]> git.saurik.com Git - apple/javascriptcore.git/blob - llint/LLIntSlowPaths.cpp
JavaScriptCore-1097.3.3.tar.gz
[apple/javascriptcore.git] / llint / LLIntSlowPaths.cpp
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
50 namespace 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
152 extern "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
166 extern "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
191 LLINT_SLOW_PATH_DECL(trace_prologue)
192 {
193 dataLog("%p / %p: in prologue.\n", exec->codeBlock(), exec);
194 LLINT_END_IMPL();
195 }
196
197 static 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
208 LLINT_SLOW_PATH_DECL(trace_prologue_function_for_call)
209 {
210 traceFunctionPrologue(exec, "call prologue", CodeForCall);
211 LLINT_END_IMPL();
212 }
213
214 LLINT_SLOW_PATH_DECL(trace_prologue_function_for_construct)
215 {
216 traceFunctionPrologue(exec, "construct prologue", CodeForConstruct);
217 LLINT_END_IMPL();
218 }
219
220 LLINT_SLOW_PATH_DECL(trace_arityCheck_for_call)
221 {
222 traceFunctionPrologue(exec, "call arity check", CodeForCall);
223 LLINT_END_IMPL();
224 }
225
226 LLINT_SLOW_PATH_DECL(trace_arityCheck_for_construct)
227 {
228 traceFunctionPrologue(exec, "construct arity check", CodeForConstruct);
229 LLINT_END_IMPL();
230 }
231
232 LLINT_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
247 LLINT_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
258 inline 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.
265 inline 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
299 enum EntryKind { Prologue, ArityCheck };
300 static 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
319 LLINT_SLOW_PATH_DECL(entry_osr)
320 {
321 return entryOSR(exec, pc, exec->codeBlock(), "entry_osr", Prologue);
322 }
323
324 LLINT_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
329 LLINT_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
334 LLINT_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
339 LLINT_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
344 LLINT_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
374 LLINT_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
389 LLINT_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
410 LLINT_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
424 LLINT_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
438 LLINT_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
449 LLINT_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
459 LLINT_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
479 LLINT_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
487 LLINT_SLOW_PATH_DECL(slow_path_new_object)
488 {
489 LLINT_BEGIN();
490 LLINT_RETURN(constructEmptyObject(exec));
491 }
492
493 LLINT_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
499 LLINT_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
505 LLINT_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
514 LLINT_SLOW_PATH_DECL(slow_path_not)
515 {
516 LLINT_BEGIN();
517 LLINT_RETURN(jsBoolean(!LLINT_OP_C(2).jsValue().toBoolean(exec)));
518 }
519
520 LLINT_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
526 LLINT_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
532 LLINT_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
538 LLINT_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
544 LLINT_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
550 LLINT_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
556 LLINT_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
562 LLINT_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
568 LLINT_SLOW_PATH_DECL(slow_path_pre_inc)
569 {
570 LLINT_BEGIN();
571 LLINT_RETURN(jsNumber(LLINT_OP(1).jsValue().toNumber(exec) + 1));
572 }
573
574 LLINT_SLOW_PATH_DECL(slow_path_pre_dec)
575 {
576 LLINT_BEGIN();
577 LLINT_RETURN(jsNumber(LLINT_OP(1).jsValue().toNumber(exec) - 1));
578 }
579
580 LLINT_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
588 LLINT_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
596 LLINT_SLOW_PATH_DECL(slow_path_to_jsnumber)
597 {
598 LLINT_BEGIN();
599 LLINT_RETURN(jsNumber(LLINT_OP_C(2).jsValue().toNumber(exec)));
600 }
601
602 LLINT_SLOW_PATH_DECL(slow_path_negate)
603 {
604 LLINT_BEGIN();
605 LLINT_RETURN(jsNumber(-LLINT_OP_C(2).jsValue().toNumber(exec)));
606 }
607
608 LLINT_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
628 LLINT_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
634 LLINT_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
640 LLINT_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
646 LLINT_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
652 LLINT_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
658 LLINT_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
664 LLINT_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
670 LLINT_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
676 LLINT_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
682 LLINT_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
688 LLINT_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
700 LLINT_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
706 LLINT_SLOW_PATH_DECL(slow_path_typeof)
707 {
708 LLINT_BEGIN();
709 LLINT_RETURN(jsTypeStringForValue(exec, LLINT_OP_C(2).jsValue()));
710 }
711
712 LLINT_SLOW_PATH_DECL(slow_path_is_object)
713 {
714 LLINT_BEGIN();
715 LLINT_RETURN(jsBoolean(jsIsObjectType(LLINT_OP_C(2).jsValue())));
716 }
717
718 LLINT_SLOW_PATH_DECL(slow_path_is_function)
719 {
720 LLINT_BEGIN();
721 LLINT_RETURN(jsBoolean(jsIsFunctionType(LLINT_OP_C(2).jsValue())));
722 }
723
724 LLINT_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
730 LLINT_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
736 LLINT_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
747 static 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
776 LLINT_SLOW_PATH_DECL(slow_path_resolve_global)
777 {
778 LLINT_BEGIN();
779 LLINT_RETURN_PROFILED(op_resolve_global, resolveGlobal(exec, pc));
780 }
781
782 LLINT_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
788 LLINT_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
794 LLINT_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
808 LLINT_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
819 LLINT_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
829 LLINT_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
839 LLINT_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
873 LLINT_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
883 LLINT_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
943 LLINT_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
955 inline 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
974 LLINT_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
980 LLINT_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
994 LLINT_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
1000 LLINT_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
1029 LLINT_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
1055 LLINT_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
1064 LLINT_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
1090 LLINT_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
1102 LLINT_SLOW_PATH_DECL(slow_path_jtrue)
1103 {
1104 LLINT_BEGIN();
1105 LLINT_BRANCH(op_jtrue, LLINT_OP_C(1).jsValue().toBoolean(exec));
1106 }
1107
1108 LLINT_SLOW_PATH_DECL(slow_path_jfalse)
1109 {
1110 LLINT_BEGIN();
1111 LLINT_BRANCH(op_jfalse, !LLINT_OP_C(1).jsValue().toBoolean(exec));
1112 }
1113
1114 LLINT_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
1120 LLINT_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
1126 LLINT_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
1132 LLINT_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
1138 LLINT_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
1144 LLINT_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
1150 LLINT_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
1156 LLINT_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
1162 LLINT_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
1178 LLINT_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
1192 LLINT_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
1206 LLINT_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
1219 LLINT_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
1234 static 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
1288 inline 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
1335 inline 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
1355 LLINT_SLOW_PATH_DECL(slow_path_call)
1356 {
1357 LLINT_BEGIN_NO_SET_PC();
1358 return genericCall(exec, pc, CodeForCall);
1359 }
1360
1361 LLINT_SLOW_PATH_DECL(slow_path_construct)
1362 {
1363 LLINT_BEGIN_NO_SET_PC();
1364 return genericCall(exec, pc, CodeForConstruct);
1365 }
1366
1367 LLINT_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
1389 LLINT_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
1411 LLINT_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
1430 LLINT_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
1438 LLINT_SLOW_PATH_DECL(slow_path_strcat)
1439 {
1440 LLINT_BEGIN();
1441 LLINT_RETURN(jsString(exec, &LLINT_OP(2), pc[3].u.operand));
1442 }
1443
1444 LLINT_SLOW_PATH_DECL(slow_path_to_primitive)
1445 {
1446 LLINT_BEGIN();
1447 LLINT_RETURN(LLINT_OP_C(2).jsValue().toPrimitive(exec));
1448 }
1449
1450 LLINT_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
1474 LLINT_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
1486 LLINT_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
1499 LLINT_SLOW_PATH_DECL(slow_path_pop_scope)
1500 {
1501 LLINT_BEGIN();
1502 exec->setScopeChain(exec->scopeChain()->pop());
1503 LLINT_END();
1504 }
1505
1506 LLINT_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
1515 LLINT_SLOW_PATH_DECL(slow_path_throw)
1516 {
1517 LLINT_BEGIN();
1518 LLINT_THROW(LLINT_OP_C(1).jsValue());
1519 }
1520
1521 LLINT_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
1527 LLINT_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
1539 LLINT_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
1546 LLINT_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
1553 LLINT_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)