Bug 487561 - More cleanup from bug 452498 and bug 487271 patches (r=mrbkap/igor, and this fixes bug 487570).
authorBrendan Eich <brendan@mozilla.org>
Thu, 09 Apr 2009 15:05:12 -0700
changeset 27164 547f9171ae0f84d892a6929e14b8439275fa8b01
parent 27163 3d7e030e283f05d9547a2b69a4523cd735ce622e
child 27165 38c0b853764c96a460ef614321077c9be9d79920
push idunknown
push userunknown
push dateunknown
reviewersmrbkap, igor, and
bugs487561, 452498, 487271, 487570
milestone1.9.2a1pre
Bug 487561 - More cleanup from bug 452498 and bug 487271 patches (r=mrbkap/igor, and this fixes bug 487570).
js/src/jsinterp.cpp
js/src/jsparse.h
--- a/js/src/jsinterp.cpp
+++ b/js/src/jsinterp.cpp
@@ -2486,16 +2486,90 @@ JS_STATIC_ASSERT(!CAN_DO_FAST_INC_DEC(IN
     __SUNPRO_C >= 0x570)
 #  define JS_THREADED_INTERP 1
 # else
 #  define JS_THREADED_INTERP 0
 # endif
 #endif
 
 /*
+ * Deadlocks or else bad races are likely if JS_THREADSAFE, so we must rely on
+ * single-thread DEBUG js shell testing to verify property cache hits.
+ */
+#if defined DEBUG && !defined JS_THREADSAFE
+
+# define ASSERT_VALID_PROPERTY_CACHE_HIT(pcoff,obj,pobj,entry)                \
+    JS_BEGIN_MACRO                                                            \
+        if (!AssertValidPropertyCacheHit(cx, script, regs, pcoff, obj, pobj,  \
+                                         entry)) {                            \
+            goto error;                                                       \
+        }                                                                     \
+    JS_END_MACRO
+
+static bool
+AssertValidPropertyCacheHit(JSContext *cx, JSScript *script, JSFrameRegs& regs,
+                            ptrdiff_t pcoff, JSObject *start, JSObject *found,
+                            JSPropCacheEntry *entry)
+{
+    uint32 sample = cx->runtime->gcNumber;
+
+    JSAtom *atom;
+    if (pcoff >= 0)
+        GET_ATOM_FROM_BYTECODE(script, regs.pc, pcoff, atom);
+    else
+        atom = cx->runtime->atomState.lengthAtom;
+
+    JSObject *obj, *pobj;
+    JSProperty *prop;
+    bool ok;
+
+    if (JOF_OPMODE(*regs.pc) == JOF_NAME) {
+        ok = js_FindProperty(cx, ATOM_TO_JSID(atom), &obj, &pobj, &prop);
+    } else {
+        obj = start;
+        ok = js_LookupProperty(cx, obj, ATOM_TO_JSID(atom), &pobj, &prop);
+    }
+    if (!ok)
+        return false;
+    if (!prop)
+        return true;
+    if (cx->runtime->gcNumber != sample ||
+        PCVCAP_SHAPE(entry->vcap) != OBJ_SHAPE(pobj)) {
+        OBJ_DROP_PROPERTY(cx, pobj, prop);
+        return true;
+    }
+    JS_ASSERT(prop);
+    JS_ASSERT(pobj == found);
+
+    JSScopeProperty *sprop = (JSScopeProperty *) prop;
+    if (PCVAL_IS_SLOT(entry->vword)) {
+        JS_ASSERT(PCVAL_TO_SLOT(entry->vword) == sprop->slot);
+    } else if (PCVAL_IS_SPROP(entry->vword)) {
+        JS_ASSERT(PCVAL_TO_SPROP(entry->vword) == sprop);
+    } else {
+        jsval v;
+        JS_ASSERT(PCVAL_IS_OBJECT(entry->vword));
+        JS_ASSERT(entry->vword != PCVAL_NULL);
+        JS_ASSERT(SCOPE_IS_BRANDED(OBJ_SCOPE(pobj)));
+        JS_ASSERT(SPROP_HAS_STUB_GETTER(sprop));
+        JS_ASSERT(SPROP_HAS_VALID_SLOT(sprop, OBJ_SCOPE(pobj)));
+        v = LOCKED_OBJ_GET_SLOT(pobj, sprop->slot);
+        JS_ASSERT(VALUE_IS_FUNCTION(cx, v));
+        JS_ASSERT(PCVAL_TO_OBJECT(entry->vword) == JSVAL_TO_OBJECT(v));
+    }
+
+    OBJ_DROP_PROPERTY(cx, pobj, prop);
+    return true;
+}
+
+#else
+# define ASSERT_VALID_PROPERTY_CACHE_HIT(pcoff,obj,pobj,entry) ((void) 0)
+#endif
+
+/*
  * Ensure that the intrepreter switch can close call-bytecode cases in the
  * same way as non-call bytecodes.
  */
 JS_STATIC_ASSERT(JSOP_NAME_LENGTH == JSOP_CALLNAME_LENGTH);
 JS_STATIC_ASSERT(JSOP_GETGVAR_LENGTH == JSOP_CALLGVAR_LENGTH);
 JS_STATIC_ASSERT(JSOP_GETUPVAR_LENGTH == JSOP_CALLUPVAR_LENGTH);
 JS_STATIC_ASSERT(JSOP_GETDSLOT_LENGTH == JSOP_CALLDSLOT_LENGTH);
 JS_STATIC_ASSERT(JSOP_GETARG_LENGTH == JSOP_CALLARG_LENGTH);
@@ -3469,68 +3543,16 @@ js_Interpret(JSContext *cx)
             LOCKED_OBJ_WRITE_BARRIER(cx, obj, (sprop)->slot, *vp);            \
         } else {                                                              \
             if (!js_NativeSet(cx, obj, sprop, vp))                            \
                 goto error;                                                   \
         }                                                                     \
     JS_END_MACRO
 
 /*
- * Deadlocks or else bad races are likely if JS_THREADSAFE, so we must rely on
- * single-thread DEBUG js shell testing to verify property cache hits.
- */
-#if defined DEBUG && !defined JS_THREADSAFE
-# define ASSERT_VALID_PROPERTY_CACHE_HIT(pcoff,obj,pobj,entry)                \
-    do {                                                                      \
-        JSAtom *atom_;                                                        \
-        JSObject *obj_, *pobj_;                                               \
-        JSProperty *prop_;                                                    \
-        JSScopeProperty *sprop_;                                              \
-        uint32 sample_ = rt->gcNumber;                                        \
-        if (pcoff >= 0)                                                       \
-            GET_ATOM_FROM_BYTECODE(script, regs.pc, pcoff, atom_);            \
-        else                                                                  \
-            atom_ = rt->atomState.lengthAtom;                                 \
-        if (JOF_OPMODE(op) == JOF_NAME) {                                     \
-            ok = js_FindProperty(cx, ATOM_TO_JSID(atom_), &obj_, &pobj_,      \
-                                 &prop_);                                     \
-        } else {                                                              \
-            obj_ = obj;                                                       \
-            ok = js_LookupProperty(cx, obj, ATOM_TO_JSID(atom_), &pobj_,      \
-                                   &prop_);                                   \
-        }                                                                     \
-        if (!ok)                                                              \
-            goto error;                                                       \
-        if (rt->gcNumber != sample_)                                          \
-            break;                                                            \
-        JS_ASSERT(prop_);                                                     \
-        JS_ASSERT(pobj_ == pobj);                                             \
-        sprop_ = (JSScopeProperty *) prop_;                                   \
-        if (PCVAL_IS_SLOT(entry->vword)) {                                    \
-            JS_ASSERT(PCVAL_TO_SLOT(entry->vword) == sprop_->slot);           \
-        } else if (PCVAL_IS_SPROP(entry->vword)) {                            \
-            JS_ASSERT(PCVAL_TO_SPROP(entry->vword) == sprop_);                \
-        } else {                                                              \
-            jsval v_;                                                         \
-            JS_ASSERT(PCVAL_IS_OBJECT(entry->vword));                         \
-            JS_ASSERT(entry->vword != PCVAL_NULL);                            \
-            JS_ASSERT(SCOPE_IS_BRANDED(OBJ_SCOPE(pobj)));                     \
-            JS_ASSERT(SPROP_HAS_STUB_GETTER(sprop_));                         \
-            JS_ASSERT(SPROP_HAS_VALID_SLOT(sprop_, OBJ_SCOPE(pobj_)));        \
-            v_ = LOCKED_OBJ_GET_SLOT(pobj_, sprop_->slot);                    \
-            JS_ASSERT(VALUE_IS_FUNCTION(cx, v_));                             \
-            JS_ASSERT(PCVAL_TO_OBJECT(entry->vword) == JSVAL_TO_OBJECT(v_));  \
-        }                                                                     \
-        OBJ_DROP_PROPERTY(cx, pobj_, prop_);                                  \
-    } while (0)
-#else
-# define ASSERT_VALID_PROPERTY_CACHE_HIT(pcoff,obj,pobj,entry) ((void) 0)
-#endif
-
-/*
  * Skip the JSOP_POP typically found after a JSOP_SET* opcode, where oplen is
  * the constant length of the SET opcode sequence, and spdec is the constant
  * by which to decrease the stack pointer to pop all of the SET op's operands.
  *
  * NB: unlike macros that could conceivably be replaced by functions (ignoring
  * goto error), where a call should not have to be braced in order to expand
  * correctly (e.g., in if (cond) FOO(); else BAR()), these three macros lack
  * JS_{BEGIN,END}_MACRO brackets. They are also indented so as to align with
--- a/js/src/jsparse.h
+++ b/js/src/jsparse.h
@@ -724,22 +724,30 @@ JSParseNode::isFunArg() const
         return ((JSDefinition *)this)->isFunArg();
 #endif
     return test(PND_FUNARG);
 }
 
 inline void
 JSParseNode::setFunArg()
 {
-    if (pn_defn) {
-        ((JSDefinition *)this)->pn_dflags |= PND_FUNARG;
-    } else if (pn_used) {
+    /*
+     * pn_defn NAND pn_used must be true, per this chart:
+     *
+     *   pn_defn pn_used
+     *         0       0        anonymous function used implicitly, e.g. by
+     *                          hidden yield in a genexp
+     *         0       1        a use of a definition or placeholder
+     *         1       0        a definition or placeholder
+     *         1       1        error: this case must not be possible
+     */
+    JS_ASSERT(!(pn_defn & pn_used));
+    if (pn_used)
         pn_lexdef->pn_dflags |= PND_FUNARG;
-        pn_dflags |= PND_FUNARG;
-    }
+    pn_dflags |= PND_FUNARG;
 }
 
 struct JSObjectBox {
     JSObjectBox         *traceLink;
     JSObjectBox         *emitLink;
     JSObject            *object;
 };
 
@@ -779,17 +787,17 @@ struct JSFunctionBoxQueue {
             vector[head++ & lengthMask] = funbox;
             funbox->queued = true;
         }
     }
 
     JSFunctionBox *pull() {
         if (tail == head)
             return NULL;
-        JS_ASSERT(tail != head);
+        JS_ASSERT(tail < head);
         JSFunctionBox *funbox = vector[tail++ & lengthMask];
         funbox->queued = false;
         return funbox;
     }
 };
 
 #define NUM_TEMP_FREELISTS      6U      /* 32 to 2048 byte size classes (32 bit) */