merge
authorNicholas Nethercote <nnethercote@mozilla.com>
Thu, 04 Nov 2010 16:55:13 -0700
changeset 57720 5d2de219ba728a0af05049f00c3bb506017a08d3
parent 57718 92af3359a18ffd2bd1dc259593bca527e68a0881 (current diff)
parent 57719 b38546e5b5f8fdaaa08239cd39c66982706d36c7 (diff)
child 57721 d1c6cef6da3a99ea8b80cb447f6bfb83ba7c6022
push id1
push usershaver@mozilla.com
push dateTue, 04 Jan 2011 17:58:04 +0000
milestone2.0b8pre
merge
js/src/jstracer.cpp
--- a/js/src/jstracer.cpp
+++ b/js/src/jstracer.cpp
@@ -2295,21 +2295,21 @@ TraceRecorder::TraceRecorder(JSContext* 
         } else {
             entryLabel = w.label();
         }
         NanoAssert(entryLabel);
         NanoAssert(!fragment->loopLabel);
         fragment->loopLabel = entryLabel;
     })
 
-    lirbuf->sp = w.name(w.ldpStateField(sp), "sp");
-    lirbuf->rp = w.name(w.ldpStateField(rp), "rp");
-    InitConst(cx_ins) = w.name(w.ldpStateField(cx), "cx");
-    InitConst(eos_ins) = w.name(w.ldpStateField(eos), "eos");
-    InitConst(eor_ins) = w.name(w.ldpStateField(eor), "eor");
+    lirbuf->sp = w.ldpStateField(sp);
+    lirbuf->rp = w.ldpStateField(rp);
+    InitConst(cx_ins) = w.ldpStateField(cx);
+    InitConst(eos_ins) = w.ldpStateField(eos);
+    InitConst(eor_ins) = w.ldpStateField(eor);
 
     strictModeCode_ins = w.name(w.immi(cx->fp()->script()->strictModeCode), "strict");
 
     /* If we came from exit, we might not have enough global types. */
     if (tree->globalSlots->length() > tree->nGlobalTypes())
         SpecializeTreesToMissingGlobals(cx, globalObj, tree);
 
     /* read into registers all values on the stack and all globals we know so far */
@@ -2338,30 +2338,29 @@ TraceRecorder::TraceRecorder(JSContext* 
             LIns* counterPtr = w.nameImmpNonGC((void *) &JS_THREAD_DATA(cx)->iterationCounter);
             LIns* counterValue = w.ldiVolatile(counterPtr);
             LIns* test = w.ltiN(counterValue, LOOP_COUNT_MAX);
             LIns *branch = w.jfUnoptimizable(test);
             /* 
              * stiVolatile() uses ACCSET_STORE_ANY;  If LICM is implemented
              * (bug 545406) this counter will need its own region.
              */
-            w.stiVolatile(w.addi(counterValue, w.nameImmi(1)), counterPtr);
+            w.stiVolatile(w.addi(counterValue, w.immi(1)), counterPtr);
             w.label(branch);
             w.comment("end-count-loop-iterations");
         }
 #endif
     }
 
     /*
      * If we are attached to a tree call guard, make sure the guard the inner
      * tree exited from is what we expect it to be.
      */
     if (anchor && anchor->exitType == NESTED_EXIT) {
-        LIns* nested_ins = w.name(w.ldpStateField(outermostTreeExitGuard),
-                                  "outermostTreeExitGuard");
+        LIns* nested_ins = w.ldpStateField(outermostTreeExitGuard);
         guard(true, w.eqp(nested_ins, w.nameImmpNonGC(innermost)), NESTED_EXIT);
     }
 
     w.comment("end-setup");
 }
 
 TraceRecorder::~TraceRecorder()
 {
@@ -8834,21 +8833,21 @@ TraceRecorder::equalityHelper(Value& l, 
         } else if (l.isBoolean()) {
             JS_ASSERT(r.isBoolean());
             cond = (l == r);
         } else if (l.isString()) {
             JSString *l_str = l.toString();
             JSString *r_str = r.toString();
             if (!l_str->isRope() && !r_str->isRope() && l_str->length() == 1 && r_str->length() == 1) {
                 VMSideExit *exit = snapshot(BRANCH_EXIT);
-                LIns *c = w.nameImmw(1);
+                LIns *c = w.immw(1);
                 guard(true, w.eqp(w.getStringLength(l_ins), c), exit);
                 guard(true, w.eqp(w.getStringLength(r_ins), c), exit);
-                l_ins = w.getStringChar0(l_ins);
-                r_ins = w.getStringChar0(r_ins);
+                l_ins = w.getStringChar(l_ins, w.immpNonGC(0));
+                r_ins = w.getStringChar(r_ins, w.immpNonGC(0));
             } else {
                 args[0] = r_ins, args[1] = l_ins;
                 l_ins = w.call(&js_EqualStrings_ci, args);
                 r_ins = w.immi(1);
             }
             cond = !!js_EqualStrings(l.toString(), r.toString());
         } else {
             JS_ASSERT(l.isNumber() && r.isNumber());
@@ -9366,17 +9365,17 @@ TraceRecorder::guardPropertyCacheHit(LIn
                   exit);
         }
     } else {
         CHECK_STATUS(guardShape(obj_ins, aobj, entry->kshape, "guard_kshape", exit));
     }
 
     if (entry->adding()) {
         LIns *vshape_ins =
-            w.ldiRuntimeProtoHazardShape(w.name(w.ldpConstContextField(runtime), "runtime"));
+            w.ldiRuntimeProtoHazardShape(w.ldpConstContextField(runtime));
 
         guard(true,
               w.name(w.eqiN(vshape_ins, vshape), "guard_protoHazardShape"),
               MISMATCH_EXIT);
     }
 
     // For any hit that goes up the scope and/or proto chains, we will need to
     // guard on the shape of the object containing the property.
