Fix PunboxAssembler interface returning wrong labels (bug 625757, r=cdleary, a=betaN+).
authorDavid Anderson <danderson@mozilla.com>
Fri, 14 Jan 2011 15:42:42 -0800
changeset 60637 4275fce7591ba790bdfb2dc069759a492c2636b4
parent 60636 0f1fd87b570d08e9411eb06809440f0b2b738852
child 60638 ea7bedcd069cea4e676deb43e5f788447269ed04
push id18053
push usercleary@mozilla.com
push dateSat, 15 Jan 2011 03:38:42 +0000
treeherdermozilla-central@4275fce7591b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerscdleary, betaN
bugs625757
milestone2.0b10pre
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Fix PunboxAssembler interface returning wrong labels (bug 625757, r=cdleary, a=betaN+).
js/src/assembler/assembler/AbstractMacroAssembler.h
js/src/jit-test/tests/jaeger/bug625757.js
js/src/methodjit/Compiler.cpp
js/src/methodjit/Compiler.h
js/src/methodjit/ICLabels.h
js/src/methodjit/MonoIC.h
js/src/methodjit/NunboxAssembler.h
js/src/methodjit/PunboxAssembler.h
--- a/js/src/assembler/assembler/AbstractMacroAssembler.h
+++ b/js/src/assembler/assembler/AbstractMacroAssembler.h
@@ -475,16 +475,21 @@ public:
     {
         return m_assembler.executableCopy(buffer);
     }
 
     Label label()
     {
         return Label(this);
     }
