2 * Copyright (C) 2011, 2012, 2013 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 "ArrayConstructor.h"
33 #include "CallFrame.h"
34 #include "CommonSlowPaths.h"
35 #include "GetterSetter.h"
36 #include "HostCallReturnValue.h"
37 #include "Interpreter.h"
39 #include "JITDriver.h"
40 #include "JSActivation.h"
41 #include "JSCJSValue.h"
42 #include "JSGlobalObjectFunctions.h"
43 #include "JSNameScope.h"
44 #include "JSPropertyNameIterator.h"
46 #include "JSWithScope.h"
47 #include "LLIntCommon.h"
48 #include "LLIntExceptions.h"
49 #include "LowLevelInterpreter.h"
50 #include "ObjectConstructor.h"
51 #include "Operations.h"
52 #include "StructureRareDataInlines.h"
53 #include <wtf/StringPrintStream.h>
55 namespace JSC
{ namespace LLInt
{
57 #define LLINT_BEGIN_NO_SET_PC() \
58 VM& vm = exec->vm(); \
59 NativeCallFrameTracer tracer(&vm, exec)
62 #define LLINT_SET_PC_FOR_STUBS() do { \
63 exec->codeBlock()->bytecodeOffset(pc); \
64 exec->setCurrentVPC(pc + 1); \
67 #define LLINT_SET_PC_FOR_STUBS() do { \
68 exec->setCurrentVPC(pc + 1); \
72 #define LLINT_BEGIN() \
73 LLINT_BEGIN_NO_SET_PC(); \
74 LLINT_SET_PC_FOR_STUBS()
76 #define LLINT_OP(index) (exec->uncheckedR(pc[index].u.operand))
77 #define LLINT_OP_C(index) (exec->r(pc[index].u.operand))
79 #define LLINT_RETURN_TWO(first, second) do { \
80 return encodeResult(first, second); \
83 #define LLINT_END_IMPL() LLINT_RETURN_TWO(pc, exec)
85 #define LLINT_THROW(exceptionToThrow) do { \
86 vm.exception = (exceptionToThrow); \
87 pc = returnToThrow(exec, pc); \
91 #define LLINT_CHECK_EXCEPTION() do { \
92 if (UNLIKELY(vm.exception)) { \
93 pc = returnToThrow(exec, pc); \
98 #define LLINT_END() do { \
99 LLINT_CHECK_EXCEPTION(); \
103 #define LLINT_BRANCH(opcode, condition) do { \
104 bool __b_condition = (condition); \
105 LLINT_CHECK_EXCEPTION(); \
107 pc += pc[OPCODE_LENGTH(opcode) - 1].u.operand; \
109 pc += OPCODE_LENGTH(opcode); \
113 #define LLINT_RETURN(value) do { \
114 JSValue __r_returnValue = (value); \
115 LLINT_CHECK_EXCEPTION(); \
116 LLINT_OP(1) = __r_returnValue; \
120 #if ENABLE(VALUE_PROFILER)
121 #define LLINT_RETURN_PROFILED(opcode, value) do { \
122 JSValue __rp_returnValue = (value); \
123 LLINT_CHECK_EXCEPTION(); \
124 LLINT_OP(1) = __rp_returnValue; \
125 LLINT_PROFILE_VALUE(opcode, __rp_returnValue); \
129 #define LLINT_PROFILE_VALUE(opcode, value) do { \
130 pc[OPCODE_LENGTH(opcode) - 1].u.profile->m_buckets[0] = \
131 JSValue::encode(value); \
134 #else // ENABLE(VALUE_PROFILER)
135 #define LLINT_RETURN_PROFILED(opcode, value) LLINT_RETURN(value)
137 #define LLINT_PROFILE_VALUE(opcode, value) do { } while (false)
139 #endif // ENABLE(VALUE_PROFILER)
141 #define LLINT_CALL_END_IMPL(exec, callTarget) LLINT_RETURN_TWO((callTarget), (exec))
143 #define LLINT_CALL_THROW(exec, pc, exceptionToThrow) do { \
144 ExecState* __ct_exec = (exec); \
145 Instruction* __ct_pc = (pc); \
146 vm.exception = (exceptionToThrow); \
147 LLINT_CALL_END_IMPL(__ct_exec, callToThrow(__ct_exec, __ct_pc)); \
150 #define LLINT_CALL_CHECK_EXCEPTION(exec, pc) do { \
151 ExecState* __cce_exec = (exec); \
152 Instruction* __cce_pc = (pc); \
153 if (UNLIKELY(vm.exception)) \
154 LLINT_CALL_END_IMPL(__cce_exec, callToThrow(__cce_exec, __cce_pc)); \
157 #define LLINT_CALL_RETURN(exec, pc, callTarget) do { \
158 ExecState* __cr_exec = (exec); \
159 Instruction* __cr_pc = (pc); \
160 void* __cr_callTarget = (callTarget); \
161 LLINT_CALL_CHECK_EXCEPTION(__cr_exec->callerFrame(), __cr_pc); \
162 LLINT_CALL_END_IMPL(__cr_exec, __cr_callTarget); \
165 extern "C" SlowPathReturnType
llint_trace_operand(ExecState
* exec
, Instruction
* pc
, int fromWhere
, int operand
)
168 dataLogF("%p / %p: executing bc#%zu, op#%u: Trace(%d): %d: %d\n",
171 static_cast<intptr_t>(pc
- exec
->codeBlock()->instructions().begin()),
172 exec
->vm().interpreter
->getOpcodeID(pc
[0].u
.opcode
),
175 pc
[operand
].u
.operand
);
179 extern "C" SlowPathReturnType
llint_trace_value(ExecState
* exec
, Instruction
* pc
, int fromWhere
, int operand
)
181 JSValue value
= LLINT_OP_C(operand
).jsValue();
187 EncodedJSValue asValue
;
189 u
.asValue
= JSValue::encode(value
);
191 "%p / %p: executing bc#%zu, op#%u: Trace(%d): %d: %d: %08x:%08x: %s\n",
194 static_cast<intptr_t>(pc
- exec
->codeBlock()->instructions().begin()),
195 exec
->vm().interpreter
->getOpcodeID(pc
[0].u
.opcode
),
198 pc
[operand
].u
.operand
,
201 toCString(value
).data());
205 LLINT_SLOW_PATH_DECL(trace_prologue
)
207 dataLogF("%p / %p: in prologue.\n", exec
->codeBlock(), exec
);
211 static void traceFunctionPrologue(ExecState
* exec
, const char* comment
, CodeSpecializationKind kind
)
213 JSFunction
* callee
= jsCast
<JSFunction
*>(exec
->callee());
214 FunctionExecutable
* executable
= callee
->jsExecutable();
215 CodeBlock
* codeBlock
= &executable
->generatedBytecodeFor(kind
);
216 dataLogF("%p / %p: in %s of function %p, executable %p; numVars = %u, numParameters = %u, numCalleeRegisters = %u, caller = %p.\n",
217 codeBlock
, exec
, comment
, callee
, executable
,
218 codeBlock
->m_numVars
, codeBlock
->numParameters(), codeBlock
->m_numCalleeRegisters
,
219 exec
->callerFrame());
222 LLINT_SLOW_PATH_DECL(trace_prologue_function_for_call
)
224 traceFunctionPrologue(exec
, "call prologue", CodeForCall
);
228 LLINT_SLOW_PATH_DECL(trace_prologue_function_for_construct
)
230 traceFunctionPrologue(exec
, "construct prologue", CodeForConstruct
);
234 LLINT_SLOW_PATH_DECL(trace_arityCheck_for_call
)
236 traceFunctionPrologue(exec
, "call arity check", CodeForCall
);
240 LLINT_SLOW_PATH_DECL(trace_arityCheck_for_construct
)
242 traceFunctionPrologue(exec
, "construct arity check", CodeForConstruct
);
246 LLINT_SLOW_PATH_DECL(trace
)
248 dataLogF("%p / %p: executing bc#%zu, %s, scope %p\n",
251 static_cast<intptr_t>(pc
- exec
->codeBlock()->instructions().begin()),
252 opcodeNames
[exec
->vm().interpreter
->getOpcodeID(pc
[0].u
.opcode
)],
254 if (exec
->vm().interpreter
->getOpcodeID(pc
[0].u
.opcode
) == op_ret
) {
255 dataLogF("Will be returning to %p\n", exec
->returnPC().value());
256 dataLogF("The new cfr will be %p\n", exec
->callerFrame());
261 LLINT_SLOW_PATH_DECL(special_trace
)
263 dataLogF("%p / %p: executing special case bc#%zu, op#%u, return PC is %p\n",
266 static_cast<intptr_t>(pc
- exec
->codeBlock()->instructions().begin()),
267 exec
->vm().interpreter
->getOpcodeID(pc
[0].u
.opcode
),
268 exec
->returnPC().value());
273 inline bool shouldJIT(ExecState
* exec
)
275 // You can modify this to turn off JITting without rebuilding the world.
276 return exec
->vm().canUseJIT();
279 // Returns true if we should try to OSR.
280 inline bool jitCompileAndSetHeuristics(CodeBlock
* codeBlock
, ExecState
* exec
)
282 codeBlock
->updateAllValueProfilePredictions();
284 if (!codeBlock
->checkIfJITThresholdReached()) {
285 #if ENABLE(JIT_VERBOSE_OSR)
286 dataLogF(" JIT threshold should be lifted.\n");
291 CodeBlock::JITCompilationResult result
= codeBlock
->jitCompile(exec
);
293 case CodeBlock::AlreadyCompiled
:
294 #if ENABLE(JIT_VERBOSE_OSR)
295 dataLogF(" Code was already compiled.\n");
297 codeBlock
->jitSoon();
299 case CodeBlock::CouldNotCompile
:
300 #if ENABLE(JIT_VERBOSE_OSR)
301 dataLogF(" JIT compilation failed.\n");
303 codeBlock
->dontJITAnytimeSoon();
305 case CodeBlock::CompiledSuccessfully
:
306 #if ENABLE(JIT_VERBOSE_OSR)
307 dataLogF(" JIT compilation successful.\n");
309 codeBlock
->jitSoon();
312 RELEASE_ASSERT_NOT_REACHED();
316 enum EntryKind
{ Prologue
, ArityCheck
};
317 static SlowPathReturnType
entryOSR(ExecState
* exec
, Instruction
*, CodeBlock
* codeBlock
, const char *name
, EntryKind kind
)
319 #if ENABLE(JIT_VERBOSE_OSR)
320 dataLog(*codeBlock
, ": Entered ", name
, " with executeCounter = ", codeBlock
->llintExecuteCounter(), "\n");
325 if (!shouldJIT(exec
)) {
326 codeBlock
->dontJITAnytimeSoon();
327 LLINT_RETURN_TWO(0, exec
);
329 if (!jitCompileAndSetHeuristics(codeBlock
, exec
))
330 LLINT_RETURN_TWO(0, exec
);
332 if (kind
== Prologue
)
333 LLINT_RETURN_TWO(codeBlock
->getJITCode().executableAddressAtOffset(0), exec
);
334 ASSERT(kind
== ArityCheck
);
335 LLINT_RETURN_TWO(codeBlock
->getJITCodeWithArityCheck().executableAddress(), exec
);
338 LLINT_SLOW_PATH_DECL(entry_osr
)
340 return entryOSR(exec
, pc
, exec
->codeBlock(), "entry_osr", Prologue
);
343 LLINT_SLOW_PATH_DECL(entry_osr_function_for_call
)
345 return entryOSR(exec
, pc
, &jsCast
<JSFunction
*>(exec
->callee())->jsExecutable()->generatedBytecodeFor(CodeForCall
), "entry_osr_function_for_call", Prologue
);
348 LLINT_SLOW_PATH_DECL(entry_osr_function_for_construct
)
350 return entryOSR(exec
, pc
, &jsCast
<JSFunction
*>(exec
->callee())->jsExecutable()->generatedBytecodeFor(CodeForConstruct
), "entry_osr_function_for_construct", Prologue
);
353 LLINT_SLOW_PATH_DECL(entry_osr_function_for_call_arityCheck
)
355 return entryOSR(exec
, pc
, &jsCast
<JSFunction
*>(exec
->callee())->jsExecutable()->generatedBytecodeFor(CodeForCall
), "entry_osr_function_for_call_arityCheck", ArityCheck
);
358 LLINT_SLOW_PATH_DECL(entry_osr_function_for_construct_arityCheck
)
360 return entryOSR(exec
, pc
, &jsCast
<JSFunction
*>(exec
->callee())->jsExecutable()->generatedBytecodeFor(CodeForConstruct
), "entry_osr_function_for_construct_arityCheck", ArityCheck
);
363 LLINT_SLOW_PATH_DECL(loop_osr
)
365 CodeBlock
* codeBlock
= exec
->codeBlock();
367 #if ENABLE(JIT_VERBOSE_OSR)
368 dataLog(*codeBlock
, ": Entered loop_osr with executeCounter = ", codeBlock
->llintExecuteCounter(), "\n");
371 if (!shouldJIT(exec
)) {
372 codeBlock
->dontJITAnytimeSoon();
373 LLINT_RETURN_TWO(0, exec
);
376 if (!jitCompileAndSetHeuristics(codeBlock
, exec
))
377 LLINT_RETURN_TWO(0, exec
);
379 ASSERT(codeBlock
->getJITType() == JITCode::BaselineJIT
);
381 Vector
<BytecodeAndMachineOffset
> map
;
382 codeBlock
->jitCodeMap()->decode(map
);
383 BytecodeAndMachineOffset
* mapping
= binarySearch
<BytecodeAndMachineOffset
, unsigned>(map
, map
.size(), pc
- codeBlock
->instructions().begin(), BytecodeAndMachineOffset::getBytecodeIndex
);
385 ASSERT(mapping
->m_bytecodeIndex
== static_cast<unsigned>(pc
- codeBlock
->instructions().begin()));
387 void* jumpTarget
= codeBlock
->getJITCode().executableAddressAtOffset(mapping
->m_machineCodeOffset
);
390 LLINT_RETURN_TWO(jumpTarget
, exec
);
393 LLINT_SLOW_PATH_DECL(replace
)
395 CodeBlock
* codeBlock
= exec
->codeBlock();
397 #if ENABLE(JIT_VERBOSE_OSR)
398 dataLog(*codeBlock
, ": Entered replace with executeCounter = ", codeBlock
->llintExecuteCounter(), "\n");
402 jitCompileAndSetHeuristics(codeBlock
, exec
);
404 codeBlock
->dontJITAnytimeSoon();
407 #endif // ENABLE(JIT)
409 LLINT_SLOW_PATH_DECL(stack_check
)
412 #if LLINT_SLOW_PATH_TRACING
413 dataLogF("Checking stack height with exec = %p.\n", exec
);
414 dataLogF("CodeBlock = %p.\n", exec
->codeBlock());
415 dataLogF("Num callee registers = %u.\n", exec
->codeBlock()->m_numCalleeRegisters
);
416 dataLogF("Num vars = %u.\n", exec
->codeBlock()->m_numVars
);
417 dataLogF("Current end is at %p.\n", exec
->vm().interpreter
->stack().end());
419 ASSERT(&exec
->registers()[exec
->codeBlock()->m_numCalleeRegisters
] > exec
->vm().interpreter
->stack().end());
420 if (UNLIKELY(!vm
.interpreter
->stack().grow(&exec
->registers()[exec
->codeBlock()->m_numCalleeRegisters
]))) {
421 ReturnAddressPtr returnPC
= exec
->returnPC();
422 exec
= exec
->callerFrame();
423 vm
.exception
= createStackOverflowError(exec
);
424 interpreterThrowInCaller(exec
, returnPC
);
425 pc
= returnToThrowForThrownException(exec
);
430 LLINT_SLOW_PATH_DECL(slow_path_call_arityCheck
)
433 ExecState
* newExec
= CommonSlowPaths::arityCheckFor(exec
, &vm
.interpreter
->stack(), CodeForCall
);
435 ReturnAddressPtr returnPC
= exec
->returnPC();
436 exec
= exec
->callerFrame();
437 vm
.exception
= createStackOverflowError(exec
);
438 interpreterThrowInCaller(exec
, returnPC
);
439 LLINT_RETURN_TWO(bitwise_cast
<void*>(static_cast<uintptr_t>(1)), exec
);
441 LLINT_RETURN_TWO(0, newExec
);
444 LLINT_SLOW_PATH_DECL(slow_path_construct_arityCheck
)
447 ExecState
* newExec
= CommonSlowPaths::arityCheckFor(exec
, &vm
.interpreter
->stack(), CodeForConstruct
);
449 ReturnAddressPtr returnPC
= exec
->returnPC();
450 exec
= exec
->callerFrame();
451 vm
.exception
= createStackOverflowError(exec
);
452 interpreterThrowInCaller(exec
, returnPC
);
453 LLINT_RETURN_TWO(bitwise_cast
<void*>(static_cast<uintptr_t>(1)), exec
);
455 LLINT_RETURN_TWO(0, newExec
);
458 LLINT_SLOW_PATH_DECL(slow_path_create_activation
)
461 #if LLINT_SLOW_PATH_TRACING
462 dataLogF("Creating an activation, exec = %p!\n", exec
);
464 JSActivation
* activation
= JSActivation::create(vm
, exec
, exec
->codeBlock());
465 exec
->setScope(activation
);
466 LLINT_RETURN(JSValue(activation
));
469 LLINT_SLOW_PATH_DECL(slow_path_create_arguments
)
472 JSValue arguments
= JSValue(Arguments::create(vm
, exec
));
473 LLINT_CHECK_EXCEPTION();
474 exec
->uncheckedR(pc
[1].u
.operand
) = arguments
;
475 exec
->uncheckedR(unmodifiedArgumentsRegister(pc
[1].u
.operand
)) = arguments
;
479 LLINT_SLOW_PATH_DECL(slow_path_create_this
)
482 JSFunction
* constructor
= jsCast
<JSFunction
*>(LLINT_OP(2).jsValue().asCell());
485 ConstructData constructData
;
486 ASSERT(constructor
->methodTable()->getConstructData(constructor
, constructData
) == ConstructTypeJS
);
489 size_t inlineCapacity
= pc
[3].u
.operand
;
490 Structure
* structure
= constructor
->allocationProfile(exec
, inlineCapacity
)->structure();
491 LLINT_RETURN(constructEmptyObject(exec
, structure
));
494 LLINT_SLOW_PATH_DECL(slow_path_convert_this
)
497 JSValue v1
= LLINT_OP(1).jsValue();
498 ASSERT(v1
.isPrimitive());
499 #if ENABLE(VALUE_PROFILER)
500 pc
[OPCODE_LENGTH(op_convert_this
) - 1].u
.profile
->m_buckets
[0] =
501 JSValue::encode(v1
.structureOrUndefined());
503 LLINT_RETURN(v1
.toThisObject(exec
));
506 LLINT_SLOW_PATH_DECL(slow_path_new_object
)
509 LLINT_RETURN(constructEmptyObject(exec
, pc
[3].u
.objectAllocationProfile
->structure()));
512 LLINT_SLOW_PATH_DECL(slow_path_new_array
)
515 LLINT_RETURN(constructArray(exec
, pc
[4].u
.arrayAllocationProfile
, bitwise_cast
<JSValue
*>(&LLINT_OP(2)), pc
[3].u
.operand
));
518 LLINT_SLOW_PATH_DECL(slow_path_new_array_with_size
)
521 LLINT_RETURN(constructArrayWithSizeQuirk(exec
, pc
[3].u
.arrayAllocationProfile
, exec
->lexicalGlobalObject(), LLINT_OP_C(2).jsValue()));
524 LLINT_SLOW_PATH_DECL(slow_path_new_array_buffer
)
527 LLINT_RETURN(constructArray(exec
, pc
[4].u
.arrayAllocationProfile
, exec
->codeBlock()->constantBuffer(pc
[2].u
.operand
), pc
[3].u
.operand
));
530 LLINT_SLOW_PATH_DECL(slow_path_new_regexp
)
533 RegExp
* regExp
= exec
->codeBlock()->regexp(pc
[2].u
.operand
);
534 if (!regExp
->isValid())
535 LLINT_THROW(createSyntaxError(exec
, "Invalid flag supplied to RegExp constructor."));
536 LLINT_RETURN(RegExpObject::create(vm
, exec
->lexicalGlobalObject(), exec
->lexicalGlobalObject()->regExpStructure(), regExp
));
539 LLINT_SLOW_PATH_DECL(slow_path_not
)
542 LLINT_RETURN(jsBoolean(!LLINT_OP_C(2).jsValue().toBoolean(exec
)));
545 LLINT_SLOW_PATH_DECL(slow_path_eq
)
548 LLINT_RETURN(jsBoolean(JSValue::equal(exec
, LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue())));
551 LLINT_SLOW_PATH_DECL(slow_path_neq
)
554 LLINT_RETURN(jsBoolean(!JSValue::equal(exec
, LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue())));
557 LLINT_SLOW_PATH_DECL(slow_path_stricteq
)
560 LLINT_RETURN(jsBoolean(JSValue::strictEqual(exec
, LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue())));
563 LLINT_SLOW_PATH_DECL(slow_path_nstricteq
)
566 LLINT_RETURN(jsBoolean(!JSValue::strictEqual(exec
, LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue())));
569 LLINT_SLOW_PATH_DECL(slow_path_less
)
572 LLINT_RETURN(jsBoolean(jsLess
<true>(exec
, LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue())));
575 LLINT_SLOW_PATH_DECL(slow_path_lesseq
)
578 LLINT_RETURN(jsBoolean(jsLessEq
<true>(exec
, LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue())));
581 LLINT_SLOW_PATH_DECL(slow_path_greater
)
584 LLINT_RETURN(jsBoolean(jsLess
<false>(exec
, LLINT_OP_C(3).jsValue(), LLINT_OP_C(2).jsValue())));
587 LLINT_SLOW_PATH_DECL(slow_path_greatereq
)
590 LLINT_RETURN(jsBoolean(jsLessEq
<false>(exec
, LLINT_OP_C(3).jsValue(), LLINT_OP_C(2).jsValue())));
593 LLINT_SLOW_PATH_DECL(slow_path_pre_inc
)
596 LLINT_RETURN(jsNumber(LLINT_OP(1).jsValue().toNumber(exec
) + 1));
599 LLINT_SLOW_PATH_DECL(slow_path_pre_dec
)
602 LLINT_RETURN(jsNumber(LLINT_OP(1).jsValue().toNumber(exec
) - 1));
605 LLINT_SLOW_PATH_DECL(slow_path_to_number
)
608 LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toNumber(exec
)));
611 LLINT_SLOW_PATH_DECL(slow_path_negate
)
614 LLINT_RETURN(jsNumber(-LLINT_OP_C(2).jsValue().toNumber(exec
)));
617 LLINT_SLOW_PATH_DECL(slow_path_add
)
620 JSValue v1
= LLINT_OP_C(2).jsValue();
621 JSValue v2
= LLINT_OP_C(3).jsValue();
623 #if LLINT_SLOW_PATH_TRACING
624 dataLog("Trying to add ", v1
, " to ", v2
, ".\n");
627 if (v1
.isString() && !v2
.isObject())
628 LLINT_RETURN(jsString(exec
, asString(v1
), v2
.toString(exec
)));
630 if (v1
.isNumber() && v2
.isNumber())
631 LLINT_RETURN(jsNumber(v1
.asNumber() + v2
.asNumber()));
633 LLINT_RETURN(jsAddSlowCase(exec
, v1
, v2
));
636 // The following arithmetic and bitwise operations need to be sure to run
637 // toNumber() on their operands in order. (A call to toNumber() is idempotent
638 // if an exception is already set on the ExecState.)
640 LLINT_SLOW_PATH_DECL(slow_path_mul
)
643 double a
= LLINT_OP_C(2).jsValue().toNumber(exec
);
644 double b
= LLINT_OP_C(3).jsValue().toNumber(exec
);
645 LLINT_RETURN(jsNumber(a
* b
));
648 LLINT_SLOW_PATH_DECL(slow_path_sub
)
651 double a
= LLINT_OP_C(2).jsValue().toNumber(exec
);
652 double b
= LLINT_OP_C(3).jsValue().toNumber(exec
);
653 LLINT_RETURN(jsNumber(a
- b
));
656 LLINT_SLOW_PATH_DECL(slow_path_div
)
659 double a
= LLINT_OP_C(2).jsValue().toNumber(exec
);
660 double b
= LLINT_OP_C(3).jsValue().toNumber(exec
);
661 LLINT_RETURN(jsNumber(a
/ b
));
664 LLINT_SLOW_PATH_DECL(slow_path_mod
)
667 double a
= LLINT_OP_C(2).jsValue().toNumber(exec
);
668 double b
= LLINT_OP_C(3).jsValue().toNumber(exec
);
669 LLINT_RETURN(jsNumber(fmod(a
, b
)));
672 LLINT_SLOW_PATH_DECL(slow_path_lshift
)
675 int32_t a
= LLINT_OP_C(2).jsValue().toInt32(exec
);
676 uint32_t b
= LLINT_OP_C(3).jsValue().toUInt32(exec
);
677 LLINT_RETURN(jsNumber(a
<< (b
& 31)));
680 LLINT_SLOW_PATH_DECL(slow_path_rshift
)
683 int32_t a
= LLINT_OP_C(2).jsValue().toInt32(exec
);
684 uint32_t b
= LLINT_OP_C(3).jsValue().toUInt32(exec
);
685 LLINT_RETURN(jsNumber(a
>> (b
& 31)));
688 LLINT_SLOW_PATH_DECL(slow_path_urshift
)
691 uint32_t a
= LLINT_OP_C(2).jsValue().toUInt32(exec
);
692 uint32_t b
= LLINT_OP_C(3).jsValue().toUInt32(exec
);
693 LLINT_RETURN(jsNumber(a
>> (b
& 31)));
696 LLINT_SLOW_PATH_DECL(slow_path_bitand
)
699 int32_t a
= LLINT_OP_C(2).jsValue().toInt32(exec
);
700 int32_t b
= LLINT_OP_C(3).jsValue().toInt32(exec
);
701 LLINT_RETURN(jsNumber(a
& b
));
704 LLINT_SLOW_PATH_DECL(slow_path_bitor
)
707 int32_t a
= LLINT_OP_C(2).jsValue().toInt32(exec
);
708 int32_t b
= LLINT_OP_C(3).jsValue().toInt32(exec
);
709 LLINT_RETURN(jsNumber(a
| b
));
712 LLINT_SLOW_PATH_DECL(slow_path_bitxor
)
715 int32_t a
= LLINT_OP_C(2).jsValue().toInt32(exec
);
716 int32_t b
= LLINT_OP_C(3).jsValue().toInt32(exec
);
717 LLINT_RETURN(jsNumber(a
^ b
));
720 LLINT_SLOW_PATH_DECL(slow_path_check_has_instance
)
724 JSValue value
= LLINT_OP_C(2).jsValue();
725 JSValue baseVal
= LLINT_OP_C(3).jsValue();
726 if (baseVal
.isObject()) {
727 JSObject
* baseObject
= asObject(baseVal
);
728 ASSERT(!baseObject
->structure()->typeInfo().implementsDefaultHasInstance());
729 if (baseObject
->structure()->typeInfo().implementsHasInstance()) {
730 pc
+= pc
[4].u
.operand
;
731 LLINT_RETURN(jsBoolean(baseObject
->methodTable()->customHasInstance(baseObject
, exec
, value
)));
734 LLINT_THROW(createInvalidParamError(exec
, "instanceof", baseVal
));
737 LLINT_SLOW_PATH_DECL(slow_path_instanceof
)
740 JSValue value
= LLINT_OP_C(2).jsValue();
741 JSValue proto
= LLINT_OP_C(3).jsValue();
742 ASSERT(!value
.isObject() || !proto
.isObject());
743 LLINT_RETURN(jsBoolean(JSObject::defaultHasInstance(exec
, value
, proto
)));
746 LLINT_SLOW_PATH_DECL(slow_path_typeof
)
749 LLINT_RETURN(jsTypeStringForValue(exec
, LLINT_OP_C(2).jsValue()));
752 LLINT_SLOW_PATH_DECL(slow_path_is_object
)
755 LLINT_RETURN(jsBoolean(jsIsObjectType(exec
, LLINT_OP_C(2).jsValue())));
758 LLINT_SLOW_PATH_DECL(slow_path_is_function
)
761 LLINT_RETURN(jsBoolean(jsIsFunctionType(LLINT_OP_C(2).jsValue())));
764 LLINT_SLOW_PATH_DECL(slow_path_in
)
767 LLINT_RETURN(jsBoolean(CommonSlowPaths::opIn(exec
, LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue())));
770 LLINT_SLOW_PATH_DECL(slow_path_resolve
)
773 Identifier ident
= exec
->codeBlock()->identifier(pc
[2].u
.operand
);
774 ResolveOperations
* operations
= pc
[3].u
.resolveOperations
;
775 JSValue result
= JSScope::resolve(exec
, ident
, operations
);
776 ASSERT(operations
->size());
777 if (operations
->isEmpty())
778 LLINT_RETURN_PROFILED(op_resolve
, result
);
780 switch (operations
->data()[0].m_operation
) {
781 case ResolveOperation::GetAndReturnGlobalProperty
:
782 pc
[0].u
.opcode
= LLInt::getOpcode(llint_op_resolve_global_property
);
785 case ResolveOperation::GetAndReturnGlobalVar
:
786 pc
[0].u
.opcode
= LLInt::getOpcode(llint_op_resolve_global_var
);
789 case ResolveOperation::SkipTopScopeNode
:
790 pc
[0].u
.opcode
= LLInt::getOpcode(llint_op_resolve_scoped_var_with_top_scope_check
);
793 case ResolveOperation::SkipScopes
:
794 if (operations
->data()[0].m_scopesToSkip
)
795 pc
[0].u
.opcode
= LLInt::getOpcode(llint_op_resolve_scoped_var
);
797 pc
[0].u
.opcode
= LLInt::getOpcode(llint_op_resolve_scoped_var_on_top_scope
);
803 LLINT_RETURN_PROFILED(op_resolve
, result
);
806 LLINT_SLOW_PATH_DECL(slow_path_put_to_base
)
809 PutToBaseOperation
* operation
= pc
[4].u
.putToBaseOperation
;
810 JSScope::resolvePut(exec
, LLINT_OP_C(1).jsValue(), exec
->codeBlock()->identifier(pc
[2].u
.operand
), LLINT_OP_C(3).jsValue(), operation
);
811 switch (operation
->m_kind
) {
812 case PutToBaseOperation::VariablePut
:
813 pc
[0].u
.opcode
= LLInt::getOpcode(llint_op_put_to_base_variable
);
822 LLINT_SLOW_PATH_DECL(slow_path_resolve_base
)
825 Identifier
& ident
= exec
->codeBlock()->identifier(pc
[2].u
.operand
);
826 ResolveOperations
* operations
= pc
[4].u
.resolveOperations
;
828 if (pc
[3].u
.operand
) {
829 result
= JSScope::resolveBase(exec
, ident
, true, operations
, pc
[5].u
.putToBaseOperation
);
831 LLINT_THROW(vm
.exception
);
833 result
= JSScope::resolveBase(exec
, ident
, false, operations
, pc
[5].u
.putToBaseOperation
);
835 ASSERT(operations
->size());
836 if (operations
->isEmpty()) {
837 LLINT_PROFILE_VALUE(op_resolve_base
, result
);
838 LLINT_RETURN(result
);
841 switch (operations
->data()[0].m_operation
) {
842 case ResolveOperation::ReturnGlobalObjectAsBase
:
843 pc
[0].u
.opcode
= LLInt::getOpcode(llint_op_resolve_base_to_global
);
846 case ResolveOperation::SkipTopScopeNode
:
847 pc
[0].u
.opcode
= LLInt::getOpcode(llint_op_resolve_base_to_scope_with_top_scope_check
);
850 case ResolveOperation::SkipScopes
:
851 pc
[0].u
.opcode
= LLInt::getOpcode(llint_op_resolve_base_to_scope
);
857 LLINT_PROFILE_VALUE(op_resolve_base
, result
);
858 LLINT_RETURN(result
);
861 LLINT_SLOW_PATH_DECL(slow_path_resolve_with_base
)
864 ResolveOperations
* operations
= pc
[4].u
.resolveOperations
;
865 JSValue result
= JSScope::resolveWithBase(exec
, exec
->codeBlock()->identifier(pc
[3].u
.operand
), &LLINT_OP(1), operations
, pc
[5].u
.putToBaseOperation
);
866 LLINT_CHECK_EXCEPTION();
867 LLINT_OP(2) = result
;
868 LLINT_PROFILE_VALUE(op_resolve_with_base
, result
);
872 LLINT_SLOW_PATH_DECL(slow_path_resolve_with_this
)
875 ResolveOperations
* operations
= pc
[4].u
.resolveOperations
;
876 JSValue result
= JSScope::resolveWithThis(exec
, exec
->codeBlock()->identifier(pc
[3].u
.operand
), &LLINT_OP(1), operations
);
877 LLINT_CHECK_EXCEPTION();
878 LLINT_OP(2) = result
;
879 LLINT_PROFILE_VALUE(op_resolve_with_this
, result
);
883 LLINT_SLOW_PATH_DECL(slow_path_init_global_const_check
)
886 CodeBlock
* codeBlock
= exec
->codeBlock();
887 symbolTablePut(codeBlock
->globalObject(), exec
, codeBlock
->identifier(pc
[4].u
.operand
), LLINT_OP_C(2).jsValue(), true);
891 LLINT_SLOW_PATH_DECL(slow_path_get_by_id
)
894 CodeBlock
* codeBlock
= exec
->codeBlock();
895 Identifier
& ident
= codeBlock
->identifier(pc
[3].u
.operand
);
896 JSValue baseValue
= LLINT_OP_C(2).jsValue();
897 PropertySlot
slot(baseValue
);
899 JSValue result
= baseValue
.get(exec
, ident
, slot
);
900 LLINT_CHECK_EXCEPTION();
901 LLINT_OP(1) = result
;
903 if (!LLINT_ALWAYS_ACCESS_SLOW
904 && baseValue
.isCell()
905 && slot
.isCacheable()
906 && slot
.slotBase() == baseValue
907 && slot
.cachedPropertyType() == PropertySlot::Value
) {
909 JSCell
* baseCell
= baseValue
.asCell();
910 Structure
* structure
= baseCell
->structure();
912 if (!structure
->isUncacheableDictionary()
913 && !structure
->typeInfo().prohibitsPropertyCaching()) {
914 pc
[4].u
.structure
.set(
915 vm
, codeBlock
->ownerExecutable(), structure
);
916 if (isInlineOffset(slot
.cachedOffset())) {
917 pc
[0].u
.opcode
= LLInt::getOpcode(llint_op_get_by_id
);
918 pc
[5].u
.operand
= offsetInInlineStorage(slot
.cachedOffset()) * sizeof(JSValue
) + JSObject::offsetOfInlineStorage();
920 pc
[0].u
.opcode
= LLInt::getOpcode(llint_op_get_by_id_out_of_line
);
921 pc
[5].u
.operand
= offsetInButterfly(slot
.cachedOffset()) * sizeof(JSValue
);
926 if (!LLINT_ALWAYS_ACCESS_SLOW
927 && isJSArray(baseValue
)
928 && ident
== exec
->propertyNames().length
) {
929 pc
[0].u
.opcode
= LLInt::getOpcode(llint_op_get_array_length
);
930 #if ENABLE(VALUE_PROFILER)
931 ArrayProfile
* arrayProfile
= codeBlock
->getOrAddArrayProfile(pc
- codeBlock
->instructions().begin());
932 arrayProfile
->observeStructure(baseValue
.asCell()->structure());
933 pc
[4].u
.arrayProfile
= arrayProfile
;
937 #if ENABLE(VALUE_PROFILER)
938 pc
[OPCODE_LENGTH(op_get_by_id
) - 1].u
.profile
->m_buckets
[0] = JSValue::encode(result
);
943 LLINT_SLOW_PATH_DECL(slow_path_get_arguments_length
)
946 CodeBlock
* codeBlock
= exec
->codeBlock();
947 Identifier
& ident
= codeBlock
->identifier(pc
[3].u
.operand
);
948 JSValue baseValue
= LLINT_OP(2).jsValue();
949 PropertySlot
slot(baseValue
);
950 LLINT_RETURN(baseValue
.get(exec
, ident
, slot
));
953 LLINT_SLOW_PATH_DECL(slow_path_put_by_id
)
956 CodeBlock
* codeBlock
= exec
->codeBlock();
957 Identifier
& ident
= codeBlock
->identifier(pc
[2].u
.operand
);
959 JSValue baseValue
= LLINT_OP_C(1).jsValue();
960 PutPropertySlot
slot(codeBlock
->isStrictMode());
962 asObject(baseValue
)->putDirect(vm
, ident
, LLINT_OP_C(3).jsValue(), slot
);
964 baseValue
.put(exec
, ident
, LLINT_OP_C(3).jsValue(), slot
);
965 LLINT_CHECK_EXCEPTION();
967 if (!LLINT_ALWAYS_ACCESS_SLOW
968 && baseValue
.isCell()
969 && slot
.isCacheable()) {
971 JSCell
* baseCell
= baseValue
.asCell();
972 Structure
* structure
= baseCell
->structure();
974 if (!structure
->isUncacheableDictionary()
975 && !structure
->typeInfo().prohibitsPropertyCaching()
976 && baseCell
== slot
.base()) {
978 if (slot
.type() == PutPropertySlot::NewProperty
) {
979 if (!structure
->isDictionary() && structure
->previousID()->outOfLineCapacity() == structure
->outOfLineCapacity()) {
980 ASSERT(structure
->previousID()->transitionWatchpointSetHasBeenInvalidated());
982 // This is needed because some of the methods we call
984 pc
[0].u
.opcode
= LLInt::getOpcode(llint_op_put_by_id
);
986 if (normalizePrototypeChain(exec
, baseCell
) != InvalidPrototypeChain
) {
987 ASSERT(structure
->previousID()->isObject());
988 pc
[4].u
.structure
.set(
989 vm
, codeBlock
->ownerExecutable(), structure
->previousID());
990 if (isInlineOffset(slot
.cachedOffset()))
991 pc
[5].u
.operand
= offsetInInlineStorage(slot
.cachedOffset()) * sizeof(JSValue
) + JSObject::offsetOfInlineStorage();
993 pc
[5].u
.operand
= offsetInButterfly(slot
.cachedOffset()) * sizeof(JSValue
);
994 pc
[6].u
.structure
.set(
995 vm
, codeBlock
->ownerExecutable(), structure
);
996 StructureChain
* chain
= structure
->prototypeChain(exec
);
998 pc
[7].u
.structureChain
.set(
999 vm
, codeBlock
->ownerExecutable(), chain
);
1001 if (pc
[8].u
.operand
) {
1002 if (isInlineOffset(slot
.cachedOffset()))
1003 pc
[0].u
.opcode
= LLInt::getOpcode(llint_op_put_by_id_transition_direct
);
1005 pc
[0].u
.opcode
= LLInt::getOpcode(llint_op_put_by_id_transition_direct_out_of_line
);
1007 if (isInlineOffset(slot
.cachedOffset()))
1008 pc
[0].u
.opcode
= LLInt::getOpcode(llint_op_put_by_id_transition_normal
);
1010 pc
[0].u
.opcode
= LLInt::getOpcode(llint_op_put_by_id_transition_normal_out_of_line
);
1015 pc
[4].u
.structure
.set(
1016 vm
, codeBlock
->ownerExecutable(), structure
);
1017 if (isInlineOffset(slot
.cachedOffset())) {
1018 pc
[0].u
.opcode
= LLInt::getOpcode(llint_op_put_by_id
);
1019 pc
[5].u
.operand
= offsetInInlineStorage(slot
.cachedOffset()) * sizeof(JSValue
) + JSObject::offsetOfInlineStorage();
1021 pc
[0].u
.opcode
= LLInt::getOpcode(llint_op_put_by_id_out_of_line
);
1022 pc
[5].u
.operand
= offsetInButterfly(slot
.cachedOffset()) * sizeof(JSValue
);
1031 LLINT_SLOW_PATH_DECL(slow_path_del_by_id
)
1034 CodeBlock
* codeBlock
= exec
->codeBlock();
1035 JSObject
* baseObject
= LLINT_OP_C(2).jsValue().toObject(exec
);
1036 bool couldDelete
= baseObject
->methodTable()->deleteProperty(baseObject
, exec
, codeBlock
->identifier(pc
[3].u
.operand
));
1037 LLINT_CHECK_EXCEPTION();
1038 if (!couldDelete
&& codeBlock
->isStrictMode())
1039 LLINT_THROW(createTypeError(exec
, "Unable to delete property."));
1040 LLINT_RETURN(jsBoolean(couldDelete
));
1043 inline JSValue
getByVal(ExecState
* exec
, JSValue baseValue
, JSValue subscript
)
1045 if (LIKELY(baseValue
.isCell() && subscript
.isString())) {
1046 if (JSValue result
= baseValue
.asCell()->fastGetOwnProperty(exec
, asString(subscript
)->value(exec
)))
1050 if (subscript
.isUInt32()) {
1051 uint32_t i
= subscript
.asUInt32();
1052 if (isJSString(baseValue
) && asString(baseValue
)->canGetIndex(i
))
1053 return asString(baseValue
)->getIndex(exec
, i
);
1055 return baseValue
.get(exec
, i
);
1058 if (isName(subscript
))
1059 return baseValue
.get(exec
, jsCast
<NameInstance
*>(subscript
.asCell())->privateName());
1061 Identifier
property(exec
, subscript
.toString(exec
)->value(exec
));
1062 return baseValue
.get(exec
, property
);
1065 LLINT_SLOW_PATH_DECL(slow_path_get_by_val
)
1068 LLINT_RETURN_PROFILED(op_get_by_val
, getByVal(exec
, LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue()));
1071 LLINT_SLOW_PATH_DECL(slow_path_get_argument_by_val
)
1074 JSValue arguments
= LLINT_OP(2).jsValue();
1076 arguments
= Arguments::create(vm
, exec
);
1077 LLINT_CHECK_EXCEPTION();
1078 LLINT_OP(2) = arguments
;
1079 exec
->uncheckedR(unmodifiedArgumentsRegister(pc
[2].u
.operand
)) = arguments
;
1082 LLINT_RETURN_PROFILED(op_get_argument_by_val
, getByVal(exec
, arguments
, LLINT_OP_C(3).jsValue()));
1085 LLINT_SLOW_PATH_DECL(slow_path_get_by_pname
)
1088 LLINT_RETURN(getByVal(exec
, LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue()));
1091 LLINT_SLOW_PATH_DECL(slow_path_put_by_val
)
1095 JSValue baseValue
= LLINT_OP_C(1).jsValue();
1096 JSValue subscript
= LLINT_OP_C(2).jsValue();
1097 JSValue value
= LLINT_OP_C(3).jsValue();
1099 if (LIKELY(subscript
.isUInt32())) {
1100 uint32_t i
= subscript
.asUInt32();
1101 if (baseValue
.isObject()) {
1102 JSObject
* object
= asObject(baseValue
);
1103 if (object
->canSetIndexQuickly(i
))
1104 object
->setIndexQuickly(vm
, i
, value
);
1106 object
->methodTable()->putByIndex(object
, exec
, i
, value
, exec
->codeBlock()->isStrictMode());
1109 baseValue
.putByIndex(exec
, i
, value
, exec
->codeBlock()->isStrictMode());
1113 if (isName(subscript
)) {
1114 PutPropertySlot
slot(exec
->codeBlock()->isStrictMode());
1115 baseValue
.put(exec
, jsCast
<NameInstance
*>(subscript
.asCell())->privateName(), value
, slot
);
1119 Identifier
property(exec
, subscript
.toString(exec
)->value(exec
));
1120 LLINT_CHECK_EXCEPTION();
1121 PutPropertySlot
slot(exec
->codeBlock()->isStrictMode());
1122 baseValue
.put(exec
, property
, value
, slot
);
1126 LLINT_SLOW_PATH_DECL(slow_path_del_by_val
)
1129 JSValue baseValue
= LLINT_OP_C(2).jsValue();
1130 JSObject
* baseObject
= baseValue
.toObject(exec
);
1132 JSValue subscript
= LLINT_OP_C(3).jsValue();
1137 if (subscript
.getUInt32(i
))
1138 couldDelete
= baseObject
->methodTable()->deletePropertyByIndex(baseObject
, exec
, i
);
1139 else if (isName(subscript
))
1140 couldDelete
= baseObject
->methodTable()->deleteProperty(baseObject
, exec
, jsCast
<NameInstance
*>(subscript
.asCell())->privateName());
1142 LLINT_CHECK_EXCEPTION();
1143 Identifier
property(exec
, subscript
.toString(exec
)->value(exec
));
1144 LLINT_CHECK_EXCEPTION();
1145 couldDelete
= baseObject
->methodTable()->deleteProperty(baseObject
, exec
, property
);
1148 if (!couldDelete
&& exec
->codeBlock()->isStrictMode())
1149 LLINT_THROW(createTypeError(exec
, "Unable to delete property."));
1151 LLINT_RETURN(jsBoolean(couldDelete
));
1154 LLINT_SLOW_PATH_DECL(slow_path_put_by_index
)
1157 JSValue arrayValue
= LLINT_OP_C(1).jsValue();
1158 ASSERT(isJSArray(arrayValue
));
1159 asArray(arrayValue
)->putDirectIndex(exec
, pc
[2].u
.operand
, LLINT_OP_C(3).jsValue());
1163 LLINT_SLOW_PATH_DECL(slow_path_put_getter_setter
)
1166 ASSERT(LLINT_OP(1).jsValue().isObject());
1167 JSObject
* baseObj
= asObject(LLINT_OP(1).jsValue());
1169 GetterSetter
* accessor
= GetterSetter::create(exec
);
1170 LLINT_CHECK_EXCEPTION();
1172 JSValue getter
= LLINT_OP(3).jsValue();
1173 JSValue setter
= LLINT_OP(4).jsValue();
1174 ASSERT(getter
.isObject() || getter
.isUndefined());
1175 ASSERT(setter
.isObject() || setter
.isUndefined());
1176 ASSERT(getter
.isObject() || setter
.isObject());
1178 if (!getter
.isUndefined())
1179 accessor
->setGetter(vm
, asObject(getter
));
1180 if (!setter
.isUndefined())
1181 accessor
->setSetter(vm
, asObject(setter
));
1182 baseObj
->putDirectAccessor(
1184 exec
->codeBlock()->identifier(pc
[2].u
.operand
),
1185 accessor
, Accessor
);
1189 LLINT_SLOW_PATH_DECL(slow_path_jtrue
)
1192 LLINT_BRANCH(op_jtrue
, LLINT_OP_C(1).jsValue().toBoolean(exec
));
1195 LLINT_SLOW_PATH_DECL(slow_path_jfalse
)
1198 LLINT_BRANCH(op_jfalse
, !LLINT_OP_C(1).jsValue().toBoolean(exec
));
1201 LLINT_SLOW_PATH_DECL(slow_path_jless
)
1204 LLINT_BRANCH(op_jless
, jsLess
<true>(exec
, LLINT_OP_C(1).jsValue(), LLINT_OP_C(2).jsValue()));
1207 LLINT_SLOW_PATH_DECL(slow_path_jnless
)
1210 LLINT_BRANCH(op_jnless
, !jsLess
<true>(exec
, LLINT_OP_C(1).jsValue(), LLINT_OP_C(2).jsValue()));
1213 LLINT_SLOW_PATH_DECL(slow_path_jgreater
)
1216 LLINT_BRANCH(op_jgreater
, jsLess
<false>(exec
, LLINT_OP_C(2).jsValue(), LLINT_OP_C(1).jsValue()));
1219 LLINT_SLOW_PATH_DECL(slow_path_jngreater
)
1222 LLINT_BRANCH(op_jngreater
, !jsLess
<false>(exec
, LLINT_OP_C(2).jsValue(), LLINT_OP_C(1).jsValue()));
1225 LLINT_SLOW_PATH_DECL(slow_path_jlesseq
)
1228 LLINT_BRANCH(op_jlesseq
, jsLessEq
<true>(exec
, LLINT_OP_C(1).jsValue(), LLINT_OP_C(2).jsValue()));
1231 LLINT_SLOW_PATH_DECL(slow_path_jnlesseq
)
1234 LLINT_BRANCH(op_jnlesseq
, !jsLessEq
<true>(exec
, LLINT_OP_C(1).jsValue(), LLINT_OP_C(2).jsValue()));
1237 LLINT_SLOW_PATH_DECL(slow_path_jgreatereq
)
1240 LLINT_BRANCH(op_jgreatereq
, jsLessEq
<false>(exec
, LLINT_OP_C(2).jsValue(), LLINT_OP_C(1).jsValue()));
1243 LLINT_SLOW_PATH_DECL(slow_path_jngreatereq
)
1246 LLINT_BRANCH(op_jngreatereq
, !jsLessEq
<false>(exec
, LLINT_OP_C(2).jsValue(), LLINT_OP_C(1).jsValue()));
1249 LLINT_SLOW_PATH_DECL(slow_path_switch_imm
)
1252 JSValue scrutinee
= LLINT_OP_C(3).jsValue();
1253 ASSERT(scrutinee
.isDouble());
1254 double value
= scrutinee
.asDouble();
1255 int32_t intValue
= static_cast<int32_t>(value
);
1256 int defaultOffset
= pc
[2].u
.operand
;
1257 if (value
== intValue
) {
1258 CodeBlock
* codeBlock
= exec
->codeBlock();
1259 pc
+= codeBlock
->immediateSwitchJumpTable(pc
[1].u
.operand
).offsetForValue(intValue
, defaultOffset
);
1261 pc
+= defaultOffset
;
1265 LLINT_SLOW_PATH_DECL(slow_path_switch_char
)
1268 JSValue scrutinee
= LLINT_OP_C(3).jsValue();
1269 ASSERT(scrutinee
.isString());
1270 JSString
* string
= asString(scrutinee
);
1271 ASSERT(string
->length() == 1);
1272 int defaultOffset
= pc
[2].u
.operand
;
1273 StringImpl
* impl
= string
->value(exec
).impl();
1274 CodeBlock
* codeBlock
= exec
->codeBlock();
1275 pc
+= codeBlock
->characterSwitchJumpTable(pc
[1].u
.operand
).offsetForValue((*impl
)[0], defaultOffset
);
1279 LLINT_SLOW_PATH_DECL(slow_path_switch_string
)
1282 JSValue scrutinee
= LLINT_OP_C(3).jsValue();
1283 int defaultOffset
= pc
[2].u
.operand
;
1284 if (!scrutinee
.isString())
1285 pc
+= defaultOffset
;
1287 CodeBlock
* codeBlock
= exec
->codeBlock();
1288 pc
+= codeBlock
->stringSwitchJumpTable(pc
[1].u
.operand
).offsetForValue(asString(scrutinee
)->value(exec
).impl(), defaultOffset
);
1293 LLINT_SLOW_PATH_DECL(slow_path_new_func
)
1296 CodeBlock
* codeBlock
= exec
->codeBlock();
1297 ASSERT(codeBlock
->codeType() != FunctionCode
1298 || !codeBlock
->needsFullScopeChain()
1299 || exec
->uncheckedR(codeBlock
->activationRegister()).jsValue());
1300 #if LLINT_SLOW_PATH_TRACING
1301 dataLogF("Creating function!\n");
1303 LLINT_RETURN(JSFunction::create(exec
, codeBlock
->functionDecl(pc
[2].u
.operand
), exec
->scope()));
1306 LLINT_SLOW_PATH_DECL(slow_path_new_func_exp
)
1309 CodeBlock
* codeBlock
= exec
->codeBlock();
1310 FunctionExecutable
* function
= codeBlock
->functionExpr(pc
[2].u
.operand
);
1311 JSFunction
* func
= JSFunction::create(exec
, function
, exec
->scope());
1316 static SlowPathReturnType
handleHostCall(ExecState
* execCallee
, Instruction
* pc
, JSValue callee
, CodeSpecializationKind kind
)
1318 #if LLINT_SLOW_PATH_TRACING
1319 dataLog("Performing host call.\n");
1322 ExecState
* exec
= execCallee
->callerFrame();
1323 VM
& vm
= exec
->vm();
1325 execCallee
->setScope(exec
->scope());
1326 execCallee
->setCodeBlock(0);
1327 execCallee
->clearReturnPC();
1329 if (kind
== CodeForCall
) {
1331 CallType callType
= getCallData(callee
, callData
);
1333 ASSERT(callType
!= CallTypeJS
);
1335 if (callType
== CallTypeHost
) {
1336 NativeCallFrameTracer
tracer(&vm
, execCallee
);
1337 execCallee
->setCallee(asObject(callee
));
1338 vm
.hostCallReturnValue
= JSValue::decode(callData
.native
.function(execCallee
));
1340 LLINT_CALL_RETURN(execCallee
, pc
, LLInt::getCodePtr(getHostCallReturnValue
));
1343 #if LLINT_SLOW_PATH_TRACING
1344 dataLog("Call callee is not a function: ", callee
, "\n");
1347 ASSERT(callType
== CallTypeNone
);
1348 LLINT_CALL_THROW(exec
, pc
, createNotAFunctionError(exec
, callee
));
1351 ASSERT(kind
== CodeForConstruct
);
1353 ConstructData constructData
;
1354 ConstructType constructType
= getConstructData(callee
, constructData
);
1356 ASSERT(constructType
!= ConstructTypeJS
);
1358 if (constructType
== ConstructTypeHost
) {
1359 NativeCallFrameTracer
tracer(&vm
, execCallee
);
1360 execCallee
->setCallee(asObject(callee
));
1361 vm
.hostCallReturnValue
= JSValue::decode(constructData
.native
.function(execCallee
));
1363 LLINT_CALL_RETURN(execCallee
, pc
, LLInt::getCodePtr(getHostCallReturnValue
));
1366 #if LLINT_SLOW_PATH_TRACING
1367 dataLog("Constructor callee is not a function: ", callee
, "\n");
1370 ASSERT(constructType
== ConstructTypeNone
);
1371 LLINT_CALL_THROW(exec
, pc
, createNotAConstructorError(exec
, callee
));
1374 inline SlowPathReturnType
setUpCall(ExecState
* execCallee
, Instruction
* pc
, CodeSpecializationKind kind
, JSValue calleeAsValue
, LLIntCallLinkInfo
* callLinkInfo
= 0)
1376 #if LLINT_SLOW_PATH_TRACING
1377 dataLogF("Performing call with recorded PC = %p\n", execCallee
->callerFrame()->currentVPC());
1380 JSCell
* calleeAsFunctionCell
= getJSFunction(calleeAsValue
);
1381 if (!calleeAsFunctionCell
)
1382 return handleHostCall(execCallee
, pc
, calleeAsValue
, kind
);
1384 JSFunction
* callee
= jsCast
<JSFunction
*>(calleeAsFunctionCell
);
1385 JSScope
* scope
= callee
->scopeUnchecked();
1386 VM
& vm
= *scope
->vm();
1387 execCallee
->setScope(scope
);
1388 ExecutableBase
* executable
= callee
->executable();
1390 MacroAssemblerCodePtr codePtr
;
1391 CodeBlock
* codeBlock
= 0;
1392 if (executable
->isHostFunction())
1393 codePtr
= executable
->hostCodeEntryFor(kind
);
1395 FunctionExecutable
* functionExecutable
= static_cast<FunctionExecutable
*>(executable
);
1396 JSObject
* error
= functionExecutable
->compileFor(execCallee
, callee
->scope(), kind
);
1398 LLINT_CALL_THROW(execCallee
->callerFrame(), pc
, error
);
1399 codeBlock
= &functionExecutable
->generatedBytecodeFor(kind
);
1401 if (execCallee
->argumentCountIncludingThis() < static_cast<size_t>(codeBlock
->numParameters()))
1402 codePtr
= functionExecutable
->jsCodeWithArityCheckEntryFor(kind
);
1404 codePtr
= functionExecutable
->jsCodeEntryFor(kind
);
1407 if (!LLINT_ALWAYS_ACCESS_SLOW
&& callLinkInfo
) {
1408 if (callLinkInfo
->isOnList())
1409 callLinkInfo
->remove();
1410 ExecState
* execCaller
= execCallee
->callerFrame();
1411 callLinkInfo
->callee
.set(vm
, execCaller
->codeBlock()->ownerExecutable(), callee
);
1412 callLinkInfo
->lastSeenCallee
.set(vm
, execCaller
->codeBlock()->ownerExecutable(), callee
);
1413 callLinkInfo
->machineCodeTarget
= codePtr
;
1415 codeBlock
->linkIncomingCall(callLinkInfo
);
1418 LLINT_CALL_RETURN(execCallee
, pc
, codePtr
.executableAddress());
1421 inline SlowPathReturnType
genericCall(ExecState
* exec
, Instruction
* pc
, CodeSpecializationKind kind
)
1424 // - Set up a call frame.
1425 // - Figure out what to call and compile it if necessary.
1426 // - If possible, link the call's inline cache.
1427 // - Return a tuple of machine code address to call and the new call frame.
1429 JSValue calleeAsValue
= LLINT_OP_C(1).jsValue();
1431 ExecState
* execCallee
= exec
+ pc
[3].u
.operand
;
1433 execCallee
->setArgumentCountIncludingThis(pc
[2].u
.operand
);
1434 execCallee
->uncheckedR(JSStack::Callee
) = calleeAsValue
;
1435 execCallee
->setCallerFrame(exec
);
1437 ASSERT(pc
[4].u
.callLinkInfo
);
1438 return setUpCall(execCallee
, pc
, kind
, calleeAsValue
, pc
[4].u
.callLinkInfo
);
1441 LLINT_SLOW_PATH_DECL(slow_path_call
)
1443 LLINT_BEGIN_NO_SET_PC();
1444 return genericCall(exec
, pc
, CodeForCall
);
1447 LLINT_SLOW_PATH_DECL(slow_path_construct
)
1449 LLINT_BEGIN_NO_SET_PC();
1450 return genericCall(exec
, pc
, CodeForConstruct
);
1453 LLINT_SLOW_PATH_DECL(slow_path_call_varargs
)
1457 // - Set up a call frame while respecting the variable arguments.
1458 // - Figure out what to call and compile it if necessary.
1459 // - Return a tuple of machine code address to call and the new call frame.
1461 JSValue calleeAsValue
= LLINT_OP_C(1).jsValue();
1463 ExecState
* execCallee
= loadVarargs(
1464 exec
, &vm
.interpreter
->stack(),
1465 LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue(), pc
[4].u
.operand
);
1466 LLINT_CALL_CHECK_EXCEPTION(exec
, pc
);
1468 execCallee
->uncheckedR(JSStack::Callee
) = calleeAsValue
;
1469 execCallee
->setCallerFrame(exec
);
1470 exec
->setCurrentVPC(pc
+ OPCODE_LENGTH(op_call_varargs
));
1472 return setUpCall(execCallee
, pc
, CodeForCall
, calleeAsValue
);
1475 LLINT_SLOW_PATH_DECL(slow_path_call_eval
)
1477 LLINT_BEGIN_NO_SET_PC();
1478 JSValue calleeAsValue
= LLINT_OP(1).jsValue();
1480 ExecState
* execCallee
= exec
+ pc
[3].u
.operand
;
1482 execCallee
->setArgumentCountIncludingThis(pc
[2].u
.operand
);
1483 execCallee
->setCallerFrame(exec
);
1484 execCallee
->uncheckedR(JSStack::Callee
) = calleeAsValue
;
1485 execCallee
->setScope(exec
->scope());
1486 execCallee
->setReturnPC(LLInt::getCodePtr(llint_generic_return_point
));
1487 execCallee
->setCodeBlock(0);
1488 exec
->setCurrentVPC(pc
+ OPCODE_LENGTH(op_call_eval
));
1490 if (!isHostFunction(calleeAsValue
, globalFuncEval
))
1491 return setUpCall(execCallee
, pc
, CodeForCall
, calleeAsValue
);
1493 vm
.hostCallReturnValue
= eval(execCallee
);
1494 LLINT_CALL_RETURN(execCallee
, pc
, LLInt::getCodePtr(getHostCallReturnValue
));
1497 LLINT_SLOW_PATH_DECL(slow_path_tear_off_activation
)
1500 ASSERT(exec
->codeBlock()->needsFullScopeChain());
1501 jsCast
<JSActivation
*>(LLINT_OP(1).jsValue())->tearOff(vm
);
1505 LLINT_SLOW_PATH_DECL(slow_path_tear_off_arguments
)
1508 ASSERT(exec
->codeBlock()->usesArguments());
1509 Arguments
* arguments
= jsCast
<Arguments
*>(exec
->uncheckedR(unmodifiedArgumentsRegister(pc
[1].u
.operand
)).jsValue());
1510 if (JSValue activationValue
= LLINT_OP_C(2).jsValue())
1511 arguments
->didTearOffActivation(exec
, jsCast
<JSActivation
*>(activationValue
));
1513 arguments
->tearOff(exec
);
1517 LLINT_SLOW_PATH_DECL(slow_path_strcat
)
1520 LLINT_RETURN(jsString(exec
, &LLINT_OP(2), pc
[3].u
.operand
));
1523 LLINT_SLOW_PATH_DECL(slow_path_to_primitive
)
1526 LLINT_RETURN(LLINT_OP_C(2).jsValue().toPrimitive(exec
));
1529 LLINT_SLOW_PATH_DECL(slow_path_get_pnames
)
1532 JSValue v
= LLINT_OP(2).jsValue();
1533 if (v
.isUndefinedOrNull()) {
1534 pc
+= pc
[5].u
.operand
;
1538 JSObject
* o
= v
.toObject(exec
);
1539 Structure
* structure
= o
->structure();
1540 JSPropertyNameIterator
* jsPropertyNameIterator
= structure
->enumerationCache();
1541 if (!jsPropertyNameIterator
|| jsPropertyNameIterator
->cachedPrototypeChain() != structure
->prototypeChain(exec
))
1542 jsPropertyNameIterator
= JSPropertyNameIterator::create(exec
, o
);
1544 LLINT_OP(1) = JSValue(jsPropertyNameIterator
);
1545 LLINT_OP(2) = JSValue(o
);
1546 LLINT_OP(3) = Register::withInt(0);
1547 LLINT_OP(4) = Register::withInt(jsPropertyNameIterator
->size());
1549 pc
+= OPCODE_LENGTH(op_get_pnames
);
1553 LLINT_SLOW_PATH_DECL(slow_path_next_pname
)
1556 JSObject
* base
= asObject(LLINT_OP(2).jsValue());
1557 JSString
* property
= asString(LLINT_OP(1).jsValue());
1558 if (base
->hasProperty(exec
, Identifier(exec
, property
->value(exec
)))) {
1560 pc
+= pc
[6].u
.operand
;
1561 } // Else, don't change the PC, so the interpreter will reloop.
1565 LLINT_SLOW_PATH_DECL(slow_path_push_with_scope
)
1568 JSValue v
= LLINT_OP_C(1).jsValue();
1569 JSObject
* o
= v
.toObject(exec
);
1570 LLINT_CHECK_EXCEPTION();
1572 exec
->setScope(JSWithScope::create(exec
, o
));
1577 LLINT_SLOW_PATH_DECL(slow_path_pop_scope
)
1580 exec
->setScope(exec
->scope()->next());
1584 LLINT_SLOW_PATH_DECL(slow_path_push_name_scope
)
1587 CodeBlock
* codeBlock
= exec
->codeBlock();
1588 JSNameScope
* scope
= JSNameScope::create(exec
, codeBlock
->identifier(pc
[1].u
.operand
), LLINT_OP(2).jsValue(), pc
[3].u
.operand
);
1589 exec
->setScope(scope
);
1593 LLINT_SLOW_PATH_DECL(slow_path_throw
)
1596 LLINT_THROW(LLINT_OP_C(1).jsValue());
1599 LLINT_SLOW_PATH_DECL(slow_path_throw_static_error
)
1602 if (pc
[2].u
.operand
)
1603 LLINT_THROW(createReferenceError(exec
, LLINT_OP_C(1).jsValue().toString(exec
)->value(exec
)));
1605 LLINT_THROW(createTypeError(exec
, LLINT_OP_C(1).jsValue().toString(exec
)->value(exec
)));
1608 LLINT_SLOW_PATH_DECL(slow_path_handle_watchdog_timer
)
1610 LLINT_BEGIN_NO_SET_PC();
1611 if (UNLIKELY(vm
.watchdog
.didFire(exec
)))
1612 LLINT_THROW(createTerminatedExecutionException(&vm
));
1613 LLINT_RETURN_TWO(0, exec
);
1616 LLINT_SLOW_PATH_DECL(slow_path_debug
)
1619 int debugHookID
= pc
[1].u
.operand
;
1620 int firstLine
= pc
[2].u
.operand
;
1621 int lastLine
= pc
[3].u
.operand
;
1622 int column
= pc
[4].u
.operand
;
1624 vm
.interpreter
->debug(exec
, static_cast<DebugHookID
>(debugHookID
), firstLine
, lastLine
, column
);
1629 LLINT_SLOW_PATH_DECL(slow_path_profile_will_call
)
1632 if (LegacyProfiler
* profiler
= vm
.enabledProfiler())
1633 profiler
->willExecute(exec
, LLINT_OP(1).jsValue());
1637 LLINT_SLOW_PATH_DECL(slow_path_profile_did_call
)
1640 if (LegacyProfiler
* profiler
= vm
.enabledProfiler())
1641 profiler
->didExecute(exec
, LLINT_OP(1).jsValue());
1645 LLINT_SLOW_PATH_DECL(throw_from_native_call
)
1648 ASSERT(vm
.exception
);
1652 } } // namespace JSC::LLInt
1654 #endif // ENABLE(LLINT)