Merge backout.
authorDavid Anderson <danderson@mozilla.com>
Tue, 01 Feb 2011 13:48:57 -0800
changeset 62042 a4b132fe80298d2a2312762c8f93784517f5413d
parent 62040 92a6b1ebfb9e56a8cc555ce95b2d9bfdf1103834 (current diff)
parent 62041 884ece11403551ac0c3ceea021d05c34d2cf57a3 (diff)
child 62044 f1afdc854d3fd0ca4bfb82fc4a9093ca4f33fc24
push idunknown
push userunknown
push dateunknown
milestone2.0b11pre
Merge backout.
js/src/methodjit/MethodJIT.cpp
js/src/methodjit/MethodJIT.h
--- a/js/src/methodjit/Compiler.cpp
+++ b/js/src/methodjit/Compiler.cpp
@@ -92,18 +92,17 @@ mjit::Compiler::Compiler(JSContext *cx, 
     fun(fp->isFunctionFrame() && !fp->isEvalFrame()
         ? fp->fun()
         : NULL),
     isConstructing(fp->isConstructing()),
     analysis(NULL), jumpMap(NULL), savedTraps(NULL),
     frame(cx, script, fun, masm),
     branchPatches(CompilerAllocPolicy(cx, *thisFromCtor())),
 #if defined JS_MONOIC
-    getGlobalNames(CompilerAllocPolicy(cx, *thisFromCtor())),
-    setGlobalNames(CompilerAllocPolicy(cx, *thisFromCtor())),
+    mics(CompilerAllocPolicy(cx, *thisFromCtor())),
     callICs(CompilerAllocPolicy(cx, *thisFromCtor())),
     equalityICs(CompilerAllocPolicy(cx, *thisFromCtor())),
     traceICs(CompilerAllocPolicy(cx, *thisFromCtor())),
 #endif
 #if defined JS_POLYIC
     pics(CompilerAllocPolicy(cx, *thisFromCtor())), 
     getElemICs(CompilerAllocPolicy(cx, *thisFromCtor())),
     setElemICs(CompilerAllocPolicy(cx, *thisFromCtor())),
@@ -433,18 +432,17 @@ mjit::Compiler::finishThisUp(JITScript *
         if (opinfo && opinfo->safePoint)
             nNmapLive++;
     }
 
     /* Please keep in sync with JITScript::scriptDataSize! */
     size_t totalBytes = sizeof(JITScript) +
                         sizeof(NativeMapEntry) * nNmapLive +
 #if defined JS_MONOIC
-                        sizeof(ic::GetGlobalNameIC) * getGlobalNames.length() +
-                        sizeof(ic::SetGlobalNameIC) * setGlobalNames.length() +
+                        sizeof(ic::MICInfo) * mics.length() +
                         sizeof(ic::CallICInfo) * callICs.length() +
                         sizeof(ic::EqualityICInfo) * equalityICs.length() +
                         sizeof(ic::TraceICInfo) * traceICs.length() +
 #endif
 #if defined JS_POLYIC
                         sizeof(ic::PICInfo) * pics.length() +
                         sizeof(ic::GetElementIC) * getElemICs.length() +
                         sizeof(ic::SetElementIC) * setElemICs.length() +
@@ -486,72 +484,56 @@ mjit::Compiler::finishThisUp(JITScript *
     JS_ASSERT(ix == nNmapLive);
 
     if (fun) {
         jit->arityCheckEntry = stubCode.locationOf(arityLabel).executableAddress();
         jit->fastEntry = fullCode.locationOf(invokeLabel).executableAddress();
     }
 
 #if defined JS_MONOIC
-    jit->nGetGlobalNames = getGlobalNames.length();
-    if (getGlobalNames.length()) {
-        jit->getGlobalNames = (ic::GetGlobalNameIC *)cursor;
-        cursor += sizeof(ic::GetGlobalNameIC) * getGlobalNames.length();
+    jit->nMICs = mics.length();
+    if (mics.length()) {
+        jit->mics = (ic::MICInfo *)cursor;
+        cursor += sizeof(ic::MICInfo) * mics.length();
     } else {
-        jit->getGlobalNames = NULL;
-    }
-
-    for (size_t i = 0; i < getGlobalNames.length(); i++) {
-        ic::GetGlobalNameIC &to = jit->getGlobalNames[i];
-        GetGlobalNameICInfo &from = getGlobalNames[i];
-        from.copyTo(to, fullCode, stubCode);
-
-        int offset = fullCode.locationOf(from.load) - to.fastPathStart;
-        to.loadStoreOffset = offset;
-        JS_ASSERT(to.loadStoreOffset == offset);
-
-        stubCode.patch(from.addrLabel, &to);
-    }
-
-    jit->nSetGlobalNames = setGlobalNames.length();
-    if (setGlobalNames.length()) {
-        jit->setGlobalNames = (ic::SetGlobalNameIC *)cursor;
-        cursor += sizeof(ic::SetGlobalNameIC) * setGlobalNames.length();
-    } else {
-        jit->setGlobalNames = NULL;
+        jit->mics = NULL;
     }
 
-    for (size_t i = 0; i < setGlobalNames.length(); i++) {
-        ic::SetGlobalNameIC &to = jit->setGlobalNames[i];
-        SetGlobalNameICInfo &from = setGlobalNames[i];
-        from.copyTo(to, fullCode, stubCode);
-        to.slowPathStart = stubCode.locationOf(from.slowPathStart);
-
-        int offset = fullCode.locationOf(from.store).labelAtOffset(0) -
-                     to.fastPathStart;
-        to.loadStoreOffset = offset;
-        JS_ASSERT(to.loadStoreOffset == offset);
-
-        to.extraShapeGuard = 0;
-        to.objConst = from.objConst;
-        to.shapeReg = from.shapeReg;
-        to.objReg = from.objReg;
-        to.vr = from.vr;
-
-        offset = fullCode.locationOf(from.shapeGuardJump) -
-                 to.fastPathStart;
-        to.inlineShapeJump = offset;
-        JS_ASSERT(to.inlineShapeJump == offset);
-
-        offset = fullCode.locationOf(from.fastPathRejoin) -
-                 to.fastPathStart;
-        to.fastRejoinOffset = offset;
-        JS_ASSERT(to.fastRejoinOffset == offset);
-
-        stubCode.patch(from.addrLabel, &to);
+    if (ic::MICInfo *scriptMICs = jit->mics) {
+        for (size_t i = 0; i < mics.length(); i++) {
+            scriptMICs[i].kind = mics[i].kind;
+            scriptMICs[i].fastPathStart = fullCode.locationOf(mics[i].fastPathStart);
+            scriptMICs[i].slowPathStart = stubCode.locationOf(mics[i].slowPathStart);
+            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].usePropertyCache = mics[i].usePropertyCache;
+            scriptMICs[i].extraShapeGuard = 0;
+            scriptMICs[i].objConst = mics[i].objConst;
+            scriptMICs[i].shapeReg = mics[i].shapeReg;
+            scriptMICs[i].objReg = mics[i].objReg;
+            scriptMICs[i].vr = mics[i].vr;
+
+            if (mics[i].kind == ic::MICInfo::SET) {
+                int offset = fullCode.locationOf(mics[i].shapeGuardJump) -
+                             scriptMICs[i].fastPathStart;
+                scriptMICs[i].inlineShapeJump = offset;
+                JS_ASSERT(scriptMICs[i].inlineShapeJump == offset);
+
+                offset = fullCode.locationOf(mics[i].fastPathRejoin) -
+                         scriptMICs[i].fastPathStart;
+                scriptMICs[i].fastRejoinOffset = offset;
+                JS_ASSERT(scriptMICs[i].fastRejoinOffset == offset);
+            }
+
+            stubCode.patch(mics[i].addrLabel, &scriptMICs[i]);
+        }
     }
 
     jit->nCallICs = callICs.length();
     if (callICs.length()) {
         jit->callICs = (ic::CallICInfo *)cursor;
         cursor += sizeof(ic::CallICInfo) * callICs.length();
     } else {
         jit->callICs = NULL;
@@ -2989,19 +2971,19 @@ mjit::Compiler::jsop_length()
     frame.pop();
     frame.pushSynced();
     return true;
 #endif
 }
 
 #ifdef JS_MONOIC
 void
-mjit::Compiler::passMICAddress(GlobalNameICInfo &ic)
+mjit::Compiler::passMICAddress(MICGenInfo &mic)
 {
-    ic.addrLabel = stubcc.masm.moveWithPatch(ImmPtr(NULL), Registers::ArgReg1);
+    mic.addrLabel = stubcc.masm.moveWithPatch(ImmPtr(NULL), Registers::ArgReg1);
 }
 #endif
 
 #if defined JS_POLYIC
 void
 mjit::Compiler::passICAddress(BaseICInfo *ic)
 {
     ic->paramAddr = stubcc.masm.moveWithPatch(ImmPtr(NULL), Registers::ArgReg1);
@@ -4325,69 +4307,68 @@ mjit::Compiler::jsop_getgname(uint32 ind
         return;
     }
 #if defined JS_MONOIC
     jsop_bindgname();
 
     FrameEntry *fe = frame.peek(-1);
     JS_ASSERT(fe->isTypeKnown() && fe->getKnownType() == JSVAL_TYPE_OBJECT);
 
-    GetGlobalNameICInfo ic;
+    MICGenInfo mic(ic::MICInfo::GET);
     RESERVE_IC_SPACE(masm);
     RegisterID objReg;
     Jump shapeGuard;
 
-    ic.usePropertyCache = true;
-
-    ic.fastPathStart = masm.label();
+    mic.fastPathStart = masm.label();
     if (fe->isConstant()) {
         JSObject *obj = &fe->getValue().toObject();
         frame.pop();
         JS_ASSERT(obj->isNative());
 
         objReg = frame.allocReg();
 
         masm.load32FromImm(&obj->objShape, objReg);
         shapeGuard = masm.branch32WithPatch(Assembler::NotEqual, objReg,
-                                            Imm32(int32(JSObjectMap::INVALID_SHAPE)), ic.shape);
+                                            Imm32(int32(JSObjectMap::INVALID_SHAPE)), mic.shape);
         masm.move(ImmPtr(obj), objReg);
     } else {
         objReg = frame.ownRegForData(fe);
         frame.pop();
         RegisterID reg = frame.allocReg();
 
         masm.loadShape(objReg, reg);
         shapeGuard = masm.branch32WithPatch(Assembler::NotEqual, reg,
-                                            Imm32(int32(JSObjectMap::INVALID_SHAPE)), ic.shape);
+                                            Imm32(int32(JSObjectMap::INVALID_SHAPE)), mic.shape);
         frame.freeReg(reg);
     }
-    stubcc.linkExit(shapeGuard, Uses(0));
+    mic.slowPathStart = stubcc.linkExit(shapeGuard, Uses(0));
 
     stubcc.leave();
-    passMICAddress(ic);
-    ic.slowPathCall = OOL_STUBCALL(ic::GetGlobalName);
+    passMICAddress(mic);
+    mic.call = OOL_STUBCALL(ic::GetGlobalName);
 
     /* Garbage value. */
     uint32 slot = 1 << 24;
 
     masm.loadPtr(Address(objReg, offsetof(JSObject, slots)), objReg);
     Address address(objReg, slot);
     
     /* Allocate any register other than objReg. */
     RegisterID treg = frame.allocReg();
     /* After dreg is loaded, it's safe to clobber objReg. */
     RegisterID dreg = objReg;
 
-    ic.load = masm.loadValueWithAddressOffsetPatch(address, treg, dreg);
+    mic.load = masm.loadValueWithAddressOffsetPatch(address, treg, dreg);
 
     frame.pushRegs(treg, dreg);
 
     stubcc.rejoin(Changes(1));
 
-    getGlobalNames.append(ic);
+    mic.fastPathRejoin = masm.label();
+    mics.append(mic);
 
 #else
     jsop_getgname_slow(index);
 #endif
 }
 
 void
 mjit::Compiler::jsop_setgname_slow(JSAtom *atom, bool usePropertyCache)
@@ -4405,79 +4386,79 @@ mjit::Compiler::jsop_setgname_slow(JSAto
 void
 mjit::Compiler::jsop_setgname(JSAtom *atom, bool usePropertyCache)
 {
 #if defined JS_MONOIC
     FrameEntry *objFe = frame.peek(-2);
     FrameEntry *fe = frame.peek(-1);
     JS_ASSERT_IF(objFe->isTypeKnown(), objFe->getKnownType() == JSVAL_TYPE_OBJECT);
 
-    SetGlobalNameICInfo ic;
-
-    frame.pinEntry(fe, ic.vr);
-    Jump shapeGuard;
+    MICGenInfo mic(ic::MICInfo::SET);
+    frame.pinEntry(fe, mic.vr);
 
     RESERVE_IC_SPACE(masm);
-    ic.fastPathStart = masm.label();
+    Jump shapeGuard;
+
+    mic.fastPathStart = masm.label();
     if (objFe->isConstant()) {
         JSObject *obj = &objFe->getValue().toObject();
         JS_ASSERT(obj->isNative());
 
-        ic.objReg = frame.allocReg();
-        ic.shapeReg = ic.objReg;
-        ic.objConst = true;
-
-        masm.load32FromImm(&obj->objShape, ic.shapeReg);
-        shapeGuard = masm.branch32WithPatch(Assembler::NotEqual, ic.shapeReg,
+        mic.objReg = frame.allocReg();
+        mic.shapeReg = mic.objReg;
+        mic.objConst = true;
+
+        masm.load32FromImm(&obj->objShape, mic.shapeReg);
+        shapeGuard = masm.branch32WithPatch(Assembler::NotEqual, mic.shapeReg,
                                             Imm32(int32(JSObjectMap::INVALID_SHAPE)),
-                                            ic.shape);
-        masm.move(ImmPtr(obj), ic.objReg);
+                                            mic.shape);
+        masm.move(ImmPtr(obj), mic.objReg);
     } else {
-        ic.objReg = frame.copyDataIntoReg(objFe);
-        ic.shapeReg = frame.allocReg();
-        ic.objConst = false;
-
-        masm.loadShape(ic.objReg, ic.shapeReg);
-        shapeGuard = masm.branch32WithPatch(Assembler::NotEqual, ic.shapeReg,
+        mic.objReg = frame.copyDataIntoReg(objFe);
+        mic.shapeReg = frame.allocReg();
+        mic.objConst = false;
+
+        masm.loadShape(mic.objReg, mic.shapeReg);
+        shapeGuard = masm.branch32WithPatch(Assembler::NotEqual, mic.shapeReg,
                                             Imm32(int32(JSObjectMap::INVALID_SHAPE)),
-                                            ic.shape);
-        frame.freeReg(ic.shapeReg);
+                                            mic.shape);
+        frame.freeReg(mic.shapeReg);
     }
-    ic.shapeGuardJump = shapeGuard;
-    ic.slowPathStart = stubcc.linkExit(shapeGuard, Uses(2));
+    mic.shapeGuardJump = shapeGuard;
+    mic.slowPathStart = stubcc.linkExit(shapeGuard, Uses(2));
 
     stubcc.leave();
-    passMICAddress(ic);
-    ic.slowPathCall = OOL_STUBCALL(ic::SetGlobalName);
+    passMICAddress(mic);
+    mic.call = OOL_STUBCALL(ic::SetGlobalName);
 
     /* Garbage value. */
     uint32 slot = 1 << 24;
 
-    ic.usePropertyCache = usePropertyCache;
-
-    masm.loadPtr(Address(ic.objReg, offsetof(JSObject, slots)), ic.objReg);
-    Address address(ic.objReg, slot);
-
-    if (ic.vr.isConstant()) {
-        ic.store = masm.storeValueWithAddressOffsetPatch(ic.vr.value(), address);
-    } else if (ic.vr.isTypeKnown()) {
-        ic.store = masm.storeValueWithAddressOffsetPatch(ImmType(ic.vr.knownType()),
-                                                          ic.vr.dataReg(), address);
+    mic.usePropertyCache = usePropertyCache;
+
+    masm.loadPtr(Address(mic.objReg, offsetof(JSObject, slots)), mic.objReg);
+    Address address(mic.objReg, slot);
+
+    if (mic.vr.isConstant()) {
+        mic.store = masm.storeValueWithAddressOffsetPatch(mic.vr.value(), address);
+    } else if (mic.vr.isTypeKnown()) {
+        mic.store = masm.storeValueWithAddressOffsetPatch(ImmType(mic.vr.knownType()),
+                                                          mic.vr.dataReg(), address);
     } else {
-        ic.store = masm.storeValueWithAddressOffsetPatch(ic.vr.typeReg(), ic.vr.dataReg(), address);
+        mic.store = masm.storeValueWithAddressOffsetPatch(mic.vr.typeReg(), mic.vr.dataReg(), address);
     }
 
-    frame.freeReg(ic.objReg);
-    frame.unpinEntry(ic.vr);
+    frame.freeReg(mic.objReg);
+    frame.unpinEntry(mic.vr);
     frame.shimmy(1);
 
     stubcc.rejoin(Changes(1));
 
-    ic.fastPathRejoin = masm.label();
-    setGlobalNames.append(ic);
+    mic.fastPathRejoin = masm.label();
+    mics.append(mic);
 #else
     jsop_setgname_slow(atom, usePropertyCache);
 #endif
 }
 
 void
 mjit::Compiler::jsop_setelem_slow()
 {
--- a/js/src/methodjit/Compiler.h
+++ b/js/src/methodjit/Compiler.h
@@ -62,48 +62,34 @@ class Compiler : public BaseCompiler
           : jump(j), pc(pc)
         { }
 
         Jump jump;
         jsbytecode *pc;
     };
 
 #if defined JS_MONOIC
-    struct GlobalNameICInfo {
+    struct MICGenInfo {
+        MICGenInfo(ic::MICInfo::Kind kind) : kind(kind)
+        { }
         Label fastPathStart;
-        Call slowPathCall;
+        Label slowPathStart;
+        Label fastPathRejoin;
+        Label load;
         DataLabel32 shape;
         DataLabelPtr addrLabel;
-        bool usePropertyCache;
-
-        void copyTo(ic::GlobalNameIC &to, JSC::LinkBuffer &full, JSC::LinkBuffer &stub) {
-            to.fastPathStart = full.locationOf(fastPathStart);
-
-            int offset = full.locationOf(shape) - to.fastPathStart;
-            to.shapeOffset = offset;
-            JS_ASSERT(to.shapeOffset == offset);
-
-            to.slowPathCall = stub.locationOf(slowPathCall);
-            to.usePropertyCache = usePropertyCache;
-        }
-    };
-
-    struct GetGlobalNameICInfo : public GlobalNameICInfo {
-        Label load;
-    };
-
-    struct SetGlobalNameICInfo : public GlobalNameICInfo {
-        Label slowPathStart;
-        Label fastPathRejoin;
         DataLabel32 store;
+        Call call;
+        ic::MICInfo::Kind kind;
         Jump shapeGuardJump;
         ValueRemat vr;
         RegisterID objReg;
         RegisterID shapeReg;
         bool objConst;
+        bool usePropertyCache;
     };
 
     struct EqualityGenInfo {
         DataLabelPtr addrLabel;
         Label stubEntry;
         Call stubCall;
         BoolStub stub;
         MaybeJump jumpToStub;
@@ -336,18 +322,17 @@ class Compiler : public BaseCompiler
     analyze::Script *analysis;
     Label *jumpMap;
     bool *savedTraps;
     jsbytecode *PC;
     Assembler masm;
     FrameState frame;
     js::Vector<BranchPatch, 64, CompilerAllocPolicy> branchPatches;
 #if defined JS_MONOIC
-    js::Vector<GetGlobalNameICInfo, 16, CompilerAllocPolicy> getGlobalNames;
-    js::Vector<SetGlobalNameICInfo, 16, CompilerAllocPolicy> setGlobalNames;
+    js::Vector<MICGenInfo, 64, CompilerAllocPolicy> mics;
     js::Vector<CallGenInfo, 64, CompilerAllocPolicy> callICs;
     js::Vector<EqualityGenInfo, 64, CompilerAllocPolicy> equalityICs;
     js::Vector<TraceGenInfo, 64, CompilerAllocPolicy> traceICs;
 #endif
 #if defined JS_POLYIC
     js::Vector<PICGenInfo, 16, CompilerAllocPolicy> pics;
     js::Vector<GetElementICInfo, 16, CompilerAllocPolicy> getElemICs;
     js::Vector<SetElementICInfo, 16, CompilerAllocPolicy> setElemICs;
@@ -409,17 +394,17 @@ class Compiler : public BaseCompiler
     void iterNext();
     bool iterMore();
     void iterEnd();
     MaybeJump loadDouble(FrameEntry *fe, FPRegisterID fpReg);
 #ifdef JS_POLYIC
     void passICAddress(BaseICInfo *ic);
 #endif
 #ifdef JS_MONOIC
-    void passMICAddress(GlobalNameICInfo &mic);
+    void passMICAddress(MICGenInfo &mic);
 #endif
     bool constructThis();
 
     /* Opcode handlers. */
     bool jumpAndTrace(Jump j, jsbytecode *target, Jump *slow = NULL);
     void jsop_bindname(JSAtom *atom, bool usePropCache);
     void jsop_setglobal(uint32 index);
     void jsop_getglobal(uint32 index);
--- a/js/src/methodjit/MethodJIT.cpp
+++ b/js/src/methodjit/MethodJIT.cpp
@@ -840,18 +840,17 @@ mjit::JITScript::~JITScript()
 
 /* Please keep in sync with Compiler::finishThisUp! */
 size_t
 mjit::JITScript::scriptDataSize()
 {
     return sizeof(JITScript) +
         sizeof(NativeMapEntry) * nNmapPairs +
 #if defined JS_MONOIC
-        sizeof(ic::GetGlobalNameIC) * nGetGlobalNames +
-        sizeof(ic::SetGlobalNameIC) * nSetGlobalNames +
+        sizeof(ic::MICInfo) * nMICs +
         sizeof(ic::CallICInfo) * nCallICs +
         sizeof(ic::EqualityICInfo) * nEqualityICs +
         sizeof(ic::TraceICInfo) * nTraceICs +
 #endif
 #if defined JS_POLYIC
         sizeof(ic::PICInfo) * nPICs +
         sizeof(ic::GetElementIC) * nGetElems +
         sizeof(ic::SetElementIC) * nSetElems +
--- a/js/src/methodjit/MethodJIT.h
+++ b/js/src/methodjit/MethodJIT.h
@@ -241,18 +241,17 @@ class CompilerAllocPolicy : public Conte
 
 namespace ic {
 # if defined JS_POLYIC
     struct PICInfo;
     struct GetElementIC;
     struct SetElementIC;
 # endif
 # if defined JS_MONOIC
-    struct GetGlobalNameIC;
-    struct SetGlobalNameIC;
+    struct MICInfo;
     struct EqualityICInfo;
     struct TraceICInfo;
     struct CallICInfo;
 # endif
 }
 }
 
 typedef void (JS_FASTCALL *VoidStub)(VMFrame &);
@@ -272,18 +271,18 @@ typedef void (JS_FASTCALL *VoidStubAtom)
 typedef JSString * (JS_FASTCALL *JSStrStub)(VMFrame &);
 typedef JSString * (JS_FASTCALL *JSStrStubUInt32)(VMFrame &, uint32);
 typedef void (JS_FASTCALL *VoidStubJSObj)(VMFrame &, JSObject *);
 typedef void (JS_FASTCALL *VoidStubPC)(VMFrame &, jsbytecode *);
 typedef JSBool (JS_FASTCALL *BoolStubUInt32)(VMFrame &f, uint32);
 #ifdef JS_MONOIC
 typedef void (JS_FASTCALL *VoidStubCallIC)(VMFrame &, js::mjit::ic::CallICInfo *);
 typedef void * (JS_FASTCALL *VoidPtrStubCallIC)(VMFrame &, js::mjit::ic::CallICInfo *);
-typedef void (JS_FASTCALL *VoidStubGetGlobal)(VMFrame &, js::mjit::ic::GetGlobalNameIC *);
-typedef void (JS_FASTCALL *VoidStubSetGlobal)(VMFrame &, js::mjit::ic::SetGlobalNameIC *);
+typedef void (JS_FASTCALL *VoidStubMIC)(VMFrame &, js::mjit::ic::MICInfo *);
+typedef void * (JS_FASTCALL *VoidPtrStubMIC)(VMFrame &, js::mjit::ic::MICInfo *);
 typedef JSBool (JS_FASTCALL *BoolStubEqualityIC)(VMFrame &, js::mjit::ic::EqualityICInfo *);
 typedef void * (JS_FASTCALL *VoidPtrStubTraceIC)(VMFrame &, js::mjit::ic::TraceICInfo *);
 #endif
 #ifdef JS_POLYIC
 typedef void (JS_FASTCALL *VoidStubPIC)(VMFrame &, js::mjit::ic::PICInfo *);
 typedef void (JS_FASTCALL *VoidStubGetElemIC)(VMFrame &, js::mjit::ic::GetElementIC *);
 typedef void (JS_FASTCALL *VoidStubSetElemIC)(VMFrame &f, js::mjit::ic::SetElementIC *);
 #endif
@@ -307,39 +306,37 @@ struct JITScript {
 
     void            *invokeEntry;       /* invoke address */
     void            *fastEntry;         /* cached entry, fastest */
     void            *arityCheckEntry;   /* arity check address */
 
     /* To minimize the size of this struct on 64-bit, put uint32s after all pointers. */
     js::mjit::CallSite *callSites;
 #ifdef JS_MONOIC
-    ic::GetGlobalNameIC *getGlobalNames;
-    ic::SetGlobalNameIC *setGlobalNames;
-    ic::CallICInfo      *callICs;
-    ic::EqualityICInfo  *equalityICs;
-    ic::TraceICInfo     *traceICs;
+    ic::MICInfo     *mics;      /* MICs in this script. */
+    ic::CallICInfo  *callICs;   /* CallICs in this script. */
+    ic::EqualityICInfo *equalityICs;
+    ic::TraceICInfo *traceICs;
 #endif
 #ifdef JS_POLYIC
-    ic::PICInfo         *pics;
-    ic::GetElementIC    *getElems;
-    ic::SetElementIC    *setElems;
+    ic::PICInfo     *pics;      /* PICs in this script */
+    ic::GetElementIC *getElems;
+    ic::SetElementIC *setElems;
 #endif
 
     uint32          nCallSites:31;
     bool            singleStepMode:1;   /* compiled in "single step mode" */
 #ifdef JS_MONOIC
-    uint32          nGetGlobalNames;
-    uint32          nSetGlobalNames;
-    uint32          nCallICs;
+    uint32          nMICs;      /* number of MonoICs */
+    uint32          nCallICs;   /* number of call ICs */
     uint32          nEqualityICs;
     uint32          nTraceICs;
 #endif
 #ifdef JS_POLYIC
-    uint32          nPICs;
+    uint32          nPICs;      /* number of PolyICs */
     uint32          nGetElems;
     uint32          nSetElems;
 #endif
 
 #ifdef JS_MONOIC
     // Additional ExecutablePools that IC stubs were generated into.
     typedef Vector<JSC::ExecutablePool *, 0, SystemAllocPolicy> ExecPoolVector;
     ExecPoolVector execPools;
--- a/js/src/methodjit/MonoIC.cpp
+++ b/js/src/methodjit/MonoIC.cpp
@@ -68,108 +68,109 @@ typedef JSC::MacroAssembler::Imm32 Imm32
 typedef JSC::MacroAssembler::ImmPtr ImmPtr;
 typedef JSC::MacroAssembler::Call Call;
 typedef JSC::MacroAssembler::Label Label;
 typedef JSC::MacroAssembler::DataLabel32 DataLabel32;
 
 #if defined JS_MONOIC
 
 static void
-PatchGetFallback(VMFrame &f, ic::GetGlobalNameIC *ic)
+PatchGetFallback(VMFrame &f, ic::MICInfo *ic)
 {
     Repatcher repatch(f.jit());
     JSC::FunctionPtr fptr(JS_FUNC_TO_DATA_PTR(void *, stubs::GetGlobalName));
-    repatch.relink(ic->slowPathCall, fptr);
+    repatch.relink(ic->stubCall, fptr);
 }
 
 void JS_FASTCALL
-ic::GetGlobalName(VMFrame &f, ic::GetGlobalNameIC *ic)
+ic::GetGlobalName(VMFrame &f, ic::MICInfo *ic)
 {
     JSObject *obj = f.fp()->scopeChain().getGlobal();
     JSAtom *atom = f.fp()->script()->getAtom(GET_INDEX(f.regs.pc));
     jsid id = ATOM_TO_JSID(atom);
 
+    JS_ASSERT(ic->kind == ic::MICInfo::GET);
+
     const Shape *shape = obj->nativeLookup(id);
     if (!shape ||
         !shape->hasDefaultGetterOrIsMethod() ||
         !shape->hasSlot())
     {
         if (shape)
             PatchGetFallback(f, ic);
         stubs::GetGlobalName(f);
         return;
     }
     uint32 slot = shape->slot;
 
     /* Patch shape guard. */
     Repatcher repatcher(f.jit());
-    repatcher.repatch(ic->fastPathStart.dataLabel32AtOffset(ic->shapeOffset), obj->shape());
+    repatcher.repatch(ic->shape, obj->shape());
 
     /* Patch loads. */
-    JSC::CodeLocationLabel label = ic->fastPathStart.labelAtOffset(ic->loadStoreOffset);
-    repatcher.patchAddressOffsetForValueLoad(label, slot * sizeof(Value));
+    repatcher.patchAddressOffsetForValueLoad(ic->load, slot * sizeof(Value));
 
     /* Do load anyway... this time. */
     stubs::GetGlobalName(f);
 }
 
 template <JSBool strict>
 static void JS_FASTCALL
-DisabledSetGlobal(VMFrame &f, ic::SetGlobalNameIC *ic)
+DisabledSetGlobal(VMFrame &f, ic::MICInfo *ic)
 {
     JSScript *script = f.fp()->script();
     JSAtom *atom = script->getAtom(GET_INDEX(f.regs.pc));
     stubs::SetGlobalName<strict>(f, atom);
 }
 
-template void JS_FASTCALL DisabledSetGlobal<true>(VMFrame &f, ic::SetGlobalNameIC *ic);
-template void JS_FASTCALL DisabledSetGlobal<false>(VMFrame &f, ic::SetGlobalNameIC *ic);
+template void JS_FASTCALL DisabledSetGlobal<true>(VMFrame &f, ic::MICInfo *ic);
+template void JS_FASTCALL DisabledSetGlobal<false>(VMFrame &f, ic::MICInfo *ic);
 
 template <JSBool strict>
 static void JS_FASTCALL
-DisabledSetGlobalNoCache(VMFrame &f, ic::SetGlobalNameIC *ic)
+DisabledSetGlobalNoCache(VMFrame &f, ic::MICInfo *ic)
 {
     JSScript *script = f.fp()->script();
     JSAtom *atom = script->getAtom(GET_INDEX(f.regs.pc));
     stubs::SetGlobalNameNoCache<strict>(f, atom);
 }
 
-template void JS_FASTCALL DisabledSetGlobalNoCache<true>(VMFrame &f, ic::SetGlobalNameIC *ic);
-template void JS_FASTCALL DisabledSetGlobalNoCache<false>(VMFrame &f, ic::SetGlobalNameIC *ic);
+template void JS_FASTCALL DisabledSetGlobalNoCache<true>(VMFrame &f, ic::MICInfo *ic);
+template void JS_FASTCALL DisabledSetGlobalNoCache<false>(VMFrame &f, ic::MICInfo *ic);
 
 static void
-PatchSetFallback(VMFrame &f, ic::SetGlobalNameIC *ic)
+PatchSetFallback(VMFrame &f, ic::MICInfo *ic)
 {
     JSScript *script = f.fp()->script();
 
     Repatcher repatch(f.jit());
-    VoidStubSetGlobal stub = ic->usePropertyCache
-                             ? STRICT_VARIANT(DisabledSetGlobal)
-                             : STRICT_VARIANT(DisabledSetGlobalNoCache);
+    VoidStubMIC stub = ic->usePropertyCache
+                       ? STRICT_VARIANT(DisabledSetGlobal)
+                       : STRICT_VARIANT(DisabledSetGlobalNoCache);
     JSC::FunctionPtr fptr(JS_FUNC_TO_DATA_PTR(void *, stub));
-    repatch.relink(ic->slowPathCall, fptr);
+    repatch.relink(ic->stubCall, fptr);
 }
 
 static LookupStatus
-UpdateSetGlobalNameStub(VMFrame &f, ic::SetGlobalNameIC *ic, JSObject *obj, const Shape *shape)
+UpdateSetGlobalNameStub(VMFrame &f, ic::MICInfo *ic, JSObject *obj, const Shape *shape)
 {
     Repatcher repatcher(ic->extraStub);
 
     JSC::CodeLocationLabel label(JSC::MacroAssemblerCodePtr(ic->extraStub.start()));
     repatcher.repatch(label.dataLabel32AtOffset(ic->extraShapeGuard), obj->shape());
 
     label = label.labelAtOffset(ic->extraStoreOffset);
     repatcher.patchAddressOffsetForValueStore(label, shape->slot * sizeof(Value),
                                               ic->vr.isTypeKnown());
 
     return Lookup_Cacheable;
 }
 
 static LookupStatus
-AttachSetGlobalNameStub(VMFrame &f, ic::SetGlobalNameIC *ic, JSObject *obj, const Shape *shape)
+AttachSetGlobalNameStub(VMFrame &f, ic::MICInfo *ic, JSObject *obj, const Shape *shape)
 {
     Assembler masm;
 
     Label start = masm.label();
 
     DataLabel32 shapeLabel;
     Jump guard = masm.branch32WithPatch(Assembler::NotEqual, ic->shapeReg, Imm32(obj->shape()),
                                         shapeLabel);
@@ -241,17 +242,17 @@ AttachSetGlobalNameStub(VMFrame &f, ic::
     offset = linker.locationOf(store) - linker.locationOf(start);
     ic->extraStoreOffset = offset;
     JS_ASSERT(ic->extraStoreOffset == offset);
 
     return Lookup_Cacheable;
 }
 
 static LookupStatus
-UpdateSetGlobalName(VMFrame &f, ic::SetGlobalNameIC *ic, JSObject *obj, const Shape *shape)
+UpdateGlobalName(VMFrame &f, ic::MICInfo *ic, JSObject *obj, const Shape *shape)
 {
     /* Give globals a chance to appear. */
     if (!shape)
         return Lookup_Uncacheable;
 
     if (shape->isMethod() ||
         !shape->hasDefaultSetter() ||
         !shape->writable() ||
@@ -284,34 +285,32 @@ UpdateSetGlobalName(VMFrame &f, ic::SetG
         if (ic->extraShapeGuard)
             return UpdateSetGlobalNameStub(f, ic, obj, shape);
 
         return AttachSetGlobalNameStub(f, ic, obj, shape);
     }
 
     /* Object is not branded, so we can use the inline path. */
     Repatcher repatcher(f.jit());
-    repatcher.repatch(ic->fastPathStart.dataLabel32AtOffset(ic->shapeOffset), obj->shape());
-
-    JSC::CodeLocationLabel label = ic->fastPathStart.labelAtOffset(ic->loadStoreOffset);
-    repatcher.patchAddressOffsetForValueStore(label, shape->slot * sizeof(Value),
+    repatcher.repatch(ic->shape, obj->shape());
+    repatcher.patchAddressOffsetForValueStore(ic->load, shape->slot * sizeof(Value),
                                               ic->vr.isTypeKnown());
 
     return Lookup_Cacheable;
 }
 
 void JS_FASTCALL
-ic::SetGlobalName(VMFrame &f, ic::SetGlobalNameIC *ic)
+ic::SetGlobalName(VMFrame &f, ic::MICInfo *ic)
 {
     JSObject *obj = f.fp()->scopeChain().getGlobal();
     JSScript *script = f.fp()->script();
     JSAtom *atom = script->getAtom(GET_INDEX(f.regs.pc));
     const Shape *shape = obj->nativeLookup(ATOM_TO_JSID(atom));
 
-    LookupStatus status = UpdateSetGlobalName(f, ic, obj, shape);
+    LookupStatus status = UpdateGlobalName(f, ic, obj, shape);
     if (status == Lookup_Error)
         THROW();
 
     if (ic->usePropertyCache)
         STRICT_VARIANT(stubs::SetGlobalName)(f, atom);
     else
         STRICT_VARIANT(stubs::SetGlobalNameNoCache)(f, atom);
 }
@@ -1154,31 +1153,40 @@ ic::SplatApplyArgs(VMFrame &f)
 
     f.u.call.dynamicArgc = n;
     return true;
 }
 
 void
 JITScript::purgeMICs()
 {
-    if (!nGetGlobalNames || !nSetGlobalNames)
+    if (!nMICs)
         return;
 
     Repatcher repatch(this);
 
-    for (uint32 i = 0; i < nGetGlobalNames; i++) {
-        ic::GetGlobalNameIC &ic = getGlobalNames[i];
-        JSC::CodeLocationDataLabel32 label = ic.fastPathStart.dataLabel32AtOffset(ic.shapeOffset);
-        repatch.repatch(label, int(JSObjectMap::INVALID_SHAPE));
-    }
+    for (uint32 i = 0; i < nMICs; i++) {
+        ic::MICInfo &mic = mics[i];
+        switch (mic.kind) {
+          case ic::MICInfo::SET:
+          case ic::MICInfo::GET:
+          {
+            /* Patch shape guard. */
+            repatch.repatch(mic.shape, int(JSObjectMap::INVALID_SHAPE));
 
-    for (uint32 i = 0; i < nSetGlobalNames; i++) {
-        ic::SetGlobalNameIC &ic = setGlobalNames[i];
-        JSC::CodeLocationDataLabel32 label = ic.fastPathStart.dataLabel32AtOffset(ic.shapeOffset);
-        repatch.repatch(label, int(JSObjectMap::INVALID_SHAPE));
+            /* 
+             * If the stub call was patched, leave it alone -- it probably will
+             * just be invalidated again.
+             */
+            break;
+          }
+          default:
+            JS_NOT_REACHED("Unknown MIC type during purge");
+            break;
+        }
     }
 }
 
 void
 ic::PurgeMICs(JSContext *cx, JSScript *script)
 {
     /* MICs are purged during GC to handle changing shapes. */
     JS_ASSERT(cx->runtime->gcRegenShapes);
@@ -1268,20 +1276,21 @@ JITScript::sweepCallICs(JSContext *cx, b
             JSC::FunctionPtr fptr(JS_FUNC_TO_DATA_PTR(void *, ic::Equality));
             repatcher.relink(ic.stubCall, fptr);
             repatcher.relink(ic.jumpToStub, ic.stubEntry);
 
             ic.generated = false;
             released++;
         }
 
-        for (uint32 i = 0; i < nSetGlobalNames; i++) {
-            ic::SetGlobalNameIC &ic = setGlobalNames[i];
+        for (uint32 i = 0; i < nMICs; i ++) {
+            ic::MICInfo &ic = mics[i];
             if (!ic.extraShapeGuard)
                 continue;
+            JS_ASSERT(ic.kind == ic::MICInfo::SET);
             repatcher.relink(ic.fastPathStart.jumpAtOffset(ic.inlineShapeJump), ic.slowPathStart);
             ic.extraShapeGuard = 0;
             released++;
         }
 
         JS_ASSERT(released == execPools.length());
         for (uint32 i = 0; i < released; i++)
             execPools[i]->release();
--- a/js/src/methodjit/MonoIC.h
+++ b/js/src/methodjit/MonoIC.h
@@ -86,54 +86,53 @@ class FrameSize
 
     uint32 getArgc(VMFrame &f) const {
         return isStatic() ? staticArgc() : f.u.call.dynamicArgc;
     }
 };
 
 namespace ic {
 
-struct GlobalNameIC
-{
+struct MICInfo {
+    enum Kind
+#ifdef _MSC_VER
+    : uint8_t
+#endif
+    {
+        GET,
+        SET
+    };
+
     typedef JSC::MacroAssembler::RegisterID RegisterID;
 
-    JSC::CodeLocationLabel  fastPathStart;
-    JSC::CodeLocationCall   slowPathCall;
+    JSC::CodeLocationLabel fastPathStart;
+    JSC::CodeLocationLabel slowPathStart;
 
     /*
      * - 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.
      */
-    int32 loadStoreOffset   : 15;
-    int32 shapeOffset       : 15;
-    bool usePropertyCache   : 1;
-};
-
-struct GetGlobalNameIC : public GlobalNameIC
-{
-};
-
-struct SetGlobalNameIC : public GlobalNameIC
-{
-    JSC::CodeLocationLabel  slowPathStart;
-
-    /* Dynamically generted stub for method-write checks. */
-    JSC::JITCode            extraStub;
+    JSC::CodeLocationLabel load;
+    JSC::CodeLocationDataLabel32 shape;
+    JSC::CodeLocationCall stubCall;
 
     /* SET only, if we had to generate an out-of-line path. */
+    Kind kind : 2;
+    bool usePropertyCache : 1;
     int inlineShapeJump : 10;   /* Offset into inline path for shape jump. */
     int extraShapeGuard : 6;    /* Offset into stub for shape guard. */
     bool objConst : 1;          /* True if the object is constant. */
     RegisterID objReg   : 5;    /* Register for object, if objConst is false. */
     RegisterID shapeReg : 5;    /* Register for shape; volatile. */
+    JSC::JITCode extraStub;     /* Out-of-line generated stub. */
 
     int fastRejoinOffset : 16;  /* Offset from fastPathStart to rejoin. */
     int extraStoreOffset : 16;  /* Offset into store code. */
 
     /* SET only. */
     ValueRemat vr;              /* RHS value. */
 };
 
@@ -155,18 +154,18 @@ struct TraceICInfo {
     uint32 loopCounterStart;
 
     bool initialized : 1;
     bool hasSlowTraceHint : 1;
 };
 
 static const uint16 BAD_TRACEIC_INDEX = (uint16)0xffff;
 
-void JS_FASTCALL GetGlobalName(VMFrame &f, ic::GetGlobalNameIC *ic);
-void JS_FASTCALL SetGlobalName(VMFrame &f, ic::SetGlobalNameIC *ic);
+void JS_FASTCALL GetGlobalName(VMFrame &f, ic::MICInfo *ic);
+void JS_FASTCALL SetGlobalName(VMFrame &f, ic::MICInfo *ic);
 
 struct EqualityICInfo {
     typedef JSC::MacroAssembler::RegisterID RegisterID;
 
     JSC::CodeLocationLabel stubEntry;
     JSC::CodeLocationCall stubCall;
     BoolStub stub;
     JSC::CodeLocationLabel target;