9f64da0ee9c72119803053643582ac36d2cf36d9
[WebKit-https.git] / Source / JavaScriptCore / runtime / CommonSlowPaths.cpp
1 /*
2  * Copyright (C) 2011-2016 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 "CommonSlowPaths.h"
28
29 #include "ArithProfile.h"
30 #include "ArrayConstructor.h"
31 #include "BuiltinNames.h"
32 #include "CallFrame.h"
33 #include "ClonedArguments.h"
34 #include "CodeProfiling.h"
35 #include "CommonSlowPathsExceptions.h"
36 #include "DefinePropertyAttributes.h"
37 #include "DirectArguments.h"
38 #include "Error.h"
39 #include "ErrorHandlingScope.h"
40 #include "ExceptionFuzz.h"
41 #include "GetterSetter.h"
42 #include "HostCallReturnValue.h"
43 #include "Interpreter.h"
44 #include "JIT.h"
45 #include "JSCInlines.h"
46 #include "JSCJSValue.h"
47 #include "JSGlobalObjectFunctions.h"
48 #include "JSLexicalEnvironment.h"
49 #include "JSPropertyNameEnumerator.h"
50 #include "JSString.h"
51 #include "JSWithScope.h"
52 #include "LLIntCommon.h"
53 #include "LLIntExceptions.h"
54 #include "LowLevelInterpreter.h"
55 #include "MathCommon.h"
56 #include "ObjectConstructor.h"
57 #include "ScopedArguments.h"
58 #include "StructureRareDataInlines.h"
59 #include "TypeProfilerLog.h"
60 #include <wtf/StringPrintStream.h>
61
62 namespace JSC {
63
64 #define BEGIN_NO_SET_PC() \
65     VM& vm = exec->vm();      \
66     NativeCallFrameTracer tracer(&vm, exec); \
67     auto throwScope = DECLARE_THROW_SCOPE(vm); \
68     UNUSED_PARAM(throwScope)
69
70 #ifndef NDEBUG
71 #define SET_PC_FOR_STUBS() do { \
72         exec->codeBlock()->bytecodeOffset(pc); \
73         exec->setCurrentVPC(pc + 1); \
74     } while (false)
75 #else
76 #define SET_PC_FOR_STUBS() do { \
77         exec->setCurrentVPC(pc + 1); \
78     } while (false)
79 #endif
80
81 #define RETURN_TO_THROW(exec, pc)   pc = LLInt::returnToThrow(exec)
82
83 #define BEGIN()                           \
84     BEGIN_NO_SET_PC();                    \
85     SET_PC_FOR_STUBS()
86
87 #define OP(index) (exec->uncheckedR(pc[index].u.operand))
88 #define OP_C(index) (exec->r(pc[index].u.operand))
89
90 #define RETURN_TWO(first, second) do {       \
91         return encodeResult(first, second);        \
92     } while (false)
93
94 #define END_IMPL() RETURN_TWO(pc, exec)
95
96 #define THROW(exceptionToThrow) do {                        \
97         auto scope = DECLARE_THROW_SCOPE(vm);               \
98         throwException(exec, scope, exceptionToThrow);      \
99         RETURN_TO_THROW(exec, pc);                          \
100         END_IMPL();                                         \
101     } while (false)
102
103 #define CHECK_EXCEPTION() do {                    \
104         doExceptionFuzzingIfEnabled(exec, "CommonSlowPaths", pc);   \
105         if (UNLIKELY(throwScope.exception())) {   \
106             RETURN_TO_THROW(exec, pc);            \
107             END_IMPL();                           \
108         }                                         \
109     } while (false)
110
111 #define END() do {                        \
112         CHECK_EXCEPTION();                \
113         END_IMPL();                       \
114     } while (false)
115
116 #define BRANCH(opcode, condition) do {                      \
117         bool bCondition = (condition);                         \
118         CHECK_EXCEPTION();                                  \
119         if (bCondition)                                        \
120             pc += pc[OPCODE_LENGTH(opcode) - 1].u.operand;        \
121         else                                                      \
122             pc += OPCODE_LENGTH(opcode);                          \
123         END_IMPL();                                         \
124     } while (false)
125
126 #define RETURN_WITH_PROFILING(value__, profilingAction__) do { \
127         JSValue returnValue__ = (value__);  \
128         CHECK_EXCEPTION();                  \
129         OP(1) = returnValue__;              \
130         profilingAction__;                  \
131         END_IMPL();                         \
132     } while (false)
133
134 #define RETURN(value) \
135     RETURN_WITH_PROFILING(value, { })
136
137 #define RETURN_PROFILED(opcode__, value__) \
138     RETURN_WITH_PROFILING(value__, PROFILE_VALUE(opcode__, returnValue__))
139
140 #define PROFILE_VALUE(opcode, value) do { \
141         pc[OPCODE_LENGTH(opcode) - 1].u.profile->m_buckets[0] = \
142         JSValue::encode(value);                  \
143     } while (false)
144
145 #define CALL_END_IMPL(exec, callTarget) RETURN_TWO((callTarget), (exec))
146
147 #define CALL_CHECK_EXCEPTION(exec, pc) do {                          \
148         ExecState* cceExec = (exec);                                 \
149         Instruction* ccePC = (pc);                                   \
150         if (UNLIKELY(throwScope.exception()))                        \
151             CALL_END_IMPL(cceExec, LLInt::callToThrow(cceExec));     \
152     } while (false)
153
154 #define CALL_RETURN(exec, pc, callTarget) do {                    \
155         ExecState* crExec = (exec);                                  \
156         Instruction* crPC = (pc);                                    \
157         void* crCallTarget = (callTarget);                           \
158         CALL_CHECK_EXCEPTION(crExec->callerFrame(), crPC);  \
159         CALL_END_IMPL(crExec, crCallTarget);                \
160     } while (false)
161
162 static CommonSlowPaths::ArityCheckData* setupArityCheckData(VM& vm, int slotsToAdd)
163 {
164     CommonSlowPaths::ArityCheckData* result = vm.arityCheckData.get();
165     result->paddedStackSpace = slotsToAdd;
166 #if ENABLE(JIT)
167     if (vm.canUseJIT())
168         result->thunkToCall = vm.getCTIStub(arityFixupGenerator).code().executableAddress();
169     else
170 #endif
171         result->thunkToCall = 0;
172     return result;
173 }
174
175 SLOW_PATH_DECL(slow_path_call_arityCheck)
176 {
177     BEGIN();
178     int slotsToAdd = CommonSlowPaths::arityCheckFor(exec, vm, CodeForCall);
179     if (slotsToAdd < 0) {
180         exec = exec->callerFrame();
181         vm.topCallFrame = exec;
182         ErrorHandlingScope errorScope(vm);
183         CommonSlowPaths::interpreterThrowInCaller(exec, createStackOverflowError(exec));
184         RETURN_TWO(bitwise_cast<void*>(static_cast<uintptr_t>(1)), exec);
185     }
186     RETURN_TWO(0, setupArityCheckData(vm, slotsToAdd));
187 }
188
189 SLOW_PATH_DECL(slow_path_construct_arityCheck)
190 {
191     BEGIN();
192     int slotsToAdd = CommonSlowPaths::arityCheckFor(exec, vm, CodeForConstruct);
193     if (slotsToAdd < 0) {
194         exec = exec->callerFrame();
195         vm.topCallFrame = exec;
196         ErrorHandlingScope errorScope(vm);
197         CommonSlowPaths::interpreterThrowInCaller(exec, createStackOverflowError(exec));
198         RETURN_TWO(bitwise_cast<void*>(static_cast<uintptr_t>(1)), exec);
199     }
200     RETURN_TWO(0, setupArityCheckData(vm, slotsToAdd));
201 }
202
203 SLOW_PATH_DECL(slow_path_create_direct_arguments)
204 {
205     BEGIN();
206     RETURN(DirectArguments::createByCopying(exec));
207 }
208
209 SLOW_PATH_DECL(slow_path_create_scoped_arguments)
210 {
211     BEGIN();
212     JSLexicalEnvironment* scope = jsCast<JSLexicalEnvironment*>(OP(2).jsValue());
213     ScopedArgumentsTable* table = scope->symbolTable()->arguments();
214     RETURN(ScopedArguments::createByCopying(exec, table, scope));
215 }
216
217 SLOW_PATH_DECL(slow_path_create_cloned_arguments)
218 {
219     BEGIN();
220     RETURN(ClonedArguments::createWithMachineFrame(exec, exec, ArgumentsMode::Cloned));
221 }
222
223 SLOW_PATH_DECL(slow_path_create_this)
224 {
225     BEGIN();
226     JSObject* result;
227     JSObject* constructorAsObject = asObject(OP(2).jsValue());
228     if (constructorAsObject->type() == JSFunctionType) {
229         JSFunction* constructor = jsCast<JSFunction*>(constructorAsObject);
230         auto& cacheWriteBarrier = pc[4].u.jsCell;
231         if (!cacheWriteBarrier)
232             cacheWriteBarrier.set(exec->vm(), exec->codeBlock(), constructor);
233         else if (cacheWriteBarrier.unvalidatedGet() != JSCell::seenMultipleCalleeObjects() && cacheWriteBarrier.get() != constructor)
234             cacheWriteBarrier.setWithoutWriteBarrier(JSCell::seenMultipleCalleeObjects());
235
236         size_t inlineCapacity = pc[3].u.operand;
237         Structure* structure = constructor->rareData(exec, inlineCapacity)->objectAllocationProfile()->structure();
238         result = constructEmptyObject(exec, structure);
239     } else {
240         // http://ecma-international.org/ecma-262/6.0/#sec-ordinarycreatefromconstructor
241         JSValue proto = constructorAsObject->get(exec, exec->propertyNames().prototype);
242         CHECK_EXCEPTION();
243         if (proto.isObject())
244             result = constructEmptyObject(exec, asObject(proto));
245         else
246             result = constructEmptyObject(exec);
247     }
248     RETURN(result);
249 }
250
251 SLOW_PATH_DECL(slow_path_to_this)
252 {
253     BEGIN();
254     JSValue v1 = OP(1).jsValue();
255     if (v1.isCell()) {
256         Structure* myStructure = v1.asCell()->structure(vm);
257         Structure* otherStructure = pc[2].u.structure.get();
258         if (myStructure != otherStructure) {
259             if (otherStructure)
260                 pc[3].u.toThisStatus = ToThisConflicted;
261             pc[2].u.structure.set(vm, exec->codeBlock(), myStructure);
262         }
263     } else {
264         pc[3].u.toThisStatus = ToThisConflicted;
265         pc[2].u.structure.clear();
266     }
267     RETURN(v1.toThis(exec, exec->codeBlock()->isStrictMode() ? StrictMode : NotStrictMode));
268 }
269
270 SLOW_PATH_DECL(slow_path_throw_tdz_error)
271 {
272     BEGIN();
273     THROW(createTDZError(exec));
274 }
275
276 SLOW_PATH_DECL(slow_path_throw_strict_mode_readonly_property_write_error)
277 {
278     BEGIN();
279     THROW(createTypeError(exec, ASCIILiteral(ReadonlyPropertyWriteError)));
280 }
281
282 SLOW_PATH_DECL(slow_path_not)
283 {
284     BEGIN();
285     RETURN(jsBoolean(!OP_C(2).jsValue().toBoolean(exec)));
286 }
287
288 SLOW_PATH_DECL(slow_path_eq)
289 {
290     BEGIN();
291     RETURN(jsBoolean(JSValue::equal(exec, OP_C(2).jsValue(), OP_C(3).jsValue())));
292 }
293
294 SLOW_PATH_DECL(slow_path_neq)
295 {
296     BEGIN();
297     RETURN(jsBoolean(!JSValue::equal(exec, OP_C(2).jsValue(), OP_C(3).jsValue())));
298 }
299
300 SLOW_PATH_DECL(slow_path_stricteq)
301 {
302     BEGIN();
303     RETURN(jsBoolean(JSValue::strictEqual(exec, OP_C(2).jsValue(), OP_C(3).jsValue())));
304 }
305
306 SLOW_PATH_DECL(slow_path_nstricteq)
307 {
308     BEGIN();
309     RETURN(jsBoolean(!JSValue::strictEqual(exec, OP_C(2).jsValue(), OP_C(3).jsValue())));
310 }
311
312 SLOW_PATH_DECL(slow_path_less)
313 {
314     BEGIN();
315     RETURN(jsBoolean(jsLess<true>(exec, OP_C(2).jsValue(), OP_C(3).jsValue())));
316 }
317
318 SLOW_PATH_DECL(slow_path_lesseq)
319 {
320     BEGIN();
321     RETURN(jsBoolean(jsLessEq<true>(exec, OP_C(2).jsValue(), OP_C(3).jsValue())));
322 }
323
324 SLOW_PATH_DECL(slow_path_greater)
325 {
326     BEGIN();
327     RETURN(jsBoolean(jsLess<false>(exec, OP_C(3).jsValue(), OP_C(2).jsValue())));
328 }
329
330 SLOW_PATH_DECL(slow_path_greatereq)
331 {
332     BEGIN();
333     RETURN(jsBoolean(jsLessEq<false>(exec, OP_C(3).jsValue(), OP_C(2).jsValue())));
334 }
335
336 SLOW_PATH_DECL(slow_path_inc)
337 {
338     BEGIN();
339     RETURN(jsNumber(OP(1).jsValue().toNumber(exec) + 1));
340 }
341
342 SLOW_PATH_DECL(slow_path_dec)
343 {
344     BEGIN();
345     RETURN(jsNumber(OP(1).jsValue().toNumber(exec) - 1));
346 }
347
348 SLOW_PATH_DECL(slow_path_to_string)
349 {
350     BEGIN();
351     RETURN(OP_C(2).jsValue().toString(exec));
352 }
353
354 #if ENABLE(JIT)
355 static void updateArithProfileForUnaryArithOp(Instruction* pc, JSValue result, JSValue operand)
356 {
357     ArithProfile& profile = *bitwise_cast<ArithProfile*>(&pc[3].u.operand);
358     profile.observeLHS(operand);
359     ASSERT(result.isNumber());
360     if (!result.isInt32()) {
361         if (operand.isInt32())
362             profile.setObservedInt32Overflow();
363
364         double doubleVal = result.asNumber();
365         if (!doubleVal && std::signbit(doubleVal))
366             profile.setObservedNegZeroDouble();
367         else {
368             profile.setObservedNonNegZeroDouble();
369
370             // The Int52 overflow check here intentionally omits 1ll << 51 as a valid negative Int52 value.
371             // Therefore, we will get a false positive if the result is that value. This is intentionally
372             // done to simplify the checking algorithm.
373             static const int64_t int52OverflowPoint = (1ll << 51);
374             int64_t int64Val = static_cast<int64_t>(std::abs(doubleVal));
375             if (int64Val >= int52OverflowPoint)
376                 profile.setObservedInt52Overflow();
377         }
378     }
379 }
380 #else
381 static void updateArithProfileForUnaryArithOp(Instruction*, JSValue, JSValue) { }
382 #endif
383
384 SLOW_PATH_DECL(slow_path_negate)
385 {
386     BEGIN();
387     JSValue operand = OP_C(2).jsValue();
388     JSValue result = jsNumber(-operand.toNumber(exec));
389     RETURN_WITH_PROFILING(result, {
390         updateArithProfileForUnaryArithOp(pc, result, operand);
391     });
392 }
393
394 #if ENABLE(DFG_JIT)
395 static void updateArithProfileForBinaryArithOp(ExecState* exec, Instruction* pc, JSValue result, JSValue left, JSValue right)
396 {
397     CodeBlock* codeBlock = exec->codeBlock();
398     ArithProfile& profile = *codeBlock->arithProfileForPC(pc);
399
400     if (result.isNumber()) {
401         if (!result.isInt32()) {
402             if (left.isInt32() && right.isInt32())
403                 profile.setObservedInt32Overflow();
404
405             double doubleVal = result.asNumber();
406             if (!doubleVal && std::signbit(doubleVal))
407                 profile.setObservedNegZeroDouble();
408             else {
409                 profile.setObservedNonNegZeroDouble();
410
411                 // The Int52 overflow check here intentionally omits 1ll << 51 as a valid negative Int52 value.
412                 // Therefore, we will get a false positive if the result is that value. This is intentionally
413                 // done to simplify the checking algorithm.
414                 static const int64_t int52OverflowPoint = (1ll << 51);
415                 int64_t int64Val = static_cast<int64_t>(std::abs(doubleVal));
416                 if (int64Val >= int52OverflowPoint)
417                     profile.setObservedInt52Overflow();
418             }
419         }
420     } else
421         profile.setObservedNonNumber();
422 }
423 #else
424 static void updateArithProfileForBinaryArithOp(ExecState*, Instruction*, JSValue, JSValue, JSValue) { }
425 #endif
426
427 SLOW_PATH_DECL(slow_path_to_number)
428 {
429     BEGIN();
430     JSValue argument = OP_C(2).jsValue();
431     JSValue result = jsNumber(argument.toNumber(exec));
432     RETURN_PROFILED(op_to_number, result);
433 }
434
435 SLOW_PATH_DECL(slow_path_add)
436 {
437     BEGIN();
438     JSValue v1 = OP_C(2).jsValue();
439     JSValue v2 = OP_C(3).jsValue();
440     JSValue result;
441
442     ArithProfile& arithProfile = *exec->codeBlock()->arithProfileForPC(pc);
443     arithProfile.observeLHSAndRHS(v1, v2);
444
445     if (v1.isString() && !v2.isObject())
446         result = jsString(exec, asString(v1), v2.toString(exec));
447     else if (v1.isNumber() && v2.isNumber())
448         result = jsNumber(v1.asNumber() + v2.asNumber());
449     else
450         result = jsAddSlowCase(exec, v1, v2);
451
452     RETURN_WITH_PROFILING(result, {
453         updateArithProfileForBinaryArithOp(exec, pc, result, v1, v2);
454     });
455 }
456
457 // The following arithmetic and bitwise operations need to be sure to run
458 // toNumber() on their operands in order.  (A call to toNumber() is idempotent
459 // if an exception is already set on the ExecState.)
460
461 SLOW_PATH_DECL(slow_path_mul)
462 {
463     BEGIN();
464     JSValue left = OP_C(2).jsValue();
465     JSValue right = OP_C(3).jsValue();
466     double a = left.toNumber(exec);
467     if (UNLIKELY(throwScope.exception()))
468         RETURN(JSValue());
469     double b = right.toNumber(exec);
470     JSValue result = jsNumber(a * b);
471     RETURN_WITH_PROFILING(result, {
472         updateArithProfileForBinaryArithOp(exec, pc, result, left, right);
473     });
474 }
475
476 SLOW_PATH_DECL(slow_path_sub)
477 {
478     BEGIN();
479     JSValue left = OP_C(2).jsValue();
480     JSValue right = OP_C(3).jsValue();
481     double a = left.toNumber(exec);
482     if (UNLIKELY(throwScope.exception()))
483         RETURN(JSValue());
484     double b = right.toNumber(exec);
485     JSValue result = jsNumber(a - b);
486     RETURN_WITH_PROFILING(result, {
487         updateArithProfileForBinaryArithOp(exec, pc, result, left, right);
488     });
489 }
490
491 SLOW_PATH_DECL(slow_path_div)
492 {
493     BEGIN();
494     JSValue left = OP_C(2).jsValue();
495     JSValue right = OP_C(3).jsValue();
496     double a = left.toNumber(exec);
497     if (UNLIKELY(throwScope.exception()))
498         RETURN(JSValue());
499     double b = right.toNumber(exec);
500     if (UNLIKELY(throwScope.exception()))
501         RETURN(JSValue());
502     JSValue result = jsNumber(a / b);
503     RETURN_WITH_PROFILING(result, {
504         updateArithProfileForBinaryArithOp(exec, pc, result, left, right);
505     });
506 }
507
508 SLOW_PATH_DECL(slow_path_mod)
509 {
510     BEGIN();
511     double a = OP_C(2).jsValue().toNumber(exec);
512     if (UNLIKELY(throwScope.exception()))
513         RETURN(JSValue());
514     double b = OP_C(3).jsValue().toNumber(exec);
515     RETURN(jsNumber(jsMod(a, b)));
516 }
517
518 SLOW_PATH_DECL(slow_path_pow)
519 {
520     BEGIN();
521     double a = OP_C(2).jsValue().toNumber(exec);
522     if (UNLIKELY(throwScope.exception()))
523         RETURN(JSValue());
524     double b = OP_C(3).jsValue().toNumber(exec);
525     if (UNLIKELY(throwScope.exception()))
526         RETURN(JSValue());
527     RETURN(jsNumber(operationMathPow(a, b)));
528 }
529
530 SLOW_PATH_DECL(slow_path_lshift)
531 {
532     BEGIN();
533     int32_t a = OP_C(2).jsValue().toInt32(exec);
534     if (UNLIKELY(throwScope.exception()))
535         RETURN(JSValue());
536     uint32_t b = OP_C(3).jsValue().toUInt32(exec);
537     RETURN(jsNumber(a << (b & 31)));
538 }
539
540 SLOW_PATH_DECL(slow_path_rshift)
541 {
542     BEGIN();
543     int32_t a = OP_C(2).jsValue().toInt32(exec);
544     if (UNLIKELY(throwScope.exception()))
545         RETURN(JSValue());
546     uint32_t b = OP_C(3).jsValue().toUInt32(exec);
547     RETURN(jsNumber(a >> (b & 31)));
548 }
549
550 SLOW_PATH_DECL(slow_path_urshift)
551 {
552     BEGIN();
553     uint32_t a = OP_C(2).jsValue().toUInt32(exec);
554     if (UNLIKELY(throwScope.exception()))
555         RETURN(JSValue());
556     uint32_t b = OP_C(3).jsValue().toUInt32(exec);
557     RETURN(jsNumber(static_cast<int32_t>(a >> (b & 31))));
558 }
559
560 SLOW_PATH_DECL(slow_path_unsigned)
561 {
562     BEGIN();
563     uint32_t a = OP_C(2).jsValue().toUInt32(exec);
564     RETURN(jsNumber(a));
565 }
566
567 SLOW_PATH_DECL(slow_path_bitand)
568 {
569     BEGIN();
570     int32_t a = OP_C(2).jsValue().toInt32(exec);
571     if (UNLIKELY(throwScope.exception()))
572         RETURN(JSValue());
573     int32_t b = OP_C(3).jsValue().toInt32(exec);
574     RETURN(jsNumber(a & b));
575 }
576
577 SLOW_PATH_DECL(slow_path_bitor)
578 {
579     BEGIN();
580     int32_t a = OP_C(2).jsValue().toInt32(exec);
581     if (UNLIKELY(throwScope.exception()))
582         RETURN(JSValue());
583     int32_t b = OP_C(3).jsValue().toInt32(exec);
584     RETURN(jsNumber(a | b));
585 }
586
587 SLOW_PATH_DECL(slow_path_bitxor)
588 {
589     BEGIN();
590     int32_t a = OP_C(2).jsValue().toInt32(exec);
591     if (UNLIKELY(throwScope.exception()))
592         RETURN(JSValue());
593     int32_t b = OP_C(3).jsValue().toInt32(exec);
594     RETURN(jsNumber(a ^ b));
595 }
596
597 SLOW_PATH_DECL(slow_path_typeof)
598 {
599     BEGIN();
600     RETURN(jsTypeStringForValue(exec, OP_C(2).jsValue()));
601 }
602
603 SLOW_PATH_DECL(slow_path_is_object_or_null)
604 {
605     BEGIN();
606     RETURN(jsBoolean(jsIsObjectTypeOrNull(exec, OP_C(2).jsValue())));
607 }
608
609 SLOW_PATH_DECL(slow_path_is_function)
610 {
611     BEGIN();
612     RETURN(jsBoolean(jsIsFunctionType(OP_C(2).jsValue())));
613 }
614
615 SLOW_PATH_DECL(slow_path_in)
616 {
617     BEGIN();
618     RETURN(jsBoolean(CommonSlowPaths::opIn(exec, OP_C(2).jsValue(), OP_C(3).jsValue())));
619 }
620
621 SLOW_PATH_DECL(slow_path_del_by_val)
622 {
623     BEGIN();
624     JSValue baseValue = OP_C(2).jsValue();
625     JSObject* baseObject = baseValue.toObject(exec);
626     CHECK_EXCEPTION();
627     
628     JSValue subscript = OP_C(3).jsValue();
629     
630     bool couldDelete;
631     
632     uint32_t i;
633     if (subscript.getUInt32(i))
634         couldDelete = baseObject->methodTable(vm)->deletePropertyByIndex(baseObject, exec, i);
635     else {
636         CHECK_EXCEPTION();
637         auto property = subscript.toPropertyKey(exec);
638         CHECK_EXCEPTION();
639         couldDelete = baseObject->methodTable(vm)->deleteProperty(baseObject, exec, property);
640     }
641     
642     if (!couldDelete && exec->codeBlock()->isStrictMode())
643         THROW(createTypeError(exec, UnableToDeletePropertyError));
644     
645     RETURN(jsBoolean(couldDelete));
646 }
647
648 SLOW_PATH_DECL(slow_path_strcat)
649 {
650     BEGIN();
651     RETURN(jsStringFromRegisterArray(exec, &OP(2), pc[3].u.operand));
652 }
653
654 SLOW_PATH_DECL(slow_path_to_primitive)
655 {
656     BEGIN();
657     RETURN(OP_C(2).jsValue().toPrimitive(exec));
658 }
659
660 SLOW_PATH_DECL(slow_path_enter)
661 {
662     BEGIN();
663     CodeBlock* codeBlock = exec->codeBlock();
664     Heap::heap(codeBlock)->writeBarrier(codeBlock);
665     END();
666 }
667
668 SLOW_PATH_DECL(slow_path_get_enumerable_length)
669 {
670     BEGIN();
671     JSValue enumeratorValue = OP(2).jsValue();
672     if (enumeratorValue.isUndefinedOrNull())
673         RETURN(jsNumber(0));
674
675     JSPropertyNameEnumerator* enumerator = jsCast<JSPropertyNameEnumerator*>(enumeratorValue.asCell());
676
677     RETURN(jsNumber(enumerator->indexedLength()));
678 }
679
680 SLOW_PATH_DECL(slow_path_has_indexed_property)
681 {
682     BEGIN();
683     JSObject* base = OP(2).jsValue().toObject(exec);
684     CHECK_EXCEPTION();
685     JSValue property = OP(3).jsValue();
686     pc[4].u.arrayProfile->observeStructure(base->structure(vm));
687     ASSERT(property.isUInt32());
688     RETURN(jsBoolean(base->hasPropertyGeneric(exec, property.asUInt32(), PropertySlot::InternalMethodType::GetOwnProperty)));
689 }
690
691 SLOW_PATH_DECL(slow_path_has_structure_property)
692 {
693     BEGIN();
694     JSObject* base = OP(2).jsValue().toObject(exec);
695     CHECK_EXCEPTION();
696     JSValue property = OP(3).jsValue();
697     ASSERT(property.isString());
698     JSPropertyNameEnumerator* enumerator = jsCast<JSPropertyNameEnumerator*>(OP(4).jsValue().asCell());
699     if (base->structure(vm)->id() == enumerator->cachedStructureID())
700         RETURN(jsBoolean(true));
701     RETURN(jsBoolean(base->hasPropertyGeneric(exec, asString(property.asCell())->toIdentifier(exec), PropertySlot::InternalMethodType::GetOwnProperty)));
702 }
703
704 SLOW_PATH_DECL(slow_path_has_generic_property)
705 {
706     BEGIN();
707     JSObject* base = OP(2).jsValue().toObject(exec);
708     CHECK_EXCEPTION();
709     JSValue property = OP(3).jsValue();
710     bool result;
711     if (property.isString())
712         result = base->hasPropertyGeneric(exec, asString(property.asCell())->toIdentifier(exec), PropertySlot::InternalMethodType::GetOwnProperty);
713     else {
714         ASSERT(property.isUInt32());
715         result = base->hasPropertyGeneric(exec, property.asUInt32(), PropertySlot::InternalMethodType::GetOwnProperty);
716     }
717     RETURN(jsBoolean(result));
718 }
719
720 SLOW_PATH_DECL(slow_path_get_direct_pname)
721 {
722     BEGIN();
723     JSValue baseValue = OP_C(2).jsValue();
724     JSValue property = OP(3).jsValue();
725     ASSERT(property.isString());
726     RETURN(baseValue.get(exec, asString(property)->toIdentifier(exec)));
727 }
728
729 SLOW_PATH_DECL(slow_path_get_property_enumerator)
730 {
731     BEGIN();
732     JSValue baseValue = OP(2).jsValue();
733     if (baseValue.isUndefinedOrNull())
734         RETURN(JSPropertyNameEnumerator::create(vm));
735
736     JSObject* base = baseValue.toObject(exec);
737     CHECK_EXCEPTION();
738
739     RETURN(propertyNameEnumerator(exec, base));
740 }
741
742 SLOW_PATH_DECL(slow_path_next_structure_enumerator_pname)
743 {
744     BEGIN();
745     JSPropertyNameEnumerator* enumerator = jsCast<JSPropertyNameEnumerator*>(OP(2).jsValue().asCell());
746     uint32_t index = OP(3).jsValue().asUInt32();
747
748     JSString* propertyName = nullptr;
749     if (index < enumerator->endStructurePropertyIndex())
750         propertyName = enumerator->propertyNameAtIndex(index);
751     RETURN(propertyName ? propertyName : jsNull());
752 }
753
754 SLOW_PATH_DECL(slow_path_next_generic_enumerator_pname)
755 {
756     BEGIN();
757     JSPropertyNameEnumerator* enumerator = jsCast<JSPropertyNameEnumerator*>(OP(2).jsValue().asCell());
758     uint32_t index = OP(3).jsValue().asUInt32();
759
760     JSString* propertyName = nullptr;
761     if (enumerator->endStructurePropertyIndex() <= index && index < enumerator->endGenericPropertyIndex())
762         propertyName = enumerator->propertyNameAtIndex(index);
763     RETURN(propertyName ? propertyName : jsNull());
764 }
765
766 SLOW_PATH_DECL(slow_path_to_index_string)
767 {
768     BEGIN();
769     RETURN(jsString(exec, Identifier::from(exec, OP(2).jsValue().asUInt32()).string()));
770 }
771
772 SLOW_PATH_DECL(slow_path_profile_type_clear_log)
773 {
774     BEGIN();
775     vm.typeProfilerLog()->processLogEntries(ASCIILiteral("LLInt log full."));
776     END();
777 }
778
779 SLOW_PATH_DECL(slow_path_assert)
780 {
781     BEGIN();
782     RELEASE_ASSERT_WITH_MESSAGE(OP(1).jsValue().asBoolean(), "JS assertion failed at line %d in:\n%s\n", pc[2].u.operand, exec->codeBlock()->sourceCodeForTools().data());
783     END();
784 }
785
786 SLOW_PATH_DECL(slow_path_create_lexical_environment)
787 {
788     BEGIN();
789     int scopeReg = pc[2].u.operand;
790     JSScope* currentScope = exec->uncheckedR(scopeReg).Register::scope();
791     SymbolTable* symbolTable = jsCast<SymbolTable*>(OP_C(3).jsValue());
792     JSValue initialValue = OP_C(4).jsValue();
793     ASSERT(initialValue == jsUndefined() || initialValue == jsTDZValue());
794     JSScope* newScope = JSLexicalEnvironment::create(vm, exec->lexicalGlobalObject(), currentScope, symbolTable, initialValue);
795     RETURN(newScope);
796 }
797
798 SLOW_PATH_DECL(slow_path_push_with_scope)
799 {
800     BEGIN();
801     JSObject* newScope = OP_C(2).jsValue().toObject(exec);
802     CHECK_EXCEPTION();
803
804     int scopeReg = pc[3].u.operand;
805     JSScope* currentScope = exec->uncheckedR(scopeReg).Register::scope();
806     RETURN(JSWithScope::create(vm, exec->lexicalGlobalObject(), newScope, currentScope));
807 }
808
809 SLOW_PATH_DECL(slow_path_resolve_scope)
810 {
811     BEGIN();
812     const Identifier& ident = exec->codeBlock()->identifier(pc[3].u.operand);
813     JSScope* scope = exec->uncheckedR(pc[2].u.operand).Register::scope();
814     JSObject* resolvedScope = JSScope::resolve(exec, scope, ident);
815     // Proxy can throw an error here, e.g. Proxy in with statement's @unscopables.
816     CHECK_EXCEPTION();
817
818     ResolveType resolveType = static_cast<ResolveType>(pc[4].u.operand);
819
820     // ModuleVar does not keep the scope register value alive in DFG.
821     ASSERT(resolveType != ModuleVar);
822
823     if (resolveType == UnresolvedProperty || resolveType == UnresolvedPropertyWithVarInjectionChecks) {
824         if (resolvedScope->isGlobalObject()) {
825             JSGlobalObject* globalObject = jsCast<JSGlobalObject*>(resolvedScope);
826             if (globalObject->hasProperty(exec, ident)) {
827                 ConcurrentJITLocker locker(exec->codeBlock()->m_lock);
828                 if (resolveType == UnresolvedProperty)
829                     pc[4].u.operand = GlobalProperty;
830                 else
831                     pc[4].u.operand = GlobalPropertyWithVarInjectionChecks;
832
833                 pc[6].u.pointer = globalObject;
834             }
835         } else if (resolvedScope->isGlobalLexicalEnvironment()) {
836             JSGlobalLexicalEnvironment* globalLexicalEnvironment = jsCast<JSGlobalLexicalEnvironment*>(resolvedScope);
837             ConcurrentJITLocker locker(exec->codeBlock()->m_lock);
838             if (resolveType == UnresolvedProperty)
839                 pc[4].u.operand = GlobalLexicalVar;
840             else
841                 pc[4].u.operand = GlobalLexicalVarWithVarInjectionChecks;
842             pc[6].u.pointer = globalLexicalEnvironment;
843         }
844     }
845
846     RETURN(resolvedScope);
847 }
848
849 SLOW_PATH_DECL(slow_path_create_rest)
850 {
851     BEGIN();
852     unsigned arraySize = OP_C(2).jsValue().asUInt32();
853     JSGlobalObject* globalObject = exec->lexicalGlobalObject();
854     Structure* structure = globalObject->restParameterStructure();
855     unsigned numParamsToSkip = pc[3].u.unsignedValue;
856     JSValue* argumentsToCopyRegion = exec->addressOfArgumentsStart() + numParamsToSkip;
857     RETURN(constructArray(exec, structure, argumentsToCopyRegion, arraySize));
858 }
859
860 SLOW_PATH_DECL(slow_path_get_by_id_with_this)
861 {
862     BEGIN();
863     const Identifier& ident = exec->codeBlock()->identifier(pc[4].u.operand);
864     JSValue baseValue = OP_C(2).jsValue();
865     JSValue thisVal = OP_C(3).jsValue();
866     PropertySlot slot(thisVal, PropertySlot::PropertySlot::InternalMethodType::Get);
867     JSValue result = baseValue.get(exec, ident, slot);
868     RETURN_PROFILED(op_get_by_id_with_this, result);
869 }
870
871 SLOW_PATH_DECL(slow_path_get_by_val_with_this)
872 {
873     BEGIN();
874
875     JSValue baseValue = OP_C(2).jsValue();
876     JSValue thisValue = OP_C(3).jsValue();
877     JSValue subscript = OP_C(4).jsValue();
878
879     if (LIKELY(baseValue.isCell() && subscript.isString())) {
880         VM& vm = exec->vm();
881         Structure& structure = *baseValue.asCell()->structure(vm);
882         if (JSCell::canUseFastGetOwnProperty(structure)) {
883             if (RefPtr<AtomicStringImpl> existingAtomicString = asString(subscript)->toExistingAtomicString(exec)) {
884                 if (JSValue result = baseValue.asCell()->fastGetOwnProperty(vm, structure, existingAtomicString.get()))
885                     RETURN_PROFILED(op_get_by_val_with_this, result);
886             }
887         }
888     }
889     
890     PropertySlot slot(thisValue, PropertySlot::PropertySlot::InternalMethodType::Get);
891     if (subscript.isUInt32()) {
892         uint32_t i = subscript.asUInt32();
893         if (isJSString(baseValue) && asString(baseValue)->canGetIndex(i))
894             RETURN_PROFILED(op_get_by_val_with_this, asString(baseValue)->getIndex(exec, i));
895         
896         RETURN_PROFILED(op_get_by_val_with_this, baseValue.get(exec, i, slot));
897     }
898
899     baseValue.requireObjectCoercible(exec);
900     CHECK_EXCEPTION();
901     auto property = subscript.toPropertyKey(exec);
902     CHECK_EXCEPTION();
903     RETURN_PROFILED(op_get_by_val_with_this, baseValue.get(exec, property, slot));
904 }
905
906 SLOW_PATH_DECL(slow_path_put_by_id_with_this)
907 {
908     BEGIN();
909     CodeBlock* codeBlock = exec->codeBlock();
910     const Identifier& ident = codeBlock->identifier(pc[3].u.operand);
911     JSValue baseValue = OP_C(1).jsValue();
912     JSValue thisVal = OP_C(2).jsValue();
913     JSValue putValue = OP_C(4).jsValue();
914     PutPropertySlot slot(thisVal, codeBlock->isStrictMode(), codeBlock->putByIdContext());
915     baseValue.putInline(exec, ident, putValue, slot);
916     END();
917 }
918
919 SLOW_PATH_DECL(slow_path_put_by_val_with_this)
920 {
921     BEGIN();
922     JSValue baseValue = OP_C(1).jsValue();
923     JSValue thisValue = OP_C(2).jsValue();
924     JSValue subscript = OP_C(3).jsValue();
925     JSValue value = OP_C(4).jsValue();
926     
927     auto property = subscript.toPropertyKey(exec);
928     CHECK_EXCEPTION();
929     PutPropertySlot slot(thisValue, exec->codeBlock()->isStrictMode());
930     baseValue.put(exec, property, value, slot);
931     END();
932 }
933
934 SLOW_PATH_DECL(slow_path_define_data_property)
935 {
936     BEGIN();
937     JSObject* base = asObject(OP_C(1).jsValue());
938     JSValue property = OP_C(2).jsValue();
939     JSValue value = OP_C(3).jsValue();
940     JSValue attributes = OP_C(4).jsValue();
941     ASSERT(attributes.isInt32());
942
943     auto propertyName = property.toPropertyKey(exec);
944     CHECK_EXCEPTION();
945     PropertyDescriptor descriptor = toPropertyDescriptor(value, jsUndefined(), jsUndefined(), DefinePropertyAttributes(attributes.asInt32()));
946     ASSERT((descriptor.attributes() & Accessor) || (!descriptor.isAccessorDescriptor()));
947     base->methodTable(vm)->defineOwnProperty(base, exec, propertyName, descriptor, true);
948     END();
949 }
950
951 SLOW_PATH_DECL(slow_path_define_accessor_property)
952 {
953     BEGIN();
954     JSObject* base = asObject(OP_C(1).jsValue());
955     JSValue property = OP_C(2).jsValue();
956     JSValue getter = OP_C(3).jsValue();
957     JSValue setter = OP_C(4).jsValue();
958     JSValue attributes = OP_C(5).jsValue();
959     ASSERT(attributes.isInt32());
960
961     auto propertyName = property.toPropertyKey(exec);
962     CHECK_EXCEPTION();
963     PropertyDescriptor descriptor = toPropertyDescriptor(jsUndefined(), getter, setter, DefinePropertyAttributes(attributes.asInt32()));
964     ASSERT((descriptor.attributes() & Accessor) || (!descriptor.isAccessorDescriptor()));
965     base->methodTable(vm)->defineOwnProperty(base, exec, propertyName, descriptor, true);
966     END();
967 }
968
969 SLOW_PATH_DECL(slow_path_throw_static_error)
970 {
971     BEGIN();
972     JSValue errorMessageValue = OP_C(1).jsValue();
973     RELEASE_ASSERT(errorMessageValue.isString());
974     String errorMessage = asString(errorMessageValue)->value(exec);
975     ErrorType errorType = static_cast<ErrorType>(pc[2].u.unsignedValue);
976     THROW(createError(exec, errorType, errorMessage));
977 }
978
979 } // namespace JSC