jscript: Pack jsval_t to 64-bit structure on i386.

This commit is contained in:
Jacek Caban 2012-09-18 19:02:27 +02:00 committed by Alexandre Julliard
parent 33331b1ccf
commit 37509e540f
2 changed files with 114 additions and 33 deletions

View File

@ -239,8 +239,8 @@ HRESULT jsval_variant(jsval_t *val, VARIANT *var)
VARIANT *v; VARIANT *v;
HRESULT hres; HRESULT hres;
val->type = JSV_VARIANT; __JSVAL_TYPE(*val) = JSV_VARIANT;
val->u.v = v = heap_alloc(sizeof(VARIANT)); __JSVAL_VAR(*val) = v = heap_alloc(sizeof(VARIANT));
if(!v) if(!v)
return E_OUTOFMEMORY; return E_OUTOFMEMORY;

View File

@ -19,17 +19,52 @@
#ifndef JSVAL_H #ifndef JSVAL_H
#define JSVAL_H #define JSVAL_H
/*
* jsval_t structure is used to represent JavaScript dynamically-typed values.
* It's a (type,value) pair, usually represented as a structure of enum (type)
* and union (value of given type). For both memory and speed performance, we
* use tricks allowing storing both values as a struct with size equal to
* size of double (that is 64-bit) on 32-bit systems. For that, we use the fact
* that NaN value representation has 52 (almost) free bits.
*/
#ifdef __i386__
#define JSVAL_DOUBLE_LAYOUT_PTR32
#endif
#ifdef JSVAL_DOUBLE_LAYOUT_PTR32
/* NaN exponent and our 0x80000 marker */
#define JSV_VAL(x) (0x7ff80000|x)
#else
#define JSV_VAL(x) x
#endif
typedef enum { typedef enum {
JSV_UNDEFINED, JSV_UNDEFINED = JSV_VAL(1),
JSV_NULL, JSV_NULL = JSV_VAL(2),
JSV_OBJECT, JSV_OBJECT = JSV_VAL(3),
JSV_STRING, JSV_STRING = JSV_VAL(4),
JSV_NUMBER, JSV_NUMBER = JSV_VAL(5),
JSV_BOOL, JSV_BOOL = JSV_VAL(6),
JSV_VARIANT JSV_VARIANT = JSV_VAL(7)
} jsval_type_t; } jsval_type_t;
struct _jsval_t { struct _jsval_t {
#ifdef JSVAL_DOUBLE_LAYOUT_PTR32
union {
double n;
struct {
union {
IDispatch *obj;
BSTR str;
BOOL b;
VARIANT *v;
UINT_PTR as_uintptr;
} u;
jsval_type_t tag;
} s;
} u;
#else
jsval_type_t type; jsval_type_t type;
union { union {
IDispatch *obj; IDispatch *obj;
@ -38,29 +73,50 @@ struct _jsval_t {
BOOL b; BOOL b;
VARIANT *v; VARIANT *v;
} u; } u;
#endif
}; };
#ifdef JSVAL_DOUBLE_LAYOUT_PTR32
C_ASSERT(sizeof(jsval_t) == sizeof(double));
#define __JSVAL_TYPE(x) ((x).u.s.tag)
#define __JSVAL_BOOL(x) ((x).u.s.u.b)
#define __JSVAL_STR(x) ((x).u.s.u.str)
#define __JSVAL_OBJ(x) ((x).u.s.u.obj)
#define __JSVAL_VAR(x) ((x).u.s.u.v)
#else
#define __JSVAL_TYPE(x) ((x).type)
#define __JSVAL_BOOL(x) ((x).u.b)
#define __JSVAL_STR(x) ((x).u.str)
#define __JSVAL_OBJ(x) ((x).u.obj)
#define __JSVAL_VAR(x) ((x).u.v)
#endif
static inline jsval_t jsval_bool(BOOL b) static inline jsval_t jsval_bool(BOOL b)
{ {
jsval_t ret; jsval_t ret;
ret.type = JSV_BOOL; __JSVAL_TYPE(ret) = JSV_BOOL;
ret.u.b = b; __JSVAL_BOOL(ret) = b;
return ret; return ret;
} }
static inline jsval_t jsval_string(BSTR str) static inline jsval_t jsval_string(BSTR str)
{ {
jsval_t ret; jsval_t ret;
ret.type = JSV_STRING; __JSVAL_TYPE(ret) = JSV_STRING;
ret.u.str = str; __JSVAL_STR(ret) = str;
return ret; return ret;
} }
static inline jsval_t jsval_disp(IDispatch *obj) static inline jsval_t jsval_disp(IDispatch *obj)
{ {
jsval_t ret; jsval_t ret;
ret.type = JSV_OBJECT; __JSVAL_TYPE(ret) = JSV_OBJECT;
ret.u.obj = obj; __JSVAL_OBJ(ret) = obj;
return ret; return ret;
} }
@ -71,72 +127,97 @@ static inline jsval_t jsval_obj(jsdisp_t *obj)
static inline jsval_t jsval_null(void) static inline jsval_t jsval_null(void)
{ {
jsval_t ret = { JSV_NULL }; jsval_t ret;
__JSVAL_TYPE(ret) = JSV_NULL;
return ret; return ret;
} }
static inline jsval_t jsval_undefined(void) static inline jsval_t jsval_undefined(void)
{ {
jsval_t ret = { JSV_UNDEFINED }; jsval_t ret;
__JSVAL_TYPE(ret) = JSV_UNDEFINED;
return ret; return ret;
} }
static inline jsval_t jsval_number(double n) static inline jsval_t jsval_number(double n)
{ {
jsval_t ret; jsval_t ret;
#ifdef JSVAL_DOUBLE_LAYOUT_PTR32
ret.u.n = n;
/* normalize NaN value */
if((ret.u.s.tag & 0x7ff00000) == 0x7ff00000) {
/* isinf */
if(ret.u.s.tag & 0xfffff) {
ret.u.s.tag = 0x7ff00000;
ret.u.s.u.as_uintptr = ~0;
}else if(ret.u.s.u.as_uintptr) {
ret.u.s.tag = 0x7ff00000;
}
}
return ret;
#else
ret.type = JSV_NUMBER; ret.type = JSV_NUMBER;
ret.u.n = n; ret.u.n = n;
#endif
return ret; return ret;
} }
static inline jsval_type_t jsval_type(jsval_t v)
{
return v.type;
}
static inline BOOL is_object_instance(jsval_t v) static inline BOOL is_object_instance(jsval_t v)
{ {
return v.type == JSV_OBJECT; return __JSVAL_TYPE(v) == JSV_OBJECT;
} }
static inline BOOL is_undefined(jsval_t v) static inline BOOL is_undefined(jsval_t v)
{ {
return v.type == JSV_UNDEFINED; return __JSVAL_TYPE(v) == JSV_UNDEFINED;
} }
static inline BOOL is_null(jsval_t v) static inline BOOL is_null(jsval_t v)
{ {
return v.type == JSV_NULL; return __JSVAL_TYPE(v) == JSV_NULL;
} }
static inline BOOL is_null_instance(jsval_t v) static inline BOOL is_null_instance(jsval_t v)
{ {
return v.type == JSV_NULL || (v.type == JSV_OBJECT && !v.u.obj); return is_null(v) || (is_object_instance(v) && !__JSVAL_OBJ(v));
} }
static inline BOOL is_string(jsval_t v) static inline BOOL is_string(jsval_t v)
{ {
return v.type == JSV_STRING; return __JSVAL_TYPE(v) == JSV_STRING;
} }
static inline BOOL is_number(jsval_t v) static inline BOOL is_number(jsval_t v)
{ {
#ifdef JSVAL_DOUBLE_LAYOUT_PTR32
return (v.u.s.tag & 0x7ff80000) != 0x7ff80000;
#else
return v.type == JSV_NUMBER; return v.type == JSV_NUMBER;
#endif
} }
static inline BOOL is_variant(jsval_t v) static inline BOOL is_variant(jsval_t v)
{ {
return v.type == JSV_VARIANT; return __JSVAL_TYPE(v) == JSV_VARIANT;
} }
static inline BOOL is_bool(jsval_t v) static inline BOOL is_bool(jsval_t v)
{ {
return v.type == JSV_BOOL; return __JSVAL_TYPE(v) == JSV_BOOL;
}
static inline jsval_type_t jsval_type(jsval_t v)
{
#ifdef JSVAL_DOUBLE_LAYOUT_PTR32
return is_number(v) ? JSV_NUMBER : v.u.s.tag;
#else
return v.type;
#endif
} }
static inline IDispatch *get_object(jsval_t v) static inline IDispatch *get_object(jsval_t v)
{ {
return v.u.obj; return __JSVAL_OBJ(v);
} }
static inline double get_number(jsval_t v) static inline double get_number(jsval_t v)
@ -146,17 +227,17 @@ static inline double get_number(jsval_t v)
static inline BSTR get_string(jsval_t v) static inline BSTR get_string(jsval_t v)
{ {
return v.u.str; return __JSVAL_STR(v);
} }
static inline VARIANT *get_variant(jsval_t v) static inline VARIANT *get_variant(jsval_t v)
{ {
return v.u.v; return __JSVAL_VAR(v);
} }
static inline BOOL get_bool(jsval_t v) static inline BOOL get_bool(jsval_t v)
{ {
return v.u.b; return __JSVAL_BOOL(v);
} }
HRESULT variant_to_jsval(VARIANT*,jsval_t*) DECLSPEC_HIDDEN; HRESULT variant_to_jsval(VARIANT*,jsval_t*) DECLSPEC_HIDDEN;