@@ -9406,17 +9405,17 @@ TraceRecorder::stobj_set_fslot(LIns *obj
     box_value_into(v, v_ins, FSlotsAddress(obj_ins, slot));
 }
 
 void
 TraceRecorder::stobj_set_dslot(LIns *obj_ins, unsigned slot, LIns*& slots_ins, 
                                const Value &v, LIns* v_ins)
 {
     if (!slots_ins)
-        slots_ins = w.name(w.ldpObjSlots(obj_ins), "slots");
+        slots_ins = w.ldpObjSlots(obj_ins);
     box_value_into(v, v_ins, DSlotsAddress(slots_ins, slot));
 }
 
 void
 TraceRecorder::stobj_set_slot(JSObject *obj, LIns* obj_ins, unsigned slot, LIns*& slots_ins,
                               const Value &v, LIns* v_ins)
 {
     /*
@@ -9443,24 +9442,24 @@ TraceRecorder::unbox_slot(JSObject *obj,
 }
 
 #if JS_BITS_PER_WORD == 32
 
 void
 TraceRecorder::box_undefined_into(Address addr)
 {
     w.stiValueTag(w.nameImmui(JSVAL_TAG_UNDEFINED), addr);
-    w.stiValuePayload(w.nameImmi(0), addr);
+    w.stiValuePayload(w.immi(0), addr);
 }
 
 void
 TraceRecorder::box_null_into(Address addr)
 {
     w.stiValueTag(w.nameImmui(JSVAL_TAG_NULL), addr);
-    w.stiValuePayload(w.nameImmi(0), addr);
+    w.stiValuePayload(w.immi(0), addr);
 }
 
 inline LIns*
 TraceRecorder::unbox_number_as_double(Address addr, LIns *tag_ins, VMSideExit *exit)
 {
     guard(true, w.leui(tag_ins, w.nameImmui(JSVAL_UPPER_INCL_TAG_OF_NUMBER_SET)), exit);
     LIns *val_ins = w.ldiValuePayload(addr);
     LIns* args[] = { val_ins, tag_ins };
@@ -9486,17 +9485,17 @@ TraceRecorder::unbox_non_double_object(A
     guard(true, w.eqi(tag_ins, w.nameImmui(JSVAL_TYPE_TO_TAG(type))), exit);
     return val_ins;
 }
 
 LIns*
 TraceRecorder::unbox_object(Address addr, LIns* tag_ins, JSValueType type, VMSideExit* exit)
 {
     JS_ASSERT(type == JSVAL_TYPE_FUNOBJ || type == JSVAL_TYPE_NONFUNOBJ);
-    guard(true, w.eqi(tag_ins, w.nameImmui(JSVAL_TAG_OBJECT)), exit);
+    guard(true, w.name(w.eqi(tag_ins, w.nameImmui(JSVAL_TAG_OBJECT)), "isObj"), exit);
     LIns *payload_ins = w.ldiValuePayload(addr);
     if (type == JSVAL_TYPE_FUNOBJ)
         guardClass(payload_ins, &js_FunctionClass, exit, LOAD_NORMAL);
     else
         guardNotClass(payload_ins, &js_FunctionClass, exit, LOAD_NORMAL);
     return payload_ins;
 }
 
@@ -9504,22 +9503,22 @@ LIns*
 TraceRecorder::unbox_value(const Value &v, Address addr, VMSideExit *exit, bool force_double)
 {
     LIns *tag_ins = w.ldiValueTag(addr);
 
     if (v.isNumber() && force_double)
         return unbox_number_as_double(addr, tag_ins, exit);
 
     if (v.isInt32()) {
-        guard(true, w.eqi(tag_ins, w.nameImmui(JSVAL_TAG_INT32)), exit);
+        guard(true, w.name(w.eqi(tag_ins, w.nameImmui(JSVAL_TAG_INT32)), "isInt"), exit);
         return w.i2d(w.ldiValuePayload(addr));
     }
 
     if (v.isDouble()) {
-        guard(true, w.ltui(tag_ins, w.nameImmui(JSVAL_TAG_CLEAR)), exit);
+        guard(true, w.name(w.ltui(tag_ins, w.nameImmui(JSVAL_TAG_CLEAR)), "isDouble"), exit);
         return w.ldd(addr);
     }
 
     if (v.isObject()) {
         JSValueType type = v.toObject().isFunction() ? JSVAL_TYPE_FUNOBJ : JSVAL_TYPE_NONFUNOBJ;
         return unbox_object(addr, tag_ins, type, exit);
     }
 
@@ -9825,21 +9824,25 @@ TraceRecorder::getThis(LIns*& this_ins)
 JS_REQUIRES_STACK void
 TraceRecorder::guardClassHelper(bool cond, LIns* obj_ins, Class* clasp, VMSideExit* exit,
                                 LoadQual loadQual)
 {
     LIns* class_ins = w.ldpObjClasp(obj_ins, loadQual);
 
 #ifdef JS_JIT_SPEW
     char namebuf[32];
+    JS_snprintf(namebuf, sizeof namebuf, "%s_clasp", clasp->name);
+    LIns* clasp_ins = w.name(w.immpNonGC(clasp), namebuf);
     JS_snprintf(namebuf, sizeof namebuf, "guard(class is %s)", clasp->name);
+    LIns* cmp_ins = w.name(w.eqp(class_ins, clasp_ins), namebuf);
 #else
-    static const char namebuf[] = "";
-#endif
-    guard(cond, w.name(w.eqp(class_ins, w.nameImmpNonGC(clasp)), namebuf), exit);
+    LIns* clasp_ins = w.immpNonGC(clasp);
+    LIns* cmp_ins = w.eqp(class_ins, clasp_ins);
+#endif
+    guard(cond, cmp_ins, exit);
 }
 
 JS_REQUIRES_STACK void
 TraceRecorder::guardClass(LIns* obj_ins, Class* clasp, VMSideExit* exit, LoadQual loadQual)
 {
     guardClassHelper(true, obj_ins, clasp, exit, loadQual);
 }
 
@@ -9996,17 +9999,17 @@ TraceRecorder::putActivationObjects()
         args_ins = w.allocp(nargs * sizeof(Value));
         /* Don't copy all the actuals if we are only boxing for the callobj. */
         Address addr = AllocSlotsAddress(args_ins);
         if (nargs == nactual)
             fp->forEachCanonicalActualArg(BoxArg(this, addr));
         else
             fp->forEachFormalArg(BoxArg(this, addr));
     } else {
-        args_ins = w.nameImmpNonGC(0);
+        args_ins = w.immpNonGC(0);
     }
 
     if (have_args) {
         LIns* argsobj_ins = getFrameObjPtr(fp->addressOfArgs());
         LIns* args[] = { args_ins, argsobj_ins, cx_ins };
         w.call(&js_PutArgumentsOnTrace_ci, args);
     }
 
