[INFER] Add WithType variation for nativeSetSlot, fix gaps in type barriers, bug 657901.
authorBrian Hackett <bhackett1024@gmail.com>
Wed, 18 May 2011 10:43:08 -0700
changeset 75075 29bd8523ead93a79c69a4ac5749df438c630a9d0
parent 75074 bcd868ff18d4e572c9fba427ee714af42046e327
child 75076 9aeb58c8c43f71c13418f2e377e3a9e832e01153
push id2
push userbsmedberg@mozilla.com
push dateFri, 19 Aug 2011 14:38:13 +0000
bugs657901
milestone6.0a1
[INFER] Add WithType variation for nativeSetSlot, fix gaps in type barriers, bug 657901.
js/src/jit-test/tests/basic/bug657901.js
js/src/jsinterp.cpp
js/src/jsobj.cpp
js/src/jsobj.h
js/src/jsobjinlines.h
js/src/methodjit/StubCalls-inl.h
js/src/methodjit/StubCalls.cpp
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/basic/bug657901.js
@@ -0,0 +1,8 @@
+function f() {};
+function g(o) {
+    f = new Function("");
+    eval("");
+}
+g({});
+g({});
+f++;
--- a/js/src/jsinterp.cpp
+++ b/js/src/jsinterp.cpp
@@ -3254,18 +3254,17 @@ END_CASE(JSOP_PICK)
     JS_END_MACRO
 
 #define NATIVE_SET(cx,obj,shape,entry,strict,vp)                              \
     JS_BEGIN_MACRO                                                            \
         if (shape->hasDefaultSetter() &&                                      \
             (shape)->slot != SHAPE_INVALID_SLOT &&                            \
             !(obj)->brandedOrHasMethodBarrier()) {                            \
             /* Fast path for, e.g., plain Object instance properties. */      \
-            (obj)->nativeSetSlot((shape)->slot, *vp);                         \
-            cx->addTypePropertyId(obj->getType(), shape->propid, *vp);        \
+            (obj)->nativeSetSlotWithType(cx, shape, *vp);                     \
         } else {                                                              \
             if (!js_NativeSet(cx, obj, shape, false, strict, vp))             \
                 goto error;                                                   \
         }                                                                     \
     JS_END_MACRO
 
 /*
  * Skip the JSOP_POP typically found after a JSOP_SET* opcode, where oplen is
@@ -4387,17 +4386,17 @@ BEGIN_CASE(JSOP_SETMETHOD)
                     obj->extend(cx, shape);
 
                     /*
                      * No method change check here because here we are adding a
                      * new property, not updating an existing slot's value that
                      * might contain a method of a branded shape.
                      */
                     TRACE_1(AddProperty, obj);
-                    obj->nativeSetSlot(slot, rval);
+                    obj->nativeSetSlotWithType(cx, shape, rval);
 
                     /*
                      * Purge the property cache of the id we may have just
                      * shadowed in obj's scope and proto chains.
                      */
                     js_PurgeScopeChain(cx, obj, shape->propid);
                     break;
                 }
@@ -5948,18 +5947,17 @@ BEGIN_CASE(JSOP_INITMETHOD)
         obj->extend(cx, shape);
 
         /*
          * No method change check here because here we are adding a new
          * property, not updating an existing slot's value that might
          * contain a method of a branded shape.
          */
         TRACE_1(AddProperty, obj);
