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