LCOV - code coverage report
Current view: top level - js/src/jit/x64 - SharedICHelpers-x64.h (source / functions) Hit Total Coverage
Test: output.info Lines: 75 85 88.2 %
Date: 2017-07-14 16:53:18 Functions: 14 15 93.3 %
Legend: Lines: hit not hit

          Line data    Source code
       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/. */
       6             : 
       7             : #ifndef jit_x64_SharedICHelpers_x64_h
       8             : #define jit_x64_SharedICHelpers_x64_h
       9             : 
      10             : #include "jit/BaselineFrame.h"
      11             : #include "jit/BaselineIC.h"
      12             : #include "jit/MacroAssembler.h"
      13             : #include "jit/SharedICRegisters.h"
      14             : 
      15             : namespace js {
      16             : namespace jit {
      17             : 
      18             : // Distance from Stack top to the top Value inside an IC stub (this is the return address).
      19             : static const size_t ICStackValueOffset = sizeof(void*);
      20             : 
      21             : inline void
      22         848 : EmitRestoreTailCallReg(MacroAssembler& masm)
      23             : {
      24         848 :     masm.Pop(ICTailCallReg);
      25         848 : }
      26             : 
      27             : inline void
      28             : EmitRepushTailCallReg(MacroAssembler& masm)
      29             : {
      30             :     masm.Push(ICTailCallReg);
      31             : }
      32             : 
      33             : inline void
      34       19345 : EmitCallIC(CodeOffset* patchOffset, MacroAssembler& masm)
      35             : {
      36             :     // Move ICEntry offset into ICStubReg
      37       19345 :     CodeOffset offset = masm.movWithPatch(ImmWord(-1), ICStubReg);
      38       19345 :     *patchOffset = offset;
      39             : 
      40             :     // Load stub pointer into ICStubReg
      41       38690 :     masm.loadPtr(Address(ICStubReg, (int32_t) ICEntry::offsetOfFirstStub()),
      42       19345 :                  ICStubReg);
      43             : 
      44             :     // Call the stubcode.
      45       19345 :     masm.call(Address(ICStubReg, ICStub::offsetOfStubCode()));
      46       19345 : }
      47             : 
      48             : inline void
      49         409 : EmitEnterTypeMonitorIC(MacroAssembler& masm,
      50             :                        size_t monitorStubOffset = ICMonitoredStub::offsetOfFirstMonitorStub())
      51             : {
      52             :     // This is expected to be called from within an IC, when ICStubReg
      53             :     // is properly initialized to point to the stub.
      54         409 :     masm.loadPtr(Address(ICStubReg, (int32_t) monitorStubOffset), ICStubReg);
      55             : 
      56             :     // Jump to the stubcode.
      57         409 :     masm.jmp(Operand(ICStubReg, (int32_t) ICStub::offsetOfStubCode()));
      58         409 : }
      59             : 
      60             : inline void
      61        2114 : EmitReturnFromIC(MacroAssembler& masm)
      62             : {
      63        2114 :     masm.ret();
      64        2114 : }
      65             : 
      66             : inline void
      67          18 : EmitChangeICReturnAddress(MacroAssembler& masm, Register reg)
      68             : {
      69          18 :     masm.storePtr(reg, Address(StackPointer, 0));
      70          18 : }
      71             : 
      72             : inline void
      73         848 : EmitBaselineTailCallVM(JitCode* target, MacroAssembler& masm, uint32_t argSize)
      74             : {
      75        1696 :     ScratchRegisterScope scratch(masm);
      76             : 
      77             :     // We an assume during this that R0 and R1 have been pushed.
      78         848 :     masm.movq(BaselineFrameReg, scratch);
      79         848 :     masm.addq(Imm32(BaselineFrame::FramePointerOffset), scratch);
      80         848 :     masm.subq(BaselineStackReg, scratch);
      81             : 
      82             :     // Store frame size without VMFunction arguments for GC marking.
      83         848 :     masm.movq(scratch, rdx);
      84         848 :     masm.subq(Imm32(argSize), rdx);
      85         848 :     masm.store32(rdx, Address(BaselineFrameReg, BaselineFrame::reverseOffsetOfFrameSize()));
      86             : 
      87             :     // Push frame descriptor and perform the tail call.
      88         848 :     masm.makeFrameDescriptor(scratch, JitFrame_BaselineJS, ExitFrameLayout::Size());
      89         848 :     masm.push(scratch);
      90         848 :     masm.push(ICTailCallReg);
      91         848 :     masm.jmp(target);
      92         848 : }
      93             : 
      94             : inline void
      95           0 : EmitIonTailCallVM(JitCode* target, MacroAssembler& masm, uint32_t stackSize)
      96             : {
      97             :     // For tail calls, find the already pushed JitFrame_IonJS signifying the
      98             :     // end of the Ion frame. Retrieve the length of the frame and repush
      99             :     // JitFrame_IonJS with the extra stacksize, rendering the original
     100             :     // JitFrame_IonJS obsolete.
     101             : 
     102           0 :     ScratchRegisterScope scratch(masm);
     103             : 
     104           0 :     masm.loadPtr(Address(esp, stackSize), scratch);
     105           0 :     masm.shrq(Imm32(FRAMESIZE_SHIFT), scratch);
     106           0 :     masm.addq(Imm32(stackSize + JitStubFrameLayout::Size() - sizeof(intptr_t)), scratch);
     107             : 
     108             :     // Push frame descriptor and perform the tail call.
     109           0 :     masm.makeFrameDescriptor(scratch, JitFrame_IonJS, ExitFrameLayout::Size());
     110           0 :     masm.push(scratch);
     111           0 :     masm.push(ICTailCallReg);
     112           0 :     masm.jmp(target);
     113           0 : }
     114             : 
     115             : inline void
     116         387 : EmitBaselineCreateStubFrameDescriptor(MacroAssembler& masm, Register reg, uint32_t headerSize)
     117             : {
     118             :     // Compute stub frame size. We have to add two pointers: the stub reg and previous
     119             :     // frame pointer pushed by EmitEnterStubFrame.
     120         387 :     masm.movq(BaselineFrameReg, reg);
     121         387 :     masm.addq(Imm32(sizeof(void*) * 2), reg);
     122         387 :     masm.subq(BaselineStackReg, reg);
     123             : 
     124         387 :     masm.makeFrameDescriptor(reg, JitFrame_BaselineStub, headerSize);
     125         387 : }
     126             : 
     127             : inline void
     128         246 : EmitBaselineCallVM(JitCode* target, MacroAssembler& masm)
     129             : {
     130         492 :     ScratchRegisterScope scratch(masm);
     131         246 :     EmitBaselineCreateStubFrameDescriptor(masm, scratch, ExitFrameLayout::Size());
     132         246 :     masm.push(scratch);
     133         246 :     masm.call(target);
     134         246 : }
     135             : 
     136             : // Size of vales pushed by EmitEnterStubFrame.
     137             : static const uint32_t STUB_FRAME_SIZE = 4 * sizeof(void*);
     138             : static const uint32_t STUB_FRAME_SAVED_STUB_OFFSET = sizeof(void*);
     139             : 
     140             : inline void
     141         385 : EmitBaselineEnterStubFrame(MacroAssembler& masm, Register)
     142             : {
     143         770 :     ScratchRegisterScope scratch(masm);
     144             : 
     145             :     // Compute frame size. Because the return address is still on the stack,
     146             :     // this is:
     147             :     //
     148             :     //   BaselineFrameReg
     149             :     //   + BaselineFrame::FramePointerOffset
     150             :     //   - BaselineStackReg
     151             :     //   - sizeof(return address)
     152             :     //
     153             :     // The two constants cancel each other out, so we can just calculate
     154             :     // BaselineFrameReg - BaselineStackReg.
     155             : 
     156             :     static_assert(BaselineFrame::FramePointerOffset == sizeof(void*),
     157             :                   "FramePointerOffset must be the same as the return address size");
     158             : 
     159         385 :     masm.movq(BaselineFrameReg, scratch);
     160         385 :     masm.subq(BaselineStackReg, scratch);
     161             : 
     162         385 :     masm.store32(scratch, Address(BaselineFrameReg, BaselineFrame::reverseOffsetOfFrameSize()));
     163             : 
     164             :     // Note: when making changes here,  don't forget to update STUB_FRAME_SIZE
     165             :     // if needed.
     166             : 
     167             :     // Push the return address that's currently on top of the stack.
     168         385 :     masm.Push(Operand(BaselineStackReg, 0));
     169             : 
     170             :     // Replace the original return address with the frame descriptor.
     171         385 :     masm.makeFrameDescriptor(scratch, JitFrame_BaselineJS, BaselineStubFrameLayout::Size());
     172         385 :     masm.storePtr(scratch, Address(BaselineStackReg, sizeof(uintptr_t)));
     173             : 
     174             :     // Save old frame pointer, stack pointer and stub reg.
     175         385 :     masm.Push(ICStubReg);
     176         385 :     masm.Push(BaselineFrameReg);
     177         385 :     masm.mov(BaselineStackReg, BaselineFrameReg);
     178         385 : }
     179             : 
     180             : inline void
     181         665 : EmitBaselineLeaveStubFrame(MacroAssembler& masm, bool calledIntoIon = false)
     182             : {
     183             :     // Ion frames do not save and restore the frame pointer. If we called
     184             :     // into Ion, we have to restore the stack pointer from the frame descriptor.
     185             :     // If we performed a VM call, the descriptor has been popped already so
     186             :     // in that case we use the frame pointer.
     187         665 :     if (calledIntoIon) {
     188         582 :         ScratchRegisterScope scratch(masm);
     189         291 :         masm.Pop(scratch);
     190         291 :         masm.shrq(Imm32(FRAMESIZE_SHIFT), scratch);
     191         291 :         masm.addq(scratch, BaselineStackReg);
     192             :     } else {
     193         374 :         masm.mov(BaselineFrameReg, BaselineStackReg);
     194             :     }
     195             : 
     196         665 :     masm.Pop(BaselineFrameReg);
     197         665 :     masm.Pop(ICStubReg);
     198             : 
     199             :     // The return address is on top of the stack, followed by the frame
     200             :     // descriptor. Use a pop instruction to overwrite the frame descriptor
     201             :     // with the return address. Note that pop increments the stack pointer
     202             :     // before computing the address.
     203         665 :     masm.Pop(Operand(BaselineStackReg, 0));
     204         665 : }
     205             : 
     206             : inline void
     207             : EmitStowICValues(MacroAssembler& masm, int values)
     208             : {
     209             :     MOZ_ASSERT(values >= 0 && values <= 2);
     210             :     switch(values) {
     211             :       case 1:
     212             :         // Stow R0
     213             :         masm.pop(ICTailCallReg);
     214             :         masm.Push(R0);
     215             :         masm.push(ICTailCallReg);
     216             :         break;
     217             :       case 2:
     218             :         // Stow R0 and R1
     219             :         masm.pop(ICTailCallReg);
     220             :         masm.Push(R0);
     221             :         masm.Push(R1);
     222             :         masm.push(ICTailCallReg);
     223             :         break;
     224             :     }
     225             : }
     226             : 
     227             : inline void
     228             : EmitUnstowICValues(MacroAssembler& masm, int values, bool discard = false)
     229             : {
     230             :     MOZ_ASSERT(values >= 0 && values <= 2);
     231             :     switch(values) {
     232             :       case 1:
     233             :         // Unstow R0
     234             :         masm.pop(ICTailCallReg);
     235             :         if (discard)
     236             :             masm.addPtr(Imm32(sizeof(Value)), BaselineStackReg);
     237             :         else
     238             :             masm.popValue(R0);
     239             :         masm.push(ICTailCallReg);
     240             :         break;
     241             :       case 2:
     242             :         // Unstow R0 and R1
     243             :         masm.pop(ICTailCallReg);
     244             :         if (discard) {
     245             :             masm.addPtr(Imm32(sizeof(Value) * 2), BaselineStackReg);
     246             :         } else {
     247             :             masm.popValue(R1);
     248             :             masm.popValue(R0);
     249             :         }
     250             :         masm.push(ICTailCallReg);
     251             :         break;
     252             :     }
     253             :     masm.adjustFrame(-values * sizeof(Value));
     254             : }
     255             : 
     256             : template <typename AddrType>
     257             : inline void
     258          56 : EmitPreBarrier(MacroAssembler& masm, const AddrType& addr, MIRType type)
     259             : {
     260          56 :     masm.guardedCallPreBarrier(addr, type);
     261          56 : }
     262             : 
     263             : inline void
     264        1900 : EmitStubGuardFailure(MacroAssembler& masm)
     265             : {
     266             :     // Load next stub into ICStubReg
     267        1900 :     masm.loadPtr(Address(ICStubReg, ICStub::offsetOfNext()), ICStubReg);
     268             : 
     269             :     // Return address is already loaded, just jump to the next stubcode.
     270        1900 :     masm.jmp(Operand(ICStubReg, ICStub::offsetOfStubCode()));
     271        1900 : }
     272             : 
     273             : } // namespace jit
     274             : } // namespace js
     275             : 
     276             : #endif /* jit_x64_SharedICHelpers_x64_h */

Generated by: LCOV version 1.13