Merge.
authorAndreas Gal <gal@mozilla.com>
Thu, 16 Apr 2009 15:56:46 -0700
changeset 27475 c93bbb0ba9ba3517e57fd8157a42f7a9adfb99bd
parent 27474 b30d69a63b3c256567e3eba265f94bb70cec265c (current diff)
parent 27472 d5e427e3bc634c402087deb8ca06802262c5011d (diff)
child 27476 8b5483c37cd2cf0f59bd1b6c11123997f6f9c5b4
push id6576
push userrsayre@mozilla.com
push dateSat, 18 Apr 2009 15:37:12 +0000
treeherderautoland@55d20693b9cb [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone1.9.2a1pre
Merge.
js/src/jsstr.cpp
--- a/js/src/jsfun.cpp
+++ b/js/src/jsfun.cpp
@@ -617,33 +617,35 @@ js_GetCallObject(JSContext *cx, JSStackF
 #endif
 
     /*
      * Create the call object, using the frame's enclosing scope as its
      * parent, and link the call to its stack frame. For a named function
      * expression Call's parent points to an environment object holding
      * function's name.
      */
-    JSObject *parent = fp->scopeChain;
     JSAtom *lambdaName = (fp->fun->flags & JSFUN_LAMBDA) ? fp->fun->atom : NULL;
     if (lambdaName) {
-        parent = js_NewObjectWithGivenProto(cx, &js_DeclEnvClass, NULL,
-                                            parent, 0);
-        if (!parent)
+        JSObject *env = js_NewObjectWithGivenProto(cx, &js_DeclEnvClass, NULL,
+                                                   fp->scopeChain, 0);
+        if (!env)
             return JS_FALSE;
+
+        /* Root env. */
+        fp->scopeChain = env;
     }
-    callobj = js_NewObject(cx, &js_CallClass, NULL, parent, 0);
+    callobj = js_NewObject(cx, &js_CallClass, NULL, fp->scopeChain, 0);
     if (!callobj)
         return NULL;
 
     JS_SetPrivate(cx, callobj, fp);
     JS_ASSERT(fp->fun == GET_FUNCTION_PRIVATE(cx, fp->callee));
     STOBJ_SET_SLOT(callobj, JSSLOT_CALLEE, OBJECT_TO_JSVAL(fp->callee));
     if (lambdaName &&
-        !js_DefineNativeProperty(cx, parent, ATOM_TO_JSID(lambdaName),
+        !js_DefineNativeProperty(cx, fp->scopeChain, ATOM_TO_JSID(lambdaName),
                                  OBJECT_TO_JSVAL(fp->callee), NULL, NULL,
                                  JSPROP_PERMANENT | JSPROP_READONLY,
                                  0, 0, NULL)) {
         return JS_FALSE;
     }
 
     fp->callobj = callobj;
 
--- a/js/src/jslock.h
+++ b/js/src/jslock.h
@@ -311,11 +311,22 @@ js_CompareAndSwap(jsword *w, jsword ov, 
 static inline JSBool
 js_CompareAndSwap(jsword *w, jsword ov, jsword nv)
 {
     return (*w == ov) ? *w = nv, JS_TRUE : JS_FALSE;
 }
 
 #endif
 
+static inline void
+js_AtomicSetMask(jsword *w, jsword mask)
+{
+    jsword ov, nv;
+
+    do {
+        ov = *w;
+        nv = ov | mask;
+    } while (!js_CompareAndSwap(w, ov, nv));
+}
+
 JS_END_EXTERN_C
 
 #endif /* jslock_h___ */
--- a/js/src/jsstr.cpp
+++ b/js/src/jsstr.cpp
@@ -2930,17 +2930,17 @@ js_FinalizeStringRT(JSRuntime *rt, JSStr
                      * Assume that the finalizer for the permanently interned
                      * string knows how to deal with null context.
                      */
                     finalizer(cx, str);
                 }
             }
         }
     }
-    if (valid)
+    if (valid && JSSTRING_IS_DEFLATED(str))
         js_PurgeDeflatedStringCache(rt, str);
 }
 
 JS_FRIEND_API(const char *)
 js_ValueToPrintable(JSContext *cx, jsval v, JSValueToStringFun v2sfun)
 {
     JSString *str;
 
@@ -3449,16 +3449,17 @@ js_SetStringBytes(JSContext *cx, JSStrin
     hash = js_hash_string_pointer(str);
     hep = JS_HashTableRawLookup(cache, hash, str);
     JS_ASSERT(*hep == NULL);
     ok = JS_HashTableRawAdd(cache, hep, hash, str, bytes) != NULL;
 #ifdef DEBUG
     if (ok)
         rt->deflatedStringCacheBytes += length;
 #endif
+    JSSTRING_SET_DEFLATED(str);
 
     JS_RELEASE_LOCK(rt->deflatedStringCacheLock);
     return ok;
 }
 
 const char *
 js_GetStringBytes(JSContext *cx, JSString *str)
 {
@@ -3503,16 +3504,17 @@ js_GetStringBytes(JSContext *cx, JSStrin
     } else {
         bytes = js_DeflateString(cx, JSSTRING_CHARS(str),
                                  JSSTRING_LENGTH(str));
         if (bytes) {
             if (JS_HashTableRawAdd(cache, hep, hash, str, bytes)) {
 #ifdef DEBUG
                 rt->deflatedStringCacheBytes += JSSTRING_LENGTH(str);
 #endif
+                JSSTRING_SET_DEFLATED(str);
             } else {
                 if (cx)
                     JS_free(cx, bytes);
                 else
                     free(bytes);
                 bytes = NULL;
             }
         }
--- a/js/src/jsstr.h
+++ b/js/src/jsstr.h
@@ -103,18 +103,19 @@ struct JSString {
  * JSSTRFLAG_PREFIX should be used only if JSSTRFLAG_DEPENDENT is set and
  * JSSTRFLAG_MUTABLE should be used only if the string is flat.
  * JSSTRFLAG_ATOMIZED is used only with the flat immutable strings.
  */
 #define JSSTRFLAG_DEPENDENT         JSSTRING_BIT(JS_BITS_PER_WORD - 1)
 #define JSSTRFLAG_PREFIX            JSSTRING_BIT(JS_BITS_PER_WORD - 2)
 #define JSSTRFLAG_MUTABLE           JSSTRFLAG_PREFIX
 #define JSSTRFLAG_ATOMIZED          JSSTRING_BIT(JS_BITS_PER_WORD - 3)
+#define JSSTRFLAG_DEFLATED          JSSTRING_BIT(JS_BITS_PER_WORD - 4)
 
-#define JSSTRING_LENGTH_BITS        (JS_BITS_PER_WORD - 3)
+#define JSSTRING_LENGTH_BITS        (JS_BITS_PER_WORD - 4)
 #define JSSTRING_LENGTH_MASK        JSSTRING_BITMASK(JSSTRING_LENGTH_BITS)
 
 /* Universal JSString type inquiry and accessor macros. */
 #define JSSTRING_BIT(n)             ((size_t)1 << (n))
 #define JSSTRING_BITMASK(n)         (JSSTRING_BIT(n) - 1)
 #define JSSTRING_HAS_FLAG(str,flg)  ((str)->length & (flg))
 #define JSSTRING_IS_DEPENDENT(str)  JSSTRING_HAS_FLAG(str, JSSTRFLAG_DEPENDENT)
 #define JSSTRING_IS_FLAT(str)       (!JSSTRING_IS_DEPENDENT(str))
@@ -127,16 +128,23 @@ struct JSString {
 
 #define JSSTRING_CHARS(str)         (JSSTRING_IS_DEPENDENT(str)               \
                                      ? JSSTRDEP_CHARS(str)                    \
                                      : JSFLATSTR_CHARS(str))
 #define JSSTRING_LENGTH(str)        (JSSTRING_IS_DEPENDENT(str)               \
                                      ? JSSTRDEP_LENGTH(str)                   \
                                      : JSFLATSTR_LENGTH(str))
 
+JS_STATIC_ASSERT(sizeof(size_t) == sizeof(jsword));
+
+#define JSSTRING_IS_DEFLATED(str)   ((str)->length & JSSTRFLAG_DEFLATED)
+
+#define JSSTRING_SET_DEFLATED(str)  js_AtomicSetMask((jsword*)&(str)->length, \
+                                                     JSSTRFLAG_DEFLATED);
+
 #define JSSTRING_CHARS_AND_LENGTH(str, chars_, length_)                       \
     ((void)(JSSTRING_IS_DEPENDENT(str)                                        \
             ? ((length_) = JSSTRDEP_LENGTH(str),                              \
                (chars_) = JSSTRDEP_CHARS(str))                                \
             : ((length_) = JSFLATSTR_LENGTH(str),                             \
                (chars_) = JSFLATSTR_CHARS(str))))
 
 #define JSSTRING_CHARS_AND_END(str, chars_, end)                              \
@@ -177,18 +185,20 @@ struct JSString {
  *
  * On the other hand, if the thread sees that the flag is unset, it could be
  * seeing a stale value when another thread has just atomized the string and
  * set the flag. But this can lead only to an extra call to js_AtomizeString.
  * This function would find that the string was already hashed and return it
  * with the atomized bit set.
  */
 #define JSFLATSTR_SET_ATOMIZED(str)                                           \
-    ((void)(JS_ASSERT(JSSTRING_IS_FLAT(str) && !JSSTRING_IS_MUTABLE(str)),    \
-            (str)->length |= JSSTRFLAG_ATOMIZED))
+    JS_BEGIN_MACRO                                                            \
+        JS_ASSERT(JSSTRING_IS_FLAT(str) && !JSSTRING_IS_MUTABLE(str));        \
+        js_AtomicSetMask((jsword*) &(str)->length, JSSTRFLAG_ATOMIZED);       \
+    JS_END_MACRO
 
 #define JSFLATSTR_SET_MUTABLE(str)                                            \
     ((void)(JS_ASSERT(JSSTRING_IS_FLAT(str) && !JSSTRING_IS_ATOMIZED(str)),   \
             (str)->length |= JSSTRFLAG_MUTABLE))
 
 #define JSFLATSTR_CLEAR_MUTABLE(str)                                          \
     ((void)(JS_ASSERT(JSSTRING_IS_FLAT(str)),                                 \
             JSSTRING_HAS_FLAG(str, JSSTRFLAG_MUTABLE) &&                      \