[INFER] Update shape number after rolling back properties in scripted 'new' correction, bug 662044.
authorBrian Hackett <bhackett1024@gmail.com>
Sat, 04 Jun 2011 07:59:12 -0700
changeset 75137 2ebc9b25756bda2dbaeab77f4f2faa000feac3fd
parent 75136 994d2ceb427815a79246c25e91b8ecc0a77ae579
child 75138 53649a1d6e4542f8a27fb40c57d7086117676325
push id2
push userbsmedberg@mozilla.com
push dateFri, 19 Aug 2011 14:38:13 +0000
bugs662044
milestone6.0a1
[INFER] Update shape number after rolling back properties in scripted 'new' correction, bug 662044.
js/src/jit-test/tests/basic/bug662044.js
js/src/jsinfer.cpp
js/src/jsobj.h
js/src/jsscope.cpp
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/basic/bug662044.js
@@ -0,0 +1,12 @@
+eval("var OBJ = new MyObject(true); OBJ.valueOf()") 
+function MyObject( value ) {
+  this.valueOf = new Function( "return this.value" );
+}
+eval("\
+var VERSION = \"ECMA_1\";\
+var DATE1 = new Date();\
+var MYOB1 = new MyObject( DATE1 );\
+function MyProtoValuelessObject() {}\
+function Function() {\
+  __proto__[MyProtoValuelessObject] = VERSION;\
+}");
--- a/js/src/jsinfer.cpp
+++ b/js/src/jsinfer.cpp
@@ -3004,17 +3004,17 @@ TypeObject::clearNewScript(JSContext *cx
                 } else {
                     JS_ASSERT(init->kind == TypeNewScript::Initializer::DONE);
                     finished = true;
                     break;
                 }
             }
 
             if (!finished)
-                obj->rollbackProperties(numProperties);
+                obj->rollbackProperties(cx, numProperties);
         }
     }
 
     cx->free_(newScript);
     newScript = NULL;
 }
 
 void
--- a/js/src/jsobj.h
+++ b/js/src/jsobj.h
@@ -688,17 +688,17 @@ struct JSObject : js::gc::Cell {
     bool ensureClassReservedSlotsForEmptyObject(JSContext *cx);
 
     inline bool ensureClassReservedSlots(JSContext *cx);
 
     inline uint32 slotSpan() const;
 
     inline bool containsSlot(uint32 slot) const;
 
-    void rollbackProperties(uint32 slotSpan);
+    void rollbackProperties(JSContext *cx, uint32 slotSpan);
 
     js::Value& getSlotRef(uintN slot) {
         JS_ASSERT(slot < capacity);
         size_t fixed = numFixedSlots();
         if (slot < fixed)
             return fixedSlots()[slot];
         return slots[slot - fixed];
     }
--- a/js/src/jsscope.cpp
+++ b/js/src/jsscope.cpp
@@ -1256,24 +1256,25 @@ JSObject::clear(JSContext *cx)
     setMap(shape);
 
     LeaveTraceIfGlobalObject(cx, this);
     JS_ATOMIC_INCREMENT(&cx->runtime->propertyRemovals);
     CHECK_SHAPE_CONSISTENCY(this);
 }
 
 void
-JSObject::rollbackProperties(uint32 slotSpan)
+JSObject::rollbackProperties(JSContext *cx, uint32 slotSpan)
 {
     /* Remove properties from this object until it has a matching slot span. */
-    JS_ASSERT(!hasSlotsArray() && slotSpan <= this->slotSpan());
+    JS_ASSERT(!inDictionaryMode() && !hasSlotsArray() && slotSpan <= this->slotSpan());
     while (this->slotSpan() != slotSpan) {
         JS_ASSERT(lastProp->hasSlot() && getSlot(lastProp->slot).isUndefined());
         removeLastProperty();
     }
+    updateShape(cx);
 }
 
 void
 JSObject::generateOwnShape(JSContext *cx)
 {
 #ifdef JS_TRACER
     JS_ASSERT_IF(!parent && JS_ON_TRACE(cx), JS_TRACE_MONITOR_ON_TRACE(cx)->bailExit);
     LeaveTraceIfGlobalObject(cx, this);