2 * Copyright (C) 2008 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
32 #include "Arguments.h"
33 #include "CodeBlock.h"
34 #include "JITInlineMethods.h"
35 #include "JITStubCall.h"
37 #include "JSFunction.h"
38 #include "Interpreter.h"
39 #include "ResultType.h"
40 #include "SamplingTool.h"
50 void JIT::emit_op_call_put_result(Instruction
* instruction
)
52 int dst
= instruction
[1].u
.operand
;
53 emitValueProfilingSite();
54 emitPutVirtualRegister(dst
);
56 killLastResultRegister(); // Make lastResultRegister tracking simpler in the DFG.
59 void JIT::compileLoadVarargs(Instruction
* instruction
)
61 int thisValue
= instruction
[2].u
.operand
;
62 int arguments
= instruction
[3].u
.operand
;
63 int firstFreeRegister
= instruction
[4].u
.operand
;
65 killLastResultRegister();
69 if (m_codeBlock
->usesArguments() && arguments
== m_codeBlock
->argumentsRegister()) {
70 emitGetVirtualRegister(arguments
, regT0
);
71 slowCase
.append(branchPtr(NotEqual
, regT0
, TrustedImmPtr(JSValue::encode(JSValue()))));
73 emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount
, regT0
);
74 slowCase
.append(branch32(Above
, regT0
, TrustedImm32(Arguments::MaxArguments
+ 1)));
75 // regT0: argumentCountIncludingThis
78 add32(TrustedImm32(firstFreeRegister
+ RegisterFile::CallFrameHeaderSize
), regT1
);
79 lshift32(TrustedImm32(3), regT1
);
80 addPtr(callFrameRegister
, regT1
);
81 // regT1: newCallFrame
83 slowCase
.append(branchPtr(Below
, AbsoluteAddress(m_globalData
->interpreter
->registerFile().addressOfEnd()), regT1
));
85 // Initialize ArgumentCount.
86 store32(regT0
, Address(regT1
, RegisterFile::ArgumentCount
* static_cast<int>(sizeof(Register
)) + OBJECT_OFFSETOF(EncodedValueDescriptor
, asBits
.payload
)));
89 emitGetVirtualRegister(thisValue
, regT2
);
90 storePtr(regT2
, Address(regT1
, CallFrame::thisArgumentOffset() * static_cast<int>(sizeof(Register
))));
94 signExtend32ToPtr(regT0
, regT0
);
95 end
.append(branchAddPtr(Zero
, TrustedImm32(1), regT0
));
96 // regT0: -argumentCount
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);
106 if (m_codeBlock
->usesArguments() && arguments
== m_codeBlock
->argumentsRegister())
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
);
115 if (m_codeBlock
->usesArguments() && arguments
== m_codeBlock
->argumentsRegister())
119 void JIT::compileCallEval()
121 JITStubCall
stubCall(this, cti_op_call_eval
); // Initializes ScopeChain; ReturnPC; CodeBlock.
123 addSlowCase(branchPtr(Equal
, regT0
, TrustedImmPtr(JSValue::encode(JSValue()))));
124 emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame
, callFrameRegister
);
126 sampleCodeBlock(m_codeBlock
);
129 void JIT::compileCallEvalSlowCase(Vector
<SlowCaseEntry
>::iterator
& iter
)
133 emitGetFromCallFrameHeaderPtr(RegisterFile::Callee
, regT0
);
134 emitNakedCall(m_globalData
->jitStubs
->ctiVirtualCall());
136 sampleCodeBlock(m_codeBlock
);
139 void JIT::compileOpCall(OpcodeID opcodeID
, Instruction
* instruction
, unsigned callLinkInfoIndex
)
141 int callee
= instruction
[1].u
.operand
;
144 - Updates callFrameRegister to callee callFrame.
145 - Initializes ArgumentCount; CallerFrame; Callee.
148 - Caller initializes ScopeChain.
149 - Callee initializes ReturnPC; CodeBlock.
150 - Callee restores callFrameRegister before return.
153 - Caller initializes ScopeChain; ReturnPC; CodeBlock.
154 - Caller restores callFrameRegister after return.
157 if (opcodeID
== op_call_varargs
)
158 compileLoadVarargs(instruction
);
160 int argCount
= instruction
[2].u
.operand
;
161 int registerOffset
= instruction
[3].u
.operand
;
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.
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.
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
);
174 if (opcodeID
== op_call_eval
) {
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
);
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
;
191 loadPtr(Address(regT0
, OBJECT_OFFSETOF(JSFunction
, m_scopeChain
)), regT1
);
192 emitPutToCallFrameHeader(regT1
, RegisterFile::ScopeChain
);
193 m_callStructureStubCompilationInfo
[callLinkInfoIndex
].hotPathOther
= emitNakedCall();
195 sampleCodeBlock(m_codeBlock
);
198 void JIT::compileOpCallSlowCase(OpcodeID opcodeID
, Instruction
*, Vector
<SlowCaseEntry
>::iterator
& iter
, unsigned callLinkInfoIndex
)
200 if (opcodeID
== op_call_eval
) {
201 compileCallEvalSlowCase(iter
);
207 m_callStructureStubCompilationInfo
[callLinkInfoIndex
].callReturnLocation
= emitNakedCall(opcodeID
== op_construct
? m_globalData
->jitStubs
->ctiVirtualConstructLink() : m_globalData
->jitStubs
->ctiVirtualCallLink());
209 sampleCodeBlock(m_codeBlock
);
214 #endif // USE(JSVALUE64)
215 #endif // ENABLE(JIT)