]> git.saurik.com Git - apple/javascriptcore.git/blame - ftl/FTLSlowPathCall.cpp
JavaScriptCore-7601.1.46.3.tar.gz
[apple/javascriptcore.git] / ftl / FTLSlowPathCall.cpp
CommitLineData
81345200
A
1/*
2 * Copyright (C) 2013, 2014 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "config.h"
27#include "FTLSlowPathCall.h"
28
29#if ENABLE(FTL_JIT)
30
31#include "CCallHelpers.h"
32#include "FTLState.h"
33#include "GPRInfo.h"
34#include "JSCInlines.h"
35
36namespace JSC { namespace FTL {
37
38namespace {
39
40// This code relies on us being 64-bit. FTL is currently always 64-bit.
41static const size_t wordSize = 8;
42
43// This will be an RAII thingy that will set up the necessary stack sizes and offsets and such.
44class CallContext {
45public:
46 CallContext(
47 State& state, const RegisterSet& usedRegisters, CCallHelpers& jit,
48 unsigned numArgs, GPRReg returnRegister)
49 : m_state(state)
50 , m_usedRegisters(usedRegisters)
51 , m_jit(jit)
52 , m_numArgs(numArgs)
53 , m_returnRegister(returnRegister)
54 {
55 // We don't care that you're using callee-save, stack, or hardware registers.
56 m_usedRegisters.exclude(RegisterSet::stackRegisters());
57 m_usedRegisters.exclude(RegisterSet::reservedHardwareRegisters());
58 m_usedRegisters.exclude(RegisterSet::calleeSaveRegisters());
59
60 // The return register doesn't need to be saved.
61 if (m_returnRegister != InvalidGPRReg)
62 m_usedRegisters.clear(m_returnRegister);
63
64 size_t stackBytesNeededForReturnAddress = wordSize;
65
66 m_offsetToSavingArea =
67 (std::max(m_numArgs, NUMBER_OF_ARGUMENT_REGISTERS) - NUMBER_OF_ARGUMENT_REGISTERS) * wordSize;
68
69 for (unsigned i = std::min(NUMBER_OF_ARGUMENT_REGISTERS, numArgs); i--;)
70 m_argumentRegisters.set(GPRInfo::toArgumentRegister(i));
71 m_callingConventionRegisters.merge(m_argumentRegisters);
72 if (returnRegister != InvalidGPRReg)
73 m_callingConventionRegisters.set(GPRInfo::returnValueGPR);
74 m_callingConventionRegisters.filter(m_usedRegisters);
75
76 unsigned numberOfCallingConventionRegisters =
77 m_callingConventionRegisters.numberOfSetRegisters();
78
79 size_t offsetToThunkSavingArea =
80 m_offsetToSavingArea +
81 numberOfCallingConventionRegisters * wordSize;
82
83 m_stackBytesNeeded =
84 offsetToThunkSavingArea +
85 stackBytesNeededForReturnAddress +
86 (m_usedRegisters.numberOfSetRegisters() - numberOfCallingConventionRegisters) * wordSize;
87
88 m_stackBytesNeeded = (m_stackBytesNeeded + stackAlignmentBytes() - 1) & ~(stackAlignmentBytes() - 1);
89
90 m_jit.subPtr(CCallHelpers::TrustedImm32(m_stackBytesNeeded), CCallHelpers::stackPointerRegister);
91
92 m_thunkSaveSet = m_usedRegisters;
93
94 // This relies on all calling convention registers also being temp registers.
95 unsigned stackIndex = 0;
96 for (unsigned i = GPRInfo::numberOfRegisters; i--;) {
97 GPRReg reg = GPRInfo::toRegister(i);
98 if (!m_callingConventionRegisters.get(reg))
99 continue;
100 m_jit.storePtr(reg, CCallHelpers::Address(CCallHelpers::stackPointerRegister, m_offsetToSavingArea + (stackIndex++) * wordSize));
101 m_thunkSaveSet.clear(reg);
102 }
103
104 m_offset = offsetToThunkSavingArea;
105 }
106
107 ~CallContext()
108 {
109 if (m_returnRegister != InvalidGPRReg)
110 m_jit.move(GPRInfo::returnValueGPR, m_returnRegister);
111
112 unsigned stackIndex = 0;
113 for (unsigned i = GPRInfo::numberOfRegisters; i--;) {
114 GPRReg reg = GPRInfo::toRegister(i);
115 if (!m_callingConventionRegisters.get(reg))
116 continue;
117 m_jit.loadPtr(CCallHelpers::Address(CCallHelpers::stackPointerRegister, m_offsetToSavingArea + (stackIndex++) * wordSize), reg);
118 }
119
120 m_jit.addPtr(CCallHelpers::TrustedImm32(m_stackBytesNeeded), CCallHelpers::stackPointerRegister);
121 }
122
123 RegisterSet usedRegisters() const
124 {
125 return m_thunkSaveSet;
126 }
127
128 ptrdiff_t offset() const
129 {
130 return m_offset;
131 }
132
133 SlowPathCallKey keyWithTarget(void* callTarget) const
134 {
135 return SlowPathCallKey(usedRegisters(), callTarget, m_argumentRegisters, offset());
136 }
137
138 MacroAssembler::Call makeCall(void* callTarget, MacroAssembler::JumpList* exceptionTarget)
139 {
140 MacroAssembler::Call result = m_jit.call();
141 m_state.finalizer->slowPathCalls.append(SlowPathCall(
142 result, keyWithTarget(callTarget)));
143 if (exceptionTarget)
144 exceptionTarget->append(m_jit.emitExceptionCheck());
145 return result;
146 }
147
148private:
149 State& m_state;
150 RegisterSet m_usedRegisters;
151 RegisterSet m_argumentRegisters;
152 RegisterSet m_callingConventionRegisters;
153 CCallHelpers& m_jit;
154 unsigned m_numArgs;
155 GPRReg m_returnRegister;
156 size_t m_offsetToSavingArea;
157 size_t m_stackBytesNeeded;
158 RegisterSet m_thunkSaveSet;
159 ptrdiff_t m_offset;
160};
161
162} // anonymous namespace
163
164void storeCodeOrigin(State& state, CCallHelpers& jit, CodeOrigin codeOrigin)
165{
166 if (!codeOrigin.isSet())
167 return;
168
169 unsigned index = state.jitCode->common.addCodeOrigin(codeOrigin);
170 unsigned locationBits = CallFrame::Location::encodeAsCodeOriginIndex(index);
171 jit.store32(
172 CCallHelpers::TrustedImm32(locationBits),
173 CCallHelpers::tagFor(static_cast<VirtualRegister>(JSStack::ArgumentCount)));
174}
175
ed1e77d3
A
176MacroAssembler::Call callOperation(
177 State& state, const RegisterSet& usedRegisters, CCallHelpers& jit,
178 CodeOrigin codeOrigin, MacroAssembler::JumpList* exceptionTarget,
179 J_JITOperation_ESsiCI operation, GPRReg result, StructureStubInfo* stubInfo,
180 GPRReg object, const UniquedStringImpl* uid)
181{
182 storeCodeOrigin(state, jit, codeOrigin);
183 CallContext context(state, usedRegisters, jit, 4, result);
184 jit.setupArgumentsWithExecState(
185 CCallHelpers::TrustedImmPtr(stubInfo), object, CCallHelpers::TrustedImmPtr(uid));
186 return context.makeCall(bitwise_cast<void*>(operation), exceptionTarget);
187}
188
81345200
A
189MacroAssembler::Call callOperation(
190 State& state, const RegisterSet& usedRegisters, CCallHelpers& jit,
191 CodeOrigin codeOrigin, MacroAssembler::JumpList* exceptionTarget,
192 J_JITOperation_ESsiJI operation, GPRReg result, StructureStubInfo* stubInfo,
ed1e77d3 193 GPRReg object, UniquedStringImpl* uid)
81345200
A
194{
195 storeCodeOrigin(state, jit, codeOrigin);
196 CallContext context(state, usedRegisters, jit, 4, result);
197 jit.setupArgumentsWithExecState(
198 CCallHelpers::TrustedImmPtr(stubInfo), object,
199 CCallHelpers::TrustedImmPtr(uid));
200 return context.makeCall(bitwise_cast<void*>(operation), exceptionTarget);
201}
202
203MacroAssembler::Call callOperation(
204 State& state, const RegisterSet& usedRegisters, CCallHelpers& jit,
205 CodeOrigin codeOrigin, MacroAssembler::JumpList* exceptionTarget,
206 V_JITOperation_ESsiJJI operation, StructureStubInfo* stubInfo, GPRReg value,
ed1e77d3 207 GPRReg object, UniquedStringImpl* uid)
81345200
A
208{
209 storeCodeOrigin(state, jit, codeOrigin);
210 CallContext context(state, usedRegisters, jit, 5, InvalidGPRReg);
211 jit.setupArgumentsWithExecState(
212 CCallHelpers::TrustedImmPtr(stubInfo), value, object,
213 CCallHelpers::TrustedImmPtr(uid));
214 return context.makeCall(bitwise_cast<void*>(operation), exceptionTarget);
215}
216
217} } // namespace JSC::FTL
218
219#endif // ENABLE(FTL_JIT)
220