+
+    DataLabel32 dataLabel32()
+    {
+        return DataLabel32(this);
+    }
     
     Label align()
     {
         m_assembler.align(16);
         return Label(this);
     }
 
     ptrdiff_t differenceBetween(Label from, Jump to)
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/jaeger/bug625757.js
@@ -0,0 +1,4 @@
+for(var i=0; i<20; i++) {
+    var x = 5e-324;
+}
+/* Don't crash. */
--- a/js/src/methodjit/Compiler.cpp
+++ b/js/src/methodjit/Compiler.cpp
@@ -484,17 +484,20 @@ mjit::Compiler::finishThisUp(JITScript *
 
     if (ic::MICInfo *scriptMICs = jit->mics) {
         for (size_t i = 0; i < mics.length(); i++) {
             scriptMICs[i].kind = mics[i].kind;
             scriptMICs[i].entry = fullCode.locationOf(mics[i].entry);
             switch (mics[i].kind) {
               case ic::MICInfo::GET:
               case ic::MICInfo::SET:
-                scriptMICs[i].load = fullCode.locationOf(mics[i].load);
+                if (mics[i].kind == ic::MICInfo::GET)
+                    scriptMICs[i].load = fullCode.locationOf(mics[i].load);
+                else
+                    scriptMICs[i].load = fullCode.locationOf(mics[i].store).labelAtOffset(0);
                 scriptMICs[i].shape = fullCode.locationOf(mics[i].shape);
                 scriptMICs[i].stubCall = stubCode.locationOf(mics[i].call);
                 scriptMICs[i].stubEntry = stubCode.locationOf(mics[i].stubEntry);
                 scriptMICs[i].u.name.typeConst = mics[i].u.name.typeConst;
                 scriptMICs[i].u.name.dataConst = mics[i].u.name.dataConst;
                 scriptMICs[i].u.name.usePropertyCache = mics[i].u.name.usePropertyCache;
                 break;
               default:
@@ -3444,17 +3447,17 @@ mjit::Compiler::jsop_setprop(JSAtom *ato
     }
 
     /* Load dslots. */
     Label dslotsLoadLabel = masm.loadPtrWithPatchToLEA(Address(objReg, offsetof(JSObject, slots)),
                                                        objReg);
 
     /* Store RHS into object slot. */
     Address slot(objReg, 1 << 24);
-    Label inlineValueStore = masm.storeValueWithAddressOffsetPatch(vr, slot);
+    DataLabel32 inlineValueStore = masm.storeValueWithAddressOffsetPatch(vr, slot);
     pic.fastPathRejoin = masm.label();
 
     frame.freeReg(objReg);
     frame.freeReg(shapeReg);
 
     /* "Pop under", taking out object (LHS) and leaving RHS. */
     frame.shimmy(1);
 
@@ -4423,34 +4426,23 @@ mjit::Compiler::jsop_setgname(JSAtom *at
     } else {
         v = fe->getValue();
     }
 
     masm.loadPtr(Address(objReg, offsetof(JSObject, slots)), objReg);
     Address address(objReg, slot);
 
     if (mic.u.name.dataConst) {
-        mic.load = masm.storeValueWithAddressOffsetPatch(v, address);
+        mic.store = masm.storeValueWithAddressOffsetPatch(v, address);
     } else if (mic.u.name.typeConst) {
-        mic.load = masm.storeValueWithAddressOffsetPatch(ImmType(typeTag), dataReg, address);
+        mic.store = masm.storeValueWithAddressOffsetPatch(ImmType(typeTag), dataReg, address);
     } else {
-        mic.load = masm.storeValueWithAddressOffsetPatch(typeReg, dataReg, address);
+        mic.store = masm.storeValueWithAddressOffsetPatch(typeReg, dataReg, address);
     }
 
-#if defined JS_PUNBOX64
-    /* 
-     * Instructions on x86_64 can vary in size based on registers
-     * used. Since we only need to patch the last instruction in
-     * both paths above, remember the distance between the
-     * load label and after the instruction to be patched.
-     */
-    mic.patchValueOffset = masm.differenceBetween(mic.load, masm.label());
-    JS_ASSERT(mic.patchValueOffset == masm.differenceBetween(mic.load, masm.label()));
-#endif
-
     frame.freeReg(objReg);
     frame.popn(2);
     if (mic.u.name.dataConst) {
         frame.push(v);
     } else {
         if (mic.u.name.typeConst)
             frame.pushTypedPayload(typeTag, dataReg);
         else
--- a/js/src/methodjit/Compiler.h
+++ b/js/src/methodjit/Compiler.h
@@ -69,20 +69,18 @@ class Compiler : public BaseCompiler
 #if defined JS_MONOIC
     struct MICGenInfo {
         MICGenInfo(ic::MICInfo::Kind kind) : kind(kind)
         { }
         Label entry;
         Label stubEntry;
         DataLabel32 shape;
         DataLabelPtr addrLabel;
-#if defined JS_PUNBOX64
-        uint32 patchValueOffset;
-#endif
         Label load;
+        DataLabel32 store;
         Call call;
         ic::MICInfo::Kind kind;
         jsbytecode *jumpTarget;
         Jump traceHint;
         MaybeJump slowTraceHint;
         union {
             struct {
                 bool typeConst;
--- a/js/src/methodjit/ICLabels.h
+++ b/js/src/methodjit/ICLabels.h
@@ -227,17 +227,17 @@ struct GetPropLabels : MacroAssemblerTyp
     int32 inlineTypeJumpOffset : 8;
 #endif
 };
 
 /* SetPropCompiler */
 struct SetPropLabels : MacroAssemblerTypedefs {
     friend class ::ICOffsetInitializer;
 
-    void setInlineValueStore(MacroAssembler &masm, Label fastPathRejoin, Label inlineValueStore,
+    void setInlineValueStore(MacroAssembler &masm, Label fastPathRejoin, DataLabel32 inlineValueStore,
                              const ValueRemat &vr) {
         int offset = masm.differenceBetween(fastPathRejoin, inlineValueStore);
         setInlineValueStoreOffset(offset, vr.isConstant(), vr.isTypeKnown());
     }
 
     CodeLocationLabel getInlineValueStore(CodeLocationLabel fastPathRejoin, const ValueRemat &vr) {
         return fastPathRejoin.labelAtOffset(getInlineValueStoreOffset(vr.isConstant(),
                                                                       vr.isTypeKnown()));
--- a/js/src/methodjit/MonoIC.h
+++ b/js/src/methodjit/MonoIC.h
@@ -99,18 +99,16 @@ struct MICInfo {
         GET,
         SET
     };
 
     /* Used by multiple MICs. */
     JSC::CodeLocationLabel entry;
     JSC::CodeLocationLabel stubEntry;
 
-    /* TODO: use a union-like structure for the below. */
-
     /*
      * - ARM and x64 always emit exactly one instruction which needs to be
      *   patched. On ARM, the label points to the patched instruction, whilst
      *   on x64 it points to the instruction after it.
      * - For x86, the label "load" points to the start of the load/store
      *   sequence, which may consist of one or two "mov" instructions. Because
      *   of this, x86 is the only platform which requires non-trivial patching
      *   code.
--- a/js/src/methodjit/NunboxAssembler.h
+++ b/js/src/methodjit/NunboxAssembler.h
@@ -198,82 +198,73 @@ class NunboxAssembler : public JSC::Macr
     }
 
     /*
      * Store a (64b) js::Value from type |treg| and payload |dreg| into |address|, and
      * return a label which can be used by
      * ICRepatcher::patchAddressOffsetForValueStore to patch the address'
      * offset.
      */
-    Label storeValueWithAddressOffsetPatch(RegisterID treg, RegisterID dreg, Address address) {
-        Label start = label();
+    DataLabel32 storeValueWithAddressOffsetPatch(RegisterID treg, RegisterID dreg, Address address) {
+        DataLabel32 start = dataLabel32();
 #if defined JS_CPU_X86
         /*
          * On x86 there are two stores to patch and they both encode the offset
          * in-line.
          */
         storeTypeTag(treg, address);
         DBGLABEL_NOMASM(endType);
         storePayload(dreg, address);
         DBGLABEL_NOMASM(endPayload);
         JS_ASSERT(differenceBetween(start, endType) == 6);
         JS_ASSERT(differenceBetween(endType, endPayload) == 6);
         return start;
 #elif defined JS_CPU_ARM
-        DataLabel32 store = store64WithAddressOffsetPatch(treg, dreg, address);
-        JS_ASSERT(differenceBetween(start, store) == 0);
-        (void) store;
-        return start;
+        return store64WithAddressOffsetPatch(treg, dreg, address);
 #endif
     }
 
     /* Overloaded for storing a constant type. */
-    Label storeValueWithAddressOffsetPatch(ImmType type, RegisterID dreg, Address address) {
-        Label start = label();
+    DataLabel32 storeValueWithAddressOffsetPatch(ImmType type, RegisterID dreg, Address address) {
+        DataLabel32 start = dataLabel32();
 #if defined JS_CPU_X86
         storeTypeTag(type, address);
         DBGLABEL_NOMASM(endType);
         storePayload(dreg, address);
         DBGLABEL_NOMASM(endPayload);
         JS_ASSERT(differenceBetween(start, endType) == 10);
         JS_ASSERT(differenceBetween(endType, endPayload) == 6);
         return start;
 #elif defined JS_CPU_ARM
-        DataLabel32 store = store64WithAddressOffsetPatch(type, dreg, address);
-        JS_ASSERT(differenceBetween(start, store) == 0);
-        (void) store;
-        return start;
+        return store64WithAddressOffsetPatch(type, dreg, address);
 #endif
     }
 
     /* Overloaded for storing constant type and data. */
-    Label storeValueWithAddressOffsetPatch(const Value &v, Address address) {
+    DataLabel32 storeValueWithAddressOffsetPatch(const Value &v, Address address) {
         jsval_layout jv;
         jv.asBits = JSVAL_BITS(Jsvalify(v));
         ImmTag type(jv.s.tag);
         Imm32 payload(jv.s.payload.u32);
-        Label start = label();
+        DataLabel32 start = dataLabel32();
 #if defined JS_CPU_X86
         store32(type, tagOf(address));
         DBGLABEL_NOMASM(endType);
         store32(payload, payloadOf(address));
         DBGLABEL_NOMASM(endPayload);
         JS_ASSERT(differenceBetween(start, endType) == 10);
         JS_ASSERT(differenceBetween(endType, endPayload) == 10);
         return start;
 #elif defined JS_CPU_ARM
-        DataLabel32 store = store64WithAddressOffsetPatch(type, payload, address);
-        JS_ASSERT(differenceBetween(start, store) == 0);
-        (void) store;
-        return start;
+        return store64WithAddressOffsetPatch(type, payload, address);
 #endif
     }
 
     /* Overloaded for store with value remat info. */
-    Label storeValueWithAddressOffsetPatch(const ValueRemat &vr, Address address) {
+    DataLabel32 storeValueWithAddressOffsetPatch(const ValueRemat &vr, Address address) {
         if (vr.isConstant()) {
             return storeValueWithAddressOffsetPatch(vr.value(), address);
         } else if (vr.isTypeKnown()) {
             ImmType type(vr.knownType());
             RegisterID data(vr.dataReg());
             return storeValueWithAddressOffsetPatch(type, data, address);
         } else {
             RegisterID type(vr.typeReg());
--- a/js/src/methodjit/PunboxAssembler.h
+++ b/js/src/methodjit/PunboxAssembler.h
@@ -154,35 +154,40 @@ class PunboxAssembler : public JSC::Macr
         storeValue(Registers::ValueReg, address);
     }
 
     /*
      * Store a (64b) js::Value from 'type' and 'payload' into 'address', and
      * return a label which can be used by
      * Repatcher::patchAddressOffsetForValueStore to patch the address offset.
      */
-    Label storeValueWithAddressOffsetPatch(RegisterID type, RegisterID payload, Address address) {
-        storeValueFromComponents(type, payload, address);
-        return label();
+    DataLabel32 storeValueWithAddressOffsetPatch(RegisterID type, RegisterID payload, Address address) {
+        move(type, Registers::ValueReg);
+        orPtr(payload, Registers::ValueReg);
+        return storePtrWithAddressOffsetPatch(Registers::ValueReg, address);
     }
 
     /* Overload for constant type. */
-    Label storeValueWithAddressOffsetPatch(ImmTag type, RegisterID payload, Address address) {
-        storeValueFromComponents(type, payload, address);
-        return label();
+    DataLabel32 storeValueWithAddressOffsetPatch(ImmTag type, RegisterID payload, Address address) {
+        move(type, Registers::ValueReg);
+        orPtr(payload, Registers::ValueReg);
+        return storePtrWithAddressOffsetPatch(Registers::ValueReg, address);
     }
 
     /* Overload for constant type and constant data. */
-    Label storeValueWithAddressOffsetPatch(const Value &v, Address address) {
-        storeValue(v, address);
-        return label();
+    DataLabel32 storeValueWithAddressOffsetPatch(const Value &v, Address address) {
+        jsval_layout jv;
+        jv.asBits = JSVAL_BITS(Jsvalify(v));
+
+        move(ImmPtr(reinterpret_cast<void*>(jv.asBits)), Registers::ValueReg);
+        return storePtrWithAddressOffsetPatch(Registers::ValueReg, valueOf(address));
     }
 
     /* Overloaded for store with value remat info. */
-    Label storeValueWithAddressOffsetPatch(const ValueRemat &vr, Address address) {
+    DataLabel32 storeValueWithAddressOffsetPatch(const ValueRemat &vr, Address address) {
         if (vr.isConstant()) {
             return storeValueWithAddressOffsetPatch(vr.value(), address);
         } else if (vr.isTypeKnown()) {
             ImmType type(vr.knownType());
             RegisterID data(vr.dataReg());
             return storeValueWithAddressOffsetPatch(type, data, address);
         } else {
             RegisterID type(vr.typeReg());