2 * Copyright (C) 2011, 2012, 2013, 2014 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"
28 #include "Arguments.h"
29 #include "ArrayConstructor.h"
30 #include "CallFrame.h"
31 #include "CommonSlowPaths.h"
32 #include "CommonSlowPathsExceptions.h"
33 #include "ErrorHandlingScope.h"
34 #include "GetterSetter.h"
35 #include "HostCallReturnValue.h"
36 #include "Interpreter.h"
38 #include "JITExceptions.h"
39 #include "JSActivation.h"
40 #include "JSCJSValue.h"
41 #include "JSGlobalObjectFunctions.h"
42 #include "JSNameScope.h"
43 #include "JSPropertyNameIterator.h"
44 #include "JSStackInlines.h"
46 #include "JSWithScope.h"
47 #include "LLIntCommon.h"
48 #include "LLIntExceptions.h"
49 #include "LowLevelInterpreter.h"
50 #include "ObjectConstructor.h"
51 #include "JSCInlines.h"
52 #include "ProtoCallFrame.h"
53 #include "StructureRareDataInlines.h"
54 #include <wtf/StringPrintStream.h>
56 namespace JSC
{ namespace LLInt
{
58 #define LLINT_BEGIN_NO_SET_PC() \
59 VM& vm = exec->vm(); \
60 NativeCallFrameTracer tracer(&vm, exec)
63 #define LLINT_SET_PC_FOR_STUBS() do { \
64 exec->codeBlock()->bytecodeOffset(pc); \
65 exec->setCurrentVPC(pc + 1); \
68 #define LLINT_SET_PC_FOR_STUBS() do { \
69 exec->setCurrentVPC(pc + 1); \
73 #define LLINT_BEGIN() \
74 LLINT_BEGIN_NO_SET_PC(); \
75 LLINT_SET_PC_FOR_STUBS()
77 #define LLINT_OP(index) (exec->uncheckedR(pc[index].u.operand))
78 #define LLINT_OP_C(index) (exec->r(pc[index].u.operand))
80 #define LLINT_RETURN_TWO(first, second) do { \
81 return encodeResult(first, second); \
84 #define LLINT_END_IMPL() LLINT_RETURN_TWO(pc, 0)
86 #define LLINT_THROW(exceptionToThrow) do { \
87 vm.throwException(exec, exceptionToThrow); \
88 pc = returnToThrow(exec); \
92 #define LLINT_CHECK_EXCEPTION() do { \
93 if (UNLIKELY(vm.exception())) { \
94 pc = returnToThrow(exec); \
99 #define LLINT_END() do { \
100 LLINT_CHECK_EXCEPTION(); \
104 #define LLINT_BRANCH(opcode, condition) do { \
105 bool __b_condition = (condition); \
106 LLINT_CHECK_EXCEPTION(); \
108 pc += pc[OPCODE_LENGTH(opcode) - 1].u.operand; \
110 pc += OPCODE_LENGTH(opcode); \
114 #define LLINT_RETURN(value) do { \
115 JSValue __r_returnValue = (value); \
116 LLINT_CHECK_EXCEPTION(); \
117 LLINT_OP(1) = __r_returnValue; \
121 #define LLINT_RETURN_WITH_PC_ADJUSTMENT(value, pcAdjustment) do { \
122 JSValue __r_returnValue = (value); \
123 LLINT_CHECK_EXCEPTION(); \
124 LLINT_OP(1) = __r_returnValue; \
125 pc += (pcAdjustment); \
129 #define LLINT_RETURN_PROFILED(opcode, value) do { \
130 JSValue __rp_returnValue = (value); \
131 LLINT_CHECK_EXCEPTION(); \
132 LLINT_OP(1) = __rp_returnValue; \
133 LLINT_PROFILE_VALUE(opcode, __rp_returnValue); \
137 #define LLINT_PROFILE_VALUE(opcode, value) do { \
138 pc[OPCODE_LENGTH(opcode) - 1].u.profile->m_buckets[0] = \
139 JSValue::encode(value); \
142 #define LLINT_CALL_END_IMPL(exec, callTarget) LLINT_RETURN_TWO((callTarget), (exec))
144 #define LLINT_CALL_THROW(exec, exceptionToThrow) do { \
145 ExecState* __ct_exec = (exec); \
146 vm.throwException(__ct_exec, exceptionToThrow); \
147 LLINT_CALL_END_IMPL(0, callToThrow(__ct_exec)); \
150 #define LLINT_CALL_CHECK_EXCEPTION(exec) do { \
151 ExecState* __cce_exec = (exec); \
152 if (UNLIKELY(vm.exception())) \
153 LLINT_CALL_END_IMPL(0, callToThrow(__cce_exec)); \
156 #define LLINT_CALL_RETURN(exec, callTarget) do { \
157 ExecState* __cr_exec = (exec); \
158 void* __cr_callTarget = (callTarget); \
159 LLINT_CALL_CHECK_EXCEPTION(__cr_exec); \
160 LLINT_CALL_END_IMPL(__cr_exec, __cr_callTarget); \
163 #define LLINT_RETURN_CALLEE_FRAME(execCallee) do { \
164 ExecState* __rcf_exec = (execCallee); \
165 LLINT_RETURN_TWO(pc, __rcf_exec); \
169 extern "C" SlowPathReturnType
llint_trace_operand(ExecState
* exec
, Instruction
* pc
, int fromWhere
, int operand
)
172 dataLogF("%p / %p: executing bc#%zu, op#%u: Trace(%d): %d: %d\n",
175 static_cast<intptr_t>(pc
- exec
->codeBlock()->instructions().begin()),
176 exec
->vm().interpreter
->getOpcodeID(pc
[0].u
.opcode
),
179 pc
[operand
].u
.operand
);
183 extern "C" SlowPathReturnType
llint_trace_value(ExecState
* exec
, Instruction
* pc
, int fromWhere
, int operand
)
185 JSValue value
= LLINT_OP_C(operand
).jsValue();
191 EncodedJSValue asValue
;
193 u
.asValue
= JSValue::encode(value
);
195 "%p / %p: executing bc#%zu, op#%u: Trace(%d): %d: %d: %08x:%08x: %s\n",
198 static_cast<intptr_t>(pc
- exec
->codeBlock()->instructions().begin()),
199 exec
->vm().interpreter
->getOpcodeID(pc
[0].u
.opcode
),
202 pc
[operand
].u
.operand
,
205 toCString(value
).data());
209 LLINT_SLOW_PATH_DECL(trace_prologue
)
211 dataLogF("%p / %p: in prologue.\n", exec
->codeBlock(), exec
);
215 static void traceFunctionPrologue(ExecState
* exec
, const char* comment
, CodeSpecializationKind kind
)
217 JSFunction
* callee
= jsCast
<JSFunction
*>(exec
->callee());
218 FunctionExecutable
* executable
= callee
->jsExecutable();
219 CodeBlock
* codeBlock
= executable
->codeBlockFor(kind
);
220 dataLogF("%p / %p: in %s of function %p, executable %p; numVars = %u, numParameters = %u, numCalleeRegisters = %u, caller = %p.\n",
221 codeBlock
, exec
, comment
, callee
, executable
,
222 codeBlock
->m_numVars
, codeBlock
->numParameters(), codeBlock
->m_numCalleeRegisters
,
223 exec
->callerFrame());
226 LLINT_SLOW_PATH_DECL(trace_prologue_function_for_call
)
228 traceFunctionPrologue(exec
, "call prologue", CodeForCall
);
232 LLINT_SLOW_PATH_DECL(trace_prologue_function_for_construct
)
234 traceFunctionPrologue(exec
, "construct prologue", CodeForConstruct
);
238 LLINT_SLOW_PATH_DECL(trace_arityCheck_for_call
)
240 traceFunctionPrologue(exec
, "call arity check", CodeForCall
);
244 LLINT_SLOW_PATH_DECL(trace_arityCheck_for_construct
)
246 traceFunctionPrologue(exec
, "construct arity check", CodeForConstruct
);
250 LLINT_SLOW_PATH_DECL(trace
)
252 dataLogF("%p / %p: executing bc#%zu, %s, scope %p, pc = %p\n",
255 static_cast<intptr_t>(pc
- exec
->codeBlock()->instructions().begin()),
256 opcodeNames
[exec
->vm().interpreter
->getOpcodeID(pc
[0].u
.opcode
)],
258 if (exec
->vm().interpreter
->getOpcodeID(pc
[0].u
.opcode
) == op_enter
) {
259 dataLogF("Frame will eventually return to %p\n", exec
->returnPC().value());
260 *bitwise_cast
<volatile char*>(exec
->returnPC().value());
262 if (exec
->vm().interpreter
->getOpcodeID(pc
[0].u
.opcode
) == op_ret
) {
263 dataLogF("Will be returning to %p\n", exec
->returnPC().value());
264 dataLogF("The new cfr will be %p\n", exec
->callerFrame());
269 LLINT_SLOW_PATH_DECL(special_trace
)
271 dataLogF("%p / %p: executing special case bc#%zu, op#%u, return PC is %p\n",
274 static_cast<intptr_t>(pc
- exec
->codeBlock()->instructions().begin()),
275 exec
->vm().interpreter
->getOpcodeID(pc
[0].u
.opcode
),
276 exec
->returnPC().value());
280 enum EntryKind
{ Prologue
, ArityCheck
};
283 inline bool shouldJIT(ExecState
* exec
)
285 // You can modify this to turn off JITting without rebuilding the world.
286 return exec
->vm().canUseJIT();
289 // Returns true if we should try to OSR.
290 inline bool jitCompileAndSetHeuristics(CodeBlock
* codeBlock
, ExecState
* exec
)
293 DeferGCForAWhile
deferGC(vm
.heap
); // My callers don't set top callframe, so we don't want to GC here at all.
295 codeBlock
->updateAllValueProfilePredictions();
297 if (!codeBlock
->checkIfJITThresholdReached()) {
298 if (Options::verboseOSR())
299 dataLogF(" JIT threshold should be lifted.\n");
303 switch (codeBlock
->jitType()) {
304 case JITCode::BaselineJIT
: {
305 if (Options::verboseOSR())
306 dataLogF(" Code was already compiled.\n");
307 codeBlock
->jitSoon();
310 case JITCode::InterpreterThunk
: {
311 CompilationResult result
= JIT::compile(&vm
, codeBlock
, JITCompilationCanFail
);
313 case CompilationFailed
:
314 if (Options::verboseOSR())
315 dataLogF(" JIT compilation failed.\n");
316 codeBlock
->dontJITAnytimeSoon();
318 case CompilationSuccessful
:
319 if (Options::verboseOSR())
320 dataLogF(" JIT compilation successful.\n");
321 codeBlock
->install();
322 codeBlock
->jitSoon();
325 RELEASE_ASSERT_NOT_REACHED();
330 RELEASE_ASSERT_NOT_REACHED();
335 static SlowPathReturnType
entryOSR(ExecState
* exec
, Instruction
*, CodeBlock
* codeBlock
, const char *name
, EntryKind kind
)
337 if (Options::verboseOSR()) {
339 *codeBlock
, ": Entered ", name
, " with executeCounter = ",
340 codeBlock
->llintExecuteCounter(), "\n");
343 if (!shouldJIT(exec
)) {
344 codeBlock
->dontJITAnytimeSoon();
345 LLINT_RETURN_TWO(0, 0);
347 if (!jitCompileAndSetHeuristics(codeBlock
, exec
))
348 LLINT_RETURN_TWO(0, 0);
350 if (kind
== Prologue
)
351 LLINT_RETURN_TWO(codeBlock
->jitCode()->executableAddress(), 0);
352 ASSERT(kind
== ArityCheck
);
353 LLINT_RETURN_TWO(codeBlock
->jitCode()->addressForCall(
354 *codeBlock
->vm(), codeBlock
->ownerExecutable(), MustCheckArity
,
355 RegisterPreservationNotRequired
).executableAddress(), 0);
358 static SlowPathReturnType
entryOSR(ExecState
* exec
, Instruction
*, CodeBlock
* codeBlock
, const char*, EntryKind
)
360 codeBlock
->dontJITAnytimeSoon();
361 LLINT_RETURN_TWO(0, exec
);
363 #endif // ENABLE(JIT)
365 LLINT_SLOW_PATH_DECL(entry_osr
)
367 return entryOSR(exec
, pc
, exec
->codeBlock(), "entry_osr", Prologue
);
370 LLINT_SLOW_PATH_DECL(entry_osr_function_for_call
)
372 return entryOSR(exec
, pc
, jsCast
<JSFunction
*>(exec
->callee())->jsExecutable()->codeBlockForCall(), "entry_osr_function_for_call", Prologue
);
375 LLINT_SLOW_PATH_DECL(entry_osr_function_for_construct
)
377 return entryOSR(exec
, pc
, jsCast
<JSFunction
*>(exec
->callee())->jsExecutable()->codeBlockForConstruct(), "entry_osr_function_for_construct", Prologue
);
380 LLINT_SLOW_PATH_DECL(entry_osr_function_for_call_arityCheck
)
382 return entryOSR(exec
, pc
, jsCast
<JSFunction
*>(exec
->callee())->jsExecutable()->codeBlockForCall(), "entry_osr_function_for_call_arityCheck", ArityCheck
);
385 LLINT_SLOW_PATH_DECL(entry_osr_function_for_construct_arityCheck
)
387 return entryOSR(exec
, pc
, jsCast
<JSFunction
*>(exec
->callee())->jsExecutable()->codeBlockForConstruct(), "entry_osr_function_for_construct_arityCheck", ArityCheck
);
390 LLINT_SLOW_PATH_DECL(loop_osr
)
392 CodeBlock
* codeBlock
= exec
->codeBlock();
395 if (Options::verboseOSR()) {
397 *codeBlock
, ": Entered loop_osr with executeCounter = ",
398 codeBlock
->llintExecuteCounter(), "\n");
401 if (!shouldJIT(exec
)) {
402 codeBlock
->dontJITAnytimeSoon();
403 LLINT_RETURN_TWO(0, 0);
406 if (!jitCompileAndSetHeuristics(codeBlock
, exec
))
407 LLINT_RETURN_TWO(0, 0);
409 ASSERT(codeBlock
->jitType() == JITCode::BaselineJIT
);
411 Vector
<BytecodeAndMachineOffset
> map
;
412 codeBlock
->jitCodeMap()->decode(map
);
413 BytecodeAndMachineOffset
* mapping
= binarySearch
<BytecodeAndMachineOffset
, unsigned>(map
, map
.size(), pc
- codeBlock
->instructions().begin(), BytecodeAndMachineOffset::getBytecodeIndex
);
415 ASSERT(mapping
->m_bytecodeIndex
== static_cast<unsigned>(pc
- codeBlock
->instructions().begin()));
417 void* jumpTarget
= codeBlock
->jitCode()->executableAddressAtOffset(mapping
->m_machineCodeOffset
);
420 LLINT_RETURN_TWO(jumpTarget
, exec
->topOfFrame());
423 codeBlock
->dontJITAnytimeSoon();
424 LLINT_RETURN_TWO(0, 0);
425 #endif // ENABLE(JIT)
428 LLINT_SLOW_PATH_DECL(replace
)
430 CodeBlock
* codeBlock
= exec
->codeBlock();
433 if (Options::verboseOSR()) {
435 *codeBlock
, ": Entered replace with executeCounter = ",
436 codeBlock
->llintExecuteCounter(), "\n");
440 jitCompileAndSetHeuristics(codeBlock
, exec
);
442 codeBlock
->dontJITAnytimeSoon();
445 codeBlock
->dontJITAnytimeSoon();
447 #endif // ENABLE(JIT)
450 LLINT_SLOW_PATH_DECL(stack_check
)
453 #if LLINT_SLOW_PATH_TRACING
454 dataLogF("Checking stack height with exec = %p.\n", exec
);
455 dataLogF("CodeBlock = %p.\n", exec
->codeBlock());
456 dataLogF("Num callee registers = %u.\n", exec
->codeBlock()->m_numCalleeRegisters
);
457 dataLogF("Num vars = %u.\n", exec
->codeBlock()->m_numVars
);
459 #if ENABLE(LLINT_C_LOOP)
460 dataLogF("Current end is at %p.\n", exec
->vm().jsStackLimit());
462 dataLogF("Current end is at %p.\n", exec
->vm().stackLimit());
466 // This stack check is done in the prologue for a function call, and the
467 // CallFrame is not completely set up yet. For example, if the frame needs
468 // an activation object, the activation object will only be set up after
469 // we start executing the function. If we need to throw a StackOverflowError
470 // here, then we need to tell the prologue to start the stack unwinding from
471 // the caller frame (which is fully set up) instead. To do that, we return
472 // the caller's CallFrame in the second return value.
474 // If the stack check succeeds and we don't need to throw the error, then
475 // we'll return 0 instead. The prologue will check for a non-zero value
476 // when determining whether to set the callFrame or not.
478 // For JIT enabled builds which uses the C stack, the stack is not growable.
479 // Hence, if we get here, then we know a stack overflow is imminent. So, just
480 // throw the StackOverflowError unconditionally.
482 ASSERT(!vm
.interpreter
->stack().containsAddress(exec
->topOfFrame()));
483 if (LIKELY(vm
.interpreter
->stack().ensureCapacityFor(exec
->topOfFrame())))
484 LLINT_RETURN_TWO(pc
, 0);
487 exec
= exec
->callerFrame();
488 vm
.topCallFrame
= exec
;
489 ErrorHandlingScope
errorScope(vm
);
490 CommonSlowPaths::interpreterThrowInCaller(exec
, createStackOverflowError(exec
));
491 pc
= returnToThrowForThrownException(exec
);
492 LLINT_RETURN_TWO(pc
, exec
);
495 LLINT_SLOW_PATH_DECL(slow_path_create_activation
)
498 #if LLINT_SLOW_PATH_TRACING
499 dataLogF("Creating an activation, exec = %p!\n", exec
);
501 JSActivation
* activation
= JSActivation::create(vm
, exec
, exec
->codeBlock());
502 exec
->setScope(activation
);
503 LLINT_RETURN(JSValue(activation
));
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(constructArrayNegativeIndexed(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()->regExpStructure(), regExp
));
539 LLINT_SLOW_PATH_DECL(slow_path_check_has_instance
)
543 JSValue value
= LLINT_OP_C(2).jsValue();
544 JSValue baseVal
= LLINT_OP_C(3).jsValue();
545 if (baseVal
.isObject()) {
546 JSObject
* baseObject
= asObject(baseVal
);
547 ASSERT(!baseObject
->structure()->typeInfo().implementsDefaultHasInstance());
548 if (baseObject
->structure()->typeInfo().implementsHasInstance()) {
549 JSValue result
= jsBoolean(baseObject
->methodTable()->customHasInstance(baseObject
, exec
, value
));
550 LLINT_RETURN_WITH_PC_ADJUSTMENT(result
, pc
[4].u
.operand
);
553 LLINT_THROW(createInvalidParameterError(exec
, "instanceof", baseVal
));
556 LLINT_SLOW_PATH_DECL(slow_path_instanceof
)
559 JSValue value
= LLINT_OP_C(2).jsValue();
560 JSValue proto
= LLINT_OP_C(3).jsValue();
561 ASSERT(!value
.isObject() || !proto
.isObject());
562 LLINT_RETURN(jsBoolean(JSObject::defaultHasInstance(exec
, value
, proto
)));
565 LLINT_SLOW_PATH_DECL(slow_path_get_by_id
)
568 CodeBlock
* codeBlock
= exec
->codeBlock();
569 const Identifier
& ident
= codeBlock
->identifier(pc
[3].u
.operand
);
570 JSValue baseValue
= LLINT_OP_C(2).jsValue();
571 PropertySlot
slot(baseValue
);
573 JSValue result
= baseValue
.get(exec
, ident
, slot
);
574 LLINT_CHECK_EXCEPTION();
575 LLINT_OP(1) = result
;
577 if (!LLINT_ALWAYS_ACCESS_SLOW
578 && baseValue
.isCell()
579 && slot
.isCacheable()
580 && slot
.slotBase() == baseValue
581 && slot
.isCacheableValue()) {
583 JSCell
* baseCell
= baseValue
.asCell();
584 Structure
* structure
= baseCell
->structure();
586 if (!structure
->isUncacheableDictionary()
587 && !structure
->typeInfo().prohibitsPropertyCaching()
588 && !structure
->typeInfo().newImpurePropertyFiresWatchpoints()) {
589 ConcurrentJITLocker
locker(codeBlock
->m_lock
);
591 pc
[4].u
.structure
.set(
592 vm
, codeBlock
->ownerExecutable(), structure
);
593 if (isInlineOffset(slot
.cachedOffset())) {
594 pc
[0].u
.opcode
= LLInt::getOpcode(op_get_by_id
);
595 pc
[5].u
.operand
= offsetInInlineStorage(slot
.cachedOffset()) * sizeof(JSValue
) + JSObject::offsetOfInlineStorage();
597 pc
[0].u
.opcode
= LLInt::getOpcode(op_get_by_id_out_of_line
);
598 pc
[5].u
.operand
= offsetInButterfly(slot
.cachedOffset()) * sizeof(JSValue
);
603 if (!LLINT_ALWAYS_ACCESS_SLOW
604 && isJSArray(baseValue
)
605 && ident
== exec
->propertyNames().length
) {
606 pc
[0].u
.opcode
= LLInt::getOpcode(op_get_array_length
);
607 ArrayProfile
* arrayProfile
= codeBlock
->getOrAddArrayProfile(pc
- codeBlock
->instructions().begin());
608 arrayProfile
->observeStructure(baseValue
.asCell()->structure());
609 pc
[4].u
.arrayProfile
= arrayProfile
;
612 pc
[OPCODE_LENGTH(op_get_by_id
) - 1].u
.profile
->m_buckets
[0] = JSValue::encode(result
);
616 LLINT_SLOW_PATH_DECL(slow_path_get_arguments_length
)
619 CodeBlock
* codeBlock
= exec
->codeBlock();
620 const Identifier
& ident
= codeBlock
->identifier(pc
[3].u
.operand
);
621 JSValue baseValue
= LLINT_OP(2).jsValue();
622 PropertySlot
slot(baseValue
);
623 LLINT_RETURN(baseValue
.get(exec
, ident
, slot
));
626 LLINT_SLOW_PATH_DECL(slow_path_put_by_id
)
629 CodeBlock
* codeBlock
= exec
->codeBlock();
630 const Identifier
& ident
= codeBlock
->identifier(pc
[2].u
.operand
);
632 JSValue baseValue
= LLINT_OP_C(1).jsValue();
633 PutPropertySlot
slot(baseValue
, codeBlock
->isStrictMode(), codeBlock
->putByIdContext());
635 asObject(baseValue
)->putDirect(vm
, ident
, LLINT_OP_C(3).jsValue(), slot
);
637 baseValue
.put(exec
, ident
, LLINT_OP_C(3).jsValue(), slot
);
638 LLINT_CHECK_EXCEPTION();
640 if (!LLINT_ALWAYS_ACCESS_SLOW
641 && baseValue
.isCell()
642 && slot
.isCacheablePut()) {
644 JSCell
* baseCell
= baseValue
.asCell();
645 Structure
* structure
= baseCell
->structure();
647 if (!structure
->isUncacheableDictionary()
648 && !structure
->typeInfo().prohibitsPropertyCaching()
649 && baseCell
== slot
.base()) {
651 if (slot
.type() == PutPropertySlot::NewProperty
) {
652 GCSafeConcurrentJITLocker
locker(codeBlock
->m_lock
, vm
.heap
);
654 if (!structure
->isDictionary() && structure
->previousID()->outOfLineCapacity() == structure
->outOfLineCapacity()) {
655 ASSERT(structure
->previousID()->transitionWatchpointSetHasBeenInvalidated());
657 // This is needed because some of the methods we call
659 pc
[0].u
.opcode
= LLInt::getOpcode(op_put_by_id
);
661 if (normalizePrototypeChain(exec
, baseCell
) != InvalidPrototypeChain
) {
662 ASSERT(structure
->previousID()->isObject());
663 pc
[4].u
.structure
.set(
664 vm
, codeBlock
->ownerExecutable(), structure
->previousID());
665 if (isInlineOffset(slot
.cachedOffset()))
666 pc
[5].u
.operand
= offsetInInlineStorage(slot
.cachedOffset()) * sizeof(JSValue
) + JSObject::offsetOfInlineStorage();
668 pc
[5].u
.operand
= offsetInButterfly(slot
.cachedOffset()) * sizeof(JSValue
);
669 pc
[6].u
.structure
.set(
670 vm
, codeBlock
->ownerExecutable(), structure
);
671 StructureChain
* chain
= structure
->prototypeChain(exec
);
673 pc
[7].u
.structureChain
.set(
674 vm
, codeBlock
->ownerExecutable(), chain
);
676 if (pc
[8].u
.operand
) {
677 if (isInlineOffset(slot
.cachedOffset()))
678 pc
[0].u
.opcode
= LLInt::getOpcode(op_put_by_id_transition_direct
);
680 pc
[0].u
.opcode
= LLInt::getOpcode(op_put_by_id_transition_direct_out_of_line
);
682 if (isInlineOffset(slot
.cachedOffset()))
683 pc
[0].u
.opcode
= LLInt::getOpcode(op_put_by_id_transition_normal
);
685 pc
[0].u
.opcode
= LLInt::getOpcode(op_put_by_id_transition_normal_out_of_line
);
690 pc
[4].u
.structure
.set(
691 vm
, codeBlock
->ownerExecutable(), structure
);
692 if (isInlineOffset(slot
.cachedOffset())) {
693 pc
[0].u
.opcode
= LLInt::getOpcode(op_put_by_id
);
694 pc
[5].u
.operand
= offsetInInlineStorage(slot
.cachedOffset()) * sizeof(JSValue
) + JSObject::offsetOfInlineStorage();
696 pc
[0].u
.opcode
= LLInt::getOpcode(op_put_by_id_out_of_line
);
697 pc
[5].u
.operand
= offsetInButterfly(slot
.cachedOffset()) * sizeof(JSValue
);
706 LLINT_SLOW_PATH_DECL(slow_path_del_by_id
)
709 CodeBlock
* codeBlock
= exec
->codeBlock();
710 JSObject
* baseObject
= LLINT_OP_C(2).jsValue().toObject(exec
);
711 bool couldDelete
= baseObject
->methodTable()->deleteProperty(baseObject
, exec
, codeBlock
->identifier(pc
[3].u
.operand
));
712 LLINT_CHECK_EXCEPTION();
713 if (!couldDelete
&& codeBlock
->isStrictMode())
714 LLINT_THROW(createTypeError(exec
, "Unable to delete property."));
715 LLINT_RETURN(jsBoolean(couldDelete
));
718 inline JSValue
getByVal(ExecState
* exec
, JSValue baseValue
, JSValue subscript
)
720 if (LIKELY(baseValue
.isCell() && subscript
.isString())) {
722 Structure
& structure
= *baseValue
.asCell()->structure(vm
);
723 if (JSCell::canUseFastGetOwnProperty(structure
)) {
724 if (JSValue result
= baseValue
.asCell()->fastGetOwnProperty(vm
, structure
, asString(subscript
)->value(exec
)))
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 if (isName(subscript
))
738 return baseValue
.get(exec
, jsCast
<NameInstance
*>(subscript
.asCell())->privateName());
740 Identifier property
= subscript
.toString(exec
)->toIdentifier(exec
);
741 return baseValue
.get(exec
, property
);
744 LLINT_SLOW_PATH_DECL(slow_path_get_by_val
)
747 LLINT_RETURN_PROFILED(op_get_by_val
, getByVal(exec
, LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue()));
750 LLINT_SLOW_PATH_DECL(slow_path_get_argument_by_val
)
753 JSValue arguments
= LLINT_OP(2).jsValue();
755 arguments
= Arguments::create(vm
, exec
);
756 LLINT_CHECK_EXCEPTION();
757 LLINT_OP(2) = arguments
;
758 exec
->uncheckedR(unmodifiedArgumentsRegister(VirtualRegister(pc
[2].u
.operand
)).offset()) = arguments
;
761 LLINT_RETURN_PROFILED(op_get_argument_by_val
, getByVal(exec
, arguments
, LLINT_OP_C(3).jsValue()));
764 LLINT_SLOW_PATH_DECL(slow_path_get_by_pname
)
767 LLINT_RETURN(getByVal(exec
, LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue()));
770 LLINT_SLOW_PATH_DECL(slow_path_put_by_val
)
774 JSValue baseValue
= LLINT_OP_C(1).jsValue();
775 JSValue subscript
= LLINT_OP_C(2).jsValue();
776 JSValue value
= LLINT_OP_C(3).jsValue();
778 if (LIKELY(subscript
.isUInt32())) {
779 uint32_t i
= subscript
.asUInt32();
780 if (baseValue
.isObject()) {
781 JSObject
* object
= asObject(baseValue
);
782 if (object
->canSetIndexQuickly(i
))
783 object
->setIndexQuickly(vm
, i
, value
);
785 object
->methodTable()->putByIndex(object
, exec
, i
, value
, exec
->codeBlock()->isStrictMode());
788 baseValue
.putByIndex(exec
, i
, value
, exec
->codeBlock()->isStrictMode());
792 if (isName(subscript
)) {
793 PutPropertySlot
slot(baseValue
, exec
->codeBlock()->isStrictMode());
794 baseValue
.put(exec
, jsCast
<NameInstance
*>(subscript
.asCell())->privateName(), value
, slot
);
798 Identifier
property(exec
, subscript
.toString(exec
)->value(exec
));
799 LLINT_CHECK_EXCEPTION();
800 PutPropertySlot
slot(baseValue
, exec
->codeBlock()->isStrictMode());
801 baseValue
.put(exec
, property
, value
, slot
);
805 LLINT_SLOW_PATH_DECL(slow_path_put_by_val_direct
)
809 JSValue baseValue
= LLINT_OP_C(1).jsValue();
810 JSValue subscript
= LLINT_OP_C(2).jsValue();
811 JSValue value
= LLINT_OP_C(3).jsValue();
812 RELEASE_ASSERT(baseValue
.isObject());
813 JSObject
* baseObject
= asObject(baseValue
);
814 if (LIKELY(subscript
.isUInt32())) {
815 uint32_t i
= subscript
.asUInt32();
816 baseObject
->putDirectIndex(exec
, i
, value
);
817 } else if (isName(subscript
)) {
818 PutPropertySlot
slot(baseObject
, exec
->codeBlock()->isStrictMode());
819 baseObject
->putDirect(exec
->vm(), jsCast
<NameInstance
*>(subscript
.asCell())->privateName(), value
, slot
);
821 Identifier
property(exec
, subscript
.toString(exec
)->value(exec
));
822 if (!exec
->vm().exception()) { // Don't put to an object if toString threw an exception.
823 PutPropertySlot
slot(baseObject
, exec
->codeBlock()->isStrictMode());
824 baseObject
->putDirect(exec
->vm(), property
, value
, slot
);
830 LLINT_SLOW_PATH_DECL(slow_path_del_by_val
)
833 JSValue baseValue
= LLINT_OP_C(2).jsValue();
834 JSObject
* baseObject
= baseValue
.toObject(exec
);
836 JSValue subscript
= LLINT_OP_C(3).jsValue();
841 if (subscript
.getUInt32(i
))
842 couldDelete
= baseObject
->methodTable()->deletePropertyByIndex(baseObject
, exec
, i
);
843 else if (isName(subscript
))
844 couldDelete
= baseObject
->methodTable()->deleteProperty(baseObject
, exec
, jsCast
<NameInstance
*>(subscript
.asCell())->privateName());
846 LLINT_CHECK_EXCEPTION();
847 Identifier
property(exec
, subscript
.toString(exec
)->value(exec
));
848 LLINT_CHECK_EXCEPTION();
849 couldDelete
= baseObject
->methodTable()->deleteProperty(baseObject
, exec
, property
);
852 if (!couldDelete
&& exec
->codeBlock()->isStrictMode())
853 LLINT_THROW(createTypeError(exec
, "Unable to delete property."));
855 LLINT_RETURN(jsBoolean(couldDelete
));
858 LLINT_SLOW_PATH_DECL(slow_path_put_by_index
)
861 JSValue arrayValue
= LLINT_OP_C(1).jsValue();
862 ASSERT(isJSArray(arrayValue
));
863 asArray(arrayValue
)->putDirectIndex(exec
, pc
[2].u
.operand
, LLINT_OP_C(3).jsValue());
867 LLINT_SLOW_PATH_DECL(slow_path_put_getter_setter
)
870 ASSERT(LLINT_OP(1).jsValue().isObject());
871 JSObject
* baseObj
= asObject(LLINT_OP(1).jsValue());
873 GetterSetter
* accessor
= GetterSetter::create(vm
);
874 LLINT_CHECK_EXCEPTION();
876 JSValue getter
= LLINT_OP(3).jsValue();
877 JSValue setter
= LLINT_OP(4).jsValue();
878 ASSERT(getter
.isObject() || getter
.isUndefined());
879 ASSERT(setter
.isObject() || setter
.isUndefined());
880 ASSERT(getter
.isObject() || setter
.isObject());
882 if (!getter
.isUndefined())
883 accessor
->setGetter(vm
, asObject(getter
));
884 if (!setter
.isUndefined())
885 accessor
->setSetter(vm
, asObject(setter
));
886 baseObj
->putDirectAccessor(
888 exec
->codeBlock()->identifier(pc
[2].u
.operand
),
893 LLINT_SLOW_PATH_DECL(slow_path_jtrue
)
896 LLINT_BRANCH(op_jtrue
, LLINT_OP_C(1).jsValue().toBoolean(exec
));
899 LLINT_SLOW_PATH_DECL(slow_path_jfalse
)
902 LLINT_BRANCH(op_jfalse
, !LLINT_OP_C(1).jsValue().toBoolean(exec
));
905 LLINT_SLOW_PATH_DECL(slow_path_jless
)
908 LLINT_BRANCH(op_jless
, jsLess
<true>(exec
, LLINT_OP_C(1).jsValue(), LLINT_OP_C(2).jsValue()));
911 LLINT_SLOW_PATH_DECL(slow_path_jnless
)
914 LLINT_BRANCH(op_jnless
, !jsLess
<true>(exec
, LLINT_OP_C(1).jsValue(), LLINT_OP_C(2).jsValue()));
917 LLINT_SLOW_PATH_DECL(slow_path_jgreater
)
920 LLINT_BRANCH(op_jgreater
, jsLess
<false>(exec
, LLINT_OP_C(2).jsValue(), LLINT_OP_C(1).jsValue()));
923 LLINT_SLOW_PATH_DECL(slow_path_jngreater
)
926 LLINT_BRANCH(op_jngreater
, !jsLess
<false>(exec
, LLINT_OP_C(2).jsValue(), LLINT_OP_C(1).jsValue()));
929 LLINT_SLOW_PATH_DECL(slow_path_jlesseq
)
932 LLINT_BRANCH(op_jlesseq
, jsLessEq
<true>(exec
, LLINT_OP_C(1).jsValue(), LLINT_OP_C(2).jsValue()));
935 LLINT_SLOW_PATH_DECL(slow_path_jnlesseq
)
938 LLINT_BRANCH(op_jnlesseq
, !jsLessEq
<true>(exec
, LLINT_OP_C(1).jsValue(), LLINT_OP_C(2).jsValue()));
941 LLINT_SLOW_PATH_DECL(slow_path_jgreatereq
)
944 LLINT_BRANCH(op_jgreatereq
, jsLessEq
<false>(exec
, LLINT_OP_C(2).jsValue(), LLINT_OP_C(1).jsValue()));
947 LLINT_SLOW_PATH_DECL(slow_path_jngreatereq
)
950 LLINT_BRANCH(op_jngreatereq
, !jsLessEq
<false>(exec
, LLINT_OP_C(2).jsValue(), LLINT_OP_C(1).jsValue()));
953 LLINT_SLOW_PATH_DECL(slow_path_switch_imm
)
956 JSValue scrutinee
= LLINT_OP_C(3).jsValue();
957 ASSERT(scrutinee
.isDouble());
958 double value
= scrutinee
.asDouble();
959 int32_t intValue
= static_cast<int32_t>(value
);
960 int defaultOffset
= pc
[2].u
.operand
;
961 if (value
== intValue
) {
962 CodeBlock
* codeBlock
= exec
->codeBlock();
963 pc
+= codeBlock
->switchJumpTable(pc
[1].u
.operand
).offsetForValue(intValue
, defaultOffset
);
969 LLINT_SLOW_PATH_DECL(slow_path_switch_char
)
972 JSValue scrutinee
= LLINT_OP_C(3).jsValue();
973 ASSERT(scrutinee
.isString());
974 JSString
* string
= asString(scrutinee
);
975 ASSERT(string
->length() == 1);
976 int defaultOffset
= pc
[2].u
.operand
;
977 StringImpl
* impl
= string
->value(exec
).impl();
978 CodeBlock
* codeBlock
= exec
->codeBlock();
979 pc
+= codeBlock
->switchJumpTable(pc
[1].u
.operand
).offsetForValue((*impl
)[0], defaultOffset
);
983 LLINT_SLOW_PATH_DECL(slow_path_switch_string
)
986 JSValue scrutinee
= LLINT_OP_C(3).jsValue();
987 int defaultOffset
= pc
[2].u
.operand
;
988 if (!scrutinee
.isString())
991 CodeBlock
* codeBlock
= exec
->codeBlock();
992 pc
+= codeBlock
->stringSwitchJumpTable(pc
[1].u
.operand
).offsetForValue(asString(scrutinee
)->value(exec
).impl(), defaultOffset
);
997 LLINT_SLOW_PATH_DECL(slow_path_new_func
)
1000 CodeBlock
* codeBlock
= exec
->codeBlock();
1001 ASSERT(codeBlock
->codeType() != FunctionCode
|| !codeBlock
->needsActivation() || exec
->hasActivation());
1002 #if LLINT_SLOW_PATH_TRACING
1003 dataLogF("Creating function!\n");
1005 LLINT_RETURN(JSFunction::create(vm
, codeBlock
->functionDecl(pc
[2].u
.operand
), exec
->scope()));
1008 LLINT_SLOW_PATH_DECL(slow_path_new_func_exp
)
1011 CodeBlock
* codeBlock
= exec
->codeBlock();
1012 FunctionExecutable
* function
= codeBlock
->functionExpr(pc
[2].u
.operand
);
1013 JSFunction
* func
= JSFunction::create(vm
, function
, exec
->scope());
1018 static SlowPathReturnType
handleHostCall(ExecState
* execCallee
, Instruction
* pc
, JSValue callee
, CodeSpecializationKind kind
)
1022 #if LLINT_SLOW_PATH_TRACING
1023 dataLog("Performing host call.\n");
1026 ExecState
* exec
= execCallee
->callerFrame();
1027 VM
& vm
= exec
->vm();
1029 execCallee
->setScope(exec
->scope());
1030 execCallee
->setCodeBlock(0);
1031 execCallee
->clearReturnPC();
1033 if (kind
== CodeForCall
) {
1035 CallType callType
= getCallData(callee
, callData
);
1037 ASSERT(callType
!= CallTypeJS
);
1039 if (callType
== CallTypeHost
) {
1040 NativeCallFrameTracer
tracer(&vm
, execCallee
);
1041 execCallee
->setCallee(asObject(callee
));
1042 vm
.hostCallReturnValue
= JSValue::decode(callData
.native
.function(execCallee
));
1044 LLINT_CALL_RETURN(execCallee
, LLInt::getCodePtr(getHostCallReturnValue
));
1047 #if LLINT_SLOW_PATH_TRACING
1048 dataLog("Call callee is not a function: ", callee
, "\n");
1051 ASSERT(callType
== CallTypeNone
);
1052 LLINT_CALL_THROW(exec
, createNotAFunctionError(exec
, callee
));
1055 ASSERT(kind
== CodeForConstruct
);
1057 ConstructData constructData
;
1058 ConstructType constructType
= getConstructData(callee
, constructData
);
1060 ASSERT(constructType
!= ConstructTypeJS
);
1062 if (constructType
== ConstructTypeHost
) {
1063 NativeCallFrameTracer
tracer(&vm
, execCallee
);
1064 execCallee
->setCallee(asObject(callee
));
1065 vm
.hostCallReturnValue
= JSValue::decode(constructData
.native
.function(execCallee
));
1067 LLINT_CALL_RETURN(execCallee
, LLInt::getCodePtr(getHostCallReturnValue
));
1070 #if LLINT_SLOW_PATH_TRACING
1071 dataLog("Constructor callee is not a function: ", callee
, "\n");
1074 ASSERT(constructType
== ConstructTypeNone
);
1075 LLINT_CALL_THROW(exec
, createNotAConstructorError(exec
, callee
));
1078 inline SlowPathReturnType
setUpCall(ExecState
* execCallee
, Instruction
* pc
, CodeSpecializationKind kind
, JSValue calleeAsValue
, LLIntCallLinkInfo
* callLinkInfo
= 0)
1080 #if LLINT_SLOW_PATH_TRACING
1081 dataLogF("Performing call with recorded PC = %p\n", execCallee
->callerFrame()->currentVPC());
1084 JSCell
* calleeAsFunctionCell
= getJSFunction(calleeAsValue
);
1085 if (!calleeAsFunctionCell
)
1086 return handleHostCall(execCallee
, pc
, calleeAsValue
, kind
);
1088 JSFunction
* callee
= jsCast
<JSFunction
*>(calleeAsFunctionCell
);
1089 JSScope
* scope
= callee
->scopeUnchecked();
1090 VM
& vm
= *scope
->vm();
1091 execCallee
->setScope(scope
);
1092 ExecutableBase
* executable
= callee
->executable();
1094 MacroAssemblerCodePtr codePtr
;
1095 CodeBlock
* codeBlock
= 0;
1096 if (executable
->isHostFunction())
1097 codePtr
= executable
->entrypointFor(vm
, kind
, MustCheckArity
, RegisterPreservationNotRequired
);
1099 FunctionExecutable
* functionExecutable
= static_cast<FunctionExecutable
*>(executable
);
1100 JSObject
* error
= functionExecutable
->prepareForExecution(execCallee
, callee
, &scope
, kind
);
1101 execCallee
->setScope(scope
);
1103 LLINT_CALL_THROW(execCallee
->callerFrame(), error
);
1104 codeBlock
= functionExecutable
->codeBlockFor(kind
);
1106 ArityCheckMode arity
;
1107 if (execCallee
->argumentCountIncludingThis() < static_cast<size_t>(codeBlock
->numParameters()))
1108 arity
= MustCheckArity
;
1110 arity
= ArityCheckNotRequired
;
1111 codePtr
= functionExecutable
->entrypointFor(vm
, kind
, arity
, RegisterPreservationNotRequired
);
1116 if (!LLINT_ALWAYS_ACCESS_SLOW
&& callLinkInfo
) {
1117 ExecState
* execCaller
= execCallee
->callerFrame();
1119 CodeBlock
* callerCodeBlock
= execCaller
->codeBlock();
1121 ConcurrentJITLocker
locker(callerCodeBlock
->m_lock
);
1123 if (callLinkInfo
->isOnList())
1124 callLinkInfo
->remove();
1125 callLinkInfo
->callee
.set(vm
, callerCodeBlock
->ownerExecutable(), callee
);
1126 callLinkInfo
->lastSeenCallee
.set(vm
, callerCodeBlock
->ownerExecutable(), callee
);
1127 callLinkInfo
->machineCodeTarget
= codePtr
;
1129 codeBlock
->linkIncomingCall(execCaller
, callLinkInfo
);
1132 LLINT_CALL_RETURN(execCallee
, codePtr
.executableAddress());
1135 inline SlowPathReturnType
genericCall(ExecState
* exec
, Instruction
* pc
, CodeSpecializationKind kind
)
1138 // - Set up a call frame.
1139 // - Figure out what to call and compile it if necessary.
1140 // - If possible, link the call's inline cache.
1141 // - Return a tuple of machine code address to call and the new call frame.
1143 JSValue calleeAsValue
= LLINT_OP_C(2).jsValue();
1145 ExecState
* execCallee
= exec
- pc
[4].u
.operand
;
1147 execCallee
->setArgumentCountIncludingThis(pc
[3].u
.operand
);
1148 execCallee
->uncheckedR(JSStack::Callee
) = calleeAsValue
;
1149 execCallee
->setCallerFrame(exec
);
1151 ASSERT(pc
[5].u
.callLinkInfo
);
1152 return setUpCall(execCallee
, pc
, kind
, calleeAsValue
, pc
[5].u
.callLinkInfo
);
1155 LLINT_SLOW_PATH_DECL(slow_path_call
)
1157 LLINT_BEGIN_NO_SET_PC();
1158 return genericCall(exec
, pc
, CodeForCall
);
1161 LLINT_SLOW_PATH_DECL(slow_path_construct
)
1163 LLINT_BEGIN_NO_SET_PC();
1164 return genericCall(exec
, pc
, CodeForConstruct
);
1167 LLINT_SLOW_PATH_DECL(slow_path_size_frame_for_varargs
)
1171 // - Set up a call frame while respecting the variable arguments.
1173 ExecState
* execCallee
= sizeFrameForVarargs(exec
, &vm
.interpreter
->stack(),
1174 LLINT_OP_C(4).jsValue(), pc
[5].u
.operand
, pc
[6].u
.operand
);
1175 LLINT_CALL_CHECK_EXCEPTION(exec
);
1177 vm
.newCallFrameReturnValue
= execCallee
;
1179 LLINT_RETURN_CALLEE_FRAME(execCallee
);
1182 LLINT_SLOW_PATH_DECL(slow_path_call_varargs
)
1184 LLINT_BEGIN_NO_SET_PC();
1186 // - Figure out what to call and compile it if necessary.
1187 // - Return a tuple of machine code address to call and the new call frame.
1189 JSValue calleeAsValue
= LLINT_OP_C(2).jsValue();
1191 ExecState
* execCallee
= vm
.newCallFrameReturnValue
;
1193 loadVarargs(exec
, execCallee
, LLINT_OP_C(3).jsValue(), LLINT_OP_C(4).jsValue(), pc
[6].u
.operand
);
1194 LLINT_CALL_CHECK_EXCEPTION(exec
);
1196 execCallee
->uncheckedR(JSStack::Callee
) = calleeAsValue
;
1197 execCallee
->setCallerFrame(exec
);
1198 exec
->setCurrentVPC(pc
);
1200 return setUpCall(execCallee
, pc
, CodeForCall
, calleeAsValue
);
1203 LLINT_SLOW_PATH_DECL(slow_path_construct_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 loadVarargs(exec
, execCallee
, LLINT_OP_C(3).jsValue(), LLINT_OP_C(4).jsValue(), pc
[6].u
.operand
);
1215 LLINT_CALL_CHECK_EXCEPTION(exec
);
1217 execCallee
->uncheckedR(JSStack::Callee
) = calleeAsValue
;
1218 execCallee
->setCallerFrame(exec
);
1219 exec
->setCurrentVPC(pc
);
1221 return setUpCall(execCallee
, pc
, CodeForConstruct
, calleeAsValue
);
1224 LLINT_SLOW_PATH_DECL(slow_path_call_eval
)
1226 LLINT_BEGIN_NO_SET_PC();
1227 JSValue calleeAsValue
= LLINT_OP(2).jsValue();
1229 ExecState
* execCallee
= exec
- pc
[4].u
.operand
;
1231 execCallee
->setArgumentCountIncludingThis(pc
[3].u
.operand
);
1232 execCallee
->setCallerFrame(exec
);
1233 execCallee
->uncheckedR(JSStack::Callee
) = calleeAsValue
;
1234 execCallee
->setScope(exec
->scope());
1235 execCallee
->setReturnPC(LLInt::getCodePtr(llint_generic_return_point
));
1236 execCallee
->setCodeBlock(0);
1237 exec
->setCurrentVPC(pc
);
1239 if (!isHostFunction(calleeAsValue
, globalFuncEval
))
1240 return setUpCall(execCallee
, pc
, CodeForCall
, calleeAsValue
);
1242 vm
.hostCallReturnValue
= eval(execCallee
);
1243 LLINT_CALL_RETURN(execCallee
, LLInt::getCodePtr(getHostCallReturnValue
));
1246 LLINT_SLOW_PATH_DECL(slow_path_tear_off_activation
)
1249 ASSERT(exec
->codeBlock()->needsActivation());
1250 jsCast
<JSActivation
*>(LLINT_OP(1).jsValue())->tearOff(vm
);
1254 LLINT_SLOW_PATH_DECL(slow_path_tear_off_arguments
)
1257 ASSERT(exec
->codeBlock()->usesArguments());
1258 Arguments
* arguments
= jsCast
<Arguments
*>(exec
->uncheckedR(unmodifiedArgumentsRegister(VirtualRegister(pc
[1].u
.operand
)).offset()).jsValue());
1259 if (JSValue activationValue
= LLINT_OP_C(2).jsValue())
1260 arguments
->didTearOffActivation(exec
, jsCast
<JSActivation
*>(activationValue
));
1262 arguments
->tearOff(exec
);
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_get_pnames
)
1281 JSValue v
= LLINT_OP(2).jsValue();
1282 if (v
.isUndefinedOrNull()) {
1283 pc
+= pc
[5].u
.operand
;
1287 JSObject
* o
= v
.toObject(exec
);
1288 Structure
* structure
= o
->structure();
1289 JSPropertyNameIterator
* jsPropertyNameIterator
= structure
->enumerationCache();
1290 if (!jsPropertyNameIterator
|| jsPropertyNameIterator
->cachedPrototypeChain() != structure
->prototypeChain(exec
))
1291 jsPropertyNameIterator
= JSPropertyNameIterator::create(exec
, o
);
1293 LLINT_OP(1) = JSValue(jsPropertyNameIterator
);
1294 LLINT_OP(2) = JSValue(o
);
1295 LLINT_OP(3) = Register::withInt(0);
1296 LLINT_OP(4) = Register::withInt(jsPropertyNameIterator
->size());
1298 pc
+= OPCODE_LENGTH(op_get_pnames
);
1302 LLINT_SLOW_PATH_DECL(slow_path_next_pname
)
1305 JSObject
* base
= asObject(LLINT_OP(2).jsValue());
1306 JSString
* property
= asString(LLINT_OP(1).jsValue());
1307 if (base
->hasProperty(exec
, Identifier(exec
, property
->value(exec
)))) {
1309 pc
+= pc
[6].u
.operand
;
1310 } // Else, don't change the PC, so the interpreter will reloop.
1314 LLINT_SLOW_PATH_DECL(slow_path_push_with_scope
)
1317 JSValue v
= LLINT_OP_C(1).jsValue();
1318 JSObject
* o
= v
.toObject(exec
);
1319 LLINT_CHECK_EXCEPTION();
1321 exec
->setScope(JSWithScope::create(exec
, o
));
1326 LLINT_SLOW_PATH_DECL(slow_path_pop_scope
)
1329 exec
->setScope(exec
->scope()->next());
1333 LLINT_SLOW_PATH_DECL(slow_path_push_name_scope
)
1336 CodeBlock
* codeBlock
= exec
->codeBlock();
1337 JSNameScope
* scope
= JSNameScope::create(exec
, codeBlock
->identifier(pc
[1].u
.operand
), LLINT_OP(2).jsValue(), pc
[3].u
.operand
);
1338 exec
->setScope(scope
);
1342 LLINT_SLOW_PATH_DECL(slow_path_throw
)
1345 LLINT_THROW(LLINT_OP_C(1).jsValue());
1348 LLINT_SLOW_PATH_DECL(slow_path_throw_static_error
)
1351 if (pc
[2].u
.operand
)
1352 LLINT_THROW(createReferenceError(exec
, errorDescriptionForValue(exec
, LLINT_OP_C(1).jsValue())->value(exec
)));
1354 LLINT_THROW(createTypeError(exec
, errorDescriptionForValue(exec
, LLINT_OP_C(1).jsValue())->value(exec
)));
1357 LLINT_SLOW_PATH_DECL(slow_path_handle_watchdog_timer
)
1359 LLINT_BEGIN_NO_SET_PC();
1360 ASSERT(vm
.watchdog
);
1361 if (UNLIKELY(vm
.watchdog
->didFire(exec
)))
1362 LLINT_THROW(createTerminatedExecutionException(&vm
));
1363 LLINT_RETURN_TWO(0, exec
);
1366 LLINT_SLOW_PATH_DECL(slow_path_debug
)
1369 int debugHookID
= pc
[1].u
.operand
;
1370 vm
.interpreter
->debug(exec
, static_cast<DebugHookID
>(debugHookID
));
1375 LLINT_SLOW_PATH_DECL(slow_path_profile_will_call
)
1378 if (LegacyProfiler
* profiler
= vm
.enabledProfiler())
1379 profiler
->willExecute(exec
, LLINT_OP(1).jsValue());
1383 LLINT_SLOW_PATH_DECL(slow_path_profile_did_call
)
1386 if (LegacyProfiler
* profiler
= vm
.enabledProfiler())
1387 profiler
->didExecute(exec
, LLINT_OP(1).jsValue());
1391 LLINT_SLOW_PATH_DECL(slow_path_handle_exception
)
1393 LLINT_BEGIN_NO_SET_PC();
1394 ASSERT(vm
.exception());
1395 genericUnwind(&vm
, exec
, vm
.exception());
1399 LLINT_SLOW_PATH_DECL(slow_path_resolve_scope
)
1402 const Identifier
& ident
= exec
->codeBlock()->identifier(pc
[2].u
.operand
);
1403 LLINT_RETURN(JSScope::resolve(exec
, exec
->scope(), ident
));
1406 LLINT_SLOW_PATH_DECL(slow_path_get_from_scope
)
1409 const Identifier
& ident
= exec
->codeBlock()->identifier(pc
[3].u
.operand
);
1410 JSObject
* scope
= jsCast
<JSObject
*>(LLINT_OP(2).jsValue());
1411 ResolveModeAndType
modeAndType(pc
[4].u
.operand
);
1413 PropertySlot
slot(scope
);
1414 if (!scope
->getPropertySlot(exec
, ident
, slot
)) {
1415 if (modeAndType
.mode() == ThrowIfNotFound
)
1416 LLINT_RETURN(exec
->vm().throwException(exec
, createUndefinedVariableError(exec
, ident
)));
1417 LLINT_RETURN(jsUndefined());
1420 // Covers implicit globals. Since they don't exist until they first execute, we didn't know how to cache them at compile time.
1421 if (slot
.isCacheableValue() && slot
.slotBase() == scope
&& scope
->structure()->propertyAccessesAreCacheable()) {
1422 if (modeAndType
.type() == GlobalProperty
|| modeAndType
.type() == GlobalPropertyWithVarInjectionChecks
) {
1423 CodeBlock
* codeBlock
= exec
->codeBlock();
1424 ConcurrentJITLocker
locker(codeBlock
->m_lock
);
1425 pc
[5].u
.structure
.set(exec
->vm(), codeBlock
->ownerExecutable(), scope
->structure());
1426 pc
[6].u
.operand
= slot
.cachedOffset();
1430 LLINT_RETURN(slot
.getValue(exec
, ident
));
1433 LLINT_SLOW_PATH_DECL(slow_path_put_to_scope
)
1436 CodeBlock
* codeBlock
= exec
->codeBlock();
1437 const Identifier
& ident
= codeBlock
->identifier(pc
[2].u
.operand
);
1438 JSObject
* scope
= jsCast
<JSObject
*>(LLINT_OP(1).jsValue());
1439 JSValue value
= LLINT_OP_C(3).jsValue();
1440 ResolveModeAndType modeAndType
= ResolveModeAndType(pc
[4].u
.operand
);
1442 if (modeAndType
.mode() == ThrowIfNotFound
&& !scope
->hasProperty(exec
, ident
))
1443 LLINT_THROW(createUndefinedVariableError(exec
, ident
));
1445 PutPropertySlot
slot(scope
, codeBlock
->isStrictMode());
1446 scope
->methodTable()->put(scope
, exec
, ident
, value
, slot
);
1448 // Covers implicit globals. Since they don't exist until they first execute, we didn't know how to cache them at compile time.
1449 if (modeAndType
.type() == GlobalProperty
|| modeAndType
.type() == GlobalPropertyWithVarInjectionChecks
) {
1450 if (slot
.isCacheablePut() && slot
.base() == scope
&& scope
->structure()->propertyAccessesAreCacheable()) {
1451 ConcurrentJITLocker
locker(codeBlock
->m_lock
);
1452 pc
[5].u
.structure
.set(exec
->vm(), codeBlock
->ownerExecutable(), scope
->structure());
1453 pc
[6].u
.operand
= slot
.cachedOffset();
1460 extern "C" SlowPathReturnType
llint_throw_stack_overflow_error(VM
* vm
, ProtoCallFrame
* protoFrame
)
1462 ExecState
* exec
= vm
->topCallFrame
;
1464 exec
= protoFrame
->scope()->globalObject()->globalExec();
1465 throwStackOverflowError(exec
);
1466 return encodeResult(0, 0);
1470 extern "C" SlowPathReturnType
llint_stack_check_at_vm_entry(VM
* vm
, Register
* newTopOfStack
)
1472 bool success
= vm
->interpreter
->stack().ensureCapacityFor(newTopOfStack
);
1473 return encodeResult(reinterpret_cast<void*>(success
), 0);
1477 extern "C" void llint_write_barrier_slow(ExecState
* exec
, JSCell
* cell
)
1479 VM
& vm
= exec
->vm();
1480 vm
.heap
.writeBarrier(cell
);
1483 extern "C" NO_RETURN_DUE_TO_CRASH
void llint_crash()
1488 } } // namespace JSC::LLInt