]> git.saurik.com Git - apple/javascriptcore.git/blame - llint/LLIntSlowPaths.cpp
JavaScriptCore-1097.3.3.tar.gz
[apple/javascriptcore.git] / llint / LLIntSlowPaths.cpp
CommitLineData
6fe7ccc8
A
1/*
2 * Copyright (C) 2011, 2012 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#if ENABLE(LLINT)
30
31#include "Arguments.h"
32#include "CallFrame.h"
33#include "CommonSlowPaths.h"
34#include "GetterSetter.h"
35#include "HostCallReturnValue.h"
36#include "Interpreter.h"
37#include "JIT.h"
38#include "JITDriver.h"
39#include "JSActivation.h"
40#include "JSGlobalObjectFunctions.h"
41#include "JSPropertyNameIterator.h"
42#include "JSStaticScopeObject.h"
43#include "JSString.h"
44#include "JSValue.h"
45#include "LLIntCommon.h"
46#include "LLIntExceptions.h"
47#include "LowLevelInterpreter.h"
48#include "Operations.h"
49
50namespace JSC { namespace LLInt {
51
52#define LLINT_BEGIN_NO_SET_PC() \
53 JSGlobalData& globalData = exec->globalData(); \
54 NativeCallFrameTracer tracer(&globalData, exec)
55
56#ifndef NDEBUG
57#define LLINT_SET_PC_FOR_STUBS() do { \
58 exec->codeBlock()->bytecodeOffset(pc); \
59 exec->setCurrentVPC(pc + 1); \
60 } while (false)
61#else
62#define LLINT_SET_PC_FOR_STUBS() do { \
63 exec->setCurrentVPC(pc + 1); \
64 } while (false)
65#endif
66
67#define LLINT_BEGIN() \
68 LLINT_BEGIN_NO_SET_PC(); \
69 LLINT_SET_PC_FOR_STUBS()
70
71#define LLINT_OP(index) (exec->uncheckedR(pc[index].u.operand))
72#define LLINT_OP_C(index) (exec->r(pc[index].u.operand))
73
74#define LLINT_RETURN_TWO(first, second) do { \
75 return encodeResult(first, second); \
76 } while (false)
77
78#define LLINT_END_IMPL() LLINT_RETURN_TWO(pc, exec)
79
80#define LLINT_THROW(exceptionToThrow) do { \
81 globalData.exception = (exceptionToThrow); \
82 pc = returnToThrow(exec, pc); \
83 LLINT_END_IMPL(); \
84 } while (false)
85
86#define LLINT_CHECK_EXCEPTION() do { \
87 if (UNLIKELY(globalData.exception)) { \
88 pc = returnToThrow(exec, pc); \
89 LLINT_END_IMPL(); \
90 } \
91 } while (false)
92
93#define LLINT_END() do { \
94 LLINT_CHECK_EXCEPTION(); \
95 LLINT_END_IMPL(); \
96 } while (false)
97
98#define LLINT_BRANCH(opcode, condition) do { \
99 bool __b_condition = (condition); \
100 LLINT_CHECK_EXCEPTION(); \
101 if (__b_condition) \
102 pc += pc[OPCODE_LENGTH(opcode) - 1].u.operand; \
103 else \
104 pc += OPCODE_LENGTH(opcode); \
105 LLINT_END_IMPL(); \
106 } while (false)
107
108#define LLINT_RETURN(value) do { \
109 JSValue __r_returnValue = (value); \
110 LLINT_CHECK_EXCEPTION(); \
111 LLINT_OP(1) = __r_returnValue; \
112 LLINT_END_IMPL(); \
113 } while (false)
114
115#if ENABLE(VALUE_PROFILER)
116#define LLINT_RETURN_PROFILED(opcode, value) do { \
117 JSValue __rp_returnValue = (value); \
118 LLINT_CHECK_EXCEPTION(); \
119 LLINT_OP(1) = __rp_returnValue; \
120 pc[OPCODE_LENGTH(opcode) - 1].u.profile->m_buckets[0] = \
121 JSValue::encode(__rp_returnValue); \
122 LLINT_END_IMPL(); \
123 } while (false)
124#else // ENABLE(VALUE_PROFILER)
125#define LLINT_RETURN_PROFILED(opcode, value) LLINT_RETURN(value)
126#endif // ENABLE(VALUE_PROFILER)
127
128#define LLINT_CALL_END_IMPL(exec, callTarget) LLINT_RETURN_TWO((callTarget), (exec))
129
130#define LLINT_CALL_THROW(exec, pc, exceptionToThrow) do { \
131 ExecState* __ct_exec = (exec); \
132 Instruction* __ct_pc = (pc); \
133 globalData.exception = (exceptionToThrow); \
134 LLINT_CALL_END_IMPL(__ct_exec, callToThrow(__ct_exec, __ct_pc)); \
135 } while (false)
136
137#define LLINT_CALL_CHECK_EXCEPTION(exec, pc) do { \
138 ExecState* __cce_exec = (exec); \
139 Instruction* __cce_pc = (pc); \
140 if (UNLIKELY(globalData.exception)) \
141 LLINT_CALL_END_IMPL(__cce_exec, callToThrow(__cce_exec, __cce_pc)); \
142 } while (false)
143
144#define LLINT_CALL_RETURN(exec, pc, callTarget) do { \
145 ExecState* __cr_exec = (exec); \
146 Instruction* __cr_pc = (pc); \
147 void* __cr_callTarget = (callTarget); \
148 LLINT_CALL_CHECK_EXCEPTION(__cr_exec->callerFrame(), __cr_pc); \
149 LLINT_CALL_END_IMPL(__cr_exec, __cr_callTarget); \
150 } while (false)
151
152extern "C" SlowPathReturnType llint_trace_operand(ExecState* exec, Instruction* pc, int fromWhere, int operand)
153{
154 LLINT_BEGIN();
155 dataLog("%p / %p: executing bc#%zu, op#%u: Trace(%d): %d: %d\n",
156 exec->codeBlock(),
157 exec,
158 static_cast<intptr_t>(pc - exec->codeBlock()->instructions().begin()),
159 exec->globalData().interpreter->getOpcodeID(pc[0].u.opcode),
160 fromWhere,
161 operand,
162 pc[operand].u.operand);
163 LLINT_END();
164}
165
166extern "C" SlowPathReturnType llint_trace_value(ExecState* exec, Instruction* pc, int fromWhere, int operand)
167{
168 JSValue value = LLINT_OP_C(operand).jsValue();
169 union {
170 struct {
171 uint32_t tag;
172 uint32_t payload;
173 } bits;
174 EncodedJSValue asValue;
175 } u;
176 u.asValue = JSValue::encode(value);
177 dataLog("%p / %p: executing bc#%zu, op#%u: Trace(%d): %d: %d: %08x:%08x: %s\n",
178 exec->codeBlock(),
179 exec,
180 static_cast<intptr_t>(pc - exec->codeBlock()->instructions().begin()),
181 exec->globalData().interpreter->getOpcodeID(pc[0].u.opcode),
182 fromWhere,
183 operand,
184 pc[operand].u.operand,
185 u.bits.tag,
186 u.bits.payload,
187 value.description());
188 LLINT_END_IMPL();
189}
190
191LLINT_SLOW_PATH_DECL(trace_prologue)
192{
193 dataLog("%p / %p: in prologue.\n", exec->codeBlock(), exec);
194 LLINT_END_IMPL();
195}
196
197static void traceFunctionPrologue(ExecState* exec, const char* comment, CodeSpecializationKind kind)
198{
199 JSFunction* callee = jsCast<JSFunction*>(exec->callee());
200 FunctionExecutable* executable = callee->jsExecutable();
201 CodeBlock* codeBlock = &executable->generatedBytecodeFor(kind);
202 dataLog("%p / %p: in %s of function %p, executable %p; numVars = %u, numParameters = %u, numCalleeRegisters = %u, caller = %p.\n",
203 codeBlock, exec, comment, callee, executable,
204 codeBlock->m_numVars, codeBlock->numParameters(), codeBlock->m_numCalleeRegisters,
205 exec->callerFrame());
206}
207
208LLINT_SLOW_PATH_DECL(trace_prologue_function_for_call)
209{
210 traceFunctionPrologue(exec, "call prologue", CodeForCall);
211 LLINT_END_IMPL();
212}
213
214LLINT_SLOW_PATH_DECL(trace_prologue_function_for_construct)
215{
216 traceFunctionPrologue(exec, "construct prologue", CodeForConstruct);
217 LLINT_END_IMPL();
218}
219
220LLINT_SLOW_PATH_DECL(trace_arityCheck_for_call)
221{
222 traceFunctionPrologue(exec, "call arity check", CodeForCall);
223 LLINT_END_IMPL();
224}
225
226LLINT_SLOW_PATH_DECL(trace_arityCheck_for_construct)
227{
228 traceFunctionPrologue(exec, "construct arity check", CodeForConstruct);
229 LLINT_END_IMPL();
230}
231
232LLINT_SLOW_PATH_DECL(trace)
233{
234 dataLog("%p / %p: executing bc#%zu, %s, scope %p\n",
235 exec->codeBlock(),
236 exec,
237 static_cast<intptr_t>(pc - exec->codeBlock()->instructions().begin()),
238 opcodeNames[exec->globalData().interpreter->getOpcodeID(pc[0].u.opcode)],
239 exec->scopeChain());
240 if (exec->globalData().interpreter->getOpcodeID(pc[0].u.opcode) == op_ret) {
241 dataLog("Will be returning to %p\n", exec->returnPC().value());
242 dataLog("The new cfr will be %p\n", exec->callerFrame());
243 }
244 LLINT_END_IMPL();
245}
246
247LLINT_SLOW_PATH_DECL(special_trace)
248{
249 dataLog("%p / %p: executing special case bc#%zu, op#%u, return PC is %p\n",
250 exec->codeBlock(),
251 exec,
252 static_cast<intptr_t>(pc - exec->codeBlock()->instructions().begin()),
253 exec->globalData().interpreter->getOpcodeID(pc[0].u.opcode),
254 exec->returnPC().value());
255 LLINT_END_IMPL();
256}
257
258inline bool shouldJIT(ExecState* exec)
259{
260 // You can modify this to turn off JITting without rebuilding the world.
261 return exec->globalData().canUseJIT();
262}
263
264// Returns true if we should try to OSR.
265inline bool jitCompileAndSetHeuristics(CodeBlock* codeBlock, ExecState* exec)
266{
267 if (!codeBlock->checkIfJITThresholdReached()) {
268#if ENABLE(JIT_VERBOSE_OSR)
269 dataLog(" JIT threshold should be lifted.\n");
270#endif
271 return false;
272 }
273
274 CodeBlock::JITCompilationResult result = codeBlock->jitCompile(exec->globalData());
275 switch (result) {
276 case CodeBlock::AlreadyCompiled:
277#if ENABLE(JIT_VERBOSE_OSR)
278 dataLog(" Code was already compiled.\n");
279#endif
280 codeBlock->jitSoon();
281 return true;
282 case CodeBlock::CouldNotCompile:
283#if ENABLE(JIT_VERBOSE_OSR)
284 dataLog(" JIT compilation failed.\n");
285#endif
286 codeBlock->dontJITAnytimeSoon();
287 return false;
288 case CodeBlock::CompiledSuccessfully:
289#if ENABLE(JIT_VERBOSE_OSR)
290 dataLog(" JIT compilation successful.\n");
291#endif
292 codeBlock->jitSoon();
293 return true;
294 }
295 ASSERT_NOT_REACHED();
296 return false;
297}
298
299enum EntryKind { Prologue, ArityCheck };
300static SlowPathReturnType entryOSR(ExecState* exec, Instruction* pc, CodeBlock* codeBlock, const char *name, EntryKind kind)
301{
302#if ENABLE(JIT_VERBOSE_OSR)
303 dataLog("%p: Entered %s with executeCounter = %d\n", codeBlock, name, codeBlock->llintExecuteCounter());
304#endif
305
306 if (!shouldJIT(exec)) {
307 codeBlock->dontJITAnytimeSoon();
308 LLINT_RETURN_TWO(0, exec);
309 }
310 if (!jitCompileAndSetHeuristics(codeBlock, exec))
311 LLINT_RETURN_TWO(0, exec);
312
313 if (kind == Prologue)
314 LLINT_RETURN_TWO(codeBlock->getJITCode().executableAddressAtOffset(0), exec);
315 ASSERT(kind == ArityCheck);
316 LLINT_RETURN_TWO(codeBlock->getJITCodeWithArityCheck().executableAddress(), exec);
317}
318
319LLINT_SLOW_PATH_DECL(entry_osr)
320{
321 return entryOSR(exec, pc, exec->codeBlock(), "entry_osr", Prologue);
322}
323
324LLINT_SLOW_PATH_DECL(entry_osr_function_for_call)
325{
326 return entryOSR(exec, pc, &jsCast<JSFunction*>(exec->callee())->jsExecutable()->generatedBytecodeFor(CodeForCall), "entry_osr_function_for_call", Prologue);
327}
328
329LLINT_SLOW_PATH_DECL(entry_osr_function_for_construct)
330{
331 return entryOSR(exec, pc, &jsCast<JSFunction*>(exec->callee())->jsExecutable()->generatedBytecodeFor(CodeForConstruct), "entry_osr_function_for_construct", Prologue);
332}
333
334LLINT_SLOW_PATH_DECL(entry_osr_function_for_call_arityCheck)
335{
336 return entryOSR(exec, pc, &jsCast<JSFunction*>(exec->callee())->jsExecutable()->generatedBytecodeFor(CodeForCall), "entry_osr_function_for_call_arityCheck", ArityCheck);
337}
338
339LLINT_SLOW_PATH_DECL(entry_osr_function_for_construct_arityCheck)
340{
341 return entryOSR(exec, pc, &jsCast<JSFunction*>(exec->callee())->jsExecutable()->generatedBytecodeFor(CodeForConstruct), "entry_osr_function_for_construct_arityCheck", ArityCheck);
342}
343
344LLINT_SLOW_PATH_DECL(loop_osr)
345{
346 CodeBlock* codeBlock = exec->codeBlock();
347
348#if ENABLE(JIT_VERBOSE_OSR)
349 dataLog("%p: Entered loop_osr with executeCounter = %d\n", codeBlock, codeBlock->llintExecuteCounter());
350#endif
351
352 if (!shouldJIT(exec)) {
353 codeBlock->dontJITAnytimeSoon();
354 LLINT_RETURN_TWO(0, exec);
355 }
356
357 if (!jitCompileAndSetHeuristics(codeBlock, exec))
358 LLINT_RETURN_TWO(0, exec);
359
360 ASSERT(codeBlock->getJITType() == JITCode::BaselineJIT);
361
362 Vector<BytecodeAndMachineOffset> map;
363 codeBlock->jitCodeMap()->decode(map);
364 BytecodeAndMachineOffset* mapping = binarySearch<BytecodeAndMachineOffset, unsigned, BytecodeAndMachineOffset::getBytecodeIndex>(map.begin(), map.size(), pc - codeBlock->instructions().begin());
365 ASSERT(mapping);
366 ASSERT(mapping->m_bytecodeIndex == static_cast<unsigned>(pc - codeBlock->instructions().begin()));
367
368 void* jumpTarget = codeBlock->getJITCode().executableAddressAtOffset(mapping->m_machineCodeOffset);
369 ASSERT(jumpTarget);
370
371 LLINT_RETURN_TWO(jumpTarget, exec);
372}
373
374LLINT_SLOW_PATH_DECL(replace)
375{
376 CodeBlock* codeBlock = exec->codeBlock();
377
378#if ENABLE(JIT_VERBOSE_OSR)
379 dataLog("%p: Entered replace with executeCounter = %d\n", codeBlock, codeBlock->llintExecuteCounter());
380#endif
381
382 if (shouldJIT(exec))
383 jitCompileAndSetHeuristics(codeBlock, exec);
384 else
385 codeBlock->dontJITAnytimeSoon();
386 LLINT_END_IMPL();
387}
388
389LLINT_SLOW_PATH_DECL(register_file_check)
390{
391 LLINT_BEGIN();
392#if LLINT_SLOW_PATH_TRACING
393 dataLog("Checking stack height with exec = %p.\n", exec);
394 dataLog("CodeBlock = %p.\n", exec->codeBlock());
395 dataLog("Num callee registers = %u.\n", exec->codeBlock()->m_numCalleeRegisters);
396 dataLog("Num vars = %u.\n", exec->codeBlock()->m_numVars);
397 dataLog("Current end is at %p.\n", exec->globalData().interpreter->registerFile().end());
398#endif
399 ASSERT(&exec->registers()[exec->codeBlock()->m_numCalleeRegisters] > exec->globalData().interpreter->registerFile().end());
400 if (UNLIKELY(!globalData.interpreter->registerFile().grow(&exec->registers()[exec->codeBlock()->m_numCalleeRegisters]))) {
401 ReturnAddressPtr returnPC = exec->returnPC();
402 exec = exec->callerFrame();
403 globalData.exception = createStackOverflowError(exec);
404 interpreterThrowInCaller(exec, returnPC);
405 pc = returnToThrowForThrownException(exec);
406 }
407 LLINT_END_IMPL();
408}
409
410LLINT_SLOW_PATH_DECL(slow_path_call_arityCheck)
411{
412 LLINT_BEGIN();
413 ExecState* newExec = CommonSlowPaths::arityCheckFor(exec, &globalData.interpreter->registerFile(), CodeForCall);
414 if (!newExec) {
415 ReturnAddressPtr returnPC = exec->returnPC();
416 exec = exec->callerFrame();
417 globalData.exception = createStackOverflowError(exec);
418 interpreterThrowInCaller(exec, returnPC);
419 LLINT_RETURN_TWO(bitwise_cast<void*>(static_cast<uintptr_t>(1)), exec);
420 }
421 LLINT_RETURN_TWO(0, newExec);
422}
423
424LLINT_SLOW_PATH_DECL(slow_path_construct_arityCheck)
425{
426 LLINT_BEGIN();
427 ExecState* newExec = CommonSlowPaths::arityCheckFor(exec, &globalData.interpreter->registerFile(), CodeForConstruct);
428 if (!newExec) {
429 ReturnAddressPtr returnPC = exec->returnPC();
430 exec = exec->callerFrame();
431 globalData.exception = createStackOverflowError(exec);
432 interpreterThrowInCaller(exec, returnPC);
433 LLINT_RETURN_TWO(bitwise_cast<void*>(static_cast<uintptr_t>(1)), exec);
434 }
435 LLINT_RETURN_TWO(0, newExec);
436}
437
438LLINT_SLOW_PATH_DECL(slow_path_create_activation)
439{
440 LLINT_BEGIN();
441#if LLINT_SLOW_PATH_TRACING
442 dataLog("Creating an activation, exec = %p!\n", exec);
443#endif
444 JSActivation* activation = JSActivation::create(globalData, exec, static_cast<FunctionExecutable*>(exec->codeBlock()->ownerExecutable()));
445 exec->setScopeChain(exec->scopeChain()->push(activation));
446 LLINT_RETURN(JSValue(activation));
447}
448
449LLINT_SLOW_PATH_DECL(slow_path_create_arguments)
450{
451 LLINT_BEGIN();
452 JSValue arguments = JSValue(Arguments::create(globalData, exec));
453 LLINT_CHECK_EXCEPTION();
454 exec->uncheckedR(pc[1].u.operand) = arguments;
455 exec->uncheckedR(unmodifiedArgumentsRegister(pc[1].u.operand)) = arguments;
456 LLINT_END();
457}
458
459LLINT_SLOW_PATH_DECL(slow_path_create_this)
460{
461 LLINT_BEGIN();
462 JSFunction* constructor = jsCast<JSFunction*>(exec->callee());
463
464#if !ASSERT_DISABLED
465 ConstructData constructData;
466 ASSERT(constructor->methodTable()->getConstructData(constructor, constructData) == ConstructTypeJS);
467#endif
468
469 Structure* structure;
470 JSValue proto = LLINT_OP(2).jsValue();
471 if (proto.isObject())
472 structure = asObject(proto)->inheritorID(globalData);
473 else
474 structure = constructor->scope()->globalObject->emptyObjectStructure();
475
476 LLINT_RETURN(constructEmptyObject(exec, structure));
477}
478
479LLINT_SLOW_PATH_DECL(slow_path_convert_this)
480{
481 LLINT_BEGIN();
482 JSValue v1 = LLINT_OP(1).jsValue();
483 ASSERT(v1.isPrimitive());
484 LLINT_RETURN(v1.toThisObject(exec));
485}
486
487LLINT_SLOW_PATH_DECL(slow_path_new_object)
488{
489 LLINT_BEGIN();
490 LLINT_RETURN(constructEmptyObject(exec));
491}
492
493LLINT_SLOW_PATH_DECL(slow_path_new_array)
494{
495 LLINT_BEGIN();
496 LLINT_RETURN(constructArray(exec, bitwise_cast<JSValue*>(&LLINT_OP(2)), pc[3].u.operand));
497}
498
499LLINT_SLOW_PATH_DECL(slow_path_new_array_buffer)
500{
501 LLINT_BEGIN();
502 LLINT_RETURN(constructArray(exec, exec->codeBlock()->constantBuffer(pc[2].u.operand), pc[3].u.operand));
503}
504
505LLINT_SLOW_PATH_DECL(slow_path_new_regexp)
506{
507 LLINT_BEGIN();
508 RegExp* regExp = exec->codeBlock()->regexp(pc[2].u.operand);
509 if (!regExp->isValid())
510 LLINT_THROW(createSyntaxError(exec, "Invalid flag supplied to RegExp constructor."));
511 LLINT_RETURN(RegExpObject::create(globalData, exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->regExpStructure(), regExp));
512}
513
514LLINT_SLOW_PATH_DECL(slow_path_not)
515{
516 LLINT_BEGIN();
517 LLINT_RETURN(jsBoolean(!LLINT_OP_C(2).jsValue().toBoolean(exec)));
518}
519
520LLINT_SLOW_PATH_DECL(slow_path_eq)
521{
522 LLINT_BEGIN();
523 LLINT_RETURN(jsBoolean(JSValue::equal(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue())));
524}
525
526LLINT_SLOW_PATH_DECL(slow_path_neq)
527{
528 LLINT_BEGIN();
529 LLINT_RETURN(jsBoolean(!JSValue::equal(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue())));
530}
531
532LLINT_SLOW_PATH_DECL(slow_path_stricteq)
533{
534 LLINT_BEGIN();
535 LLINT_RETURN(jsBoolean(JSValue::strictEqual(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue())));
536}
537
538LLINT_SLOW_PATH_DECL(slow_path_nstricteq)
539{
540 LLINT_BEGIN();
541 LLINT_RETURN(jsBoolean(!JSValue::strictEqual(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue())));
542}
543
544LLINT_SLOW_PATH_DECL(slow_path_less)
545{
546 LLINT_BEGIN();
547 LLINT_RETURN(jsBoolean(jsLess<true>(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue())));
548}
549
550LLINT_SLOW_PATH_DECL(slow_path_lesseq)
551{
552 LLINT_BEGIN();
553 LLINT_RETURN(jsBoolean(jsLessEq<true>(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue())));
554}
555
556LLINT_SLOW_PATH_DECL(slow_path_greater)
557{
558 LLINT_BEGIN();
559 LLINT_RETURN(jsBoolean(jsLess<false>(exec, LLINT_OP_C(3).jsValue(), LLINT_OP_C(2).jsValue())));
560}
561
562LLINT_SLOW_PATH_DECL(slow_path_greatereq)
563{
564 LLINT_BEGIN();
565 LLINT_RETURN(jsBoolean(jsLessEq<false>(exec, LLINT_OP_C(3).jsValue(), LLINT_OP_C(2).jsValue())));
566}
567
568LLINT_SLOW_PATH_DECL(slow_path_pre_inc)
569{
570 LLINT_BEGIN();
571 LLINT_RETURN(jsNumber(LLINT_OP(1).jsValue().toNumber(exec) + 1));
572}
573
574LLINT_SLOW_PATH_DECL(slow_path_pre_dec)
575{
576 LLINT_BEGIN();
577 LLINT_RETURN(jsNumber(LLINT_OP(1).jsValue().toNumber(exec) - 1));
578}
579
580LLINT_SLOW_PATH_DECL(slow_path_post_inc)
581{
582 LLINT_BEGIN();
583 double result = LLINT_OP(2).jsValue().toNumber(exec);
584 LLINT_OP(2) = jsNumber(result + 1);
585 LLINT_RETURN(jsNumber(result));
586}
587
588LLINT_SLOW_PATH_DECL(slow_path_post_dec)
589{
590 LLINT_BEGIN();
591 double result = LLINT_OP(2).jsValue().toNumber(exec);
592 LLINT_OP(2) = jsNumber(result - 1);
593 LLINT_RETURN(jsNumber(result));
594}
595
596LLINT_SLOW_PATH_DECL(slow_path_to_jsnumber)
597{
598 LLINT_BEGIN();
599 LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toNumber(exec)));
600}
601
602LLINT_SLOW_PATH_DECL(slow_path_negate)
603{
604 LLINT_BEGIN();
605 LLINT_RETURN(jsNumber(-LLINT_OP_C(2).jsValue().toNumber(exec)));
606}
607
608LLINT_SLOW_PATH_DECL(slow_path_add)
609{
610 LLINT_BEGIN();
611 JSValue v1 = LLINT_OP_C(2).jsValue();
612 JSValue v2 = LLINT_OP_C(3).jsValue();
613
614#if LLINT_SLOW_PATH_TRACING
615 dataLog("Trying to add %s", v1.description());
616 dataLog(" to %s.\n", v2.description());
617#endif
618
619 if (v1.isString() && !v2.isObject())
620 LLINT_RETURN(jsString(exec, asString(v1), v2.toString(exec)));
621
622 if (v1.isNumber() && v2.isNumber())
623 LLINT_RETURN(jsNumber(v1.asNumber() + v2.asNumber()));
624
625 LLINT_RETURN(jsAddSlowCase(exec, v1, v2));
626}
627
628LLINT_SLOW_PATH_DECL(slow_path_mul)
629{
630 LLINT_BEGIN();
631 LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toNumber(exec) * LLINT_OP_C(3).jsValue().toNumber(exec)));
632}
633
634LLINT_SLOW_PATH_DECL(slow_path_sub)
635{
636 LLINT_BEGIN();
637 LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toNumber(exec) - LLINT_OP_C(3).jsValue().toNumber(exec)));
638}
639
640LLINT_SLOW_PATH_DECL(slow_path_div)
641{
642 LLINT_BEGIN();
643 LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toNumber(exec) / LLINT_OP_C(3).jsValue().toNumber(exec)));
644}
645
646LLINT_SLOW_PATH_DECL(slow_path_mod)
647{
648 LLINT_BEGIN();
649 LLINT_RETURN(jsNumber(fmod(LLINT_OP_C(2).jsValue().toNumber(exec), LLINT_OP_C(3).jsValue().toNumber(exec))));
650}
651
652LLINT_SLOW_PATH_DECL(slow_path_lshift)
653{
654 LLINT_BEGIN();
655 LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toInt32(exec) << (LLINT_OP_C(3).jsValue().toUInt32(exec) & 31)));
656}
657
658LLINT_SLOW_PATH_DECL(slow_path_rshift)
659{
660 LLINT_BEGIN();
661 LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toInt32(exec) >> (LLINT_OP_C(3).jsValue().toUInt32(exec) & 31)));
662}
663
664LLINT_SLOW_PATH_DECL(slow_path_urshift)
665{
666 LLINT_BEGIN();
667 LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toUInt32(exec) >> (LLINT_OP_C(3).jsValue().toUInt32(exec) & 31)));
668}
669
670LLINT_SLOW_PATH_DECL(slow_path_bitand)
671{
672 LLINT_BEGIN();
673 LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toInt32(exec) & LLINT_OP_C(3).jsValue().toInt32(exec)));
674}
675
676LLINT_SLOW_PATH_DECL(slow_path_bitor)
677{
678 LLINT_BEGIN();
679 LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toInt32(exec) | LLINT_OP_C(3).jsValue().toInt32(exec)));
680}
681
682LLINT_SLOW_PATH_DECL(slow_path_bitxor)
683{
684 LLINT_BEGIN();
685 LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toInt32(exec) ^ LLINT_OP_C(3).jsValue().toInt32(exec)));
686}
687
688LLINT_SLOW_PATH_DECL(slow_path_check_has_instance)
689{
690 LLINT_BEGIN();
691 JSValue baseVal = LLINT_OP_C(1).jsValue();
692#ifndef NDEBUG
693 TypeInfo typeInfo(UnspecifiedType);
694 ASSERT(!baseVal.isObject()
695 || !(typeInfo = asObject(baseVal)->structure()->typeInfo()).implementsHasInstance());
696#endif
697 LLINT_THROW(createInvalidParamError(exec, "instanceof", baseVal));
698}
699
700LLINT_SLOW_PATH_DECL(slow_path_instanceof)
701{
702 LLINT_BEGIN();
703 LLINT_RETURN(jsBoolean(CommonSlowPaths::opInstanceOfSlow(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue(), LLINT_OP_C(4).jsValue())));
704}
705
706LLINT_SLOW_PATH_DECL(slow_path_typeof)
707{
708 LLINT_BEGIN();
709 LLINT_RETURN(jsTypeStringForValue(exec, LLINT_OP_C(2).jsValue()));
710}
711
712LLINT_SLOW_PATH_DECL(slow_path_is_object)
713{
714 LLINT_BEGIN();
715 LLINT_RETURN(jsBoolean(jsIsObjectType(LLINT_OP_C(2).jsValue())));
716}
717
718LLINT_SLOW_PATH_DECL(slow_path_is_function)
719{
720 LLINT_BEGIN();
721 LLINT_RETURN(jsBoolean(jsIsFunctionType(LLINT_OP_C(2).jsValue())));
722}
723
724LLINT_SLOW_PATH_DECL(slow_path_in)
725{
726 LLINT_BEGIN();
727 LLINT_RETURN(jsBoolean(CommonSlowPaths::opIn(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue())));
728}
729
730LLINT_SLOW_PATH_DECL(slow_path_resolve)
731{
732 LLINT_BEGIN();
733 LLINT_RETURN_PROFILED(op_resolve, CommonSlowPaths::opResolve(exec, exec->codeBlock()->identifier(pc[2].u.operand)));
734}
735
736LLINT_SLOW_PATH_DECL(slow_path_resolve_skip)
737{
738 LLINT_BEGIN();
739 LLINT_RETURN_PROFILED(
740 op_resolve_skip,
741 CommonSlowPaths::opResolveSkip(
742 exec,
743 exec->codeBlock()->identifier(pc[2].u.operand),
744 pc[3].u.operand));
745}
746
747static JSValue resolveGlobal(ExecState* exec, Instruction* pc)
748{
749 CodeBlock* codeBlock = exec->codeBlock();
750 JSGlobalObject* globalObject = codeBlock->globalObject();
751 ASSERT(globalObject->isGlobalObject());
752 int property = pc[2].u.operand;
753 Structure* structure = pc[3].u.structure.get();
754
755 ASSERT_UNUSED(structure, structure != globalObject->structure());
756
757 Identifier& ident = codeBlock->identifier(property);
758 PropertySlot slot(globalObject);
759
760 if (globalObject->getPropertySlot(exec, ident, slot)) {
761 JSValue result = slot.getValue(exec, ident);
762 if (slot.isCacheableValue() && !globalObject->structure()->isUncacheableDictionary()
763 && slot.slotBase() == globalObject) {
764 pc[3].u.structure.set(
765 exec->globalData(), codeBlock->ownerExecutable(), globalObject->structure());
766 pc[4] = slot.cachedOffset();
767 }
768
769 return result;
770 }
771
772 exec->globalData().exception = createUndefinedVariableError(exec, ident);
773 return JSValue();
774}
775
776LLINT_SLOW_PATH_DECL(slow_path_resolve_global)
777{
778 LLINT_BEGIN();
779 LLINT_RETURN_PROFILED(op_resolve_global, resolveGlobal(exec, pc));
780}
781
782LLINT_SLOW_PATH_DECL(slow_path_resolve_global_dynamic)
783{
784 LLINT_BEGIN();
785 LLINT_RETURN_PROFILED(op_resolve_global_dynamic, resolveGlobal(exec, pc));
786}
787
788LLINT_SLOW_PATH_DECL(slow_path_resolve_for_resolve_global_dynamic)
789{
790 LLINT_BEGIN();
791 LLINT_RETURN_PROFILED(op_resolve_global_dynamic, CommonSlowPaths::opResolve(exec, exec->codeBlock()->identifier(pc[2].u.operand)));
792}
793
794LLINT_SLOW_PATH_DECL(slow_path_resolve_base)
795{
796 LLINT_BEGIN();
797 Identifier& ident = exec->codeBlock()->identifier(pc[2].u.operand);
798 if (pc[3].u.operand) {
799 JSValue base = JSC::resolveBase(exec, ident, exec->scopeChain(), true);
800 if (!base)
801 LLINT_THROW(createErrorForInvalidGlobalAssignment(exec, ident.ustring()));
802 LLINT_RETURN(base);
803 }
804
805 LLINT_RETURN_PROFILED(op_resolve_base, JSC::resolveBase(exec, ident, exec->scopeChain(), false));
806}
807
808LLINT_SLOW_PATH_DECL(slow_path_ensure_property_exists)
809{
810 LLINT_BEGIN();
811 JSObject* object = asObject(LLINT_OP(1).jsValue());
812 PropertySlot slot(object);
813 Identifier& ident = exec->codeBlock()->identifier(pc[2].u.operand);
814 if (!object->getPropertySlot(exec, ident, slot))
815 LLINT_THROW(createErrorForInvalidGlobalAssignment(exec, ident.ustring()));
816 LLINT_END();
817}
818
819LLINT_SLOW_PATH_DECL(slow_path_resolve_with_base)
820{
821 LLINT_BEGIN();
822 JSValue result = CommonSlowPaths::opResolveWithBase(exec, exec->codeBlock()->identifier(pc[3].u.operand), LLINT_OP(1));
823 LLINT_CHECK_EXCEPTION();
824 LLINT_OP(2) = result;
825 // FIXME: technically should have profiling, but we don't do it because the DFG won't use it.
826 LLINT_END();
827}
828
829LLINT_SLOW_PATH_DECL(slow_path_resolve_with_this)
830{
831 LLINT_BEGIN();
832 JSValue result = CommonSlowPaths::opResolveWithThis(exec, exec->codeBlock()->identifier(pc[3].u.operand), LLINT_OP(1));
833 LLINT_CHECK_EXCEPTION();
834 LLINT_OP(2) = result;
835 // FIXME: technically should have profiling, but we don't do it because the DFG won't use it.
836 LLINT_END();
837}
838
839LLINT_SLOW_PATH_DECL(slow_path_get_by_id)
840{
841 LLINT_BEGIN();
842 CodeBlock* codeBlock = exec->codeBlock();
843 Identifier& ident = codeBlock->identifier(pc[3].u.operand);
844 JSValue baseValue = LLINT_OP_C(2).jsValue();
845 PropertySlot slot(baseValue);
846
847 JSValue result = baseValue.get(exec, ident, slot);
848 LLINT_CHECK_EXCEPTION();
849 LLINT_OP(1) = result;
850
851 if (baseValue.isCell()
852 && slot.isCacheable()
853 && slot.slotBase() == baseValue
854 && slot.cachedPropertyType() == PropertySlot::Value) {
855
856 JSCell* baseCell = baseValue.asCell();
857 Structure* structure = baseCell->structure();
858
859 if (!structure->isUncacheableDictionary()
860 && !structure->typeInfo().prohibitsPropertyCaching()) {
861 pc[4].u.structure.set(
862 globalData, codeBlock->ownerExecutable(), structure);
863 pc[5].u.operand = slot.cachedOffset() * sizeof(JSValue);
864 }
865 }
866
867#if ENABLE(VALUE_PROFILER)
868 pc[OPCODE_LENGTH(op_get_by_id) - 1].u.profile->m_buckets[0] = JSValue::encode(result);
869#endif
870 LLINT_END();
871}
872
873LLINT_SLOW_PATH_DECL(slow_path_get_arguments_length)
874{
875 LLINT_BEGIN();
876 CodeBlock* codeBlock = exec->codeBlock();
877 Identifier& ident = codeBlock->identifier(pc[3].u.operand);
878 JSValue baseValue = LLINT_OP(2).jsValue();
879 PropertySlot slot(baseValue);
880 LLINT_RETURN(baseValue.get(exec, ident, slot));
881}
882
883LLINT_SLOW_PATH_DECL(slow_path_put_by_id)
884{
885 LLINT_BEGIN();
886 CodeBlock* codeBlock = exec->codeBlock();
887 Identifier& ident = codeBlock->identifier(pc[2].u.operand);
888
889 JSValue baseValue = LLINT_OP_C(1).jsValue();
890 PutPropertySlot slot(codeBlock->isStrictMode());
891 if (pc[8].u.operand)
892 asObject(baseValue)->putDirect(globalData, ident, LLINT_OP_C(3).jsValue(), slot);
893 else
894 baseValue.put(exec, ident, LLINT_OP_C(3).jsValue(), slot);
895 LLINT_CHECK_EXCEPTION();
896
897 if (baseValue.isCell()
898 && slot.isCacheable()) {
899
900 JSCell* baseCell = baseValue.asCell();
901 Structure* structure = baseCell->structure();
902
903 if (!structure->isUncacheableDictionary()
904 && !structure->typeInfo().prohibitsPropertyCaching()
905 && baseCell == slot.base()) {
906
907 if (slot.type() == PutPropertySlot::NewProperty) {
908 if (!structure->isDictionary() && structure->previousID()->propertyStorageCapacity() == structure->propertyStorageCapacity()) {
909 // This is needed because some of the methods we call
910 // below may GC.
911 pc[0].u.opcode = bitwise_cast<void*>(&llint_op_put_by_id);
912
913 normalizePrototypeChain(exec, baseCell);
914
915 ASSERT(structure->previousID()->isObject());
916 pc[4].u.structure.set(
917 globalData, codeBlock->ownerExecutable(), structure->previousID());
918 pc[5].u.operand = slot.cachedOffset() * sizeof(JSValue);
919 pc[6].u.structure.set(
920 globalData, codeBlock->ownerExecutable(), structure);
921 StructureChain* chain = structure->prototypeChain(exec);
922 ASSERT(chain);
923 pc[7].u.structureChain.set(
924 globalData, codeBlock->ownerExecutable(), chain);
925
926 if (pc[8].u.operand)
927 pc[0].u.opcode = bitwise_cast<void*>(&llint_op_put_by_id_transition_direct);
928 else
929 pc[0].u.opcode = bitwise_cast<void*>(&llint_op_put_by_id_transition_normal);
930 }
931 } else {
932 pc[0].u.opcode = bitwise_cast<void*>(&llint_op_put_by_id);
933 pc[4].u.structure.set(
934 globalData, codeBlock->ownerExecutable(), structure);
935 pc[5].u.operand = slot.cachedOffset() * sizeof(JSValue);
936 }
937 }
938 }
939
940 LLINT_END();
941}
942
943LLINT_SLOW_PATH_DECL(slow_path_del_by_id)
944{
945 LLINT_BEGIN();
946 CodeBlock* codeBlock = exec->codeBlock();
947 JSObject* baseObject = LLINT_OP_C(2).jsValue().toObject(exec);
948 bool couldDelete = baseObject->methodTable()->deleteProperty(baseObject, exec, codeBlock->identifier(pc[3].u.operand));
949 LLINT_CHECK_EXCEPTION();
950 if (!couldDelete && codeBlock->isStrictMode())
951 LLINT_THROW(createTypeError(exec, "Unable to delete property."));
952 LLINT_RETURN(jsBoolean(couldDelete));
953}
954
955inline JSValue getByVal(ExecState* exec, JSValue baseValue, JSValue subscript)
956{
957 if (LIKELY(baseValue.isCell() && subscript.isString())) {
958 if (JSValue result = baseValue.asCell()->fastGetOwnProperty(exec, asString(subscript)->value(exec)))
959 return result;
960 }
961
962 if (subscript.isUInt32()) {
963 uint32_t i = subscript.asUInt32();
964 if (isJSString(baseValue) && asString(baseValue)->canGetIndex(i))
965 return asString(baseValue)->getIndex(exec, i);
966
967 return baseValue.get(exec, i);
968 }
969
970 Identifier property(exec, subscript.toString(exec)->value(exec));
971 return baseValue.get(exec, property);
972}
973
974LLINT_SLOW_PATH_DECL(slow_path_get_by_val)
975{
976 LLINT_BEGIN();
977 LLINT_RETURN_PROFILED(op_get_by_val, getByVal(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue()));
978}
979
980LLINT_SLOW_PATH_DECL(slow_path_get_argument_by_val)
981{
982 LLINT_BEGIN();
983 JSValue arguments = LLINT_OP(2).jsValue();
984 if (!arguments) {
985 arguments = Arguments::create(globalData, exec);
986 LLINT_CHECK_EXCEPTION();
987 LLINT_OP(2) = arguments;
988 exec->uncheckedR(unmodifiedArgumentsRegister(pc[2].u.operand)) = arguments;
989 }
990
991 LLINT_RETURN(getByVal(exec, arguments, LLINT_OP_C(3).jsValue()));
992}
993
994LLINT_SLOW_PATH_DECL(slow_path_get_by_pname)
995{
996 LLINT_BEGIN();
997 LLINT_RETURN(getByVal(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue()));
998}
999
1000LLINT_SLOW_PATH_DECL(slow_path_put_by_val)
1001{
1002 LLINT_BEGIN();
1003
1004 JSValue baseValue = LLINT_OP_C(1).jsValue();
1005 JSValue subscript = LLINT_OP_C(2).jsValue();
1006 JSValue value = LLINT_OP_C(3).jsValue();
1007
1008 if (LIKELY(subscript.isUInt32())) {
1009 uint32_t i = subscript.asUInt32();
1010 if (isJSArray(baseValue)) {
1011 JSArray* jsArray = asArray(baseValue);
1012 if (jsArray->canSetIndex(i))
1013 jsArray->setIndex(globalData, i, value);
1014 else
1015 JSArray::putByIndex(jsArray, exec, i, value, exec->codeBlock()->isStrictMode());
1016 LLINT_END();
1017 }
1018 baseValue.putByIndex(exec, i, value, exec->codeBlock()->isStrictMode());
1019 LLINT_END();
1020 }
1021
1022 Identifier property(exec, subscript.toString(exec)->value(exec));
1023 LLINT_CHECK_EXCEPTION();
1024 PutPropertySlot slot(exec->codeBlock()->isStrictMode());
1025 baseValue.put(exec, property, value, slot);
1026 LLINT_END();
1027}
1028
1029LLINT_SLOW_PATH_DECL(slow_path_del_by_val)
1030{
1031 LLINT_BEGIN();
1032 JSValue baseValue = LLINT_OP_C(2).jsValue();
1033 JSObject* baseObject = baseValue.toObject(exec);
1034
1035 JSValue subscript = LLINT_OP_C(3).jsValue();
1036
1037 bool couldDelete;
1038
1039 uint32_t i;
1040 if (subscript.getUInt32(i))
1041 couldDelete = baseObject->methodTable()->deletePropertyByIndex(baseObject, exec, i);
1042 else {
1043 LLINT_CHECK_EXCEPTION();
1044 Identifier property(exec, subscript.toString(exec)->value(exec));
1045 LLINT_CHECK_EXCEPTION();
1046 couldDelete = baseObject->methodTable()->deleteProperty(baseObject, exec, property);
1047 }
1048
1049 if (!couldDelete && exec->codeBlock()->isStrictMode())
1050 LLINT_THROW(createTypeError(exec, "Unable to delete property."));
1051
1052 LLINT_RETURN(jsBoolean(couldDelete));
1053}
1054
1055LLINT_SLOW_PATH_DECL(slow_path_put_by_index)
1056{
1057 LLINT_BEGIN();
1058 JSValue arrayValue = LLINT_OP_C(1).jsValue();
1059 ASSERT(isJSArray(arrayValue));
1060 asArray(arrayValue)->putDirectIndex(exec, pc[2].u.operand, LLINT_OP_C(3).jsValue(), false);
1061 LLINT_END();
1062}
1063
1064LLINT_SLOW_PATH_DECL(slow_path_put_getter_setter)
1065{
1066 LLINT_BEGIN();
1067 ASSERT(LLINT_OP(1).jsValue().isObject());
1068 JSObject* baseObj = asObject(LLINT_OP(1).jsValue());
1069
1070 GetterSetter* accessor = GetterSetter::create(exec);
1071 LLINT_CHECK_EXCEPTION();
1072
1073 JSValue getter = LLINT_OP(3).jsValue();
1074 JSValue setter = LLINT_OP(4).jsValue();
1075 ASSERT(getter.isObject() || getter.isUndefined());
1076 ASSERT(setter.isObject() || setter.isUndefined());
1077 ASSERT(getter.isObject() || setter.isObject());
1078
1079 if (!getter.isUndefined())
1080 accessor->setGetter(globalData, asObject(getter));
1081 if (!setter.isUndefined())
1082 accessor->setSetter(globalData, asObject(setter));
1083 baseObj->putDirectAccessor(
1084 globalData,
1085 exec->codeBlock()->identifier(pc[2].u.operand),
1086 accessor, Accessor);
1087 LLINT_END();
1088}
1089
1090LLINT_SLOW_PATH_DECL(slow_path_jmp_scopes)
1091{
1092 LLINT_BEGIN();
1093 unsigned count = pc[1].u.operand;
1094 ScopeChainNode* tmp = exec->scopeChain();
1095 while (count--)
1096 tmp = tmp->pop();
1097 exec->setScopeChain(tmp);
1098 pc += pc[2].u.operand;
1099 LLINT_END();
1100}
1101
1102LLINT_SLOW_PATH_DECL(slow_path_jtrue)
1103{
1104 LLINT_BEGIN();
1105 LLINT_BRANCH(op_jtrue, LLINT_OP_C(1).jsValue().toBoolean(exec));
1106}
1107
1108LLINT_SLOW_PATH_DECL(slow_path_jfalse)
1109{
1110 LLINT_BEGIN();
1111 LLINT_BRANCH(op_jfalse, !LLINT_OP_C(1).jsValue().toBoolean(exec));
1112}
1113
1114LLINT_SLOW_PATH_DECL(slow_path_jless)
1115{
1116 LLINT_BEGIN();
1117 LLINT_BRANCH(op_jless, jsLess<true>(exec, LLINT_OP_C(1).jsValue(), LLINT_OP_C(2).jsValue()));
1118}
1119
1120LLINT_SLOW_PATH_DECL(slow_path_jnless)
1121{
1122 LLINT_BEGIN();
1123 LLINT_BRANCH(op_jnless, !jsLess<true>(exec, LLINT_OP_C(1).jsValue(), LLINT_OP_C(2).jsValue()));
1124}
1125
1126LLINT_SLOW_PATH_DECL(slow_path_jgreater)
1127{
1128 LLINT_BEGIN();
1129 LLINT_BRANCH(op_jgreater, jsLess<false>(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(1).jsValue()));
1130}
1131
1132LLINT_SLOW_PATH_DECL(slow_path_jngreater)
1133{
1134 LLINT_BEGIN();
1135 LLINT_BRANCH(op_jngreater, !jsLess<false>(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(1).jsValue()));
1136}
1137
1138LLINT_SLOW_PATH_DECL(slow_path_jlesseq)
1139{
1140 LLINT_BEGIN();
1141 LLINT_BRANCH(op_jlesseq, jsLessEq<true>(exec, LLINT_OP_C(1).jsValue(), LLINT_OP_C(2).jsValue()));
1142}
1143
1144LLINT_SLOW_PATH_DECL(slow_path_jnlesseq)
1145{
1146 LLINT_BEGIN();
1147 LLINT_BRANCH(op_jnlesseq, !jsLessEq<true>(exec, LLINT_OP_C(1).jsValue(), LLINT_OP_C(2).jsValue()));
1148}
1149
1150LLINT_SLOW_PATH_DECL(slow_path_jgreatereq)
1151{
1152 LLINT_BEGIN();
1153 LLINT_BRANCH(op_jgreatereq, jsLessEq<false>(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(1).jsValue()));
1154}
1155
1156LLINT_SLOW_PATH_DECL(slow_path_jngreatereq)
1157{
1158 LLINT_BEGIN();
1159 LLINT_BRANCH(op_jngreatereq, !jsLessEq<false>(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(1).jsValue()));
1160}
1161
1162LLINT_SLOW_PATH_DECL(slow_path_switch_imm)
1163{
1164 LLINT_BEGIN();
1165 JSValue scrutinee = LLINT_OP_C(3).jsValue();
1166 ASSERT(scrutinee.isDouble());
1167 double value = scrutinee.asDouble();
1168 int32_t intValue = static_cast<int32_t>(value);
1169 int defaultOffset = pc[2].u.operand;
1170 if (value == intValue) {
1171 CodeBlock* codeBlock = exec->codeBlock();
1172 pc += codeBlock->immediateSwitchJumpTable(pc[1].u.operand).offsetForValue(intValue, defaultOffset);
1173 } else
1174 pc += defaultOffset;
1175 LLINT_END();
1176}
1177
1178LLINT_SLOW_PATH_DECL(slow_path_switch_char)
1179{
1180 LLINT_BEGIN();
1181 JSValue scrutinee = LLINT_OP_C(3).jsValue();
1182 ASSERT(scrutinee.isString());
1183 JSString* string = asString(scrutinee);
1184 ASSERT(string->length() == 1);
1185 int defaultOffset = pc[2].u.operand;
1186 StringImpl* impl = string->value(exec).impl();
1187 CodeBlock* codeBlock = exec->codeBlock();
1188 pc += codeBlock->characterSwitchJumpTable(pc[1].u.operand).offsetForValue((*impl)[0], defaultOffset);
1189 LLINT_END();
1190}
1191
1192LLINT_SLOW_PATH_DECL(slow_path_switch_string)
1193{
1194 LLINT_BEGIN();
1195 JSValue scrutinee = LLINT_OP_C(3).jsValue();
1196 int defaultOffset = pc[2].u.operand;
1197 if (!scrutinee.isString())
1198 pc += defaultOffset;
1199 else {
1200 CodeBlock* codeBlock = exec->codeBlock();
1201 pc += codeBlock->stringSwitchJumpTable(pc[1].u.operand).offsetForValue(asString(scrutinee)->value(exec).impl(), defaultOffset);
1202 }
1203 LLINT_END();
1204}
1205
1206LLINT_SLOW_PATH_DECL(slow_path_new_func)
1207{
1208 LLINT_BEGIN();
1209 CodeBlock* codeBlock = exec->codeBlock();
1210 ASSERT(codeBlock->codeType() != FunctionCode
1211 || !codeBlock->needsFullScopeChain()
1212 || exec->uncheckedR(codeBlock->activationRegister()).jsValue());
1213#if LLINT_SLOW_PATH_TRACING
1214 dataLog("Creating function!\n");
1215#endif
1216 LLINT_RETURN(codeBlock->functionDecl(pc[2].u.operand)->make(exec, exec->scopeChain()));
1217}
1218
1219LLINT_SLOW_PATH_DECL(slow_path_new_func_exp)
1220{
1221 LLINT_BEGIN();
1222 CodeBlock* codeBlock = exec->codeBlock();
1223 FunctionExecutable* function = codeBlock->functionExpr(pc[2].u.operand);
1224 JSFunction* func = function->make(exec, exec->scopeChain());
1225
1226 if (!function->name().isNull()) {
1227 JSStaticScopeObject* functionScopeObject = JSStaticScopeObject::create(exec, function->name(), func, ReadOnly | DontDelete);
1228 func->setScope(globalData, func->scope()->push(functionScopeObject));
1229 }
1230
1231 LLINT_RETURN(func);
1232}
1233
1234static SlowPathReturnType handleHostCall(ExecState* execCallee, Instruction* pc, JSValue callee, CodeSpecializationKind kind)
1235{
1236 ExecState* exec = execCallee->callerFrame();
1237 JSGlobalData& globalData = exec->globalData();
1238
1239 execCallee->setScopeChain(exec->scopeChain());
1240 execCallee->setCodeBlock(0);
1241 execCallee->clearReturnPC();
1242
1243 if (kind == CodeForCall) {
1244 CallData callData;
1245 CallType callType = getCallData(callee, callData);
1246
1247 ASSERT(callType != CallTypeJS);
1248
1249 if (callType == CallTypeHost) {
1250 NativeCallFrameTracer tracer(&globalData, execCallee);
1251 execCallee->setCallee(asObject(callee));
1252 globalData.hostCallReturnValue = JSValue::decode(callData.native.function(execCallee));
1253
1254 LLINT_CALL_RETURN(execCallee, pc, reinterpret_cast<void*>(getHostCallReturnValue));
1255 }
1256
1257#if LLINT_SLOW_PATH_TRACING
1258 dataLog("Call callee is not a function: %s\n", callee.description());
1259#endif
1260
1261 ASSERT(callType == CallTypeNone);
1262 LLINT_CALL_THROW(exec, pc, createNotAFunctionError(exec, callee));
1263 }
1264
1265 ASSERT(kind == CodeForConstruct);
1266
1267 ConstructData constructData;
1268 ConstructType constructType = getConstructData(callee, constructData);
1269
1270 ASSERT(constructType != ConstructTypeJS);
1271
1272 if (constructType == ConstructTypeHost) {
1273 NativeCallFrameTracer tracer(&globalData, execCallee);
1274 execCallee->setCallee(asObject(callee));
1275 globalData.hostCallReturnValue = JSValue::decode(constructData.native.function(execCallee));
1276
1277 LLINT_CALL_RETURN(execCallee, pc, reinterpret_cast<void*>(getHostCallReturnValue));
1278 }
1279
1280#if LLINT_SLOW_PATH_TRACING
1281 dataLog("Constructor callee is not a function: %s\n", callee.description());
1282#endif
1283
1284 ASSERT(constructType == ConstructTypeNone);
1285 LLINT_CALL_THROW(exec, pc, createNotAConstructorError(exec, callee));
1286}
1287
1288inline SlowPathReturnType setUpCall(ExecState* execCallee, Instruction* pc, CodeSpecializationKind kind, JSValue calleeAsValue, LLIntCallLinkInfo* callLinkInfo = 0)
1289{
1290#if LLINT_SLOW_PATH_TRACING
1291 dataLog("Performing call with recorded PC = %p\n", execCallee->callerFrame()->currentVPC());
1292#endif
1293
1294 JSCell* calleeAsFunctionCell = getJSFunction(calleeAsValue);
1295 if (!calleeAsFunctionCell)
1296 return handleHostCall(execCallee, pc, calleeAsValue, kind);
1297
1298 JSFunction* callee = jsCast<JSFunction*>(calleeAsFunctionCell);
1299 ScopeChainNode* scope = callee->scopeUnchecked();
1300 JSGlobalData& globalData = *scope->globalData;
1301 execCallee->setScopeChain(scope);
1302 ExecutableBase* executable = callee->executable();
1303
1304 MacroAssemblerCodePtr codePtr;
1305 CodeBlock* codeBlock = 0;
1306 if (executable->isHostFunction())
1307 codePtr = executable->generatedJITCodeFor(kind).addressForCall();
1308 else {
1309 FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable);
1310 JSObject* error = functionExecutable->compileFor(execCallee, callee->scope(), kind);
1311 if (error)
1312 LLINT_CALL_THROW(execCallee->callerFrame(), pc, error);
1313 codeBlock = &functionExecutable->generatedBytecodeFor(kind);
1314 ASSERT(codeBlock);
1315 if (execCallee->argumentCountIncludingThis() < static_cast<size_t>(codeBlock->numParameters()))
1316 codePtr = functionExecutable->generatedJITCodeWithArityCheckFor(kind);
1317 else
1318 codePtr = functionExecutable->generatedJITCodeFor(kind).addressForCall();
1319 }
1320
1321 if (callLinkInfo) {
1322 if (callLinkInfo->isOnList())
1323 callLinkInfo->remove();
1324 ExecState* execCaller = execCallee->callerFrame();
1325 callLinkInfo->callee.set(globalData, execCaller->codeBlock()->ownerExecutable(), callee);
1326 callLinkInfo->lastSeenCallee.set(globalData, execCaller->codeBlock()->ownerExecutable(), callee);
1327 callLinkInfo->machineCodeTarget = codePtr;
1328 if (codeBlock)
1329 codeBlock->linkIncomingCall(callLinkInfo);
1330 }
1331
1332 LLINT_CALL_RETURN(execCallee, pc, codePtr.executableAddress());
1333}
1334
1335inline SlowPathReturnType genericCall(ExecState* exec, Instruction* pc, CodeSpecializationKind kind)
1336{
1337 // This needs to:
1338 // - Set up a call frame.
1339 // - Figure out what to call and compile it if necessary.
1340 // - If possible, link the call's inline cache.
1341 // - Return a tuple of machine code address to call and the new call frame.
1342
1343 JSValue calleeAsValue = LLINT_OP_C(1).jsValue();
1344
1345 ExecState* execCallee = exec + pc[3].u.operand;
1346
1347 execCallee->setArgumentCountIncludingThis(pc[2].u.operand);
1348 execCallee->uncheckedR(RegisterFile::Callee) = calleeAsValue;
1349 execCallee->setCallerFrame(exec);
1350
1351 ASSERT(pc[4].u.callLinkInfo);
1352 return setUpCall(execCallee, pc, kind, calleeAsValue, pc[4].u.callLinkInfo);
1353}
1354
1355LLINT_SLOW_PATH_DECL(slow_path_call)
1356{
1357 LLINT_BEGIN_NO_SET_PC();
1358 return genericCall(exec, pc, CodeForCall);
1359}
1360
1361LLINT_SLOW_PATH_DECL(slow_path_construct)
1362{
1363 LLINT_BEGIN_NO_SET_PC();
1364 return genericCall(exec, pc, CodeForConstruct);
1365}
1366
1367LLINT_SLOW_PATH_DECL(slow_path_call_varargs)
1368{
1369 LLINT_BEGIN();
1370 // This needs to:
1371 // - Set up a call frame while respecting the variable arguments.
1372 // - Figure out what to call and compile it if necessary.
1373 // - Return a tuple of machine code address to call and the new call frame.
1374
1375 JSValue calleeAsValue = LLINT_OP_C(1).jsValue();
1376
1377 ExecState* execCallee = loadVarargs(
1378 exec, &globalData.interpreter->registerFile(),
1379 LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue(), pc[4].u.operand);
1380 LLINT_CALL_CHECK_EXCEPTION(exec, pc);
1381
1382 execCallee->uncheckedR(RegisterFile::Callee) = calleeAsValue;
1383 execCallee->setCallerFrame(exec);
1384 exec->setCurrentVPC(pc + OPCODE_LENGTH(op_call_varargs));
1385
1386 return setUpCall(execCallee, pc, CodeForCall, calleeAsValue);
1387}
1388
1389LLINT_SLOW_PATH_DECL(slow_path_call_eval)
1390{
1391 LLINT_BEGIN_NO_SET_PC();
1392 JSValue calleeAsValue = LLINT_OP(1).jsValue();
1393
1394 ExecState* execCallee = exec + pc[3].u.operand;
1395
1396 execCallee->setArgumentCountIncludingThis(pc[2].u.operand);
1397 execCallee->setCallerFrame(exec);
1398 execCallee->uncheckedR(RegisterFile::Callee) = calleeAsValue;
1399 execCallee->setScopeChain(exec->scopeChain());
1400 execCallee->setReturnPC(bitwise_cast<Instruction*>(&llint_generic_return_point));
1401 execCallee->setCodeBlock(0);
1402 exec->setCurrentVPC(pc + OPCODE_LENGTH(op_call_eval));
1403
1404 if (!isHostFunction(calleeAsValue, globalFuncEval))
1405 return setUpCall(execCallee, pc, CodeForCall, calleeAsValue);
1406
1407 globalData.hostCallReturnValue = eval(execCallee);
1408 LLINT_CALL_RETURN(execCallee, pc, reinterpret_cast<void*>(getHostCallReturnValue));
1409}
1410
1411LLINT_SLOW_PATH_DECL(slow_path_tear_off_activation)
1412{
1413 LLINT_BEGIN();
1414 ASSERT(exec->codeBlock()->needsFullScopeChain());
1415 JSValue activationValue = LLINT_OP(1).jsValue();
1416 if (!activationValue) {
1417 if (JSValue v = exec->uncheckedR(unmodifiedArgumentsRegister(pc[2].u.operand)).jsValue()) {
1418 if (!exec->codeBlock()->isStrictMode())
1419 asArguments(v)->tearOff(exec);
1420 }
1421 LLINT_END();
1422 }
1423 JSActivation* activation = asActivation(activationValue);
1424 activation->tearOff(globalData);
1425 if (JSValue v = exec->uncheckedR(unmodifiedArgumentsRegister(pc[2].u.operand)).jsValue())
1426 asArguments(v)->didTearOffActivation(globalData, activation);
1427 LLINT_END();
1428}
1429
1430LLINT_SLOW_PATH_DECL(slow_path_tear_off_arguments)
1431{
1432 LLINT_BEGIN();
1433 ASSERT(exec->codeBlock()->usesArguments() && !exec->codeBlock()->needsFullScopeChain());
1434 asArguments(exec->uncheckedR(unmodifiedArgumentsRegister(pc[1].u.operand)).jsValue())->tearOff(exec);
1435 LLINT_END();
1436}
1437
1438LLINT_SLOW_PATH_DECL(slow_path_strcat)
1439{
1440 LLINT_BEGIN();
1441 LLINT_RETURN(jsString(exec, &LLINT_OP(2), pc[3].u.operand));
1442}
1443
1444LLINT_SLOW_PATH_DECL(slow_path_to_primitive)
1445{
1446 LLINT_BEGIN();
1447 LLINT_RETURN(LLINT_OP_C(2).jsValue().toPrimitive(exec));
1448}
1449
1450LLINT_SLOW_PATH_DECL(slow_path_get_pnames)
1451{
1452 LLINT_BEGIN();
1453 JSValue v = LLINT_OP(2).jsValue();
1454 if (v.isUndefinedOrNull()) {
1455 pc += pc[5].u.operand;
1456 LLINT_END();
1457 }
1458
1459 JSObject* o = v.toObject(exec);
1460 Structure* structure = o->structure();
1461 JSPropertyNameIterator* jsPropertyNameIterator = structure->enumerationCache();
1462 if (!jsPropertyNameIterator || jsPropertyNameIterator->cachedPrototypeChain() != structure->prototypeChain(exec))
1463 jsPropertyNameIterator = JSPropertyNameIterator::create(exec, o);
1464
1465 LLINT_OP(1) = JSValue(jsPropertyNameIterator);
1466 LLINT_OP(2) = JSValue(o);
1467 LLINT_OP(3) = Register::withInt(0);
1468 LLINT_OP(4) = Register::withInt(jsPropertyNameIterator->size());
1469
1470 pc += OPCODE_LENGTH(op_get_pnames);
1471 LLINT_END();
1472}
1473
1474LLINT_SLOW_PATH_DECL(slow_path_next_pname)
1475{
1476 LLINT_BEGIN();
1477 JSObject* base = asObject(LLINT_OP(2).jsValue());
1478 JSString* property = asString(LLINT_OP(1).jsValue());
1479 if (base->hasProperty(exec, Identifier(exec, property->value(exec)))) {
1480 // Go to target.
1481 pc += pc[6].u.operand;
1482 } // Else, don't change the PC, so the interpreter will reloop.
1483 LLINT_END();
1484}
1485
1486LLINT_SLOW_PATH_DECL(slow_path_push_scope)
1487{
1488 LLINT_BEGIN();
1489 JSValue v = LLINT_OP(1).jsValue();
1490 JSObject* o = v.toObject(exec);
1491 LLINT_CHECK_EXCEPTION();
1492
1493 LLINT_OP(1) = o;
1494 exec->setScopeChain(exec->scopeChain()->push(o));
1495
1496 LLINT_END();
1497}
1498
1499LLINT_SLOW_PATH_DECL(slow_path_pop_scope)
1500{
1501 LLINT_BEGIN();
1502 exec->setScopeChain(exec->scopeChain()->pop());
1503 LLINT_END();
1504}
1505
1506LLINT_SLOW_PATH_DECL(slow_path_push_new_scope)
1507{
1508 LLINT_BEGIN();
1509 CodeBlock* codeBlock = exec->codeBlock();
1510 JSObject* scope = JSStaticScopeObject::create(exec, codeBlock->identifier(pc[2].u.operand), LLINT_OP(3).jsValue(), DontDelete);
1511 exec->setScopeChain(exec->scopeChain()->push(scope));
1512 LLINT_RETURN(scope);
1513}
1514
1515LLINT_SLOW_PATH_DECL(slow_path_throw)
1516{
1517 LLINT_BEGIN();
1518 LLINT_THROW(LLINT_OP_C(1).jsValue());
1519}
1520
1521LLINT_SLOW_PATH_DECL(slow_path_throw_reference_error)
1522{
1523 LLINT_BEGIN();
1524 LLINT_THROW(createReferenceError(exec, LLINT_OP_C(1).jsValue().toString(exec)->value(exec)));
1525}
1526
1527LLINT_SLOW_PATH_DECL(slow_path_debug)
1528{
1529 LLINT_BEGIN();
1530 int debugHookID = pc[1].u.operand;
1531 int firstLine = pc[2].u.operand;
1532 int lastLine = pc[3].u.operand;
1533
1534 globalData.interpreter->debug(exec, static_cast<DebugHookID>(debugHookID), firstLine, lastLine);
1535
1536 LLINT_END();
1537}
1538
1539LLINT_SLOW_PATH_DECL(slow_path_profile_will_call)
1540{
1541 LLINT_BEGIN();
1542 (*Profiler::enabledProfilerReference())->willExecute(exec, LLINT_OP(1).jsValue());
1543 LLINT_END();
1544}
1545
1546LLINT_SLOW_PATH_DECL(slow_path_profile_did_call)
1547{
1548 LLINT_BEGIN();
1549 (*Profiler::enabledProfilerReference())->didExecute(exec, LLINT_OP(1).jsValue());
1550 LLINT_END();
1551}
1552
1553LLINT_SLOW_PATH_DECL(throw_from_native_call)
1554{
1555 LLINT_BEGIN();
1556 ASSERT(globalData.exception);
1557 LLINT_END();
1558}
1559
1560} } // namespace JSC::LLInt
1561
1562#endif // ENABLE(LLINT)