2 * Copyright (C) 2011-2015 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"
29 #include "ArrayConstructor.h"
30 #include "CallFrame.h"
31 #include "CommonSlowPaths.h"
32 #include "CommonSlowPathsExceptions.h"
34 #include "ErrorHandlingScope.h"
35 #include "ExceptionFuzz.h"
36 #include "GetterSetter.h"
37 #include "HostCallReturnValue.h"
38 #include "Interpreter.h"
40 #include "JITExceptions.h"
41 #include "JSLexicalEnvironment.h"
42 #include "JSCInlines.h"
43 #include "JSCJSValue.h"
44 #include "JSGlobalObjectFunctions.h"
45 #include "JSNameScope.h"
46 #include "JSStackInlines.h"
48 #include "JSWithScope.h"
49 #include "LLIntCommon.h"
50 #include "LLIntExceptions.h"
51 #include "LegacyProfiler.h"
52 #include "LowLevelInterpreter.h"
53 #include "ObjectConstructor.h"
54 #include "ProtoCallFrame.h"
55 #include "StructureRareDataInlines.h"
56 #include <wtf/StringPrintStream.h>
58 namespace JSC
{ namespace LLInt
{
60 #define LLINT_BEGIN_NO_SET_PC() \
61 VM& vm = exec->vm(); \
62 NativeCallFrameTracer tracer(&vm, exec)
65 #define LLINT_SET_PC_FOR_STUBS() do { \
66 exec->codeBlock()->bytecodeOffset(pc); \
67 exec->setCurrentVPC(pc + 1); \
70 #define LLINT_SET_PC_FOR_STUBS() do { \
71 exec->setCurrentVPC(pc + 1); \
75 #define LLINT_BEGIN() \
76 LLINT_BEGIN_NO_SET_PC(); \
77 LLINT_SET_PC_FOR_STUBS()
79 #define LLINT_OP(index) (exec->uncheckedR(pc[index].u.operand))
80 #define LLINT_OP_C(index) (exec->r(pc[index].u.operand))
82 #define LLINT_RETURN_TWO(first, second) do { \
83 return encodeResult(first, second); \
86 #define LLINT_END_IMPL() LLINT_RETURN_TWO(pc, 0)
88 #define LLINT_THROW(exceptionToThrow) do { \
89 vm.throwException(exec, exceptionToThrow); \
90 pc = returnToThrow(exec); \
94 #define LLINT_CHECK_EXCEPTION() do { \
95 doExceptionFuzzingIfEnabled(exec, "LLIntSlowPaths", pc); \
96 if (UNLIKELY(vm.exception())) { \
97 pc = returnToThrow(exec); \
102 #define LLINT_END() do { \
103 LLINT_CHECK_EXCEPTION(); \
107 #define LLINT_BRANCH(opcode, condition) do { \
108 bool __b_condition = (condition); \
109 LLINT_CHECK_EXCEPTION(); \
111 pc += pc[OPCODE_LENGTH(opcode) - 1].u.operand; \
113 pc += OPCODE_LENGTH(opcode); \
117 #define LLINT_RETURN(value) do { \
118 JSValue __r_returnValue = (value); \
119 LLINT_CHECK_EXCEPTION(); \
120 LLINT_OP(1) = __r_returnValue; \
124 #define LLINT_RETURN_WITH_PC_ADJUSTMENT(value, pcAdjustment) do { \
125 JSValue __r_returnValue = (value); \
126 LLINT_CHECK_EXCEPTION(); \
127 LLINT_OP(1) = __r_returnValue; \
128 pc += (pcAdjustment); \
132 #define LLINT_RETURN_PROFILED(opcode, value) do { \
133 JSValue __rp_returnValue = (value); \
134 LLINT_CHECK_EXCEPTION(); \
135 LLINT_OP(1) = __rp_returnValue; \
136 LLINT_PROFILE_VALUE(opcode, __rp_returnValue); \
140 #define LLINT_PROFILE_VALUE(opcode, value) do { \
141 pc[OPCODE_LENGTH(opcode) - 1].u.profile->m_buckets[0] = \
142 JSValue::encode(value); \
145 #define LLINT_CALL_END_IMPL(exec, callTarget) LLINT_RETURN_TWO((callTarget), (exec))
147 #define LLINT_CALL_THROW(exec, exceptionToThrow) do { \
148 ExecState* __ct_exec = (exec); \
149 vm.throwException(__ct_exec, exceptionToThrow); \
150 LLINT_CALL_END_IMPL(0, callToThrow(__ct_exec)); \
153 #define LLINT_CALL_CHECK_EXCEPTION(exec, execCallee) do { \
154 ExecState* __cce_exec = (exec); \
155 ExecState* __cce_execCallee = (execCallee); \
156 doExceptionFuzzingIfEnabled(__cce_exec, "LLIntSlowPaths/call", nullptr); \
157 if (UNLIKELY(vm.exception())) \
158 LLINT_CALL_END_IMPL(0, callToThrow(__cce_execCallee)); \
161 #define LLINT_CALL_RETURN(exec, execCallee, callTarget) do { \
162 ExecState* __cr_exec = (exec); \
163 ExecState* __cr_execCallee = (execCallee); \
164 void* __cr_callTarget = (callTarget); \
165 LLINT_CALL_CHECK_EXCEPTION(__cr_exec, __cr_execCallee); \
166 LLINT_CALL_END_IMPL(__cr_execCallee, __cr_callTarget); \
169 #define LLINT_RETURN_CALLEE_FRAME(execCallee) do { \
170 ExecState* __rcf_exec = (execCallee); \
171 LLINT_RETURN_TWO(pc, __rcf_exec); \
174 extern "C" SlowPathReturnType
llint_trace_operand(ExecState
* exec
, Instruction
* pc
, int fromWhere
, int operand
)
177 dataLogF("%p / %p: executing bc#%zu, op#%u: Trace(%d): %d: %d\n",
180 static_cast<intptr_t>(pc
- exec
->codeBlock()->instructions().begin()),
181 exec
->vm().interpreter
->getOpcodeID(pc
[0].u
.opcode
),
184 pc
[operand
].u
.operand
);
188 extern "C" SlowPathReturnType
llint_trace_value(ExecState
* exec
, Instruction
* pc
, int fromWhere
, int operand
)
190 JSValue value
= LLINT_OP_C(operand
).jsValue();
196 EncodedJSValue asValue
;
198 u
.asValue
= JSValue::encode(value
);
200 "%p / %p: executing bc#%zu, op#%u: Trace(%d): %d: %d: %08x:%08x: %s\n",
203 static_cast<intptr_t>(pc
- exec
->codeBlock()->instructions().begin()),
204 exec
->vm().interpreter
->getOpcodeID(pc
[0].u
.opcode
),
207 pc
[operand
].u
.operand
,
210 toCString(value
).data());
214 LLINT_SLOW_PATH_DECL(trace_prologue
)
216 dataLogF("%p / %p: in prologue.\n", exec
->codeBlock(), exec
);
220 static void traceFunctionPrologue(ExecState
* exec
, const char* comment
, CodeSpecializationKind kind
)
222 JSFunction
* callee
= jsCast
<JSFunction
*>(exec
->callee());
223 FunctionExecutable
* executable
= callee
->jsExecutable();
224 CodeBlock
* codeBlock
= executable
->codeBlockFor(kind
);
225 dataLogF("%p / %p: in %s of function %p, executable %p; numVars = %u, numParameters = %u, numCalleeRegisters = %u, caller = %p.\n",
226 codeBlock
, exec
, comment
, callee
, executable
,
227 codeBlock
->m_numVars
, codeBlock
->numParameters(), codeBlock
->m_numCalleeRegisters
,
228 exec
->callerFrame());
231 LLINT_SLOW_PATH_DECL(trace_prologue_function_for_call
)
233 traceFunctionPrologue(exec
, "call prologue", CodeForCall
);
237 LLINT_SLOW_PATH_DECL(trace_prologue_function_for_construct
)
239 traceFunctionPrologue(exec
, "construct prologue", CodeForConstruct
);
243 LLINT_SLOW_PATH_DECL(trace_arityCheck_for_call
)
245 traceFunctionPrologue(exec
, "call arity check", CodeForCall
);
249 LLINT_SLOW_PATH_DECL(trace_arityCheck_for_construct
)
251 traceFunctionPrologue(exec
, "construct arity check", CodeForConstruct
);
255 LLINT_SLOW_PATH_DECL(trace
)
257 dataLogF("%p / %p: executing bc#%zu, %s, pc = %p\n",
260 static_cast<intptr_t>(pc
- exec
->codeBlock()->instructions().begin()),
261 opcodeNames
[exec
->vm().interpreter
->getOpcodeID(pc
[0].u
.opcode
)], pc
);
262 if (exec
->vm().interpreter
->getOpcodeID(pc
[0].u
.opcode
) == op_enter
) {
263 dataLogF("Frame will eventually return to %p\n", exec
->returnPC().value());
264 *bitwise_cast
<volatile char*>(exec
->returnPC().value());
266 if (exec
->vm().interpreter
->getOpcodeID(pc
[0].u
.opcode
) == op_ret
) {
267 dataLogF("Will be returning to %p\n", exec
->returnPC().value());
268 dataLogF("The new cfr will be %p\n", exec
->callerFrame());
273 LLINT_SLOW_PATH_DECL(special_trace
)
275 dataLogF("%p / %p: executing special case bc#%zu, op#%u, return PC is %p\n",
278 static_cast<intptr_t>(pc
- exec
->codeBlock()->instructions().begin()),
279 exec
->vm().interpreter
->getOpcodeID(pc
[0].u
.opcode
),
280 exec
->returnPC().value());
284 enum EntryKind
{ Prologue
, ArityCheck
};
287 inline bool shouldJIT(ExecState
* exec
)
289 // You can modify this to turn off JITting without rebuilding the world.
290 return exec
->vm().canUseJIT();
293 // Returns true if we should try to OSR.
294 inline bool jitCompileAndSetHeuristics(CodeBlock
* codeBlock
, ExecState
* exec
)
297 DeferGCForAWhile
deferGC(vm
.heap
); // My callers don't set top callframe, so we don't want to GC here at all.
299 codeBlock
->updateAllValueProfilePredictions();
301 if (!codeBlock
->checkIfJITThresholdReached()) {
302 if (Options::verboseOSR())
303 dataLogF(" JIT threshold should be lifted.\n");
307 switch (codeBlock
->jitType()) {
308 case JITCode::BaselineJIT
: {
309 if (Options::verboseOSR())
310 dataLogF(" Code was already compiled.\n");
311 codeBlock
->jitSoon();
314 case JITCode::InterpreterThunk
: {
315 CompilationResult result
= JIT::compile(&vm
, codeBlock
, JITCompilationCanFail
);
317 case CompilationFailed
:
318 if (Options::verboseOSR())
319 dataLogF(" JIT compilation failed.\n");
320 codeBlock
->dontJITAnytimeSoon();
322 case CompilationSuccessful
:
323 if (Options::verboseOSR())
324 dataLogF(" JIT compilation successful.\n");
325 codeBlock
->install();
326 codeBlock
->jitSoon();
329 RELEASE_ASSERT_NOT_REACHED();
334 dataLog("Unexpected code block in LLInt: ", *codeBlock
, "\n");
335 RELEASE_ASSERT_NOT_REACHED();
340 static SlowPathReturnType
entryOSR(ExecState
* exec
, Instruction
*, CodeBlock
* codeBlock
, const char *name
, EntryKind kind
)
342 if (Options::verboseOSR()) {
344 *codeBlock
, ": Entered ", name
, " with executeCounter = ",
345 codeBlock
->llintExecuteCounter(), "\n");
348 if (!shouldJIT(exec
)) {
349 codeBlock
->dontJITAnytimeSoon();
350 LLINT_RETURN_TWO(0, 0);
352 if (!jitCompileAndSetHeuristics(codeBlock
, exec
))
353 LLINT_RETURN_TWO(0, 0);
355 if (kind
== Prologue
)
356 LLINT_RETURN_TWO(codeBlock
->jitCode()->executableAddress(), 0);
357 ASSERT(kind
== ArityCheck
);
358 LLINT_RETURN_TWO(codeBlock
->jitCode()->addressForCall(
359 *codeBlock
->vm(), codeBlock
->ownerExecutable(), MustCheckArity
,
360 RegisterPreservationNotRequired
).executableAddress(), 0);
363 static SlowPathReturnType
entryOSR(ExecState
* exec
, Instruction
*, CodeBlock
* codeBlock
, const char*, EntryKind
)
365 codeBlock
->dontJITAnytimeSoon();
366 LLINT_RETURN_TWO(0, exec
);
368 #endif // ENABLE(JIT)
370 LLINT_SLOW_PATH_DECL(entry_osr
)
372 return entryOSR(exec
, pc
, exec
->codeBlock(), "entry_osr", Prologue
);
375 LLINT_SLOW_PATH_DECL(entry_osr_function_for_call
)
377 return entryOSR(exec
, pc
, jsCast
<JSFunction
*>(exec
->callee())->jsExecutable()->codeBlockForCall(), "entry_osr_function_for_call", Prologue
);
380 LLINT_SLOW_PATH_DECL(entry_osr_function_for_construct
)
382 return entryOSR(exec
, pc
, jsCast
<JSFunction
*>(exec
->callee())->jsExecutable()->codeBlockForConstruct(), "entry_osr_function_for_construct", Prologue
);
385 LLINT_SLOW_PATH_DECL(entry_osr_function_for_call_arityCheck
)
387 return entryOSR(exec
, pc
, jsCast
<JSFunction
*>(exec
->callee())->jsExecutable()->codeBlockForCall(), "entry_osr_function_for_call_arityCheck", ArityCheck
);
390 LLINT_SLOW_PATH_DECL(entry_osr_function_for_construct_arityCheck
)
392 return entryOSR(exec
, pc
, jsCast
<JSFunction
*>(exec
->callee())->jsExecutable()->codeBlockForConstruct(), "entry_osr_function_for_construct_arityCheck", ArityCheck
);
395 LLINT_SLOW_PATH_DECL(loop_osr
)
397 CodeBlock
* codeBlock
= exec
->codeBlock();
400 if (Options::verboseOSR()) {
402 *codeBlock
, ": Entered loop_osr with executeCounter = ",
403 codeBlock
->llintExecuteCounter(), "\n");
406 if (!shouldJIT(exec
)) {
407 codeBlock
->dontJITAnytimeSoon();
408 LLINT_RETURN_TWO(0, 0);
411 if (!jitCompileAndSetHeuristics(codeBlock
, exec
))
412 LLINT_RETURN_TWO(0, 0);
414 ASSERT(codeBlock
->jitType() == JITCode::BaselineJIT
);
416 Vector
<BytecodeAndMachineOffset
> map
;
417 codeBlock
->jitCodeMap()->decode(map
);
418 BytecodeAndMachineOffset
* mapping
= binarySearch
<BytecodeAndMachineOffset
, unsigned>(map
, map
.size(), pc
- codeBlock
->instructions().begin(), BytecodeAndMachineOffset::getBytecodeIndex
);
420 ASSERT(mapping
->m_bytecodeIndex
== static_cast<unsigned>(pc
- codeBlock
->instructions().begin()));
422 void* jumpTarget
= codeBlock
->jitCode()->executableAddressAtOffset(mapping
->m_machineCodeOffset
);
425 LLINT_RETURN_TWO(jumpTarget
, exec
->topOfFrame());
428 codeBlock
->dontJITAnytimeSoon();
429 LLINT_RETURN_TWO(0, 0);
430 #endif // ENABLE(JIT)
433 LLINT_SLOW_PATH_DECL(replace
)
435 CodeBlock
* codeBlock
= exec
->codeBlock();
438 if (Options::verboseOSR()) {
440 *codeBlock
, ": Entered replace with executeCounter = ",
441 codeBlock
->llintExecuteCounter(), "\n");
445 jitCompileAndSetHeuristics(codeBlock
, exec
);
447 codeBlock
->dontJITAnytimeSoon();
450 codeBlock
->dontJITAnytimeSoon();
452 #endif // ENABLE(JIT)
455 LLINT_SLOW_PATH_DECL(stack_check
)
458 #if LLINT_SLOW_PATH_TRACING
459 dataLogF("Checking stack height with exec = %p.\n", exec
);
460 dataLogF("CodeBlock = %p.\n", exec
->codeBlock());
461 dataLogF("Num callee registers = %u.\n", exec
->codeBlock()->m_numCalleeRegisters
);
462 dataLogF("Num vars = %u.\n", exec
->codeBlock()->m_numVars
);
465 dataLogF("Current end is at %p.\n", exec
->vm().stackLimit());
467 dataLogF("Current end is at %p.\n", exec
->vm().jsStackLimit());
471 // If the stack check succeeds and we don't need to throw the error, then
472 // we'll return 0 instead. The prologue will check for a non-zero value
473 // when determining whether to set the callFrame or not.
475 // For JIT enabled builds which uses the C stack, the stack is not growable.
476 // Hence, if we get here, then we know a stack overflow is imminent. So, just
477 // throw the StackOverflowError unconditionally.
479 ASSERT(!vm
.interpreter
->stack().containsAddress(exec
->topOfFrame()));
480 if (LIKELY(vm
.interpreter
->stack().ensureCapacityFor(exec
->topOfFrame())))
481 LLINT_RETURN_TWO(pc
, 0);
484 vm
.topCallFrame
= exec
;
485 ErrorHandlingScope
errorScope(vm
);
486 CommonSlowPaths::interpreterThrowInCaller(exec
, createStackOverflowError(exec
));
487 pc
= returnToThrowForThrownException(exec
);
488 LLINT_RETURN_TWO(pc
, exec
);
491 LLINT_SLOW_PATH_DECL(slow_path_create_lexical_environment
)
494 #if LLINT_SLOW_PATH_TRACING
495 dataLogF("Creating an lexicalEnvironment, exec = %p!\n", exec
);
497 int scopeReg
= pc
[2].u
.operand
;
498 JSScope
* scope
= exec
->uncheckedR(scopeReg
).Register::scope();
499 JSLexicalEnvironment
* lexicalEnvironment
= JSLexicalEnvironment::create(vm
, exec
, scope
, exec
->codeBlock());
500 LLINT_RETURN(JSValue(lexicalEnvironment
));
503 LLINT_SLOW_PATH_DECL(slow_path_new_object
)
506 LLINT_RETURN(constructEmptyObject(exec
, pc
[3].u
.objectAllocationProfile
->structure()));
509 LLINT_SLOW_PATH_DECL(slow_path_new_array
)
512 LLINT_RETURN(constructArrayNegativeIndexed(exec
, pc
[4].u
.arrayAllocationProfile
, bitwise_cast
<JSValue
*>(&LLINT_OP(2)), pc
[3].u
.operand
));
515 LLINT_SLOW_PATH_DECL(slow_path_new_array_with_size
)
518 LLINT_RETURN(constructArrayWithSizeQuirk(exec
, pc
[3].u
.arrayAllocationProfile
, exec
->lexicalGlobalObject(), LLINT_OP_C(2).jsValue()));
521 LLINT_SLOW_PATH_DECL(slow_path_new_array_buffer
)
524 LLINT_RETURN(constructArray(exec
, pc
[4].u
.arrayAllocationProfile
, exec
->codeBlock()->constantBuffer(pc
[2].u
.operand
), pc
[3].u
.operand
));
527 LLINT_SLOW_PATH_DECL(slow_path_new_regexp
)
530 RegExp
* regExp
= exec
->codeBlock()->regexp(pc
[2].u
.operand
);
531 if (!regExp
->isValid())
532 LLINT_THROW(createSyntaxError(exec
, "Invalid flag supplied to RegExp constructor."));
533 LLINT_RETURN(RegExpObject::create(vm
, exec
->lexicalGlobalObject()->regExpStructure(), regExp
));
536 LLINT_SLOW_PATH_DECL(slow_path_check_has_instance
)
540 JSValue value
= LLINT_OP_C(2).jsValue();
541 JSValue baseVal
= LLINT_OP_C(3).jsValue();
542 if (baseVal
.isObject()) {
543 JSObject
* baseObject
= asObject(baseVal
);
544 ASSERT(!baseObject
->structure()->typeInfo().implementsDefaultHasInstance());
545 if (baseObject
->structure()->typeInfo().implementsHasInstance()) {
546 JSValue result
= jsBoolean(baseObject
->methodTable()->customHasInstance(baseObject
, exec
, value
));
547 LLINT_RETURN_WITH_PC_ADJUSTMENT(result
, pc
[4].u
.operand
);
550 LLINT_THROW(createInvalidInstanceofParameterError(exec
, baseVal
));
553 LLINT_SLOW_PATH_DECL(slow_path_instanceof
)
556 JSValue value
= LLINT_OP_C(2).jsValue();
557 JSValue proto
= LLINT_OP_C(3).jsValue();
558 ASSERT(!value
.isObject() || !proto
.isObject());
559 LLINT_RETURN(jsBoolean(JSObject::defaultHasInstance(exec
, value
, proto
)));
562 LLINT_SLOW_PATH_DECL(slow_path_get_by_id
)
565 CodeBlock
* codeBlock
= exec
->codeBlock();
566 const Identifier
& ident
= codeBlock
->identifier(pc
[3].u
.operand
);
567 JSValue baseValue
= LLINT_OP_C(2).jsValue();
568 PropertySlot
slot(baseValue
);
570 JSValue result
= baseValue
.get(exec
, ident
, slot
);
571 LLINT_CHECK_EXCEPTION();
572 LLINT_OP(1) = result
;
574 if (!LLINT_ALWAYS_ACCESS_SLOW
575 && baseValue
.isCell()
576 && slot
.isCacheable()
577 && slot
.slotBase() == baseValue
578 && slot
.isCacheableValue()) {
580 JSCell
* baseCell
= baseValue
.asCell();
581 Structure
* structure
= baseCell
->structure();
583 if (!structure
->isUncacheableDictionary()
584 && !structure
->typeInfo().prohibitsPropertyCaching()
585 && !structure
->typeInfo().newImpurePropertyFiresWatchpoints()) {
586 ConcurrentJITLocker
locker(codeBlock
->m_lock
);
588 pc
[4].u
.structure
.set(
589 vm
, codeBlock
->ownerExecutable(), structure
);
590 if (isInlineOffset(slot
.cachedOffset())) {
591 pc
[0].u
.opcode
= LLInt::getOpcode(op_get_by_id
);
592 pc
[5].u
.operand
= offsetInInlineStorage(slot
.cachedOffset()) * sizeof(JSValue
) + JSObject::offsetOfInlineStorage();
594 pc
[0].u
.opcode
= LLInt::getOpcode(op_get_by_id_out_of_line
);
595 pc
[5].u
.operand
= offsetInButterfly(slot
.cachedOffset()) * sizeof(JSValue
);
600 if (!LLINT_ALWAYS_ACCESS_SLOW
601 && isJSArray(baseValue
)
602 && ident
== exec
->propertyNames().length
) {
603 pc
[0].u
.opcode
= LLInt::getOpcode(op_get_array_length
);
604 ArrayProfile
* arrayProfile
= codeBlock
->getOrAddArrayProfile(pc
- codeBlock
->instructions().begin());
605 arrayProfile
->observeStructure(baseValue
.asCell()->structure());
606 pc
[4].u
.arrayProfile
= arrayProfile
;
609 pc
[OPCODE_LENGTH(op_get_by_id
) - 1].u
.profile
->m_buckets
[0] = JSValue::encode(result
);
613 LLINT_SLOW_PATH_DECL(slow_path_get_arguments_length
)
616 CodeBlock
* codeBlock
= exec
->codeBlock();
617 const Identifier
& ident
= codeBlock
->identifier(pc
[3].u
.operand
);
618 JSValue baseValue
= LLINT_OP(2).jsValue();
619 PropertySlot
slot(baseValue
);
620 LLINT_RETURN(baseValue
.get(exec
, ident
, slot
));
623 LLINT_SLOW_PATH_DECL(slow_path_put_by_id
)
626 CodeBlock
* codeBlock
= exec
->codeBlock();
627 const Identifier
& ident
= codeBlock
->identifier(pc
[2].u
.operand
);
629 JSValue baseValue
= LLINT_OP_C(1).jsValue();
630 PutPropertySlot
slot(baseValue
, codeBlock
->isStrictMode(), codeBlock
->putByIdContext());
632 asObject(baseValue
)->putDirect(vm
, ident
, LLINT_OP_C(3).jsValue(), slot
);
634 baseValue
.put(exec
, ident
, LLINT_OP_C(3).jsValue(), slot
);
635 LLINT_CHECK_EXCEPTION();
637 if (!LLINT_ALWAYS_ACCESS_SLOW
638 && baseValue
.isCell()
639 && slot
.isCacheablePut()) {
641 JSCell
* baseCell
= baseValue
.asCell();
642 Structure
* structure
= baseCell
->structure();
644 if (!structure
->isUncacheableDictionary()
645 && !structure
->typeInfo().prohibitsPropertyCaching()
646 && baseCell
== slot
.base()) {
648 if (slot
.type() == PutPropertySlot::NewProperty
) {
649 GCSafeConcurrentJITLocker
locker(codeBlock
->m_lock
, vm
.heap
);
651 if (!structure
->isDictionary() && structure
->previousID()->outOfLineCapacity() == structure
->outOfLineCapacity()) {
652 ASSERT(structure
->previousID()->transitionWatchpointSetHasBeenInvalidated());
654 // This is needed because some of the methods we call
656 pc
[0].u
.opcode
= LLInt::getOpcode(op_put_by_id
);
658 if (normalizePrototypeChain(exec
, structure
) != InvalidPrototypeChain
) {
659 ASSERT(structure
->previousID()->isObject());
660 pc
[4].u
.structure
.set(
661 vm
, codeBlock
->ownerExecutable(), structure
->previousID());
662 if (isInlineOffset(slot
.cachedOffset()))
663 pc
[5].u
.operand
= offsetInInlineStorage(slot
.cachedOffset()) * sizeof(JSValue
) + JSObject::offsetOfInlineStorage();
665 pc
[5].u
.operand
= offsetInButterfly(slot
.cachedOffset()) * sizeof(JSValue
);
666 pc
[6].u
.structure
.set(
667 vm
, codeBlock
->ownerExecutable(), structure
);
668 StructureChain
* chain
= structure
->prototypeChain(exec
);
670 pc
[7].u
.structureChain
.set(
671 vm
, codeBlock
->ownerExecutable(), chain
);
673 if (pc
[8].u
.operand
) {
674 if (isInlineOffset(slot
.cachedOffset()))
675 pc
[0].u
.opcode
= LLInt::getOpcode(op_put_by_id_transition_direct
);
677 pc
[0].u
.opcode
= LLInt::getOpcode(op_put_by_id_transition_direct_out_of_line
);
679 if (isInlineOffset(slot
.cachedOffset()))
680 pc
[0].u
.opcode
= LLInt::getOpcode(op_put_by_id_transition_normal
);
682 pc
[0].u
.opcode
= LLInt::getOpcode(op_put_by_id_transition_normal_out_of_line
);
687 structure
->didCachePropertyReplacement(vm
, slot
.cachedOffset());
688 pc
[4].u
.structure
.set(
689 vm
, codeBlock
->ownerExecutable(), structure
);
690 if (isInlineOffset(slot
.cachedOffset())) {
691 pc
[0].u
.opcode
= LLInt::getOpcode(op_put_by_id
);
692 pc
[5].u
.operand
= offsetInInlineStorage(slot
.cachedOffset()) * sizeof(JSValue
) + JSObject::offsetOfInlineStorage();
694 pc
[0].u
.opcode
= LLInt::getOpcode(op_put_by_id_out_of_line
);
695 pc
[5].u
.operand
= offsetInButterfly(slot
.cachedOffset()) * sizeof(JSValue
);
704 LLINT_SLOW_PATH_DECL(slow_path_del_by_id
)
707 CodeBlock
* codeBlock
= exec
->codeBlock();
708 JSObject
* baseObject
= LLINT_OP_C(2).jsValue().toObject(exec
);
709 bool couldDelete
= baseObject
->methodTable()->deleteProperty(baseObject
, exec
, codeBlock
->identifier(pc
[3].u
.operand
));
710 LLINT_CHECK_EXCEPTION();
711 if (!couldDelete
&& codeBlock
->isStrictMode())
712 LLINT_THROW(createTypeError(exec
, "Unable to delete property."));
713 LLINT_RETURN(jsBoolean(couldDelete
));
716 inline JSValue
getByVal(ExecState
* exec
, JSValue baseValue
, JSValue subscript
)
718 if (LIKELY(baseValue
.isCell() && subscript
.isString())) {
720 Structure
& structure
= *baseValue
.asCell()->structure(vm
);
721 if (JSCell::canUseFastGetOwnProperty(structure
)) {
722 if (RefPtr
<AtomicStringImpl
> existingAtomicString
= asString(subscript
)->toExistingAtomicString(exec
)) {
723 if (JSValue result
= baseValue
.asCell()->fastGetOwnProperty(vm
, structure
, existingAtomicString
.get()))
729 if (subscript
.isUInt32()) {
730 uint32_t i
= subscript
.asUInt32();
731 if (isJSString(baseValue
) && asString(baseValue
)->canGetIndex(i
))
732 return asString(baseValue
)->getIndex(exec
, i
);
734 return baseValue
.get(exec
, i
);
737 baseValue
.requireObjectCoercible(exec
);
738 if (exec
->hadException())
739 return jsUndefined();
740 auto property
= subscript
.toPropertyKey(exec
);
741 if (exec
->hadException())
742 return jsUndefined();
743 return baseValue
.get(exec
, property
);
746 LLINT_SLOW_PATH_DECL(slow_path_get_by_val
)
749 LLINT_RETURN_PROFILED(op_get_by_val
, getByVal(exec
, LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue()));
752 LLINT_SLOW_PATH_DECL(slow_path_put_by_val
)
756 JSValue baseValue
= LLINT_OP_C(1).jsValue();
757 JSValue subscript
= LLINT_OP_C(2).jsValue();
758 JSValue value
= LLINT_OP_C(3).jsValue();
760 if (LIKELY(subscript
.isUInt32())) {
761 uint32_t i
= subscript
.asUInt32();
762 if (baseValue
.isObject()) {
763 JSObject
* object
= asObject(baseValue
);
764 if (object
->canSetIndexQuickly(i
))
765 object
->setIndexQuickly(vm
, i
, value
);
767 object
->methodTable()->putByIndex(object
, exec
, i
, value
, exec
->codeBlock()->isStrictMode());
770 baseValue
.putByIndex(exec
, i
, value
, exec
->codeBlock()->isStrictMode());
774 auto property
= subscript
.toPropertyKey(exec
);
775 LLINT_CHECK_EXCEPTION();
776 PutPropertySlot
slot(baseValue
, exec
->codeBlock()->isStrictMode());
777 baseValue
.put(exec
, property
, value
, slot
);
781 LLINT_SLOW_PATH_DECL(slow_path_put_by_val_direct
)
785 JSValue baseValue
= LLINT_OP_C(1).jsValue();
786 JSValue subscript
= LLINT_OP_C(2).jsValue();
787 JSValue value
= LLINT_OP_C(3).jsValue();
788 RELEASE_ASSERT(baseValue
.isObject());
789 JSObject
* baseObject
= asObject(baseValue
);
790 bool isStrictMode
= exec
->codeBlock()->isStrictMode();
791 if (LIKELY(subscript
.isUInt32())) {
792 // Despite its name, JSValue::isUInt32 will return true only for positive boxed int32_t; all those values are valid array indices.
793 ASSERT(isIndex(subscript
.asUInt32()));
794 baseObject
->putDirectIndex(exec
, subscript
.asUInt32(), value
, 0, isStrictMode
? PutDirectIndexShouldThrow
: PutDirectIndexShouldNotThrow
);
798 if (subscript
.isDouble()) {
799 double subscriptAsDouble
= subscript
.asDouble();
800 uint32_t subscriptAsUInt32
= static_cast<uint32_t>(subscriptAsDouble
);
801 if (subscriptAsDouble
== subscriptAsUInt32
&& isIndex(subscriptAsUInt32
)) {
802 baseObject
->putDirectIndex(exec
, subscriptAsUInt32
, value
, 0, isStrictMode
? PutDirectIndexShouldThrow
: PutDirectIndexShouldNotThrow
);
807 // Don't put to an object if toString threw an exception.
808 auto property
= subscript
.toPropertyKey(exec
);
809 if (exec
->vm().exception())
812 if (Optional
<uint32_t> index
= parseIndex(property
))
813 baseObject
->putDirectIndex(exec
, index
.value(), value
, 0, isStrictMode
? PutDirectIndexShouldThrow
: PutDirectIndexShouldNotThrow
);
815 PutPropertySlot
slot(baseObject
, isStrictMode
);
816 baseObject
->putDirect(exec
->vm(), property
, value
, slot
);
821 LLINT_SLOW_PATH_DECL(slow_path_del_by_val
)
824 JSValue baseValue
= LLINT_OP_C(2).jsValue();
825 JSObject
* baseObject
= baseValue
.toObject(exec
);
827 JSValue subscript
= LLINT_OP_C(3).jsValue();
832 if (subscript
.getUInt32(i
))
833 couldDelete
= baseObject
->methodTable()->deletePropertyByIndex(baseObject
, exec
, i
);
835 LLINT_CHECK_EXCEPTION();
836 auto property
= subscript
.toPropertyKey(exec
);
837 LLINT_CHECK_EXCEPTION();
838 couldDelete
= baseObject
->methodTable()->deleteProperty(baseObject
, exec
, property
);
841 if (!couldDelete
&& exec
->codeBlock()->isStrictMode())
842 LLINT_THROW(createTypeError(exec
, "Unable to delete property."));
844 LLINT_RETURN(jsBoolean(couldDelete
));
847 LLINT_SLOW_PATH_DECL(slow_path_put_by_index
)
850 JSValue arrayValue
= LLINT_OP_C(1).jsValue();
851 ASSERT(isJSArray(arrayValue
));
852 asArray(arrayValue
)->putDirectIndex(exec
, pc
[2].u
.operand
, LLINT_OP_C(3).jsValue());
856 LLINT_SLOW_PATH_DECL(slow_path_put_getter_by_id
)
859 ASSERT(LLINT_OP(1).jsValue().isObject());
860 JSObject
* baseObj
= asObject(LLINT_OP(1).jsValue());
862 JSValue getter
= LLINT_OP(3).jsValue();
863 ASSERT(getter
.isObject());
865 baseObj
->putGetter(exec
, exec
->codeBlock()->identifier(pc
[2].u
.operand
), asObject(getter
));
869 LLINT_SLOW_PATH_DECL(slow_path_put_setter_by_id
)
872 ASSERT(LLINT_OP(1).jsValue().isObject());
873 JSObject
* baseObj
= asObject(LLINT_OP(1).jsValue());
875 JSValue setter
= LLINT_OP(3).jsValue();
876 ASSERT(setter
.isObject());
878 baseObj
->putSetter(exec
, exec
->codeBlock()->identifier(pc
[2].u
.operand
), asObject(setter
));
882 LLINT_SLOW_PATH_DECL(slow_path_put_getter_setter
)
885 ASSERT(LLINT_OP(1).jsValue().isObject());
886 JSObject
* baseObj
= asObject(LLINT_OP(1).jsValue());
888 GetterSetter
* accessor
= GetterSetter::create(vm
, exec
->lexicalGlobalObject());
889 LLINT_CHECK_EXCEPTION();
891 JSValue getter
= LLINT_OP(3).jsValue();
892 JSValue setter
= LLINT_OP(4).jsValue();
893 ASSERT(getter
.isObject() || getter
.isUndefined());
894 ASSERT(setter
.isObject() || setter
.isUndefined());
895 ASSERT(getter
.isObject() || setter
.isObject());
897 if (!getter
.isUndefined())
898 accessor
->setGetter(vm
, exec
->lexicalGlobalObject(), asObject(getter
));
899 if (!setter
.isUndefined())
900 accessor
->setSetter(vm
, exec
->lexicalGlobalObject(), asObject(setter
));
901 baseObj
->putDirectAccessor(
903 exec
->codeBlock()->identifier(pc
[2].u
.operand
),
908 LLINT_SLOW_PATH_DECL(slow_path_jtrue
)
911 LLINT_BRANCH(op_jtrue
, LLINT_OP_C(1).jsValue().toBoolean(exec
));
914 LLINT_SLOW_PATH_DECL(slow_path_jfalse
)
917 LLINT_BRANCH(op_jfalse
, !LLINT_OP_C(1).jsValue().toBoolean(exec
));
920 LLINT_SLOW_PATH_DECL(slow_path_jless
)
923 LLINT_BRANCH(op_jless
, jsLess
<true>(exec
, LLINT_OP_C(1).jsValue(), LLINT_OP_C(2).jsValue()));
926 LLINT_SLOW_PATH_DECL(slow_path_jnless
)
929 LLINT_BRANCH(op_jnless
, !jsLess
<true>(exec
, LLINT_OP_C(1).jsValue(), LLINT_OP_C(2).jsValue()));
932 LLINT_SLOW_PATH_DECL(slow_path_jgreater
)
935 LLINT_BRANCH(op_jgreater
, jsLess
<false>(exec
, LLINT_OP_C(2).jsValue(), LLINT_OP_C(1).jsValue()));
938 LLINT_SLOW_PATH_DECL(slow_path_jngreater
)
941 LLINT_BRANCH(op_jngreater
, !jsLess
<false>(exec
, LLINT_OP_C(2).jsValue(), LLINT_OP_C(1).jsValue()));
944 LLINT_SLOW_PATH_DECL(slow_path_jlesseq
)
947 LLINT_BRANCH(op_jlesseq
, jsLessEq
<true>(exec
, LLINT_OP_C(1).jsValue(), LLINT_OP_C(2).jsValue()));
950 LLINT_SLOW_PATH_DECL(slow_path_jnlesseq
)
953 LLINT_BRANCH(op_jnlesseq
, !jsLessEq
<true>(exec
, LLINT_OP_C(1).jsValue(), LLINT_OP_C(2).jsValue()));
956 LLINT_SLOW_PATH_DECL(slow_path_jgreatereq
)
959 LLINT_BRANCH(op_jgreatereq
, jsLessEq
<false>(exec
, LLINT_OP_C(2).jsValue(), LLINT_OP_C(1).jsValue()));
962 LLINT_SLOW_PATH_DECL(slow_path_jngreatereq
)
965 LLINT_BRANCH(op_jngreatereq
, !jsLessEq
<false>(exec
, LLINT_OP_C(2).jsValue(), LLINT_OP_C(1).jsValue()));
968 LLINT_SLOW_PATH_DECL(slow_path_switch_imm
)
971 JSValue scrutinee
= LLINT_OP_C(3).jsValue();
972 ASSERT(scrutinee
.isDouble());
973 double value
= scrutinee
.asDouble();
974 int32_t intValue
= static_cast<int32_t>(value
);
975 int defaultOffset
= pc
[2].u
.operand
;
976 if (value
== intValue
) {
977 CodeBlock
* codeBlock
= exec
->codeBlock();
978 pc
+= codeBlock
->switchJumpTable(pc
[1].u
.operand
).offsetForValue(intValue
, defaultOffset
);
984 LLINT_SLOW_PATH_DECL(slow_path_switch_char
)
987 JSValue scrutinee
= LLINT_OP_C(3).jsValue();
988 ASSERT(scrutinee
.isString());
989 JSString
* string
= asString(scrutinee
);
990 ASSERT(string
->length() == 1);
991 int defaultOffset
= pc
[2].u
.operand
;
992 StringImpl
* impl
= string
->value(exec
).impl();
993 CodeBlock
* codeBlock
= exec
->codeBlock();
994 pc
+= codeBlock
->switchJumpTable(pc
[1].u
.operand
).offsetForValue((*impl
)[0], defaultOffset
);
998 LLINT_SLOW_PATH_DECL(slow_path_switch_string
)
1001 JSValue scrutinee
= LLINT_OP_C(3).jsValue();
1002 int defaultOffset
= pc
[2].u
.operand
;
1003 if (!scrutinee
.isString())
1004 pc
+= defaultOffset
;
1006 CodeBlock
* codeBlock
= exec
->codeBlock();
1007 pc
+= codeBlock
->stringSwitchJumpTable(pc
[1].u
.operand
).offsetForValue(asString(scrutinee
)->value(exec
).impl(), defaultOffset
);
1012 LLINT_SLOW_PATH_DECL(slow_path_new_func
)
1015 CodeBlock
* codeBlock
= exec
->codeBlock();
1016 ASSERT(codeBlock
->codeType() != FunctionCode
|| !codeBlock
->needsActivation() || exec
->hasActivation());
1017 JSScope
* scope
= exec
->uncheckedR(pc
[2].u
.operand
).Register::scope();
1018 #if LLINT_SLOW_PATH_TRACING
1019 dataLogF("Creating function!\n");
1021 LLINT_RETURN(JSFunction::create(vm
, codeBlock
->functionDecl(pc
[3].u
.operand
), scope
));
1024 LLINT_SLOW_PATH_DECL(slow_path_new_func_exp
)
1027 CodeBlock
* codeBlock
= exec
->codeBlock();
1028 JSScope
* scope
= exec
->uncheckedR(pc
[2].u
.operand
).Register::scope();
1029 FunctionExecutable
* function
= codeBlock
->functionExpr(pc
[3].u
.operand
);
1030 JSFunction
* func
= JSFunction::create(vm
, function
, scope
);
1035 static SlowPathReturnType
handleHostCall(ExecState
* execCallee
, Instruction
* pc
, JSValue callee
, CodeSpecializationKind kind
)
1039 #if LLINT_SLOW_PATH_TRACING
1040 dataLog("Performing host call.\n");
1043 ExecState
* exec
= execCallee
->callerFrame();
1044 VM
& vm
= exec
->vm();
1046 execCallee
->setCodeBlock(0);
1047 execCallee
->clearReturnPC();
1049 if (kind
== CodeForCall
) {
1051 CallType callType
= getCallData(callee
, callData
);
1053 ASSERT(callType
!= CallTypeJS
);
1055 if (callType
== CallTypeHost
) {
1056 NativeCallFrameTracer
tracer(&vm
, execCallee
);
1057 execCallee
->setCallee(asObject(callee
));
1058 vm
.hostCallReturnValue
= JSValue::decode(callData
.native
.function(execCallee
));
1060 LLINT_CALL_RETURN(execCallee
, execCallee
, LLInt::getCodePtr(getHostCallReturnValue
));
1063 #if LLINT_SLOW_PATH_TRACING
1064 dataLog("Call callee is not a function: ", callee
, "\n");
1067 ASSERT(callType
== CallTypeNone
);
1068 LLINT_CALL_THROW(exec
, createNotAFunctionError(exec
, callee
));
1071 ASSERT(kind
== CodeForConstruct
);
1073 ConstructData constructData
;
1074 ConstructType constructType
= getConstructData(callee
, constructData
);
1076 ASSERT(constructType
!= ConstructTypeJS
);
1078 if (constructType
== ConstructTypeHost
) {
1079 NativeCallFrameTracer
tracer(&vm
, execCallee
);
1080 execCallee
->setCallee(asObject(callee
));
1081 vm
.hostCallReturnValue
= JSValue::decode(constructData
.native
.function(execCallee
));
1083 LLINT_CALL_RETURN(execCallee
, execCallee
, LLInt::getCodePtr(getHostCallReturnValue
));
1086 #if LLINT_SLOW_PATH_TRACING
1087 dataLog("Constructor callee is not a function: ", callee
, "\n");
1090 ASSERT(constructType
== ConstructTypeNone
);
1091 LLINT_CALL_THROW(exec
, createNotAConstructorError(exec
, callee
));
1094 inline SlowPathReturnType
setUpCall(ExecState
* execCallee
, Instruction
* pc
, CodeSpecializationKind kind
, JSValue calleeAsValue
, LLIntCallLinkInfo
* callLinkInfo
= 0)
1096 ExecState
* exec
= execCallee
->callerFrame();
1098 #if LLINT_SLOW_PATH_TRACING
1099 dataLogF("Performing call with recorded PC = %p\n", exec
->currentVPC());
1102 JSCell
* calleeAsFunctionCell
= getJSFunction(calleeAsValue
);
1103 if (!calleeAsFunctionCell
)
1104 return handleHostCall(execCallee
, pc
, calleeAsValue
, kind
);
1106 JSFunction
* callee
= jsCast
<JSFunction
*>(calleeAsFunctionCell
);
1107 JSScope
* scope
= callee
->scopeUnchecked();
1108 VM
& vm
= *scope
->vm();
1109 ExecutableBase
* executable
= callee
->executable();
1111 MacroAssemblerCodePtr codePtr
;
1112 CodeBlock
* codeBlock
= 0;
1113 if (executable
->isHostFunction())
1114 codePtr
= executable
->entrypointFor(vm
, kind
, MustCheckArity
, RegisterPreservationNotRequired
);
1116 FunctionExecutable
* functionExecutable
= static_cast<FunctionExecutable
*>(executable
);
1118 if (!isCall(kind
) && functionExecutable
->isBuiltinFunction())
1119 LLINT_CALL_THROW(exec
, createNotAConstructorError(exec
, callee
));
1121 JSObject
* error
= functionExecutable
->prepareForExecution(execCallee
, callee
, scope
, kind
);
1123 LLINT_CALL_THROW(exec
, error
);
1124 codeBlock
= functionExecutable
->codeBlockFor(kind
);
1126 ArityCheckMode arity
;
1127 if (execCallee
->argumentCountIncludingThis() < static_cast<size_t>(codeBlock
->numParameters()))
1128 arity
= MustCheckArity
;
1130 arity
= ArityCheckNotRequired
;
1131 codePtr
= functionExecutable
->entrypointFor(vm
, kind
, arity
, RegisterPreservationNotRequired
);
1136 if (!LLINT_ALWAYS_ACCESS_SLOW
&& callLinkInfo
) {
1137 CodeBlock
* callerCodeBlock
= exec
->codeBlock();
1139 ConcurrentJITLocker
locker(callerCodeBlock
->m_lock
);
1141 if (callLinkInfo
->isOnList())
1142 callLinkInfo
->remove();
1143 callLinkInfo
->callee
.set(vm
, callerCodeBlock
->ownerExecutable(), callee
);
1144 callLinkInfo
->lastSeenCallee
.set(vm
, callerCodeBlock
->ownerExecutable(), callee
);
1145 callLinkInfo
->machineCodeTarget
= codePtr
;
1147 codeBlock
->linkIncomingCall(exec
, callLinkInfo
);
1150 LLINT_CALL_RETURN(exec
, execCallee
, codePtr
.executableAddress());
1153 inline SlowPathReturnType
genericCall(ExecState
* exec
, Instruction
* pc
, CodeSpecializationKind kind
)
1156 // - Set up a call frame.
1157 // - Figure out what to call and compile it if necessary.
1158 // - If possible, link the call's inline cache.
1159 // - Return a tuple of machine code address to call and the new call frame.
1161 JSValue calleeAsValue
= LLINT_OP_C(2).jsValue();
1163 ExecState
* execCallee
= exec
- pc
[4].u
.operand
;
1165 execCallee
->setArgumentCountIncludingThis(pc
[3].u
.operand
);
1166 execCallee
->uncheckedR(JSStack::Callee
) = calleeAsValue
;
1167 execCallee
->setCallerFrame(exec
);
1169 ASSERT(pc
[5].u
.callLinkInfo
);
1170 return setUpCall(execCallee
, pc
, kind
, calleeAsValue
, pc
[5].u
.callLinkInfo
);
1173 LLINT_SLOW_PATH_DECL(slow_path_call
)
1175 LLINT_BEGIN_NO_SET_PC();
1176 return genericCall(exec
, pc
, CodeForCall
);
1179 LLINT_SLOW_PATH_DECL(slow_path_construct
)
1181 LLINT_BEGIN_NO_SET_PC();
1182 return genericCall(exec
, pc
, CodeForConstruct
);
1185 LLINT_SLOW_PATH_DECL(slow_path_size_frame_for_varargs
)
1189 // - Set up a call frame while respecting the variable arguments.
1191 unsigned numUsedStackSlots
= -pc
[5].u
.operand
;
1192 unsigned length
= sizeFrameForVarargs(exec
, &vm
.interpreter
->stack(),
1193 LLINT_OP_C(4).jsValue(), numUsedStackSlots
, pc
[6].u
.operand
);
1194 LLINT_CALL_CHECK_EXCEPTION(exec
, exec
);
1196 ExecState
* execCallee
= calleeFrameForVarargs(exec
, numUsedStackSlots
, length
+ 1);
1197 vm
.varargsLength
= length
;
1198 vm
.newCallFrameReturnValue
= execCallee
;
1200 LLINT_RETURN_CALLEE_FRAME(execCallee
);
1203 LLINT_SLOW_PATH_DECL(slow_path_call_varargs
)
1205 LLINT_BEGIN_NO_SET_PC();
1207 // - Figure out what to call and compile it if necessary.
1208 // - Return a tuple of machine code address to call and the new call frame.
1210 JSValue calleeAsValue
= LLINT_OP_C(2).jsValue();
1212 ExecState
* execCallee
= vm
.newCallFrameReturnValue
;
1214 setupVarargsFrameAndSetThis(exec
, execCallee
, LLINT_OP_C(3).jsValue(), LLINT_OP_C(4).jsValue(), pc
[6].u
.operand
, vm
.varargsLength
);
1215 LLINT_CALL_CHECK_EXCEPTION(exec
, exec
);
1217 execCallee
->uncheckedR(JSStack::Callee
) = calleeAsValue
;
1218 execCallee
->setCallerFrame(exec
);
1219 exec
->setCurrentVPC(pc
);
1221 return setUpCall(execCallee
, pc
, CodeForCall
, calleeAsValue
);
1224 LLINT_SLOW_PATH_DECL(slow_path_construct_varargs
)
1226 LLINT_BEGIN_NO_SET_PC();
1228 // - Figure out what to call and compile it if necessary.
1229 // - Return a tuple of machine code address to call and the new call frame.
1231 JSValue calleeAsValue
= LLINT_OP_C(2).jsValue();
1233 ExecState
* execCallee
= vm
.newCallFrameReturnValue
;
1235 setupVarargsFrameAndSetThis(exec
, execCallee
, LLINT_OP_C(3).jsValue(), LLINT_OP_C(4).jsValue(), pc
[6].u
.operand
, vm
.varargsLength
);
1236 LLINT_CALL_CHECK_EXCEPTION(exec
, exec
);
1238 execCallee
->uncheckedR(JSStack::Callee
) = calleeAsValue
;
1239 execCallee
->setCallerFrame(exec
);
1240 exec
->setCurrentVPC(pc
);
1242 return setUpCall(execCallee
, pc
, CodeForConstruct
, calleeAsValue
);
1245 LLINT_SLOW_PATH_DECL(slow_path_call_eval
)
1247 LLINT_BEGIN_NO_SET_PC();
1248 JSValue calleeAsValue
= LLINT_OP(2).jsValue();
1250 ExecState
* execCallee
= exec
- pc
[4].u
.operand
;
1252 execCallee
->setArgumentCountIncludingThis(pc
[3].u
.operand
);
1253 execCallee
->setCallerFrame(exec
);
1254 execCallee
->uncheckedR(JSStack::Callee
) = calleeAsValue
;
1255 execCallee
->setReturnPC(LLInt::getCodePtr(llint_generic_return_point
));
1256 execCallee
->setCodeBlock(0);
1257 exec
->setCurrentVPC(pc
);
1259 if (!isHostFunction(calleeAsValue
, globalFuncEval
))
1260 return setUpCall(execCallee
, pc
, CodeForCall
, calleeAsValue
);
1262 vm
.hostCallReturnValue
= eval(execCallee
);
1263 LLINT_CALL_RETURN(exec
, execCallee
, LLInt::getCodePtr(getHostCallReturnValue
));
1266 LLINT_SLOW_PATH_DECL(slow_path_strcat
)
1269 LLINT_RETURN(jsStringFromRegisterArray(exec
, &LLINT_OP(2), pc
[3].u
.operand
));
1272 LLINT_SLOW_PATH_DECL(slow_path_to_primitive
)
1275 LLINT_RETURN(LLINT_OP_C(2).jsValue().toPrimitive(exec
));
1278 LLINT_SLOW_PATH_DECL(slow_path_push_with_scope
)
1281 JSValue v
= LLINT_OP_C(2).jsValue();
1282 JSObject
* o
= v
.toObject(exec
);
1283 LLINT_CHECK_EXCEPTION();
1285 int scopeReg
= pc
[1].u
.operand
;
1286 JSScope
* currentScope
= exec
->uncheckedR(scopeReg
).Register::scope();
1287 exec
->uncheckedR(scopeReg
) = JSWithScope::create(exec
, o
, currentScope
);
1292 LLINT_SLOW_PATH_DECL(slow_path_pop_scope
)
1295 int scopeReg
= pc
[1].u
.operand
;
1296 JSScope
* scope
= exec
->uncheckedR(scopeReg
).Register::scope();
1297 exec
->uncheckedR(scopeReg
) = scope
->next();
1301 LLINT_SLOW_PATH_DECL(slow_path_push_name_scope
)
1304 int scopeReg
= pc
[1].u
.operand
;
1305 JSScope
* currentScope
= exec
->uncheckedR(scopeReg
).Register::scope();
1306 JSValue value
= LLINT_OP_C(2).jsValue();
1307 SymbolTable
* symbolTable
= jsCast
<SymbolTable
*>(LLINT_OP_C(3).jsValue());
1308 JSNameScope::Type type
= static_cast<JSNameScope::Type
>(pc
[4].u
.operand
);
1309 JSNameScope
* scope
= JSNameScope::create(vm
, exec
->lexicalGlobalObject(), currentScope
, symbolTable
, value
, type
);
1310 exec
->uncheckedR(scopeReg
) = scope
;
1314 LLINT_SLOW_PATH_DECL(slow_path_throw
)
1317 LLINT_THROW(LLINT_OP_C(1).jsValue());
1320 LLINT_SLOW_PATH_DECL(slow_path_throw_static_error
)
1323 JSValue errorMessageValue
= LLINT_OP_C(1).jsValue();
1324 RELEASE_ASSERT(errorMessageValue
.isString());
1325 String errorMessage
= asString(errorMessageValue
)->value(exec
);
1326 if (pc
[2].u
.operand
)
1327 LLINT_THROW(createReferenceError(exec
, errorMessage
));
1329 LLINT_THROW(createTypeError(exec
, errorMessage
));
1332 LLINT_SLOW_PATH_DECL(slow_path_handle_watchdog_timer
)
1334 LLINT_BEGIN_NO_SET_PC();
1335 ASSERT(vm
.watchdog
);
1336 if (UNLIKELY(vm
.watchdog
->didFire(exec
)))
1337 LLINT_THROW(createTerminatedExecutionException(&vm
));
1338 LLINT_RETURN_TWO(0, exec
);
1341 LLINT_SLOW_PATH_DECL(slow_path_debug
)
1344 int debugHookID
= pc
[1].u
.operand
;
1345 vm
.interpreter
->debug(exec
, static_cast<DebugHookID
>(debugHookID
));
1350 LLINT_SLOW_PATH_DECL(slow_path_profile_will_call
)
1353 if (LegacyProfiler
* profiler
= vm
.enabledProfiler())
1354 profiler
->willExecute(exec
, LLINT_OP(1).jsValue());
1358 LLINT_SLOW_PATH_DECL(slow_path_profile_did_call
)
1361 if (LegacyProfiler
* profiler
= vm
.enabledProfiler())
1362 profiler
->didExecute(exec
, LLINT_OP(1).jsValue());
1366 LLINT_SLOW_PATH_DECL(slow_path_handle_exception
)
1368 LLINT_BEGIN_NO_SET_PC();
1369 genericUnwind(&vm
, exec
);
1373 LLINT_SLOW_PATH_DECL(slow_path_resolve_scope
)
1376 const Identifier
& ident
= exec
->codeBlock()->identifier(pc
[3].u
.operand
);
1377 JSScope
* scope
= LLINT_OP(2).Register::scope();
1378 LLINT_RETURN(JSScope::resolve(exec
, scope
, ident
));
1381 LLINT_SLOW_PATH_DECL(slow_path_get_from_scope
)
1385 const Identifier
& ident
= exec
->codeBlock()->identifier(pc
[3].u
.operand
);
1386 JSObject
* scope
= jsCast
<JSObject
*>(LLINT_OP(2).jsValue());
1387 ResolveModeAndType
modeAndType(pc
[4].u
.operand
);
1389 PropertySlot
slot(scope
);
1390 if (!scope
->getPropertySlot(exec
, ident
, slot
)) {
1391 if (modeAndType
.mode() == ThrowIfNotFound
)
1392 LLINT_RETURN(exec
->vm().throwException(exec
, createUndefinedVariableError(exec
, ident
)));
1393 LLINT_RETURN(jsUndefined());
1396 // Covers implicit globals. Since they don't exist until they first execute, we didn't know how to cache them at compile time.
1397 if (slot
.isCacheableValue() && slot
.slotBase() == scope
&& scope
->structure()->propertyAccessesAreCacheable()) {
1398 if (modeAndType
.type() == GlobalProperty
|| modeAndType
.type() == GlobalPropertyWithVarInjectionChecks
) {
1399 CodeBlock
* codeBlock
= exec
->codeBlock();
1400 Structure
* structure
= scope
->structure(vm
);
1402 ConcurrentJITLocker
locker(codeBlock
->m_lock
);
1403 pc
[5].u
.structure
.set(exec
->vm(), codeBlock
->ownerExecutable(), structure
);
1404 pc
[6].u
.operand
= slot
.cachedOffset();
1406 structure
->startWatchingPropertyForReplacements(vm
, slot
.cachedOffset());
1410 LLINT_RETURN(slot
.getValue(exec
, ident
));
1413 LLINT_SLOW_PATH_DECL(slow_path_put_to_scope
)
1417 CodeBlock
* codeBlock
= exec
->codeBlock();
1418 const Identifier
& ident
= codeBlock
->identifier(pc
[2].u
.operand
);
1419 JSObject
* scope
= jsCast
<JSObject
*>(LLINT_OP(1).jsValue());
1420 JSValue value
= LLINT_OP_C(3).jsValue();
1421 ResolveModeAndType modeAndType
= ResolveModeAndType(pc
[4].u
.operand
);
1422 if (modeAndType
.type() == LocalClosureVar
) {
1423 JSLexicalEnvironment
* environment
= jsCast
<JSLexicalEnvironment
*>(scope
);
1424 environment
->variableAt(ScopeOffset(pc
[6].u
.operand
)).set(vm
, environment
, value
);
1426 // Have to do this *after* the write, because if this puts the set into IsWatched, then we need
1427 // to have already changed the value of the variable. Otherwise we might watch and constant-fold
1428 // to the Undefined value from before the assignment.
1429 if (WatchpointSet
* set
= pc
[5].u
.watchpointSet
)
1430 set
->touch("Executed op_put_scope<LocalClosureVar>");
1434 if (modeAndType
.mode() == ThrowIfNotFound
&& !scope
->hasProperty(exec
, ident
))
1435 LLINT_THROW(createUndefinedVariableError(exec
, ident
));
1437 PutPropertySlot
slot(scope
, codeBlock
->isStrictMode());
1438 scope
->methodTable()->put(scope
, exec
, ident
, value
, slot
);
1440 CommonSlowPaths::tryCachePutToScopeGlobal(exec
, codeBlock
, pc
, scope
, modeAndType
, slot
);
1445 extern "C" SlowPathReturnType
llint_throw_stack_overflow_error(VM
* vm
, ProtoCallFrame
* protoFrame
)
1447 ExecState
* exec
= vm
->topCallFrame
;
1449 exec
= protoFrame
->callee()->globalObject()->globalExec();
1450 throwStackOverflowError(exec
);
1451 return encodeResult(0, 0);
1455 extern "C" SlowPathReturnType
llint_stack_check_at_vm_entry(VM
* vm
, Register
* newTopOfStack
)
1457 bool success
= vm
->interpreter
->stack().ensureCapacityFor(newTopOfStack
);
1458 return encodeResult(reinterpret_cast<void*>(success
), 0);
1462 extern "C" void llint_write_barrier_slow(ExecState
* exec
, JSCell
* cell
)
1464 VM
& vm
= exec
->vm();
1465 vm
.heap
.writeBarrier(cell
);
1468 extern "C" NO_RETURN_DUE_TO_CRASH
void llint_crash()
1473 } } // namespace JSC::LLInt