Bug 1200560, IonMonkey: Part 1: Get tailCallVM working in shared stubs embedded in ion on arm, r=sstangl
authorHannes Verschore <hv1989@gmail.com>
Thu, 10 Sep 2015 14:02:22 +0200
changeset 296080 a1255d7b2c115f59f0ff0e3f698464b0a1ddc6e6
parent 296079 8d7edac29dad30794d96fa21445ccb4d43a5c952
child 296081 0e15a964f1f967fff3a225f782d6e2585b0af272
push id962
push userjlund@mozilla.com
push dateFri, 04 Dec 2015 23:28:54 +0000
treeherdermozilla-release@23a2d286e80f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssstangl
bugs1200560
milestone43.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1200560, IonMonkey: Part 1: Get tailCallVM working in shared stubs embedded in ion on arm, r=sstangl
js/src/jit/CodeGenerator.cpp
js/src/jit/arm/SharedICHelpers-arm.h
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -1683,32 +1683,43 @@ CodeGenerator::visitStringReplace(LStrin
 }
 
 void
 CodeGenerator::emitSharedStub(ICStub::Kind kind, LInstruction* lir)
 {
     JSScript* script = lir->mirRaw()->block()->info().script();
     jsbytecode* pc = lir->mirRaw()->toInstruction()->resumePoint()->pc();
 
+#ifdef JS_USE_LINK_REGISTER
+    // Some architectures don't push the return address on the stack but
+    // use the link register. In that case the stack isn't aligned. Push
+    // to make sure we are aligned.
+    masm.Push(Imm32(0));
+#endif
+
     // Create descriptor signifying end of Ion frame.
     uint32_t descriptor = MakeFrameDescriptor(masm.framePushed(), JitFrame_IonJS);
     masm.Push(Imm32(descriptor));
 
     // Call into the stubcode.
     CodeOffsetLabel patchOffset;
     IonICEntry entry(script->pcToOffset(pc), ICEntry::Kind_Op, script);
     EmitCallIC(&patchOffset, masm);
     entry.setReturnOffset(CodeOffsetLabel(masm.currentOffset()));
 
     SharedStub sharedStub(kind, entry, patchOffset);
     masm.propagateOOM(sharedStubs_.append(sharedStub));
 
     // Fix up upon return.
     uint32_t callOffset = masm.currentOffset();
+#ifdef JS_USE_LINK_REGISTER
+    masm.freeStack(sizeof(intptr_t) * 2);
+#else
     masm.freeStack(sizeof(intptr_t));
+#endif
     markSafepointAt(callOffset, lir);
 }
 
 void
 CodeGenerator::visitBinarySharedStub(LBinarySharedStub* lir)
 {
     JSOp jsop = JSOp(*lir->mir()->resumePoint()->pc());
     switch (jsop) {
--- a/js/src/jit/arm/SharedICHelpers-arm.h
+++ b/js/src/jit/arm/SharedICHelpers-arm.h
@@ -103,17 +103,33 @@ EmitBaselineTailCallVM(JitCode* target, 
     masm.push(r0);
     masm.push(lr);
     masm.branch(target);
 }
 
 inline void
 EmitIonTailCallVM(JitCode* target, MacroAssembler& masm, uint32_t stackSize)
 {
-    MOZ_CRASH("Not implemented yet.");
+    // We assume during this that R0 and R1 have been pushed, and that R2 is
+    // unused.
+    MOZ_ASSERT(R2 == ValueOperand(r1, r0));
+
+    masm.loadPtr(Address(sp, stackSize), r0);
+    masm.rshiftPtr(Imm32(FRAMESIZE_SHIFT), r0);
+    masm.add32(Imm32(stackSize + JitStubFrameLayout::Size() - sizeof(intptr_t)), r0);
+
+    // Push frame descriptor and perform the tail call.
+    // ICTailCallReg (lr) already contains the return address (as we keep
+    // it there through the stub calls), but the VMWrapper code being called
+    // expects the return address to also be pushed on the stack.
+    MOZ_ASSERT(ICTailCallReg == lr);
+    masm.makeFrameDescriptor(r0, JitFrame_IonJS);
+    masm.push(r0);
+    masm.push(lr);
+    masm.branch(target);
 }
 
 inline void
 EmitBaselineCreateStubFrameDescriptor(MacroAssembler& masm, Register reg)
 {
     // Compute stub frame size. We have to add two pointers: the stub reg and
     // previous frame pointer pushed by EmitEnterStubFrame.
     masm.mov(BaselineFrameReg, reg);
@@ -182,18 +198,18 @@ EmitBaselineLeaveStubFrame(MacroAssemble
     ScratchRegisterScope scratch(masm);
 
     // Ion frames do not save and restore the frame pointer. If we called into
     // Ion, we have to restore the stack pointer from the frame descriptor. If
     // we performed a VM call, the descriptor has been popped already so in that
     // case we use the frame pointer.
     if (calledIntoIon) {
         masm.pop(scratch);
-        masm.ma_lsr(Imm32(FRAMESIZE_SHIFT), scratch, scratch);
-        masm.ma_add(scratch, BaselineStackReg);
+        masm.rshiftPtr(Imm32(FRAMESIZE_SHIFT), scratch);
+        masm.add32(scratch, BaselineStackReg);
     } else {
         masm.mov(BaselineFrameReg, BaselineStackReg);
     }
 
     masm.pop(BaselineFrameReg);
     masm.pop(ICStubReg);
 
     // Load the return address.