[JAEGER] Start of stub-call compiler; sub-classed MacroAssembler into mjit::Assembler.
authorDavid Anderson <danderson@mozilla.com>
Wed, 26 May 2010 17:08:08 -0700
changeset 52608 0b9cfe5ef098f9ad8a87b36e535f9e8df4fe99d8
parent 52607 ec13cf65e503515e790747c410990f3af34916db
child 52609 a6edb3f0d569ec5e339047cf800abd04c96d4dfc
push id1
push userroot
push dateTue, 26 Apr 2011 22:38:44 +0000
treeherdermozilla-beta@bfdb6e623a36 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone1.9.3a5pre
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
[JAEGER] Start of stub-call compiler; sub-classed MacroAssembler into mjit::Assembler.
js/src/Makefile.in
js/src/methodjit/Compiler.cpp
js/src/methodjit/Compiler.h
js/src/methodjit/MachineRegs.h
js/src/methodjit/MethodJIT.h
js/src/methodjit/RematInfo.h
js/src/methodjit/StubCalls.cpp
js/src/methodjit/StubCalls.h
js/src/methodjit/StubCompiler.cpp
js/src/methodjit/StubCompiler.h
js/src/methodjit/Stubs.cpp
js/src/methodjit/Stubs.h
js/src/methodjit/nunbox/Assembler.h
js/src/methodjit/nunbox/CodeGenerator.cpp
js/src/methodjit/nunbox/CodeGenerator.h
js/src/methodjit/nunbox/FastOps.cpp
js/src/methodjit/nunbox/FrameState.cpp
js/src/methodjit/nunbox/FrameState.h
--- a/js/src/Makefile.in
+++ b/js/src/Makefile.in
@@ -295,21 +295,22 @@ CPPSRCS += 	Assertions.cpp \
 		ExecutableAllocatorPosix.cpp \
 		ExecutableAllocatorWin.cpp \
 		ExecutableAllocator.cpp \
 		ARMAssembler.cpp \
 		MacroAssemblerARM.cpp \
 		MethodJIT.cpp \
 		BytecodeAnalyzer.cpp \
 		Logging.cpp \
-		Stubs.cpp \
+		StubCalls.cpp \
 		Compiler.cpp \
 		CodeGenerator.cpp \
 		FrameState.cpp \
 		FastOps.cpp \
+		StubCompiler.cpp \
 		$(NULL)
 #		PICStubCompiler.cpp \
 
 ifeq (86, $(findstring 86,$(TARGET_CPU)))
 ifeq (x86_64, $(TARGET_CPU))
 ifeq ($(OS_ARCH),WINNT)
 ASFILES +=	TrampolineMasmX64.asm
 endif
