blob: 77dc04ad1c1702b42b197e31bd28ddc2c113e42f [file] [log] [blame]
barraclough@apple.come367b002008-12-04 05:43:14 +00001/*
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"
barraclough@apple.come367b002008-12-04 05:43:14 +000027
28#if ENABLE(JIT)
oliver@apple.com0cc25c32010-10-19 23:55:08 +000029#if USE(JSVALUE64)
ggaren@apple.com7214b5a2010-05-21 20:52:30 +000030#include "JIT.h"
barraclough@apple.come367b002008-12-04 05:43:14 +000031
ggaren@apple.com539d1bb2011-11-14 19:21:40 +000032#include "Arguments.h"
barraclough@apple.come367b002008-12-04 05:43:14 +000033#include "CodeBlock.h"
34#include "JITInlineMethods.h"
ggaren@apple.com0e5741a2009-05-12 01:26:52 +000035#include "JITStubCall.h"
barraclough@apple.come367b002008-12-04 05:43:14 +000036#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
barraclough@apple.comc73ede72010-05-20 20:12:44 +000050void JIT::emit_op_call_put_result(Instruction* instruction)
ggaren@apple.com29496602009-05-12 04:20:29 +000051{
52 int dst = instruction[1].u.operand;
fpizlo@apple.com95a9f0d2011-08-20 02:17:49 +000053 emitValueProfilingSite(FirstProfilingSite);
barraclough@apple.comc73ede72010-05-20 20:12:44 +000054 emitPutVirtualRegister(dst);
55}
56
ggaren@apple.com539d1bb2011-11-14 19:21:40 +000057void JIT::compileLoadVarargs(Instruction* instruction)
barraclough@apple.comc73ede72010-05-20 20:12:44 +000058{
ggaren@apple.com539d1bb2011-11-14 19:21:40 +000059 int thisValue = instruction[2].u.operand;
60 int arguments = instruction[3].u.operand;
61 int firstFreeRegister = instruction[4].u.operand;
ggaren@apple.com29496602009-05-12 04:20:29 +000062
ggaren@apple.com539d1bb2011-11-14 19:21:40 +000063 killLastResultRegister();
ggaren@apple.com29496602009-05-12 04:20:29 +000064
ggaren@apple.com539d1bb2011-11-14 19:21:40 +000065 JumpList slowCase;
66 JumpList end;
67 if (m_codeBlock->usesArguments()
68 && arguments == m_codeBlock->argumentsRegister()
69 && m_codeBlock->m_numParameters == 1) {
70 emitGetVirtualRegister(arguments, regT0);
71 slowCase.append(branchPtr(NotEqual, regT0, TrustedImmPtr(JSValue::encode(JSValue()))));
barraclough@apple.com6f026ee2009-08-20 21:49:07 +000072
ggaren@apple.com539d1bb2011-11-14 19:21:40 +000073 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 emitFastArithReTagImmediate(regT0, regT2);
87 storePtr(regT2, Address(regT1, RegisterFile::ArgumentCount * static_cast<int>(sizeof(Register))));
88
89 // Initialize 'this' and copy arguments.
90 neg32(regT0);
91 signExtend32ToPtr(regT0, regT0);
92 emitGetVirtualRegister(thisValue, regT2);
93 storePtr(regT2, BaseIndex(regT1, regT0, TimesEight, -(RegisterFile::CallFrameHeaderSize * static_cast<int>(sizeof(Register)))));
94 end.append(branchAddPtr(Zero, Imm32(1), regT0));
95
96 Label copyLoop = label();
97 loadPtr(BaseIndex(callFrameRegister, regT0, TimesEight, -((RegisterFile::CallFrameHeaderSize + 1) * static_cast<int>(sizeof(Register)))), regT2);
98 storePtr(regT2, BaseIndex(regT1, regT0, TimesEight, -(RegisterFile::CallFrameHeaderSize * static_cast<int>(sizeof(Register)))));
99 branchAddPtr(NonZero, Imm32(1), regT0).linkTo(copyLoop, this);
100
101 end.append(jump());
102 }
103
104 if (m_codeBlock->m_numParameters == 1)
105 slowCase.link(this);
106
107 JITStubCall stubCall(this, cti_op_load_varargs);
108 stubCall.addArgument(thisValue, regT0);
109 stubCall.addArgument(arguments, regT0);
110 stubCall.addArgument(Imm32(firstFreeRegister));
111 stubCall.call(regT1);
112
113 if (m_codeBlock->m_numParameters == 1)
114 end.link(this);
115}
116
117void JIT::compileCallEval()
118{
119 JITStubCall stubCall(this, cti_op_call_eval); // Initializes ScopeChain; ReturnPC; CodeBlock.
120 stubCall.call();
121 addSlowCase(branchPtr(Equal, regT0, TrustedImmPtr(JSValue::encode(JSValue()))));
122 emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, callFrameRegister);
123
124 sampleCodeBlock(m_codeBlock);
125}
126
127void JIT::compileCallEvalSlowCase(Vector<SlowCaseEntry>::iterator& iter)
128{
129 linkSlowCase(iter);
130
131 emitGetFromCallFrameHeaderPtr(RegisterFile::Callee, regT0);
oliver@apple.com815b8e12010-07-15 04:30:13 +0000132 emitNakedCall(m_globalData->jitStubs->ctiVirtualCall());
ggaren@apple.com29496602009-05-12 04:20:29 +0000133
ggaren@apple.com29496602009-05-12 04:20:29 +0000134 sampleCodeBlock(m_codeBlock);
135}
136
barraclough@apple.com249befb2008-12-13 03:18:10 +0000137void JIT::compileOpCall(OpcodeID opcodeID, Instruction* instruction, unsigned callLinkInfoIndex)
barraclough@apple.come367b002008-12-04 05:43:14 +0000138{
barraclough@apple.comc73ede72010-05-20 20:12:44 +0000139 int callee = instruction[1].u.operand;
barraclough@apple.come367b002008-12-04 05:43:14 +0000140
ggaren@apple.com539d1bb2011-11-14 19:21:40 +0000141 /* Caller always:
142 - Updates callFrameRegister to callee callFrame.
143 - Initializes ArgumentCount; CallerFrame; Callee.
144
145 For a JS call:
146 - Caller initializes ScopeChain.
147 - Callee initializes ReturnPC; CodeBlock.
148 - Callee restores callFrameRegister before return.
149
150 For a non-JS call:
151 - Caller initializes ScopeChain; ReturnPC; CodeBlock.
152 - Caller restores callFrameRegister after return.
153 */
154
155 if (opcodeID == op_call_varargs)
156 compileLoadVarargs(instruction);
157 else {
158 int argCount = instruction[2].u.operand;
159 int registerOffset = instruction[3].u.operand;
160
161 addPtr(TrustedImm32(registerOffset * sizeof(Register)), callFrameRegister, regT1);
162 storePtr(TrustedImmPtr(JSValue::encode(jsNumber(argCount))), Address(regT1, RegisterFile::ArgumentCount * static_cast<int>(sizeof(Register))));
163 } // regT1 holds newCallFrame with ArgumentCount initialized.
164 emitGetVirtualRegister(callee, regT0); // regT0 holds callee.
165
166 storePtr(callFrameRegister, Address(regT1, RegisterFile::CallerFrame * static_cast<int>(sizeof(Register))));
167 storePtr(regT0, Address(regT1, RegisterFile::Callee * static_cast<int>(sizeof(Register))));
168 move(regT1, callFrameRegister);
169
barraclough@apple.come367b002008-12-04 05:43:14 +0000170 if (opcodeID == op_call_eval) {
ggaren@apple.com539d1bb2011-11-14 19:21:40 +0000171 compileCallEval();
172 return;
barraclough@apple.come367b002008-12-04 05:43:14 +0000173 }
174
barraclough@apple.com289318a2008-12-22 01:00:07 +0000175 DataLabelPtr addressOfLinkedFunctionCheck;
barraclough@apple.com970af2c2009-08-13 05:58:36 +0000176 BEGIN_UNINTERRUPTED_SEQUENCE(sequenceOpCall);
ggaren@apple.com539d1bb2011-11-14 19:21:40 +0000177 Jump slowCase = branchPtrWithPatch(NotEqual, regT0, addressOfLinkedFunctionCheck, TrustedImmPtr(JSValue::encode(JSValue())));
barraclough@apple.com970af2c2009-08-13 05:58:36 +0000178 END_UNINTERRUPTED_SEQUENCE(sequenceOpCall);
ggaren@apple.com539d1bb2011-11-14 19:21:40 +0000179 addSlowCase(slowCase);
barraclough@apple.com970af2c2009-08-13 05:58:36 +0000180
ggaren@apple.com539d1bb2011-11-14 19:21:40 +0000181 ASSERT_JIT_OFFSET(differenceBetween(addressOfLinkedFunctionCheck, slowCase), patchOffsetOpCallCompareToJump);
commit-queue@webkit.org4ea48922011-07-06 00:56:49 +0000182 ASSERT(m_callStructureStubCompilationInfo.size() == callLinkInfoIndex);
183 m_callStructureStubCompilationInfo.append(StructureStubCompilationInfo());
barraclough@apple.come367b002008-12-04 05:43:14 +0000184 m_callStructureStubCompilationInfo[callLinkInfoIndex].hotPathBegin = addressOfLinkedFunctionCheck;
ggaren@apple.com539d1bb2011-11-14 19:21:40 +0000185 m_callStructureStubCompilationInfo[callLinkInfoIndex].callType = CallLinkInfo::callTypeFor(opcodeID);
oliver@apple.com1386ec92011-10-07 18:39:45 +0000186 m_callStructureStubCompilationInfo[callLinkInfoIndex].bytecodeIndex = m_bytecodeOffset;
barraclough@apple.come367b002008-12-04 05:43:14 +0000187
ggaren@apple.com539d1bb2011-11-14 19:21:40 +0000188 loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_scopeChain)), regT1);
189 emitPutToCallFrameHeader(regT1, RegisterFile::ScopeChain);
barraclough@apple.com97bacef2009-06-05 07:55:38 +0000190 m_callStructureStubCompilationInfo[callLinkInfoIndex].hotPathOther = emitNakedCall();
barraclough@apple.come367b002008-12-04 05:43:14 +0000191
barraclough@apple.com24a7abb2009-01-16 23:34:46 +0000192 sampleCodeBlock(m_codeBlock);
barraclough@apple.come367b002008-12-04 05:43:14 +0000193}
194
ggaren@apple.com539d1bb2011-11-14 19:21:40 +0000195void JIT::compileOpCallSlowCase(OpcodeID opcodeID, Instruction*, Vector<SlowCaseEntry>::iterator& iter, unsigned callLinkInfoIndex)
barraclough@apple.come367b002008-12-04 05:43:14 +0000196{
ggaren@apple.com539d1bb2011-11-14 19:21:40 +0000197 if (opcodeID == op_call_eval) {
198 compileCallEvalSlowCase(iter);
199 return;
200 }
barraclough@apple.come367b002008-12-04 05:43:14 +0000201
barraclough@apple.com4f46a502008-12-13 01:39:38 +0000202 linkSlowCase(iter);
ggaren@apple.com539d1bb2011-11-14 19:21:40 +0000203
oliver@apple.com815b8e12010-07-15 04:30:13 +0000204 m_callStructureStubCompilationInfo[callLinkInfoIndex].callReturnLocation = emitNakedCall(opcodeID == op_construct ? m_globalData->jitStubs->ctiVirtualConstructLink() : m_globalData->jitStubs->ctiVirtualCallLink());
barraclough@apple.come367b002008-12-04 05:43:14 +0000205
barraclough@apple.com24a7abb2009-01-16 23:34:46 +0000206 sampleCodeBlock(m_codeBlock);
barraclough@apple.come367b002008-12-04 05:43:14 +0000207}
208
barraclough@apple.come367b002008-12-04 05:43:14 +0000209} // namespace JSC
210
oliver@apple.com0cc25c32010-10-19 23:55:08 +0000211#endif // USE(JSVALUE64)
barraclough@apple.come367b002008-12-04 05:43:14 +0000212#endif // ENABLE(JIT)