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