js/src/jit/x86/BaselineHelpers-x86.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_x86_BaselineHelpers_x86_h
     8 #define jit_x86_BaselineHelpers_x86_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     // Load stubcode pointer from BaselineStubEntry into BaselineTailCallReg
    46     // BaselineTailCallReg will always be unused in the contexts where ICs are called.
    47     masm.call(Operand(BaselineStubReg, ICStub::offsetOfStubCode()));
    48 }
    50 inline void
    51 EmitEnterTypeMonitorIC(MacroAssembler &masm,
    52                        size_t monitorStubOffset = ICMonitoredStub::offsetOfFirstMonitorStub())
    53 {
    54     // This is expected to be called from within an IC, when BaselineStubReg
    55     // is properly initialized to point to the stub.
    56     masm.loadPtr(Address(BaselineStubReg, (int32_t) monitorStubOffset), BaselineStubReg);
    58     // Jump to the stubcode.
    59     masm.jmp(Operand(BaselineStubReg, (int32_t) ICStub::offsetOfStubCode()));
    60 }
    62 inline void
    63 EmitReturnFromIC(MacroAssembler &masm)
    64 {
    65     masm.ret();
    66 }
    68 inline void
    69 EmitChangeICReturnAddress(MacroAssembler &masm, Register reg)
    70 {
    71     masm.storePtr(reg, Address(StackPointer, 0));
    72 }
    74 inline void
    75 EmitTailCallVM(JitCode *target, MacroAssembler &masm, uint32_t argSize)
    76 {
    77     // We assume during this that R0 and R1 have been pushed.
    79     // Compute frame size.
    80     masm.movl(BaselineFrameReg, eax);
    81     masm.addl(Imm32(BaselineFrame::FramePointerOffset), eax);
    82     masm.subl(BaselineStackReg, eax);
    84     // Store frame size without VMFunction arguments for GC marking.
    85     masm.movl(eax, ebx);
    86     masm.subl(Imm32(argSize), ebx);
    87     masm.store32(ebx, Address(BaselineFrameReg, BaselineFrame::reverseOffsetOfFrameSize()));
    89     // Push frame descriptor and perform the tail call.
    90     masm.makeFrameDescriptor(eax, JitFrame_BaselineJS);
    91     masm.push(eax);
    92     masm.push(BaselineTailCallReg);
    93     masm.jmp(target);
    94 }
    96 inline void
    97 EmitCreateStubFrameDescriptor(MacroAssembler &masm, Register reg)
    98 {
    99     // Compute stub frame size. We have to add two pointers: the stub reg and previous
   100     // frame pointer pushed by EmitEnterStubFrame.
   101     masm.movl(BaselineFrameReg, reg);
   102     masm.addl(Imm32(sizeof(void *) * 2), reg);
   103     masm.subl(BaselineStackReg, reg);
   105     masm.makeFrameDescriptor(reg, JitFrame_BaselineStub);
   106 }
   108 inline void
   109 EmitCallVM(JitCode *target, MacroAssembler &masm)
   110 {
   111     EmitCreateStubFrameDescriptor(masm, eax);
   112     masm.push(eax);
   113     masm.call(target);
   114 }
   116 // Size of vales pushed by EmitEnterStubFrame.
   117 static const uint32_t STUB_FRAME_SIZE = 4 * sizeof(void *);
   118 static const uint32_t STUB_FRAME_SAVED_STUB_OFFSET = sizeof(void *);
   120 inline void
   121 EmitEnterStubFrame(MacroAssembler &masm, Register scratch)
   122 {
   123     JS_ASSERT(scratch != BaselineTailCallReg);
   125     EmitRestoreTailCallReg(masm);
   127     // Compute frame size.
   128     masm.movl(BaselineFrameReg, scratch);
   129     masm.addl(Imm32(BaselineFrame::FramePointerOffset), scratch);
   130     masm.subl(BaselineStackReg, scratch);
   132     masm.store32(scratch, Address(BaselineFrameReg, BaselineFrame::reverseOffsetOfFrameSize()));
   134     // Note: when making changes here,  don't forget to update STUB_FRAME_SIZE
   135     // if needed.
   137     // Push frame descriptor and return address.
   138     masm.makeFrameDescriptor(scratch, JitFrame_BaselineJS);
   139     masm.push(scratch);
   140     masm.push(BaselineTailCallReg);
   142     // Save old frame pointer, stack pointer and stub reg.
   143     masm.push(BaselineStubReg);
   144     masm.push(BaselineFrameReg);
   145     masm.mov(BaselineStackReg, BaselineFrameReg);
   146 }
   148 inline void
   149 EmitLeaveStubFrameHead(MacroAssembler &masm, bool calledIntoIon = false)
   150 {
   151     // Ion frames do not save and restore the frame pointer. If we called
   152     // into Ion, we have to restore the stack pointer from the frame descriptor.
   153     // If we performed a VM call, the descriptor has been popped already so
   154     // in that case we use the frame pointer.
   155     if (calledIntoIon) {
   156         Register scratch = BaselineTailCallReg;
   157         masm.pop(scratch);
   158         masm.shrl(Imm32(FRAMESIZE_SHIFT), scratch);
   159         masm.addl(scratch, BaselineStackReg);
   160     } else {
   161         masm.mov(BaselineFrameReg, BaselineStackReg);
   162     }
   163 }
   165 inline void
   166 EmitLeaveStubFrameCommonTail(MacroAssembler &masm)
   167 {
   168     masm.pop(BaselineFrameReg);
   169     masm.pop(BaselineStubReg);
   171     // Pop return address.
   172     masm.pop(BaselineTailCallReg);
   174     // Overwrite frame descriptor with return address, so that the stack matches
   175     // the state before entering the stub frame.
   176     masm.storePtr(BaselineTailCallReg, Address(BaselineStackReg, 0));
   177 }
   179 inline void
   180 EmitLeaveStubFrame(MacroAssembler &masm, bool calledIntoIon = false)
   181 {
   182     EmitLeaveStubFrameHead(masm, calledIntoIon);
   183     EmitLeaveStubFrameCommonTail(masm);
   184 }
   186 inline void
   187 EmitStowICValues(MacroAssembler &masm, int values)
   188 {
   189     JS_ASSERT(values >= 0 && values <= 2);
   190     switch(values) {
   191       case 1:
   192         // Stow R0
   193         masm.pop(BaselineTailCallReg);
   194         masm.pushValue(R0);
   195         masm.push(BaselineTailCallReg);
   196         break;
   197       case 2:
   198         // Stow R0 and R1
   199         masm.pop(BaselineTailCallReg);
   200         masm.pushValue(R0);
   201         masm.pushValue(R1);
   202         masm.push(BaselineTailCallReg);
   203         break;
   204     }
   205 }
   207 inline void
   208 EmitUnstowICValues(MacroAssembler &masm, int values, bool discard = false)
   209 {
   210     JS_ASSERT(values >= 0 && values <= 2);
   211     switch(values) {
   212       case 1:
   213         // Unstow R0
   214         masm.pop(BaselineTailCallReg);
   215         if (discard)
   216             masm.addPtr(Imm32(sizeof(Value)), BaselineStackReg);
   217         else
   218             masm.popValue(R0);
   219         masm.push(BaselineTailCallReg);
   220         break;
   221       case 2:
   222         // Unstow R0 and R1
   223         masm.pop(BaselineTailCallReg);
   224         if (discard) {
   225             masm.addPtr(Imm32(sizeof(Value) * 2), BaselineStackReg);
   226         } else {
   227             masm.popValue(R1);
   228             masm.popValue(R0);
   229         }
   230         masm.push(BaselineTailCallReg);
   231         break;
   232     }
   233 }
   235 inline void
   236 EmitCallTypeUpdateIC(MacroAssembler &masm, JitCode *code, uint32_t objectOffset)
   237 {
   238     // R0 contains the value that needs to be typechecked.
   239     // The object we're updating is a boxed Value on the stack, at offset
   240     // objectOffset from stack top, excluding the return address.
   242     // Save the current BaselineStubReg to stack
   243     masm.push(BaselineStubReg);
   245     // This is expected to be called from within an IC, when BaselineStubReg
   246     // is properly initialized to point to the stub.
   247     masm.loadPtr(Address(BaselineStubReg, (int32_t) ICUpdatedStub::offsetOfFirstUpdateStub()),
   248                  BaselineStubReg);
   250     // Call the stubcode.
   251     masm.call(Operand(BaselineStubReg, ICStub::offsetOfStubCode()));
   253     // Restore the old stub reg.
   254     masm.pop(BaselineStubReg);
   256     // The update IC will store 0 or 1 in R1.scratchReg() reflecting if the
   257     // value in R0 type-checked properly or not.
   258     Label success;
   259     masm.cmp32(R1.scratchReg(), Imm32(1));
   260     masm.j(Assembler::Equal, &success);
   262     // If the IC failed, then call the update fallback function.
   263     EmitEnterStubFrame(masm, R1.scratchReg());
   265     masm.loadValue(Address(BaselineStackReg, STUB_FRAME_SIZE + objectOffset), R1);
   267     masm.pushValue(R0);
   268     masm.pushValue(R1);
   269     masm.push(BaselineStubReg);
   271     // Load previous frame pointer, push BaselineFrame *.
   272     masm.loadPtr(Address(BaselineFrameReg, 0), R0.scratchReg());
   273     masm.pushBaselineFramePtr(R0.scratchReg(), R0.scratchReg());
   275     EmitCallVM(code, masm);
   276     EmitLeaveStubFrame(masm);
   278     // Success at end.
   279     masm.bind(&success);
   280 }
   282 template <typename AddrType>
   283 inline void
   284 EmitPreBarrier(MacroAssembler &masm, const AddrType &addr, MIRType type)
   285 {
   286     masm.patchableCallPreBarrier(addr, type);
   287 }
   289 inline void
   290 EmitStubGuardFailure(MacroAssembler &masm)
   291 {
   292     // NOTE: This routine assumes that the stub guard code left the stack in the
   293     // same state it was in when it was entered.
   295     // BaselineStubEntry points to the current stub.
   297     // Load next stub into BaselineStubReg
   298     masm.loadPtr(Address(BaselineStubReg, (int32_t) ICStub::offsetOfNext()), BaselineStubReg);
   300     // Return address is already loaded, just jump to the next stubcode.
   301     masm.jmp(Operand(BaselineStubReg, (int32_t) ICStub::offsetOfStubCode()));
   302 }
   305 } // namespace jit
   306 } // namespace js
   308 #endif // JS_ION
   310 #endif /* jit_x86_BaselineHelpers_x86_h */

mercurial