]> git.saurik.com Git - apple/javascriptcore.git/blame_incremental - jit/JITCall.cpp
JavaScriptCore-1097.13.tar.gz
[apple/javascriptcore.git] / jit / JITCall.cpp
... / ...
CommitLineData
1/*
2 * Copyright (C) 2008 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
28#if ENABLE(JIT)
29#if USE(JSVALUE64)
30#include "JIT.h"
31
32#include "Arguments.h"
33#include "CodeBlock.h"
34#include "JITInlineMethods.h"
35#include "JITStubCall.h"
36#include "JSArray.h"
37#include "JSFunction.h"
38#include "Interpreter.h"
39#include "ResultType.h"
40#include "SamplingTool.h"
41
42#ifndef NDEBUG
43#include <stdio.h>
44#endif
45
46using namespace std;
47
48namespace JSC {
49
50void JIT::emit_op_call_put_result(Instruction* instruction)
51{
52 int dst = instruction[1].u.operand;
53 emitValueProfilingSite();
54 emitPutVirtualRegister(dst);
55 if (canBeOptimized())
56 killLastResultRegister(); // Make lastResultRegister tracking simpler in the DFG.
57}
58
59void JIT::compileLoadVarargs(Instruction* instruction)
60{
61 int thisValue = instruction[2].u.operand;
62 int arguments = instruction[3].u.operand;
63 int firstFreeRegister = instruction[4].u.operand;
64
65 killLastResultRegister();
66
67 JumpList slowCase;
68 JumpList end;
69 if (m_codeBlock->usesArguments() && arguments == m_codeBlock->argumentsRegister()) {
70 emitGetVirtualRegister(arguments, regT0);
71 slowCase.append(branchPtr(NotEqual, regT0, TrustedImmPtr(JSValue::encode(JSValue()))));
72
73 emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount, regT0);
74 slowCase.append(branch32(Above, regT0, TrustedImm32(Arguments::MaxArguments + 1)));
75 // regT0: argumentCountIncludingThis
76
77 move(regT0, regT1);
78 add32(TrustedImm32(firstFreeRegister + RegisterFile::CallFrameHeaderSize), regT1);
79 lshift32(TrustedImm32(3), regT1);
80 addPtr(callFrameRegister, regT1);
81 // regT1: newCallFrame
82
83 slowCase.append(branchPtr(Below, AbsoluteAddress(m_globalData->interpreter->registerFile().addressOfEnd()), regT1));
84
85 // Initialize ArgumentCount.
86 store32(regT0, Address(regT1, RegisterFile::ArgumentCount * static_cast<int>(sizeof(Register)) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)));
87
88 // Initialize 'this'.
89 emitGetVirtualRegister(thisValue, regT2);
90 storePtr(regT2, Address(regT1, CallFrame::thisArgumentOffset() * static_cast<int>(sizeof(Register))));
91
92 // Copy arguments.
93 neg32(regT0);
94 signExtend32ToPtr(regT0, regT0);
95 end.append(branchAddPtr(Zero, TrustedImm32(1), regT0));
96 // regT0: -argumentCount
97
98 Label copyLoop = label();
99 loadPtr(BaseIndex(callFrameRegister, regT0, TimesEight, CallFrame::thisArgumentOffset() * static_cast<int>(sizeof(Register))), regT2);
100 storePtr(regT2, BaseIndex(regT1, regT0, TimesEight, CallFrame::thisArgumentOffset() * static_cast<int>(sizeof(Register))));
101 branchAddPtr(NonZero, TrustedImm32(1), regT0).linkTo(copyLoop, this);
102
103 end.append(jump());
104 }
105
106 if (m_codeBlock->usesArguments() && arguments == m_codeBlock->argumentsRegister())
107 slowCase.link(this);
108
109 JITStubCall stubCall(this, cti_op_load_varargs);
110 stubCall.addArgument(thisValue, regT0);
111 stubCall.addArgument(arguments, regT0);
112 stubCall.addArgument(Imm32(firstFreeRegister));
113 stubCall.call(regT1);
114
115 if (m_codeBlock->usesArguments() && arguments == m_codeBlock->argumentsRegister())
116 end.link(this);
117}
118
119void JIT::compileCallEval()
120{
121 JITStubCall stubCall(this, cti_op_call_eval); // Initializes ScopeChain; ReturnPC; CodeBlock.
122 stubCall.call();
123 addSlowCase(branchPtr(Equal, regT0, TrustedImmPtr(JSValue::encode(JSValue()))));
124 emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, callFrameRegister);
125
126 sampleCodeBlock(m_codeBlock);
127}
128
129void JIT::compileCallEvalSlowCase(Vector<SlowCaseEntry>::iterator& iter)
130{
131 linkSlowCase(iter);
132
133 emitGetFromCallFrameHeaderPtr(RegisterFile::Callee, regT0);
134 emitNakedCall(m_globalData->jitStubs->ctiVirtualCall());
135
136 sampleCodeBlock(m_codeBlock);
137}
138
139void JIT::compileOpCall(OpcodeID opcodeID, Instruction* instruction, unsigned callLinkInfoIndex)
140{
141 int callee = instruction[1].u.operand;
142
143 /* Caller always:
144 - Updates callFrameRegister to callee callFrame.
145 - Initializes ArgumentCount; CallerFrame; Callee.
146
147 For a JS call:
148 - Caller initializes ScopeChain.
149 - Callee initializes ReturnPC; CodeBlock.
150 - Callee restores callFrameRegister before return.
151
152 For a non-JS call:
153 - Caller initializes ScopeChain; ReturnPC; CodeBlock.
154 - Caller restores callFrameRegister after return.
155 */
156
157 if (opcodeID == op_call_varargs)
158 compileLoadVarargs(instruction);
159 else {
160 int argCount = instruction[2].u.operand;
161 int registerOffset = instruction[3].u.operand;
162
163 addPtr(TrustedImm32(registerOffset * sizeof(Register)), callFrameRegister, regT1);
164 store32(TrustedImm32(argCount), Address(regT1, RegisterFile::ArgumentCount * static_cast<int>(sizeof(Register)) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)));
165 } // regT1 holds newCallFrame with ArgumentCount initialized.
166
167 store32(TrustedImm32(instruction - m_codeBlock->instructions().begin()), Address(callFrameRegister, RegisterFile::ArgumentCount * static_cast<int>(sizeof(Register)) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)));
168 emitGetVirtualRegister(callee, regT0); // regT0 holds callee.
169
170 storePtr(callFrameRegister, Address(regT1, RegisterFile::CallerFrame * static_cast<int>(sizeof(Register))));
171 storePtr(regT0, Address(regT1, RegisterFile::Callee * static_cast<int>(sizeof(Register))));
172 move(regT1, callFrameRegister);
173
174 if (opcodeID == op_call_eval) {
175 compileCallEval();
176 return;
177 }
178
179 DataLabelPtr addressOfLinkedFunctionCheck;
180 BEGIN_UNINTERRUPTED_SEQUENCE(sequenceOpCall);
181 Jump slowCase = branchPtrWithPatch(NotEqual, regT0, addressOfLinkedFunctionCheck, TrustedImmPtr(JSValue::encode(JSValue())));
182 END_UNINTERRUPTED_SEQUENCE(sequenceOpCall);
183 addSlowCase(slowCase);
184
185 ASSERT(m_callStructureStubCompilationInfo.size() == callLinkInfoIndex);
186 m_callStructureStubCompilationInfo.append(StructureStubCompilationInfo());
187 m_callStructureStubCompilationInfo[callLinkInfoIndex].hotPathBegin = addressOfLinkedFunctionCheck;
188 m_callStructureStubCompilationInfo[callLinkInfoIndex].callType = CallLinkInfo::callTypeFor(opcodeID);
189 m_callStructureStubCompilationInfo[callLinkInfoIndex].bytecodeIndex = m_bytecodeOffset;
190
191 loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_scopeChain)), regT1);
192 emitPutToCallFrameHeader(regT1, RegisterFile::ScopeChain);
193 m_callStructureStubCompilationInfo[callLinkInfoIndex].hotPathOther = emitNakedCall();
194
195 sampleCodeBlock(m_codeBlock);
196}
197
198void JIT::compileOpCallSlowCase(OpcodeID opcodeID, Instruction*, Vector<SlowCaseEntry>::iterator& iter, unsigned callLinkInfoIndex)
199{
200 if (opcodeID == op_call_eval) {
201 compileCallEvalSlowCase(iter);
202 return;
203 }
204
205 linkSlowCase(iter);
206
207 m_callStructureStubCompilationInfo[callLinkInfoIndex].callReturnLocation = emitNakedCall(opcodeID == op_construct ? m_globalData->jitStubs->ctiVirtualConstructLink() : m_globalData->jitStubs->ctiVirtualCallLink());
208
209 sampleCodeBlock(m_codeBlock);
210}
211
212} // namespace JSC
213
214#endif // USE(JSVALUE64)
215#endif // ENABLE(JIT)