--- a/js/src/methodjit/Compiler.cpp
+++ b/js/src/methodjit/Compiler.cpp
@@ -58,17 +58,17 @@ static const char *OpcodeNames[] = {
 #if ENABLE_ASSEMBLER && WTF_CPU_X86 && !WTF_PLATFORM_MAC
 JSC::MacroAssemblerX86Common::SSE2CheckState JSC::MacroAssemblerX86Common::s_sse2CheckState =
 NotCheckedSSE2; 
 #endif 
 
 mjit::Compiler::Compiler(JSContext *cx, JSScript *script, JSFunction *fun, JSObject *scopeChain)
   : cx(cx), script(script), scopeChain(scopeChain), globalObj(scopeChain->getGlobal()), fun(fun),
     analysis(cx, script), jumpMap(NULL), frame(cx, script, masm), cg(masm, frame),
-    branchPatches(ContextAllocPolicy(cx))
+    branchPatches(ContextAllocPolicy(cx)), stubcc(cx, *this, frame, script)
 {
 }
 
 #define CHECK_STATUS(expr)              \
     JS_BEGIN_MACRO                      \
         CompileStatus status_ = (expr); \
         if (status_ != Compile_Okay)    \
             return status_;             \
--- a/js/src/methodjit/Compiler.h
+++ b/js/src/methodjit/Compiler.h
@@ -39,30 +39,29 @@
  * ***** END LICENSE BLOCK ***** */
 #if !defined jsjaeger_compiler_h__ && defined JS_METHODJIT
 #define jsjaeger_compiler_h__
 
 #include "jscntxt.h"
 #include "jstl.h"
 #include "BytecodeAnalyzer.h"
 #include "MethodJIT.h"
-#include "assembler/assembler/MacroAssembler.h"
 #include "CodeGenIncludes.h"
+#include "StubCompiler.h"
 
 namespace js {
 namespace mjit {
 
 class Compiler
 {
     typedef JSC::MacroAssembler::Label Label;
     typedef JSC::MacroAssembler::ImmPtr ImmPtr;
     typedef JSC::MacroAssembler::RegisterID RegisterID;
     typedef JSC::MacroAssembler::Address Address;
     typedef JSC::MacroAssembler::Jump Jump;
-    typedef JSC::MacroAssembler MacroAssembler;
 
     struct BranchPatch {
         BranchPatch(const Jump &j, jsbytecode *pc)
           : jump(j), pc(pc)
         { }
 
         Jump jump;
         jsbytecode *pc;
@@ -71,31 +70,34 @@ class Compiler
     JSContext *cx;
     JSScript *script;
     JSObject *scopeChain;
     JSObject *globalObj;
     JSFunction *fun;
     BytecodeAnalyzer analysis;
     Label *jumpMap;
     jsbytecode *PC;
-    MacroAssembler masm;
+    Assembler masm;
     FrameState frame;
     CodeGenerator cg;
     js::Vector<BranchPatch, 64> branchPatches;
+    StubCompiler stubcc;
 
   public:
     // Special atom index used to indicate that the atom is 'length'. This
     // follows interpreter usage in JSOP_LENGTH.
     enum { LengthAtomIndex = uint32(-2) };
 
     Compiler(JSContext *cx, JSScript *script, JSFunction *fun, JSObject *scopeChain);
     ~Compiler();
 
     CompileStatus Compile();
 
+    jsbytecode *getPC() { return PC; }
+
   private:
     CompileStatus generatePrologue();
     CompileStatus generateMethod();
     CompileStatus generateEpilogue();
     CompileStatus finishThisUp();
 
     /* Non-emitting helpers. */
     const Label &labelOf(jsbytecode *pc);
--- a/js/src/methodjit/MachineRegs.h
+++ b/js/src/methodjit/MachineRegs.h
@@ -46,16 +46,32 @@
 namespace js {
 
 namespace mjit {
 
 struct Registers {
 
     typedef JSC::MacroAssembler::RegisterID RegisterID;
 
+#if defined(JS_CPU_X86) || defined(JS_CPU_X64)
+    static const RegisterID ReturnReg = JSC::X86Registers::eax;
+# if defined(JS_CPU_X86) || defined(_MSC_VER)
+    static const RegisterID ArgReg0 = JSC::X86Registers::ecx;
+    static const RegisterID ArgReg1 = JSC::X86Registers::edx;
+# else
+    static const RegisterID ArgReg0 = JSC::X86Registers::edi;
+    static const RegisterID ArgReg1 = JSC::X86Registers::esi;
+# endif
+#elif JS_CPU_ARM
+    static const RegisterID ReturnReg = JSC::ARMRegisters::r0;
+    static const RegisterID ArgReg0 = JSC::ARMRegisters::r0;
+    static const RegisterID ArgReg1 = JSC::ARMRegisters::r1;
+#endif
+
+
     static inline uint32 maskReg(RegisterID reg) {
         return (1 << reg);
     }
 
     static inline uint32 mask2Regs(RegisterID reg1, RegisterID reg2) {
         return maskReg(reg1) | maskReg(reg2);
     }
 
@@ -118,19 +134,23 @@ struct Registers {
 
     static const uint32 SingleByteRegs = TempRegs | SavedRegs;
 #else
 # error "Unsupported platform"
 #endif
 
     static const uint32 AvailRegs = SavedRegs | TempRegs;
 
-    Registers() : freeMask(AvailRegs)
-    {
-    }
+    Registers()
+      : freeMask(AvailRegs)
+    { }
+
+    Registers(uint32 freeMask)
+      : freeMask(freeMask)
+    { }
 
     void reset() {
         freeMask = AvailRegs;
     }
 
     bool anyRegsFree() {
         return !!freeMask;
     }
--- a/js/src/methodjit/MethodJIT.h
+++ b/js/src/methodjit/MethodJIT.h
@@ -66,20 +66,16 @@ struct VMFrame
 
 #if defined(JS_CPU_X86)
     uintptr_t               padding[2];
 #elif defined(JS_CPU_ARM)
     uintptr_t               padding;
 #endif
 
     union Arguments {
-        struct BINDNAME {
-            uint32   index;
-            JSObject *obj;
-        } bindname;
         struct DEFVAR {
             jsatomid index;
             uint32   op;
         } defvar;
         struct LAMBDA {
             uint32 index;
             JSOp   op;
         } lambda;
--- a/js/src/methodjit/RematInfo.h
+++ b/js/src/methodjit/RematInfo.h
@@ -74,20 +74,22 @@ struct RematInfo {
         location_ = PhysLoc_Memory;
     }
 
     void setConstant() { location_ = PhysLoc_Constant; }
 
     bool isCopy() { return location_ == PhysLoc_Copy; }
     bool isConstant() { return location_ == PhysLoc_Constant; }
     bool inRegister() { return location_ == PhysLoc_Register; }
+    bool inMemory() { return location_ == PhysLoc_Memory; }
     RegisterID reg() { return reg_; }
 
     void unsync() { synced_ = false; }
     bool synced() { return synced_; }
+    bool needsSync() { return !inMemory() && !synced(); }
 
     /* Set if location is PhysLoc_Register. */
     RegisterID reg_;
 
     /* Remat source. */
     PhysLoc    location_;
 
     /* Whether or not the value has been synced to memory. */
rename from js/src/methodjit/Stubs.cpp
rename to js/src/methodjit/StubCalls.cpp
--- a/js/src/methodjit/Stubs.cpp
+++ b/js/src/methodjit/StubCalls.cpp
@@ -47,17 +47,17 @@
 #include "jsiter.h"
 #include "jsnum.h"
 #include "jsxml.h"
 #include "jsstaticcheck.h"
 #include "jsbool.h"
 #include "assembler/assembler/MacroAssemblerCodeRef.h"
 #include "jsiter.h"
 #include "jstypes.h"
-#include "methodjit/Stubs.h"
+#include "methodjit/StubCalls.h"
 #include "jstracer.h"
 #include "jspropertycache.h"
 #include "jspropertycacheinlines.h"
 #include "jsscopeinlines.h"
 #include "jsscriptinlines.h"
 #include "jsstrinlines.h"
 #include "jsobjinlines.h"
 #include "jscntxtinlines.h"
@@ -77,16 +77,39 @@ using namespace JSC;
 
 #define THROWV(v)       \
     do {                \
         void *ptr = JS_FUNC_TO_DATA_PTR(void *, JaegerThrowpoline); \
         f.setReturnAddress(ReturnAddressPtr(FunctionPtr(ptr))); \
         return v;       \
     } while (0)
 
+JSObject * JS_FASTCALL
+mjit::stubs::BindName(VMFrame &f)
+{
+    PropertyCacheEntry *entry;
+
+    /* Fast-path should have caught this. See comment in interpreter. */
+    JS_ASSERT(f.fp->scopeChain->getParent());
+
+    JSAtom *atom;
+    JSObject *obj2;
+    JSContext *cx = f.cx;
+    JSObject *obj = f.fp->scopeChain->getParent();
+    JS_PROPERTY_CACHE(cx).test(cx, f.regs.pc, obj, obj2, entry, atom);
+    if (!atom)
+        return obj;
+
+    jsid id = ATOM_TO_JSID(atom);
+    obj = js_FindIdentifierBase(cx, f.fp->scopeChain, id);
+    if (!obj)
+        THROWV(NULL);
+    return obj;
+}
+
 static bool
 InlineReturn(JSContext *cx)
 {
     bool ok = true;
 
     JSStackFrame *fp = cx->fp;
 
     JS_ASSERT(!fp->blockChain);
rename from js/src/methodjit/Stubs.h
rename to js/src/methodjit/StubCalls.h
--- a/js/src/methodjit/Stubs.h
+++ b/js/src/methodjit/StubCalls.h
@@ -43,16 +43,17 @@
 
 #include "MethodJIT.h"
 
 namespace js {
 namespace mjit {
 namespace stubs {
 
 void * JS_FASTCALL Return(VMFrame &f);
+JSObject * JS_FASTCALL BindName(VMFrame &f);
 
 }}} /* namespace stubs,mjit,js */
 
 extern "C" void *
 js_InternalThrow(js::VMFrame &f);
 
 #endif /* jslogic_h__ */
 
new file mode 100644
--- /dev/null
+++ b/js/src/methodjit/StubCompiler.cpp
@@ -0,0 +1,131 @@
+/* -*- 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 Anderson <danderson@mozilla.com>
+ *   David Mandelin <dmandelin@mozilla.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 ***** */
+
+#include "StubCompiler.h"
+#include "Compiler.h"
+
+using namespace js;
+using namespace mjit;
+
+StubCompiler::StubCompiler(JSContext *cx, mjit::Compiler &cc, FrameState &frame, JSScript *script)
+  : cx(cx), cc(cc), frame(frame), script(script), exits(ContextAllocPolicy(cx))
+{
+}
+
+void
+StubCompiler::linkExit(Jump j)
+{
+    /* :TODO: oom check */
+    exits.append(ExitPatch(j, masm.label()));
+}
+
+void
+StubCompiler::syncAndSpill()
+{
+    frame.sync(masm);
+}
+
+void *
+StubCompiler::getCallTarget(void *fun)
+{
+#ifdef JS_CPU_ARM
+    /*
+     * Insert a veneer for ARM to allow it to catch exceptions. There is no
+     * reliable way to determine the location of the return address on the
+     * stack, so it cannot be hijacked.
+     *
+     * :TODO: It wouldn't surprise me if GCC always pushes LR first. In that
+     * case, this looks like the x86-style call, and we can hijack the stack
+     * slot accordingly, thus avoiding the cost of a veneer. This should be
+     * investigated.
+     */
+
+    void *pfun = JS_FUNC_TO_DATA_PTR(void *, JaegerStubVeneer);
+
+    /*
+     * We put the real target address into IP, as this won't conflict with
+     * the EABI argument-passing mechanism. Technically, this isn't ABI-
+     * compliant.
+     */
+    masm.move(Imm32(intptr_t(fun)), ARMRegisters::ip);
+#else
+    /*
+     * Architectures that push the return address to an easily-determined
+     * location on the stack can hijack C++'s return mechanism by overwriting
+     * that address, so a veneer is not required.
+     */
+    void *pfun = fun;
+#endif
+    return pfun;
+}
+
+typedef JSC::MacroAssembler::RegisterID RegisterID;
+typedef JSC::MacroAssembler::ImmPtr ImmPtr;
+typedef JSC::MacroAssembler::Imm32 Imm32;
+
+/* Need a temp reg that is not ArgReg1. */
+#if defined(JS_CPU_X86) || defined(JS_CPU_ARM)
+static const RegisterID ClobberInCall = JSC::X86Registers::ecx;
+#elif defined(JS_CPU_ARM)
+static const RegisterID ClobberInCall = JSC::ARMRegisters::r2;
+#endif
+
+JS_STATIC_ASSERT(ClobberInCall != Registers::ArgReg1);
+
+void
+StubCompiler::scall(void *ptr)
+{
+    /* PC -> regs->pc :( */
+    masm.storePtr(ImmPtr(cc.getPC()),
+                  FrameAddress(offsetof(VMFrame, regs) + offsetof(JSFrameRegs, pc)));
+
+    /* sp = fp + slots() + stackDepth */
+    masm.addPtr(Imm32(sizeof(JSStackFrame) +
+                (frame.stackDepth() + script->nfixed) * sizeof(jsval)),
+                FrameState::FpReg, ClobberInCall);
+
+    /* regs->sp = sp */
+    masm.storePtr(ClobberInCall,
+                  FrameAddress(offsetof(VMFrame, regs) + offsetof(JSFrameRegs, sp)));
+    
+    /* VMFrame -> ArgReg0 */
+    masm.move(Assembler::stackPointerRegister, Registers::ArgReg0);
+}
+
new file mode 100644
--- /dev/null
+++ b/js/src/methodjit/StubCompiler.h
@@ -0,0 +1,95 @@
+/* -*- 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 Anderson <danderson@mozilla.com>
+ *   David Mandelin <dmandelin@mozilla.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(jsstub_compiler_h__) && defined(JS_METHODJIT)
+#define jsstub_compiler_h__
+
+#include "jscntxt.h"
+#include "jstl.h"
+#include "MethodJIT.h"
+#include "methodjit/nunbox/Assembler.h"
+#include "CodeGenIncludes.h"
+
+namespace js {
+namespace mjit {
+
+class Compiler;
+
+struct StubCallInfo {
+    uint32 numSpills;
+};
+
+class StubCompiler
+{
+    typedef JSC::MacroAssembler::Jump Jump;
+    typedef JSC::MacroAssembler::Label Label;
+
+    struct ExitPatch {
+        ExitPatch(Jump from, Label to)
+          : from(from), to(to)
+        { }
+
+        Jump from;
+        Label to;
+    };
+
+    JSContext *cx;
+    Compiler &cc;
+    FrameState &frame;
+    JSScript *script;
+    Assembler masm;
+    Vector<ExitPatch, 64, ContextAllocPolicy> exits;
+
+  public:
+    StubCompiler(JSContext *cx, mjit::Compiler &cc, FrameState &frame, JSScript *script);
+    void linkExit(Jump j);
+    void syncAndSpill();
+    void call(JSObjStub stub) { scall(JS_FUNC_TO_DATA_PTR(void *, stub)); }
+
+  private:
+    void scall(void *ptr);
+    void *getCallTarget(void *fun);
+};
+
+} /* namepsace mjit */
+} /* namespace js */
+
+#endif /* jsstub_compiler_h__ */
+
new file mode 100644
--- /dev/null
+++ b/js/src/methodjit/nunbox/Assembler.h
@@ -0,0 +1,56 @@
+/* -*- 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 Anderson <danderson@mozilla.com>
+ *   David Mandelin <dmandelin@mozilla.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_assembler_h__ && defined JS_METHODJIT
+#define jsjaeger_assembler_h__
+
+#include "assembler/assembler/MacroAssembler.h"
+
+namespace js {
+namespace mjit {
+
+class Assembler : public JSC::MacroAssembler
+{
+  public:
+};
+
+} /* namespace js */
+} /* namespace mjit */
+
+#endif
--- a/js/src/methodjit/nunbox/CodeGenerator.cpp
+++ b/js/src/methodjit/nunbox/CodeGenerator.cpp
@@ -52,17 +52,17 @@ static const uint32 PAYLOAD_OFFSET = 0;
 class ImmIntPtr : public JSC::MacroAssembler::ImmPtr
 {
   public:
     ImmIntPtr(int64_t i64)
       : ImmPtr(reinterpret_cast<void*>(i64))
     { }
 };
 
-CodeGenerator::CodeGenerator(MacroAssembler &masm, FrameState &frame)
+CodeGenerator::CodeGenerator(Assembler &masm, FrameState &frame)
   : masm(masm), frame(frame)
 {
 }
 
 void
 CodeGenerator::storeJsval(const Value &v, Address address)
 {
     jsval_layout jv;
--- a/js/src/methodjit/nunbox/CodeGenerator.h
+++ b/js/src/methodjit/nunbox/CodeGenerator.h
@@ -39,34 +39,33 @@
  * ***** END LICENSE BLOCK ***** */
 #if !defined jsjaeger_codegen_h__ && defined JS_METHODJIT
 #define jsjaeger_codegen_h__
 
 #include "jscntxt.h"
 #include "jstl.h"
 #include "methodjit/MethodJIT.h"
 #include "methodjit/nunbox/FrameState.h"
-#include "assembler/assembler/MacroAssembler.h"
+#include "methodjit/nunbox/Assembler.h"
 
 namespace js {
 namespace mjit {
 
 class CodeGenerator
 {
-    typedef JSC::MacroAssembler MacroAssembler;
     typedef JSC::MacroAssembler::Address Address;
     typedef JSC::MacroAssembler::Imm32 Imm32;
     typedef JSC::MacroAssembler::ImmPtr ImmPtr;
     typedef JSC::MacroAssembler::RegisterID RegisterID;
 
-    MacroAssembler &masm;
+    Assembler      &masm;
     FrameState     &frame;
 
   public:
-    CodeGenerator(MacroAssembler &masm, FrameState &frame);
+    CodeGenerator(Assembler &masm, FrameState &frame);
 
     void storeValue(FrameEntry *vi, Address address, bool popped);
     void storeJsval(const Value &v, Address address);
     void pushValueOntoFrame(Address address);
 };
 
 } /* namespace js */
 } /* namespace mjit */
--- a/js/src/methodjit/nunbox/FastOps.cpp
+++ b/js/src/methodjit/nunbox/FastOps.cpp
@@ -34,34 +34,38 @@
  * 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 ***** */
 #include "methodjit/MethodJIT.h"
 #include "methodjit/Compiler.h"
+#include "methodjit/StubCalls.h"
 
 #include "jsautooplen.h"
 
 using namespace js;
+using namespace js::mjit;
 
 static const uint32 TAG_OFFSET     = 4;
 static const uint32 PAYLOAD_OFFSET = 0;
 
 void
 mjit::Compiler::jsop_bindname(uint32 index)
 {
     RegisterID reg = frame.allocReg();
     masm.loadPtr(Address(FrameState::FpReg, offsetof(JSStackFrame, scopeChain)), reg);
 
     Address address(reg, offsetof(JSObject, fslots) + JSSLOT_PARENT * sizeof(jsval));
 
     masm.load32(Address(address.base, address.offset + PAYLOAD_OFFSET), reg);
-#ifdef JS_64BIT
-# error "Bleh!"
-#endif
+    Jump j = masm.branchTestPtr(Assembler::Zero, reg, reg);
 
-    Jump j = masm.branchTestPtr(MacroAssembler::Zero, reg, reg);
+    {
+        stubcc.linkExit(j);
+        stubcc.syncAndSpill();
+        stubcc.call(stubs::BindName);
+    }
 
     frame.pushObject(reg);
 }
 
--- a/js/src/methodjit/nunbox/FrameState.cpp
+++ b/js/src/methodjit/nunbox/FrameState.cpp
@@ -112,8 +112,51 @@ FrameState::invalidate(FrameEntry *fe)
 
 void
 FrameState::flush()
 {
     for (FrameEntry *fe = base; fe < sp; fe++)
         invalidate(fe);
 }
 
+void
+FrameState::syncRegister(Assembler &masm, RegisterID reg, const RegState &state) const
+{
+    JS_NOT_REACHED("bleh");
+}
+
+void
+FrameState::syncType(FrameEntry *fe, Assembler &masm) const
+{
+}
+
+void
+FrameState::syncData(FrameEntry *fe, Assembler &masm) const
+{
+}
+
+void
+FrameState::sync(Assembler &masm) const
+{
+    for (FrameEntry *fe = base; fe < sp; fe++) {
+        if (fe->type.needsSync())
+            syncType(fe, masm);
+        if (fe->data.needsSync())
+            syncData(fe, masm);
+    }
+}
+
+void
+FrameState::restoreTempRegs(Assembler &masm) const
+{
+#if 0
+    /* Get a mask of all allocated registers that must be synced. */
+    Registers temps = regalloc.freeMask & Registers::TempRegs;
+
+    while (temps.anyRegsFree()) {
+        RegisterID reg = temps.allocReg();
+        if (!regstate[reg].tracked)
+            continue;
+        syncRegister(masm, reg, regstate[reg]);
+    }
+#endif
+}
+
--- a/js/src/methodjit/nunbox/FrameState.h
+++ b/js/src/methodjit/nunbox/FrameState.h
@@ -37,26 +37,33 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #if !defined jsjaeger_framestate_h__ && defined JS_METHODJIT
 #define jsjaeger_framestate_h__
 
 #include "jsapi.h"
 #include "methodjit/MachineRegs.h"
-#include "assembler/assembler/MacroAssembler.h"
+#include "methodjit/nunbox/Assembler.h"
 #include "methodjit/nunbox/FrameEntry.h"
 
 namespace js {
 namespace mjit {
 
 enum TypeInfo {
     Type_Unknown
 };
 
+struct FrameAddress : JSC::MacroAssembler::Address
+{
+    FrameAddress(int32 offset)
+      : Address(JSC::MacroAssembler::stackPointerRegister, offset)
+    { }
+};
+
 class FrameState
 {
     typedef JSC::MacroAssembler::RegisterID RegisterID;
     typedef JSC::MacroAssembler::Address Address;
     typedef JSC::MacroAssembler MacroAssembler;
 
     struct RegState {
         enum ValuePart {
@@ -66,17 +73,17 @@ class FrameState
 
         uint32     index;
         ValuePart  part;
         bool       spillable;
         bool       tracked;
     };
 
   public:
-    FrameState(JSContext *cx, JSScript *script, MacroAssembler &masm)
+    FrameState(JSContext *cx, JSScript *script, Assembler &masm)
       : cx(cx), script(script), masm(masm), base(NULL)
     { }
     ~FrameState();
 
 #if defined(JS_CPU_X86) || defined(JS_CPU_X64)
     static const RegisterID FpReg = JSC::X86Registers::ebx;
 #elif defined(JS_CPU_ARM)
     static const RegisterID FpReg = JSC::X86Registers::r11;
@@ -181,26 +188,31 @@ class FrameState
         sp = spBase + newDepth;
         if (oldDepth <= newDepth)
             return;
         memset(spBase, 0, sizeof(FrameEntry) * (newDepth - oldDepth));
     }
 
     void flush();
     void assertValidRegisterState();
+    void sync(Assembler &masm) const;
+    void restoreTempRegs(Assembler &masm) const;
 
   private:
+    void syncType(FrameEntry *fe, Assembler &masm) const;
+    void syncData(FrameEntry *fe, Assembler &masm) const;
+    void syncRegister(Assembler &masm, RegisterID reg, const RegState &state) const;
     void evictSomething();
     void invalidate(FrameEntry *fe);
     RegisterID getDataReg(FrameEntry *vi, FrameEntry *backing);
 
   private:
     JSContext *cx;
     JSScript *script;
-    MacroAssembler &masm;
+    Assembler &masm;
     FrameEntry *base;
     FrameEntry *locals;
     FrameEntry *args;
     FrameEntry *sp;
     Registers regalloc;
     RegState  regstate[MacroAssembler::TotalRegisters];
 };