TraceRecorder::record_SetPropMiss mis-layered on top of record_SetPropHit (454689, r=mrbkap).
authorBrendan Eich <brendan@mozilla.org>
Thu, 11 Sep 2008 18:35:29 -0700
changeset 19171 9b57626564890a8860ed66336db8dafa4957948d
parent 19170 8e25f600225f5b47b6103112f6dcb6f40de9ea93
child 19172 3cc51edbb1c9830ca3b6dd5af005930e140b0520
push id1992
push userbrendan@mozilla.com
push dateFri, 12 Sep 2008 01:36:12 +0000
treeherdermozilla-central@9b5762656489 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmrbkap
bugs454689
milestone1.9.1b1pre
TraceRecorder::record_SetPropMiss mis-layered on top of record_SetPropHit (454689, r=mrbkap).
js/src/jsbuiltins.cpp
js/src/jscntxt.cpp
js/src/jsinterp.cpp
js/src/jstracer.cpp
js/src/jstracer.h
--- a/js/src/jsbuiltins.cpp
+++ b/js/src/jsbuiltins.cpp
@@ -572,16 +572,17 @@ js_AddProperty(JSContext* cx, JSObject* 
             JS_UNLOCK_OBJ(cx, obj);
             return JS_FALSE;
         }
     }
 
     uint32 slot = sprop->slot;
     if (!scope->table && sprop->parent == scope->lastProp && slot == scope->map.freeslot) {
         if (slot < STOBJ_NSLOTS(obj) && !OBJ_GET_CLASS(cx, obj)->reserveSlots) {
+            JS_ASSERT(JSVAL_IS_VOID(STOBJ_GET_SLOT(obj, scope->map.freeslot)));
             ++scope->map.freeslot;
         } else {
             if (!js_AllocSlot(cx, obj, &slot)) {
                 JS_UNLOCK_SCOPE(cx, scope);
                 return JS_FALSE;
             }
 
             if (slot != sprop->slot)
--- a/js/src/jscntxt.cpp
+++ b/js/src/jscntxt.cpp
@@ -60,19 +60,17 @@
 #include "jslock.h"
 #include "jsnum.h"
 #include "jsobj.h"
 #include "jsopcode.h"
 #include "jsscan.h"
 #include "jsscope.h"
 #include "jsscript.h"
 #include "jsstr.h"
-#ifdef JS_TRACER
 #include "jstracer.h"
-#endif
 
 #ifdef JS_THREADSAFE
 #include "prtypes.h"
 
 /*
  * The index for JSThread info, returned by PR_NewThreadPrivateIndex.  The
  * index value is visible and shared by all threads, but the data associated
  * with it is private to each thread.
--- a/js/src/jsinterp.cpp
+++ b/js/src/jsinterp.cpp
@@ -64,19 +64,17 @@
 #include "jsnum.h"
 #include "jsobj.h"
 #include "jsopcode.h"
 #include "jsscan.h"
 #include "jsscope.h"
 #include "jsscript.h"
 #include "jsstr.h"
 #include "jsstaticcheck.h"
-#ifdef JS_TRACER
 #include "jstracer.h"
-#endif
 
 #ifdef INCLUDE_MOZILLA_DTRACE
 #include "jsdtracef.h"
 #endif
 
 #if JS_HAS_XML_SUPPORT
 #include "jsxml.h"
 #endif
@@ -4447,19 +4445,17 @@ js_Interpret(JSContext *cx)
                         JS_LOCK_OBJ(cx, obj);
                         scope = OBJ_SCOPE(obj);
                         if (scope->shape == kshape) {
                             JS_ASSERT(PCVAL_IS_SPROP(entry->vword));
                             sprop = PCVAL_TO_SPROP(entry->vword);
                             JS_ASSERT(!(sprop->attrs & JSPROP_READONLY));
                             JS_ASSERT(!SCOPE_IS_SEALED(OBJ_SCOPE(obj)));
 
-#ifdef JS_TRACER
-                            TRACE_2(SetPropHit, kshape, sprop);
-#endif
+                            TRACE_2(SetPropHit, entry, sprop);
 
                             if (scope->object == obj) {
                                 /*
                                  * Fastest path: the cached sprop is already
                                  * in scope. Just NATIVE_SET and break to get
                                  * out of the do-while(0).
                                  */
                                 if (sprop == scope->lastProp ||
@@ -6083,19 +6079,17 @@ js_Interpret(JSContext *cx)
                     /*
                      * Detect a repeated property name and force a miss to
                      * share the strict warning code and cope with complexity
                      * managed by js_AddScopeProperty.
                      */
                     if (sprop->parent != scope->lastProp)
                         goto do_initprop_miss;
 
-#ifdef JS_TRACER
-                    TRACE_2(SetPropHit, kshape, sprop);
-#endif
+                    TRACE_2(SetPropHit, entry, sprop);
 
                     /*
                      * Otherwise this entry must be for a direct property of
                      * obj, not a proto-property, and there cannot have been
                      * any deletions of prior properties.
                      */
                     JS_ASSERT(PCVCAP_MAKE(sprop->shape, 0, 0) == entry->vcap);
                     JS_ASSERT(!SCOPE_HAD_MIDDLE_DELETE(scope));
--- a/js/src/jstracer.cpp
+++ b/js/src/jstracer.cpp
@@ -4388,17 +4388,17 @@ TraceRecorder::record_JSOP_SETPROP()
 
     JSObject* obj = JSVAL_TO_OBJECT(l);
     if (obj->map->ops->setProperty != js_SetProperty)
         ABORT_TRACE("non-native JSObjectOps::setProperty");
     return true;
 }
 
 bool
-TraceRecorder::record_SetPropHit(uint32 kshape, JSScopeProperty* sprop)
+TraceRecorder::record_SetPropHit(JSPropCacheEntry* entry, JSScopeProperty* sprop)
 {
     jsbytecode* pc = cx->fp->regs->pc;
     jsval& r = stackval(-1);
     jsval& l = stackval(-2);
 
     JS_ASSERT(!JSVAL_IS_PRIMITIVE(l));
     JSObject* obj = JSVAL_TO_OBJECT(l);
     LIns* obj_ins = get(&l);
@@ -4420,23 +4420,23 @@ TraceRecorder::record_SetPropHit(uint32 
 
     // The global object's shape is guarded at trace entry, all others need a guard here.
     LIns* map_ins = lir->insLoad(LIR_ldp, obj_ins, (int)offsetof(JSObject, map));
     LIns* ops_ins;
     if (!map_is_native(obj->map, map_ins, ops_ins, offsetof(JSObjectOps, setProperty)))
         return false;
 
     LIns* shape_ins = addName(lir->insLoad(LIR_ld, map_ins, offsetof(JSScope, shape)), "shape");
-    guard(true, addName(lir->ins2i(LIR_eq, shape_ins, kshape), "guard(shape)"), MISMATCH_EXIT);
-
-    JSScope* scope = OBJ_SCOPE(obj);
-    if (scope->object != obj || !SCOPE_HAS_PROPERTY(scope, sprop)) {
+    guard(true, addName(lir->ins2i(LIR_eq, shape_ins, entry->kshape), "guard(shape)"),
+          MISMATCH_EXIT);
+
+    if (entry->kshape != PCVCAP_SHAPE(entry->vcap)) {
         LIns* args[] = { INS_CONSTPTR(sprop), obj_ins, cx_ins };
         LIns* ok_ins = lir->insCall(F_AddProperty, args);
-        guard(false, lir->ins_eq0(ok_ins), MISMATCH_EXIT);
+        guard(false, lir->ins_eq0(ok_ins), OOM_EXIT);
     }
 
     LIns* dslots_ins = NULL;
     LIns* v_ins = get(&r);
     LIns* boxed_ins = v_ins;
     if (!box_jsval(r, boxed_ins))
         return false;
     if (!native_set(obj_ins, sprop, dslots_ins, boxed_ins))
@@ -4445,21 +4445,31 @@ TraceRecorder::record_SetPropHit(uint32 
     if (*pc != JSOP_INITPROP && pc[JSOP_SETPROP_LENGTH] != JSOP_POP)
         set(&l, v_ins);
     return true;
 }
 
 bool
 TraceRecorder::record_SetPropMiss(JSPropCacheEntry* entry)
 {
-    if (!entry->kpc)
+    if (entry->kpc != cx->fp->regs->pc || !PCVAL_IS_SPROP(entry->vword))
         ABORT_TRACE("can't trace uncacheable property set");
 
-    JS_ASSERT(PCVAL_IS_SPROP(entry->vword));
-    return record_SetPropHit(entry->kshape, PCVAL_TO_SPROP(entry->vword));
+    JSScopeProperty* sprop = PCVAL_TO_SPROP(entry->vword);
+
+#ifdef DEBUG
+    jsval& l = stackval(-2);
+    JSObject* obj = JSVAL_TO_OBJECT(l);
+    JSScope* scope = OBJ_SCOPE(obj);
+    JS_ASSERT(scope->object == obj);
+    JS_ASSERT(scope->shape == PCVCAP_SHAPE(entry->vcap));
+    JS_ASSERT(SCOPE_HAS_PROPERTY(scope, sprop));
+#endif
+
+    return record_SetPropHit(entry, sprop);
 }
 
 bool
 TraceRecorder::record_JSOP_GETELEM()
 {
     jsval& r = stackval(-1);
     jsval& l = stackval(-2);
 
--- a/js/src/jstracer.h
+++ b/js/src/jstracer.h
@@ -37,17 +37,17 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef jstracer_h___
 #define jstracer_h___
 
-#if defined JS_TRACER
+#ifdef JS_TRACER
 
 #include "jsstddef.h"
 #include "jstypes.h"
 #include "jslock.h"
 #include "jsnum.h"
 #include "jsinterp.h"
 
 #include "nanojit/nanojit.h"
@@ -353,17 +353,17 @@ public:
     bool selectCallablePeerFragment(nanojit::Fragment** first);
     void prepareTreeCall(nanojit::Fragment* inner);
     void emitTreeCall(nanojit::Fragment* inner, nanojit::GuardRecord* lr);
     unsigned getCallDepth() const;
     bool trackLoopEdges();
     
     bool record_EnterFrame();
     bool record_LeaveFrame();
-    bool record_SetPropHit(uint32 kshape, JSScopeProperty* sprop);
+    bool record_SetPropHit(JSPropCacheEntry* entry, JSScopeProperty* sprop);
     bool record_SetPropMiss(JSPropCacheEntry* entry);
 
     void deepAbort() { deepAborted = true; }
     bool wasDeepAborted() { return deepAborted; }
 
 #define OPDEF(op,val,name,token,length,nuses,ndefs,prec,format)               \
     bool record_##op();
 # include "jsopcode.tbl"
@@ -422,11 +422,17 @@ extern void
 js_FlushJITCache(JSContext* cx);
 
 extern void
 js_FlushJITOracle(JSContext* cx);
 
 extern void
 js_ShutDownJIT();
 
-#endif /* defined JS_TRACER */
+#else  /* !JS_TRACER */
+
+#define RECORD(x)               ((void)0)
+#define TRACE_1(x,a)            ((void)0)
+#define TRACE_2(x,a,b)          ((void)0)
+
+#endif /* !JS_TRACER */
 
 #endif /* jstracer_h___ */