We should support CreateThis in the FTL
[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, 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(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     auto leftNumeric = left.toNumeric(exec);
521     CHECK_EXCEPTION();
522     auto rightNumeric = right.toNumeric(exec);
523     CHECK_EXCEPTION();
524
525     if (WTF::holds_alternative<JSBigInt*>(leftNumeric) || WTF::holds_alternative<JSBigInt*>(rightNumeric)) {
526         if (WTF::holds_alternative<JSBigInt*>(leftNumeric) && WTF::holds_alternative<JSBigInt*>(rightNumeric)) {
527             JSBigInt* result = JSBigInt::sub(vm, WTF::get<JSBigInt*>(leftNumeric), WTF::get<JSBigInt*>(rightNumeric));
528             RETURN_WITH_PROFILING(result, {
529                 updateArithProfileForBinaryArithOp(exec, pc, result, left, right);
530             });
531         }
532
533         THROW(createTypeError(exec, "Invalid mix of BigInt and other type in subtraction."));
534     }
535
536     JSValue result = jsNumber(WTF::get<double>(leftNumeric) - WTF::get<double>(rightNumeric));
537     RETURN_WITH_PROFILING(result, {
538         updateArithProfileForBinaryArithOp(exec, pc, result, left, right);
539     });
540 }
541
542 SLOW_PATH_DECL(slow_path_div)
543 {
544     BEGIN();
545     JSValue left = OP_C(2).jsValue();
546     JSValue right = OP_C(3).jsValue();
547     auto leftNumeric = left.toNumeric(exec);
548     CHECK_EXCEPTION();
549     auto rightNumeric = right.toNumeric(exec);
550     CHECK_EXCEPTION();
551
552     if (WTF::holds_alternative<JSBigInt*>(leftNumeric) || WTF::holds_alternative<JSBigInt*>(rightNumeric)) {
553         if (WTF::holds_alternative<JSBigInt*>(leftNumeric) && WTF::holds_alternative<JSBigInt*>(rightNumeric)) {
554             JSBigInt* result = JSBigInt::divide(exec, WTF::get<JSBigInt*>(leftNumeric), WTF::get<JSBigInt*>(rightNumeric));
555             CHECK_EXCEPTION();
556             RETURN_WITH_PROFILING(result, {
557                 updateArithProfileForBinaryArithOp(exec, pc, result, left, right);
558             });
559         }
560
561         THROW(createTypeError(exec, "Invalid mix of BigInt and other type in division."));
562     }
563
564     double a = WTF::get<double>(leftNumeric);
565     double b = WTF::get<double>(rightNumeric);
566     JSValue result = jsNumber(a / b);
567     RETURN_WITH_PROFILING(result, {
568         updateArithProfileForBinaryArithOp(exec, pc, result, left, right);
569     });
570 }
571
572 SLOW_PATH_DECL(slow_path_mod)
573 {
574     BEGIN();
575     JSValue left = OP_C(2).jsValue();
576     JSValue right = OP_C(3).jsValue();
577     auto leftNumeric = left.toNumeric(exec);
578     CHECK_EXCEPTION();
579     auto rightNumeric = right.toNumeric(exec);
580     CHECK_EXCEPTION();
581     
582     if (WTF::holds_alternative<JSBigInt*>(leftNumeric) || WTF::holds_alternative<JSBigInt*>(rightNumeric)) {
583         if (WTF::holds_alternative<JSBigInt*>(leftNumeric) && WTF::holds_alternative<JSBigInt*>(rightNumeric)) {
584             JSBigInt* result = JSBigInt::remainder(exec, WTF::get<JSBigInt*>(leftNumeric), WTF::get<JSBigInt*>(rightNumeric));
585             CHECK_EXCEPTION();
586             RETURN(result);
587         }
588
589         THROW(createTypeError(exec, "Invalid mix of BigInt and other type in remainder operation."));
590     }
591     
592     double a = WTF::get<double>(leftNumeric);
593     double b = WTF::get<double>(rightNumeric);
594     RETURN(jsNumber(jsMod(a, b)));
595 }
596
597 SLOW_PATH_DECL(slow_path_pow)
598 {
599     BEGIN();
600     double a = OP_C(2).jsValue().toNumber(exec);
601     if (UNLIKELY(throwScope.exception()))
602         RETURN(JSValue());
603     double b = OP_C(3).jsValue().toNumber(exec);
604     if (UNLIKELY(throwScope.exception()))
605         RETURN(JSValue());
606     RETURN(jsNumber(operationMathPow(a, b)));
607 }
608
609 SLOW_PATH_DECL(slow_path_lshift)
610 {
611     BEGIN();
612     int32_t a = OP_C(2).jsValue().toInt32(exec);
613     if (UNLIKELY(throwScope.exception()))
614         RETURN(JSValue());
615     uint32_t b = OP_C(3).jsValue().toUInt32(exec);
616     RETURN(jsNumber(a << (b & 31)));
617 }
618
619 SLOW_PATH_DECL(slow_path_rshift)
620 {
621     BEGIN();
622     int32_t a = OP_C(2).jsValue().toInt32(exec);
623     if (UNLIKELY(throwScope.exception()))
624         RETURN(JSValue());
625     uint32_t b = OP_C(3).jsValue().toUInt32(exec);
626     RETURN(jsNumber(a >> (b & 31)));
627 }
628
629 SLOW_PATH_DECL(slow_path_urshift)
630 {
631     BEGIN();
632     uint32_t a = OP_C(2).jsValue().toUInt32(exec);
633     if (UNLIKELY(throwScope.exception()))
634         RETURN(JSValue());
635     uint32_t b = OP_C(3).jsValue().toUInt32(exec);
636     RETURN(jsNumber(static_cast<int32_t>(a >> (b & 31))));
637 }
638
639 SLOW_PATH_DECL(slow_path_unsigned)
640 {
641     BEGIN();
642     uint32_t a = OP_C(2).jsValue().toUInt32(exec);
643     RETURN(jsNumber(a));
644 }
645
646 SLOW_PATH_DECL(slow_path_bitand)
647 {
648     BEGIN();
649     int32_t a = OP_C(2).jsValue().toInt32(exec);
650     if (UNLIKELY(throwScope.exception()))
651         RETURN(JSValue());
652     int32_t b = OP_C(3).jsValue().toInt32(exec);
653     RETURN(jsNumber(a & b));
654 }
655
656 SLOW_PATH_DECL(slow_path_bitor)
657 {
658     BEGIN();
659     int32_t a = OP_C(2).jsValue().toInt32(exec);
660     if (UNLIKELY(throwScope.exception()))
661         RETURN(JSValue());
662     int32_t b = OP_C(3).jsValue().toInt32(exec);
663     RETURN(jsNumber(a | b));
664 }
665
666 SLOW_PATH_DECL(slow_path_bitxor)
667 {
668     BEGIN();
669     int32_t a = OP_C(2).jsValue().toInt32(exec);
670     if (UNLIKELY(throwScope.exception()))
671         RETURN(JSValue());
672     int32_t b = OP_C(3).jsValue().toInt32(exec);
673     RETURN(jsNumber(a ^ b));
674 }
675
676 SLOW_PATH_DECL(slow_path_typeof)
677 {
678     BEGIN();
679     RETURN(jsTypeStringForValue(exec, OP_C(2).jsValue()));
680 }
681
682 SLOW_PATH_DECL(slow_path_is_object_or_null)
683 {
684     BEGIN();
685     RETURN(jsBoolean(jsIsObjectTypeOrNull(exec, OP_C(2).jsValue())));
686 }
687
688 SLOW_PATH_DECL(slow_path_is_function)
689 {
690     BEGIN();
691     RETURN(jsBoolean(OP_C(2).jsValue().isFunction(vm)));
692 }
693
694 SLOW_PATH_DECL(slow_path_in_by_val)
695 {
696     BEGIN();
697     RETURN(jsBoolean(CommonSlowPaths::opInByVal(exec, OP_C(2).jsValue(), OP_C(3).jsValue(), pc[4].u.arrayProfile)));
698 }
699
700 SLOW_PATH_DECL(slow_path_in_by_id)
701 {
702     BEGIN();
703
704     JSValue baseValue = OP_C(2).jsValue();
705     if (!baseValue.isObject())
706         THROW(createInvalidInParameterError(exec, baseValue));
707
708     RETURN(jsBoolean(asObject(baseValue)->hasProperty(exec, exec->codeBlock()->identifier(pc[3].u.operand))));
709 }
710
711 SLOW_PATH_DECL(slow_path_del_by_val)
712 {
713     BEGIN();
714     JSValue baseValue = OP_C(2).jsValue();
715     JSObject* baseObject = baseValue.toObject(exec);
716     CHECK_EXCEPTION();
717     
718     JSValue subscript = OP_C(3).jsValue();
719     
720     bool couldDelete;
721     
722     uint32_t i;
723     if (subscript.getUInt32(i))
724         couldDelete = baseObject->methodTable(vm)->deletePropertyByIndex(baseObject, exec, i);
725     else {
726         CHECK_EXCEPTION();
727         auto property = subscript.toPropertyKey(exec);
728         CHECK_EXCEPTION();
729         couldDelete = baseObject->methodTable(vm)->deleteProperty(baseObject, exec, property);
730     }
731     
732     if (!couldDelete && exec->codeBlock()->isStrictMode())
733         THROW(createTypeError(exec, UnableToDeletePropertyError));
734     
735     RETURN(jsBoolean(couldDelete));
736 }
737
738 SLOW_PATH_DECL(slow_path_strcat)
739 {
740     BEGIN();
741     RETURN(jsStringFromRegisterArray(exec, &OP(2), pc[3].u.operand));
742 }
743
744 SLOW_PATH_DECL(slow_path_to_primitive)
745 {
746     BEGIN();
747     RETURN(OP_C(2).jsValue().toPrimitive(exec));
748 }
749
750 SLOW_PATH_DECL(slow_path_enter)
751 {
752     BEGIN();
753     CodeBlock* codeBlock = exec->codeBlock();
754     Heap::heap(codeBlock)->writeBarrier(codeBlock);
755     END();
756 }
757
758 SLOW_PATH_DECL(slow_path_get_enumerable_length)
759 {
760     BEGIN();
761     JSValue enumeratorValue = OP(2).jsValue();
762     if (enumeratorValue.isUndefinedOrNull())
763         RETURN(jsNumber(0));
764
765     JSPropertyNameEnumerator* enumerator = jsCast<JSPropertyNameEnumerator*>(enumeratorValue.asCell());
766
767     RETURN(jsNumber(enumerator->indexedLength()));
768 }
769
770 SLOW_PATH_DECL(slow_path_has_indexed_property)
771 {
772     BEGIN();
773     JSObject* base = OP(2).jsValue().toObject(exec);
774     CHECK_EXCEPTION();
775     JSValue property = OP(3).jsValue();
776     pc[4].u.arrayProfile->observeStructure(base->structure(vm));
777     ASSERT(property.isUInt32());
778     RETURN(jsBoolean(base->hasPropertyGeneric(exec, property.asUInt32(), PropertySlot::InternalMethodType::GetOwnProperty)));
779 }
780
781 SLOW_PATH_DECL(slow_path_has_structure_property)
782 {
783     BEGIN();
784     JSObject* base = OP(2).jsValue().toObject(exec);
785     CHECK_EXCEPTION();
786     JSValue property = OP(3).jsValue();
787     ASSERT(property.isString());
788     JSPropertyNameEnumerator* enumerator = jsCast<JSPropertyNameEnumerator*>(OP(4).jsValue().asCell());
789     if (base->structure(vm)->id() == enumerator->cachedStructureID())
790         RETURN(jsBoolean(true));
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_has_generic_property)
798 {
799     BEGIN();
800     JSObject* base = OP(2).jsValue().toObject(exec);
801     CHECK_EXCEPTION();
802     JSValue property = OP(3).jsValue();
803     JSString* string = asString(property);
804     auto propertyName = string->toIdentifier(exec);
805     CHECK_EXCEPTION();
806     RETURN(jsBoolean(base->hasPropertyGeneric(exec, propertyName, PropertySlot::InternalMethodType::GetOwnProperty)));
807 }
808
809 SLOW_PATH_DECL(slow_path_get_direct_pname)
810 {
811     BEGIN();
812     JSValue baseValue = OP_C(2).jsValue();
813     JSValue property = OP(3).jsValue();
814     JSString* string = asString(property);
815     auto propertyName = string->toIdentifier(exec);
816     CHECK_EXCEPTION();
817     RETURN(baseValue.get(exec, propertyName));
818 }
819
820 SLOW_PATH_DECL(slow_path_get_property_enumerator)
821 {
822     BEGIN();
823     JSValue baseValue = OP(2).jsValue();
824     if (baseValue.isUndefinedOrNull())
825         RETURN(JSPropertyNameEnumerator::create(vm));
826
827     JSObject* base = baseValue.toObject(exec);
828     CHECK_EXCEPTION();
829
830     RETURN(propertyNameEnumerator(exec, base));
831 }
832
833 SLOW_PATH_DECL(slow_path_next_structure_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 (index < enumerator->endStructurePropertyIndex())
841         propertyName = enumerator->propertyNameAtIndex(index);
842     RETURN(propertyName ? propertyName : jsNull());
843 }
844
845 SLOW_PATH_DECL(slow_path_next_generic_enumerator_pname)
846 {
847     BEGIN();
848     JSPropertyNameEnumerator* enumerator = jsCast<JSPropertyNameEnumerator*>(OP(2).jsValue().asCell());
849     uint32_t index = OP(3).jsValue().asUInt32();
850
851     JSString* propertyName = nullptr;
852     if (enumerator->endStructurePropertyIndex() <= index && index < enumerator->endGenericPropertyIndex())
853         propertyName = enumerator->propertyNameAtIndex(index);
854     RETURN(propertyName ? propertyName : jsNull());
855 }
856
857 SLOW_PATH_DECL(slow_path_to_index_string)
858 {
859     BEGIN();
860     RETURN(jsString(exec, Identifier::from(exec, OP(2).jsValue().asUInt32()).string()));
861 }
862
863 SLOW_PATH_DECL(slow_path_profile_type_clear_log)
864 {
865     BEGIN();
866     vm.typeProfilerLog()->processLogEntries("LLInt log full."_s);
867     END();
868 }
869
870 SLOW_PATH_DECL(slow_path_unreachable)
871 {
872     BEGIN();
873     UNREACHABLE_FOR_PLATFORM();
874     END();
875 }
876
877 SLOW_PATH_DECL(slow_path_create_lexical_environment)
878 {
879     BEGIN();
880     int scopeReg = pc[2].u.operand;
881     JSScope* currentScope = exec->uncheckedR(scopeReg).Register::scope();
882     SymbolTable* symbolTable = jsCast<SymbolTable*>(OP_C(3).jsValue());
883     JSValue initialValue = OP_C(4).jsValue();
884     ASSERT(initialValue == jsUndefined() || initialValue == jsTDZValue());
885     JSScope* newScope = JSLexicalEnvironment::create(vm, exec->lexicalGlobalObject(), currentScope, symbolTable, initialValue);
886     RETURN(newScope);
887 }
888
889 SLOW_PATH_DECL(slow_path_push_with_scope)
890 {
891     BEGIN();
892     JSObject* newScope = OP_C(3).jsValue().toObject(exec);
893     CHECK_EXCEPTION();
894
895     int scopeReg = pc[2].u.operand;
896     JSScope* currentScope = exec->uncheckedR(scopeReg).Register::scope();
897     RETURN(JSWithScope::create(vm, exec->lexicalGlobalObject(), currentScope, newScope));
898 }
899
900 SLOW_PATH_DECL(slow_path_resolve_scope_for_hoisting_func_decl_in_eval)
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     JSValue resolvedScope = JSScope::resolveScopeForHoistingFuncDeclInEval(exec, scope, ident);
906
907     CHECK_EXCEPTION();
908
909     RETURN(resolvedScope);
910 }
911
912 SLOW_PATH_DECL(slow_path_resolve_scope)
913 {
914     BEGIN();
915     const Identifier& ident = exec->codeBlock()->identifier(pc[3].u.operand);
916     JSScope* scope = exec->uncheckedR(pc[2].u.operand).Register::scope();
917     JSObject* resolvedScope = JSScope::resolve(exec, scope, ident);
918     // Proxy can throw an error here, e.g. Proxy in with statement's @unscopables.
919     CHECK_EXCEPTION();
920
921     ResolveType resolveType = static_cast<ResolveType>(pc[4].u.operand);
922
923     // ModuleVar does not keep the scope register value alive in DFG.
924     ASSERT(resolveType != ModuleVar);
925
926     if (resolveType == UnresolvedProperty || resolveType == UnresolvedPropertyWithVarInjectionChecks) {
927         if (resolvedScope->isGlobalObject()) {
928             JSGlobalObject* globalObject = jsCast<JSGlobalObject*>(resolvedScope);
929             bool hasProperty = globalObject->hasProperty(exec, ident);
930             CHECK_EXCEPTION();
931             if (hasProperty) {
932                 ConcurrentJSLocker locker(exec->codeBlock()->m_lock);
933                 if (resolveType == UnresolvedProperty)
934                     pc[4].u.operand = GlobalProperty;
935                 else
936                     pc[4].u.operand = GlobalPropertyWithVarInjectionChecks;
937
938                 pc[6].u.pointer = globalObject;
939             }
940         } else if (resolvedScope->isGlobalLexicalEnvironment()) {
941             JSGlobalLexicalEnvironment* globalLexicalEnvironment = jsCast<JSGlobalLexicalEnvironment*>(resolvedScope);
942             ConcurrentJSLocker locker(exec->codeBlock()->m_lock);
943             if (resolveType == UnresolvedProperty)
944                 pc[4].u.operand = GlobalLexicalVar;
945             else
946                 pc[4].u.operand = GlobalLexicalVarWithVarInjectionChecks;
947             pc[6].u.pointer = globalLexicalEnvironment;
948         }
949     }
950
951     RETURN(resolvedScope);
952 }
953
954 SLOW_PATH_DECL(slow_path_create_rest)
955 {
956     BEGIN();
957     unsigned arraySize = OP_C(2).jsValue().asUInt32();
958     JSGlobalObject* globalObject = exec->lexicalGlobalObject();
959     Structure* structure = globalObject->restParameterStructure();
960     unsigned numParamsToSkip = pc[3].u.unsignedValue;
961     JSValue* argumentsToCopyRegion = exec->addressOfArgumentsStart() + numParamsToSkip;
962     RETURN(constructArray(exec, structure, argumentsToCopyRegion, arraySize));
963 }
964
965 SLOW_PATH_DECL(slow_path_get_by_id_with_this)
966 {
967     BEGIN();
968     const Identifier& ident = exec->codeBlock()->identifier(pc[4].u.operand);
969     JSValue baseValue = OP_C(2).jsValue();
970     JSValue thisVal = OP_C(3).jsValue();
971     PropertySlot slot(thisVal, PropertySlot::PropertySlot::InternalMethodType::Get);
972     JSValue result = baseValue.get(exec, ident, slot);
973     RETURN_PROFILED(op_get_by_id_with_this, result);
974 }
975
976 SLOW_PATH_DECL(slow_path_get_by_val_with_this)
977 {
978     BEGIN();
979
980     JSValue baseValue = OP_C(2).jsValue();
981     JSValue thisValue = OP_C(3).jsValue();
982     JSValue subscript = OP_C(4).jsValue();
983
984     if (LIKELY(baseValue.isCell() && subscript.isString())) {
985         Structure& structure = *baseValue.asCell()->structure(vm);
986         if (JSCell::canUseFastGetOwnProperty(structure)) {
987             if (RefPtr<AtomicStringImpl> existingAtomicString = asString(subscript)->toExistingAtomicString(exec)) {
988                 if (JSValue result = baseValue.asCell()->fastGetOwnProperty(vm, structure, existingAtomicString.get()))
989                     RETURN_PROFILED(op_get_by_val_with_this, result);
990             }
991         }
992     }
993     
994     PropertySlot slot(thisValue, PropertySlot::PropertySlot::InternalMethodType::Get);
995     if (subscript.isUInt32()) {
996         uint32_t i = subscript.asUInt32();
997         if (isJSString(baseValue) && asString(baseValue)->canGetIndex(i))
998             RETURN_PROFILED(op_get_by_val_with_this, asString(baseValue)->getIndex(exec, i));
999         
1000         RETURN_PROFILED(op_get_by_val_with_this, baseValue.get(exec, i, slot));
1001     }
1002
1003     baseValue.requireObjectCoercible(exec);
1004     CHECK_EXCEPTION();
1005     auto property = subscript.toPropertyKey(exec);
1006     CHECK_EXCEPTION();
1007     RETURN_PROFILED(op_get_by_val_with_this, baseValue.get(exec, property, slot));
1008 }
1009
1010 SLOW_PATH_DECL(slow_path_put_by_id_with_this)
1011 {
1012     BEGIN();
1013     CodeBlock* codeBlock = exec->codeBlock();
1014     const Identifier& ident = codeBlock->identifier(pc[3].u.operand);
1015     JSValue baseValue = OP_C(1).jsValue();
1016     JSValue thisVal = OP_C(2).jsValue();
1017     JSValue putValue = OP_C(4).jsValue();
1018     PutPropertySlot slot(thisVal, codeBlock->isStrictMode(), codeBlock->putByIdContext());
1019     baseValue.putInline(exec, ident, putValue, slot);
1020     END();
1021 }
1022
1023 SLOW_PATH_DECL(slow_path_put_by_val_with_this)
1024 {
1025     BEGIN();
1026     JSValue baseValue = OP_C(1).jsValue();
1027     JSValue thisValue = OP_C(2).jsValue();
1028     JSValue subscript = OP_C(3).jsValue();
1029     JSValue value = OP_C(4).jsValue();
1030     
1031     auto property = subscript.toPropertyKey(exec);
1032     CHECK_EXCEPTION();
1033     PutPropertySlot slot(thisValue, exec->codeBlock()->isStrictMode());
1034     baseValue.put(exec, property, value, slot);
1035     END();
1036 }
1037
1038 SLOW_PATH_DECL(slow_path_define_data_property)
1039 {
1040     BEGIN();
1041     JSObject* base = asObject(OP_C(1).jsValue());
1042     JSValue property = OP_C(2).jsValue();
1043     JSValue value = OP_C(3).jsValue();
1044     JSValue attributes = OP_C(4).jsValue();
1045     ASSERT(attributes.isInt32());
1046
1047     auto propertyName = property.toPropertyKey(exec);
1048     CHECK_EXCEPTION();
1049     PropertyDescriptor descriptor = toPropertyDescriptor(value, jsUndefined(), jsUndefined(), DefinePropertyAttributes(attributes.asInt32()));
1050     ASSERT((descriptor.attributes() & PropertyAttribute::Accessor) || (!descriptor.isAccessorDescriptor()));
1051     base->methodTable(vm)->defineOwnProperty(base, exec, propertyName, descriptor, true);
1052     END();
1053 }
1054
1055 SLOW_PATH_DECL(slow_path_define_accessor_property)
1056 {
1057     BEGIN();
1058     JSObject* base = asObject(OP_C(1).jsValue());
1059     JSValue property = OP_C(2).jsValue();
1060     JSValue getter = OP_C(3).jsValue();
1061     JSValue setter = OP_C(4).jsValue();
1062     JSValue attributes = OP_C(5).jsValue();
1063     ASSERT(attributes.isInt32());
1064
1065     auto propertyName = property.toPropertyKey(exec);
1066     CHECK_EXCEPTION();
1067     PropertyDescriptor descriptor = toPropertyDescriptor(jsUndefined(), getter, setter, DefinePropertyAttributes(attributes.asInt32()));
1068     ASSERT((descriptor.attributes() & PropertyAttribute::Accessor) || (!descriptor.isAccessorDescriptor()));
1069     base->methodTable(vm)->defineOwnProperty(base, exec, propertyName, descriptor, true);
1070     END();
1071 }
1072
1073 SLOW_PATH_DECL(slow_path_throw_static_error)
1074 {
1075     BEGIN();
1076     JSValue errorMessageValue = OP_C(1).jsValue();
1077     RELEASE_ASSERT(errorMessageValue.isString());
1078     String errorMessage = asString(errorMessageValue)->value(exec);
1079     ErrorType errorType = static_cast<ErrorType>(pc[2].u.unsignedValue);
1080     THROW(createError(exec, errorType, errorMessage));
1081 }
1082
1083 SLOW_PATH_DECL(slow_path_new_array_with_spread)
1084 {
1085     BEGIN();
1086     int numItems = pc[3].u.operand;
1087     ASSERT(numItems >= 0);
1088     const BitVector& bitVector = exec->codeBlock()->unlinkedCodeBlock()->bitVector(pc[4].u.unsignedValue);
1089
1090     JSValue* values = bitwise_cast<JSValue*>(&OP(2));
1091
1092     Checked<unsigned, RecordOverflow> checkedArraySize = 0;
1093     for (int i = 0; i < numItems; i++) {
1094         if (bitVector.get(i)) {
1095             JSValue value = values[-i];
1096             JSFixedArray* array = jsCast<JSFixedArray*>(value);
1097             checkedArraySize += array->size();
1098         } else
1099             checkedArraySize += 1;
1100     }
1101     if (UNLIKELY(checkedArraySize.hasOverflowed()))
1102         THROW(createOutOfMemoryError(exec));
1103
1104     unsigned arraySize = checkedArraySize.unsafeGet();
1105     JSGlobalObject* globalObject = exec->lexicalGlobalObject();
1106     Structure* structure = globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithContiguous);
1107
1108     JSArray* result = JSArray::tryCreate(vm, structure, arraySize);
1109     if (UNLIKELY(!result))
1110         THROW(createOutOfMemoryError(exec));
1111     CHECK_EXCEPTION();
1112
1113     unsigned index = 0;
1114     for (int i = 0; i < numItems; i++) {
1115         JSValue value = values[-i];
1116         if (bitVector.get(i)) {
1117             // We are spreading.
1118             JSFixedArray* array = jsCast<JSFixedArray*>(value);
1119             for (unsigned i = 0; i < array->size(); i++) {
1120                 RELEASE_ASSERT(array->get(i));
1121                 result->putDirectIndex(exec, index, array->get(i));
1122                 CHECK_EXCEPTION();
1123                 ++index;
1124             }
1125         } else {
1126             // We are not spreading.
1127             result->putDirectIndex(exec, index, value);
1128             CHECK_EXCEPTION();
1129             ++index;
1130         }
1131     }
1132
1133     RETURN(result);
1134 }
1135
1136 SLOW_PATH_DECL(slow_path_new_array_buffer)
1137 {
1138     BEGIN();
1139     auto* newArrayBuffer = bitwise_cast<OpNewArrayBuffer*>(pc);
1140     ASSERT(exec->codeBlock()->isConstantRegisterIndex(newArrayBuffer->immutableButterfly()));
1141     JSImmutableButterfly* immutableButterfly = bitwise_cast<JSImmutableButterfly*>(GET_C(newArrayBuffer->immutableButterfly()).jsValue().asCell());
1142     auto* profile = newArrayBuffer->profile();
1143
1144     IndexingType indexingMode = profile->selectIndexingType();
1145     Structure* structure = exec->lexicalGlobalObject()->arrayStructureForIndexingTypeDuringAllocation(indexingMode);
1146     ASSERT(isCopyOnWrite(indexingMode));
1147     ASSERT(!structure->outOfLineCapacity());
1148
1149     if (UNLIKELY(immutableButterfly->indexingMode() != indexingMode)) {
1150         auto* newButterfly = JSImmutableButterfly::create(vm, indexingMode, immutableButterfly->length());
1151         for (unsigned i = 0; i < immutableButterfly->length(); ++i)
1152             newButterfly->setIndex(vm, i, immutableButterfly->get(i));
1153         immutableButterfly = newButterfly;
1154         CodeBlock* codeBlock = exec->codeBlock();
1155
1156         // FIXME: This is kinda gross and only works because we can't inline new_array_bufffer in the baseline.
1157         // We also cannot allocate a new butterfly from compilation threads since it's invalid to allocate cells from
1158         // a compilation thread.
1159         WTF::storeStoreFence();
1160         codeBlock->constantRegister(newArrayBuffer->immutableButterfly()).set(vm, codeBlock, immutableButterfly);
1161         WTF::storeStoreFence();
1162     }
1163
1164     JSArray* result = CommonSlowPaths::allocateNewArrayBuffer(vm, structure, immutableButterfly);
1165     ASSERT(isCopyOnWrite(result->indexingMode()) || exec->lexicalGlobalObject()->isHavingABadTime());
1166     ArrayAllocationProfile::updateLastAllocationFor(profile, result);
1167     RETURN(result);
1168 }
1169
1170 SLOW_PATH_DECL(slow_path_spread)
1171 {
1172     BEGIN();
1173
1174     JSValue iterable = OP_C(2).jsValue();
1175
1176     if (iterable.isCell() && isJSArray(iterable.asCell())) {
1177         JSArray* array = jsCast<JSArray*>(iterable);
1178         if (array->isIteratorProtocolFastAndNonObservable()) {
1179             // JSFixedArray::createFromArray does not consult the prototype chain,
1180             // so we must be sure that not consulting the prototype chain would
1181             // produce the same value during iteration.
1182             RETURN(JSFixedArray::createFromArray(exec, vm, array));
1183         }
1184     }
1185
1186     JSGlobalObject* globalObject = exec->lexicalGlobalObject();
1187
1188     JSArray* array;
1189     {
1190         JSFunction* iterationFunction = globalObject->iteratorProtocolFunction();
1191         CallData callData;
1192         CallType callType = JSC::getCallData(vm, iterationFunction, callData);
1193         ASSERT(callType != CallType::None);
1194
1195         MarkedArgumentBuffer arguments;
1196         arguments.append(iterable);
1197         ASSERT(!arguments.hasOverflowed());
1198         JSValue arrayResult = call(exec, iterationFunction, callType, callData, jsNull(), arguments);
1199         CHECK_EXCEPTION();
1200         array = jsCast<JSArray*>(arrayResult);
1201     }
1202
1203     RETURN(JSFixedArray::createFromArray(exec, vm, array));
1204 }
1205
1206 } // namespace JSC