Bug 567152 - Assertion failure: !generic(). r=brendan.
authorJason Orendorff <jorendorff@mozilla.com>
Wed, 02 Jun 2010 16:45:23 -0700
changeset 43256 331702c6884fcdd54bb3d95d50f132545a6200bb
parent 43255 602df4d60a1c649133f71952872ef405a8501764
child 43257 96dbe8a784f15719031a8716921ad50a86650a15
push idunknown
push userunknown
push dateunknown
reviewersbrendan
bugs567152
milestone1.9.3a5pre
Bug 567152 - Assertion failure: !generic(). r=brendan.
js/src/jsobjinlines.h
js/src/jsscope.h
js/src/tests/js1_8_5/regress/jstests.list
js/src/tests/js1_8_5/regress/regress-567152.js
--- a/js/src/jsobjinlines.h
+++ b/js/src/jsobjinlines.h
@@ -488,17 +488,17 @@ JSObject::unbrand(JSContext *cx)
         JSScope *scope = this->scope();
         if (scope->isSharedEmpty()) {
             scope = js_GetMutableScope(cx, this);
             if (!scope) {
                 JS_UNLOCK_OBJ(cx, this);
                 return false;
             }
         }
-        scope->setGeneric();
+        scope->unbrand(cx);
         JS_UNLOCK_SCOPE(cx, scope);
     }
     return true;
 }
 
 inline bool
 JSObject::isCallable()
 {
--- a/js/src/jsscope.h
+++ b/js/src/jsscope.h
@@ -219,17 +219,19 @@ struct JSEmptyScope;
 
 struct JSScope : public JSObjectMap
 {
 #ifdef JS_THREADSAFE
     JSTitle         title;              /* lock state */
 #endif
     JSObject        *object;            /* object that owns this scope */
     uint32          freeslot;           /* index of next free slot in object */
+  protected:
     uint8           flags;              /* flags, see below */
+  public:
     int8            hashShift;          /* multiplicative hash shift */
 
     uint16          spare;              /* reserved */
     uint32          entryCount;         /* number of entries in table */
     uint32          removedCount;       /* removed entry sentinels in table */
     JSScopeProperty **table;            /* table of ptrs to shared tree nodes */
     JSEmptyScope    *emptyScope;        /* cache for getEmptyScope below */
 
@@ -418,29 +420,40 @@ struct JSScope : public JSObjectMap
         flags |= SEALED;
     }
 
     /*
      * A branded scope's object contains plain old methods (function-valued
      * properties without magic getters and setters), and its scope->shape
      * evolves whenever a function value changes.
      */
-    bool branded()              { JS_ASSERT(!generic()); return flags & BRANDED; }
+    bool branded()              { return flags & BRANDED; }
 
     bool brand(JSContext *cx, uint32 slot, jsval v) {
+        JS_ASSERT(!generic());
         JS_ASSERT(!branded());
         generateOwnShape(cx);
         if (js_IsPropertyCacheDisabled(cx))  // check for rt->shapeGen overflow
             return false;
         flags |= BRANDED;
         return true;
     }
 
     bool generic()              { return flags & GENERIC; }
-    void setGeneric()           { flags |= GENERIC; }
+
+    /*
+     * Here and elsewhere "unbrand" means "make generic". We never actually
+     * clear the BRANDED bit on any object. Once branded, there's no point in
+     * being generic, since the shape has already evolved unpredictably. So
+     * obj->unbrand() on a branded object does nothing.
+     */
+    void unbrand(JSContext *cx) {
+        if (!branded())
+            flags |= GENERIC;
+    }
 
     bool hadIndexedProperties() { return flags & INDEXED_PROPERTIES; }
     void setIndexedProperties() { flags |= INDEXED_PROPERTIES; }
 
     bool hasOwnShape()          { return flags & OWN_SHAPE; }
 
     bool hasRegenFlag(uint8 regenFlag) { return (flags & SHAPE_REGEN) == regenFlag; }
 
--- a/js/src/tests/js1_8_5/regress/jstests.list
+++ b/js/src/tests/js1_8_5/regress/jstests.list
@@ -16,9 +16,10 @@ fails script regress-555246-1.js
 script regress-559438.js
 script regress-560101.js
 script regress-560998-1.js
 script regress-560998-2.js
 script regress-563210.js
 script regress-563221.js
 script regress-566549.js
 script regress-566914.js
+script regress-567152.js
 script regress-569306.js
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/js/src/tests/js1_8_5/regress/regress-567152.js
@@ -0,0 +1,12 @@
+// Any copyright is dedicated to the Public Domain.
+// http://creativecommons.org/licenses/publicdomain/
+// Contributors: Gary Kwong <gary@rumblingedge.com>,
+//               Jason Orendorff <jorendorff@mozilla.com>
+
+function c(a) {
+    this.f = function () { a; };
+}
+c(0);  // set both BRANDED and GENERIC bits in global scope
+Object.defineProperty(this, "f", {configurable: true, enumerable: true, value: 3});
+
+reportCompare(0, 0, "");