-        cx->addTypePropertyId(obj->getType(), shape->propid, rval);
-        obj->nativeSetSlot(slot, rval);
+        obj->nativeSetSlotWithType(cx, shape, rval);
     } else {
         PCMETER(JS_PROPERTY_CACHE(cx).inipcmisses++);
 
         /* Get the immediate property name into id. */
         JSAtom *atom;
         LOAD_ATOM(0, atom);
         jsid id = ATOM_TO_JSID(atom);
 
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -4976,17 +4976,17 @@ CallAddPropertyHook(JSContext *cx, Class
 {
     if (clasp->addProperty != PropertyStub) {
         Value nominal = *vp;
 
         if (!CallJSPropertyOp(cx, clasp->addProperty, obj, shape->propid, vp))
             return false;
         if (*vp != nominal) {
             if (obj->containsSlot(shape->slot))
-                obj->nativeSetSlot(shape->slot, *vp);
+                obj->nativeSetSlotWithType(cx, shape, *vp);
         }
     }
     return true;
 }
 
 namespace js {
 
 const Shape *
--- a/js/src/jsobj.h
+++ b/js/src/jsobj.h
@@ -711,16 +711,17 @@ struct JSObject : js::gc::Cell {
     inline const js::Value &nativeGetSlot(uintN slot) const;
 
     void setSlot(uintN slot, const js::Value &value) {
         JS_ASSERT(slot < capacity);
         getSlotRef(slot) = value;
     }
 
     inline void nativeSetSlot(uintN slot, const js::Value &value);
+    inline void nativeSetSlotWithType(JSContext *cx, const js::Shape *shape, const js::Value &value);
 
     inline js::Value getReservedSlot(uintN index) const;
 
     /* For slots which are known to always be fixed, due to the way they are allocated. */
 
     js::Value &getFixedSlotRef(uintN slot) {
         JS_ASSERT(slot < numFixedSlots());
         return fixedSlots()[slot];
--- a/js/src/jsobjinlines.h
+++ b/js/src/jsobjinlines.h
@@ -1005,16 +1005,23 @@ JSObject::nativeGetSlot(uintN slot) cons
 inline void
 JSObject::nativeSetSlot(uintN slot, const js::Value &value)
 {
     JS_ASSERT(isNative());
     JS_ASSERT(containsSlot(slot));
     return setSlot(slot, value);
 }
 
+inline void
+JSObject::nativeSetSlotWithType(JSContext *cx, const js::Shape *shape, const js::Value &value)
+{
+    nativeSetSlot(shape->slot, value);
+    cx->addTypePropertyId(getType(), shape->propid, value);
+}
+
 inline bool
 JSObject::isNative() const
 {
     return lastProp->isNative();
 }
 
 inline bool
 JSObject::isNewborn() const
--- a/js/src/methodjit/StubCalls-inl.h
+++ b/js/src/methodjit/StubCalls-inl.h
@@ -71,17 +71,17 @@ ReportAtomNotDefined(JSContext *cx, JSAt
 }
 
 #define NATIVE_SET(cx,obj,shape,entry,strict,vp)                              \
     JS_BEGIN_MACRO                                                            \
         if (shape->hasDefaultSetter() &&                                      \
             (shape)->slot != SHAPE_INVALID_SLOT &&                            \
             !(obj)->brandedOrHasMethodBarrier()) {                            \
             /* Fast path for, e.g., plain Object instance properties. */      \
-            (obj)->nativeSetSlot((shape)->slot, *vp);                         \
+            (obj)->nativeSetSlotWithType(cx, shape, *vp);                     \
         } else {                                                              \
             if (!js_NativeSet(cx, obj, shape, false, strict, vp))             \
                 THROW();                                                      \
         }                                                                     \
     JS_END_MACRO
 
 #define NATIVE_GET(cx,obj,pobj,shape,getHow,vp,onerr)                         \
     JS_BEGIN_MACRO                                                            \
--- a/js/src/methodjit/StubCalls.cpp
+++ b/js/src/methodjit/StubCalls.cpp
@@ -2191,18 +2191,17 @@ InitPropOrMethod(VMFrame &f, JSAtom *ato
                   obj->shape() == obj->lastProperty()->shapeid);
         obj->extend(cx, shape);
 
         /*
          * No method change check here because here we are adding a new
          * property, not updating an existing slot's value that might
          * contain a method of a branded shape.
          */
-        cx->addTypePropertyId(obj->getType(), ATOM_TO_JSID(atom), rval);
-        obj->nativeSetSlot(slot, rval);
+        obj->nativeSetSlotWithType(cx, shape, rval);
     } else {
         PCMETER(JS_PROPERTY_CACHE(cx).inipcmisses++);
 
         /* Get the immediate property name into id. */
         jsid id = ATOM_TO_JSID(atom);
 
         uintN defineHow = (op == JSOP_INITMETHOD)
                           ? DNP_CACHE_RESULT | DNP_SET_METHOD