]> git.saurik.com Git - apple/javascriptcore.git/blame - jit/JITCall.cpp
JavaScriptCore-1097.13.tar.gz
[apple/javascriptcore.git] / jit / JITCall.cpp
CommitLineData
9dae56ea
A
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"
9dae56ea
A
27
28#if ENABLE(JIT)
14957cd0
A
29#if USE(JSVALUE64)
30#include "JIT.h"
9dae56ea 31
6fe7ccc8 32#include "Arguments.h"
9dae56ea
A
33#include "CodeBlock.h"
34#include "JITInlineMethods.h"
ba379fdc 35#include "JITStubCall.h"
9dae56ea
A
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
14957cd0 50void JIT::emit_op_call_put_result(Instruction* instruction)
ba379fdc
A
51{
52 int dst = instruction[1].u.operand;
6fe7ccc8 53 emitValueProfilingSite();
14957cd0 54 emitPutVirtualRegister(dst);
6fe7ccc8
A
55 if (canBeOptimized())
56 killLastResultRegister(); // Make lastResultRegister tracking simpler in the DFG.
9dae56ea
A
57}
58
6fe7ccc8 59void JIT::compileLoadVarargs(Instruction* instruction)
ba379fdc 60{
6fe7ccc8
A
61 int thisValue = instruction[2].u.operand;
62 int arguments = instruction[3].u.operand;
63 int firstFreeRegister = instruction[4].u.operand;
ba379fdc 64
6fe7ccc8 65 killLastResultRegister();
ba379fdc 66
6fe7ccc8
A
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()))));
14957cd0 72
6fe7ccc8
A
73 emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount, regT0);
74 slowCase.append(branch32(Above, regT0, TrustedImm32(Arguments::MaxArguments + 1)));
75 // regT0: argumentCountIncludingThis
9dae56ea 76
6fe7ccc8
A
77 move(regT0, regT1);
78 add32(TrustedImm32(firstFreeRegister + RegisterFile::CallFrameHeaderSize), regT1);
79 lshift32(TrustedImm32(3), regT1);
80 addPtr(callFrameRegister, regT1);
81 // regT1: newCallFrame
ba379fdc 82
6fe7ccc8 83 slowCase.append(branchPtr(Below, AbsoluteAddress(m_globalData->interpreter->registerFile().addressOfEnd()), regT1));
9dae56ea 84
6fe7ccc8
A
85 // Initialize ArgumentCount.
86 store32(regT0, Address(regT1, RegisterFile::ArgumentCount * static_cast<int>(sizeof(Register)) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)));
9dae56ea 87
6fe7ccc8
A
88 // Initialize 'this'.
89 emitGetVirtualRegister(thisValue, regT2);
90 storePtr(regT2, Address(regT1, CallFrame::thisArgumentOffset() * static_cast<int>(sizeof(Register))));
9dae56ea 91
6fe7ccc8
A
92 // Copy arguments.
93 neg32(regT0);
94 signExtend32ToPtr(regT0, regT0);
95 end.append(branchAddPtr(Zero, TrustedImm32(1), regT0));
96 // regT0: -argumentCount
9dae56ea 97
6fe7ccc8
A
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);
9dae56ea 102
6fe7ccc8
A
103 end.append(jump());
104 }
9dae56ea 105
6fe7ccc8
A
106 if (m_codeBlock->usesArguments() && arguments == m_codeBlock->argumentsRegister())
107 slowCase.link(this);
9dae56ea 108
6fe7ccc8
A
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);
9dae56ea
A
117}
118
6fe7ccc8 119void JIT::compileCallEval()
9dae56ea 120{
6fe7ccc8 121 JITStubCall stubCall(this, cti_op_call_eval); // Initializes ScopeChain; ReturnPC; CodeBlock.
14957cd0 122 stubCall.call();
6fe7ccc8
A
123 addSlowCase(branchPtr(Equal, regT0, TrustedImmPtr(JSValue::encode(JSValue()))));
124 emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, callFrameRegister);
9dae56ea
A
125
126 sampleCodeBlock(m_codeBlock);
127}
128
6fe7ccc8
A
129void JIT::compileCallEvalSlowCase(Vector<SlowCaseEntry>::iterator& iter)
130{
131 linkSlowCase(iter);
132
133 emitGetFromCallFrameHeaderPtr(RegisterFile::Callee, regT0);
134 emitNakedCall(m_globalData->jitStubs->ctiVirtualCall());
9dae56ea 135
6fe7ccc8
A
136 sampleCodeBlock(m_codeBlock);
137}
9dae56ea
A
138
139void JIT::compileOpCall(OpcodeID opcodeID, Instruction* instruction, unsigned callLinkInfoIndex)
140{
14957cd0 141 int callee = instruction[1].u.operand;
9dae56ea 142
6fe7ccc8
A
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
9dae56ea 174 if (opcodeID == op_call_eval) {
6fe7ccc8
A
175 compileCallEval();
176 return;
9dae56ea
A
177 }
178
9dae56ea 179 DataLabelPtr addressOfLinkedFunctionCheck;
f9bf01c6 180 BEGIN_UNINTERRUPTED_SEQUENCE(sequenceOpCall);
6fe7ccc8 181 Jump slowCase = branchPtrWithPatch(NotEqual, regT0, addressOfLinkedFunctionCheck, TrustedImmPtr(JSValue::encode(JSValue())));
f9bf01c6 182 END_UNINTERRUPTED_SEQUENCE(sequenceOpCall);
6fe7ccc8 183 addSlowCase(slowCase);
f9bf01c6 184
6fe7ccc8
A
185 ASSERT(m_callStructureStubCompilationInfo.size() == callLinkInfoIndex);
186 m_callStructureStubCompilationInfo.append(StructureStubCompilationInfo());
9dae56ea 187 m_callStructureStubCompilationInfo[callLinkInfoIndex].hotPathBegin = addressOfLinkedFunctionCheck;
6fe7ccc8
A
188 m_callStructureStubCompilationInfo[callLinkInfoIndex].callType = CallLinkInfo::callTypeFor(opcodeID);
189 m_callStructureStubCompilationInfo[callLinkInfoIndex].bytecodeIndex = m_bytecodeOffset;
9dae56ea 190
6fe7ccc8
A
191 loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_scopeChain)), regT1);
192 emitPutToCallFrameHeader(regT1, RegisterFile::ScopeChain);
ba379fdc 193 m_callStructureStubCompilationInfo[callLinkInfoIndex].hotPathOther = emitNakedCall();
9dae56ea 194
9dae56ea
A
195 sampleCodeBlock(m_codeBlock);
196}
197
6fe7ccc8 198void JIT::compileOpCallSlowCase(OpcodeID opcodeID, Instruction*, Vector<SlowCaseEntry>::iterator& iter, unsigned callLinkInfoIndex)
9dae56ea 199{
6fe7ccc8
A
200 if (opcodeID == op_call_eval) {
201 compileCallEvalSlowCase(iter);
202 return;
203 }
9dae56ea
A
204
205 linkSlowCase(iter);
6fe7ccc8 206
14957cd0 207 m_callStructureStubCompilationInfo[callLinkInfoIndex].callReturnLocation = emitNakedCall(opcodeID == op_construct ? m_globalData->jitStubs->ctiVirtualConstructLink() : m_globalData->jitStubs->ctiVirtualCallLink());
9dae56ea 208
9dae56ea
A
209 sampleCodeBlock(m_codeBlock);
210}
211
9dae56ea
A
212} // namespace JSC
213
14957cd0 214#endif // USE(JSVALUE64)
9dae56ea 215#endif // ENABLE(JIT)