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