Wed, 31 Dec 2014 06:09:35 +0100
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 #include "jit/shared/BaselineCompiler-shared.h"
9 #include "jit/BaselineIC.h"
10 #include "jit/VMFunctions.h"
12 using namespace js;
13 using namespace js::jit;
15 BaselineCompilerShared::BaselineCompilerShared(JSContext *cx, TempAllocator &alloc, JSScript *script)
16 : cx(cx),
17 script(script),
18 pc(script->code()),
19 ionCompileable_(jit::IsIonEnabled(cx) && CanIonCompileScript(cx, script, false)),
20 ionOSRCompileable_(jit::IsIonEnabled(cx) && CanIonCompileScript(cx, script, true)),
21 debugMode_(cx->compartment()->debugMode()),
22 alloc_(alloc),
23 analysis_(alloc, script),
24 frame(script, masm),
25 stubSpace_(),
26 icEntries_(),
27 pcMappingEntries_(),
28 icLoadLabels_(),
29 pushedBeforeCall_(0),
30 inCall_(false),
31 spsPushToggleOffset_()
32 { }
34 bool
35 BaselineCompilerShared::callVM(const VMFunction &fun, CallVMPhase phase)
36 {
37 JitCode *code = cx->runtime()->jitRuntime()->getVMWrapper(fun);
38 if (!code)
39 return false;
41 #ifdef DEBUG
42 // Assert prepareVMCall() has been called.
43 JS_ASSERT(inCall_);
44 inCall_ = false;
45 #endif
47 // Compute argument size. Note that this include the size of the frame pointer
48 // pushed by prepareVMCall.
49 uint32_t argSize = fun.explicitStackSlots() * sizeof(void *) + sizeof(void *);
51 // Assert all arguments were pushed.
52 JS_ASSERT(masm.framePushed() - pushedBeforeCall_ == argSize);
54 Address frameSizeAddress(BaselineFrameReg, BaselineFrame::reverseOffsetOfFrameSize());
55 uint32_t frameVals = frame.nlocals() + frame.stackDepth();
56 uint32_t frameBaseSize = BaselineFrame::FramePointerOffset + BaselineFrame::Size();
57 uint32_t frameFullSize = frameBaseSize + (frameVals * sizeof(Value));
58 if (phase == POST_INITIALIZE) {
59 masm.store32(Imm32(frameFullSize), frameSizeAddress);
60 uint32_t descriptor = MakeFrameDescriptor(frameFullSize + argSize, JitFrame_BaselineJS);
61 masm.push(Imm32(descriptor));
63 } else if (phase == PRE_INITIALIZE) {
64 masm.store32(Imm32(frameBaseSize), frameSizeAddress);
65 uint32_t descriptor = MakeFrameDescriptor(frameBaseSize + argSize, JitFrame_BaselineJS);
66 masm.push(Imm32(descriptor));
68 } else {
69 JS_ASSERT(phase == CHECK_OVER_RECURSED);
70 Label afterWrite;
71 Label writePostInitialize;
73 // If OVER_RECURSED is set, then frame locals haven't been pushed yet.
74 masm.branchTest32(Assembler::Zero,
75 frame.addressOfFlags(),
76 Imm32(BaselineFrame::OVER_RECURSED),
77 &writePostInitialize);
79 masm.move32(Imm32(frameBaseSize), BaselineTailCallReg);
80 masm.jump(&afterWrite);
82 masm.bind(&writePostInitialize);
83 masm.move32(Imm32(frameFullSize), BaselineTailCallReg);
85 masm.bind(&afterWrite);
86 masm.store32(BaselineTailCallReg, frameSizeAddress);
87 masm.add32(Imm32(argSize), BaselineTailCallReg);
88 masm.makeFrameDescriptor(BaselineTailCallReg, JitFrame_BaselineJS);
89 masm.push(BaselineTailCallReg);
90 }
92 // Perform the call.
93 masm.call(code);
94 uint32_t callOffset = masm.currentOffset();
95 masm.pop(BaselineFrameReg);
97 // Add a fake ICEntry (without stubs), so that the return offset to
98 // pc mapping works.
99 ICEntry entry(script->pcToOffset(pc), ICEntry::Kind_CallVM);
100 entry.setReturnOffset(callOffset);
102 return icEntries_.append(entry);
103 }