2 * Copyright (C) 2011, 2012 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.
27 #include "LLIntSlowPaths.h"
31 #include "Arguments.h"
32 #include "CallFrame.h"
33 #include "CommonSlowPaths.h"
34 #include "GetterSetter.h"
35 #include "HostCallReturnValue.h"
36 #include "Interpreter.h"
38 #include "JITDriver.h"
39 #include "JSActivation.h"
40 #include "JSGlobalObjectFunctions.h"
41 #include "JSPropertyNameIterator.h"
42 #include "JSStaticScopeObject.h"
45 #include "LLIntCommon.h"
46 #include "LLIntExceptions.h"
47 #include "LowLevelInterpreter.h"
48 #include "Operations.h"
50 namespace JSC
{ namespace LLInt
{
52 #define LLINT_BEGIN_NO_SET_PC() \
53 JSGlobalData& globalData = exec->globalData(); \
54 NativeCallFrameTracer tracer(&globalData, exec)
57 #define LLINT_SET_PC_FOR_STUBS() do { \
58 exec->codeBlock()->bytecodeOffset(pc); \
59 exec->setCurrentVPC(pc + 1); \
62 #define LLINT_SET_PC_FOR_STUBS() do { \
63 exec->setCurrentVPC(pc + 1); \
67 #define LLINT_BEGIN() \
68 LLINT_BEGIN_NO_SET_PC(); \
69 LLINT_SET_PC_FOR_STUBS()
71 #define LLINT_OP(index) (exec->uncheckedR(pc[index].u.operand))
72 #define LLINT_OP_C(index) (exec->r(pc[index].u.operand))
74 #define LLINT_RETURN_TWO(first, second) do { \
75 return encodeResult(first, second); \
78 #define LLINT_END_IMPL() LLINT_RETURN_TWO(pc, exec)
80 #define LLINT_THROW(exceptionToThrow) do { \
81 globalData.exception = (exceptionToThrow); \
82 pc = returnToThrow(exec, pc); \
86 #define LLINT_CHECK_EXCEPTION() do { \
87 if (UNLIKELY(globalData.exception)) { \
88 pc = returnToThrow(exec, pc); \
93 #define LLINT_END() do { \
94 LLINT_CHECK_EXCEPTION(); \
98 #define LLINT_BRANCH(opcode, condition) do { \
99 bool __b_condition = (condition); \
100 LLINT_CHECK_EXCEPTION(); \
102 pc += pc[OPCODE_LENGTH(opcode) - 1].u.operand; \
104 pc += OPCODE_LENGTH(opcode); \
108 #define LLINT_RETURN(value) do { \
109 JSValue __r_returnValue = (value); \
110 LLINT_CHECK_EXCEPTION(); \
111 LLINT_OP(1) = __r_returnValue; \
115 #if ENABLE(VALUE_PROFILER)
116 #define LLINT_RETURN_PROFILED(opcode, value) do { \
117 JSValue __rp_returnValue = (value); \
118 LLINT_CHECK_EXCEPTION(); \
119 LLINT_OP(1) = __rp_returnValue; \
120 pc[OPCODE_LENGTH(opcode) - 1].u.profile->m_buckets[0] = \
121 JSValue::encode(__rp_returnValue); \
124 #else // ENABLE(VALUE_PROFILER)
125 #define LLINT_RETURN_PROFILED(opcode, value) LLINT_RETURN(value)
126 #endif // ENABLE(VALUE_PROFILER)
128 #define LLINT_CALL_END_IMPL(exec, callTarget) LLINT_RETURN_TWO((callTarget), (exec))
130 #define LLINT_CALL_THROW(exec, pc, exceptionToThrow) do { \
131 ExecState* __ct_exec = (exec); \
132 Instruction* __ct_pc = (pc); \
133 globalData.exception = (exceptionToThrow); \
134 LLINT_CALL_END_IMPL(__ct_exec, callToThrow(__ct_exec, __ct_pc)); \
137 #define LLINT_CALL_CHECK_EXCEPTION(exec, pc) do { \
138 ExecState* __cce_exec = (exec); \
139 Instruction* __cce_pc = (pc); \
140 if (UNLIKELY(globalData.exception)) \
141 LLINT_CALL_END_IMPL(__cce_exec, callToThrow(__cce_exec, __cce_pc)); \
144 #define LLINT_CALL_RETURN(exec, pc, callTarget) do { \
145 ExecState* __cr_exec = (exec); \
146 Instruction* __cr_pc = (pc); \
147 void* __cr_callTarget = (callTarget); \
148 LLINT_CALL_CHECK_EXCEPTION(__cr_exec->callerFrame(), __cr_pc); \
149 LLINT_CALL_END_IMPL(__cr_exec, __cr_callTarget); \
152 extern "C" SlowPathReturnType
llint_trace_operand(ExecState
* exec
, Instruction
* pc
, int fromWhere
, int operand
)
155 dataLog("%p / %p: executing bc#%zu, op#%u: Trace(%d): %d: %d\n",
158 static_cast<intptr_t>(pc
- exec
->codeBlock()->instructions().begin()),
159 exec
->globalData().interpreter
->getOpcodeID(pc
[0].u
.opcode
),
162 pc
[operand
].u
.operand
);
166 extern "C" SlowPathReturnType
llint_trace_value(ExecState
* exec
, Instruction
* pc
, int fromWhere
, int operand
)
168 JSValue value
= LLINT_OP_C(operand
).jsValue();
174 EncodedJSValue asValue
;
176 u
.asValue
= JSValue::encode(value
);
177 dataLog("%p / %p: executing bc#%zu, op#%u: Trace(%d): %d: %d: %08x:%08x: %s\n",
180 static_cast<intptr_t>(pc
- exec
->codeBlock()->instructions().begin()),
181 exec
->globalData().interpreter
->getOpcodeID(pc
[0].u
.opcode
),
184 pc
[operand
].u
.operand
,
187 value
.description());
191 LLINT_SLOW_PATH_DECL(trace_prologue
)
193 dataLog("%p / %p: in prologue.\n", exec
->codeBlock(), exec
);
197 static void traceFunctionPrologue(ExecState
* exec
, const char* comment
, CodeSpecializationKind kind
)
199 JSFunction
* callee
= jsCast
<JSFunction
*>(exec
->callee());
200 FunctionExecutable
* executable
= callee
->jsExecutable();
201 CodeBlock
* codeBlock
= &executable
->generatedBytecodeFor(kind
);
202 dataLog("%p / %p: in %s of function %p, executable %p; numVars = %u, numParameters = %u, numCalleeRegisters = %u, caller = %p.\n",
203 codeBlock
, exec
, comment
, callee
, executable
,
204 codeBlock
->m_numVars
, codeBlock
->numParameters(), codeBlock
->m_numCalleeRegisters
,
205 exec
->callerFrame());
208 LLINT_SLOW_PATH_DECL(trace_prologue_function_for_call
)
210 traceFunctionPrologue(exec
, "call prologue", CodeForCall
);
214 LLINT_SLOW_PATH_DECL(trace_prologue_function_for_construct
)
216 traceFunctionPrologue(exec
, "construct prologue", CodeForConstruct
);
220 LLINT_SLOW_PATH_DECL(trace_arityCheck_for_call
)
222 traceFunctionPrologue(exec
, "call arity check", CodeForCall
);
226 LLINT_SLOW_PATH_DECL(trace_arityCheck_for_construct
)
228 traceFunctionPrologue(exec
, "construct arity check", CodeForConstruct
);
232 LLINT_SLOW_PATH_DECL(trace
)
234 dataLog("%p / %p: executing bc#%zu, %s, scope %p\n",
237 static_cast<intptr_t>(pc
- exec
->codeBlock()->instructions().begin()),
238 opcodeNames
[exec
->globalData().interpreter
->getOpcodeID(pc
[0].u
.opcode
)],
240 if (exec
->globalData().interpreter
->getOpcodeID(pc
[0].u
.opcode
) == op_ret
) {
241 dataLog("Will be returning to %p\n", exec
->returnPC().value());
242 dataLog("The new cfr will be %p\n", exec
->callerFrame());
247 LLINT_SLOW_PATH_DECL(special_trace
)
249 dataLog("%p / %p: executing special case bc#%zu, op#%u, return PC is %p\n",
252 static_cast<intptr_t>(pc
- exec
->codeBlock()->instructions().begin()),
253 exec
->globalData().interpreter
->getOpcodeID(pc
[0].u
.opcode
),
254 exec
->returnPC().value());
258 inline bool shouldJIT(ExecState
* exec
)
260 // You can modify this to turn off JITting without rebuilding the world.
261 return exec
->globalData().canUseJIT();
264 // Returns true if we should try to OSR.
265 inline bool jitCompileAndSetHeuristics(CodeBlock
* codeBlock
, ExecState
* exec
)
267 if (!codeBlock
->checkIfJITThresholdReached()) {
268 #if ENABLE(JIT_VERBOSE_OSR)
269 dataLog(" JIT threshold should be lifted.\n");
274 CodeBlock::JITCompilationResult result
= codeBlock
->jitCompile(exec
->globalData());
276 case CodeBlock::AlreadyCompiled
:
277 #if ENABLE(JIT_VERBOSE_OSR)
278 dataLog(" Code was already compiled.\n");
280 codeBlock
->jitSoon();
282 case CodeBlock::CouldNotCompile
:
283 #if ENABLE(JIT_VERBOSE_OSR)
284 dataLog(" JIT compilation failed.\n");
286 codeBlock
->dontJITAnytimeSoon();
288 case CodeBlock::CompiledSuccessfully
:
289 #if ENABLE(JIT_VERBOSE_OSR)
290 dataLog(" JIT compilation successful.\n");
292 codeBlock
->jitSoon();
295 ASSERT_NOT_REACHED();
299 enum EntryKind
{ Prologue
, ArityCheck
};
300 static SlowPathReturnType
entryOSR(ExecState
* exec
, Instruction
* pc
, CodeBlock
* codeBlock
, const char *name
, EntryKind kind
)
302 #if ENABLE(JIT_VERBOSE_OSR)
303 dataLog("%p: Entered %s with executeCounter = %d\n", codeBlock
, name
, codeBlock
->llintExecuteCounter());
306 if (!shouldJIT(exec
)) {
307 codeBlock
->dontJITAnytimeSoon();
308 LLINT_RETURN_TWO(0, exec
);
310 if (!jitCompileAndSetHeuristics(codeBlock
, exec
))
311 LLINT_RETURN_TWO(0, exec
);
313 if (kind
== Prologue
)
314 LLINT_RETURN_TWO(codeBlock
->getJITCode().executableAddressAtOffset(0), exec
);
315 ASSERT(kind
== ArityCheck
);
316 LLINT_RETURN_TWO(codeBlock
->getJITCodeWithArityCheck().executableAddress(), exec
);
319 LLINT_SLOW_PATH_DECL(entry_osr
)
321 return entryOSR(exec
, pc
, exec
->codeBlock(), "entry_osr", Prologue
);
324 LLINT_SLOW_PATH_DECL(entry_osr_function_for_call
)
326 return entryOSR(exec
, pc
, &jsCast
<JSFunction
*>(exec
->callee())->jsExecutable()->generatedBytecodeFor(CodeForCall
), "entry_osr_function_for_call", Prologue
);
329 LLINT_SLOW_PATH_DECL(entry_osr_function_for_construct
)
331 return entryOSR(exec
, pc
, &jsCast
<JSFunction
*>(exec
->callee())->jsExecutable()->generatedBytecodeFor(CodeForConstruct
), "entry_osr_function_for_construct", Prologue
);
334 LLINT_SLOW_PATH_DECL(entry_osr_function_for_call_arityCheck
)
336 return entryOSR(exec
, pc
, &jsCast
<JSFunction
*>(exec
->callee())->jsExecutable()->generatedBytecodeFor(CodeForCall
), "entry_osr_function_for_call_arityCheck", ArityCheck
);
339 LLINT_SLOW_PATH_DECL(entry_osr_function_for_construct_arityCheck
)
341 return entryOSR(exec
, pc
, &jsCast
<JSFunction
*>(exec
->callee())->jsExecutable()->generatedBytecodeFor(CodeForConstruct
), "entry_osr_function_for_construct_arityCheck", ArityCheck
);
344 LLINT_SLOW_PATH_DECL(loop_osr
)
346 CodeBlock
* codeBlock
= exec
->codeBlock();
348 #if ENABLE(JIT_VERBOSE_OSR)
349 dataLog("%p: Entered loop_osr with executeCounter = %d\n", codeBlock
, codeBlock
->llintExecuteCounter());
352 if (!shouldJIT(exec
)) {
353 codeBlock
->dontJITAnytimeSoon();
354 LLINT_RETURN_TWO(0, exec
);
357 if (!jitCompileAndSetHeuristics(codeBlock
, exec
))
358 LLINT_RETURN_TWO(0, exec
);
360 ASSERT(codeBlock
->getJITType() == JITCode::BaselineJIT
);
362 Vector
<BytecodeAndMachineOffset
> map
;
363 codeBlock
->jitCodeMap()->decode(map
);
364 BytecodeAndMachineOffset
* mapping
= binarySearch
<BytecodeAndMachineOffset
, unsigned, BytecodeAndMachineOffset::getBytecodeIndex
>(map
.begin(), map
.size(), pc
- codeBlock
->instructions().begin());
366 ASSERT(mapping
->m_bytecodeIndex
== static_cast<unsigned>(pc
- codeBlock
->instructions().begin()));
368 void* jumpTarget
= codeBlock
->getJITCode().executableAddressAtOffset(mapping
->m_machineCodeOffset
);
371 LLINT_RETURN_TWO(jumpTarget
, exec
);
374 LLINT_SLOW_PATH_DECL(replace
)
376 CodeBlock
* codeBlock
= exec
->codeBlock();
378 #if ENABLE(JIT_VERBOSE_OSR)
379 dataLog("%p: Entered replace with executeCounter = %d\n", codeBlock
, codeBlock
->llintExecuteCounter());
383 jitCompileAndSetHeuristics(codeBlock
, exec
);
385 codeBlock
->dontJITAnytimeSoon();
389 LLINT_SLOW_PATH_DECL(register_file_check
)
392 #if LLINT_SLOW_PATH_TRACING
393 dataLog("Checking stack height with exec = %p.\n", exec
);
394 dataLog("CodeBlock = %p.\n", exec
->codeBlock());
395 dataLog("Num callee registers = %u.\n", exec
->codeBlock()->m_numCalleeRegisters
);
396 dataLog("Num vars = %u.\n", exec
->codeBlock()->m_numVars
);
397 dataLog("Current end is at %p.\n", exec
->globalData().interpreter
->registerFile().end());
399 ASSERT(&exec
->registers()[exec
->codeBlock()->m_numCalleeRegisters
] > exec
->globalData().interpreter
->registerFile().end());
400 if (UNLIKELY(!globalData
.interpreter
->registerFile().grow(&exec
->registers()[exec
->codeBlock()->m_numCalleeRegisters
]))) {
401 ReturnAddressPtr returnPC
= exec
->returnPC();
402 exec
= exec
->callerFrame();
403 globalData
.exception
= createStackOverflowError(exec
);
404 interpreterThrowInCaller(exec
, returnPC
);
405 pc
= returnToThrowForThrownException(exec
);
410 LLINT_SLOW_PATH_DECL(slow_path_call_arityCheck
)
413 ExecState
* newExec
= CommonSlowPaths::arityCheckFor(exec
, &globalData
.interpreter
->registerFile(), CodeForCall
);
415 ReturnAddressPtr returnPC
= exec
->returnPC();
416 exec
= exec
->callerFrame();
417 globalData
.exception
= createStackOverflowError(exec
);
418 interpreterThrowInCaller(exec
, returnPC
);
419 LLINT_RETURN_TWO(bitwise_cast
<void*>(static_cast<uintptr_t>(1)), exec
);
421 LLINT_RETURN_TWO(0, newExec
);
424 LLINT_SLOW_PATH_DECL(slow_path_construct_arityCheck
)
427 ExecState
* newExec
= CommonSlowPaths::arityCheckFor(exec
, &globalData
.interpreter
->registerFile(), CodeForConstruct
);
429 ReturnAddressPtr returnPC
= exec
->returnPC();
430 exec
= exec
->callerFrame();
431 globalData
.exception
= createStackOverflowError(exec
);
432 interpreterThrowInCaller(exec
, returnPC
);
433 LLINT_RETURN_TWO(bitwise_cast
<void*>(static_cast<uintptr_t>(1)), exec
);
435 LLINT_RETURN_TWO(0, newExec
);
438 LLINT_SLOW_PATH_DECL(slow_path_create_activation
)
441 #if LLINT_SLOW_PATH_TRACING
442 dataLog("Creating an activation, exec = %p!\n", exec
);
444 JSActivation
* activation
= JSActivation::create(globalData
, exec
, static_cast<FunctionExecutable
*>(exec
->codeBlock()->ownerExecutable()));
445 exec
->setScopeChain(exec
->scopeChain()->push(activation
));
446 LLINT_RETURN(JSValue(activation
));
449 LLINT_SLOW_PATH_DECL(slow_path_create_arguments
)
452 JSValue arguments
= JSValue(Arguments::create(globalData
, exec
));
453 LLINT_CHECK_EXCEPTION();
454 exec
->uncheckedR(pc
[1].u
.operand
) = arguments
;
455 exec
->uncheckedR(unmodifiedArgumentsRegister(pc
[1].u
.operand
)) = arguments
;
459 LLINT_SLOW_PATH_DECL(slow_path_create_this
)
462 JSFunction
* constructor
= jsCast
<JSFunction
*>(exec
->callee());
465 ConstructData constructData
;
466 ASSERT(constructor
->methodTable()->getConstructData(constructor
, constructData
) == ConstructTypeJS
);
469 Structure
* structure
;
470 JSValue proto
= LLINT_OP(2).jsValue();
471 if (proto
.isObject())
472 structure
= asObject(proto
)->inheritorID(globalData
);
474 structure
= constructor
->scope()->globalObject
->emptyObjectStructure();
476 LLINT_RETURN(constructEmptyObject(exec
, structure
));
479 LLINT_SLOW_PATH_DECL(slow_path_convert_this
)
482 JSValue v1
= LLINT_OP(1).jsValue();
483 ASSERT(v1
.isPrimitive());
484 LLINT_RETURN(v1
.toThisObject(exec
));
487 LLINT_SLOW_PATH_DECL(slow_path_new_object
)
490 LLINT_RETURN(constructEmptyObject(exec
));
493 LLINT_SLOW_PATH_DECL(slow_path_new_array
)
496 LLINT_RETURN(constructArray(exec
, bitwise_cast
<JSValue
*>(&LLINT_OP(2)), pc
[3].u
.operand
));
499 LLINT_SLOW_PATH_DECL(slow_path_new_array_buffer
)
502 LLINT_RETURN(constructArray(exec
, exec
->codeBlock()->constantBuffer(pc
[2].u
.operand
), pc
[3].u
.operand
));
505 LLINT_SLOW_PATH_DECL(slow_path_new_regexp
)
508 RegExp
* regExp
= exec
->codeBlock()->regexp(pc
[2].u
.operand
);
509 if (!regExp
->isValid())
510 LLINT_THROW(createSyntaxError(exec
, "Invalid flag supplied to RegExp constructor."));
511 LLINT_RETURN(RegExpObject::create(globalData
, exec
->lexicalGlobalObject(), exec
->lexicalGlobalObject()->regExpStructure(), regExp
));
514 LLINT_SLOW_PATH_DECL(slow_path_not
)
517 LLINT_RETURN(jsBoolean(!LLINT_OP_C(2).jsValue().toBoolean(exec
)));
520 LLINT_SLOW_PATH_DECL(slow_path_eq
)
523 LLINT_RETURN(jsBoolean(JSValue::equal(exec
, LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue())));
526 LLINT_SLOW_PATH_DECL(slow_path_neq
)
529 LLINT_RETURN(jsBoolean(!JSValue::equal(exec
, LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue())));
532 LLINT_SLOW_PATH_DECL(slow_path_stricteq
)
535 LLINT_RETURN(jsBoolean(JSValue::strictEqual(exec
, LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue())));
538 LLINT_SLOW_PATH_DECL(slow_path_nstricteq
)
541 LLINT_RETURN(jsBoolean(!JSValue::strictEqual(exec
, LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue())));
544 LLINT_SLOW_PATH_DECL(slow_path_less
)
547 LLINT_RETURN(jsBoolean(jsLess
<true>(exec
, LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue())));
550 LLINT_SLOW_PATH_DECL(slow_path_lesseq
)
553 LLINT_RETURN(jsBoolean(jsLessEq
<true>(exec
, LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue())));
556 LLINT_SLOW_PATH_DECL(slow_path_greater
)
559 LLINT_RETURN(jsBoolean(jsLess
<false>(exec
, LLINT_OP_C(3).jsValue(), LLINT_OP_C(2).jsValue())));
562 LLINT_SLOW_PATH_DECL(slow_path_greatereq
)
565 LLINT_RETURN(jsBoolean(jsLessEq
<false>(exec
, LLINT_OP_C(3).jsValue(), LLINT_OP_C(2).jsValue())));
568 LLINT_SLOW_PATH_DECL(slow_path_pre_inc
)
571 LLINT_RETURN(jsNumber(LLINT_OP(1).jsValue().toNumber(exec
) + 1));
574 LLINT_SLOW_PATH_DECL(slow_path_pre_dec
)
577 LLINT_RETURN(jsNumber(LLINT_OP(1).jsValue().toNumber(exec
) - 1));
580 LLINT_SLOW_PATH_DECL(slow_path_post_inc
)
583 double result
= LLINT_OP(2).jsValue().toNumber(exec
);
584 LLINT_OP(2) = jsNumber(result
+ 1);
585 LLINT_RETURN(jsNumber(result
));
588 LLINT_SLOW_PATH_DECL(slow_path_post_dec
)
591 double result
= LLINT_OP(2).jsValue().toNumber(exec
);
592 LLINT_OP(2) = jsNumber(result
- 1);
593 LLINT_RETURN(jsNumber(result
));
596 LLINT_SLOW_PATH_DECL(slow_path_to_jsnumber
)
599 LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toNumber(exec
)));
602 LLINT_SLOW_PATH_DECL(slow_path_negate
)
605 LLINT_RETURN(jsNumber(-LLINT_OP_C(2).jsValue().toNumber(exec
)));
608 LLINT_SLOW_PATH_DECL(slow_path_add
)
611 JSValue v1
= LLINT_OP_C(2).jsValue();
612 JSValue v2
= LLINT_OP_C(3).jsValue();
614 #if LLINT_SLOW_PATH_TRACING
615 dataLog("Trying to add %s", v1
.description());
616 dataLog(" to %s.\n", v2
.description());
619 if (v1
.isString() && !v2
.isObject())
620 LLINT_RETURN(jsString(exec
, asString(v1
), v2
.toString(exec
)));
622 if (v1
.isNumber() && v2
.isNumber())
623 LLINT_RETURN(jsNumber(v1
.asNumber() + v2
.asNumber()));
625 LLINT_RETURN(jsAddSlowCase(exec
, v1
, v2
));
628 LLINT_SLOW_PATH_DECL(slow_path_mul
)
631 LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toNumber(exec
) * LLINT_OP_C(3).jsValue().toNumber(exec
)));
634 LLINT_SLOW_PATH_DECL(slow_path_sub
)
637 LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toNumber(exec
) - LLINT_OP_C(3).jsValue().toNumber(exec
)));
640 LLINT_SLOW_PATH_DECL(slow_path_div
)
643 LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toNumber(exec
) / LLINT_OP_C(3).jsValue().toNumber(exec
)));
646 LLINT_SLOW_PATH_DECL(slow_path_mod
)
649 LLINT_RETURN(jsNumber(fmod(LLINT_OP_C(2).jsValue().toNumber(exec
), LLINT_OP_C(3).jsValue().toNumber(exec
))));
652 LLINT_SLOW_PATH_DECL(slow_path_lshift
)
655 LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toInt32(exec
) << (LLINT_OP_C(3).jsValue().toUInt32(exec
) & 31)));
658 LLINT_SLOW_PATH_DECL(slow_path_rshift
)
661 LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toInt32(exec
) >> (LLINT_OP_C(3).jsValue().toUInt32(exec
) & 31)));
664 LLINT_SLOW_PATH_DECL(slow_path_urshift
)
667 LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toUInt32(exec
) >> (LLINT_OP_C(3).jsValue().toUInt32(exec
) & 31)));
670 LLINT_SLOW_PATH_DECL(slow_path_bitand
)
673 LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toInt32(exec
) & LLINT_OP_C(3).jsValue().toInt32(exec
)));
676 LLINT_SLOW_PATH_DECL(slow_path_bitor
)
679 LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toInt32(exec
) | LLINT_OP_C(3).jsValue().toInt32(exec
)));
682 LLINT_SLOW_PATH_DECL(slow_path_bitxor
)
685 LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toInt32(exec
) ^ LLINT_OP_C(3).jsValue().toInt32(exec
)));
688 LLINT_SLOW_PATH_DECL(slow_path_check_has_instance
)
691 JSValue baseVal
= LLINT_OP_C(1).jsValue();
693 TypeInfo
typeInfo(UnspecifiedType
);
694 ASSERT(!baseVal
.isObject()
695 || !(typeInfo
= asObject(baseVal
)->structure()->typeInfo()).implementsHasInstance());
697 LLINT_THROW(createInvalidParamError(exec
, "instanceof", baseVal
));
700 LLINT_SLOW_PATH_DECL(slow_path_instanceof
)
703 LLINT_RETURN(jsBoolean(CommonSlowPaths::opInstanceOfSlow(exec
, LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue(), LLINT_OP_C(4).jsValue())));
706 LLINT_SLOW_PATH_DECL(slow_path_typeof
)
709 LLINT_RETURN(jsTypeStringForValue(exec
, LLINT_OP_C(2).jsValue()));
712 LLINT_SLOW_PATH_DECL(slow_path_is_object
)
715 LLINT_RETURN(jsBoolean(jsIsObjectType(LLINT_OP_C(2).jsValue())));
718 LLINT_SLOW_PATH_DECL(slow_path_is_function
)
721 LLINT_RETURN(jsBoolean(jsIsFunctionType(LLINT_OP_C(2).jsValue())));
724 LLINT_SLOW_PATH_DECL(slow_path_in
)
727 LLINT_RETURN(jsBoolean(CommonSlowPaths::opIn(exec
, LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue())));
730 LLINT_SLOW_PATH_DECL(slow_path_resolve
)
733 LLINT_RETURN_PROFILED(op_resolve
, CommonSlowPaths::opResolve(exec
, exec
->codeBlock()->identifier(pc
[2].u
.operand
)));
736 LLINT_SLOW_PATH_DECL(slow_path_resolve_skip
)
739 LLINT_RETURN_PROFILED(
741 CommonSlowPaths::opResolveSkip(
743 exec
->codeBlock()->identifier(pc
[2].u
.operand
),
747 static JSValue
resolveGlobal(ExecState
* exec
, Instruction
* pc
)
749 CodeBlock
* codeBlock
= exec
->codeBlock();
750 JSGlobalObject
* globalObject
= codeBlock
->globalObject();
751 ASSERT(globalObject
->isGlobalObject());
752 int property
= pc
[2].u
.operand
;
753 Structure
* structure
= pc
[3].u
.structure
.get();
755 ASSERT_UNUSED(structure
, structure
!= globalObject
->structure());
757 Identifier
& ident
= codeBlock
->identifier(property
);
758 PropertySlot
slot(globalObject
);
760 if (globalObject
->getPropertySlot(exec
, ident
, slot
)) {
761 JSValue result
= slot
.getValue(exec
, ident
);
762 if (slot
.isCacheableValue() && !globalObject
->structure()->isUncacheableDictionary()
763 && slot
.slotBase() == globalObject
) {
764 pc
[3].u
.structure
.set(
765 exec
->globalData(), codeBlock
->ownerExecutable(), globalObject
->structure());
766 pc
[4] = slot
.cachedOffset();
772 exec
->globalData().exception
= createUndefinedVariableError(exec
, ident
);
776 LLINT_SLOW_PATH_DECL(slow_path_resolve_global
)
779 LLINT_RETURN_PROFILED(op_resolve_global
, resolveGlobal(exec
, pc
));
782 LLINT_SLOW_PATH_DECL(slow_path_resolve_global_dynamic
)
785 LLINT_RETURN_PROFILED(op_resolve_global_dynamic
, resolveGlobal(exec
, pc
));
788 LLINT_SLOW_PATH_DECL(slow_path_resolve_for_resolve_global_dynamic
)
791 LLINT_RETURN_PROFILED(op_resolve_global_dynamic
, CommonSlowPaths::opResolve(exec
, exec
->codeBlock()->identifier(pc
[2].u
.operand
)));
794 LLINT_SLOW_PATH_DECL(slow_path_resolve_base
)
797 Identifier
& ident
= exec
->codeBlock()->identifier(pc
[2].u
.operand
);
798 if (pc
[3].u
.operand
) {
799 JSValue base
= JSC::resolveBase(exec
, ident
, exec
->scopeChain(), true);
801 LLINT_THROW(createErrorForInvalidGlobalAssignment(exec
, ident
.ustring()));
805 LLINT_RETURN_PROFILED(op_resolve_base
, JSC::resolveBase(exec
, ident
, exec
->scopeChain(), false));
808 LLINT_SLOW_PATH_DECL(slow_path_ensure_property_exists
)
811 JSObject
* object
= asObject(LLINT_OP(1).jsValue());
812 PropertySlot
slot(object
);
813 Identifier
& ident
= exec
->codeBlock()->identifier(pc
[2].u
.operand
);
814 if (!object
->getPropertySlot(exec
, ident
, slot
))
815 LLINT_THROW(createErrorForInvalidGlobalAssignment(exec
, ident
.ustring()));
819 LLINT_SLOW_PATH_DECL(slow_path_resolve_with_base
)
822 JSValue result
= CommonSlowPaths::opResolveWithBase(exec
, exec
->codeBlock()->identifier(pc
[3].u
.operand
), LLINT_OP(1));
823 LLINT_CHECK_EXCEPTION();
824 LLINT_OP(2) = result
;
825 // FIXME: technically should have profiling, but we don't do it because the DFG won't use it.
829 LLINT_SLOW_PATH_DECL(slow_path_resolve_with_this
)
832 JSValue result
= CommonSlowPaths::opResolveWithThis(exec
, exec
->codeBlock()->identifier(pc
[3].u
.operand
), LLINT_OP(1));
833 LLINT_CHECK_EXCEPTION();
834 LLINT_OP(2) = result
;
835 // FIXME: technically should have profiling, but we don't do it because the DFG won't use it.
839 LLINT_SLOW_PATH_DECL(slow_path_get_by_id
)
842 CodeBlock
* codeBlock
= exec
->codeBlock();
843 Identifier
& ident
= codeBlock
->identifier(pc
[3].u
.operand
);
844 JSValue baseValue
= LLINT_OP_C(2).jsValue();
845 PropertySlot
slot(baseValue
);
847 JSValue result
= baseValue
.get(exec
, ident
, slot
);
848 LLINT_CHECK_EXCEPTION();
849 LLINT_OP(1) = result
;
851 if (baseValue
.isCell()
852 && slot
.isCacheable()
853 && slot
.slotBase() == baseValue
854 && slot
.cachedPropertyType() == PropertySlot::Value
) {
856 JSCell
* baseCell
= baseValue
.asCell();
857 Structure
* structure
= baseCell
->structure();
859 if (!structure
->isUncacheableDictionary()
860 && !structure
->typeInfo().prohibitsPropertyCaching()) {
861 pc
[4].u
.structure
.set(
862 globalData
, codeBlock
->ownerExecutable(), structure
);
863 pc
[5].u
.operand
= slot
.cachedOffset() * sizeof(JSValue
);
867 #if ENABLE(VALUE_PROFILER)
868 pc
[OPCODE_LENGTH(op_get_by_id
) - 1].u
.profile
->m_buckets
[0] = JSValue::encode(result
);
873 LLINT_SLOW_PATH_DECL(slow_path_get_arguments_length
)
876 CodeBlock
* codeBlock
= exec
->codeBlock();
877 Identifier
& ident
= codeBlock
->identifier(pc
[3].u
.operand
);
878 JSValue baseValue
= LLINT_OP(2).jsValue();
879 PropertySlot
slot(baseValue
);
880 LLINT_RETURN(baseValue
.get(exec
, ident
, slot
));
883 LLINT_SLOW_PATH_DECL(slow_path_put_by_id
)
886 CodeBlock
* codeBlock
= exec
->codeBlock();
887 Identifier
& ident
= codeBlock
->identifier(pc
[2].u
.operand
);
889 JSValue baseValue
= LLINT_OP_C(1).jsValue();
890 PutPropertySlot
slot(codeBlock
->isStrictMode());
892 asObject(baseValue
)->putDirect(globalData
, ident
, LLINT_OP_C(3).jsValue(), slot
);
894 baseValue
.put(exec
, ident
, LLINT_OP_C(3).jsValue(), slot
);
895 LLINT_CHECK_EXCEPTION();
897 if (baseValue
.isCell()
898 && slot
.isCacheable()) {
900 JSCell
* baseCell
= baseValue
.asCell();
901 Structure
* structure
= baseCell
->structure();
903 if (!structure
->isUncacheableDictionary()
904 && !structure
->typeInfo().prohibitsPropertyCaching()
905 && baseCell
== slot
.base()) {
907 if (slot
.type() == PutPropertySlot::NewProperty
) {
908 if (!structure
->isDictionary() && structure
->previousID()->propertyStorageCapacity() == structure
->propertyStorageCapacity()) {
909 // This is needed because some of the methods we call
911 pc
[0].u
.opcode
= bitwise_cast
<void*>(&llint_op_put_by_id
);
913 normalizePrototypeChain(exec
, baseCell
);
915 ASSERT(structure
->previousID()->isObject());
916 pc
[4].u
.structure
.set(
917 globalData
, codeBlock
->ownerExecutable(), structure
->previousID());
918 pc
[5].u
.operand
= slot
.cachedOffset() * sizeof(JSValue
);
919 pc
[6].u
.structure
.set(
920 globalData
, codeBlock
->ownerExecutable(), structure
);
921 StructureChain
* chain
= structure
->prototypeChain(exec
);
923 pc
[7].u
.structureChain
.set(
924 globalData
, codeBlock
->ownerExecutable(), chain
);
927 pc
[0].u
.opcode
= bitwise_cast
<void*>(&llint_op_put_by_id_transition_direct
);
929 pc
[0].u
.opcode
= bitwise_cast
<void*>(&llint_op_put_by_id_transition_normal
);
932 pc
[0].u
.opcode
= bitwise_cast
<void*>(&llint_op_put_by_id
);
933 pc
[4].u
.structure
.set(
934 globalData
, codeBlock
->ownerExecutable(), structure
);
935 pc
[5].u
.operand
= slot
.cachedOffset() * sizeof(JSValue
);
943 LLINT_SLOW_PATH_DECL(slow_path_del_by_id
)
946 CodeBlock
* codeBlock
= exec
->codeBlock();
947 JSObject
* baseObject
= LLINT_OP_C(2).jsValue().toObject(exec
);
948 bool couldDelete
= baseObject
->methodTable()->deleteProperty(baseObject
, exec
, codeBlock
->identifier(pc
[3].u
.operand
));
949 LLINT_CHECK_EXCEPTION();
950 if (!couldDelete
&& codeBlock
->isStrictMode())
951 LLINT_THROW(createTypeError(exec
, "Unable to delete property."));
952 LLINT_RETURN(jsBoolean(couldDelete
));
955 inline JSValue
getByVal(ExecState
* exec
, JSValue baseValue
, JSValue subscript
)
957 if (LIKELY(baseValue
.isCell() && subscript
.isString())) {
958 if (JSValue result
= baseValue
.asCell()->fastGetOwnProperty(exec
, asString(subscript
)->value(exec
)))
962 if (subscript
.isUInt32()) {
963 uint32_t i
= subscript
.asUInt32();
964 if (isJSString(baseValue
) && asString(baseValue
)->canGetIndex(i
))
965 return asString(baseValue
)->getIndex(exec
, i
);
967 return baseValue
.get(exec
, i
);
970 Identifier
property(exec
, subscript
.toString(exec
)->value(exec
));
971 return baseValue
.get(exec
, property
);
974 LLINT_SLOW_PATH_DECL(slow_path_get_by_val
)
977 LLINT_RETURN_PROFILED(op_get_by_val
, getByVal(exec
, LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue()));
980 LLINT_SLOW_PATH_DECL(slow_path_get_argument_by_val
)
983 JSValue arguments
= LLINT_OP(2).jsValue();
985 arguments
= Arguments::create(globalData
, exec
);
986 LLINT_CHECK_EXCEPTION();
987 LLINT_OP(2) = arguments
;
988 exec
->uncheckedR(unmodifiedArgumentsRegister(pc
[2].u
.operand
)) = arguments
;
991 LLINT_RETURN(getByVal(exec
, arguments
, LLINT_OP_C(3).jsValue()));
994 LLINT_SLOW_PATH_DECL(slow_path_get_by_pname
)
997 LLINT_RETURN(getByVal(exec
, LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue()));
1000 LLINT_SLOW_PATH_DECL(slow_path_put_by_val
)
1004 JSValue baseValue
= LLINT_OP_C(1).jsValue();
1005 JSValue subscript
= LLINT_OP_C(2).jsValue();
1006 JSValue value
= LLINT_OP_C(3).jsValue();
1008 if (LIKELY(subscript
.isUInt32())) {
1009 uint32_t i
= subscript
.asUInt32();
1010 if (isJSArray(baseValue
)) {
1011 JSArray
* jsArray
= asArray(baseValue
);
1012 if (jsArray
->canSetIndex(i
))
1013 jsArray
->setIndex(globalData
, i
, value
);
1015 JSArray::putByIndex(jsArray
, exec
, i
, value
, exec
->codeBlock()->isStrictMode());
1018 baseValue
.putByIndex(exec
, i
, value
, exec
->codeBlock()->isStrictMode());
1022 Identifier
property(exec
, subscript
.toString(exec
)->value(exec
));
1023 LLINT_CHECK_EXCEPTION();
1024 PutPropertySlot
slot(exec
->codeBlock()->isStrictMode());
1025 baseValue
.put(exec
, property
, value
, slot
);
1029 LLINT_SLOW_PATH_DECL(slow_path_del_by_val
)
1032 JSValue baseValue
= LLINT_OP_C(2).jsValue();
1033 JSObject
* baseObject
= baseValue
.toObject(exec
);
1035 JSValue subscript
= LLINT_OP_C(3).jsValue();
1040 if (subscript
.getUInt32(i
))
1041 couldDelete
= baseObject
->methodTable()->deletePropertyByIndex(baseObject
, exec
, i
);
1043 LLINT_CHECK_EXCEPTION();
1044 Identifier
property(exec
, subscript
.toString(exec
)->value(exec
));
1045 LLINT_CHECK_EXCEPTION();
1046 couldDelete
= baseObject
->methodTable()->deleteProperty(baseObject
, exec
, property
);
1049 if (!couldDelete
&& exec
->codeBlock()->isStrictMode())
1050 LLINT_THROW(createTypeError(exec
, "Unable to delete property."));
1052 LLINT_RETURN(jsBoolean(couldDelete
));
1055 LLINT_SLOW_PATH_DECL(slow_path_put_by_index
)
1058 JSValue arrayValue
= LLINT_OP_C(1).jsValue();
1059 ASSERT(isJSArray(arrayValue
));
1060 asArray(arrayValue
)->putDirectIndex(exec
, pc
[2].u
.operand
, LLINT_OP_C(3).jsValue(), false);
1064 LLINT_SLOW_PATH_DECL(slow_path_put_getter_setter
)
1067 ASSERT(LLINT_OP(1).jsValue().isObject());
1068 JSObject
* baseObj
= asObject(LLINT_OP(1).jsValue());
1070 GetterSetter
* accessor
= GetterSetter::create(exec
);
1071 LLINT_CHECK_EXCEPTION();
1073 JSValue getter
= LLINT_OP(3).jsValue();
1074 JSValue setter
= LLINT_OP(4).jsValue();
1075 ASSERT(getter
.isObject() || getter
.isUndefined());
1076 ASSERT(setter
.isObject() || setter
.isUndefined());
1077 ASSERT(getter
.isObject() || setter
.isObject());
1079 if (!getter
.isUndefined())
1080 accessor
->setGetter(globalData
, asObject(getter
));
1081 if (!setter
.isUndefined())
1082 accessor
->setSetter(globalData
, asObject(setter
));
1083 baseObj
->putDirectAccessor(
1085 exec
->codeBlock()->identifier(pc
[2].u
.operand
),
1086 accessor
, Accessor
);
1090 LLINT_SLOW_PATH_DECL(slow_path_jmp_scopes
)
1093 unsigned count
= pc
[1].u
.operand
;
1094 ScopeChainNode
* tmp
= exec
->scopeChain();
1097 exec
->setScopeChain(tmp
);
1098 pc
+= pc
[2].u
.operand
;
1102 LLINT_SLOW_PATH_DECL(slow_path_jtrue
)
1105 LLINT_BRANCH(op_jtrue
, LLINT_OP_C(1).jsValue().toBoolean(exec
));
1108 LLINT_SLOW_PATH_DECL(slow_path_jfalse
)
1111 LLINT_BRANCH(op_jfalse
, !LLINT_OP_C(1).jsValue().toBoolean(exec
));
1114 LLINT_SLOW_PATH_DECL(slow_path_jless
)
1117 LLINT_BRANCH(op_jless
, jsLess
<true>(exec
, LLINT_OP_C(1).jsValue(), LLINT_OP_C(2).jsValue()));
1120 LLINT_SLOW_PATH_DECL(slow_path_jnless
)
1123 LLINT_BRANCH(op_jnless
, !jsLess
<true>(exec
, LLINT_OP_C(1).jsValue(), LLINT_OP_C(2).jsValue()));
1126 LLINT_SLOW_PATH_DECL(slow_path_jgreater
)
1129 LLINT_BRANCH(op_jgreater
, jsLess
<false>(exec
, LLINT_OP_C(2).jsValue(), LLINT_OP_C(1).jsValue()));
1132 LLINT_SLOW_PATH_DECL(slow_path_jngreater
)
1135 LLINT_BRANCH(op_jngreater
, !jsLess
<false>(exec
, LLINT_OP_C(2).jsValue(), LLINT_OP_C(1).jsValue()));
1138 LLINT_SLOW_PATH_DECL(slow_path_jlesseq
)
1141 LLINT_BRANCH(op_jlesseq
, jsLessEq
<true>(exec
, LLINT_OP_C(1).jsValue(), LLINT_OP_C(2).jsValue()));
1144 LLINT_SLOW_PATH_DECL(slow_path_jnlesseq
)
1147 LLINT_BRANCH(op_jnlesseq
, !jsLessEq
<true>(exec
, LLINT_OP_C(1).jsValue(), LLINT_OP_C(2).jsValue()));
1150 LLINT_SLOW_PATH_DECL(slow_path_jgreatereq
)
1153 LLINT_BRANCH(op_jgreatereq
, jsLessEq
<false>(exec
, LLINT_OP_C(2).jsValue(), LLINT_OP_C(1).jsValue()));
1156 LLINT_SLOW_PATH_DECL(slow_path_jngreatereq
)
1159 LLINT_BRANCH(op_jngreatereq
, !jsLessEq
<false>(exec
, LLINT_OP_C(2).jsValue(), LLINT_OP_C(1).jsValue()));
1162 LLINT_SLOW_PATH_DECL(slow_path_switch_imm
)
1165 JSValue scrutinee
= LLINT_OP_C(3).jsValue();
1166 ASSERT(scrutinee
.isDouble());
1167 double value
= scrutinee
.asDouble();
1168 int32_t intValue
= static_cast<int32_t>(value
);
1169 int defaultOffset
= pc
[2].u
.operand
;
1170 if (value
== intValue
) {
1171 CodeBlock
* codeBlock
= exec
->codeBlock();
1172 pc
+= codeBlock
->immediateSwitchJumpTable(pc
[1].u
.operand
).offsetForValue(intValue
, defaultOffset
);
1174 pc
+= defaultOffset
;
1178 LLINT_SLOW_PATH_DECL(slow_path_switch_char
)
1181 JSValue scrutinee
= LLINT_OP_C(3).jsValue();
1182 ASSERT(scrutinee
.isString());
1183 JSString
* string
= asString(scrutinee
);
1184 ASSERT(string
->length() == 1);
1185 int defaultOffset
= pc
[2].u
.operand
;
1186 StringImpl
* impl
= string
->value(exec
).impl();
1187 CodeBlock
* codeBlock
= exec
->codeBlock();
1188 pc
+= codeBlock
->characterSwitchJumpTable(pc
[1].u
.operand
).offsetForValue((*impl
)[0], defaultOffset
);
1192 LLINT_SLOW_PATH_DECL(slow_path_switch_string
)
1195 JSValue scrutinee
= LLINT_OP_C(3).jsValue();
1196 int defaultOffset
= pc
[2].u
.operand
;
1197 if (!scrutinee
.isString())
1198 pc
+= defaultOffset
;
1200 CodeBlock
* codeBlock
= exec
->codeBlock();
1201 pc
+= codeBlock
->stringSwitchJumpTable(pc
[1].u
.operand
).offsetForValue(asString(scrutinee
)->value(exec
).impl(), defaultOffset
);
1206 LLINT_SLOW_PATH_DECL(slow_path_new_func
)
1209 CodeBlock
* codeBlock
= exec
->codeBlock();
1210 ASSERT(codeBlock
->codeType() != FunctionCode
1211 || !codeBlock
->needsFullScopeChain()
1212 || exec
->uncheckedR(codeBlock
->activationRegister()).jsValue());
1213 #if LLINT_SLOW_PATH_TRACING
1214 dataLog("Creating function!\n");
1216 LLINT_RETURN(codeBlock
->functionDecl(pc
[2].u
.operand
)->make(exec
, exec
->scopeChain()));
1219 LLINT_SLOW_PATH_DECL(slow_path_new_func_exp
)
1222 CodeBlock
* codeBlock
= exec
->codeBlock();
1223 FunctionExecutable
* function
= codeBlock
->functionExpr(pc
[2].u
.operand
);
1224 JSFunction
* func
= function
->make(exec
, exec
->scopeChain());
1226 if (!function
->name().isNull()) {
1227 JSStaticScopeObject
* functionScopeObject
= JSStaticScopeObject::create(exec
, function
->name(), func
, ReadOnly
| DontDelete
);
1228 func
->setScope(globalData
, func
->scope()->push(functionScopeObject
));
1234 static SlowPathReturnType
handleHostCall(ExecState
* execCallee
, Instruction
* pc
, JSValue callee
, CodeSpecializationKind kind
)
1236 ExecState
* exec
= execCallee
->callerFrame();
1237 JSGlobalData
& globalData
= exec
->globalData();
1239 execCallee
->setScopeChain(exec
->scopeChain());
1240 execCallee
->setCodeBlock(0);
1241 execCallee
->clearReturnPC();
1243 if (kind
== CodeForCall
) {
1245 CallType callType
= getCallData(callee
, callData
);
1247 ASSERT(callType
!= CallTypeJS
);
1249 if (callType
== CallTypeHost
) {
1250 NativeCallFrameTracer
tracer(&globalData
, execCallee
);
1251 execCallee
->setCallee(asObject(callee
));
1252 globalData
.hostCallReturnValue
= JSValue::decode(callData
.native
.function(execCallee
));
1254 LLINT_CALL_RETURN(execCallee
, pc
, reinterpret_cast<void*>(getHostCallReturnValue
));
1257 #if LLINT_SLOW_PATH_TRACING
1258 dataLog("Call callee is not a function: %s\n", callee
.description());
1261 ASSERT(callType
== CallTypeNone
);
1262 LLINT_CALL_THROW(exec
, pc
, createNotAFunctionError(exec
, callee
));
1265 ASSERT(kind
== CodeForConstruct
);
1267 ConstructData constructData
;
1268 ConstructType constructType
= getConstructData(callee
, constructData
);
1270 ASSERT(constructType
!= ConstructTypeJS
);
1272 if (constructType
== ConstructTypeHost
) {
1273 NativeCallFrameTracer
tracer(&globalData
, execCallee
);
1274 execCallee
->setCallee(asObject(callee
));
1275 globalData
.hostCallReturnValue
= JSValue::decode(constructData
.native
.function(execCallee
));
1277 LLINT_CALL_RETURN(execCallee
, pc
, reinterpret_cast<void*>(getHostCallReturnValue
));
1280 #if LLINT_SLOW_PATH_TRACING
1281 dataLog("Constructor callee is not a function: %s\n", callee
.description());
1284 ASSERT(constructType
== ConstructTypeNone
);
1285 LLINT_CALL_THROW(exec
, pc
, createNotAConstructorError(exec
, callee
));
1288 inline SlowPathReturnType
setUpCall(ExecState
* execCallee
, Instruction
* pc
, CodeSpecializationKind kind
, JSValue calleeAsValue
, LLIntCallLinkInfo
* callLinkInfo
= 0)
1290 #if LLINT_SLOW_PATH_TRACING
1291 dataLog("Performing call with recorded PC = %p\n", execCallee
->callerFrame()->currentVPC());
1294 JSCell
* calleeAsFunctionCell
= getJSFunction(calleeAsValue
);
1295 if (!calleeAsFunctionCell
)
1296 return handleHostCall(execCallee
, pc
, calleeAsValue
, kind
);
1298 JSFunction
* callee
= jsCast
<JSFunction
*>(calleeAsFunctionCell
);
1299 ScopeChainNode
* scope
= callee
->scopeUnchecked();
1300 JSGlobalData
& globalData
= *scope
->globalData
;
1301 execCallee
->setScopeChain(scope
);
1302 ExecutableBase
* executable
= callee
->executable();
1304 MacroAssemblerCodePtr codePtr
;
1305 CodeBlock
* codeBlock
= 0;
1306 if (executable
->isHostFunction())
1307 codePtr
= executable
->generatedJITCodeFor(kind
).addressForCall();
1309 FunctionExecutable
* functionExecutable
= static_cast<FunctionExecutable
*>(executable
);
1310 JSObject
* error
= functionExecutable
->compileFor(execCallee
, callee
->scope(), kind
);
1312 LLINT_CALL_THROW(execCallee
->callerFrame(), pc
, error
);
1313 codeBlock
= &functionExecutable
->generatedBytecodeFor(kind
);
1315 if (execCallee
->argumentCountIncludingThis() < static_cast<size_t>(codeBlock
->numParameters()))
1316 codePtr
= functionExecutable
->generatedJITCodeWithArityCheckFor(kind
);
1318 codePtr
= functionExecutable
->generatedJITCodeFor(kind
).addressForCall();
1322 if (callLinkInfo
->isOnList())
1323 callLinkInfo
->remove();
1324 ExecState
* execCaller
= execCallee
->callerFrame();
1325 callLinkInfo
->callee
.set(globalData
, execCaller
->codeBlock()->ownerExecutable(), callee
);
1326 callLinkInfo
->lastSeenCallee
.set(globalData
, execCaller
->codeBlock()->ownerExecutable(), callee
);
1327 callLinkInfo
->machineCodeTarget
= codePtr
;
1329 codeBlock
->linkIncomingCall(callLinkInfo
);
1332 LLINT_CALL_RETURN(execCallee
, pc
, codePtr
.executableAddress());
1335 inline SlowPathReturnType
genericCall(ExecState
* exec
, Instruction
* pc
, CodeSpecializationKind kind
)
1338 // - Set up a call frame.
1339 // - Figure out what to call and compile it if necessary.
1340 // - If possible, link the call's inline cache.
1341 // - Return a tuple of machine code address to call and the new call frame.
1343 JSValue calleeAsValue
= LLINT_OP_C(1).jsValue();
1345 ExecState
* execCallee
= exec
+ pc
[3].u
.operand
;
1347 execCallee
->setArgumentCountIncludingThis(pc
[2].u
.operand
);
1348 execCallee
->uncheckedR(RegisterFile::Callee
) = calleeAsValue
;
1349 execCallee
->setCallerFrame(exec
);
1351 ASSERT(pc
[4].u
.callLinkInfo
);
1352 return setUpCall(execCallee
, pc
, kind
, calleeAsValue
, pc
[4].u
.callLinkInfo
);
1355 LLINT_SLOW_PATH_DECL(slow_path_call
)
1357 LLINT_BEGIN_NO_SET_PC();
1358 return genericCall(exec
, pc
, CodeForCall
);
1361 LLINT_SLOW_PATH_DECL(slow_path_construct
)
1363 LLINT_BEGIN_NO_SET_PC();
1364 return genericCall(exec
, pc
, CodeForConstruct
);
1367 LLINT_SLOW_PATH_DECL(slow_path_call_varargs
)
1371 // - Set up a call frame while respecting the variable arguments.
1372 // - Figure out what to call and compile it if necessary.
1373 // - Return a tuple of machine code address to call and the new call frame.
1375 JSValue calleeAsValue
= LLINT_OP_C(1).jsValue();
1377 ExecState
* execCallee
= loadVarargs(
1378 exec
, &globalData
.interpreter
->registerFile(),
1379 LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue(), pc
[4].u
.operand
);
1380 LLINT_CALL_CHECK_EXCEPTION(exec
, pc
);
1382 execCallee
->uncheckedR(RegisterFile::Callee
) = calleeAsValue
;
1383 execCallee
->setCallerFrame(exec
);
1384 exec
->setCurrentVPC(pc
+ OPCODE_LENGTH(op_call_varargs
));
1386 return setUpCall(execCallee
, pc
, CodeForCall
, calleeAsValue
);
1389 LLINT_SLOW_PATH_DECL(slow_path_call_eval
)
1391 LLINT_BEGIN_NO_SET_PC();
1392 JSValue calleeAsValue
= LLINT_OP(1).jsValue();
1394 ExecState
* execCallee
= exec
+ pc
[3].u
.operand
;
1396 execCallee
->setArgumentCountIncludingThis(pc
[2].u
.operand
);
1397 execCallee
->setCallerFrame(exec
);
1398 execCallee
->uncheckedR(RegisterFile::Callee
) = calleeAsValue
;
1399 execCallee
->setScopeChain(exec
->scopeChain());
1400 execCallee
->setReturnPC(bitwise_cast
<Instruction
*>(&llint_generic_return_point
));
1401 execCallee
->setCodeBlock(0);
1402 exec
->setCurrentVPC(pc
+ OPCODE_LENGTH(op_call_eval
));
1404 if (!isHostFunction(calleeAsValue
, globalFuncEval
))
1405 return setUpCall(execCallee
, pc
, CodeForCall
, calleeAsValue
);
1407 globalData
.hostCallReturnValue
= eval(execCallee
);
1408 LLINT_CALL_RETURN(execCallee
, pc
, reinterpret_cast<void*>(getHostCallReturnValue
));
1411 LLINT_SLOW_PATH_DECL(slow_path_tear_off_activation
)
1414 ASSERT(exec
->codeBlock()->needsFullScopeChain());
1415 JSValue activationValue
= LLINT_OP(1).jsValue();
1416 if (!activationValue
) {
1417 if (JSValue v
= exec
->uncheckedR(unmodifiedArgumentsRegister(pc
[2].u
.operand
)).jsValue()) {
1418 if (!exec
->codeBlock()->isStrictMode())
1419 asArguments(v
)->tearOff(exec
);
1423 JSActivation
* activation
= asActivation(activationValue
);
1424 activation
->tearOff(globalData
);
1425 if (JSValue v
= exec
->uncheckedR(unmodifiedArgumentsRegister(pc
[2].u
.operand
)).jsValue())
1426 asArguments(v
)->didTearOffActivation(globalData
, activation
);
1430 LLINT_SLOW_PATH_DECL(slow_path_tear_off_arguments
)
1433 ASSERT(exec
->codeBlock()->usesArguments() && !exec
->codeBlock()->needsFullScopeChain());
1434 asArguments(exec
->uncheckedR(unmodifiedArgumentsRegister(pc
[1].u
.operand
)).jsValue())->tearOff(exec
);
1438 LLINT_SLOW_PATH_DECL(slow_path_strcat
)
1441 LLINT_RETURN(jsString(exec
, &LLINT_OP(2), pc
[3].u
.operand
));
1444 LLINT_SLOW_PATH_DECL(slow_path_to_primitive
)
1447 LLINT_RETURN(LLINT_OP_C(2).jsValue().toPrimitive(exec
));
1450 LLINT_SLOW_PATH_DECL(slow_path_get_pnames
)
1453 JSValue v
= LLINT_OP(2).jsValue();
1454 if (v
.isUndefinedOrNull()) {
1455 pc
+= pc
[5].u
.operand
;
1459 JSObject
* o
= v
.toObject(exec
);
1460 Structure
* structure
= o
->structure();
1461 JSPropertyNameIterator
* jsPropertyNameIterator
= structure
->enumerationCache();
1462 if (!jsPropertyNameIterator
|| jsPropertyNameIterator
->cachedPrototypeChain() != structure
->prototypeChain(exec
))
1463 jsPropertyNameIterator
= JSPropertyNameIterator::create(exec
, o
);
1465 LLINT_OP(1) = JSValue(jsPropertyNameIterator
);
1466 LLINT_OP(2) = JSValue(o
);
1467 LLINT_OP(3) = Register::withInt(0);
1468 LLINT_OP(4) = Register::withInt(jsPropertyNameIterator
->size());
1470 pc
+= OPCODE_LENGTH(op_get_pnames
);
1474 LLINT_SLOW_PATH_DECL(slow_path_next_pname
)
1477 JSObject
* base
= asObject(LLINT_OP(2).jsValue());
1478 JSString
* property
= asString(LLINT_OP(1).jsValue());
1479 if (base
->hasProperty(exec
, Identifier(exec
, property
->value(exec
)))) {
1481 pc
+= pc
[6].u
.operand
;
1482 } // Else, don't change the PC, so the interpreter will reloop.
1486 LLINT_SLOW_PATH_DECL(slow_path_push_scope
)
1489 JSValue v
= LLINT_OP(1).jsValue();
1490 JSObject
* o
= v
.toObject(exec
);
1491 LLINT_CHECK_EXCEPTION();
1494 exec
->setScopeChain(exec
->scopeChain()->push(o
));
1499 LLINT_SLOW_PATH_DECL(slow_path_pop_scope
)
1502 exec
->setScopeChain(exec
->scopeChain()->pop());
1506 LLINT_SLOW_PATH_DECL(slow_path_push_new_scope
)
1509 CodeBlock
* codeBlock
= exec
->codeBlock();
1510 JSObject
* scope
= JSStaticScopeObject::create(exec
, codeBlock
->identifier(pc
[2].u
.operand
), LLINT_OP(3).jsValue(), DontDelete
);
1511 exec
->setScopeChain(exec
->scopeChain()->push(scope
));
1512 LLINT_RETURN(scope
);
1515 LLINT_SLOW_PATH_DECL(slow_path_throw
)
1518 LLINT_THROW(LLINT_OP_C(1).jsValue());
1521 LLINT_SLOW_PATH_DECL(slow_path_throw_reference_error
)
1524 LLINT_THROW(createReferenceError(exec
, LLINT_OP_C(1).jsValue().toString(exec
)->value(exec
)));
1527 LLINT_SLOW_PATH_DECL(slow_path_debug
)
1530 int debugHookID
= pc
[1].u
.operand
;
1531 int firstLine
= pc
[2].u
.operand
;
1532 int lastLine
= pc
[3].u
.operand
;
1534 globalData
.interpreter
->debug(exec
, static_cast<DebugHookID
>(debugHookID
), firstLine
, lastLine
);
1539 LLINT_SLOW_PATH_DECL(slow_path_profile_will_call
)
1542 (*Profiler::enabledProfilerReference())->willExecute(exec
, LLINT_OP(1).jsValue());
1546 LLINT_SLOW_PATH_DECL(slow_path_profile_did_call
)
1549 (*Profiler::enabledProfilerReference())->didExecute(exec
, LLINT_OP(1).jsValue());
1553 LLINT_SLOW_PATH_DECL(throw_from_native_call
)
1556 ASSERT(globalData
.exception
);
1560 } } // namespace JSC::LLInt
1562 #endif // ENABLE(LLINT)