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