Bug 588021: Cross-platform PIC labels. (r=dmandelin, u=cdleary,dvander,jbramley)
authorChris Leary <cdleary@mozilla.com>
Thu, 13 Jan 2011 22:39:11 -0800
changeset 60590 61d976205e2b96a2b05237f77187ca5a79ad1979
parent 60589 87d45053e28f5b385937805039e291fea7059c4b
child 60591 4989cff3af0c18b5298d53a30509a15d8d344c71
push idunknown
push userunknown
push dateunknown
reviewersdmandelin
bugs588021
milestone2.0b10pre
Bug 588021: Cross-platform PIC labels. (r=dmandelin, u=cdleary,dvander,jbramley)
js/src/methodjit/Compiler.cpp
js/src/methodjit/Compiler.h
js/src/methodjit/ICLabels.h
js/src/methodjit/PolyIC.cpp
js/src/methodjit/PolyIC.h
--- a/js/src/methodjit/Compiler.cpp
+++ b/js/src/methodjit/Compiler.cpp
@@ -738,20 +738,16 @@ mjit::Compiler::finishThisUp(JITScript *
 
             scriptPICs[i].shapeGuard = masm.distanceOf(pics[i].shapeGuard) -
                                          masm.distanceOf(pics[i].fastPathStart);
             JS_ASSERT(scriptPICs[i].shapeGuard == masm.distanceOf(pics[i].shapeGuard) -
                                          masm.distanceOf(pics[i].fastPathStart));
             scriptPICs[i].shapeRegHasBaseShape = true;
             scriptPICs[i].pc = pics[i].pc;
 
-# if defined JS_CPU_X64
-            memcpy(&scriptPICs[i].labels, &pics[i].labels, sizeof(PICLabels));
-# endif
-
             if (pics[i].kind == ic::PICInfo::SET ||
                 pics[i].kind == ic::PICInfo::SETMETHOD) {
                 scriptPICs[i].u.vr = pics[i].vr;
             } else if (pics[i].kind != ic::PICInfo::NAME) {
                 if (pics[i].hasTypeCheck) {
                     int32 distance = stubcc.masm.distanceOf(pics[i].typeCheck) -
                                      stubcc.masm.distanceOf(pics[i].slowPathStart);
                     JS_ASSERT(distance <= 0);
@@ -3046,59 +3042,52 @@ mjit::Compiler::jsop_getprop(JSAtom *ato
 
     pic.slowPathStart = stubcc.linkExit(j, Uses(1));
 
     stubcc.leave();
     passICAddress(&pic);
     pic.slowPathCall = OOL_STUBCALL(ic::GetProp);
 
     /* Load dslots. */
-#if defined JS_NUNBOX32
-    DBGLABEL(dbgDslotsLoad);
-#elif defined JS_PUNBOX64
     Label dslotsLoadLabel = masm.label();
-#endif
     masm.loadPtr(Address(objReg, offsetof(JSObject, slots)), objReg);
 
     /* Copy the slot value to the expression stack. */
     Address slot(objReg, 1 << 24);
     frame.pop();
 
 #if defined JS_NUNBOX32
     masm.loadTypeTag(slot, shapeReg);
-    DBGLABEL(dbgTypeLoad);
+    Label typeLoad = masm.label();
 
     masm.loadPayload(slot, objReg);
-    DBGLABEL(dbgDataLoad);
+    Label dataLoad = masm.label();
 #elif defined JS_PUNBOX64
     Label inlineValueLoadLabel =
         masm.loadValueAsComponents(slot, shapeReg, objReg);
 #endif
     pic.fastPathRejoin = masm.label();
 
-    /* Assert correctness of hardcoded offsets. */
     RETURN_IF_OOM(false);
+
+    GetPropLabels &labels = pic.getPropLabels();
+    labels.setDslotsLoadOffset(masm.differenceBetween(pic.fastPathRejoin, dslotsLoadLabel));
+    labels.setInlineShapeOffset(masm.differenceBetween(pic.shapeGuard, inlineShapeLabel));
+
 #if defined JS_NUNBOX32
-    JS_ASSERT(masm.differenceBetween(pic.fastPathRejoin, dbgDslotsLoad) == GETPROP_DSLOTS_LOAD);
-    JS_ASSERT(masm.differenceBetween(pic.fastPathRejoin, dbgTypeLoad) == GETPROP_TYPE_LOAD);
-    JS_ASSERT(masm.differenceBetween(pic.fastPathRejoin, dbgDataLoad) == GETPROP_DATA_LOAD);
-    JS_ASSERT(masm.differenceBetween(pic.shapeGuard, inlineShapeLabel) == GETPROP_INLINE_SHAPE_OFFSET);
+    labels.setTypeLoad(masm.differenceBetween(pic.fastPathRejoin, typeLoad));
+    labels.setDataLoad(masm.differenceBetween(pic.fastPathRejoin, dataLoad));
+
     JS_ASSERT(masm.differenceBetween(pic.shapeGuard, dbgInlineShapeJump) == GETPROP_INLINE_SHAPE_JUMP);
 #elif defined JS_PUNBOX64
-    pic.labels.getprop.dslotsLoadOffset = masm.differenceBetween(pic.fastPathRejoin, dslotsLoadLabel);
-    JS_ASSERT(pic.labels.getprop.dslotsLoadOffset == masm.differenceBetween(pic.fastPathRejoin, dslotsLoadLabel));
-
-    pic.labels.getprop.inlineShapeOffset = masm.differenceBetween(pic.shapeGuard, inlineShapeLabel);
-    JS_ASSERT(pic.labels.getprop.inlineShapeOffset == masm.differenceBetween(pic.shapeGuard, inlineShapeLabel));
-
-    pic.labels.getprop.inlineValueOffset = masm.differenceBetween(pic.fastPathRejoin, inlineValueLoadLabel);
-    JS_ASSERT(pic.labels.getprop.inlineValueOffset == masm.differenceBetween(pic.fastPathRejoin, inlineValueLoadLabel));
+    labels.setValueLoad(masm.differenceBetween(pic.fastPathRejoin, inlineValueLoadLabel));
 
     JS_ASSERT(masm.differenceBetween(inlineShapeLabel, dbgInlineShapeJump) == GETPROP_INLINE_SHAPE_JUMP);
 #endif
+
     /* GETPROP_INLINE_TYPE_GUARD's validity is asserted above. */
 
     pic.objReg = objReg;
     frame.pushRegs(shapeReg, objReg);
 
     stubcc.rejoin(Changes(1));
 
     pics.append(pic);
@@ -3175,56 +3164,48 @@ mjit::Compiler::jsop_callprop_generic(JS
     pic.slowPathCall = OOL_STUBCALL(ic::CallProp);
 
     /* Adjust the frame. None of this will generate code. */
     frame.pop();
     frame.pushRegs(shapeReg, objReg);
     frame.pushSynced();
 
     /* Load dslots. */
-#if defined JS_NUNBOX32
-    DBGLABEL(dbgDslotsLoad);
-#elif defined JS_PUNBOX64
     Label dslotsLoadLabel = masm.label();
-#endif
     masm.loadPtr(Address(objReg, offsetof(JSObject, slots)), objReg);
 
     /* Copy the slot value to the expression stack. */
     Address slot(objReg, 1 << 24);
 
 #if defined JS_NUNBOX32
     masm.loadTypeTag(slot, shapeReg);
-    DBGLABEL(dbgTypeLoad);
+    Label typeLoad = masm.label();
 
     masm.loadPayload(slot, objReg);
-    DBGLABEL(dbgDataLoad);
+    Label dataLoad = masm.label();
 #elif defined JS_PUNBOX64
     Label inlineValueLoadLabel =
         masm.loadValueAsComponents(slot, shapeReg, objReg);
 #endif
     pic.fastPathRejoin = masm.label();
 
     /* Assert correctness of hardcoded offsets. */
     RETURN_IF_OOM(false);
     JS_ASSERT(masm.differenceBetween(pic.fastPathStart, dbgInlineTypeGuard) == GETPROP_INLINE_TYPE_GUARD);
+
+    GetPropLabels &labels = pic.getPropLabels();
+    labels.setDslotsLoadOffset(masm.differenceBetween(pic.fastPathRejoin, dslotsLoadLabel));
+    labels.setInlineShapeOffset(masm.differenceBetween(pic.shapeGuard, inlineShapeLabel));
 #if defined JS_NUNBOX32
-    JS_ASSERT(masm.differenceBetween(pic.fastPathRejoin, dbgDslotsLoad) == GETPROP_DSLOTS_LOAD);
-    JS_ASSERT(masm.differenceBetween(pic.fastPathRejoin, dbgTypeLoad) == GETPROP_TYPE_LOAD);
-    JS_ASSERT(masm.differenceBetween(pic.fastPathRejoin, dbgDataLoad) == GETPROP_DATA_LOAD);
-    JS_ASSERT(masm.differenceBetween(pic.shapeGuard, inlineShapeLabel) == GETPROP_INLINE_SHAPE_OFFSET);
+    labels.setTypeLoad(masm.differenceBetween(pic.fastPathRejoin, typeLoad));
+    labels.setDataLoad(masm.differenceBetween(pic.fastPathRejoin, dataLoad));
+
     JS_ASSERT(masm.differenceBetween(pic.shapeGuard, dbgInlineShapeJump) == GETPROP_INLINE_SHAPE_JUMP);
 #elif defined JS_PUNBOX64
-    pic.labels.getprop.dslotsLoadOffset = masm.differenceBetween(pic.fastPathRejoin, dslotsLoadLabel);
-    JS_ASSERT(pic.labels.getprop.dslotsLoadOffset == masm.differenceBetween(pic.fastPathRejoin, dslotsLoadLabel));
-
-    pic.labels.getprop.inlineShapeOffset = masm.differenceBetween(pic.shapeGuard, inlineShapeLabel);
-    JS_ASSERT(pic.labels.getprop.inlineShapeOffset == masm.differenceBetween(pic.shapeGuard, inlineShapeLabel));
-
-    pic.labels.getprop.inlineValueOffset = masm.differenceBetween(pic.fastPathRejoin, inlineValueLoadLabel);
-    JS_ASSERT(pic.labels.getprop.inlineValueOffset == masm.differenceBetween(pic.fastPathRejoin, inlineValueLoadLabel));
+    labels.setValueLoad(masm.differenceBetween(pic.fastPathRejoin, inlineValueLoadLabel));
 
     JS_ASSERT(masm.differenceBetween(inlineShapeLabel, dbgInlineShapeJump) == GETPROP_INLINE_SHAPE_JUMP);
 #endif
 
     stubcc.rejoin(Changes(2));
     pics.append(pic);
 
     return true;
@@ -3322,32 +3303,28 @@ mjit::Compiler::jsop_callprop_obj(JSAtom
 
     pic.slowPathStart = stubcc.linkExit(j, Uses(1));
 
     stubcc.leave();
     passICAddress(&pic);
     pic.slowPathCall = OOL_STUBCALL(ic::CallProp);
 
     /* Load dslots. */
-#if defined JS_NUNBOX32
-    DBGLABEL(dbgDslotsLoad);
-#elif defined JS_PUNBOX64
     Label dslotsLoadLabel = masm.label();
-#endif
     masm.loadPtr(Address(objReg, offsetof(JSObject, slots)), objReg);
 
     /* Copy the slot value to the expression stack. */
     Address slot(objReg, 1 << 24);
 
 #if defined JS_NUNBOX32
     masm.loadTypeTag(slot, shapeReg);
-    DBGLABEL(dbgTypeLoad);
+    Label dbgTypeLoad = masm.label();
 
     masm.loadPayload(slot, objReg);
-    DBGLABEL(dbgDataLoad);
+    Label dbgDataLoad = masm.label();
 #elif defined JS_PUNBOX64
     Label inlineValueLoadLabel =
         masm.loadValueAsComponents(slot, shapeReg, objReg);
 #endif
 
     pic.fastPathRejoin = masm.label();
     pic.objReg = objReg;
 
@@ -3364,31 +3341,27 @@ mjit::Compiler::jsop_callprop_obj(JSAtom
     frame.pushRegs(shapeReg, objReg);
     frame.shift(-2);
 
     /* 
      * Assert correctness of hardcoded offsets.
      * No type guard: type is asserted.
      */
     RETURN_IF_OOM(false);
+
+    GetPropLabels &labels = pic.getPropLabels();
+    labels.setDslotsLoadOffset(masm.differenceBetween(pic.fastPathRejoin, dslotsLoadLabel));
+    labels.setInlineShapeOffset(masm.differenceBetween(pic.shapeGuard, inlineShapeLabel));
 #if defined JS_NUNBOX32
-    JS_ASSERT(masm.differenceBetween(pic.fastPathRejoin, dbgDslotsLoad) == GETPROP_DSLOTS_LOAD);
-    JS_ASSERT(masm.differenceBetween(pic.fastPathRejoin, dbgTypeLoad) == GETPROP_TYPE_LOAD);
-    JS_ASSERT(masm.differenceBetween(pic.fastPathRejoin, dbgDataLoad) == GETPROP_DATA_LOAD);
-    JS_ASSERT(masm.differenceBetween(pic.shapeGuard, inlineShapeLabel) == GETPROP_INLINE_SHAPE_OFFSET);
+    labels.setTypeLoad(masm.differenceBetween(pic.fastPathRejoin, dbgTypeLoad));
+    labels.setDataLoad(masm.differenceBetween(pic.fastPathRejoin, dbgDataLoad));
+
     JS_ASSERT(masm.differenceBetween(pic.shapeGuard, dbgInlineShapeJump) == GETPROP_INLINE_SHAPE_JUMP);
 #elif defined JS_PUNBOX64
-    pic.labels.getprop.dslotsLoadOffset = masm.differenceBetween(pic.fastPathRejoin, dslotsLoadLabel);
-    JS_ASSERT(pic.labels.getprop.dslotsLoadOffset == masm.differenceBetween(pic.fastPathRejoin, dslotsLoadLabel));
-
-    pic.labels.getprop.inlineShapeOffset = masm.differenceBetween(pic.shapeGuard, inlineShapeLabel);
-    JS_ASSERT(pic.labels.getprop.inlineShapeOffset == masm.differenceBetween(pic.shapeGuard, inlineShapeLabel));
-
-    pic.labels.getprop.inlineValueOffset = masm.differenceBetween(pic.fastPathRejoin, inlineValueLoadLabel);
-    JS_ASSERT(pic.labels.getprop.inlineValueOffset == masm.differenceBetween(pic.fastPathRejoin, inlineValueLoadLabel));
+    labels.setValueLoad(masm.differenceBetween(pic.fastPathRejoin, inlineValueLoadLabel));
 
     JS_ASSERT(masm.differenceBetween(inlineShapeLabel, dbgInlineShapeJump) == GETPROP_INLINE_SHAPE_JUMP);
 #endif
 
     stubcc.rejoin(Changes(2));
     pics.append(pic);
 
     return true;
@@ -3516,23 +3489,24 @@ mjit::Compiler::jsop_setprop(JSAtom *ato
     /* Finish slow path. */
     {
         if (pic.hasTypeCheck)
             typeCheck.linkTo(stubcc.masm.label(), &stubcc.masm);
         stubcc.rejoin(Changes(1));
     }
 
     RETURN_IF_OOM(false);
+
+    SetPropLabels &labels = pic.setPropLabels();
+    labels.setInlineShapeOffset(masm.differenceBetween(pic.shapeGuard, inlineShapeOffsetLabel));
 #if defined JS_PUNBOX64
-    pic.labels.setprop.dslotsLoadOffset = masm.differenceBetween(pic.fastPathRejoin, dslotsLoadLabel);
-    pic.labels.setprop.inlineShapeOffset = masm.differenceBetween(pic.shapeGuard, inlineShapeOffsetLabel);
+    labels.setDslotsLoadOffset(masm.differenceBetween(pic.fastPathRejoin, dslotsLoadLabel));
     JS_ASSERT(masm.differenceBetween(inlineShapeOffsetLabel, dbgInlineShapeJump) == SETPROP_INLINE_SHAPE_JUMP);
     JS_ASSERT(masm.differenceBetween(pic.fastPathRejoin, dbgAfterValueStore) == SETPROP_INLINE_STORE_VALUE);
 #elif defined JS_NUNBOX32
-    JS_ASSERT(masm.differenceBetween(pic.shapeGuard, inlineShapeOffsetLabel) == SETPROP_INLINE_SHAPE_OFFSET);
     JS_ASSERT(masm.differenceBetween(pic.shapeGuard, dbgInlineShapeJump) == SETPROP_INLINE_SHAPE_JUMP);
     if (vr.isConstant()) {
         /* Constants are offset inside the opcode by 4. */
         JS_ASSERT(masm.differenceBetween(pic.fastPathRejoin, dbgInlineStoreType)-4 == SETPROP_INLINE_STORE_CONST_TYPE);
         JS_ASSERT(masm.differenceBetween(pic.fastPathRejoin, dbgAfterValueStore)-4 == SETPROP_INLINE_STORE_CONST_DATA);
         JS_ASSERT(masm.differenceBetween(pic.fastPathRejoin, dbgDslots) == SETPROP_DSLOTS_BEFORE_CONSTANT);
     } else if (vr.isTypeKnown()) {
         JS_ASSERT(masm.differenceBetween(pic.fastPathRejoin, dbgInlineStoreType)-4 == SETPROP_INLINE_STORE_KTYPE_TYPE);
@@ -3644,39 +3618,35 @@ mjit::Compiler::jsop_bindname(JSAtom *at
     pic.fastPathStart = masm.label();
 
     Address parent(pic.objReg, offsetof(JSObject, parent));
     masm.loadPtr(Address(JSFrameReg, JSStackFrame::offsetOfScopeChain()), pic.objReg);
 
     pic.shapeGuard = masm.label();
 #if defined JS_NUNBOX32
     Jump j = masm.branchPtr(Assembler::NotEqual, masm.payloadOf(parent), ImmPtr(0));
-    DBGLABEL(inlineJumpOffset);
+    Label inlineJumpOffset = masm.label();
 #elif defined JS_PUNBOX64
     masm.loadPayload(parent, Registers::ValueReg);
     Jump j = masm.branchPtr(Assembler::NotEqual, Registers::ValueReg, ImmPtr(0));
     Label inlineJumpOffset = masm.label();
 #endif
     {
         pic.slowPathStart = stubcc.linkExit(j, Uses(0));
         stubcc.leave();
         passICAddress(&pic);
         pic.slowPathCall = OOL_STUBCALL(ic::BindName);
     }
 
     pic.fastPathRejoin = masm.label();
     frame.pushTypedPayload(JSVAL_TYPE_OBJECT, pic.objReg);
     frame.freeReg(pic.shapeReg);
 
-#if defined JS_NUNBOX32
-    JS_ASSERT(masm.differenceBetween(pic.shapeGuard, inlineJumpOffset) == BINDNAME_INLINE_JUMP_OFFSET);
-#elif defined JS_PUNBOX64
-    pic.labels.bindname.inlineJumpOffset = masm.differenceBetween(pic.shapeGuard, inlineJumpOffset);
-    JS_ASSERT(pic.labels.bindname.inlineJumpOffset == masm.differenceBetween(pic.shapeGuard, inlineJumpOffset));
-#endif
+    BindNameLabels &labels = pic.bindNameLabels();
+    labels.setInlineJumpOffset(masm.differenceBetween(pic.shapeGuard, inlineJumpOffset));
 
     stubcc.rejoin(Changes(1));
 
     pics.append(pic);
 }
 
 #else /* JS_POLYIC */
 
--- a/js/src/methodjit/Compiler.h
+++ b/js/src/methodjit/Compiler.h
@@ -216,32 +216,70 @@ class Compiler : public BaseCompiler
         RegisterID idReg;
         RegisterID typeReg;
         bool usePropCache;
         Label shapeGuard;
         jsbytecode *pc;
         JSAtom *atom;
         bool hasTypeCheck;
         ValueRemat vr;
-# if defined JS_CPU_X64
-        ic::PICLabels labels;
-# endif
+#ifdef JS_HAS_IC_LABELS
+        union {
+            ic::GetPropLabels getPropLabels_;
+            ic::SetPropLabels setPropLabels_;
+            ic::BindNameLabels bindNameLabels_;
+        };
 
-        void copySimpleMembersTo(ic::PICInfo &ic) const {
+        ic::GetPropLabels &getPropLabels() {
+            JS_ASSERT(kind == ic::PICInfo::GET || kind == ic::PICInfo::CALL);
+            return getPropLabels_;
+        }
+        ic::SetPropLabels &setPropLabels() {
+            JS_ASSERT(kind == ic::PICInfo::SET || kind == ic::PICInfo::SETMETHOD);
+            return setPropLabels_;
+        }
+        ic::BindNameLabels &bindNameLabels() {
+            JS_ASSERT(kind == ic::PICInfo::BIND);
+            return bindNameLabels_;
+        }
+#else
+        ic::GetPropLabels &getPropLabels() {
+            JS_ASSERT(kind == ic::PICInfo::GET || kind == ic::PICInfo::CALL);
+            return ic::PICInfo::getPropLabels_;
+        }
+        ic::SetPropLabels &setPropLabels() {
+            JS_ASSERT(kind == ic::PICInfo::SET || kind == ic::PICInfo::SETMETHOD);
+            return ic::PICInfo::setPropLabels_;
+        }
+        ic::BindNameLabels &bindNameLabels() {
+            JS_ASSERT(kind == ic::PICInfo::BIND);
+            return ic::PICInfo::bindNameLabels_;
+        }
+#endif
+
+        void copySimpleMembersTo(ic::PICInfo &ic) {
             ic.kind = kind;
             ic.shapeReg = shapeReg;
             ic.objReg = objReg;
             ic.atom = atom;
             ic.usePropCache = usePropCache;
             if (ic.isSet()) {
                 ic.u.vr = vr;
             } else if (ic.isGet()) {
                 ic.u.get.typeReg = typeReg;
                 ic.u.get.hasTypeCheck = hasTypeCheck;
             }
+#ifdef JS_HAS_IC_LABELS
+            if (ic.isGet())
+                ic.setLabels(getPropLabels());
+            else if (ic.isSet())
+                ic.setLabels(setPropLabels());
+            else if (ic.kind == ic::PICInfo::BIND)
+                ic.setLabels(bindNameLabels());
+#endif
         }
 
     };
 
     struct Defs {
         Defs(uint32 ndefs)
           : ndefs(ndefs)
         { }
new file mode 100644
--- /dev/null
+++ b/js/src/methodjit/ICLabels.h
@@ -0,0 +1,249 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=4 sw=4 et tw=99:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla SpiderMonkey JavaScript 1.9 code, released
+ * May 28, 2008.
+ *
+ * The Initial Developer of the Original Code is
+ *   Brendan Eich <brendan@mozilla.org>
+ *
+ * Contributor(s):
+ *   David Mandelin <dmandelin@mozilla.com>
+ *   David Anderson <danderson@mozilla.com>
+ *   Chris Leary <cdleary@mozilla.com>
+ *   Jacob Bramley <Jacob.Bramely@arm.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * 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 ***** */
+
+#if !defined jsjaeger_ic_labels_h__ && defined JS_METHODJIT
+#define jsjaeger_ic_labels_h__
+
+#include "jscntxt.h"
+#include "jstl.h"
+#include "jsvector.h"
+#include "assembler/assembler/MacroAssembler.h"
+#include "assembler/assembler/CodeLocation.h"
+#include "methodjit/MethodJIT.h"
+#include "BaseAssembler.h"
+#include "RematInfo.h"
+#include "BaseCompiler.h"
+
+class ICOffsetInitializer {
+  public:
+    ICOffsetInitializer();
+};
+
+namespace js {
+namespace mjit {
+namespace ic {
+
+#if defined JS_CPU_X64 || defined JS_CPU_ARM
+/*
+ * On x64 and ARM, we create offsets dynamically instead of using hardcoded
+ * offsets into the instruction stream. This is done on x64 because of
+ * variable-width instruction encoding when using the extended register set and
+ * it is done on ARM for expediency of implementation.
+ */
+# define JS_HAS_IC_LABELS
+#endif
+
+/* GetPropCompiler */
+struct GetPropLabels {
+    friend class ::ICOffsetInitializer;
+
+    void setDslotsLoadOffset(int offset) {
+#ifdef JS_HAS_IC_LABELS
+        dslotsLoadOffset = offset;
+#endif
+        JS_ASSERT(offset == dslotsLoadOffset);
+    }
+
+    void setInlineShapeOffset(int offset) {
+#ifdef JS_HAS_IC_LABELS
+        inlineShapeOffset = offset;
+#endif
+        JS_ASSERT(offset == inlineShapeOffset);
+    }
+    
+    void setStubShapeJump(int offset) {
+#ifdef JS_HAS_IC_LABELS
+        stubShapeJump = offset;
+#endif
+        JS_ASSERT(offset == stubShapeJump);
+    }
+
+#ifdef JS_NUNBOX32
+    void setTypeLoad(int offset) {
+# ifdef JS_HAS_IC_LABELS
+        inlineTypeLoad = offset;
+# endif
+        JS_ASSERT(offset == inlineTypeLoad);
+    }
+    void setDataLoad(int offset) {
+# ifdef JS_HAS_IC_LABELS
+        inlineDataLoad = offset;
+# endif
+        JS_ASSERT(offset == inlineDataLoad);
+    }
+    JSC::CodeLocationDataLabel32 getTypeLoad(JSC::CodeLocationLabel start) {
+        return start.dataLabel32AtOffset(inlineTypeLoad);
+    }
+    JSC::CodeLocationDataLabel32 getDataLoad(JSC::CodeLocationLabel start) {
+        return start.dataLabel32AtOffset(inlineDataLoad);
+    }
+#elif JS_PUNBOX64
+    void setValueLoad(int offset) {
+# ifdef JS_HAS_IC_LABELS
+        inlineValueLoad = offset;
+# endif
+        JS_ASSERT(offset == inlineValueLoad);
+    }
+    JSC::CodeLocationDataLabel32 getValueLoad(JSC::CodeLocationLabel start) {
+        return start.dataLabel32AtOffset(inlineValueLoad);
+    }
+#endif
+
+    int getInlineShapeOffset() {
+        return inlineShapeOffset;
+    }
+    int getDslotsLoadOffset() {
+        return dslotsLoadOffset;
+    }
+    int getStubShapeJump() {
+        return stubShapeJump;
+    }
+
+  private:
+    /* Offset from storeBack to beginning of 'mov dslots, addr' */
+    int32 dslotsLoadOffset : 8;
+
+    /* Offset from shapeGuard to end of shape comparison. */
+    int32 inlineShapeOffset : 8;
+
+    /* Offset from storeBack to end of value load. */
+#ifdef JS_NUNBOX32
+    int32 inlineTypeLoad    : 8;
+    int32 inlineDataLoad    : 8;
+#elif JS_PUNBOX64
+    int32 inlineValueLoad   : 8;
+#endif
+
+    /* 
+     * Offset from lastStubStart to end of shape jump.
+     * TODO: We can redefine the location of lastStubStart to be
+     * after the jump -- at which point this is always 0.
+     */
+    int32 stubShapeJump : 8;
+};
+
+/* SetPropCompiler */
+struct SetPropLabels {
+    friend class ::ICOffsetInitializer;
+
+#ifdef JS_PUNBOX64
+    void setDslotsLoadOffset(int offset) {
+# ifdef JS_HAS_IC_LABELS
+        dslotsLoadOffset = offset;
+# endif
+        JS_ASSERT(offset == dslotsLoadOffset);
+    }
+#endif
+
+    int getDslotsLoadOffset() {
+#ifdef JS_PUNBOX64
+        return dslotsLoadOffset;
+#else
+        JS_NOT_REACHED("this is inlined");
+        return 0;
+#endif
+    }
+
+    void setInlineShapeOffset(int offset) {
+#ifdef JS_HAS_IC_LABELS
+        inlineShapeOffset = offset;
+#endif
+        JS_ASSERT(offset == inlineShapeOffset);
+    }
+
+    void setStubShapeJump(int offset) {
+#ifdef JS_HAS_IC_LABELS
+        stubShapeJump = offset;
+#endif
+        JS_ASSERT(offset == stubShapeJump);
+    }
+
+    int getInlineShapeOffset() {
+        return inlineShapeOffset;
+    }
+    int getStubShapeJump() {
+        return stubShapeJump;
+    }
+
+  private:
+#ifdef JS_PUNBOX64
+    /* Offset from storeBack to beginning of 'mov dslots, addr' */
+    int32 dslotsLoadOffset : 8;
+#endif
+
+    /* Offset from shapeGuard to end of shape comparison. */
+    int32 inlineShapeOffset : 8;
+
+    /* 
+     * Offset from lastStubStart to end of shape jump.
+     * TODO: We can redefine the location of lastStubStart to be
+     * after the jump -- at which point this is always 0.
+     */
+    int32 stubShapeJump : 8;
+};
+
+/* BindNameCompiler */
+struct BindNameLabels {
+    friend class ::ICOffsetInitializer;
+
+    void setInlineJumpOffset(int offset) {
+#ifdef JS_HAS_IC_LABELS
+        inlineJumpOffset = offset;
+#endif
+        JS_ASSERT(offset == inlineJumpOffset);
+    }
+
+    int getInlineJumpOffset() {
+        return inlineJumpOffset;
+    }
+
+  private:
+    /* Offset from shapeGuard to end of shape jump. */
+    int32 inlineJumpOffset : 8;
+};
+
+} /* namespace ic */
+} /* namespace mjit */
+} /* namespace js */
+
+#endif /* jsjaeger_ic_labels_h__ */
+
--- a/js/src/methodjit/PolyIC.cpp
+++ b/js/src/methodjit/PolyIC.cpp
@@ -63,16 +63,49 @@ using namespace js::mjit::ic;
 typedef JSC::FunctionPtr FunctionPtr;
 typedef JSC::MacroAssembler::RegisterID RegisterID;
 typedef JSC::MacroAssembler::Jump Jump;
 typedef JSC::MacroAssembler::Imm32 Imm32;
 
 /* Rough over-estimate of how much memory we need to unprotect. */
 static const uint32 INLINE_PATH_LENGTH = 64;
 
+/* Static initializer to prime platforms that use constant offsets for ICs. */
+#ifndef JS_HAS_IC_LABELS
+ICOffsetInitializer::ICOffsetInitializer()
+{
+    {
+        GetPropLabels &labels = PICInfo::getPropLabels_;
+#if defined JS_CPU_X86
+        labels.dslotsLoadOffset = -15;
+        labels.inlineShapeOffset = 6;
+        labels.inlineTypeLoad = -6;
+        labels.inlineDataLoad = 0;
+        labels.stubShapeJump = 12;
+#endif
+    }
+    {
+        SetPropLabels &labels = PICInfo::setPropLabels_;
+        labels.inlineShapeOffset = 6;
+        labels.stubShapeJump = 12;
+    }
+    {
+        BindNameLabels &labels = PICInfo::bindNameLabels_;
+#if defined JS_CPU_X86
+        labels.inlineJumpOffset = 10;
+#endif
+    }
+}
+
+ICOffsetInitializer s_ICOffsetInitializer;
+GetPropLabels PICInfo::getPropLabels_;
+SetPropLabels PICInfo::setPropLabels_;
+BindNameLabels PICInfo::bindNameLabels_;
+#endif
+
 // Helper class to simplify LinkBuffer usage in PIC stub generators.
 // This guarantees correct OOM and refcount handling for buffers while they
 // are instantiated and rooted.
 class PICLinker : public LinkerHelper
 {
     ic::BasePolyIC &ic;
 
   public:
@@ -149,17 +182,17 @@ class SetPropCompiler : public PICStubCo
     static int32 dslotsLoadOffset(ic::PICInfo &pic) {
 #if defined JS_NUNBOX32
         if (pic.u.vr.isConstant())
             return SETPROP_DSLOTS_BEFORE_CONSTANT;
         if (pic.u.vr.isTypeKnown())
             return SETPROP_DSLOTS_BEFORE_KTYPE;
         return SETPROP_DSLOTS_BEFORE_DYNAMIC;
 #elif defined JS_PUNBOX64
-        return pic.labels.setprop.dslotsLoadOffset;
+        return pic.setPropLabels().getDslotsLoadOffset();
 #endif
     }
 
 #if defined JS_NUNBOX32
     inline int32 inlineTypeOffset() {
         if (pic.u.vr.isConstant())
             return SETPROP_INLINE_STORE_CONST_TYPE;
         if (pic.u.vr.isTypeKnown())
@@ -174,21 +207,17 @@ class SetPropCompiler : public PICStubCo
             return SETPROP_INLINE_STORE_CONST_DATA;
         if (pic.u.vr.isTypeKnown())
             return SETPROP_INLINE_STORE_KTYPE_DATA;
         return SETPROP_INLINE_STORE_DYN_DATA;
     }
 #endif
 
     static int32 inlineShapeOffset(ic::PICInfo &pic) {
-#if defined JS_NUNBOX32
-        return SETPROP_INLINE_SHAPE_OFFSET;
-#elif defined JS_PUNBOX64
-        return pic.labels.setprop.inlineShapeOffset;
-#endif
+        return pic.setPropLabels().getInlineShapeOffset();
     }
 
     static int32 inlineShapeJump(ic::PICInfo &pic) {
 #if defined JS_NUNBOX32
         return SETPROP_INLINE_SHAPE_JUMP;
 #elif defined JS_PUNBOX64
         return inlineShapeOffset(pic) + SETPROP_INLINE_SHAPE_JUMP;
 #endif
@@ -274,21 +303,17 @@ class SetPropCompiler : public PICStubCo
         Repatcher repatcher(pic.lastCodeBlock(f.jit()));
         CodeLocationLabel label = pic.lastPathStart();
 
         // Patch either the inline fast path or a generated stub. The stub
         // omits the prefix of the inline fast path that loads the shape, so
         // the offsets are different.
         int shapeGuardJumpOffset;
         if (pic.stubsGenerated)
-#if defined JS_NUNBOX32
-            shapeGuardJumpOffset = SETPROP_STUB_SHAPE_JUMP;
-#elif defined JS_PUNBOX64
-            shapeGuardJumpOffset = pic.labels.setprop.stubShapeJump;
-#endif
+            shapeGuardJumpOffset = pic.setPropLabels().getStubShapeJump();
         else
             shapeGuardJumpOffset = pic.shapeGuard + inlineShapeJump();
         repatcher.relink(label.jumpAtOffset(shapeGuardJumpOffset), cs);
         if (lastStubSecondShapeGuard)
             repatcher.relink(label.jumpAtOffset(lastStubSecondShapeGuard), cs);
     }
 
     LookupStatus generateStub(uint32 initialShape, const Shape *shape, bool adding, bool inlineSlot)
@@ -304,22 +329,17 @@ class SetPropCompiler : public PICStubCo
             masm.loadShape(pic.objReg, pic.shapeReg);
             pic.shapeRegHasBaseShape = true;
         }
 
         Label start = masm.label();
         Jump shapeGuard = masm.branch32_force32(Assembler::NotEqual, pic.shapeReg,
                                                 Imm32(initialShape));
 
-#if defined JS_NUNBOX32
-        DBGLABEL(dbgStubShapeJump);
-        JS_ASSERT(masm.differenceBetween(start, dbgStubShapeJump) == SETPROP_STUB_SHAPE_JUMP);
-#elif defined JS_PUNBOX64
         Label stubShapeJumpLabel = masm.label();
-#endif
 
         JS_ASSERT_IF(!shape->hasDefaultSetter(), obj->getClass() == &js_CallClass);
 
         MaybeJump skipOver;
 
         if (adding) {
             JS_ASSERT(shape->hasSlot());
             pic.shapeRegHasBaseShape = false;
@@ -484,20 +504,17 @@ class SetPropCompiler : public PICStubCo
         // This function can patch either the inline fast path for a generated
         // stub. The stub omits the prefix of the inline fast path that loads
         // the shape, so the offsets are different.
         patchPreviousToHere(cs);
 
         pic.stubsGenerated++;
         pic.updateLastPath(buffer, start);
 
-#if defined JS_PUNBOX64
-        pic.labels.setprop.stubShapeJump = masm.differenceBetween(start, stubShapeJumpLabel);
-        JS_ASSERT(pic.labels.setprop.stubShapeJump == masm.differenceBetween(start, stubShapeJumpLabel));
-#endif
+        pic.setPropLabels().setStubShapeJump(masm.differenceBetween(start, stubShapeJumpLabel));
 
         if (pic.stubsGenerated == MAX_PIC_STUBS)
             disable("max stubs reached");
 
         return Lookup_Cacheable;
     }
 
     LookupStatus update()
@@ -740,21 +757,17 @@ struct GetPropertyHelper {
 
 class GetPropCompiler : public PICStubCompiler
 {
     JSObject    *obj;
     JSAtom      *atom;
     int         lastStubSecondShapeGuard;
 
     static int32 inlineShapeOffset(ic::PICInfo &pic) {
-#if defined JS_NUNBOX32
-        return GETPROP_INLINE_SHAPE_OFFSET;
-#elif defined JS_PUNBOX64
-        return pic.labels.getprop.inlineShapeOffset;
-#endif
+        return pic.getPropLabels().getInlineShapeOffset();
     }
 
     inline int32 inlineShapeOffset() {
         return inlineShapeOffset(pic);
     }
 
     static int32 inlineShapeJump(ic::PICInfo &pic) {
 #if defined JS_NUNBOX32
@@ -764,21 +777,17 @@ class GetPropCompiler : public PICStubCo
 #endif
     }
 
     inline int32 inlineShapeJump() {
         return inlineShapeJump(pic);
     }
 
     static int32 dslotsLoad(ic::PICInfo &pic) {
-#if defined JS_NUNBOX32
-        return GETPROP_DSLOTS_LOAD;
-#elif defined JS_PUNBOX64
-        return pic.labels.getprop.dslotsLoadOffset;
-#endif
+        return pic.getPropLabels().getDslotsLoadOffset();
     }
 
     inline int32 dslotsLoad() {
         return dslotsLoad(pic);
     }
 
   public:
     GetPropCompiler(VMFrame &f, JSScript *script, JSObject *obj, ic::PICInfo &pic, JSAtom *atom,
@@ -1074,62 +1083,63 @@ class GetPropCompiler : public PICStubCo
             JS_ASSERT(diff != 0);
             offset  = (int32(shape->slot) * sizeof(Value)) + diff;
         } else {
             offset = shape->slot * sizeof(Value);
         }
 
         uint32 shapeOffs = pic.shapeGuard + inlineShapeOffset();
         repatcher.repatch(pic.fastPathStart.dataLabel32AtOffset(shapeOffs), obj->shape());
+        GetPropLabels &labels = pic.getPropLabels();
 #if defined JS_NUNBOX32
-        repatcher.repatch(pic.fastPathRejoin.dataLabel32AtOffset(GETPROP_TYPE_LOAD), offset + 4);
-        repatcher.repatch(pic.fastPathRejoin.dataLabel32AtOffset(GETPROP_DATA_LOAD), offset);
+        repatcher.repatch(labels.getTypeLoad(pic.fastPathRejoin), offset + 4);
+        repatcher.repatch(labels.getDataLoad(pic.fastPathRejoin), offset);
 #elif defined JS_PUNBOX64
-        repatcher.repatch(pic.fastPathRejoin.dataLabel32AtOffset(pic.labels.getprop.inlineValueOffset), offset);
+        repatcher.repatch(labels.getValueLoad(pic.fastPathRejoin), offset);
 #endif
 
         pic.inlinePathPatched = true;
 
         return Lookup_Cacheable;
     }
 
     LookupStatus generateStub(JSObject *holder, const Shape *shape)
     {
         Vector<Jump, 8> shapeMismatches(cx);
 
         Assembler masm;
 
         Label start;
         Jump shapeGuard;
         Jump argsLenGuard;
+
+        bool setStubShapeOffset = true;
         if (obj->isDenseArray()) {
             start = masm.label();
             shapeGuard = masm.testObjClass(Assembler::NotEqual, pic.objReg, obj->getClass());
 
             /* 
              * No need to assert validity of GETPROP_STUB_SHAPE_JUMP in this case:
              * the IC is disabled after a dense array hit, so no patching can occur.
              */
+#ifndef JS_HAS_IC_LABELS
+            setStubShapeOffset = false;
+#endif
         } else {
             if (pic.shapeNeedsRemat()) {
                 masm.loadShape(pic.objReg, pic.shapeReg);
                 pic.shapeRegHasBaseShape = true;
             }
 
             start = masm.label();
             shapeGuard = masm.branch32_force32(Assembler::NotEqual, pic.shapeReg,
                                                Imm32(obj->shape()));
-#if defined JS_NUNBOX32
-            JS_ASSERT(masm.differenceBetween(start, shapeGuard) == GETPROP_STUB_SHAPE_JUMP);
-#endif
         }
 
-#if defined JS_PUNBOX64
         Label stubShapeJumpLabel = masm.label();
-#endif
 
         if (!shapeMismatches.append(shapeGuard))
             return error();
 
         RegisterID holderReg = pic.objReg;
         if (obj != holder) {
             // Bake in the holder identity. Careful not to clobber |objReg|, since we can't remat it.
             holderReg = pic.shapeReg;
@@ -1168,20 +1178,18 @@ class GetPropCompiler : public PICStubCo
         CodeLocationLabel cs = buffer.finalize();
         JaegerSpew(JSpew_PICs, "generated %s stub at %p\n", type, cs.executableAddress());
 
         patchPreviousToHere(cs);
 
         pic.stubsGenerated++;
         pic.updateLastPath(buffer, start);
 
-#if defined JS_PUNBOX64
-        pic.labels.getprop.stubShapeJump = masm.differenceBetween(start, stubShapeJumpLabel);
-        JS_ASSERT(pic.labels.getprop.stubShapeJump == masm.differenceBetween(start, stubShapeJumpLabel));
-#endif
+        if (setStubShapeOffset)
+            pic.getPropLabels().setStubShapeJump(masm.differenceBetween(start, stubShapeJumpLabel));
 
         if (pic.stubsGenerated == MAX_PIC_STUBS)
             disable("max stubs reached");
         if (obj->isDenseArray())
             disable("dense array");
 
         return Lookup_Cacheable;
     }
@@ -1191,21 +1199,17 @@ class GetPropCompiler : public PICStubCo
         Repatcher repatcher(pic.lastCodeBlock(f.jit()));
         CodeLocationLabel label = pic.lastPathStart();
 
         // Patch either the inline fast path or a generated stub. The stub
         // omits the prefix of the inline fast path that loads the shape, so
         // the offsets are different.
         int shapeGuardJumpOffset;
         if (pic.stubsGenerated)
-#if defined JS_NUNBOX32
-            shapeGuardJumpOffset = GETPROP_STUB_SHAPE_JUMP;
-#elif defined JS_PUNBOX64
-            shapeGuardJumpOffset = pic.labels.getprop.stubShapeJump;
-#endif
+            shapeGuardJumpOffset = pic.getPropLabels().getStubShapeJump();
         else
             shapeGuardJumpOffset = pic.shapeGuard + inlineShapeJump();
         repatcher.relink(label.jumpAtOffset(shapeGuardJumpOffset), cs);
         if (lastStubSecondShapeGuard)
             repatcher.relink(label.jumpAtOffset(lastStubSecondShapeGuard), cs);
     }
 
     LookupStatus update()
@@ -1541,21 +1545,17 @@ class ScopeNameCompiler : public PICStub
 };
 
 class BindNameCompiler : public PICStubCompiler
 {
     JSObject *scopeChain;
     JSAtom *atom;
 
     static int32 inlineJumpOffset(ic::PICInfo &pic) {
-#if defined JS_NUNBOX32
-        return BINDNAME_INLINE_JUMP_OFFSET;
-#elif defined JS_PUNBOX64
-        return pic.labels.bindname.inlineJumpOffset;
-#endif
+        return pic.bindNameLabels().getInlineJumpOffset();
     }
 
     inline int32 inlineJumpOffset() {
         return inlineJumpOffset(pic);
     }
 
   public:
     BindNameCompiler(VMFrame &f, JSScript *script, JSObject *scopeChain, ic::PICInfo &pic,
--- a/js/src/methodjit/PolyIC.h
+++ b/js/src/methodjit/PolyIC.h
@@ -44,138 +44,69 @@
 #include "jstl.h"
 #include "jsvector.h"
 #include "assembler/assembler/MacroAssembler.h"
 #include "assembler/assembler/CodeLocation.h"
 #include "methodjit/MethodJIT.h"
 #include "BaseAssembler.h"
 #include "RematInfo.h"
 #include "BaseCompiler.h"
+#include "methodjit/ICLabels.h"
 #include "assembler/moco/MocoStubs.h"
 
 namespace js {
 namespace mjit {
 namespace ic {
 
 /* Maximum number of stubs for a given callsite. */
 static const uint32 MAX_PIC_STUBS = 16;
 static const uint32 MAX_GETELEM_IC_STUBS = 17;
 
 /* SetPropCompiler */
 #if defined JS_CPU_X86
-static const int32 SETPROP_INLINE_SHAPE_OFFSET     =   6; //asserted
 static const int32 SETPROP_INLINE_SHAPE_JUMP       =  12; //asserted
 static const int32 SETPROP_DSLOTS_BEFORE_CONSTANT  = -23; //asserted
 static const int32 SETPROP_DSLOTS_BEFORE_KTYPE     = -19; //asserted
 static const int32 SETPROP_DSLOTS_BEFORE_DYNAMIC   = -15; //asserted
 static const int32 SETPROP_INLINE_STORE_DYN_TYPE   =  -6; //asserted
 static const int32 SETPROP_INLINE_STORE_DYN_DATA   =   0; //asserted
 static const int32 SETPROP_INLINE_STORE_KTYPE_TYPE = -10; //asserted
 static const int32 SETPROP_INLINE_STORE_KTYPE_DATA =   0; //asserted
 static const int32 SETPROP_INLINE_STORE_CONST_TYPE = -14; //asserted
 static const int32 SETPROP_INLINE_STORE_CONST_DATA =  -4; //asserted
-static const int32 SETPROP_STUB_SHAPE_JUMP         =  12; //asserted
 #elif defined JS_CPU_X64
 static const int32 SETPROP_INLINE_STORE_VALUE      =   0; //asserted
 static const int32 SETPROP_INLINE_SHAPE_JUMP       =   6; //asserted
 #endif
 
 /* GetPropCompiler */
 #if defined JS_CPU_X86
-static const int32 GETPROP_DSLOTS_LOAD         = -15; //asserted
-static const int32 GETPROP_TYPE_LOAD           =  -6; //asserted
-static const int32 GETPROP_DATA_LOAD           =   0; //asserted
 static const int32 GETPROP_INLINE_TYPE_GUARD   =  12; //asserted
-static const int32 GETPROP_INLINE_SHAPE_OFFSET =   6; //asserted
 static const int32 GETPROP_INLINE_SHAPE_JUMP   =  12; //asserted
-static const int32 GETPROP_STUB_SHAPE_JUMP     =  12; //asserted
 #elif defined JS_CPU_X64
 static const int32 GETPROP_INLINE_TYPE_GUARD   =  19; //asserted
 static const int32 GETPROP_INLINE_SHAPE_JUMP   =   6; //asserted
 #endif
 
-/* GetElemCompiler */
-#if defined JS_CPU_X86
-static const int32 GETELEM_DSLOTS_LOAD         = -15; //asserted
-static const int32 GETELEM_TYPE_LOAD           =  -6; //asserted
-static const int32 GETELEM_DATA_LOAD           =   0; //asserted
-static const int32 GETELEM_INLINE_SHAPE_OFFSET =   6; //asserted
-static const int32 GETELEM_INLINE_SHAPE_JUMP   =  12; //asserted
-static const int32 GETELEM_INLINE_ATOM_OFFSET  =  18; //asserted
-static const int32 GETELEM_INLINE_ATOM_JUMP    =  24; //asserted
-static const int32 GETELEM_STUB_ATOM_JUMP      =  12; //asserted
-static const int32 GETELEM_STUB_SHAPE_JUMP     =  24; //asserted
-#elif defined JS_CPU_X64
-static const int32 GETELEM_INLINE_SHAPE_JUMP   =   6; //asserted
-static const int32 GETELEM_INLINE_ATOM_JUMP    =   9; //asserted
-static const int32 GETELEM_STUB_ATOM_JUMP      =  19; //asserted (probably differs)
-#endif
-
 /* ScopeNameCompiler */
 #if defined JS_CPU_X86
 static const int32 SCOPENAME_JUMP_OFFSET = 5; //asserted
 #elif defined JS_CPU_X64
 static const int32 SCOPENAME_JUMP_OFFSET = 5; //asserted
 #endif
 
 /* BindNameCompiler */
 #if defined JS_CPU_X86
-static const int32 BINDNAME_INLINE_JUMP_OFFSET = 10; //asserted
 static const int32 BINDNAME_STUB_JUMP_OFFSET   =  5; //asserted
 #elif defined JS_CPU_X64
 static const int32 BINDNAME_STUB_JUMP_OFFSET   =  5; //asserted
 #endif
 
 void PurgePICs(JSContext *cx);
 
-/*
- * x86_64 bytecode differs in length based on the involved registers.
- * Since constants won't work, we need an array of labels.
- */
-#if defined JS_CPU_X64
-union PICLabels {
-    /* SetPropCompiler */
-    struct {
-        /* Offset from storeBack to beginning of 'mov dslots, addr' */
-        int32 dslotsLoadOffset : 8;
-
-        /* Offset from shapeGuard to end of shape comparison. */
-        int32 inlineShapeOffset : 8;
-
-        /* Offset from lastStubStart to end of shape jump. */
-        // TODO: We can redefine the location of lastStubStart to be
-        // after the jump -- at which point this is always 0.
-        int32 stubShapeJump : 8;
-    } setprop;
-
-    /* GetPropCompiler */
-    struct {
-        /* Offset from storeBack to beginning of 'mov dslots, addr' */
-        int32 dslotsLoadOffset : 8;
-
-        /* Offset from shapeGuard to end of shape comparison. */
-        int32 inlineShapeOffset : 8;
-    
-        /* Offset from storeBack to end of value load. */
-        int32 inlineValueOffset : 8;
-
-        /* Offset from lastStubStart to end of shape jump. */
-        // TODO: We can redefine the location of lastStubStart to be
-        // after the jump -- at which point this is always 0.
-        int32 stubShapeJump : 8;
-    } getprop;
-
-    /* BindNameCompiler */
-    struct {
-        /* Offset from shapeGuard to end of shape jump. */
-        int32 inlineJumpOffset : 8;
-    } bindname;
-};
-#endif
-
 enum LookupStatus {
     Lookup_Error = 0,
     Lookup_Uncacheable,
     Lookup_Cacheable
 };
 
 struct BaseIC : public MacroAssemblerTypedefs {
     BaseIC() { }
@@ -566,21 +497,53 @@ struct PICInfo : public BasePolyIC {
     inline bool shapeNeedsRemat() {
         return !shapeRegHasBaseShape;
     }
     inline bool isFastCall() {
         JS_ASSERT(kind == CALL);
         return !hasTypeCheck();
     }
 
-#if defined JS_CPU_X64
-    // Required labels for platform-specific patching.
-    PICLabels labels;
+#if !defined JS_HAS_IC_LABELS
+    static GetPropLabels getPropLabels_;
+    static SetPropLabels setPropLabels_;
+    static BindNameLabels bindNameLabels_;
+#else
+    union {
+        GetPropLabels getPropLabels_;
+        SetPropLabels setPropLabels_;
+        BindNameLabels bindNameLabels_;
+    };
+    void setLabels(const ic::GetPropLabels &labels) {
+        JS_ASSERT(isGet());
+        getPropLabels_ = labels;
+    }
+    void setLabels(const ic::SetPropLabels &labels) {
+        JS_ASSERT(isSet());
+        setPropLabels_ = labels;
+    }
+    void setLabels(const ic::BindNameLabels &labels) {
+        JS_ASSERT(kind == BIND);
+        bindNameLabels_ = labels;
+    }
 #endif
 
+    GetPropLabels &getPropLabels() {
+        JS_ASSERT(isGet());
+        return getPropLabels_;
+    }
+    SetPropLabels &setPropLabels() {
+        JS_ASSERT(isSet());
+        return setPropLabels_;
+    }
+    BindNameLabels &bindNameLabels() {
+        JS_ASSERT(kind == BIND);
+        return bindNameLabels_;
+    }
+
     // Where in the script did we generate this PIC?
     jsbytecode *pc;
     
     // Index into the script's atom table.
     JSAtom *atom;
 
     // Reset the data members to the state of a fresh PIC before any patching
     // or stub generation was done.