js/src/jit/arm/BaselineHelpers-arm.h

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
     2  * vim: set ts=8 sts=4 et sw=4 tw=99:
     3  * This Source Code Form is subject to the terms of the Mozilla Public
     4  * License, v. 2.0. If a copy of the MPL was not distributed with this
     5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     7 #ifndef jit_arm_BaselineHelpers_arm_h
     8 #define jit_arm_BaselineHelpers_arm_h
    10 #ifdef JS_ION
    11 #include "jit/BaselineFrame.h"
    12 #include "jit/BaselineIC.h"
    13 #include "jit/BaselineRegisters.h"
    14 #include "jit/IonMacroAssembler.h"
    16 namespace js {
    17 namespace jit {
    19 // Distance from sp to the top Value inside an IC stub (no return address on the stack on ARM).
    20 static const size_t ICStackValueOffset = 0;
    22 inline void
    23 EmitRestoreTailCallReg(MacroAssembler &masm)
    24 {
    25     // No-op on ARM because link register is always holding the return address.
    26 }
    28 inline void
    29 EmitRepushTailCallReg(MacroAssembler &masm)
    30 {
    31     // No-op on ARM because link register is always holding the return address.
    32 }
    34 inline void
    35 EmitCallIC(CodeOffsetLabel *patchOffset, MacroAssembler &masm)
    36 {
    37     // Move ICEntry offset into BaselineStubReg
    38     CodeOffsetLabel offset = masm.movWithPatch(ImmWord(-1), BaselineStubReg);
    39     *patchOffset = offset;
    41     // Load stub pointer into BaselineStubReg
    42     masm.loadPtr(Address(BaselineStubReg, ICEntry::offsetOfFirstStub()), BaselineStubReg);
    44     // Load stubcode pointer from BaselineStubEntry.
    45     // R2 won't be active when we call ICs, so we can use r0.
    46     JS_ASSERT(R2 == ValueOperand(r1, r0));
    47     masm.loadPtr(Address(BaselineStubReg, ICStub::offsetOfStubCode()), r0);
    49     // Call the stubcode via a direct branch-and-link
    50     masm.ma_blx(r0);
    51 }
    53 inline void
    54 EmitEnterTypeMonitorIC(MacroAssembler &masm,
    55                        size_t monitorStubOffset = ICMonitoredStub::offsetOfFirstMonitorStub())
    56 {
    57     // This is expected to be called from within an IC, when BaselineStubReg
    58     // is properly initialized to point to the stub.
    59     masm.loadPtr(Address(BaselineStubReg, (uint32_t) monitorStubOffset), BaselineStubReg);
    61     // Load stubcode pointer from BaselineStubEntry.
    62     // R2 won't be active when we call ICs, so we can use r0.
    63     JS_ASSERT(R2 == ValueOperand(r1, r0));
    64     masm.loadPtr(Address(BaselineStubReg, ICStub::offsetOfStubCode()), r0);
    66     // Jump to the stubcode.
    67     masm.branch(r0);
    68 }
    70 inline void
    71 EmitReturnFromIC(MacroAssembler &masm)
    72 {
    73     masm.ma_mov(lr, pc);
    74 }
    76 inline void
    77 EmitChangeICReturnAddress(MacroAssembler &masm, Register reg)
    78 {
    79     masm.ma_mov(reg, lr);
    80 }
    82 inline void
    83 EmitTailCallVM(JitCode *target, MacroAssembler &masm, uint32_t argSize)
    84 {
    85     // We assume during this that R0 and R1 have been pushed, and that R2 is
    86     // unused.
    87     JS_ASSERT(R2 == ValueOperand(r1, r0));
    89     // Compute frame size.
    90     masm.movePtr(BaselineFrameReg, r0);
    91     masm.ma_add(Imm32(BaselineFrame::FramePointerOffset), r0);
    92     masm.ma_sub(BaselineStackReg, r0);
    94     // Store frame size without VMFunction arguments for GC marking.
    95     masm.ma_sub(r0, Imm32(argSize), r1);
    96     masm.store32(r1, Address(BaselineFrameReg, BaselineFrame::reverseOffsetOfFrameSize()));
    98     // Push frame descriptor and perform the tail call.
    99     // BaselineTailCallReg (lr) already contains the return address (as we keep it there through
   100     // the stub calls), but the VMWrapper code being called expects the return address to also
   101     // be pushed on the stack.
   102     JS_ASSERT(BaselineTailCallReg == lr);
   103     masm.makeFrameDescriptor(r0, JitFrame_BaselineJS);
   104     masm.push(r0);
   105     masm.push(lr);
   106     masm.branch(target);
   107 }
   109 inline void
   110 EmitCreateStubFrameDescriptor(MacroAssembler &masm, Register reg)
   111 {
   112     // Compute stub frame size. We have to add two pointers: the stub reg and previous
   113     // frame pointer pushed by EmitEnterStubFrame.
   114     masm.mov(BaselineFrameReg, reg);
   115     masm.ma_add(Imm32(sizeof(void *) * 2), reg);
   116     masm.ma_sub(BaselineStackReg, reg);
   118     masm.makeFrameDescriptor(reg, JitFrame_BaselineStub);
   119 }
   121 inline void
   122 EmitCallVM(JitCode *target, MacroAssembler &masm)
   123 {
   124     EmitCreateStubFrameDescriptor(masm, r0);
   125     masm.push(r0);
   126     masm.call(target);
   127 }
   129 // Size of vales pushed by EmitEnterStubFrame.
   130 static const uint32_t STUB_FRAME_SIZE = 4 * sizeof(void *);
   131 static const uint32_t STUB_FRAME_SAVED_STUB_OFFSET = sizeof(void *);
   133 inline void
   134 EmitEnterStubFrame(MacroAssembler &masm, Register scratch)
   135 {
   136     JS_ASSERT(scratch != BaselineTailCallReg);
   138     // Compute frame size.
   139     masm.mov(BaselineFrameReg, scratch);
   140     masm.ma_add(Imm32(BaselineFrame::FramePointerOffset), scratch);
   141     masm.ma_sub(BaselineStackReg, scratch);
   143     masm.store32(scratch, Address(BaselineFrameReg, BaselineFrame::reverseOffsetOfFrameSize()));
   145     // Note: when making changes here,  don't forget to update STUB_FRAME_SIZE
   146     // if needed.
   148     // Push frame descriptor and return address.
   149     masm.makeFrameDescriptor(scratch, JitFrame_BaselineJS);
   150     masm.push(scratch);
   151     masm.push(BaselineTailCallReg);
   153     // Save old frame pointer, stack pointer and stub reg.
   154     masm.push(BaselineStubReg);
   155     masm.push(BaselineFrameReg);
   156     masm.mov(BaselineStackReg, BaselineFrameReg);
   158     // We pushed 4 words, so the stack is still aligned to 8 bytes.
   159     masm.checkStackAlignment();
   160 }
   162 inline void
   163 EmitLeaveStubFrameHead(MacroAssembler &masm, bool calledIntoIon = false)
   164 {
   165     // Ion frames do not save and restore the frame pointer. If we called
   166     // into Ion, we have to restore the stack pointer from the frame descriptor.
   167     // If we performed a VM call, the descriptor has been popped already so
   168     // in that case we use the frame pointer.
   169     if (calledIntoIon) {
   170         masm.pop(ScratchRegister);
   171         masm.ma_lsr(Imm32(FRAMESIZE_SHIFT), ScratchRegister, ScratchRegister);
   172         masm.ma_add(ScratchRegister, BaselineStackReg);
   173     } else {
   174         masm.mov(BaselineFrameReg, BaselineStackReg);
   175     }
   176 }
   178 inline void
   179 EmitLeaveStubFrameCommonTail(MacroAssembler &masm)
   180 {
   181     masm.pop(BaselineFrameReg);
   182     masm.pop(BaselineStubReg);
   184     // Load the return address.
   185     masm.pop(BaselineTailCallReg);
   187     // Discard the frame descriptor.
   188     masm.pop(ScratchRegister);
   189 }
   191 inline void
   192 EmitLeaveStubFrame(MacroAssembler &masm, bool calledIntoIon = false)
   193 {
   194     EmitLeaveStubFrameHead(masm, calledIntoIon);
   195     EmitLeaveStubFrameCommonTail(masm);
   196 }
   198 inline void
   199 EmitStowICValues(MacroAssembler &masm, int values)
   200 {
   201     JS_ASSERT(values >= 0 && values <= 2);
   202     switch(values) {
   203       case 1:
   204         // Stow R0
   205         masm.pushValue(R0);
   206         break;
   207       case 2:
   208         // Stow R0 and R1
   209         masm.pushValue(R0);
   210         masm.pushValue(R1);
   211         break;
   212     }
   213 }
   215 inline void
   216 EmitUnstowICValues(MacroAssembler &masm, int values, bool discard = false)
   217 {
   218     JS_ASSERT(values >= 0 && values <= 2);
   219     switch(values) {
   220       case 1:
   221         // Unstow R0
   222         if (discard)
   223             masm.addPtr(Imm32(sizeof(Value)), BaselineStackReg);
   224         else
   225             masm.popValue(R0);
   226         break;
   227       case 2:
   228         // Unstow R0 and R1
   229         if (discard) {
   230             masm.addPtr(Imm32(sizeof(Value) * 2), BaselineStackReg);
   231         } else {
   232             masm.popValue(R1);
   233             masm.popValue(R0);
   234         }
   235         break;
   236     }
   237 }
   239 inline void
   240 EmitCallTypeUpdateIC(MacroAssembler &masm, JitCode *code, uint32_t objectOffset)
   241 {
   242     JS_ASSERT(R2 == ValueOperand(r1, r0));
   244     // R0 contains the value that needs to be typechecked.
   245     // The object we're updating is a boxed Value on the stack, at offset
   246     // objectOffset from esp, excluding the return address.
   248     // Save the current BaselineStubReg to stack, as well as the TailCallReg,
   249     // since on ARM, the LR is live.
   250     masm.push(BaselineStubReg);
   251     masm.push(BaselineTailCallReg);
   253     // This is expected to be called from within an IC, when BaselineStubReg
   254     // is properly initialized to point to the stub.
   255     masm.loadPtr(Address(BaselineStubReg, ICUpdatedStub::offsetOfFirstUpdateStub()),
   256                  BaselineStubReg);
   258     // TODO: Change r0 uses below to use masm's configurable scratch register instead.
   260     // Load stubcode pointer from BaselineStubReg into BaselineTailCallReg.
   261     masm.loadPtr(Address(BaselineStubReg, ICStub::offsetOfStubCode()), r0);
   263     // Call the stubcode.
   264     masm.ma_blx(r0);
   266     // Restore the old stub reg and tailcall reg.
   267     masm.pop(BaselineTailCallReg);
   268     masm.pop(BaselineStubReg);
   270     // The update IC will store 0 or 1 in R1.scratchReg() reflecting if the
   271     // value in R0 type-checked properly or not.
   272     Label success;
   273     masm.cmp32(R1.scratchReg(), Imm32(1));
   274     masm.j(Assembler::Equal, &success);
   276     // If the IC failed, then call the update fallback function.
   277     EmitEnterStubFrame(masm, R1.scratchReg());
   279     masm.loadValue(Address(BaselineStackReg, STUB_FRAME_SIZE + objectOffset), R1);
   281     masm.pushValue(R0);
   282     masm.pushValue(R1);
   283     masm.push(BaselineStubReg);
   285     // Load previous frame pointer, push BaselineFrame *.
   286     masm.loadPtr(Address(BaselineFrameReg, 0), R0.scratchReg());
   287     masm.pushBaselineFramePtr(R0.scratchReg(), R0.scratchReg());
   289     EmitCallVM(code, masm);
   290     EmitLeaveStubFrame(masm);
   292     // Success at end.
   293     masm.bind(&success);
   294 }
   296 template <typename AddrType>
   297 inline void
   298 EmitPreBarrier(MacroAssembler &masm, const AddrType &addr, MIRType type)
   299 {
   300     // on ARM, lr is clobbered by patchableCallPreBarrier.  Save it first.
   301     masm.push(lr);
   302     masm.patchableCallPreBarrier(addr, type);
   303     masm.pop(lr);
   304 }
   306 inline void
   307 EmitStubGuardFailure(MacroAssembler &masm)
   308 {
   309     JS_ASSERT(R2 == ValueOperand(r1, r0));
   311     // NOTE: This routine assumes that the stub guard code left the stack in the
   312     // same state it was in when it was entered.
   314     // BaselineStubEntry points to the current stub.
   316     // Load next stub into BaselineStubReg
   317     masm.loadPtr(Address(BaselineStubReg, ICStub::offsetOfNext()), BaselineStubReg);
   319     // Load stubcode pointer from BaselineStubEntry into scratch register.
   320     masm.loadPtr(Address(BaselineStubReg, ICStub::offsetOfStubCode()), r0);
   322     // Return address is already loaded, just jump to the next stubcode.
   323     JS_ASSERT(BaselineTailCallReg == lr);
   324     masm.branch(r0);
   325 }
   328 } // namespace jit
   329 } // namespace js
   331 #endif // JS_ION
   333 #endif /* jit_arm_BaselineHelpers_arm_h */

mercurial