@@ -10015,17 +10018,17 @@ TraceRecorder::putActivationObjects()
         LIns* slots_ins;
         if (nslots) {
             slots_ins = w.allocp(sizeof(Value) * nslots);
             for (int i = 0; i < nslots; ++i) {
                 box_value_into(fp->slots()[i], get(&fp->slots()[i]), 
                                AllocSlotsAddress(slots_ins, i));
             }
         } else {
-            slots_ins = w.nameImmpNonGC(0);
+            slots_ins = w.immpNonGC(0);
         }
 
         LIns* scopeChain_ins = getFrameObjPtr(fp->addressOfScopeChain());
         LIns* args[] = { slots_ins, w.nameImmi(nslots), args_ins,
                          w.nameImmi(fp->numFormalArgs()), scopeChain_ins, cx_ins };
         w.call(&js_PutCallObjectOnTrace_ci, args);
     }
 }
@@ -10225,17 +10228,17 @@ TraceRecorder::record_JSOP_RETURN()
         AUDIT(returnLoopExits);
         return endLoop();
     }
 
     putActivationObjects();
 
 #ifdef MOZ_TRACE_JSCALLS
     if (cx->functionCallback) {
-        LIns* args[] = { w.nameImmi(0), w.nameImmpNonGC(cx->fp()->fun()), cx_ins };
+        LIns* args[] = { w.immi(0), w.nameImmpNonGC(cx->fp()->fun()), cx_ins };
         LIns* call_ins = w.call(&functionProbe_ci, args);
         guard(false, w.eqi0(call_ins), MISMATCH_EXIT);
     }
 #endif
 
     /* If we inlined this function call, make the return value available to the caller code. */
     Value& rval = stackval(-1);
     JSStackFrame *fp = cx->fp();
