]> git.saurik.com Git - apple/javascriptcore.git/blob - llint/LLIntSlowPaths.cpp
JavaScriptCore-7601.1.46.3.tar.gz
[apple/javascriptcore.git] / llint / LLIntSlowPaths.cpp
1 /*
2 * Copyright (C) 2011-2015 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
29 #include "ArrayConstructor.h"
30 #include "CallFrame.h"
31 #include "CommonSlowPaths.h"
32 #include "CommonSlowPathsExceptions.h"
33 #include "Error.h"
34 #include "ErrorHandlingScope.h"
35 #include "ExceptionFuzz.h"
36 #include "GetterSetter.h"
37 #include "HostCallReturnValue.h"
38 #include "Interpreter.h"
39 #include "JIT.h"
40 #include "JITExceptions.h"
41 #include "JSLexicalEnvironment.h"
42 #include "JSCInlines.h"
43 #include "JSCJSValue.h"
44 #include "JSGlobalObjectFunctions.h"
45 #include "JSNameScope.h"
46 #include "JSStackInlines.h"
47 #include "JSString.h"
48 #include "JSWithScope.h"
49 #include "LLIntCommon.h"
50 #include "LLIntExceptions.h"
51 #include "LegacyProfiler.h"
52 #include "LowLevelInterpreter.h"
53 #include "ObjectConstructor.h"
54 #include "ProtoCallFrame.h"
55 #include "StructureRareDataInlines.h"
56 #include <wtf/StringPrintStream.h>
57
58 namespace JSC { namespace LLInt {
59
60 #define LLINT_BEGIN_NO_SET_PC() \
61 VM& vm = exec->vm(); \
62 NativeCallFrameTracer tracer(&vm, exec)
63
64 #ifndef NDEBUG
65 #define LLINT_SET_PC_FOR_STUBS() do { \
66 exec->codeBlock()->bytecodeOffset(pc); \
67 exec->setCurrentVPC(pc + 1); \
68 } while (false)
69 #else
70 #define LLINT_SET_PC_FOR_STUBS() do { \
71 exec->setCurrentVPC(pc + 1); \
72 } while (false)
73 #endif
74
75 #define LLINT_BEGIN() \
76 LLINT_BEGIN_NO_SET_PC(); \
77 LLINT_SET_PC_FOR_STUBS()
78
79 #define LLINT_OP(index) (exec->uncheckedR(pc[index].u.operand))
80 #define LLINT_OP_C(index) (exec->r(pc[index].u.operand))
81
82 #define LLINT_RETURN_TWO(first, second) do { \
83 return encodeResult(first, second); \
84 } while (false)
85
86 #define LLINT_END_IMPL() LLINT_RETURN_TWO(pc, 0)
87
88 #define LLINT_THROW(exceptionToThrow) do { \
89 vm.throwException(exec, exceptionToThrow); \
90 pc = returnToThrow(exec); \
91 LLINT_END_IMPL(); \
92 } while (false)
93
94 #define LLINT_CHECK_EXCEPTION() do { \
95 doExceptionFuzzingIfEnabled(exec, "LLIntSlowPaths", pc); \
96 if (UNLIKELY(vm.exception())) { \
97 pc = returnToThrow(exec); \
98 LLINT_END_IMPL(); \
99 } \
100 } while (false)
101
102 #define LLINT_END() do { \
103 LLINT_CHECK_EXCEPTION(); \
104 LLINT_END_IMPL(); \
105 } while (false)
106
107 #define LLINT_BRANCH(opcode, condition) do { \
108 bool __b_condition = (condition); \
109 LLINT_CHECK_EXCEPTION(); \
110 if (__b_condition) \
111 pc += pc[OPCODE_LENGTH(opcode) - 1].u.operand; \
112 else \
113 pc += OPCODE_LENGTH(opcode); \
114 LLINT_END_IMPL(); \
115 } while (false)
116
117 #define LLINT_RETURN(value) do { \
118 JSValue __r_returnValue = (value); \
119 LLINT_CHECK_EXCEPTION(); \
120 LLINT_OP(1) = __r_returnValue; \
121 LLINT_END_IMPL(); \
122 } while (false)
123
124 #define LLINT_RETURN_WITH_PC_ADJUSTMENT(value, pcAdjustment) do { \
125 JSValue __r_returnValue = (value); \
126 LLINT_CHECK_EXCEPTION(); \
127 LLINT_OP(1) = __r_returnValue; \
128 pc += (pcAdjustment); \
129 LLINT_END_IMPL(); \
130 } while (false)
131
132 #define LLINT_RETURN_PROFILED(opcode, value) do { \
133 JSValue __rp_returnValue = (value); \
134 LLINT_CHECK_EXCEPTION(); \
135 LLINT_OP(1) = __rp_returnValue; \
136 LLINT_PROFILE_VALUE(opcode, __rp_returnValue); \
137 LLINT_END_IMPL(); \
138 } while (false)
139
140 #define LLINT_PROFILE_VALUE(opcode, value) do { \
141 pc[OPCODE_LENGTH(opcode) - 1].u.profile->m_buckets[0] = \
142 JSValue::encode(value); \
143 } while (false)
144
145 #define LLINT_CALL_END_IMPL(exec, callTarget) LLINT_RETURN_TWO((callTarget), (exec))
146
147 #define LLINT_CALL_THROW(exec, exceptionToThrow) do { \
148 ExecState* __ct_exec = (exec); \
149 vm.throwException(__ct_exec, exceptionToThrow); \
150 LLINT_CALL_END_IMPL(0, callToThrow(__ct_exec)); \
151 } while (false)
152
153 #define LLINT_CALL_CHECK_EXCEPTION(exec, execCallee) do { \
154 ExecState* __cce_exec = (exec); \
155 ExecState* __cce_execCallee = (execCallee); \
156 doExceptionFuzzingIfEnabled(__cce_exec, "LLIntSlowPaths/call", nullptr); \
157 if (UNLIKELY(vm.exception())) \
158 LLINT_CALL_END_IMPL(0, callToThrow(__cce_execCallee)); \
159 } while (false)
160
161 #define LLINT_CALL_RETURN(exec, execCallee, callTarget) do { \
162 ExecState* __cr_exec = (exec); \
163 ExecState* __cr_execCallee = (execCallee); \
164 void* __cr_callTarget = (callTarget); \
165 LLINT_CALL_CHECK_EXCEPTION(__cr_exec, __cr_execCallee); \
166 LLINT_CALL_END_IMPL(__cr_execCallee, __cr_callTarget); \
167 } while (false)
168
169 #define LLINT_RETURN_CALLEE_FRAME(execCallee) do { \
170 ExecState* __rcf_exec = (execCallee); \
171 LLINT_RETURN_TWO(pc, __rcf_exec); \
172 } while (false)
173
174 extern "C" SlowPathReturnType llint_trace_operand(ExecState* exec, Instruction* pc, int fromWhere, int operand)
175 {
176 LLINT_BEGIN();
177 dataLogF("%p / %p: executing bc#%zu, op#%u: Trace(%d): %d: %d\n",
178 exec->codeBlock(),
179 exec,
180 static_cast<intptr_t>(pc - exec->codeBlock()->instructions().begin()),
181 exec->vm().interpreter->getOpcodeID(pc[0].u.opcode),
182 fromWhere,
183 operand,
184 pc[operand].u.operand);
185 LLINT_END();
186 }
187
188 extern "C" SlowPathReturnType llint_trace_value(ExecState* exec, Instruction* pc, int fromWhere, int operand)
189 {
190 JSValue value = LLINT_OP_C(operand).jsValue();
191 union {
192 struct {
193 uint32_t tag;
194 uint32_t payload;
195 } bits;
196 EncodedJSValue asValue;
197 } u;
198 u.asValue = JSValue::encode(value);
199 dataLogF(
200 "%p / %p: executing bc#%zu, op#%u: Trace(%d): %d: %d: %08x:%08x: %s\n",
201 exec->codeBlock(),
202 exec,
203 static_cast<intptr_t>(pc - exec->codeBlock()->instructions().begin()),
204 exec->vm().interpreter->getOpcodeID(pc[0].u.opcode),
205 fromWhere,
206 operand,
207 pc[operand].u.operand,
208 u.bits.tag,
209 u.bits.payload,
210 toCString(value).data());
211 LLINT_END_IMPL();
212 }
213
214 LLINT_SLOW_PATH_DECL(trace_prologue)
215 {
216 dataLogF("%p / %p: in prologue.\n", exec->codeBlock(), exec);
217 LLINT_END_IMPL();
218 }
219
220 static void traceFunctionPrologue(ExecState* exec, const char* comment, CodeSpecializationKind kind)
221 {
222 JSFunction* callee = jsCast<JSFunction*>(exec->callee());
223 FunctionExecutable* executable = callee->jsExecutable();
224 CodeBlock* codeBlock = executable->codeBlockFor(kind);
225 dataLogF("%p / %p: in %s of function %p, executable %p; numVars = %u, numParameters = %u, numCalleeRegisters = %u, caller = %p.\n",
226 codeBlock, exec, comment, callee, executable,
227 codeBlock->m_numVars, codeBlock->numParameters(), codeBlock->m_numCalleeRegisters,
228 exec->callerFrame());
229 }
230
231 LLINT_SLOW_PATH_DECL(trace_prologue_function_for_call)
232 {
233 traceFunctionPrologue(exec, "call prologue", CodeForCall);
234 LLINT_END_IMPL();
235 }
236
237 LLINT_SLOW_PATH_DECL(trace_prologue_function_for_construct)
238 {
239 traceFunctionPrologue(exec, "construct prologue", CodeForConstruct);
240 LLINT_END_IMPL();
241 }
242
243 LLINT_SLOW_PATH_DECL(trace_arityCheck_for_call)
244 {
245 traceFunctionPrologue(exec, "call arity check", CodeForCall);
246 LLINT_END_IMPL();
247 }
248
249 LLINT_SLOW_PATH_DECL(trace_arityCheck_for_construct)
250 {
251 traceFunctionPrologue(exec, "construct arity check", CodeForConstruct);
252 LLINT_END_IMPL();
253 }
254
255 LLINT_SLOW_PATH_DECL(trace)
256 {
257 dataLogF("%p / %p: executing bc#%zu, %s, pc = %p\n",
258 exec->codeBlock(),
259 exec,
260 static_cast<intptr_t>(pc - exec->codeBlock()->instructions().begin()),
261 opcodeNames[exec->vm().interpreter->getOpcodeID(pc[0].u.opcode)], pc);
262 if (exec->vm().interpreter->getOpcodeID(pc[0].u.opcode) == op_enter) {
263 dataLogF("Frame will eventually return to %p\n", exec->returnPC().value());
264 *bitwise_cast<volatile char*>(exec->returnPC().value());
265 }
266 if (exec->vm().interpreter->getOpcodeID(pc[0].u.opcode) == op_ret) {
267 dataLogF("Will be returning to %p\n", exec->returnPC().value());
268 dataLogF("The new cfr will be %p\n", exec->callerFrame());
269 }
270 LLINT_END_IMPL();
271 }
272
273 LLINT_SLOW_PATH_DECL(special_trace)
274 {
275 dataLogF("%p / %p: executing special case bc#%zu, op#%u, return PC is %p\n",
276 exec->codeBlock(),
277 exec,
278 static_cast<intptr_t>(pc - exec->codeBlock()->instructions().begin()),
279 exec->vm().interpreter->getOpcodeID(pc[0].u.opcode),
280 exec->returnPC().value());
281 LLINT_END_IMPL();
282 }
283
284 enum EntryKind { Prologue, ArityCheck };
285
286 #if ENABLE(JIT)
287 inline bool shouldJIT(ExecState* exec)
288 {
289 // You can modify this to turn off JITting without rebuilding the world.
290 return exec->vm().canUseJIT();
291 }
292
293 // Returns true if we should try to OSR.
294 inline bool jitCompileAndSetHeuristics(CodeBlock* codeBlock, ExecState* exec)
295 {
296 VM& vm = exec->vm();
297 DeferGCForAWhile deferGC(vm.heap); // My callers don't set top callframe, so we don't want to GC here at all.
298
299 codeBlock->updateAllValueProfilePredictions();
300
301 if (!codeBlock->checkIfJITThresholdReached()) {
302 if (Options::verboseOSR())
303 dataLogF(" JIT threshold should be lifted.\n");
304 return false;
305 }
306
307 switch (codeBlock->jitType()) {
308 case JITCode::BaselineJIT: {
309 if (Options::verboseOSR())
310 dataLogF(" Code was already compiled.\n");
311 codeBlock->jitSoon();
312 return true;
313 }
314 case JITCode::InterpreterThunk: {
315 CompilationResult result = JIT::compile(&vm, codeBlock, JITCompilationCanFail);
316 switch (result) {
317 case CompilationFailed:
318 if (Options::verboseOSR())
319 dataLogF(" JIT compilation failed.\n");
320 codeBlock->dontJITAnytimeSoon();
321 return false;
322 case CompilationSuccessful:
323 if (Options::verboseOSR())
324 dataLogF(" JIT compilation successful.\n");
325 codeBlock->install();
326 codeBlock->jitSoon();
327 return true;
328 default:
329 RELEASE_ASSERT_NOT_REACHED();
330 return false;
331 }
332 }
333 default:
334 dataLog("Unexpected code block in LLInt: ", *codeBlock, "\n");
335 RELEASE_ASSERT_NOT_REACHED();
336 return false;
337 }
338 }
339
340 static SlowPathReturnType entryOSR(ExecState* exec, Instruction*, CodeBlock* codeBlock, const char *name, EntryKind kind)
341 {
342 if (Options::verboseOSR()) {
343 dataLog(
344 *codeBlock, ": Entered ", name, " with executeCounter = ",
345 codeBlock->llintExecuteCounter(), "\n");
346 }
347
348 if (!shouldJIT(exec)) {
349 codeBlock->dontJITAnytimeSoon();
350 LLINT_RETURN_TWO(0, 0);
351 }
352 if (!jitCompileAndSetHeuristics(codeBlock, exec))
353 LLINT_RETURN_TWO(0, 0);
354
355 if (kind == Prologue)
356 LLINT_RETURN_TWO(codeBlock->jitCode()->executableAddress(), 0);
357 ASSERT(kind == ArityCheck);
358 LLINT_RETURN_TWO(codeBlock->jitCode()->addressForCall(
359 *codeBlock->vm(), codeBlock->ownerExecutable(), MustCheckArity,
360 RegisterPreservationNotRequired).executableAddress(), 0);
361 }
362 #else // ENABLE(JIT)
363 static SlowPathReturnType entryOSR(ExecState* exec, Instruction*, CodeBlock* codeBlock, const char*, EntryKind)
364 {
365 codeBlock->dontJITAnytimeSoon();
366 LLINT_RETURN_TWO(0, exec);
367 }
368 #endif // ENABLE(JIT)
369
370 LLINT_SLOW_PATH_DECL(entry_osr)
371 {
372 return entryOSR(exec, pc, exec->codeBlock(), "entry_osr", Prologue);
373 }
374
375 LLINT_SLOW_PATH_DECL(entry_osr_function_for_call)
376 {
377 return entryOSR(exec, pc, jsCast<JSFunction*>(exec->callee())->jsExecutable()->codeBlockForCall(), "entry_osr_function_for_call", Prologue);
378 }
379
380 LLINT_SLOW_PATH_DECL(entry_osr_function_for_construct)
381 {
382 return entryOSR(exec, pc, jsCast<JSFunction*>(exec->callee())->jsExecutable()->codeBlockForConstruct(), "entry_osr_function_for_construct", Prologue);
383 }
384
385 LLINT_SLOW_PATH_DECL(entry_osr_function_for_call_arityCheck)
386 {
387 return entryOSR(exec, pc, jsCast<JSFunction*>(exec->callee())->jsExecutable()->codeBlockForCall(), "entry_osr_function_for_call_arityCheck", ArityCheck);
388 }
389
390 LLINT_SLOW_PATH_DECL(entry_osr_function_for_construct_arityCheck)
391 {
392 return entryOSR(exec, pc, jsCast<JSFunction*>(exec->callee())->jsExecutable()->codeBlockForConstruct(), "entry_osr_function_for_construct_arityCheck", ArityCheck);
393 }
394
395 LLINT_SLOW_PATH_DECL(loop_osr)
396 {
397 CodeBlock* codeBlock = exec->codeBlock();
398
399 #if ENABLE(JIT)
400 if (Options::verboseOSR()) {
401 dataLog(
402 *codeBlock, ": Entered loop_osr with executeCounter = ",
403 codeBlock->llintExecuteCounter(), "\n");
404 }
405
406 if (!shouldJIT(exec)) {
407 codeBlock->dontJITAnytimeSoon();
408 LLINT_RETURN_TWO(0, 0);
409 }
410
411 if (!jitCompileAndSetHeuristics(codeBlock, exec))
412 LLINT_RETURN_TWO(0, 0);
413
414 ASSERT(codeBlock->jitType() == JITCode::BaselineJIT);
415
416 Vector<BytecodeAndMachineOffset> map;
417 codeBlock->jitCodeMap()->decode(map);
418 BytecodeAndMachineOffset* mapping = binarySearch<BytecodeAndMachineOffset, unsigned>(map, map.size(), pc - codeBlock->instructions().begin(), BytecodeAndMachineOffset::getBytecodeIndex);
419 ASSERT(mapping);
420 ASSERT(mapping->m_bytecodeIndex == static_cast<unsigned>(pc - codeBlock->instructions().begin()));
421
422 void* jumpTarget = codeBlock->jitCode()->executableAddressAtOffset(mapping->m_machineCodeOffset);
423 ASSERT(jumpTarget);
424
425 LLINT_RETURN_TWO(jumpTarget, exec->topOfFrame());
426 #else // ENABLE(JIT)
427 UNUSED_PARAM(pc);
428 codeBlock->dontJITAnytimeSoon();
429 LLINT_RETURN_TWO(0, 0);
430 #endif // ENABLE(JIT)
431 }
432
433 LLINT_SLOW_PATH_DECL(replace)
434 {
435 CodeBlock* codeBlock = exec->codeBlock();
436
437 #if ENABLE(JIT)
438 if (Options::verboseOSR()) {
439 dataLog(
440 *codeBlock, ": Entered replace with executeCounter = ",
441 codeBlock->llintExecuteCounter(), "\n");
442 }
443
444 if (shouldJIT(exec))
445 jitCompileAndSetHeuristics(codeBlock, exec);
446 else
447 codeBlock->dontJITAnytimeSoon();
448 LLINT_END_IMPL();
449 #else // ENABLE(JIT)
450 codeBlock->dontJITAnytimeSoon();
451 LLINT_END_IMPL();
452 #endif // ENABLE(JIT)
453 }
454
455 LLINT_SLOW_PATH_DECL(stack_check)
456 {
457 LLINT_BEGIN();
458 #if LLINT_SLOW_PATH_TRACING
459 dataLogF("Checking stack height with exec = %p.\n", exec);
460 dataLogF("CodeBlock = %p.\n", exec->codeBlock());
461 dataLogF("Num callee registers = %u.\n", exec->codeBlock()->m_numCalleeRegisters);
462 dataLogF("Num vars = %u.\n", exec->codeBlock()->m_numVars);
463
464 #if ENABLE(JIT)
465 dataLogF("Current end is at %p.\n", exec->vm().stackLimit());
466 #else
467 dataLogF("Current end is at %p.\n", exec->vm().jsStackLimit());
468 #endif
469
470 #endif
471 // If the stack check succeeds and we don't need to throw the error, then
472 // we'll return 0 instead. The prologue will check for a non-zero value
473 // when determining whether to set the callFrame or not.
474
475 // For JIT enabled builds which uses the C stack, the stack is not growable.
476 // Hence, if we get here, then we know a stack overflow is imminent. So, just
477 // throw the StackOverflowError unconditionally.
478 #if !ENABLE(JIT)
479 ASSERT(!vm.interpreter->stack().containsAddress(exec->topOfFrame()));
480 if (LIKELY(vm.interpreter->stack().ensureCapacityFor(exec->topOfFrame())))
481 LLINT_RETURN_TWO(pc, 0);
482 #endif
483
484 vm.topCallFrame = exec;
485 ErrorHandlingScope errorScope(vm);
486 CommonSlowPaths::interpreterThrowInCaller(exec, createStackOverflowError(exec));
487 pc = returnToThrowForThrownException(exec);
488 LLINT_RETURN_TWO(pc, exec);
489 }
490
491 LLINT_SLOW_PATH_DECL(slow_path_create_lexical_environment)
492 {
493 LLINT_BEGIN();
494 #if LLINT_SLOW_PATH_TRACING
495 dataLogF("Creating an lexicalEnvironment, exec = %p!\n", exec);
496 #endif
497 int scopeReg = pc[2].u.operand;
498 JSScope* scope = exec->uncheckedR(scopeReg).Register::scope();
499 JSLexicalEnvironment* lexicalEnvironment = JSLexicalEnvironment::create(vm, exec, scope, exec->codeBlock());
500 LLINT_RETURN(JSValue(lexicalEnvironment));
501 }
502
503 LLINT_SLOW_PATH_DECL(slow_path_new_object)
504 {
505 LLINT_BEGIN();
506 LLINT_RETURN(constructEmptyObject(exec, pc[3].u.objectAllocationProfile->structure()));
507 }
508
509 LLINT_SLOW_PATH_DECL(slow_path_new_array)
510 {
511 LLINT_BEGIN();
512 LLINT_RETURN(constructArrayNegativeIndexed(exec, pc[4].u.arrayAllocationProfile, bitwise_cast<JSValue*>(&LLINT_OP(2)), pc[3].u.operand));
513 }
514
515 LLINT_SLOW_PATH_DECL(slow_path_new_array_with_size)
516 {
517 LLINT_BEGIN();
518 LLINT_RETURN(constructArrayWithSizeQuirk(exec, pc[3].u.arrayAllocationProfile, exec->lexicalGlobalObject(), LLINT_OP_C(2).jsValue()));
519 }
520
521 LLINT_SLOW_PATH_DECL(slow_path_new_array_buffer)
522 {
523 LLINT_BEGIN();
524 LLINT_RETURN(constructArray(exec, pc[4].u.arrayAllocationProfile, exec->codeBlock()->constantBuffer(pc[2].u.operand), pc[3].u.operand));
525 }
526
527 LLINT_SLOW_PATH_DECL(slow_path_new_regexp)
528 {
529 LLINT_BEGIN();
530 RegExp* regExp = exec->codeBlock()->regexp(pc[2].u.operand);
531 if (!regExp->isValid())
532 LLINT_THROW(createSyntaxError(exec, "Invalid flag supplied to RegExp constructor."));
533 LLINT_RETURN(RegExpObject::create(vm, exec->lexicalGlobalObject()->regExpStructure(), regExp));
534 }
535
536 LLINT_SLOW_PATH_DECL(slow_path_check_has_instance)
537 {
538 LLINT_BEGIN();
539
540 JSValue value = LLINT_OP_C(2).jsValue();
541 JSValue baseVal = LLINT_OP_C(3).jsValue();
542 if (baseVal.isObject()) {
543 JSObject* baseObject = asObject(baseVal);
544 ASSERT(!baseObject->structure()->typeInfo().implementsDefaultHasInstance());
545 if (baseObject->structure()->typeInfo().implementsHasInstance()) {
546 JSValue result = jsBoolean(baseObject->methodTable()->customHasInstance(baseObject, exec, value));
547 LLINT_RETURN_WITH_PC_ADJUSTMENT(result, pc[4].u.operand);
548 }
549 }
550 LLINT_THROW(createInvalidInstanceofParameterError(exec, baseVal));
551 }
552
553 LLINT_SLOW_PATH_DECL(slow_path_instanceof)
554 {
555 LLINT_BEGIN();
556 JSValue value = LLINT_OP_C(2).jsValue();
557 JSValue proto = LLINT_OP_C(3).jsValue();
558 ASSERT(!value.isObject() || !proto.isObject());
559 LLINT_RETURN(jsBoolean(JSObject::defaultHasInstance(exec, value, proto)));
560 }
561
562 LLINT_SLOW_PATH_DECL(slow_path_get_by_id)
563 {
564 LLINT_BEGIN();
565 CodeBlock* codeBlock = exec->codeBlock();
566 const Identifier& ident = codeBlock->identifier(pc[3].u.operand);
567 JSValue baseValue = LLINT_OP_C(2).jsValue();
568 PropertySlot slot(baseValue);
569
570 JSValue result = baseValue.get(exec, ident, slot);
571 LLINT_CHECK_EXCEPTION();
572 LLINT_OP(1) = result;
573
574 if (!LLINT_ALWAYS_ACCESS_SLOW
575 && baseValue.isCell()
576 && slot.isCacheable()
577 && slot.slotBase() == baseValue
578 && slot.isCacheableValue()) {
579
580 JSCell* baseCell = baseValue.asCell();
581 Structure* structure = baseCell->structure();
582
583 if (!structure->isUncacheableDictionary()
584 && !structure->typeInfo().prohibitsPropertyCaching()
585 && !structure->typeInfo().newImpurePropertyFiresWatchpoints()) {
586 ConcurrentJITLocker locker(codeBlock->m_lock);
587
588 pc[4].u.structure.set(
589 vm, codeBlock->ownerExecutable(), structure);
590 if (isInlineOffset(slot.cachedOffset())) {
591 pc[0].u.opcode = LLInt::getOpcode(op_get_by_id);
592 pc[5].u.operand = offsetInInlineStorage(slot.cachedOffset()) * sizeof(JSValue) + JSObject::offsetOfInlineStorage();
593 } else {
594 pc[0].u.opcode = LLInt::getOpcode(op_get_by_id_out_of_line);
595 pc[5].u.operand = offsetInButterfly(slot.cachedOffset()) * sizeof(JSValue);
596 }
597 }
598 }
599
600 if (!LLINT_ALWAYS_ACCESS_SLOW
601 && isJSArray(baseValue)
602 && ident == exec->propertyNames().length) {
603 pc[0].u.opcode = LLInt::getOpcode(op_get_array_length);
604 ArrayProfile* arrayProfile = codeBlock->getOrAddArrayProfile(pc - codeBlock->instructions().begin());
605 arrayProfile->observeStructure(baseValue.asCell()->structure());
606 pc[4].u.arrayProfile = arrayProfile;
607 }
608
609 pc[OPCODE_LENGTH(op_get_by_id) - 1].u.profile->m_buckets[0] = JSValue::encode(result);
610 LLINT_END();
611 }
612
613 LLINT_SLOW_PATH_DECL(slow_path_get_arguments_length)
614 {
615 LLINT_BEGIN();
616 CodeBlock* codeBlock = exec->codeBlock();
617 const Identifier& ident = codeBlock->identifier(pc[3].u.operand);
618 JSValue baseValue = LLINT_OP(2).jsValue();
619 PropertySlot slot(baseValue);
620 LLINT_RETURN(baseValue.get(exec, ident, slot));
621 }
622
623 LLINT_SLOW_PATH_DECL(slow_path_put_by_id)
624 {
625 LLINT_BEGIN();
626 CodeBlock* codeBlock = exec->codeBlock();
627 const Identifier& ident = codeBlock->identifier(pc[2].u.operand);
628
629 JSValue baseValue = LLINT_OP_C(1).jsValue();
630 PutPropertySlot slot(baseValue, codeBlock->isStrictMode(), codeBlock->putByIdContext());
631 if (pc[8].u.operand)
632 asObject(baseValue)->putDirect(vm, ident, LLINT_OP_C(3).jsValue(), slot);
633 else
634 baseValue.put(exec, ident, LLINT_OP_C(3).jsValue(), slot);
635 LLINT_CHECK_EXCEPTION();
636
637 if (!LLINT_ALWAYS_ACCESS_SLOW
638 && baseValue.isCell()
639 && slot.isCacheablePut()) {
640
641 JSCell* baseCell = baseValue.asCell();
642 Structure* structure = baseCell->structure();
643
644 if (!structure->isUncacheableDictionary()
645 && !structure->typeInfo().prohibitsPropertyCaching()
646 && baseCell == slot.base()) {
647
648 if (slot.type() == PutPropertySlot::NewProperty) {
649 GCSafeConcurrentJITLocker locker(codeBlock->m_lock, vm.heap);
650
651 if (!structure->isDictionary() && structure->previousID()->outOfLineCapacity() == structure->outOfLineCapacity()) {
652 ASSERT(structure->previousID()->transitionWatchpointSetHasBeenInvalidated());
653
654 // This is needed because some of the methods we call
655 // below may GC.
656 pc[0].u.opcode = LLInt::getOpcode(op_put_by_id);
657
658 if (normalizePrototypeChain(exec, structure) != InvalidPrototypeChain) {
659 ASSERT(structure->previousID()->isObject());
660 pc[4].u.structure.set(
661 vm, codeBlock->ownerExecutable(), structure->previousID());
662 if (isInlineOffset(slot.cachedOffset()))
663 pc[5].u.operand = offsetInInlineStorage(slot.cachedOffset()) * sizeof(JSValue) + JSObject::offsetOfInlineStorage();
664 else
665 pc[5].u.operand = offsetInButterfly(slot.cachedOffset()) * sizeof(JSValue);
666 pc[6].u.structure.set(
667 vm, codeBlock->ownerExecutable(), structure);
668 StructureChain* chain = structure->prototypeChain(exec);
669 ASSERT(chain);
670 pc[7].u.structureChain.set(
671 vm, codeBlock->ownerExecutable(), chain);
672
673 if (pc[8].u.operand) {
674 if (isInlineOffset(slot.cachedOffset()))
675 pc[0].u.opcode = LLInt::getOpcode(op_put_by_id_transition_direct);
676 else
677 pc[0].u.opcode = LLInt::getOpcode(op_put_by_id_transition_direct_out_of_line);
678 } else {
679 if (isInlineOffset(slot.cachedOffset()))
680 pc[0].u.opcode = LLInt::getOpcode(op_put_by_id_transition_normal);
681 else
682 pc[0].u.opcode = LLInt::getOpcode(op_put_by_id_transition_normal_out_of_line);
683 }
684 }
685 }
686 } else {
687 structure->didCachePropertyReplacement(vm, slot.cachedOffset());
688 pc[4].u.structure.set(
689 vm, codeBlock->ownerExecutable(), structure);
690 if (isInlineOffset(slot.cachedOffset())) {
691 pc[0].u.opcode = LLInt::getOpcode(op_put_by_id);
692 pc[5].u.operand = offsetInInlineStorage(slot.cachedOffset()) * sizeof(JSValue) + JSObject::offsetOfInlineStorage();
693 } else {
694 pc[0].u.opcode = LLInt::getOpcode(op_put_by_id_out_of_line);
695 pc[5].u.operand = offsetInButterfly(slot.cachedOffset()) * sizeof(JSValue);
696 }
697 }
698 }
699 }
700
701 LLINT_END();
702 }
703
704 LLINT_SLOW_PATH_DECL(slow_path_del_by_id)
705 {
706 LLINT_BEGIN();
707 CodeBlock* codeBlock = exec->codeBlock();
708 JSObject* baseObject = LLINT_OP_C(2).jsValue().toObject(exec);
709 bool couldDelete = baseObject->methodTable()->deleteProperty(baseObject, exec, codeBlock->identifier(pc[3].u.operand));
710 LLINT_CHECK_EXCEPTION();
711 if (!couldDelete && codeBlock->isStrictMode())
712 LLINT_THROW(createTypeError(exec, "Unable to delete property."));
713 LLINT_RETURN(jsBoolean(couldDelete));
714 }
715
716 inline JSValue getByVal(ExecState* exec, JSValue baseValue, JSValue subscript)
717 {
718 if (LIKELY(baseValue.isCell() && subscript.isString())) {
719 VM& vm = exec->vm();
720 Structure& structure = *baseValue.asCell()->structure(vm);
721 if (JSCell::canUseFastGetOwnProperty(structure)) {
722 if (RefPtr<AtomicStringImpl> existingAtomicString = asString(subscript)->toExistingAtomicString(exec)) {
723 if (JSValue result = baseValue.asCell()->fastGetOwnProperty(vm, structure, existingAtomicString.get()))
724 return result;
725 }
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 baseValue.requireObjectCoercible(exec);
738 if (exec->hadException())
739 return jsUndefined();
740 auto property = subscript.toPropertyKey(exec);
741 if (exec->hadException())
742 return jsUndefined();
743 return baseValue.get(exec, property);
744 }
745
746 LLINT_SLOW_PATH_DECL(slow_path_get_by_val)
747 {
748 LLINT_BEGIN();
749 LLINT_RETURN_PROFILED(op_get_by_val, getByVal(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue()));
750 }
751
752 LLINT_SLOW_PATH_DECL(slow_path_put_by_val)
753 {
754 LLINT_BEGIN();
755
756 JSValue baseValue = LLINT_OP_C(1).jsValue();
757 JSValue subscript = LLINT_OP_C(2).jsValue();
758 JSValue value = LLINT_OP_C(3).jsValue();
759
760 if (LIKELY(subscript.isUInt32())) {
761 uint32_t i = subscript.asUInt32();
762 if (baseValue.isObject()) {
763 JSObject* object = asObject(baseValue);
764 if (object->canSetIndexQuickly(i))
765 object->setIndexQuickly(vm, i, value);
766 else
767 object->methodTable()->putByIndex(object, exec, i, value, exec->codeBlock()->isStrictMode());
768 LLINT_END();
769 }
770 baseValue.putByIndex(exec, i, value, exec->codeBlock()->isStrictMode());
771 LLINT_END();
772 }
773
774 auto property = subscript.toPropertyKey(exec);
775 LLINT_CHECK_EXCEPTION();
776 PutPropertySlot slot(baseValue, exec->codeBlock()->isStrictMode());
777 baseValue.put(exec, property, value, slot);
778 LLINT_END();
779 }
780
781 LLINT_SLOW_PATH_DECL(slow_path_put_by_val_direct)
782 {
783 LLINT_BEGIN();
784
785 JSValue baseValue = LLINT_OP_C(1).jsValue();
786 JSValue subscript = LLINT_OP_C(2).jsValue();
787 JSValue value = LLINT_OP_C(3).jsValue();
788 RELEASE_ASSERT(baseValue.isObject());
789 JSObject* baseObject = asObject(baseValue);
790 bool isStrictMode = exec->codeBlock()->isStrictMode();
791 if (LIKELY(subscript.isUInt32())) {
792 // Despite its name, JSValue::isUInt32 will return true only for positive boxed int32_t; all those values are valid array indices.
793 ASSERT(isIndex(subscript.asUInt32()));
794 baseObject->putDirectIndex(exec, subscript.asUInt32(), value, 0, isStrictMode ? PutDirectIndexShouldThrow : PutDirectIndexShouldNotThrow);
795 LLINT_END();
796 }
797
798 if (subscript.isDouble()) {
799 double subscriptAsDouble = subscript.asDouble();
800 uint32_t subscriptAsUInt32 = static_cast<uint32_t>(subscriptAsDouble);
801 if (subscriptAsDouble == subscriptAsUInt32 && isIndex(subscriptAsUInt32)) {
802 baseObject->putDirectIndex(exec, subscriptAsUInt32, value, 0, isStrictMode ? PutDirectIndexShouldThrow : PutDirectIndexShouldNotThrow);
803 LLINT_END();
804 }
805 }
806
807 // Don't put to an object if toString threw an exception.
808 auto property = subscript.toPropertyKey(exec);
809 if (exec->vm().exception())
810 LLINT_END();
811
812 if (Optional<uint32_t> index = parseIndex(property))
813 baseObject->putDirectIndex(exec, index.value(), value, 0, isStrictMode ? PutDirectIndexShouldThrow : PutDirectIndexShouldNotThrow);
814 else {
815 PutPropertySlot slot(baseObject, isStrictMode);
816 baseObject->putDirect(exec->vm(), property, value, slot);
817 }
818 LLINT_END();
819 }
820
821 LLINT_SLOW_PATH_DECL(slow_path_del_by_val)
822 {
823 LLINT_BEGIN();
824 JSValue baseValue = LLINT_OP_C(2).jsValue();
825 JSObject* baseObject = baseValue.toObject(exec);
826
827 JSValue subscript = LLINT_OP_C(3).jsValue();
828
829 bool couldDelete;
830
831 uint32_t i;
832 if (subscript.getUInt32(i))
833 couldDelete = baseObject->methodTable()->deletePropertyByIndex(baseObject, exec, i);
834 else {
835 LLINT_CHECK_EXCEPTION();
836 auto property = subscript.toPropertyKey(exec);
837 LLINT_CHECK_EXCEPTION();
838 couldDelete = baseObject->methodTable()->deleteProperty(baseObject, exec, property);
839 }
840
841 if (!couldDelete && exec->codeBlock()->isStrictMode())
842 LLINT_THROW(createTypeError(exec, "Unable to delete property."));
843
844 LLINT_RETURN(jsBoolean(couldDelete));
845 }
846
847 LLINT_SLOW_PATH_DECL(slow_path_put_by_index)
848 {
849 LLINT_BEGIN();
850 JSValue arrayValue = LLINT_OP_C(1).jsValue();
851 ASSERT(isJSArray(arrayValue));
852 asArray(arrayValue)->putDirectIndex(exec, pc[2].u.operand, LLINT_OP_C(3).jsValue());
853 LLINT_END();
854 }
855
856 LLINT_SLOW_PATH_DECL(slow_path_put_getter_by_id)
857 {
858 LLINT_BEGIN();
859 ASSERT(LLINT_OP(1).jsValue().isObject());
860 JSObject* baseObj = asObject(LLINT_OP(1).jsValue());
861
862 JSValue getter = LLINT_OP(3).jsValue();
863 ASSERT(getter.isObject());
864
865 baseObj->putGetter(exec, exec->codeBlock()->identifier(pc[2].u.operand), asObject(getter));
866 LLINT_END();
867 }
868
869 LLINT_SLOW_PATH_DECL(slow_path_put_setter_by_id)
870 {
871 LLINT_BEGIN();
872 ASSERT(LLINT_OP(1).jsValue().isObject());
873 JSObject* baseObj = asObject(LLINT_OP(1).jsValue());
874
875 JSValue setter = LLINT_OP(3).jsValue();
876 ASSERT(setter.isObject());
877
878 baseObj->putSetter(exec, exec->codeBlock()->identifier(pc[2].u.operand), asObject(setter));
879 LLINT_END();
880 }
881
882 LLINT_SLOW_PATH_DECL(slow_path_put_getter_setter)
883 {
884 LLINT_BEGIN();
885 ASSERT(LLINT_OP(1).jsValue().isObject());
886 JSObject* baseObj = asObject(LLINT_OP(1).jsValue());
887
888 GetterSetter* accessor = GetterSetter::create(vm, exec->lexicalGlobalObject());
889 LLINT_CHECK_EXCEPTION();
890
891 JSValue getter = LLINT_OP(3).jsValue();
892 JSValue setter = LLINT_OP(4).jsValue();
893 ASSERT(getter.isObject() || getter.isUndefined());
894 ASSERT(setter.isObject() || setter.isUndefined());
895 ASSERT(getter.isObject() || setter.isObject());
896
897 if (!getter.isUndefined())
898 accessor->setGetter(vm, exec->lexicalGlobalObject(), asObject(getter));
899 if (!setter.isUndefined())
900 accessor->setSetter(vm, exec->lexicalGlobalObject(), asObject(setter));
901 baseObj->putDirectAccessor(
902 exec,
903 exec->codeBlock()->identifier(pc[2].u.operand),
904 accessor, Accessor);
905 LLINT_END();
906 }
907
908 LLINT_SLOW_PATH_DECL(slow_path_jtrue)
909 {
910 LLINT_BEGIN();
911 LLINT_BRANCH(op_jtrue, LLINT_OP_C(1).jsValue().toBoolean(exec));
912 }
913
914 LLINT_SLOW_PATH_DECL(slow_path_jfalse)
915 {
916 LLINT_BEGIN();
917 LLINT_BRANCH(op_jfalse, !LLINT_OP_C(1).jsValue().toBoolean(exec));
918 }
919
920 LLINT_SLOW_PATH_DECL(slow_path_jless)
921 {
922 LLINT_BEGIN();
923 LLINT_BRANCH(op_jless, jsLess<true>(exec, LLINT_OP_C(1).jsValue(), LLINT_OP_C(2).jsValue()));
924 }
925
926 LLINT_SLOW_PATH_DECL(slow_path_jnless)
927 {
928 LLINT_BEGIN();
929 LLINT_BRANCH(op_jnless, !jsLess<true>(exec, LLINT_OP_C(1).jsValue(), LLINT_OP_C(2).jsValue()));
930 }
931
932 LLINT_SLOW_PATH_DECL(slow_path_jgreater)
933 {
934 LLINT_BEGIN();
935 LLINT_BRANCH(op_jgreater, jsLess<false>(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(1).jsValue()));
936 }
937
938 LLINT_SLOW_PATH_DECL(slow_path_jngreater)
939 {
940 LLINT_BEGIN();
941 LLINT_BRANCH(op_jngreater, !jsLess<false>(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(1).jsValue()));
942 }
943
944 LLINT_SLOW_PATH_DECL(slow_path_jlesseq)
945 {
946 LLINT_BEGIN();
947 LLINT_BRANCH(op_jlesseq, jsLessEq<true>(exec, LLINT_OP_C(1).jsValue(), LLINT_OP_C(2).jsValue()));
948 }
949
950 LLINT_SLOW_PATH_DECL(slow_path_jnlesseq)
951 {
952 LLINT_BEGIN();
953 LLINT_BRANCH(op_jnlesseq, !jsLessEq<true>(exec, LLINT_OP_C(1).jsValue(), LLINT_OP_C(2).jsValue()));
954 }
955
956 LLINT_SLOW_PATH_DECL(slow_path_jgreatereq)
957 {
958 LLINT_BEGIN();
959 LLINT_BRANCH(op_jgreatereq, jsLessEq<false>(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(1).jsValue()));
960 }
961
962 LLINT_SLOW_PATH_DECL(slow_path_jngreatereq)
963 {
964 LLINT_BEGIN();
965 LLINT_BRANCH(op_jngreatereq, !jsLessEq<false>(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(1).jsValue()));
966 }
967
968 LLINT_SLOW_PATH_DECL(slow_path_switch_imm)
969 {
970 LLINT_BEGIN();
971 JSValue scrutinee = LLINT_OP_C(3).jsValue();
972 ASSERT(scrutinee.isDouble());
973 double value = scrutinee.asDouble();
974 int32_t intValue = static_cast<int32_t>(value);
975 int defaultOffset = pc[2].u.operand;
976 if (value == intValue) {
977 CodeBlock* codeBlock = exec->codeBlock();
978 pc += codeBlock->switchJumpTable(pc[1].u.operand).offsetForValue(intValue, defaultOffset);
979 } else
980 pc += defaultOffset;
981 LLINT_END();
982 }
983
984 LLINT_SLOW_PATH_DECL(slow_path_switch_char)
985 {
986 LLINT_BEGIN();
987 JSValue scrutinee = LLINT_OP_C(3).jsValue();
988 ASSERT(scrutinee.isString());
989 JSString* string = asString(scrutinee);
990 ASSERT(string->length() == 1);
991 int defaultOffset = pc[2].u.operand;
992 StringImpl* impl = string->value(exec).impl();
993 CodeBlock* codeBlock = exec->codeBlock();
994 pc += codeBlock->switchJumpTable(pc[1].u.operand).offsetForValue((*impl)[0], defaultOffset);
995 LLINT_END();
996 }
997
998 LLINT_SLOW_PATH_DECL(slow_path_switch_string)
999 {
1000 LLINT_BEGIN();
1001 JSValue scrutinee = LLINT_OP_C(3).jsValue();
1002 int defaultOffset = pc[2].u.operand;
1003 if (!scrutinee.isString())
1004 pc += defaultOffset;
1005 else {
1006 CodeBlock* codeBlock = exec->codeBlock();
1007 pc += codeBlock->stringSwitchJumpTable(pc[1].u.operand).offsetForValue(asString(scrutinee)->value(exec).impl(), defaultOffset);
1008 }
1009 LLINT_END();
1010 }
1011
1012 LLINT_SLOW_PATH_DECL(slow_path_new_func)
1013 {
1014 LLINT_BEGIN();
1015 CodeBlock* codeBlock = exec->codeBlock();
1016 ASSERT(codeBlock->codeType() != FunctionCode || !codeBlock->needsActivation() || exec->hasActivation());
1017 JSScope* scope = exec->uncheckedR(pc[2].u.operand).Register::scope();
1018 #if LLINT_SLOW_PATH_TRACING
1019 dataLogF("Creating function!\n");
1020 #endif
1021 LLINT_RETURN(JSFunction::create(vm, codeBlock->functionDecl(pc[3].u.operand), scope));
1022 }
1023
1024 LLINT_SLOW_PATH_DECL(slow_path_new_func_exp)
1025 {
1026 LLINT_BEGIN();
1027 CodeBlock* codeBlock = exec->codeBlock();
1028 JSScope* scope = exec->uncheckedR(pc[2].u.operand).Register::scope();
1029 FunctionExecutable* function = codeBlock->functionExpr(pc[3].u.operand);
1030 JSFunction* func = JSFunction::create(vm, function, scope);
1031
1032 LLINT_RETURN(func);
1033 }
1034
1035 static SlowPathReturnType handleHostCall(ExecState* execCallee, Instruction* pc, JSValue callee, CodeSpecializationKind kind)
1036 {
1037 UNUSED_PARAM(pc);
1038
1039 #if LLINT_SLOW_PATH_TRACING
1040 dataLog("Performing host call.\n");
1041 #endif
1042
1043 ExecState* exec = execCallee->callerFrame();
1044 VM& vm = exec->vm();
1045
1046 execCallee->setCodeBlock(0);
1047 execCallee->clearReturnPC();
1048
1049 if (kind == CodeForCall) {
1050 CallData callData;
1051 CallType callType = getCallData(callee, callData);
1052
1053 ASSERT(callType != CallTypeJS);
1054
1055 if (callType == CallTypeHost) {
1056 NativeCallFrameTracer tracer(&vm, execCallee);
1057 execCallee->setCallee(asObject(callee));
1058 vm.hostCallReturnValue = JSValue::decode(callData.native.function(execCallee));
1059
1060 LLINT_CALL_RETURN(execCallee, execCallee, LLInt::getCodePtr(getHostCallReturnValue));
1061 }
1062
1063 #if LLINT_SLOW_PATH_TRACING
1064 dataLog("Call callee is not a function: ", callee, "\n");
1065 #endif
1066
1067 ASSERT(callType == CallTypeNone);
1068 LLINT_CALL_THROW(exec, createNotAFunctionError(exec, callee));
1069 }
1070
1071 ASSERT(kind == CodeForConstruct);
1072
1073 ConstructData constructData;
1074 ConstructType constructType = getConstructData(callee, constructData);
1075
1076 ASSERT(constructType != ConstructTypeJS);
1077
1078 if (constructType == ConstructTypeHost) {
1079 NativeCallFrameTracer tracer(&vm, execCallee);
1080 execCallee->setCallee(asObject(callee));
1081 vm.hostCallReturnValue = JSValue::decode(constructData.native.function(execCallee));
1082
1083 LLINT_CALL_RETURN(execCallee, execCallee, LLInt::getCodePtr(getHostCallReturnValue));
1084 }
1085
1086 #if LLINT_SLOW_PATH_TRACING
1087 dataLog("Constructor callee is not a function: ", callee, "\n");
1088 #endif
1089
1090 ASSERT(constructType == ConstructTypeNone);
1091 LLINT_CALL_THROW(exec, createNotAConstructorError(exec, callee));
1092 }
1093
1094 inline SlowPathReturnType setUpCall(ExecState* execCallee, Instruction* pc, CodeSpecializationKind kind, JSValue calleeAsValue, LLIntCallLinkInfo* callLinkInfo = 0)
1095 {
1096 ExecState* exec = execCallee->callerFrame();
1097
1098 #if LLINT_SLOW_PATH_TRACING
1099 dataLogF("Performing call with recorded PC = %p\n", exec->currentVPC());
1100 #endif
1101
1102 JSCell* calleeAsFunctionCell = getJSFunction(calleeAsValue);
1103 if (!calleeAsFunctionCell)
1104 return handleHostCall(execCallee, pc, calleeAsValue, kind);
1105
1106 JSFunction* callee = jsCast<JSFunction*>(calleeAsFunctionCell);
1107 JSScope* scope = callee->scopeUnchecked();
1108 VM& vm = *scope->vm();
1109 ExecutableBase* executable = callee->executable();
1110
1111 MacroAssemblerCodePtr codePtr;
1112 CodeBlock* codeBlock = 0;
1113 if (executable->isHostFunction())
1114 codePtr = executable->entrypointFor(vm, kind, MustCheckArity, RegisterPreservationNotRequired);
1115 else {
1116 FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable);
1117
1118 if (!isCall(kind) && functionExecutable->isBuiltinFunction())
1119 LLINT_CALL_THROW(exec, createNotAConstructorError(exec, callee));
1120
1121 JSObject* error = functionExecutable->prepareForExecution(execCallee, callee, scope, kind);
1122 if (error)
1123 LLINT_CALL_THROW(exec, error);
1124 codeBlock = functionExecutable->codeBlockFor(kind);
1125 ASSERT(codeBlock);
1126 ArityCheckMode arity;
1127 if (execCallee->argumentCountIncludingThis() < static_cast<size_t>(codeBlock->numParameters()))
1128 arity = MustCheckArity;
1129 else
1130 arity = ArityCheckNotRequired;
1131 codePtr = functionExecutable->entrypointFor(vm, kind, arity, RegisterPreservationNotRequired);
1132 }
1133
1134 ASSERT(!!codePtr);
1135
1136 if (!LLINT_ALWAYS_ACCESS_SLOW && callLinkInfo) {
1137 CodeBlock* callerCodeBlock = exec->codeBlock();
1138
1139 ConcurrentJITLocker locker(callerCodeBlock->m_lock);
1140
1141 if (callLinkInfo->isOnList())
1142 callLinkInfo->remove();
1143 callLinkInfo->callee.set(vm, callerCodeBlock->ownerExecutable(), callee);
1144 callLinkInfo->lastSeenCallee.set(vm, callerCodeBlock->ownerExecutable(), callee);
1145 callLinkInfo->machineCodeTarget = codePtr;
1146 if (codeBlock)
1147 codeBlock->linkIncomingCall(exec, callLinkInfo);
1148 }
1149
1150 LLINT_CALL_RETURN(exec, execCallee, codePtr.executableAddress());
1151 }
1152
1153 inline SlowPathReturnType genericCall(ExecState* exec, Instruction* pc, CodeSpecializationKind kind)
1154 {
1155 // This needs to:
1156 // - Set up a call frame.
1157 // - Figure out what to call and compile it if necessary.
1158 // - If possible, link the call's inline cache.
1159 // - Return a tuple of machine code address to call and the new call frame.
1160
1161 JSValue calleeAsValue = LLINT_OP_C(2).jsValue();
1162
1163 ExecState* execCallee = exec - pc[4].u.operand;
1164
1165 execCallee->setArgumentCountIncludingThis(pc[3].u.operand);
1166 execCallee->uncheckedR(JSStack::Callee) = calleeAsValue;
1167 execCallee->setCallerFrame(exec);
1168
1169 ASSERT(pc[5].u.callLinkInfo);
1170 return setUpCall(execCallee, pc, kind, calleeAsValue, pc[5].u.callLinkInfo);
1171 }
1172
1173 LLINT_SLOW_PATH_DECL(slow_path_call)
1174 {
1175 LLINT_BEGIN_NO_SET_PC();
1176 return genericCall(exec, pc, CodeForCall);
1177 }
1178
1179 LLINT_SLOW_PATH_DECL(slow_path_construct)
1180 {
1181 LLINT_BEGIN_NO_SET_PC();
1182 return genericCall(exec, pc, CodeForConstruct);
1183 }
1184
1185 LLINT_SLOW_PATH_DECL(slow_path_size_frame_for_varargs)
1186 {
1187 LLINT_BEGIN();
1188 // This needs to:
1189 // - Set up a call frame while respecting the variable arguments.
1190
1191 unsigned numUsedStackSlots = -pc[5].u.operand;
1192 unsigned length = sizeFrameForVarargs(exec, &vm.interpreter->stack(),
1193 LLINT_OP_C(4).jsValue(), numUsedStackSlots, pc[6].u.operand);
1194 LLINT_CALL_CHECK_EXCEPTION(exec, exec);
1195
1196 ExecState* execCallee = calleeFrameForVarargs(exec, numUsedStackSlots, length + 1);
1197 vm.varargsLength = length;
1198 vm.newCallFrameReturnValue = execCallee;
1199
1200 LLINT_RETURN_CALLEE_FRAME(execCallee);
1201 }
1202
1203 LLINT_SLOW_PATH_DECL(slow_path_call_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 setupVarargsFrameAndSetThis(exec, execCallee, LLINT_OP_C(3).jsValue(), LLINT_OP_C(4).jsValue(), pc[6].u.operand, vm.varargsLength);
1215 LLINT_CALL_CHECK_EXCEPTION(exec, exec);
1216
1217 execCallee->uncheckedR(JSStack::Callee) = calleeAsValue;
1218 execCallee->setCallerFrame(exec);
1219 exec->setCurrentVPC(pc);
1220
1221 return setUpCall(execCallee, pc, CodeForCall, calleeAsValue);
1222 }
1223
1224 LLINT_SLOW_PATH_DECL(slow_path_construct_varargs)
1225 {
1226 LLINT_BEGIN_NO_SET_PC();
1227 // This needs to:
1228 // - Figure out what to call and compile it if necessary.
1229 // - Return a tuple of machine code address to call and the new call frame.
1230
1231 JSValue calleeAsValue = LLINT_OP_C(2).jsValue();
1232
1233 ExecState* execCallee = vm.newCallFrameReturnValue;
1234
1235 setupVarargsFrameAndSetThis(exec, execCallee, LLINT_OP_C(3).jsValue(), LLINT_OP_C(4).jsValue(), pc[6].u.operand, vm.varargsLength);
1236 LLINT_CALL_CHECK_EXCEPTION(exec, exec);
1237
1238 execCallee->uncheckedR(JSStack::Callee) = calleeAsValue;
1239 execCallee->setCallerFrame(exec);
1240 exec->setCurrentVPC(pc);
1241
1242 return setUpCall(execCallee, pc, CodeForConstruct, calleeAsValue);
1243 }
1244
1245 LLINT_SLOW_PATH_DECL(slow_path_call_eval)
1246 {
1247 LLINT_BEGIN_NO_SET_PC();
1248 JSValue calleeAsValue = LLINT_OP(2).jsValue();
1249
1250 ExecState* execCallee = exec - pc[4].u.operand;
1251
1252 execCallee->setArgumentCountIncludingThis(pc[3].u.operand);
1253 execCallee->setCallerFrame(exec);
1254 execCallee->uncheckedR(JSStack::Callee) = calleeAsValue;
1255 execCallee->setReturnPC(LLInt::getCodePtr(llint_generic_return_point));
1256 execCallee->setCodeBlock(0);
1257 exec->setCurrentVPC(pc);
1258
1259 if (!isHostFunction(calleeAsValue, globalFuncEval))
1260 return setUpCall(execCallee, pc, CodeForCall, calleeAsValue);
1261
1262 vm.hostCallReturnValue = eval(execCallee);
1263 LLINT_CALL_RETURN(exec, execCallee, LLInt::getCodePtr(getHostCallReturnValue));
1264 }
1265
1266 LLINT_SLOW_PATH_DECL(slow_path_strcat)
1267 {
1268 LLINT_BEGIN();
1269 LLINT_RETURN(jsStringFromRegisterArray(exec, &LLINT_OP(2), pc[3].u.operand));
1270 }
1271
1272 LLINT_SLOW_PATH_DECL(slow_path_to_primitive)
1273 {
1274 LLINT_BEGIN();
1275 LLINT_RETURN(LLINT_OP_C(2).jsValue().toPrimitive(exec));
1276 }
1277
1278 LLINT_SLOW_PATH_DECL(slow_path_push_with_scope)
1279 {
1280 LLINT_BEGIN();
1281 JSValue v = LLINT_OP_C(2).jsValue();
1282 JSObject* o = v.toObject(exec);
1283 LLINT_CHECK_EXCEPTION();
1284
1285 int scopeReg = pc[1].u.operand;
1286 JSScope* currentScope = exec->uncheckedR(scopeReg).Register::scope();
1287 exec->uncheckedR(scopeReg) = JSWithScope::create(exec, o, currentScope);
1288
1289 LLINT_END();
1290 }
1291
1292 LLINT_SLOW_PATH_DECL(slow_path_pop_scope)
1293 {
1294 LLINT_BEGIN();
1295 int scopeReg = pc[1].u.operand;
1296 JSScope* scope = exec->uncheckedR(scopeReg).Register::scope();
1297 exec->uncheckedR(scopeReg) = scope->next();
1298 LLINT_END();
1299 }
1300
1301 LLINT_SLOW_PATH_DECL(slow_path_push_name_scope)
1302 {
1303 LLINT_BEGIN();
1304 int scopeReg = pc[1].u.operand;
1305 JSScope* currentScope = exec->uncheckedR(scopeReg).Register::scope();
1306 JSValue value = LLINT_OP_C(2).jsValue();
1307 SymbolTable* symbolTable = jsCast<SymbolTable*>(LLINT_OP_C(3).jsValue());
1308 JSNameScope::Type type = static_cast<JSNameScope::Type>(pc[4].u.operand);
1309 JSNameScope* scope = JSNameScope::create(vm, exec->lexicalGlobalObject(), currentScope, symbolTable, value, type);
1310 exec->uncheckedR(scopeReg) = scope;
1311 LLINT_END();
1312 }
1313
1314 LLINT_SLOW_PATH_DECL(slow_path_throw)
1315 {
1316 LLINT_BEGIN();
1317 LLINT_THROW(LLINT_OP_C(1).jsValue());
1318 }
1319
1320 LLINT_SLOW_PATH_DECL(slow_path_throw_static_error)
1321 {
1322 LLINT_BEGIN();
1323 JSValue errorMessageValue = LLINT_OP_C(1).jsValue();
1324 RELEASE_ASSERT(errorMessageValue.isString());
1325 String errorMessage = asString(errorMessageValue)->value(exec);
1326 if (pc[2].u.operand)
1327 LLINT_THROW(createReferenceError(exec, errorMessage));
1328 else
1329 LLINT_THROW(createTypeError(exec, errorMessage));
1330 }
1331
1332 LLINT_SLOW_PATH_DECL(slow_path_handle_watchdog_timer)
1333 {
1334 LLINT_BEGIN_NO_SET_PC();
1335 ASSERT(vm.watchdog);
1336 if (UNLIKELY(vm.watchdog->didFire(exec)))
1337 LLINT_THROW(createTerminatedExecutionException(&vm));
1338 LLINT_RETURN_TWO(0, exec);
1339 }
1340
1341 LLINT_SLOW_PATH_DECL(slow_path_debug)
1342 {
1343 LLINT_BEGIN();
1344 int debugHookID = pc[1].u.operand;
1345 vm.interpreter->debug(exec, static_cast<DebugHookID>(debugHookID));
1346
1347 LLINT_END();
1348 }
1349
1350 LLINT_SLOW_PATH_DECL(slow_path_profile_will_call)
1351 {
1352 LLINT_BEGIN();
1353 if (LegacyProfiler* profiler = vm.enabledProfiler())
1354 profiler->willExecute(exec, LLINT_OP(1).jsValue());
1355 LLINT_END();
1356 }
1357
1358 LLINT_SLOW_PATH_DECL(slow_path_profile_did_call)
1359 {
1360 LLINT_BEGIN();
1361 if (LegacyProfiler* profiler = vm.enabledProfiler())
1362 profiler->didExecute(exec, LLINT_OP(1).jsValue());
1363 LLINT_END();
1364 }
1365
1366 LLINT_SLOW_PATH_DECL(slow_path_handle_exception)
1367 {
1368 LLINT_BEGIN_NO_SET_PC();
1369 genericUnwind(&vm, exec);
1370 LLINT_END_IMPL();
1371 }
1372
1373 LLINT_SLOW_PATH_DECL(slow_path_resolve_scope)
1374 {
1375 LLINT_BEGIN();
1376 const Identifier& ident = exec->codeBlock()->identifier(pc[3].u.operand);
1377 JSScope* scope = LLINT_OP(2).Register::scope();
1378 LLINT_RETURN(JSScope::resolve(exec, scope, ident));
1379 }
1380
1381 LLINT_SLOW_PATH_DECL(slow_path_get_from_scope)
1382 {
1383 LLINT_BEGIN();
1384
1385 const Identifier& ident = exec->codeBlock()->identifier(pc[3].u.operand);
1386 JSObject* scope = jsCast<JSObject*>(LLINT_OP(2).jsValue());
1387 ResolveModeAndType modeAndType(pc[4].u.operand);
1388
1389 PropertySlot slot(scope);
1390 if (!scope->getPropertySlot(exec, ident, slot)) {
1391 if (modeAndType.mode() == ThrowIfNotFound)
1392 LLINT_RETURN(exec->vm().throwException(exec, createUndefinedVariableError(exec, ident)));
1393 LLINT_RETURN(jsUndefined());
1394 }
1395
1396 // Covers implicit globals. Since they don't exist until they first execute, we didn't know how to cache them at compile time.
1397 if (slot.isCacheableValue() && slot.slotBase() == scope && scope->structure()->propertyAccessesAreCacheable()) {
1398 if (modeAndType.type() == GlobalProperty || modeAndType.type() == GlobalPropertyWithVarInjectionChecks) {
1399 CodeBlock* codeBlock = exec->codeBlock();
1400 Structure* structure = scope->structure(vm);
1401 {
1402 ConcurrentJITLocker locker(codeBlock->m_lock);
1403 pc[5].u.structure.set(exec->vm(), codeBlock->ownerExecutable(), structure);
1404 pc[6].u.operand = slot.cachedOffset();
1405 }
1406 structure->startWatchingPropertyForReplacements(vm, slot.cachedOffset());
1407 }
1408 }
1409
1410 LLINT_RETURN(slot.getValue(exec, ident));
1411 }
1412
1413 LLINT_SLOW_PATH_DECL(slow_path_put_to_scope)
1414 {
1415 LLINT_BEGIN();
1416
1417 CodeBlock* codeBlock = exec->codeBlock();
1418 const Identifier& ident = codeBlock->identifier(pc[2].u.operand);
1419 JSObject* scope = jsCast<JSObject*>(LLINT_OP(1).jsValue());
1420 JSValue value = LLINT_OP_C(3).jsValue();
1421 ResolveModeAndType modeAndType = ResolveModeAndType(pc[4].u.operand);
1422 if (modeAndType.type() == LocalClosureVar) {
1423 JSLexicalEnvironment* environment = jsCast<JSLexicalEnvironment*>(scope);
1424 environment->variableAt(ScopeOffset(pc[6].u.operand)).set(vm, environment, value);
1425
1426 // Have to do this *after* the write, because if this puts the set into IsWatched, then we need
1427 // to have already changed the value of the variable. Otherwise we might watch and constant-fold
1428 // to the Undefined value from before the assignment.
1429 if (WatchpointSet* set = pc[5].u.watchpointSet)
1430 set->touch("Executed op_put_scope<LocalClosureVar>");
1431 LLINT_END();
1432 }
1433
1434 if (modeAndType.mode() == ThrowIfNotFound && !scope->hasProperty(exec, ident))
1435 LLINT_THROW(createUndefinedVariableError(exec, ident));
1436
1437 PutPropertySlot slot(scope, codeBlock->isStrictMode());
1438 scope->methodTable()->put(scope, exec, ident, value, slot);
1439
1440 CommonSlowPaths::tryCachePutToScopeGlobal(exec, codeBlock, pc, scope, modeAndType, slot);
1441
1442 LLINT_END();
1443 }
1444
1445 extern "C" SlowPathReturnType llint_throw_stack_overflow_error(VM* vm, ProtoCallFrame* protoFrame)
1446 {
1447 ExecState* exec = vm->topCallFrame;
1448 if (!exec)
1449 exec = protoFrame->callee()->globalObject()->globalExec();
1450 throwStackOverflowError(exec);
1451 return encodeResult(0, 0);
1452 }
1453
1454 #if !ENABLE(JIT)
1455 extern "C" SlowPathReturnType llint_stack_check_at_vm_entry(VM* vm, Register* newTopOfStack)
1456 {
1457 bool success = vm->interpreter->stack().ensureCapacityFor(newTopOfStack);
1458 return encodeResult(reinterpret_cast<void*>(success), 0);
1459 }
1460 #endif
1461
1462 extern "C" void llint_write_barrier_slow(ExecState* exec, JSCell* cell)
1463 {
1464 VM& vm = exec->vm();
1465 vm.heap.writeBarrier(cell);
1466 }
1467
1468 extern "C" NO_RETURN_DUE_TO_CRASH void llint_crash()
1469 {
1470 CRASH();
1471 }
1472
1473 } } // namespace JSC::LLInt