Jacek Caban : jscript: Pack jsval_t to 64-bit structure on i386.
Alexandre Julliard
julliard at winehq.org
Wed Sep 19 13:39:44 CDT 2012
Module: wine
Branch: master
Commit: 37509e540fc892c7919613204cf527fde6cd4090
URL: http://source.winehq.org/git/wine.git/?a=commit;h=37509e540fc892c7919613204cf527fde6cd4090
Author: Jacek Caban <jacek at codeweavers.com>
Date: Tue Sep 18 19:02:27 2012 +0200
jscript: Pack jsval_t to 64-bit structure on i386.
---
dlls/jscript/jsutils.c | 4 +-
dlls/jscript/jsval.h | 143 +++++++++++++++++++++++++++++++++++++----------
2 files changed, 114 insertions(+), 33 deletions(-)
diff --git a/dlls/jscript/jsutils.c b/dlls/jscript/jsutils.c
index d4260ca..c76d09a 100644
--- a/dlls/jscript/jsutils.c
+++ b/dlls/jscript/jsutils.c
@@ -239,8 +239,8 @@ HRESULT jsval_variant(jsval_t *val, VARIANT *var)
VARIANT *v;
HRESULT hres;
- val->type = JSV_VARIANT;
- val->u.v = v = heap_alloc(sizeof(VARIANT));
+ __JSVAL_TYPE(*val) = JSV_VARIANT;
+ __JSVAL_VAR(*val) = v = heap_alloc(sizeof(VARIANT));
if(!v)
return E_OUTOFMEMORY;
diff --git a/dlls/jscript/jsval.h b/dlls/jscript/jsval.h
index a678e05..9909de7 100644
--- a/dlls/jscript/jsval.h
+++ b/dlls/jscript/jsval.h
@@ -19,17 +19,52 @@
#ifndef 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 {
- JSV_UNDEFINED,
- JSV_NULL,
- JSV_OBJECT,
- JSV_STRING,
- JSV_NUMBER,
- JSV_BOOL,
- JSV_VARIANT
+ JSV_UNDEFINED = JSV_VAL(1),
+ JSV_NULL = JSV_VAL(2),
+ JSV_OBJECT = JSV_VAL(3),
+ JSV_STRING = JSV_VAL(4),
+ JSV_NUMBER = JSV_VAL(5),
+ JSV_BOOL = JSV_VAL(6),
+ JSV_VARIANT = JSV_VAL(7)
} jsval_type_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;
union {
IDispatch *obj;
@@ -38,29 +73,50 @@ struct _jsval_t {
BOOL b;
VARIANT *v;
} 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)
{
jsval_t ret;
- ret.type = JSV_BOOL;
- ret.u.b = b;
+ __JSVAL_TYPE(ret) = JSV_BOOL;
+ __JSVAL_BOOL(ret) = b;
return ret;
}
static inline jsval_t jsval_string(BSTR str)
{
jsval_t ret;
- ret.type = JSV_STRING;
- ret.u.str = str;
+ __JSVAL_TYPE(ret) = JSV_STRING;
+ __JSVAL_STR(ret) = str;
return ret;
}
static inline jsval_t jsval_disp(IDispatch *obj)
{
jsval_t ret;
- ret.type = JSV_OBJECT;
- ret.u.obj = obj;
+ __JSVAL_TYPE(ret) = JSV_OBJECT;
+ __JSVAL_OBJ(ret) = obj;
return ret;
}
@@ -71,72 +127,97 @@ static inline jsval_t jsval_obj(jsdisp_t *obj)
static inline jsval_t jsval_null(void)
{
- jsval_t ret = { JSV_NULL };
+ jsval_t ret;
+ __JSVAL_TYPE(ret) = JSV_NULL;
return ret;
}
static inline jsval_t jsval_undefined(void)
{
- jsval_t ret = { JSV_UNDEFINED };
+ jsval_t ret;
+ __JSVAL_TYPE(ret) = JSV_UNDEFINED;
return ret;
}
static inline jsval_t jsval_number(double n)
{
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.u.n = n;
+#endif
return ret;
}
-static inline jsval_type_t jsval_type(jsval_t v)
-{
- return v.type;
-}
-
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)
{
- return v.type == JSV_UNDEFINED;
+ return __JSVAL_TYPE(v) == JSV_UNDEFINED;
}
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)
{
- 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)
{
- return v.type == JSV_STRING;
+ return __JSVAL_TYPE(v) == JSV_STRING;
}
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;
+#endif
}
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)
{
- 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)
{
- return v.u.obj;
+ return __JSVAL_OBJ(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)
{
- return v.u.str;
+ return __JSVAL_STR(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)
{
- return v.u.b;
+ return __JSVAL_BOOL(v);
}
HRESULT variant_to_jsval(VARIANT*,jsval_t*) DECLSPEC_HIDDEN;
More information about the wine-cvs
mailing list