]> git.saurik.com Git - apple/javascriptcore.git/blame_incremental - llint/LLIntSlowPaths.cpp
JavaScriptCore-7600.1.4.17.5.tar.gz
[apple/javascriptcore.git] / llint / LLIntSlowPaths.cpp
... / ...
CommitLineData
1/*
2 * Copyright (C) 2011, 2012, 2013, 2014 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
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.
12 *
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.
24 */
25
26#include "config.h"
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"
37#include "JIT.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"
45#include "JSString.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>
55
56namespace JSC { namespace LLInt {
57
58#define LLINT_BEGIN_NO_SET_PC() \
59 VM& vm = exec->vm(); \
60 NativeCallFrameTracer tracer(&vm, exec)
61
62#ifndef NDEBUG
63#define LLINT_SET_PC_FOR_STUBS() do { \
64 exec->codeBlock()->bytecodeOffset(pc); \
65 exec->setCurrentVPC(pc + 1); \
66 } while (false)
67#else
68#define LLINT_SET_PC_FOR_STUBS() do { \
69 exec->setCurrentVPC(pc + 1); \
70 } while (false)
71#endif
72
73#define LLINT_BEGIN() \
74 LLINT_BEGIN_NO_SET_PC(); \
75 LLINT_SET_PC_FOR_STUBS()
76
77#define LLINT_OP(index) (exec->uncheckedR(pc[index].u.operand))
78#define LLINT_OP_C(index) (exec->r(pc[index].u.operand))
79
80#define LLINT_RETURN_TWO(first, second) do { \
81 return encodeResult(first, second); \
82 } while (false)
83
84#define LLINT_END_IMPL() LLINT_RETURN_TWO(pc, 0)
85
86#define LLINT_THROW(exceptionToThrow) do { \
87 vm.throwException(exec, exceptionToThrow); \
88 pc = returnToThrow(exec); \
89 LLINT_END_IMPL(); \
90 } while (false)
91
92#define LLINT_CHECK_EXCEPTION() do { \
93 if (UNLIKELY(vm.exception())) { \
94 pc = returnToThrow(exec); \
95 LLINT_END_IMPL(); \
96 } \
97 } while (false)
98
99#define LLINT_END() do { \
100 LLINT_CHECK_EXCEPTION(); \
101 LLINT_END_IMPL(); \
102 } while (false)
103
104#define LLINT_BRANCH(opcode, condition) do { \
105 bool __b_condition = (condition); \
106 LLINT_CHECK_EXCEPTION(); \
107 if (__b_condition) \
108 pc += pc[OPCODE_LENGTH(opcode) - 1].u.operand; \
109 else \
110 pc += OPCODE_LENGTH(opcode); \
111 LLINT_END_IMPL(); \
112 } while (false)
113
114#define LLINT_RETURN(value) do { \
115 JSValue __r_returnValue = (value); \
116 LLINT_CHECK_EXCEPTION(); \
117 LLINT_OP(1) = __r_returnValue; \
118 LLINT_END_IMPL(); \
119 } while (false)
120
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); \
126 LLINT_END_IMPL(); \
127 } while (false)
128
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); \
134 LLINT_END_IMPL(); \
135 } while (false)
136
137#define LLINT_PROFILE_VALUE(opcode, value) do { \
138 pc[OPCODE_LENGTH(opcode) - 1].u.profile->m_buckets[0] = \
139 JSValue::encode(value); \
140 } while (false)
141
142#define LLINT_CALL_END_IMPL(exec, callTarget) LLINT_RETURN_TWO((callTarget), (exec))
143
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)); \
148 } while (false)
149
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)); \
154 } while (false)
155
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); \
161 } while (false)
162
163#define LLINT_RETURN_CALLEE_FRAME(execCallee) do { \
164 ExecState* __rcf_exec = (execCallee); \
165 LLINT_RETURN_TWO(pc, __rcf_exec); \
166 } while (false)
167
168
169extern "C" SlowPathReturnType llint_trace_operand(ExecState* exec, Instruction* pc, int fromWhere, int operand)
170{
171 LLINT_BEGIN();
172 dataLogF("%p / %p: executing bc#%zu, op#%u: Trace(%d): %d: %d\n",
173 exec->codeBlock(),
174 exec,
175 static_cast<intptr_t>(pc - exec->codeBlock()->instructions().begin()),
176 exec->vm().interpreter->getOpcodeID(pc[0].u.opcode),
177 fromWhere,
178 operand,
179 pc[operand].u.operand);
180 LLINT_END();
181}
182
183extern "C" SlowPathReturnType llint_trace_value(ExecState* exec, Instruction* pc, int fromWhere, int operand)
184{
185 JSValue value = LLINT_OP_C(operand).jsValue();
186 union {
187 struct {
188 uint32_t tag;
189 uint32_t payload;
190 } bits;
191 EncodedJSValue asValue;
192 } u;
193 u.asValue = JSValue::encode(value);
194 dataLogF(
195 "%p / %p: executing bc#%zu, op#%u: Trace(%d): %d: %d: %08x:%08x: %s\n",
196 exec->codeBlock(),
197 exec,
198 static_cast<intptr_t>(pc - exec->codeBlock()->instructions().begin()),
199 exec->vm().interpreter->getOpcodeID(pc[0].u.opcode),
200 fromWhere,
201 operand,
202 pc[operand].u.operand,
203 u.bits.tag,
204 u.bits.payload,
205 toCString(value).data());
206 LLINT_END_IMPL();
207}
208
209LLINT_SLOW_PATH_DECL(trace_prologue)
210{
211 dataLogF("%p / %p: in prologue.\n", exec->codeBlock(), exec);
212 LLINT_END_IMPL();
213}
214
215static void traceFunctionPrologue(ExecState* exec, const char* comment, CodeSpecializationKind kind)
216{
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());
224}
225
226LLINT_SLOW_PATH_DECL(trace_prologue_function_for_call)
227{
228 traceFunctionPrologue(exec, "call prologue", CodeForCall);
229 LLINT_END_IMPL();
230}
231
232LLINT_SLOW_PATH_DECL(trace_prologue_function_for_construct)
233{
234 traceFunctionPrologue(exec, "construct prologue", CodeForConstruct);
235 LLINT_END_IMPL();
236}
237
238LLINT_SLOW_PATH_DECL(trace_arityCheck_for_call)
239{
240 traceFunctionPrologue(exec, "call arity check", CodeForCall);
241 LLINT_END_IMPL();
242}
243
244LLINT_SLOW_PATH_DECL(trace_arityCheck_for_construct)
245{
246 traceFunctionPrologue(exec, "construct arity check", CodeForConstruct);
247 LLINT_END_IMPL();
248}
249
250LLINT_SLOW_PATH_DECL(trace)
251{
252 dataLogF("%p / %p: executing bc#%zu, %s, scope %p, pc = %p\n",
253 exec->codeBlock(),
254 exec,
255 static_cast<intptr_t>(pc - exec->codeBlock()->instructions().begin()),
256 opcodeNames[exec->vm().interpreter->getOpcodeID(pc[0].u.opcode)],
257 exec->scope(), pc);
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());
261 }
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());
265 }
266 LLINT_END_IMPL();
267}
268
269LLINT_SLOW_PATH_DECL(special_trace)
270{
271 dataLogF("%p / %p: executing special case bc#%zu, op#%u, return PC is %p\n",
272 exec->codeBlock(),
273 exec,
274 static_cast<intptr_t>(pc - exec->codeBlock()->instructions().begin()),
275 exec->vm().interpreter->getOpcodeID(pc[0].u.opcode),
276 exec->returnPC().value());
277 LLINT_END_IMPL();
278}
279
280enum EntryKind { Prologue, ArityCheck };
281
282#if ENABLE(JIT)
283inline bool shouldJIT(ExecState* exec)
284{
285 // You can modify this to turn off JITting without rebuilding the world.
286 return exec->vm().canUseJIT();
287}
288
289// Returns true if we should try to OSR.
290inline bool jitCompileAndSetHeuristics(CodeBlock* codeBlock, ExecState* exec)
291{
292 VM& vm = exec->vm();
293 DeferGCForAWhile deferGC(vm.heap); // My callers don't set top callframe, so we don't want to GC here at all.
294
295 codeBlock->updateAllValueProfilePredictions();
296
297 if (!codeBlock->checkIfJITThresholdReached()) {
298 if (Options::verboseOSR())
299 dataLogF(" JIT threshold should be lifted.\n");
300 return false;
301 }
302
303 switch (codeBlock->jitType()) {
304 case JITCode::BaselineJIT: {
305 if (Options::verboseOSR())
306 dataLogF(" Code was already compiled.\n");
307 codeBlock->jitSoon();
308 return true;
309 }
310 case JITCode::InterpreterThunk: {
311 CompilationResult result = JIT::compile(&vm, codeBlock, JITCompilationCanFail);
312 switch (result) {
313 case CompilationFailed:
314 if (Options::verboseOSR())
315 dataLogF(" JIT compilation failed.\n");
316 codeBlock->dontJITAnytimeSoon();
317 return false;
318 case CompilationSuccessful:
319 if (Options::verboseOSR())
320 dataLogF(" JIT compilation successful.\n");
321 codeBlock->install();
322 codeBlock->jitSoon();
323 return true;
324 default:
325 RELEASE_ASSERT_NOT_REACHED();
326 return false;
327 }
328 }
329 default:
330 RELEASE_ASSERT_NOT_REACHED();
331 return false;
332 }
333}
334
335static SlowPathReturnType entryOSR(ExecState* exec, Instruction*, CodeBlock* codeBlock, const char *name, EntryKind kind)
336{
337 if (Options::verboseOSR()) {
338 dataLog(
339 *codeBlock, ": Entered ", name, " with executeCounter = ",
340 codeBlock->llintExecuteCounter(), "\n");
341 }
342
343 if (!shouldJIT(exec)) {
344 codeBlock->dontJITAnytimeSoon();
345 LLINT_RETURN_TWO(0, 0);
346 }
347 if (!jitCompileAndSetHeuristics(codeBlock, exec))
348 LLINT_RETURN_TWO(0, 0);
349
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);
356}
357#else // ENABLE(JIT)
358static SlowPathReturnType entryOSR(ExecState* exec, Instruction*, CodeBlock* codeBlock, const char*, EntryKind)
359{
360 codeBlock->dontJITAnytimeSoon();
361 LLINT_RETURN_TWO(0, exec);
362}
363#endif // ENABLE(JIT)
364
365LLINT_SLOW_PATH_DECL(entry_osr)
366{
367 return entryOSR(exec, pc, exec->codeBlock(), "entry_osr", Prologue);
368}
369
370LLINT_SLOW_PATH_DECL(entry_osr_function_for_call)
371{
372 return entryOSR(exec, pc, jsCast<JSFunction*>(exec->callee())->jsExecutable()->codeBlockForCall(), "entry_osr_function_for_call", Prologue);
373}
374
375LLINT_SLOW_PATH_DECL(entry_osr_function_for_construct)
376{
377 return entryOSR(exec, pc, jsCast<JSFunction*>(exec->callee())->jsExecutable()->codeBlockForConstruct(), "entry_osr_function_for_construct", Prologue);
378}
379
380LLINT_SLOW_PATH_DECL(entry_osr_function_for_call_arityCheck)
381{
382 return entryOSR(exec, pc, jsCast<JSFunction*>(exec->callee())->jsExecutable()->codeBlockForCall(), "entry_osr_function_for_call_arityCheck", ArityCheck);
383}
384
385LLINT_SLOW_PATH_DECL(entry_osr_function_for_construct_arityCheck)
386{
387 return entryOSR(exec, pc, jsCast<JSFunction*>(exec->callee())->jsExecutable()->codeBlockForConstruct(), "entry_osr_function_for_construct_arityCheck", ArityCheck);
388}
389
390LLINT_SLOW_PATH_DECL(loop_osr)
391{
392 CodeBlock* codeBlock = exec->codeBlock();
393
394#if ENABLE(JIT)
395 if (Options::verboseOSR()) {
396 dataLog(
397 *codeBlock, ": Entered loop_osr with executeCounter = ",
398 codeBlock->llintExecuteCounter(), "\n");
399 }
400
401 if (!shouldJIT(exec)) {
402 codeBlock->dontJITAnytimeSoon();
403 LLINT_RETURN_TWO(0, 0);
404 }
405
406 if (!jitCompileAndSetHeuristics(codeBlock, exec))
407 LLINT_RETURN_TWO(0, 0);
408
409 ASSERT(codeBlock->jitType() == JITCode::BaselineJIT);
410
411 Vector<BytecodeAndMachineOffset> map;
412 codeBlock->jitCodeMap()->decode(map);
413 BytecodeAndMachineOffset* mapping = binarySearch<BytecodeAndMachineOffset, unsigned>(map, map.size(), pc - codeBlock->instructions().begin(), BytecodeAndMachineOffset::getBytecodeIndex);
414 ASSERT(mapping);
415 ASSERT(mapping->m_bytecodeIndex == static_cast<unsigned>(pc - codeBlock->instructions().begin()));
416
417 void* jumpTarget = codeBlock->jitCode()->executableAddressAtOffset(mapping->m_machineCodeOffset);
418 ASSERT(jumpTarget);
419
420 LLINT_RETURN_TWO(jumpTarget, exec->topOfFrame());
421#else // ENABLE(JIT)
422 UNUSED_PARAM(pc);
423 codeBlock->dontJITAnytimeSoon();
424 LLINT_RETURN_TWO(0, 0);
425#endif // ENABLE(JIT)
426}
427
428LLINT_SLOW_PATH_DECL(replace)
429{
430 CodeBlock* codeBlock = exec->codeBlock();
431
432#if ENABLE(JIT)
433 if (Options::verboseOSR()) {
434 dataLog(
435 *codeBlock, ": Entered replace with executeCounter = ",
436 codeBlock->llintExecuteCounter(), "\n");
437 }
438
439 if (shouldJIT(exec))
440 jitCompileAndSetHeuristics(codeBlock, exec);
441 else
442 codeBlock->dontJITAnytimeSoon();
443 LLINT_END_IMPL();
444#else // ENABLE(JIT)
445 codeBlock->dontJITAnytimeSoon();
446 LLINT_END_IMPL();
447#endif // ENABLE(JIT)
448}
449
450LLINT_SLOW_PATH_DECL(stack_check)
451{
452 LLINT_BEGIN();
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);
458
459#if ENABLE(LLINT_C_LOOP)
460 dataLogF("Current end is at %p.\n", exec->vm().jsStackLimit());
461#else
462 dataLogF("Current end is at %p.\n", exec->vm().stackLimit());
463#endif
464
465#endif
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.
473 //
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.
477
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.
481#if !ENABLE(JIT)
482 ASSERT(!vm.interpreter->stack().containsAddress(exec->topOfFrame()));
483 if (LIKELY(vm.interpreter->stack().ensureCapacityFor(exec->topOfFrame())))
484 LLINT_RETURN_TWO(pc, 0);
485#endif
486
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);
493}
494
495LLINT_SLOW_PATH_DECL(slow_path_create_activation)
496{
497 LLINT_BEGIN();
498#if LLINT_SLOW_PATH_TRACING
499 dataLogF("Creating an activation, exec = %p!\n", exec);
500#endif
501 JSActivation* activation = JSActivation::create(vm, exec, exec->codeBlock());
502 exec->setScope(activation);
503 LLINT_RETURN(JSValue(activation));
504}
505
506LLINT_SLOW_PATH_DECL(slow_path_new_object)
507{
508 LLINT_BEGIN();
509 LLINT_RETURN(constructEmptyObject(exec, pc[3].u.objectAllocationProfile->structure()));
510}
511
512LLINT_SLOW_PATH_DECL(slow_path_new_array)
513{
514 LLINT_BEGIN();
515 LLINT_RETURN(constructArrayNegativeIndexed(exec, pc[4].u.arrayAllocationProfile, bitwise_cast<JSValue*>(&LLINT_OP(2)), pc[3].u.operand));
516}
517
518LLINT_SLOW_PATH_DECL(slow_path_new_array_with_size)
519{
520 LLINT_BEGIN();
521 LLINT_RETURN(constructArrayWithSizeQuirk(exec, pc[3].u.arrayAllocationProfile, exec->lexicalGlobalObject(), LLINT_OP_C(2).jsValue()));
522}
523
524LLINT_SLOW_PATH_DECL(slow_path_new_array_buffer)
525{
526 LLINT_BEGIN();
527 LLINT_RETURN(constructArray(exec, pc[4].u.arrayAllocationProfile, exec->codeBlock()->constantBuffer(pc[2].u.operand), pc[3].u.operand));
528}
529
530LLINT_SLOW_PATH_DECL(slow_path_new_regexp)
531{
532 LLINT_BEGIN();
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));
537}
538
539LLINT_SLOW_PATH_DECL(slow_path_check_has_instance)
540{
541 LLINT_BEGIN();
542
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);
551 }
552 }
553 LLINT_THROW(createInvalidParameterError(exec, "instanceof", baseVal));
554}
555
556LLINT_SLOW_PATH_DECL(slow_path_instanceof)
557{
558 LLINT_BEGIN();
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)));
563}
564
565LLINT_SLOW_PATH_DECL(slow_path_get_by_id)
566{
567 LLINT_BEGIN();
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);
572
573 JSValue result = baseValue.get(exec, ident, slot);
574 LLINT_CHECK_EXCEPTION();
575 LLINT_OP(1) = result;
576
577 if (!LLINT_ALWAYS_ACCESS_SLOW
578 && baseValue.isCell()
579 && slot.isCacheable()
580 && slot.slotBase() == baseValue
581 && slot.isCacheableValue()) {
582
583 JSCell* baseCell = baseValue.asCell();
584 Structure* structure = baseCell->structure();
585
586 if (!structure->isUncacheableDictionary()
587 && !structure->typeInfo().prohibitsPropertyCaching()
588 && !structure->typeInfo().newImpurePropertyFiresWatchpoints()) {
589 ConcurrentJITLocker locker(codeBlock->m_lock);
590
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();
596 } else {
597 pc[0].u.opcode = LLInt::getOpcode(op_get_by_id_out_of_line);
598 pc[5].u.operand = offsetInButterfly(slot.cachedOffset()) * sizeof(JSValue);
599 }
600 }
601 }
602
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;
610 }
611
612 pc[OPCODE_LENGTH(op_get_by_id) - 1].u.profile->m_buckets[0] = JSValue::encode(result);
613 LLINT_END();
614}
615
616LLINT_SLOW_PATH_DECL(slow_path_get_arguments_length)
617{
618 LLINT_BEGIN();
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));
624}
625
626LLINT_SLOW_PATH_DECL(slow_path_put_by_id)
627{
628 LLINT_BEGIN();
629 CodeBlock* codeBlock = exec->codeBlock();
630 const Identifier& ident = codeBlock->identifier(pc[2].u.operand);
631
632 JSValue baseValue = LLINT_OP_C(1).jsValue();
633 PutPropertySlot slot(baseValue, codeBlock->isStrictMode(), codeBlock->putByIdContext());
634 if (pc[8].u.operand)
635 asObject(baseValue)->putDirect(vm, ident, LLINT_OP_C(3).jsValue(), slot);
636 else
637 baseValue.put(exec, ident, LLINT_OP_C(3).jsValue(), slot);
638 LLINT_CHECK_EXCEPTION();
639
640 if (!LLINT_ALWAYS_ACCESS_SLOW
641 && baseValue.isCell()
642 && slot.isCacheablePut()) {
643
644 JSCell* baseCell = baseValue.asCell();
645 Structure* structure = baseCell->structure();
646
647 if (!structure->isUncacheableDictionary()
648 && !structure->typeInfo().prohibitsPropertyCaching()
649 && baseCell == slot.base()) {
650
651 if (slot.type() == PutPropertySlot::NewProperty) {
652 GCSafeConcurrentJITLocker locker(codeBlock->m_lock, vm.heap);
653
654 if (!structure->isDictionary() && structure->previousID()->outOfLineCapacity() == structure->outOfLineCapacity()) {
655 ASSERT(structure->previousID()->transitionWatchpointSetHasBeenInvalidated());
656
657 // This is needed because some of the methods we call
658 // below may GC.
659 pc[0].u.opcode = LLInt::getOpcode(op_put_by_id);
660
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();
667 else
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);
672 ASSERT(chain);
673 pc[7].u.structureChain.set(
674 vm, codeBlock->ownerExecutable(), chain);
675
676 if (pc[8].u.operand) {
677 if (isInlineOffset(slot.cachedOffset()))
678 pc[0].u.opcode = LLInt::getOpcode(op_put_by_id_transition_direct);
679 else
680 pc[0].u.opcode = LLInt::getOpcode(op_put_by_id_transition_direct_out_of_line);
681 } else {
682 if (isInlineOffset(slot.cachedOffset()))
683 pc[0].u.opcode = LLInt::getOpcode(op_put_by_id_transition_normal);
684 else
685 pc[0].u.opcode = LLInt::getOpcode(op_put_by_id_transition_normal_out_of_line);
686 }
687 }
688 }
689 } else {
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();
695 } else {
696 pc[0].u.opcode = LLInt::getOpcode(op_put_by_id_out_of_line);
697 pc[5].u.operand = offsetInButterfly(slot.cachedOffset()) * sizeof(JSValue);
698 }
699 }
700 }
701 }
702
703 LLINT_END();
704}
705
706LLINT_SLOW_PATH_DECL(slow_path_del_by_id)
707{
708 LLINT_BEGIN();
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));
716}
717
718inline JSValue getByVal(ExecState* exec, JSValue baseValue, JSValue subscript)
719{
720 if (LIKELY(baseValue.isCell() && subscript.isString())) {
721 VM& vm = exec->vm();
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)))
725 return result;
726 }
727 }
728
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);
733
734 return baseValue.get(exec, i);
735 }
736
737 if (isName(subscript))
738 return baseValue.get(exec, jsCast<NameInstance*>(subscript.asCell())->privateName());
739
740 Identifier property = subscript.toString(exec)->toIdentifier(exec);
741 return baseValue.get(exec, property);
742}
743
744LLINT_SLOW_PATH_DECL(slow_path_get_by_val)
745{
746 LLINT_BEGIN();
747 LLINT_RETURN_PROFILED(op_get_by_val, getByVal(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue()));
748}
749
750LLINT_SLOW_PATH_DECL(slow_path_get_argument_by_val)
751{
752 LLINT_BEGIN();
753 JSValue arguments = LLINT_OP(2).jsValue();
754 if (!arguments) {
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;
759 }
760
761 LLINT_RETURN_PROFILED(op_get_argument_by_val, getByVal(exec, arguments, LLINT_OP_C(3).jsValue()));
762}
763
764LLINT_SLOW_PATH_DECL(slow_path_get_by_pname)
765{
766 LLINT_BEGIN();
767 LLINT_RETURN(getByVal(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue()));
768}
769
770LLINT_SLOW_PATH_DECL(slow_path_put_by_val)
771{
772 LLINT_BEGIN();
773
774 JSValue baseValue = LLINT_OP_C(1).jsValue();
775 JSValue subscript = LLINT_OP_C(2).jsValue();
776 JSValue value = LLINT_OP_C(3).jsValue();
777
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);
784 else
785 object->methodTable()->putByIndex(object, exec, i, value, exec->codeBlock()->isStrictMode());
786 LLINT_END();
787 }
788 baseValue.putByIndex(exec, i, value, exec->codeBlock()->isStrictMode());
789 LLINT_END();
790 }
791
792 if (isName(subscript)) {
793 PutPropertySlot slot(baseValue, exec->codeBlock()->isStrictMode());
794 baseValue.put(exec, jsCast<NameInstance*>(subscript.asCell())->privateName(), value, slot);
795 LLINT_END();
796 }
797
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);
802 LLINT_END();
803}
804
805LLINT_SLOW_PATH_DECL(slow_path_put_by_val_direct)
806{
807 LLINT_BEGIN();
808
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);
820 } else {
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);
825 }
826 }
827 LLINT_END();
828}
829
830LLINT_SLOW_PATH_DECL(slow_path_del_by_val)
831{
832 LLINT_BEGIN();
833 JSValue baseValue = LLINT_OP_C(2).jsValue();
834 JSObject* baseObject = baseValue.toObject(exec);
835
836 JSValue subscript = LLINT_OP_C(3).jsValue();
837
838 bool couldDelete;
839
840 uint32_t i;
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());
845 else {
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);
850 }
851
852 if (!couldDelete && exec->codeBlock()->isStrictMode())
853 LLINT_THROW(createTypeError(exec, "Unable to delete property."));
854
855 LLINT_RETURN(jsBoolean(couldDelete));
856}
857
858LLINT_SLOW_PATH_DECL(slow_path_put_by_index)
859{
860 LLINT_BEGIN();
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());
864 LLINT_END();
865}
866
867LLINT_SLOW_PATH_DECL(slow_path_put_getter_setter)
868{
869 LLINT_BEGIN();
870 ASSERT(LLINT_OP(1).jsValue().isObject());
871 JSObject* baseObj = asObject(LLINT_OP(1).jsValue());
872
873 GetterSetter* accessor = GetterSetter::create(vm);
874 LLINT_CHECK_EXCEPTION();
875
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());
881
882 if (!getter.isUndefined())
883 accessor->setGetter(vm, asObject(getter));
884 if (!setter.isUndefined())
885 accessor->setSetter(vm, asObject(setter));
886 baseObj->putDirectAccessor(
887 exec,
888 exec->codeBlock()->identifier(pc[2].u.operand),
889 accessor, Accessor);
890 LLINT_END();
891}
892
893LLINT_SLOW_PATH_DECL(slow_path_jtrue)
894{
895 LLINT_BEGIN();
896 LLINT_BRANCH(op_jtrue, LLINT_OP_C(1).jsValue().toBoolean(exec));
897}
898
899LLINT_SLOW_PATH_DECL(slow_path_jfalse)
900{
901 LLINT_BEGIN();
902 LLINT_BRANCH(op_jfalse, !LLINT_OP_C(1).jsValue().toBoolean(exec));
903}
904
905LLINT_SLOW_PATH_DECL(slow_path_jless)
906{
907 LLINT_BEGIN();
908 LLINT_BRANCH(op_jless, jsLess<true>(exec, LLINT_OP_C(1).jsValue(), LLINT_OP_C(2).jsValue()));
909}
910
911LLINT_SLOW_PATH_DECL(slow_path_jnless)
912{
913 LLINT_BEGIN();
914 LLINT_BRANCH(op_jnless, !jsLess<true>(exec, LLINT_OP_C(1).jsValue(), LLINT_OP_C(2).jsValue()));
915}
916
917LLINT_SLOW_PATH_DECL(slow_path_jgreater)
918{
919 LLINT_BEGIN();
920 LLINT_BRANCH(op_jgreater, jsLess<false>(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(1).jsValue()));
921}
922
923LLINT_SLOW_PATH_DECL(slow_path_jngreater)
924{
925 LLINT_BEGIN();
926 LLINT_BRANCH(op_jngreater, !jsLess<false>(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(1).jsValue()));
927}
928
929LLINT_SLOW_PATH_DECL(slow_path_jlesseq)
930{
931 LLINT_BEGIN();
932 LLINT_BRANCH(op_jlesseq, jsLessEq<true>(exec, LLINT_OP_C(1).jsValue(), LLINT_OP_C(2).jsValue()));
933}
934
935LLINT_SLOW_PATH_DECL(slow_path_jnlesseq)
936{
937 LLINT_BEGIN();
938 LLINT_BRANCH(op_jnlesseq, !jsLessEq<true>(exec, LLINT_OP_C(1).jsValue(), LLINT_OP_C(2).jsValue()));
939}
940
941LLINT_SLOW_PATH_DECL(slow_path_jgreatereq)
942{
943 LLINT_BEGIN();
944 LLINT_BRANCH(op_jgreatereq, jsLessEq<false>(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(1).jsValue()));
945}
946
947LLINT_SLOW_PATH_DECL(slow_path_jngreatereq)
948{
949 LLINT_BEGIN();
950 LLINT_BRANCH(op_jngreatereq, !jsLessEq<false>(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(1).jsValue()));
951}
952
953LLINT_SLOW_PATH_DECL(slow_path_switch_imm)
954{
955 LLINT_BEGIN();
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);
964 } else
965 pc += defaultOffset;
966 LLINT_END();
967}
968
969LLINT_SLOW_PATH_DECL(slow_path_switch_char)
970{
971 LLINT_BEGIN();
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);
980 LLINT_END();
981}
982
983LLINT_SLOW_PATH_DECL(slow_path_switch_string)
984{
985 LLINT_BEGIN();
986 JSValue scrutinee = LLINT_OP_C(3).jsValue();
987 int defaultOffset = pc[2].u.operand;
988 if (!scrutinee.isString())
989 pc += defaultOffset;
990 else {
991 CodeBlock* codeBlock = exec->codeBlock();
992 pc += codeBlock->stringSwitchJumpTable(pc[1].u.operand).offsetForValue(asString(scrutinee)->value(exec).impl(), defaultOffset);
993 }
994 LLINT_END();
995}
996
997LLINT_SLOW_PATH_DECL(slow_path_new_func)
998{
999 LLINT_BEGIN();
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");
1004#endif
1005 LLINT_RETURN(JSFunction::create(vm, codeBlock->functionDecl(pc[2].u.operand), exec->scope()));
1006}
1007
1008LLINT_SLOW_PATH_DECL(slow_path_new_func_exp)
1009{
1010 LLINT_BEGIN();
1011 CodeBlock* codeBlock = exec->codeBlock();
1012 FunctionExecutable* function = codeBlock->functionExpr(pc[2].u.operand);
1013 JSFunction* func = JSFunction::create(vm, function, exec->scope());
1014
1015 LLINT_RETURN(func);
1016}
1017
1018static SlowPathReturnType handleHostCall(ExecState* execCallee, Instruction* pc, JSValue callee, CodeSpecializationKind kind)
1019{
1020 UNUSED_PARAM(pc);
1021
1022#if LLINT_SLOW_PATH_TRACING
1023 dataLog("Performing host call.\n");
1024#endif
1025
1026 ExecState* exec = execCallee->callerFrame();
1027 VM& vm = exec->vm();
1028
1029 execCallee->setScope(exec->scope());
1030 execCallee->setCodeBlock(0);
1031 execCallee->clearReturnPC();
1032
1033 if (kind == CodeForCall) {
1034 CallData callData;
1035 CallType callType = getCallData(callee, callData);
1036
1037 ASSERT(callType != CallTypeJS);
1038
1039 if (callType == CallTypeHost) {
1040 NativeCallFrameTracer tracer(&vm, execCallee);
1041 execCallee->setCallee(asObject(callee));
1042 vm.hostCallReturnValue = JSValue::decode(callData.native.function(execCallee));
1043
1044 LLINT_CALL_RETURN(execCallee, LLInt::getCodePtr(getHostCallReturnValue));
1045 }
1046
1047#if LLINT_SLOW_PATH_TRACING
1048 dataLog("Call callee is not a function: ", callee, "\n");
1049#endif
1050
1051 ASSERT(callType == CallTypeNone);
1052 LLINT_CALL_THROW(exec, createNotAFunctionError(exec, callee));
1053 }
1054
1055 ASSERT(kind == CodeForConstruct);
1056
1057 ConstructData constructData;
1058 ConstructType constructType = getConstructData(callee, constructData);
1059
1060 ASSERT(constructType != ConstructTypeJS);
1061
1062 if (constructType == ConstructTypeHost) {
1063 NativeCallFrameTracer tracer(&vm, execCallee);
1064 execCallee->setCallee(asObject(callee));
1065 vm.hostCallReturnValue = JSValue::decode(constructData.native.function(execCallee));
1066
1067 LLINT_CALL_RETURN(execCallee, LLInt::getCodePtr(getHostCallReturnValue));
1068 }
1069
1070#if LLINT_SLOW_PATH_TRACING
1071 dataLog("Constructor callee is not a function: ", callee, "\n");
1072#endif
1073
1074 ASSERT(constructType == ConstructTypeNone);
1075 LLINT_CALL_THROW(exec, createNotAConstructorError(exec, callee));
1076}
1077
1078inline SlowPathReturnType setUpCall(ExecState* execCallee, Instruction* pc, CodeSpecializationKind kind, JSValue calleeAsValue, LLIntCallLinkInfo* callLinkInfo = 0)
1079{
1080#if LLINT_SLOW_PATH_TRACING
1081 dataLogF("Performing call with recorded PC = %p\n", execCallee->callerFrame()->currentVPC());
1082#endif
1083
1084 JSCell* calleeAsFunctionCell = getJSFunction(calleeAsValue);
1085 if (!calleeAsFunctionCell)
1086 return handleHostCall(execCallee, pc, calleeAsValue, kind);
1087
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();
1093
1094 MacroAssemblerCodePtr codePtr;
1095 CodeBlock* codeBlock = 0;
1096 if (executable->isHostFunction())
1097 codePtr = executable->entrypointFor(vm, kind, MustCheckArity, RegisterPreservationNotRequired);
1098 else {
1099 FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable);
1100 JSObject* error = functionExecutable->prepareForExecution(execCallee, callee, &scope, kind);
1101 execCallee->setScope(scope);
1102 if (error)
1103 LLINT_CALL_THROW(execCallee->callerFrame(), error);
1104 codeBlock = functionExecutable->codeBlockFor(kind);
1105 ASSERT(codeBlock);
1106 ArityCheckMode arity;
1107 if (execCallee->argumentCountIncludingThis() < static_cast<size_t>(codeBlock->numParameters()))
1108 arity = MustCheckArity;
1109 else
1110 arity = ArityCheckNotRequired;
1111 codePtr = functionExecutable->entrypointFor(vm, kind, arity, RegisterPreservationNotRequired);
1112 }
1113
1114 ASSERT(!!codePtr);
1115
1116 if (!LLINT_ALWAYS_ACCESS_SLOW && callLinkInfo) {
1117 ExecState* execCaller = execCallee->callerFrame();
1118
1119 CodeBlock* callerCodeBlock = execCaller->codeBlock();
1120
1121 ConcurrentJITLocker locker(callerCodeBlock->m_lock);
1122
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;
1128 if (codeBlock)
1129 codeBlock->linkIncomingCall(execCaller, callLinkInfo);
1130 }
1131
1132 LLINT_CALL_RETURN(execCallee, codePtr.executableAddress());
1133}
1134
1135inline SlowPathReturnType genericCall(ExecState* exec, Instruction* pc, CodeSpecializationKind kind)
1136{
1137 // This needs to:
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.
1142
1143 JSValue calleeAsValue = LLINT_OP_C(2).jsValue();
1144
1145 ExecState* execCallee = exec - pc[4].u.operand;
1146
1147 execCallee->setArgumentCountIncludingThis(pc[3].u.operand);
1148 execCallee->uncheckedR(JSStack::Callee) = calleeAsValue;
1149 execCallee->setCallerFrame(exec);
1150
1151 ASSERT(pc[5].u.callLinkInfo);
1152 return setUpCall(execCallee, pc, kind, calleeAsValue, pc[5].u.callLinkInfo);
1153}
1154
1155LLINT_SLOW_PATH_DECL(slow_path_call)
1156{
1157 LLINT_BEGIN_NO_SET_PC();
1158 return genericCall(exec, pc, CodeForCall);
1159}
1160
1161LLINT_SLOW_PATH_DECL(slow_path_construct)
1162{
1163 LLINT_BEGIN_NO_SET_PC();
1164 return genericCall(exec, pc, CodeForConstruct);
1165}
1166
1167LLINT_SLOW_PATH_DECL(slow_path_size_frame_for_varargs)
1168{
1169 LLINT_BEGIN();
1170 // This needs to:
1171 // - Set up a call frame while respecting the variable arguments.
1172
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);
1176
1177 vm.newCallFrameReturnValue = execCallee;
1178
1179 LLINT_RETURN_CALLEE_FRAME(execCallee);
1180}
1181
1182LLINT_SLOW_PATH_DECL(slow_path_call_varargs)
1183{
1184 LLINT_BEGIN_NO_SET_PC();
1185 // This needs to:
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.
1188
1189 JSValue calleeAsValue = LLINT_OP_C(2).jsValue();
1190
1191 ExecState* execCallee = vm.newCallFrameReturnValue;
1192
1193 loadVarargs(exec, execCallee, LLINT_OP_C(3).jsValue(), LLINT_OP_C(4).jsValue(), pc[6].u.operand);
1194 LLINT_CALL_CHECK_EXCEPTION(exec);
1195
1196 execCallee->uncheckedR(JSStack::Callee) = calleeAsValue;
1197 execCallee->setCallerFrame(exec);
1198 exec->setCurrentVPC(pc);
1199
1200 return setUpCall(execCallee, pc, CodeForCall, calleeAsValue);
1201}
1202
1203LLINT_SLOW_PATH_DECL(slow_path_construct_varargs)
1204{
1205 LLINT_BEGIN_NO_SET_PC();
1206 // This needs to:
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.
1209
1210 JSValue calleeAsValue = LLINT_OP_C(2).jsValue();
1211
1212 ExecState* execCallee = vm.newCallFrameReturnValue;
1213
1214 loadVarargs(exec, execCallee, LLINT_OP_C(3).jsValue(), LLINT_OP_C(4).jsValue(), pc[6].u.operand);
1215 LLINT_CALL_CHECK_EXCEPTION(exec);
1216
1217 execCallee->uncheckedR(JSStack::Callee) = calleeAsValue;
1218 execCallee->setCallerFrame(exec);
1219 exec->setCurrentVPC(pc);
1220
1221 return setUpCall(execCallee, pc, CodeForConstruct, calleeAsValue);
1222}
1223
1224LLINT_SLOW_PATH_DECL(slow_path_call_eval)
1225{
1226 LLINT_BEGIN_NO_SET_PC();
1227 JSValue calleeAsValue = LLINT_OP(2).jsValue();
1228
1229 ExecState* execCallee = exec - pc[4].u.operand;
1230
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);
1238
1239 if (!isHostFunction(calleeAsValue, globalFuncEval))
1240 return setUpCall(execCallee, pc, CodeForCall, calleeAsValue);
1241
1242 vm.hostCallReturnValue = eval(execCallee);
1243 LLINT_CALL_RETURN(execCallee, LLInt::getCodePtr(getHostCallReturnValue));
1244}
1245
1246LLINT_SLOW_PATH_DECL(slow_path_tear_off_activation)
1247{
1248 LLINT_BEGIN();
1249 ASSERT(exec->codeBlock()->needsActivation());
1250 jsCast<JSActivation*>(LLINT_OP(1).jsValue())->tearOff(vm);
1251 LLINT_END();
1252}
1253
1254LLINT_SLOW_PATH_DECL(slow_path_tear_off_arguments)
1255{
1256 LLINT_BEGIN();
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));
1261 else
1262 arguments->tearOff(exec);
1263 LLINT_END();
1264}
1265
1266LLINT_SLOW_PATH_DECL(slow_path_strcat)
1267{
1268 LLINT_BEGIN();
1269 LLINT_RETURN(jsStringFromRegisterArray(exec, &LLINT_OP(2), pc[3].u.operand));
1270}
1271
1272LLINT_SLOW_PATH_DECL(slow_path_to_primitive)
1273{
1274 LLINT_BEGIN();
1275 LLINT_RETURN(LLINT_OP_C(2).jsValue().toPrimitive(exec));
1276}
1277
1278LLINT_SLOW_PATH_DECL(slow_path_get_pnames)
1279{
1280 LLINT_BEGIN();
1281 JSValue v = LLINT_OP(2).jsValue();
1282 if (v.isUndefinedOrNull()) {
1283 pc += pc[5].u.operand;
1284 LLINT_END();
1285 }
1286
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);
1292
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());
1297
1298 pc += OPCODE_LENGTH(op_get_pnames);
1299 LLINT_END();
1300}
1301
1302LLINT_SLOW_PATH_DECL(slow_path_next_pname)
1303{
1304 LLINT_BEGIN();
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)))) {
1308 // Go to target.
1309 pc += pc[6].u.operand;
1310 } // Else, don't change the PC, so the interpreter will reloop.
1311 LLINT_END();
1312}
1313
1314LLINT_SLOW_PATH_DECL(slow_path_push_with_scope)
1315{
1316 LLINT_BEGIN();
1317 JSValue v = LLINT_OP_C(1).jsValue();
1318 JSObject* o = v.toObject(exec);
1319 LLINT_CHECK_EXCEPTION();
1320
1321 exec->setScope(JSWithScope::create(exec, o));
1322
1323 LLINT_END();
1324}
1325
1326LLINT_SLOW_PATH_DECL(slow_path_pop_scope)
1327{
1328 LLINT_BEGIN();
1329 exec->setScope(exec->scope()->next());
1330 LLINT_END();
1331}
1332
1333LLINT_SLOW_PATH_DECL(slow_path_push_name_scope)
1334{
1335 LLINT_BEGIN();
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);
1339 LLINT_END();
1340}
1341
1342LLINT_SLOW_PATH_DECL(slow_path_throw)
1343{
1344 LLINT_BEGIN();
1345 LLINT_THROW(LLINT_OP_C(1).jsValue());
1346}
1347
1348LLINT_SLOW_PATH_DECL(slow_path_throw_static_error)
1349{
1350 LLINT_BEGIN();
1351 if (pc[2].u.operand)
1352 LLINT_THROW(createReferenceError(exec, errorDescriptionForValue(exec, LLINT_OP_C(1).jsValue())->value(exec)));
1353 else
1354 LLINT_THROW(createTypeError(exec, errorDescriptionForValue(exec, LLINT_OP_C(1).jsValue())->value(exec)));
1355}
1356
1357LLINT_SLOW_PATH_DECL(slow_path_handle_watchdog_timer)
1358{
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);
1364}
1365
1366LLINT_SLOW_PATH_DECL(slow_path_debug)
1367{
1368 LLINT_BEGIN();
1369 int debugHookID = pc[1].u.operand;
1370 vm.interpreter->debug(exec, static_cast<DebugHookID>(debugHookID));
1371
1372 LLINT_END();
1373}
1374
1375LLINT_SLOW_PATH_DECL(slow_path_profile_will_call)
1376{
1377 LLINT_BEGIN();
1378 if (LegacyProfiler* profiler = vm.enabledProfiler())
1379 profiler->willExecute(exec, LLINT_OP(1).jsValue());
1380 LLINT_END();
1381}
1382
1383LLINT_SLOW_PATH_DECL(slow_path_profile_did_call)
1384{
1385 LLINT_BEGIN();
1386 if (LegacyProfiler* profiler = vm.enabledProfiler())
1387 profiler->didExecute(exec, LLINT_OP(1).jsValue());
1388 LLINT_END();
1389}
1390
1391LLINT_SLOW_PATH_DECL(slow_path_handle_exception)
1392{
1393 LLINT_BEGIN_NO_SET_PC();
1394 ASSERT(vm.exception());
1395 genericUnwind(&vm, exec, vm.exception());
1396 LLINT_END_IMPL();
1397}
1398
1399LLINT_SLOW_PATH_DECL(slow_path_resolve_scope)
1400{
1401 LLINT_BEGIN();
1402 const Identifier& ident = exec->codeBlock()->identifier(pc[2].u.operand);
1403 LLINT_RETURN(JSScope::resolve(exec, exec->scope(), ident));
1404}
1405
1406LLINT_SLOW_PATH_DECL(slow_path_get_from_scope)
1407{
1408 LLINT_BEGIN();
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);
1412
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());
1418 }
1419
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();
1427 }
1428 }
1429
1430 LLINT_RETURN(slot.getValue(exec, ident));
1431}
1432
1433LLINT_SLOW_PATH_DECL(slow_path_put_to_scope)
1434{
1435 LLINT_BEGIN();
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);
1441
1442 if (modeAndType.mode() == ThrowIfNotFound && !scope->hasProperty(exec, ident))
1443 LLINT_THROW(createUndefinedVariableError(exec, ident));
1444
1445 PutPropertySlot slot(scope, codeBlock->isStrictMode());
1446 scope->methodTable()->put(scope, exec, ident, value, slot);
1447
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();
1454 }
1455 }
1456
1457 LLINT_END();
1458}
1459
1460extern "C" SlowPathReturnType llint_throw_stack_overflow_error(VM* vm, ProtoCallFrame* protoFrame)
1461{
1462 ExecState* exec = vm->topCallFrame;
1463 if (!exec)
1464 exec = protoFrame->scope()->globalObject()->globalExec();
1465 throwStackOverflowError(exec);
1466 return encodeResult(0, 0);
1467}
1468
1469#if !ENABLE(JIT)
1470extern "C" SlowPathReturnType llint_stack_check_at_vm_entry(VM* vm, Register* newTopOfStack)
1471{
1472 bool success = vm->interpreter->stack().ensureCapacityFor(newTopOfStack);
1473 return encodeResult(reinterpret_cast<void*>(success), 0);
1474}
1475#endif
1476
1477extern "C" void llint_write_barrier_slow(ExecState* exec, JSCell* cell)
1478{
1479 VM& vm = exec->vm();
1480 vm.heap.writeBarrier(cell);
1481}
1482
1483extern "C" NO_RETURN_DUE_TO_CRASH void llint_crash()
1484{
1485 CRASH();
1486}
1487
1488} } // namespace JSC::LLInt