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
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14 * its contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 #include "RegisterFile.h"
37 #include <wtf/HashMap.h>
43 class FunctionBodyNode
;
45 class InternalFunction
;
46 class AssemblerBuffer
;
57 #if USE(JIT_STUB_ARGUMENT_VA_LIST)
58 #define STUB_ARGS void* args, ...
59 #define ARGS (reinterpret_cast<void**>(vl_args) - 1)
60 #else // JIT_STUB_ARGUMENT_REGISTER or JIT_STUB_ARGUMENT_STACK
61 #define STUB_ARGS void** args
65 #if USE(JIT_STUB_ARGUMENT_REGISTER)
69 #define JIT_STUB __fastcall
71 #define JIT_STUB __attribute__ ((fastcall))
73 #error Need to support register calling convention in this compiler
75 #else // JIT_STUB_ARGUMENT_VA_LIST or JIT_STUB_ARGUMENT_STACK
77 #define JIT_STUB __cdecl
83 // The Mac compilers are fine with this,
89 #define RETURN_PAIR(a,b) VoidPtrPair pair = { a, b }; return pair
91 typedef uint64_t VoidPtrPair
;
92 union VoidPtrPairValue
{
93 struct { void* first
; void* second
; } s
;
96 #define RETURN_PAIR(a,b) VoidPtrPairValue pair = {{ a, b }}; return pair.i
110 // We use a smaller reentrancy limit on iPhone because of the high amount of
111 // stack space required on the web thread.
112 enum { MaxReentryDepth
= 100 };
120 void initialize(JSGlobalData
*);
122 RegisterFile
& registerFile() { return m_registerFile
; }
124 Opcode
getOpcode(OpcodeID id
)
126 #if HAVE(COMPUTED_GOTO)
127 return m_opcodeTable
[id
];
133 OpcodeID
getOpcodeID(Opcode opcode
)
135 #if HAVE(COMPUTED_GOTO)
136 ASSERT(isOpcode(opcode
));
137 return m_opcodeIDTable
.get(opcode
);
143 bool isOpcode(Opcode
);
145 JSValuePtr
execute(ProgramNode
*, CallFrame
*, ScopeChainNode
*, JSObject
* thisObj
, JSValuePtr
* exception
);
146 JSValuePtr
execute(FunctionBodyNode
*, CallFrame
*, JSFunction
*, JSObject
* thisObj
, const ArgList
& args
, ScopeChainNode
*, JSValuePtr
* exception
);
147 JSValuePtr
execute(EvalNode
* evalNode
, CallFrame
* exec
, JSObject
* thisObj
, ScopeChainNode
* scopeChain
, JSValuePtr
* exception
);
149 JSValuePtr
retrieveArguments(CallFrame
*, JSFunction
*) const;
150 JSValuePtr
retrieveCaller(CallFrame
*, InternalFunction
*) const;
151 void retrieveLastCaller(CallFrame
*, int& lineNumber
, intptr_t& sourceID
, UString
& sourceURL
, JSValuePtr
& function
) const;
153 void getArgumentsData(CallFrame
*, JSFunction
*&, ptrdiff_t& firstParameterIndex
, Register
*& argv
, int& argc
);
154 void setTimeoutTime(unsigned timeoutTime
) { m_timeoutTime
= timeoutTime
; }
156 void startTimeoutCheck()
158 if (!m_timeoutCheckCount
)
161 ++m_timeoutCheckCount
;
164 void stopTimeoutCheck()
166 ASSERT(m_timeoutCheckCount
);
167 --m_timeoutCheckCount
;
170 inline void initTimeout()
172 ASSERT(!m_timeoutCheckCount
);
175 m_timeoutCheckCount
= 0;
178 void setSampler(SamplingTool
* sampler
) { m_sampler
= sampler
; }
179 SamplingTool
* sampler() { return m_sampler
; }
183 static int JIT_STUB
cti_timeout_check(STUB_ARGS
);
184 static void JIT_STUB
cti_register_file_check(STUB_ARGS
);
186 static JSObject
* JIT_STUB
cti_op_convert_this(STUB_ARGS
);
187 static void JIT_STUB
cti_op_end(STUB_ARGS
);
188 static JSValueEncodedAsPointer
* JIT_STUB
cti_op_add(STUB_ARGS
);
189 static JSValueEncodedAsPointer
* JIT_STUB
cti_op_pre_inc(STUB_ARGS
);
190 static int JIT_STUB
cti_op_loop_if_less(STUB_ARGS
);
191 static int JIT_STUB
cti_op_loop_if_lesseq(STUB_ARGS
);
192 static JSObject
* JIT_STUB
cti_op_new_object(STUB_ARGS
);
193 static void JIT_STUB
cti_op_put_by_id(STUB_ARGS
);
194 static void JIT_STUB
cti_op_put_by_id_second(STUB_ARGS
);
195 static void JIT_STUB
cti_op_put_by_id_generic(STUB_ARGS
);
196 static void JIT_STUB
cti_op_put_by_id_fail(STUB_ARGS
);
197 static JSValueEncodedAsPointer
* JIT_STUB
cti_op_get_by_id(STUB_ARGS
);
198 static JSValueEncodedAsPointer
* JIT_STUB
cti_op_get_by_id_second(STUB_ARGS
);
199 static JSValueEncodedAsPointer
* JIT_STUB
cti_op_get_by_id_generic(STUB_ARGS
);
200 static JSValueEncodedAsPointer
* JIT_STUB
cti_op_get_by_id_self_fail(STUB_ARGS
);
201 static JSValueEncodedAsPointer
* JIT_STUB
cti_op_get_by_id_proto_list(STUB_ARGS
);
202 static JSValueEncodedAsPointer
* JIT_STUB
cti_op_get_by_id_proto_list_full(STUB_ARGS
);
203 static JSValueEncodedAsPointer
* JIT_STUB
cti_op_get_by_id_proto_fail(STUB_ARGS
);
204 static JSValueEncodedAsPointer
* JIT_STUB
cti_op_get_by_id_array_fail(STUB_ARGS
);
205 static JSValueEncodedAsPointer
* JIT_STUB
cti_op_get_by_id_string_fail(STUB_ARGS
);
206 static JSValueEncodedAsPointer
* JIT_STUB
cti_op_del_by_id(STUB_ARGS
);
207 static JSValueEncodedAsPointer
* JIT_STUB
cti_op_instanceof(STUB_ARGS
);
208 static JSValueEncodedAsPointer
* JIT_STUB
cti_op_mul(STUB_ARGS
);
209 static JSObject
* JIT_STUB
cti_op_new_func(STUB_ARGS
);
210 static void* JIT_STUB
cti_op_call_JSFunction(STUB_ARGS
);
211 static VoidPtrPair JIT_STUB
cti_op_call_arityCheck(STUB_ARGS
);
212 static JSValueEncodedAsPointer
* JIT_STUB
cti_op_call_NotJSFunction(STUB_ARGS
);
213 static void JIT_STUB
cti_op_create_arguments(STUB_ARGS
);
214 static void JIT_STUB
cti_op_create_arguments_no_params(STUB_ARGS
);
215 static void JIT_STUB
cti_op_tear_off_activation(STUB_ARGS
);
216 static void JIT_STUB
cti_op_tear_off_arguments(STUB_ARGS
);
217 static void JIT_STUB
cti_op_profile_will_call(STUB_ARGS
);
218 static void JIT_STUB
cti_op_profile_did_call(STUB_ARGS
);
219 static void JIT_STUB
cti_op_ret_scopeChain(STUB_ARGS
);
220 static JSObject
* JIT_STUB
cti_op_new_array(STUB_ARGS
);
221 static JSValueEncodedAsPointer
* JIT_STUB
cti_op_resolve(STUB_ARGS
);
222 static JSValueEncodedAsPointer
* JIT_STUB
cti_op_resolve_global(STUB_ARGS
);
223 static JSObject
* JIT_STUB
cti_op_construct_JSConstruct(STUB_ARGS
);
224 static JSValueEncodedAsPointer
* JIT_STUB
cti_op_construct_NotJSConstruct(STUB_ARGS
);
225 static JSValueEncodedAsPointer
* JIT_STUB
cti_op_get_by_val(STUB_ARGS
);
226 static JSValueEncodedAsPointer
* JIT_STUB
cti_op_get_by_val_byte_array(STUB_ARGS
);
227 static VoidPtrPair JIT_STUB
cti_op_resolve_func(STUB_ARGS
);
228 static JSValueEncodedAsPointer
* JIT_STUB
cti_op_sub(STUB_ARGS
);
229 static void JIT_STUB
cti_op_put_by_val(STUB_ARGS
);
230 static void JIT_STUB
cti_op_put_by_val_array(STUB_ARGS
);
231 static void JIT_STUB
cti_op_put_by_val_byte_array(STUB_ARGS
);
232 static JSValueEncodedAsPointer
* JIT_STUB
cti_op_lesseq(STUB_ARGS
);
233 static int JIT_STUB
cti_op_loop_if_true(STUB_ARGS
);
234 static JSValueEncodedAsPointer
* JIT_STUB
cti_op_resolve_base(STUB_ARGS
);
235 static JSValueEncodedAsPointer
* JIT_STUB
cti_op_negate(STUB_ARGS
);
236 static JSValueEncodedAsPointer
* JIT_STUB
cti_op_resolve_skip(STUB_ARGS
);
237 static JSValueEncodedAsPointer
* JIT_STUB
cti_op_div(STUB_ARGS
);
238 static JSValueEncodedAsPointer
* JIT_STUB
cti_op_pre_dec(STUB_ARGS
);
239 static int JIT_STUB
cti_op_jless(STUB_ARGS
);
240 static JSValueEncodedAsPointer
* JIT_STUB
cti_op_not(STUB_ARGS
);
241 static int JIT_STUB
cti_op_jtrue(STUB_ARGS
);
242 static VoidPtrPair JIT_STUB
cti_op_post_inc(STUB_ARGS
);
243 static JSValueEncodedAsPointer
* JIT_STUB
cti_op_eq(STUB_ARGS
);
244 static JSValueEncodedAsPointer
* JIT_STUB
cti_op_lshift(STUB_ARGS
);
245 static JSValueEncodedAsPointer
* JIT_STUB
cti_op_bitand(STUB_ARGS
);
246 static JSValueEncodedAsPointer
* JIT_STUB
cti_op_rshift(STUB_ARGS
);
247 static JSValueEncodedAsPointer
* JIT_STUB
cti_op_bitnot(STUB_ARGS
);
248 static VoidPtrPair JIT_STUB
cti_op_resolve_with_base(STUB_ARGS
);
249 static JSObject
* JIT_STUB
cti_op_new_func_exp(STUB_ARGS
);
250 static JSValueEncodedAsPointer
* JIT_STUB
cti_op_mod(STUB_ARGS
);
251 static JSValueEncodedAsPointer
* JIT_STUB
cti_op_less(STUB_ARGS
);
252 static JSValueEncodedAsPointer
* JIT_STUB
cti_op_neq(STUB_ARGS
);
253 static VoidPtrPair JIT_STUB
cti_op_post_dec(STUB_ARGS
);
254 static JSValueEncodedAsPointer
* JIT_STUB
cti_op_urshift(STUB_ARGS
);
255 static JSValueEncodedAsPointer
* JIT_STUB
cti_op_bitxor(STUB_ARGS
);
256 static JSObject
* JIT_STUB
cti_op_new_regexp(STUB_ARGS
);
257 static JSValueEncodedAsPointer
* JIT_STUB
cti_op_bitor(STUB_ARGS
);
258 static JSValueEncodedAsPointer
* JIT_STUB
cti_op_call_eval(STUB_ARGS
);
259 static JSValueEncodedAsPointer
* JIT_STUB
cti_op_throw(STUB_ARGS
);
260 static JSPropertyNameIterator
* JIT_STUB
cti_op_get_pnames(STUB_ARGS
);
261 static JSValueEncodedAsPointer
* JIT_STUB
cti_op_next_pname(STUB_ARGS
);
262 static JSObject
* JIT_STUB
cti_op_push_scope(STUB_ARGS
);
263 static void JIT_STUB
cti_op_pop_scope(STUB_ARGS
);
264 static JSValueEncodedAsPointer
* JIT_STUB
cti_op_typeof(STUB_ARGS
);
265 static JSValueEncodedAsPointer
* JIT_STUB
cti_op_is_undefined(STUB_ARGS
);
266 static JSValueEncodedAsPointer
* JIT_STUB
cti_op_is_boolean(STUB_ARGS
);
267 static JSValueEncodedAsPointer
* JIT_STUB
cti_op_is_number(STUB_ARGS
);
268 static JSValueEncodedAsPointer
* JIT_STUB
cti_op_is_string(STUB_ARGS
);
269 static JSValueEncodedAsPointer
* JIT_STUB
cti_op_is_object(STUB_ARGS
);
270 static JSValueEncodedAsPointer
* JIT_STUB
cti_op_is_function(STUB_ARGS
);
271 static JSValueEncodedAsPointer
* JIT_STUB
cti_op_stricteq(STUB_ARGS
);
272 static JSValueEncodedAsPointer
* JIT_STUB
cti_op_nstricteq(STUB_ARGS
);
273 static JSValueEncodedAsPointer
* JIT_STUB
cti_op_to_jsnumber(STUB_ARGS
);
274 static JSValueEncodedAsPointer
* JIT_STUB
cti_op_in(STUB_ARGS
);
275 static JSObject
* JIT_STUB
cti_op_push_new_scope(STUB_ARGS
);
276 static void JIT_STUB
cti_op_jmp_scopes(STUB_ARGS
);
277 static void JIT_STUB
cti_op_put_by_index(STUB_ARGS
);
278 static void* JIT_STUB
cti_op_switch_imm(STUB_ARGS
);
279 static void* JIT_STUB
cti_op_switch_char(STUB_ARGS
);
280 static void* JIT_STUB
cti_op_switch_string(STUB_ARGS
);
281 static JSValueEncodedAsPointer
* JIT_STUB
cti_op_del_by_val(STUB_ARGS
);
282 static void JIT_STUB
cti_op_put_getter(STUB_ARGS
);
283 static void JIT_STUB
cti_op_put_setter(STUB_ARGS
);
284 static JSObject
* JIT_STUB
cti_op_new_error(STUB_ARGS
);
285 static void JIT_STUB
cti_op_debug(STUB_ARGS
);
287 static JSValueEncodedAsPointer
* JIT_STUB
cti_vm_throw(STUB_ARGS
);
288 static void* JIT_STUB
cti_vm_dontLazyLinkCall(STUB_ARGS
);
289 static void* JIT_STUB
cti_vm_lazyLinkCall(STUB_ARGS
);
290 static JSObject
* JIT_STUB
cti_op_push_activation(STUB_ARGS
);
292 #endif // ENABLE(JIT)
294 // Default number of ticks before a timeout check should be done.
295 static const int initialTickCountThreshold
= 1024;
297 bool isJSArray(JSValuePtr v
) { return v
.isCell() && v
.asCell()->vptr() == m_jsArrayVptr
; }
298 bool isJSString(JSValuePtr v
) { return v
.isCell() && v
.asCell()->vptr() == m_jsStringVptr
; }
299 bool isJSByteArray(JSValuePtr v
) { return v
.isCell() && v
.asCell()->vptr() == m_jsByteArrayVptr
; }
302 enum ExecutionFlag
{ Normal
, InitializeAndReturn
};
304 NEVER_INLINE JSValuePtr
callEval(CallFrame
*, RegisterFile
*, Register
* argv
, int argc
, int registerOffset
, JSValuePtr
& exceptionValue
);
305 JSValuePtr
execute(EvalNode
*, CallFrame
*, JSObject
* thisObject
, int globalRegisterOffset
, ScopeChainNode
*, JSValuePtr
* exception
);
307 NEVER_INLINE
void debug(CallFrame
*, DebugHookID
, int firstLine
, int lastLine
);
309 NEVER_INLINE
bool resolve(CallFrame
*, Instruction
*, JSValuePtr
& exceptionValue
);
310 NEVER_INLINE
bool resolveSkip(CallFrame
*, Instruction
*, JSValuePtr
& exceptionValue
);
311 NEVER_INLINE
bool resolveGlobal(CallFrame
*, Instruction
*, JSValuePtr
& exceptionValue
);
312 NEVER_INLINE
void resolveBase(CallFrame
*, Instruction
* vPC
);
313 NEVER_INLINE
bool resolveBaseAndProperty(CallFrame
*, Instruction
*, JSValuePtr
& exceptionValue
);
314 NEVER_INLINE ScopeChainNode
* createExceptionScope(CallFrame
*, const Instruction
* vPC
);
316 NEVER_INLINE
bool unwindCallFrame(CallFrame
*&, JSValuePtr
, unsigned& bytecodeOffset
, CodeBlock
*&);
317 NEVER_INLINE HandlerInfo
* throwException(CallFrame
*&, JSValuePtr
&, unsigned bytecodeOffset
, bool);
318 NEVER_INLINE
bool resolveBaseAndFunc(CallFrame
*, Instruction
*, JSValuePtr
& exceptionValue
);
320 static ALWAYS_INLINE CallFrame
* slideRegisterWindowForCall(CodeBlock
*, RegisterFile
*, CallFrame
*, size_t registerOffset
, int argc
);
322 static CallFrame
* findFunctionCallFrame(CallFrame
*, InternalFunction
*);
324 JSValuePtr
privateExecute(ExecutionFlag
, RegisterFile
*, CallFrame
*, JSValuePtr
* exception
);
326 void dumpCallFrame(CallFrame
*);
327 void dumpRegisters(CallFrame
*);
329 bool checkTimeout(JSGlobalObject
*);
330 void resetTimeoutCheck();
332 void tryCacheGetByID(CallFrame
*, CodeBlock
*, Instruction
*, JSValuePtr baseValue
, const Identifier
& propertyName
, const PropertySlot
&);
333 void uncacheGetByID(CodeBlock
*, Instruction
* vPC
);
334 void tryCachePutByID(CallFrame
*, CodeBlock
*, Instruction
*, JSValuePtr baseValue
, const PutPropertySlot
&);
335 void uncachePutByID(CodeBlock
*, Instruction
* vPC
);
337 bool isCallBytecode(Opcode opcode
) { return opcode
== getOpcode(op_call
) || opcode
== getOpcode(op_construct
) || opcode
== getOpcode(op_call_eval
); }
340 static void throwStackOverflowPreviousFrame(CallFrame
**, JSGlobalData
*, void*& returnAddress
);
342 void tryCTICacheGetByID(CallFrame
*, CodeBlock
*, void* returnAddress
, JSValuePtr baseValue
, const Identifier
& propertyName
, const PropertySlot
&);
343 void tryCTICachePutByID(CallFrame
*, CodeBlock
*, void* returnAddress
, JSValuePtr baseValue
, const PutPropertySlot
&);
346 SamplingTool
* m_sampler
;
349 RefPtr
<ExecutablePool
> m_executablePool
;
350 void* m_ctiArrayLengthTrampoline
;
351 void* m_ctiStringLengthTrampoline
;
352 void* m_ctiVirtualCallPreLink
;
353 void* m_ctiVirtualCallLink
;
354 void* m_ctiVirtualCall
;
358 unsigned m_timeoutTime
;
359 unsigned m_timeAtLastCheckTimeout
;
360 unsigned m_timeExecuting
;
361 unsigned m_timeoutCheckCount
;
362 unsigned m_ticksUntilNextTimeoutCheck
;
364 RegisterFile m_registerFile
;
367 void* m_jsByteArrayVptr
;
368 void* m_jsStringVptr
;
369 void* m_jsFunctionVptr
;
371 #if HAVE(COMPUTED_GOTO)
372 Opcode m_opcodeTable
[numOpcodeIDs
]; // Maps OpcodeID => Opcode for compiling
373 HashMap
<Opcode
, OpcodeID
> m_opcodeIDTable
; // Maps Opcode => OpcodeID for decompiling
379 #endif // Interpreter_h