@@ -10802,17 +10805,17 @@ TraceRecorder::emitNativePropertyOp(cons
 {
     JS_ASSERT(addr_boxed_val_ins->isop(LIR_allocp));
     JS_ASSERT(setflag ? !shape->hasSetterValue() : !shape->hasGetterValue());
     JS_ASSERT(setflag ? !shape->hasDefaultSetter() : !shape->hasDefaultGetterOrIsMethod());
 
     enterDeepBailCall();
 
     w.stStateField(addr_boxed_val_ins, nativeVp);
-    w.stStateField(w.nameImmi(1), nativeVpLen);
+    w.stStateField(w.immi(1), nativeVpLen);
 
     CallInfo* ci = new (traceAlloc()) CallInfo();
     ci->_address = uintptr_t(setflag ? shape->setterOp() : shape->getterOp());
     ci->_typesig = CallInfo::typeSig4(ARGTYPE_I, ARGTYPE_P, ARGTYPE_P, ARGTYPE_P, ARGTYPE_P);
     ci->_isPure = 0;
     ci->_storeAccSet = ACCSET_STORE_ANY;
     ci->_abi = ABI_CDECL;
 #ifdef DEBUG
@@ -11232,17 +11235,17 @@ TraceRecorder::callNative(uintN argc, JS
         if (fun->isConstructor()) {
             vp[1].setMagicWithObjectOrNullPayload(NULL);
             newobj_ins = w.immpMagicNull();
 
             /* Treat this as a regular call, the constructor will behave correctly. */
             mode = JSOP_CALL;
         } else {
             args[0] = w.immpObjGC(funobj);
-            args[1] = w.nameImmpNonGC(clasp);
+            args[1] = w.immpNonGC(clasp);
             args[2] = cx_ins;
             newobj_ins = w.call(&js_CreateThisFromTrace_ci, args);
             guard(false, w.eqp0(newobj_ins), OOM_EXIT);
 
             /*
              * emitNativeCall may take a snapshot below. To avoid having a type
              * mismatch (e.g., where get(&vp[1]) is an object and vp[1] is
              * null), we make sure vp[1] is some object. The actual object
@@ -11352,17 +11355,17 @@ TraceRecorder::functionCall(uintN argc, 
      * class being Function and the function being interpreted.
      */
     JSFunction* fun = GET_FUNCTION_PRIVATE(cx, &fval.toObject());
 
 #ifdef MOZ_TRACE_JSCALLS
     if (cx->functionCallback) {
         JSScript *script = FUN_SCRIPT(fun);
         if (! script || ! script->isEmpty()) {
-            LIns* args[] = { w.nameImmi(1), w.nameImmpNonGC(fun), cx_ins };
+            LIns* args[] = { w.immi(1), w.nameImmpNonGC(fun), cx_ins };
             LIns* call_ins = w.call(&functionProbe_ci, args);
             guard(false, w.eqi0(call_ins), MISMATCH_EXIT);
         }
     }
 #endif
 
     if (FUN_INTERPRETED(fun))
         return interpretedFunctionCall(fval, fun, argc, mode == JSOP_NEW);
@@ -11381,17 +11384,17 @@ TraceRecorder::functionCall(uintN argc, 
         set(&fval, stringify(argv[0]));
         pendingSpecializedNative = IGNORE_NATIVE_CALL_COMPLETE_CALLBACK;
         return RECORD_CONTINUE;
     }
 
     RecordingStatus rs = callNative(argc, mode);
 #ifdef MOZ_TRACE_JSCALLS
     if (cx->functionCallback) {
-        LIns* args[] = { w.nameImmi(0), w.nameImmpNonGC(fun), cx_ins };
+        LIns* args[] = { w.immi(0), w.nameImmpNonGC(fun), cx_ins };
         LIns* call_ins = w.call(&functionProbe_ci, args);
         guard(false, w.eqi0(call_ins), MISMATCH_EXIT);
     }
 #endif
     return rs;
 }
 
 JS_REQUIRES_STACK AbortableRecordingStatus
@@ -12294,17 +12297,17 @@ TraceRecorder::getPropertyWithScriptGett
     }
 }
 
 JS_REQUIRES_STACK RecordingStatus
 TraceRecorder::getCharCodeAt(JSString *str, LIns* str_ins, LIns* idx_ins, LIns** out)
 {
     CHECK_STATUS(makeNumberInt32(idx_ins, &idx_ins));
     idx_ins = w.ui2p(idx_ins);
-    LIns *lengthAndFlags_ins = w.name(w.ldpStringLengthAndFlags(str_ins), "mLengthAndFlags");
+    LIns *lengthAndFlags_ins = w.ldpStringLengthAndFlags(str_ins);
     if (MaybeBranch mbr = w.jt(w.eqp0(w.andp(lengthAndFlags_ins, w.nameImmw(JSString::ROPE_BIT)))))
     {
         w.call(&js_Flatten_ci, &str_ins);
         w.label(mbr);
     }
 
     guard(true,
           w.ltup(idx_ins, w.rshupN(lengthAndFlags_ins, JSString::FLAGS_LENGTH_SHIFT)),
@@ -12791,40 +12794,41 @@ TraceRecorder::setElem(int lval_spindex,
         // rarely, eg. less than 1% of the time in SunSpider.
         LIns* capacity_ins = w.ldiDenseArrayCapacity(obj_ins);
         /*
          * It's important that CSE works across this control-flow diamond
          * because it really helps series of interleaved GETELEM and SETELEM
          * operations.  Likewise with the diamond below.
          */
         w.pauseAddingCSEValues();
-        if (MaybeBranch mbr = w.jt(w.ltui(idx_ins, capacity_ins))) {
+        if (MaybeBranch mbr = w.jt(w.name(w.ltui(idx_ins, capacity_ins), "inRange"))) {
             LIns* args[] = { idx_ins, obj_ins, cx_ins };
             LIns* res_ins = w.call(&js_EnsureDenseArrayCapacity_ci, args);
             guard(false, w.eqi0(res_ins), mismatchExit);
             w.label(mbr);
         }
         w.resumeAddingCSEValues();
 
         // Get the address of the element.
-        LIns *elem_ins = w.getDslotAddress(obj_ins, idx_ins);
+        LIns *elemp_ins = w.name(w.getDslotAddress(obj_ins, idx_ins), "elemp");
 
         // If we are overwriting a hole:
         // - Guard that we don't have any indexed properties along the prototype chain.
         // - Check if the length has changed;  if so, update it to index+1.
         // This happens moderately often, eg. close to 10% of the time in
         // SunSpider, and for some benchmarks it's close to 100%.
-        Address dslotAddr = DSlotsAddress(elem_ins);
-        LIns* isHole_ins = w.eqi(
+        Address dslotAddr = DSlotsAddress(elemp_ins);
+        LIns* isHole_ins = w.name(w.eqi(
 #if JS_BITS_PER_WORD == 32
-                                 w.ldiValueTag(dslotAddr),
+                                        w.ldiValueTag(dslotAddr),
 #else
-                                 w.q2i(w.rshuqN(w.ldq(dslotAddr), JSVAL_TAG_SHIFT)),
-#endif
-                                 w.nameImmui(JSVAL_TAG_MAGIC));
+                                        w.q2i(w.rshuqN(w.ldq(dslotAddr), JSVAL_TAG_SHIFT)),
+#endif
+                                        w.nameImmui(JSVAL_TAG_MAGIC)),
+                                  "isHole");
         w.pauseAddingCSEValues();
         if (MaybeBranch mbr1 = w.jf(isHole_ins)) {
             CHECK_STATUS_A(guardPrototypeHasNoIndexedProperties(obj, obj_ins, mismatchExit));
             LIns* length_ins = w.lduiObjPrivate(obj_ins);
             if (MaybeBranch mbr2 = w.jt(w.ltui(idx_ins, length_ins))) {
                 LIns* newLength_ins = w.name(w.addiN(idx_ins, 1), "newLength");
                 w.stuiObjPrivate(obj_ins, newLength_ins);
                 w.label(mbr2);
@@ -13358,17 +13362,17 @@ TraceRecorder::record_NativeCallComplete
             if (pendingSpecializedNative->flags & JSTN_CONSTRUCTOR) {
                 LIns *cond_ins;
                 LIns *x;
 
                 // v_ins    := the object payload from native_rval_ins
                 // cond_ins := true if native_rval_ins contains a JSObject*
                 unbox_any_object(nativeRvalAddr, &v_ins, &cond_ins);
                 // x        := v_ins if native_rval_ins contains a JSObject*, NULL otherwise
-                x = w.cmovp(cond_ins, v_ins, w.nameImmw(0));
+                x = w.cmovp(cond_ins, v_ins, w.immw(0));
                 // v_ins    := newobj_ins if native_rval_ins doesn't contain a JSObject*,
                 //             the object payload from native_rval_ins otherwise
                 v_ins = w.cmovp(w.eqp0(x), newobj_ins, x);
             } else {
                 v_ins = w.ldd(nativeRvalAddr);
             }
             set(&v, v_ins);
 
@@ -13674,22 +13678,22 @@ TraceRecorder::denseArrayElement(Value& 
 
         // Return undefined and indicate that we didn't actually read this (addr_ins).
         v_ins = w.immiUndefined();
         addr_ins = NULL;
         return RECORD_CONTINUE;
     }
 
     /* Guard that index is within capacity. */
-    guard(true, w.ltui(idx_ins, capacity_ins), branchExit);
+    guard(true, w.name(w.ltui(idx_ins, capacity_ins), "inRange"), branchExit);
 
     /* Load the value and guard on its type to unbox it. */
     vp = &obj->slots[jsuint(idx)];
 	JS_ASSERT(sizeof(Value) == 8); // The |3| in the following statement requires this.
-    addr_ins = w.addp(w.name(w.ldpObjSlots(obj_ins), "slots"), w.lshpN(w.ui2p(idx_ins), 3));
+    addr_ins = w.name(w.getDslotAddress(obj_ins, idx_ins), "elemp");
     v_ins = unbox_value(*vp, DSlotsAddress(addr_ins), branchExit);
 
     /* Don't let the hole value escape. Turn it into an undefined. */
     if (vp->isMagic()) {
         CHECK_STATUS(guardPrototypeHasNoIndexedProperties(obj, obj_ins, snapshot(MISMATCH_EXIT)));
         v_ins = w.immiUndefined();
     }
     return RECORD_CONTINUE;
@@ -15469,17 +15473,17 @@ TraceRecorder::record_JSOP_STOP()
         updateAtoms(fp->script());
         return ARECORD_CONTINUE;
     }
 
     putActivationObjects();
 
 #ifdef MOZ_TRACE_JSCALLS
     if (cx->functionCallback) {
-        LIns* args[] = { w.nameImmi(0), w.nameImmpNonGC(cx->fp()->fun()), cx_ins };
+        LIns* args[] = { w.immi(0), w.nameImmpNonGC(cx->fp()->fun()), cx_ins };
         LIns* call_ins = w.call(&functionProbe_ci, args);
         guard(false, w.eqi0(call_ins), MISMATCH_EXIT);
     }
 #endif
 
     /*
      * We know falling off the end of a constructor returns the new object that
      * was passed in via fp->argv[-1], while falling off the end of a function
--- a/js/src/tracejit/Writer.h
+++ b/js/src/tracejit/Writer.h
@@ -386,19 +386,21 @@ class Writer
     }
 
     /* Specific loads and stores (those not taking an Address argument).  Ordered by AccSets.*/
 
     nj::LIns *ldStateFieldHelper(nj::LOpcode op, nj::LIns *state, int32 offset) const {
         return lir->insLoad(op, state, offset, ACCSET_STATE);
     }
     #define ldiStateField(fieldname) \
-        ldStateFieldHelper(LIR_ldi, lirbuf->state, offsetof(TracerState, fieldname))
+        name(w.ldStateFieldHelper(LIR_ldi, lirbuf->state, offsetof(TracerState, fieldname)), \
+             #fieldname)
     #define ldpStateField(fieldname) \
-        ldStateFieldHelper(LIR_ldp, lirbuf->state, offsetof(TracerState, fieldname))
+        name(w.ldStateFieldHelper(LIR_ldp, lirbuf->state, offsetof(TracerState, fieldname)), \
+             #fieldname)
 
     nj::LIns *stStateFieldHelper(nj::LIns *value, nj::LIns *state, int32 offset) const {
         return lir->insStore(value, state, offset, ACCSET_STATE);
     }
     #define stStateField(value, fieldname) \
         stStateFieldHelper(value, lirbuf->state, offsetof(TracerState, fieldname))
 
     nj::LIns *ldpRstack(nj::LIns *rp, int32 offset) const {
@@ -408,19 +410,21 @@ class Writer
     nj::LIns *stRstack(nj::LIns *value, nj::LIns *rp, int32 offset) const {
         return lir->insStore(value, rp, offset, ACCSET_RSTACK);
     }
 
     nj::LIns *ldpContextFieldHelper(nj::LIns *cx, int32 offset, nj::LoadQual loadQual) const {
         return lir->insLoad(nj::LIR_ldp, cx, offset, ACCSET_CX, loadQual);
     }
     #define ldpContextField(fieldname) \
-        ldpContextFieldHelper(cx_ins, offsetof(JSContext, fieldname), LOAD_NORMAL)
+        name(w.ldpContextFieldHelper(cx_ins, offsetof(JSContext, fieldname), LOAD_NORMAL), \
+             #fieldname)
     #define ldpConstContextField(fieldname) \
-        ldpContextFieldHelper(cx_ins, offsetof(JSContext, fieldname), LOAD_CONST)
+        name(w.ldpContextFieldHelper(cx_ins, offsetof(JSContext, fieldname), LOAD_CONST), \
+             #fieldname)
 
     nj::LIns *stContextField(nj::LIns *value, nj::LIns *cx, int32 offset) const {
         return lir->insStore(value, cx, offset, ACCSET_CX);
     }
     #define stContextField(value, fieldname) \
         stContextField((value), cx_ins, offsetof(JSContext, fieldname))
 
     nj::LIns *ldiAlloc(nj::LIns *alloc) const {
@@ -450,22 +454,24 @@ class Writer
 
     nj::LIns *ldiRuntimeProtoHazardShape(nj::LIns *runtime) const {
         return name(lir->insLoad(nj::LIR_ldi, runtime, offsetof(JSRuntime, protoHazardShape),
                                  ACCSET_RUNTIME),
                     "protoHazardShape");
     }
 
     nj::LIns *ldpObjClasp(nj::LIns *obj, nj::LoadQual loadQual) const {
-        return lir->insLoad(nj::LIR_ldp, obj, offsetof(JSObject, clasp), ACCSET_OBJ_CLASP,
-                            loadQual);
+        return name(lir->insLoad(nj::LIR_ldp, obj, offsetof(JSObject, clasp), ACCSET_OBJ_CLASP,
+                                 loadQual),
+                    "clasp");
     }
 
     nj::LIns *ldiObjFlags(nj::LIns *obj) const {
-        return lir->insLoad(nj::LIR_ldi, obj, offsetof(JSObject, flags), ACCSET_OBJ_FLAGS);
+        return name(lir->insLoad(nj::LIR_ldi, obj, offsetof(JSObject, flags), ACCSET_OBJ_FLAGS),
+                    "flags");
     }
 
     nj::LIns *ldiObjShape(nj::LIns *obj) const {
         return name(lir->insLoad(nj::LIR_ldi, obj, offsetof(JSObject, objShape), ACCSET_OBJ_SHAPE),
                     "objShape");
     }
 
     nj::LIns *ldpObjProto(nj::LIns *obj) const {
@@ -498,27 +504,30 @@ class Writer
 
     nj::LIns *ldiDenseArrayCapacity(nj::LIns *array) const {
         return name(lir->insLoad(nj::LIR_ldi, array, offsetof(JSObject, capacity),
                                  ACCSET_OBJ_CAPACITY),
                     "capacity");
     }
 
     nj::LIns *ldpObjSlots(nj::LIns *obj) const {
-        return lir->insLoad(nj::LIR_ldp, obj, offsetof(JSObject, slots), ACCSET_OBJ_SLOTS);
+        return name(lir->insLoad(nj::LIR_ldp, obj, offsetof(JSObject, slots), ACCSET_OBJ_SLOTS),
+                    "slots");
     }
 
     nj::LIns *ldiConstTypedArrayLength(nj::LIns *array) const {
-        return lir->insLoad(nj::LIR_ldi, array, js::TypedArray::lengthOffset(), ACCSET_TARRAY,
-                            nj::LOAD_CONST);
+        return name(lir->insLoad(nj::LIR_ldi, array, js::TypedArray::lengthOffset(), ACCSET_TARRAY,
+                                 nj::LOAD_CONST),
+                    "typedArrayLength");
     }
 
     nj::LIns *ldpConstTypedArrayData(nj::LIns *array) const {
-        return lir->insLoad(nj::LIR_ldp, array, js::TypedArray::dataOffset(), ACCSET_TARRAY,
-                            nj::LOAD_CONST);
+        return name(lir->insLoad(nj::LIR_ldp, array, js::TypedArray::dataOffset(), ACCSET_TARRAY,
+                                 nj::LOAD_CONST),
+                    "typedElems");
     }
 
     nj::LIns *ldc2iTypedArrayElement(nj::LIns *elems, nj::LIns *index) const {
         return lir->insLoad(nj::LIR_ldc2i, addp(elems, index), 0, ACCSET_TARRAY_DATA);
     }
 
     nj::LIns *lduc2uiTypedArrayElement(nj::LIns *elems, nj::LIns *index) const {
         return lir->insLoad(nj::LIR_lduc2ui, addp(elems, index), 0, ACCSET_TARRAY_DATA);
@@ -581,17 +590,19 @@ class Writer
     }
 
     nj::LIns *stpIterCursor(nj::LIns *cursor, nj::LIns *iter) const {
         return lir->insStore(nj::LIR_stp, cursor, iter, offsetof(NativeIterator, props_cursor),
                              ACCSET_ITER);
     }
 
     nj::LIns *ldpStringLengthAndFlags(nj::LIns *str) const {
-        return lir->insLoad(nj::LIR_ldp, str, offsetof(JSString, mLengthAndFlags), ACCSET_STRING);
+        return name(lir->insLoad(nj::LIR_ldp, str, offsetof(JSString, mLengthAndFlags),
+                                 ACCSET_STRING),
+                    "mLengthAndFlags");
     }
 
     nj::LIns *ldpStringChars(nj::LIns *str) const {
         return name(lir->insLoad(nj::LIR_ldp, str, offsetof(JSString, mChars), ACCSET_STRING),
                     "mChars");
     }
 
     nj::LIns *lduc2uiConstTypeMapEntry(nj::LIns *typemap, nj::LIns *index) const {
@@ -607,47 +618,52 @@ class Writer
     nj::LIns *stiVolatile(nj::LIns *value, nj::LIns *base) const {
         return lir->insStore(nj::LIR_sti, value, base, 0, nj::ACCSET_STORE_ANY);
     }
 
     nj::LIns *ldiVMSideExitFieldHelper(nj::LIns *lr, int32 offset) const {
         return lir->insLoad(nj::LIR_ldi, lr, offset, nj::ACCSET_LOAD_ANY);
     }
     #define ldiVMSideExitField(lr, fieldname) \
-        ldiVMSideExitFieldHelper((lr), offsetof(VMSideExit, fieldname))
+        name(w.ldiVMSideExitFieldHelper((lr), offsetof(VMSideExit, fieldname)), #fieldname)
 
     nj::LIns *ldpGuardRecordExit(nj::LIns *gr) const {
         /*
          * We use ACCSET_LOAD_ANY for the GuardRecord and VMSideExit loads;
          * they're immediately after a fragment call, and so won't be
          * optimizable anyway.
          */
-        return lir->insLoad(nj::LIR_ldp, gr, offsetof(nj::GuardRecord, exit), nj::ACCSET_LOAD_ANY);
+        return name(lir->insLoad(nj::LIR_ldp, gr, offsetof(nj::GuardRecord, exit),
+                                 nj::ACCSET_LOAD_ANY),
+                    "exit");
     }
 
     nj::LIns *stTprintArg(nj::LIns *insa[], nj::LIns *args, int index) const {
         JS_ASSERT(insa[index]);
         /* The AccSet doesn't matter much here, this is debug-only code. */
         return lir->insStore(insa[index], args, sizeof(double) * index, nj::ACCSET_STORE_ANY);
     }
 
     /* Generic loads and stores (those taking an Address argument). */
 
 #if JS_BITS_PER_WORD == 32
     nj::LIns *ldiValueTag(Address addr) const {
-        return lir->insLoad(nj::LIR_ldi, addr.base, addr.offset + sTagOffset, addr.accSet);
+        return name(lir->insLoad(nj::LIR_ldi, addr.base, addr.offset + sTagOffset, addr.accSet),
+                    "tag");
     }
 
     nj::LIns *stiValueTag(nj::LIns *tag, Address addr) const {
         JS_ASSERT(tag->isI());
         return lir->insStore(tag, addr.base, addr.offset + sTagOffset, addr.accSet);
     }
 
     nj::LIns *ldiValuePayload(Address addr) const {
-        return lir->insLoad(nj::LIR_ldi, addr.base, addr.offset + sPayloadOffset, addr.accSet);
+        return name(lir->insLoad(nj::LIR_ldi, addr.base, addr.offset + sPayloadOffset,
+                                 addr.accSet),
+                    "payload");
     }
 
     nj::LIns *stiValuePayload(nj::LIns *payload, Address addr) const {
         JS_ASSERT(payload->isI());
         return lir->insStore(payload, addr.base, addr.offset + sPayloadOffset, addr.accSet);
     }
 #endif  // JS_BITS_PER_WORD == 32
 
@@ -783,17 +799,17 @@ class Writer
 
     /* Immediates */
 
     nj::LIns *immi(int32 i) const {
         return lir->insImmI(i);
     }
 
     nj::LIns *immiUndefined() const {
-        return name(immi(0), "0");
+        return name(immi(0), "undefined");
     }
 
     /*
      * These must be macros because they stringify their argument.  Likewise
      * with similar 'nameXYZ' operations below, 
      *
      * These nameXYZ() macros have the 'name' prefix to distinguish them from the
      * non-naming XYZ() functions.
@@ -816,16 +832,20 @@ class Writer
      * TraceRecorder::immpXyzGC() variants should be used because they ensure
      * that the embedded pointer will be kept alive across GCs.  These types
      * make it difficult to inadvertently get this wrong.
      */
     nj::LIns *immpNonGC(const void *p) const {
         return lir->insImmP(p);
     }
 
+    nj::LIns *immw(intptr_t i) const {
+        return lir->insImmP((void *)i);
+    }
+
     #define nameImmpNonGC(p)    name(w.immpNonGC(p), #p)
     #define nameImmw(ww)        name(w.immpNonGC((void *) (ww)), #ww)
 
     nj::LIns *immpNull() const {
         return name(immpNonGC(NULL), "NULL");
     }
 
     #define immpMagicWhy(why)   name(w.immpNonGC((void *)(size_t)(why)), #why)
@@ -1138,60 +1158,55 @@ class Writer
     /* Operations involving non-trivial combinations of multiple instructions. */
 
     /*
      * Nb: this "Privatized" refers to the Private API in jsvalue.h.  It
      * doesn't refer to the JSObj::privateData slot!  Confusing.
      */
     nj::LIns *getObjPrivatizedSlot(nj::LIns *obj, uint32 slot) const {
 #if JS_BITS_PER_WORD == 32
-        nj::LIns *vaddr_ins = lir->insLoad(nj::LIR_ldp, obj, offsetof(JSObject, slots),
-                                           ACCSET_OBJ_SLOTS);
+        nj::LIns *vaddr_ins = ldpObjSlots(obj);
         return lir->insLoad(nj::LIR_ldi, vaddr_ins,
                             slot * sizeof(Value) + sPayloadOffset, ACCSET_SLOTS, nj::LOAD_CONST);
 
 #elif JS_BITS_PER_WORD == 64
         /* N.B. On 64-bit, privatized value are encoded differently from other pointers. */
-        nj::LIns *vaddr_ins = lir->insLoad(nj::LIR_ldp, obj, offsetof(JSObject, slots),
-                                       ACCSET_OBJ_SLOTS);
+        nj::LIns *vaddr_ins = ldpObjSlots(obj);
         nj::LIns *v_ins = lir->insLoad(nj::LIR_ldq, vaddr_ins,
                                        slot * sizeof(Value) + sPayloadOffset,
                                        ACCSET_SLOTS, nj::LOAD_CONST);
         return lshqN(v_ins, 1);
 #endif
     }
 
     nj::LIns *getDslotAddress(nj::LIns *obj, nj::LIns *idx) const {
-        nj::LIns *slots = name(ldpObjSlots(obj), "slots");
         JS_ASSERT(sizeof(Value) == 8); // The |3| in the following statement requires this.
-        return addp(slots, lshpN(ui2p(idx), 3));
+        nj::LIns *offset = lshpN(ui2p(idx), 3);
+        nj::LIns *slots = ldpObjSlots(obj);
+        return addp(slots, offset);
     }
 
     nj::LIns *getStringLength(nj::LIns *str) const {
-        return name(rshupN(name(ldpStringLengthAndFlags(str), "mLengthAndFlags"),
-                           JSString::FLAGS_LENGTH_SHIFT), "length");
+        return name(rshupN(ldpStringLengthAndFlags(str), JSString::FLAGS_LENGTH_SHIFT),
+                    "strLength");
     }
 
     nj::LIns *getStringChar(nj::LIns *str, nj::LIns *idx) const {
         nj::LIns *chars = ldpStringChars(str);
-        return lir->insLoad(nj::LIR_ldus2ui, addp(chars, lshpN(idx, 1)), 0,
-                            ACCSET_STRING_MCHARS, nj::LOAD_CONST);
-    }
-
-    nj::LIns *getStringChar0(nj::LIns *str) const {
-        nj::LIns *chars = ldpStringChars(str);
-        return lir->insLoad(nj::LIR_ldus2ui, chars, 0, ACCSET_STRING_MCHARS, nj::LOAD_CONST);
+        return name(lir->insLoad(nj::LIR_ldus2ui, addp(chars, lshpN(idx, 1)), 0,
+                                 ACCSET_STRING_MCHARS, nj::LOAD_CONST),
+                    "strChar");
     }
 
     nj::LIns *getArgsLength(nj::LIns *args) const {
         uint32 slot = JSObject::JSSLOT_ARGS_LENGTH;
-        nj::LIns *vaddr_ins = lir->insLoad(nj::LIR_ldp, args, offsetof(JSObject, slots),
-                                           ACCSET_OBJ_SLOTS);
-        return lir->insLoad(nj::LIR_ldi, vaddr_ins, slot * sizeof(Value) + sPayloadOffset,
-                            ACCSET_SLOTS);
+        nj::LIns *vaddr_ins = ldpObjSlots(args);
+        return name(lir->insLoad(nj::LIR_ldi, vaddr_ins, slot * sizeof(Value) + sPayloadOffset,
+                                 ACCSET_SLOTS),
+                    "argsLength");
     }
 };
 
 }   /* namespace tjit */
 }   /* namespace js */
 
 #endif /* tracejit_Writer_h___ */