Bug 580084 - JS_InitClass with no methods or properties breaks JSScope::emptyScope invariant. r=brendan.
authorJason Orendorff <jorendorff@mozilla.com>
Tue, 20 Jul 2010 16:57:12 -0500
changeset 48513 7fd49595dc3a4082f5efde48f57fb663210b6bc1
parent 48512 5384ab5eb6c19553014439f6c76a1845517122a0
child 48515 6d7b95761119b268a7d4b470bcd9b1bbd63656a7
push id14748
push userrsayre@mozilla.com
push dateSun, 01 Aug 2010 00:33:23 +0000
treeherdermozilla-central@f0df797bb2a9 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbrendan
bugs580084
milestone2.0b2pre
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 580084 - JS_InitClass with no methods or properties breaks JSScope::emptyScope invariant. r=brendan.
js/src/jsapi-tests/testExtendedEq.cpp
js/src/jsobj.cpp
js/src/jsscopeinlines.h
--- a/js/src/jsapi-tests/testExtendedEq.cpp
+++ b/js/src/jsapi-tests/testExtendedEq.cpp
@@ -27,19 +27,19 @@ JSExtendedClass TestExtendedEq_JSClass =
     NULL, NULL, NULL, NULL, JSCLASS_NO_RESERVED_MEMBERS
 };
 
 BEGIN_TEST(testExtendedEq_bug530489)
 {
     JSClass *clasp = (JSClass *) &TestExtendedEq_JSClass;
 
     JSObject *global = JS_GetGlobalObject(cx);
-    JS_InitClass(cx, global, global, clasp, NULL, 0, NULL, NULL, NULL, NULL);
+    CHECK(JS_InitClass(cx, global, global, clasp, NULL, 0, NULL, NULL, NULL, NULL));
 
-    JS_DefineObject(cx, global, "obj1", clasp, NULL, 0);
-    JS_DefineObject(cx, global, "obj2", clasp, NULL, 0);
+    CHECK(JS_DefineObject(cx, global, "obj1", clasp, NULL, 0));
+    CHECK(JS_DefineObject(cx, global, "obj2", clasp, NULL, 0));
 
     jsval v;
     EVAL("(function() { var r; for (var i = 0; i < 10; ++i) r = obj1 == obj2; return r; })()", &v);
     CHECK_SAME(v, JSVAL_TRUE);
     return true;
 }
 END_TEST(testExtendedEq_bug530489)
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -3511,17 +3511,23 @@ js_InitClass(JSContext *cx, JSObject *ob
     /*
      * Make sure proto's scope's emptyScope is available to be shared by
      * objects of this class.  JSScope::emptyScope is a one-slot cache. If we
      * omit this, some other class could snap it up. (The risk is particularly
      * great for Object.prototype.)
      *
      * All callers of JSObject::initSharingEmptyScope depend on this.
      */
-    if (!proto->scope()->ensureEmptyScope(cx, clasp))
+    JSScope *scope;
+    bool ok;
+    JS_LOCK_OBJ(cx, proto);
+    scope = js_GetMutableScope(cx, proto);
+    ok = scope && scope->ensureEmptyScope(cx, clasp);
+    JS_UNLOCK_OBJ(cx, proto);
+    if (!ok)
         goto bad;
 
     /* If this is a standard class, cache its prototype. */
     if (key != JSProto_Null && !js_SetClassObject(cx, obj, key, ctor, proto))
         goto bad;
 
     return proto;
 
--- a/js/src/jsscopeinlines.h
+++ b/js/src/jsscopeinlines.h
@@ -46,16 +46,17 @@
 #include "jsobj.h"
 #include "jsscope.h"
 
 #include "jscntxtinlines.h"
 
 inline JSEmptyScope *
 JSScope::createEmptyScope(JSContext *cx, js::Class *clasp)
 {
+    JS_ASSERT(!isSharedEmpty());
     JS_ASSERT(!emptyScope);
     emptyScope = cx->create<JSEmptyScope>(cx, ops, clasp);
     return emptyScope;
 }
 
 inline JSEmptyScope *
 JSScope::getEmptyScope(JSContext *cx, js::Class *clasp)
 {