js/src/jit/x64/BaselineHelpers-x64.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_x64_BaselineHelpers_x64_h
     8 #define jit_x64_BaselineHelpers_x64_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 Stack top to the top Value inside an IC stub (this is the return address).
    20 static const size_t ICStackValueOffset = sizeof(void *);
    22 inline void
    23 EmitRestoreTailCallReg(MacroAssembler &masm)
    24 {
    25     masm.pop(BaselineTailCallReg);
    26 }
    28 inline void
    29 EmitRepushTailCallReg(MacroAssembler &masm)
    30 {
    31     masm.push(BaselineTailCallReg);
    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, (int32_t) ICEntry::offsetOfFirstStub()),
    43                  BaselineStubReg);
    45     // Call the stubcode.
    46     masm.call(Operand(BaselineStubReg, ICStub::offsetOfStubCode()));
    47 }
    49 inline void
    50 EmitEnterTypeMonitorIC(MacroAssembler &masm,
    51                        size_t monitorStubOffset = ICMonitoredStub::offsetOfFirstMonitorStub())
    52 {
    53     // This is expected to be called from within an IC, when BaselineStubReg
    54     // is properly initialized to point to the stub.
    55     masm.loadPtr(Address(BaselineStubReg, (int32_t) monitorStubOffset), BaselineStubReg);
    57     // Jump to the stubcode.
    58     masm.jmp(Operand(BaselineStubReg, (int32_t) ICStub::offsetOfStubCode()));
    59 }
    61 inline void
    62 EmitReturnFromIC(MacroAssembler &masm)
    63 {
    64     masm.ret();
    65 }
    67 inline void
    68 EmitChangeICReturnAddress(MacroAssembler &masm, Register reg)
    69 {
    70     masm.storePtr(reg, Address(StackPointer, 0));
    71 }
    73 inline void
    74 EmitTailCallVM(JitCode *target, MacroAssembler &masm, uint32_t argSize)
    75 {
    76     // We an assume during this that R0 and R1 have been pushed.
    77     masm.movq(BaselineFrameReg, ScratchReg);
    78     masm.addq(Imm32(BaselineFrame::FramePointerOffset), ScratchReg);
    79     masm.subq(BaselineStackReg, ScratchReg);
    81     // Store frame size without VMFunction arguments for GC marking.
    82     masm.movq(ScratchReg, rdx);
    83     masm.subq(Imm32(argSize), rdx);
    84     masm.store32(rdx, Address(BaselineFrameReg, BaselineFrame::reverseOffsetOfFrameSize()));
    86     // Push frame descriptor and perform the tail call.
    87     masm.makeFrameDescriptor(ScratchReg, JitFrame_BaselineJS);
    88     masm.push(ScratchReg);
    89     masm.push(BaselineTailCallReg);
    90     masm.jmp(target);
    91 }
    93 inline void
    94 EmitCreateStubFrameDescriptor(MacroAssembler &masm, Register reg)
    95 {
    96     // Compute stub frame size. We have to add two pointers: the stub reg and previous
    97     // frame pointer pushed by EmitEnterStubFrame.
    98     masm.movq(BaselineFrameReg, reg);
    99     masm.addq(Imm32(sizeof(void *) * 2), reg);
   100     masm.subq(BaselineStackReg, reg);
   102     masm.makeFrameDescriptor(reg, JitFrame_BaselineStub);
   103 }
   105 inline void
   106 EmitCallVM(JitCode *target, MacroAssembler &masm)
   107 {
   108     EmitCreateStubFrameDescriptor(masm, ScratchReg);
   109     masm.push(ScratchReg);
   110     masm.call(target);
   111 }
   113 // Size of vales pushed by EmitEnterStubFrame.
   114 static const uint32_t STUB_FRAME_SIZE = 4 * sizeof(void *);
   115 static const uint32_t STUB_FRAME_SAVED_STUB_OFFSET = sizeof(void *);
   117 inline void
   118 EmitEnterStubFrame(MacroAssembler &masm, Register)
   119 {
   120     EmitRestoreTailCallReg(masm);
   122     // Compute frame size.
   123     masm.movq(BaselineFrameReg, ScratchReg);
   124     masm.addq(Imm32(BaselineFrame::FramePointerOffset), ScratchReg);
   125     masm.subq(BaselineStackReg, ScratchReg);
   127     masm.store32(ScratchReg, Address(BaselineFrameReg, BaselineFrame::reverseOffsetOfFrameSize()));
   129     // Note: when making changes here,  don't forget to update STUB_FRAME_SIZE
   130     // if needed.
   132     // Push frame descriptor and return address.
   133     masm.makeFrameDescriptor(ScratchReg, JitFrame_BaselineJS);
   134     masm.push(ScratchReg);
   135     masm.push(BaselineTailCallReg);
   137     // Save old frame pointer, stack pointer and stub reg.
   138     masm.push(BaselineStubReg);
   139     masm.push(BaselineFrameReg);
   140     masm.mov(BaselineStackReg, BaselineFrameReg);
   141 }
   143 inline void
   144 EmitLeaveStubFrameHead(MacroAssembler &masm, bool calledIntoIon = false)
   145 {
   146     // Ion frames do not save and restore the frame pointer. If we called
   147     // into Ion, we have to restore the stack pointer from the frame descriptor.
   148     // If we performed a VM call, the descriptor has been popped already so
   149     // in that case we use the frame pointer.
   150     if (calledIntoIon) {
   151         masm.pop(ScratchReg);
   152         masm.shrq(Imm32(FRAMESIZE_SHIFT), ScratchReg);
   153         masm.addq(ScratchReg, BaselineStackReg);
   154     } else {
   155         masm.mov(BaselineFrameReg, BaselineStackReg);
   156     }
   157 }
   159 inline void
   160 EmitLeaveStubFrameCommonTail(MacroAssembler &masm)
   161 {
   162     masm.pop(BaselineFrameReg);
   163     masm.pop(BaselineStubReg);
   165     // Pop return address.
   166     masm.pop(BaselineTailCallReg);
   168     // Overwrite frame descriptor with return address, so that the stack matches
   169     // the state before entering the stub frame.
   170     masm.storePtr(BaselineTailCallReg, Address(BaselineStackReg, 0));
   171 }
   173 inline void
   174 EmitLeaveStubFrame(MacroAssembler &masm, bool calledIntoIon = false)
   175 {
   176     EmitLeaveStubFrameHead(masm, calledIntoIon);
   177     EmitLeaveStubFrameCommonTail(masm);
   178 }
   180 inline void
   181 EmitStowICValues(MacroAssembler &masm, int values)
   182 {
   183     JS_ASSERT(values >= 0 && values <= 2);
   184     switch(values) {
   185       case 1:
   186         // Stow R0
   187         masm.pop(BaselineTailCallReg);
   188         masm.pushValue(R0);
   189         masm.push(BaselineTailCallReg);
   190         break;
   191       case 2:
   192         // Stow R0 and R1
   193         masm.pop(BaselineTailCallReg);
   194         masm.pushValue(R0);
   195         masm.pushValue(R1);
   196         masm.push(BaselineTailCallReg);
   197         break;
   198     }
   199 }
   201 inline void
   202 EmitUnstowICValues(MacroAssembler &masm, int values, bool discard = false)
   203 {
   204     JS_ASSERT(values >= 0 && values <= 2);
   205     switch(values) {
   206       case 1:
   207         // Unstow R0
   208         masm.pop(BaselineTailCallReg);
   209         if (discard)
   210             masm.addPtr(Imm32(sizeof(Value)), BaselineStackReg);
   211         else
   212             masm.popValue(R0);
   213         masm.push(BaselineTailCallReg);
   214         break;
   215       case 2:
   216         // Unstow R0 and R1
   217         masm.pop(BaselineTailCallReg);
   218         if (discard) {
   219             masm.addPtr(Imm32(sizeof(Value) * 2), BaselineStackReg);
   220         } else {
   221             masm.popValue(R1);
   222             masm.popValue(R0);
   223         }
   224         masm.push(BaselineTailCallReg);
   225         break;
   226     }
   227 }
   229 inline void
   230 EmitCallTypeUpdateIC(MacroAssembler &masm, JitCode *code, uint32_t objectOffset)
   231 {
   232     // R0 contains the value that needs to be typechecked.
   233     // The object we're updating is a boxed Value on the stack, at offset
   234     // objectOffset from stack top, excluding the return address.
   236     // Save the current BaselineStubReg to stack
   237     masm.push(BaselineStubReg);
   239     // This is expected to be called from within an IC, when BaselineStubReg
   240     // is properly initialized to point to the stub.
   241     masm.loadPtr(Address(BaselineStubReg, (int32_t) ICUpdatedStub::offsetOfFirstUpdateStub()),
   242                  BaselineStubReg);
   244     // Call the stubcode.
   245     masm.call(Operand(BaselineStubReg, ICStub::offsetOfStubCode()));
   247     // Restore the old stub reg.
   248     masm.pop(BaselineStubReg);
   250     // The update IC will store 0 or 1 in R1.scratchReg() reflecting if the
   251     // value in R0 type-checked properly or not.
   252     Label success;
   253     masm.cmp32(R1.scratchReg(), Imm32(1));
   254     masm.j(Assembler::Equal, &success);
   256     // If the IC failed, then call the update fallback function.
   257     EmitEnterStubFrame(masm, R1.scratchReg());
   259     masm.loadValue(Address(BaselineStackReg, STUB_FRAME_SIZE + objectOffset), R1);
   261     masm.pushValue(R0);
   262     masm.pushValue(R1);
   263     masm.push(BaselineStubReg);
   265     // Load previous frame pointer, push BaselineFrame *.
   266     masm.loadPtr(Address(BaselineFrameReg, 0), R0.scratchReg());
   267     masm.pushBaselineFramePtr(R0.scratchReg(), R0.scratchReg());
   269     EmitCallVM(code, masm);
   270     EmitLeaveStubFrame(masm);
   272     // Success at end.
   273     masm.bind(&success);
   274 }
   276 template <typename AddrType>
   277 inline void
   278 EmitPreBarrier(MacroAssembler &masm, const AddrType &addr, MIRType type)
   279 {
   280     masm.patchableCallPreBarrier(addr, type);
   281 }
   283 inline void
   284 EmitStubGuardFailure(MacroAssembler &masm)
   285 {
   286     // NOTE: This routine assumes that the stub guard code left the stack in the
   287     // same state it was in when it was entered.
   289     // BaselineStubEntry points to the current stub.
   291     // Load next stub into BaselineStubReg
   292     masm.loadPtr(Address(BaselineStubReg, ICStub::offsetOfNext()), BaselineStubReg);
   294     // Return address is already loaded, just jump to the next stubcode.
   295     masm.jmp(Operand(BaselineStubReg, ICStub::offsetOfStubCode()));
   296 }
   299 } // namespace jit
   300 } // namespace js
   302 #endif // JS_ION
   304 #endif /* jit_x64_BaselineHelpers_x64_h */

mercurial