ee5ada27950ce94c11b885225a3bf028e756aacf
[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(exec, WTF::get<JSBigInt*>(leftNumeric), WTF::get<JSBigInt*>(rightNumeric));
567             CHECK_EXCEPTION();
568             RETURN_WITH_PROFILING(result, {
569                 updateArithProfileForBinaryArithOp(exec, pc, result, left, right);
570             });
571         }
572
573         THROW(createTypeError(exec, "Invalid mix of BigInt and other type in subtraction."));
574     }
575
576     JSValue result = jsNumber(WTF::get<double>(leftNumeric) - WTF::get<double>(rightNumeric));
577     RETURN_WITH_PROFILING(result, {
578         updateArithProfileForBinaryArithOp(exec, pc, result, left, right);
579     });
580 }
581
582 SLOW_PATH_DECL(slow_path_div)
583 {
584     BEGIN();
585     auto bytecode = pc->as<OpDiv>();
586     JSValue left = GET_C(bytecode.lhs).jsValue();
587     JSValue right = GET_C(bytecode.rhs).jsValue();
588     auto leftNumeric = left.toNumeric(exec);
589     CHECK_EXCEPTION();
590     auto rightNumeric = right.toNumeric(exec);
591     CHECK_EXCEPTION();
592
593     if (WTF::holds_alternative<JSBigInt*>(leftNumeric) || WTF::holds_alternative<JSBigInt*>(rightNumeric)) {
594         if (WTF::holds_alternative<JSBigInt*>(leftNumeric) && WTF::holds_alternative<JSBigInt*>(rightNumeric)) {
595             JSBigInt* result = JSBigInt::divide(exec, WTF::get<JSBigInt*>(leftNumeric), WTF::get<JSBigInt*>(rightNumeric));
596             CHECK_EXCEPTION();
597             RETURN_WITH_PROFILING(result, {
598                 updateArithProfileForBinaryArithOp(exec, pc, result, left, right);
599             });
600         }
601
602         THROW(createTypeError(exec, "Invalid mix of BigInt and other type in division."));
603     }
604
605     double a = WTF::get<double>(leftNumeric);
606     double b = WTF::get<double>(rightNumeric);
607     JSValue result = jsNumber(a / b);
608     RETURN_WITH_PROFILING(result, {
609         updateArithProfileForBinaryArithOp(exec, pc, result, left, right);
610     });
611 }
612
613 SLOW_PATH_DECL(slow_path_mod)
614 {
615     BEGIN();
616     auto bytecode = pc->as<OpMod>();
617     JSValue left = GET_C(bytecode.lhs).jsValue();
618     JSValue right = GET_C(bytecode.rhs).jsValue();
619     auto leftNumeric = left.toNumeric(exec);
620     CHECK_EXCEPTION();
621     auto rightNumeric = right.toNumeric(exec);
622     CHECK_EXCEPTION();
623     
624     if (WTF::holds_alternative<JSBigInt*>(leftNumeric) || WTF::holds_alternative<JSBigInt*>(rightNumeric)) {
625         if (WTF::holds_alternative<JSBigInt*>(leftNumeric) && WTF::holds_alternative<JSBigInt*>(rightNumeric)) {
626             JSBigInt* result = JSBigInt::remainder(exec, WTF::get<JSBigInt*>(leftNumeric), WTF::get<JSBigInt*>(rightNumeric));
627             CHECK_EXCEPTION();
628             RETURN(result);
629         }
630
631         THROW(createTypeError(exec, "Invalid mix of BigInt and other type in remainder operation."));
632     }
633     
634     double a = WTF::get<double>(leftNumeric);
635     double b = WTF::get<double>(rightNumeric);
636     RETURN(jsNumber(jsMod(a, b)));
637 }
638
639 SLOW_PATH_DECL(slow_path_pow)
640 {
641     BEGIN();
642     auto bytecode = pc->as<OpPow>();
643     double a = GET_C(bytecode.lhs).jsValue().toNumber(exec);
644     if (UNLIKELY(throwScope.exception()))
645         RETURN(JSValue());
646     double b = GET_C(bytecode.rhs).jsValue().toNumber(exec);
647     if (UNLIKELY(throwScope.exception()))
648         RETURN(JSValue());
649     RETURN(jsNumber(operationMathPow(a, b)));
650 }
651
652 SLOW_PATH_DECL(slow_path_lshift)
653 {
654     BEGIN();
655     auto bytecode = pc->as<OpLshift>();
656     int32_t a = GET_C(bytecode.lhs).jsValue().toInt32(exec);
657     if (UNLIKELY(throwScope.exception()))
658         RETURN(JSValue());
659     uint32_t b = GET_C(bytecode.rhs).jsValue().toUInt32(exec);
660     RETURN(jsNumber(a << (b & 31)));
661 }
662
663 SLOW_PATH_DECL(slow_path_rshift)
664 {
665     BEGIN();
666     auto bytecode = pc->as<OpRshift>();
667     int32_t a = GET_C(bytecode.lhs).jsValue().toInt32(exec);
668     if (UNLIKELY(throwScope.exception()))
669         RETURN(JSValue());
670     uint32_t b = GET_C(bytecode.rhs).jsValue().toUInt32(exec);
671     RETURN(jsNumber(a >> (b & 31)));
672 }
673
674 SLOW_PATH_DECL(slow_path_urshift)
675 {
676     BEGIN();
677     auto bytecode = pc->as<OpUrshift>();
678     uint32_t a = GET_C(bytecode.lhs).jsValue().toUInt32(exec);
679     if (UNLIKELY(throwScope.exception()))
680         RETURN(JSValue());
681     uint32_t b = GET_C(bytecode.rhs).jsValue().toUInt32(exec);
682     RETURN(jsNumber(static_cast<int32_t>(a >> (b & 31))));
683 }
684
685 SLOW_PATH_DECL(slow_path_unsigned)
686 {
687     BEGIN();
688     auto bytecode = pc->as<OpUnsigned>();
689     uint32_t a = GET_C(bytecode.operand).jsValue().toUInt32(exec);
690     RETURN(jsNumber(a));
691 }
692
693 SLOW_PATH_DECL(slow_path_bitand)
694 {
695     BEGIN();
696     auto bytecode = pc->as<OpBitand>();
697     auto leftNumeric = GET_C(bytecode.lhs).jsValue().toBigIntOrInt32(exec);
698     CHECK_EXCEPTION();
699     auto rightNumeric = GET_C(bytecode.rhs).jsValue().toBigIntOrInt32(exec);
700     CHECK_EXCEPTION();
701     if (WTF::holds_alternative<JSBigInt*>(leftNumeric) || WTF::holds_alternative<JSBigInt*>(rightNumeric)) {
702         if (WTF::holds_alternative<JSBigInt*>(leftNumeric) && WTF::holds_alternative<JSBigInt*>(rightNumeric)) {
703             JSBigInt* result = JSBigInt::bitwiseAnd(exec, WTF::get<JSBigInt*>(leftNumeric), WTF::get<JSBigInt*>(rightNumeric));
704             CHECK_EXCEPTION();
705             RETURN_PROFILED(result);
706         }
707
708         THROW(createTypeError(exec, "Invalid mix of BigInt and other type in bitwise 'and' operation."));
709     }
710
711     RETURN_PROFILED(jsNumber(WTF::get<int32_t>(leftNumeric) & WTF::get<int32_t>(rightNumeric)));
712 }
713
714 SLOW_PATH_DECL(slow_path_bitor)
715 {
716     BEGIN();
717     auto bytecode = pc->as<OpBitor>();
718     auto leftNumeric = GET_C(bytecode.lhs).jsValue().toBigIntOrInt32(exec);
719     CHECK_EXCEPTION();
720     auto rightNumeric = GET_C(bytecode.rhs).jsValue().toBigIntOrInt32(exec);
721     CHECK_EXCEPTION();
722     if (WTF::holds_alternative<JSBigInt*>(leftNumeric) || WTF::holds_alternative<JSBigInt*>(rightNumeric)) {
723         if (WTF::holds_alternative<JSBigInt*>(leftNumeric) && WTF::holds_alternative<JSBigInt*>(rightNumeric)) {
724             JSBigInt* result = JSBigInt::bitwiseOr(exec, WTF::get<JSBigInt*>(leftNumeric), WTF::get<JSBigInt*>(rightNumeric));
725             CHECK_EXCEPTION();
726             RETURN_PROFILED(result);
727         }
728
729         THROW(createTypeError(exec, "Invalid mix of BigInt and other type in bitwise 'or' operation."));
730     }
731
732     RETURN_PROFILED(jsNumber(WTF::get<int32_t>(leftNumeric) | WTF::get<int32_t>(rightNumeric)));
733 }
734
735 SLOW_PATH_DECL(slow_path_bitxor)
736 {
737     BEGIN();
738     auto bytecode = pc->as<OpBitxor>();
739     auto leftNumeric = GET_C(bytecode.lhs).jsValue().toBigIntOrInt32(exec);
740     CHECK_EXCEPTION();
741     auto rightNumeric = GET_C(bytecode.rhs).jsValue().toBigIntOrInt32(exec);
742     CHECK_EXCEPTION();
743     if (WTF::holds_alternative<JSBigInt*>(leftNumeric) || WTF::holds_alternative<JSBigInt*>(rightNumeric)) {
744         if (WTF::holds_alternative<JSBigInt*>(leftNumeric) && WTF::holds_alternative<JSBigInt*>(rightNumeric)) {
745             JSBigInt* result = JSBigInt::bitwiseXor(exec, WTF::get<JSBigInt*>(leftNumeric), WTF::get<JSBigInt*>(rightNumeric));
746             CHECK_EXCEPTION();
747             RETURN(result);
748         }
749
750         THROW(createTypeError(exec, "Invalid mix of BigInt and other type in bitwise 'xor' operation."));
751     }
752
753     RETURN(jsNumber(WTF::get<int32_t>(leftNumeric) ^ WTF::get<int32_t>(rightNumeric)));
754 }
755
756 SLOW_PATH_DECL(slow_path_typeof)
757 {
758     BEGIN();
759     auto bytecode = pc->as<OpTypeof>();
760     RETURN(jsTypeStringForValue(exec, GET_C(bytecode.value).jsValue()));
761 }
762
763 SLOW_PATH_DECL(slow_path_is_object_or_null)
764 {
765     BEGIN();
766     auto bytecode = pc->as<OpIsObjectOrNull>();
767     RETURN(jsBoolean(jsIsObjectTypeOrNull(exec, GET_C(bytecode.operand).jsValue())));
768 }
769
770 SLOW_PATH_DECL(slow_path_is_function)
771 {
772     BEGIN();
773     auto bytecode = pc->as<OpIsFunction>();
774     RETURN(jsBoolean(GET_C(bytecode.operand).jsValue().isFunction(vm)));
775 }
776
777 SLOW_PATH_DECL(slow_path_in_by_val)
778 {
779     BEGIN();
780     auto bytecode = pc->as<OpInByVal>();
781     auto& metadata = bytecode.metadata(exec);
782     RETURN(jsBoolean(CommonSlowPaths::opInByVal(exec, GET_C(bytecode.base).jsValue(), GET_C(bytecode.property).jsValue(), &metadata.arrayProfile)));
783 }
784
785 SLOW_PATH_DECL(slow_path_in_by_id)
786 {
787     BEGIN();
788
789     auto bytecode = pc->as<OpInById>();
790     JSValue baseValue = GET_C(bytecode.base).jsValue();
791     if (!baseValue.isObject())
792         THROW(createInvalidInParameterError(exec, baseValue));
793
794     RETURN(jsBoolean(asObject(baseValue)->hasProperty(exec, exec->codeBlock()->identifier(bytecode.property))));
795 }
796
797 SLOW_PATH_DECL(slow_path_del_by_val)
798 {
799     BEGIN();
800     auto bytecode = pc->as<OpDelByVal>();
801     JSValue baseValue = GET_C(bytecode.base).jsValue();
802     JSObject* baseObject = baseValue.toObject(exec);
803     CHECK_EXCEPTION();
804     
805     JSValue subscript = GET_C(bytecode.property).jsValue();
806     
807     bool couldDelete;
808     
809     uint32_t i;
810     if (subscript.getUInt32(i))
811         couldDelete = baseObject->methodTable(vm)->deletePropertyByIndex(baseObject, exec, i);
812     else {
813         CHECK_EXCEPTION();
814         auto property = subscript.toPropertyKey(exec);
815         CHECK_EXCEPTION();
816         couldDelete = baseObject->methodTable(vm)->deleteProperty(baseObject, exec, property);
817     }
818     
819     if (!couldDelete && exec->codeBlock()->isStrictMode())
820         THROW(createTypeError(exec, UnableToDeletePropertyError));
821     
822     RETURN(jsBoolean(couldDelete));
823 }
824
825 SLOW_PATH_DECL(slow_path_strcat)
826 {
827     BEGIN();
828     auto bytecode = pc->as<OpStrcat>();
829     RETURN(jsStringFromRegisterArray(exec, &GET(bytecode.src), bytecode.count));
830 }
831
832 SLOW_PATH_DECL(slow_path_to_primitive)
833 {
834     BEGIN();
835     auto bytecode = pc->as<OpToPrimitive>();
836     RETURN(GET_C(bytecode.src).jsValue().toPrimitive(exec));
837 }
838
839 SLOW_PATH_DECL(slow_path_enter)
840 {
841     BEGIN();
842     CodeBlock* codeBlock = exec->codeBlock();
843     Heap::heap(codeBlock)->writeBarrier(codeBlock);
844     END();
845 }
846
847 SLOW_PATH_DECL(slow_path_get_enumerable_length)
848 {
849     BEGIN();
850     auto bytecode = pc->as<OpGetEnumerableLength>();
851     JSValue enumeratorValue = GET(bytecode.base).jsValue();
852     if (enumeratorValue.isUndefinedOrNull())
853         RETURN(jsNumber(0));
854
855     JSPropertyNameEnumerator* enumerator = jsCast<JSPropertyNameEnumerator*>(enumeratorValue.asCell());
856
857     RETURN(jsNumber(enumerator->indexedLength()));
858 }
859
860 SLOW_PATH_DECL(slow_path_has_indexed_property)
861 {
862     BEGIN();
863     auto bytecode = pc->as<OpHasIndexedProperty>();
864     auto& metadata = bytecode.metadata(exec);
865     JSObject* base = GET(bytecode.base).jsValue().toObject(exec);
866     CHECK_EXCEPTION();
867     JSValue property = GET(bytecode.property).jsValue();
868     metadata.arrayProfile.observeStructure(base->structure(vm));
869     ASSERT(property.isUInt32());
870     RETURN(jsBoolean(base->hasPropertyGeneric(exec, property.asUInt32(), PropertySlot::InternalMethodType::GetOwnProperty)));
871 }
872
873 SLOW_PATH_DECL(slow_path_has_structure_property)
874 {
875     BEGIN();
876     auto bytecode = pc->as<OpHasStructureProperty>();
877     JSObject* base = GET(bytecode.base).jsValue().toObject(exec);
878     CHECK_EXCEPTION();
879     JSValue property = GET(bytecode.property).jsValue();
880     ASSERT(property.isString());
881     JSPropertyNameEnumerator* enumerator = jsCast<JSPropertyNameEnumerator*>(GET(bytecode.enumerator).jsValue().asCell());
882     if (base->structure(vm)->id() == enumerator->cachedStructureID())
883         RETURN(jsBoolean(true));
884     JSString* string = asString(property);
885     auto propertyName = string->toIdentifier(exec);
886     CHECK_EXCEPTION();
887     RETURN(jsBoolean(base->hasPropertyGeneric(exec, propertyName, PropertySlot::InternalMethodType::GetOwnProperty)));
888 }
889
890 SLOW_PATH_DECL(slow_path_has_generic_property)
891 {
892     BEGIN();
893     auto bytecode = pc->as<OpHasGenericProperty>();
894     JSObject* base = GET(bytecode.base).jsValue().toObject(exec);
895     CHECK_EXCEPTION();
896     JSValue property = GET(bytecode.property).jsValue();
897     ASSERT(property.isString());
898     JSString* string = asString(property);
899     auto propertyName = string->toIdentifier(exec);
900     CHECK_EXCEPTION();
901     RETURN(jsBoolean(base->hasPropertyGeneric(exec, propertyName, PropertySlot::InternalMethodType::GetOwnProperty)));
902 }
903
904 SLOW_PATH_DECL(slow_path_get_direct_pname)
905 {
906     BEGIN();
907     auto bytecode = pc->as<OpGetDirectPname>();
908     JSValue baseValue = GET_C(bytecode.base).jsValue();
909     JSValue property = GET(bytecode.property).jsValue();
910     ASSERT(property.isString());
911     JSString* string = asString(property);
912     auto propertyName = string->toIdentifier(exec);
913     CHECK_EXCEPTION();
914     RETURN(baseValue.get(exec, propertyName));
915 }
916
917 SLOW_PATH_DECL(slow_path_get_property_enumerator)
918 {
919     BEGIN();
920     auto bytecode = pc->as<OpGetPropertyEnumerator>();
921     JSValue baseValue = GET(bytecode.base).jsValue();
922     if (baseValue.isUndefinedOrNull())
923         RETURN(JSPropertyNameEnumerator::create(vm));
924
925     JSObject* base = baseValue.toObject(exec);
926     CHECK_EXCEPTION();
927
928     RETURN(propertyNameEnumerator(exec, base));
929 }
930
931 SLOW_PATH_DECL(slow_path_enumerator_structure_pname)
932 {
933     BEGIN();
934     auto bytecode = pc->as<OpEnumeratorStructurePname>();
935     JSPropertyNameEnumerator* enumerator = jsCast<JSPropertyNameEnumerator*>(GET(bytecode.enumerator).jsValue().asCell());
936     uint32_t index = GET(bytecode.index).jsValue().asUInt32();
937
938     JSString* propertyName = nullptr;
939     if (index < enumerator->endStructurePropertyIndex())
940         propertyName = enumerator->propertyNameAtIndex(index);
941     RETURN(propertyName ? propertyName : jsNull());
942 }
943
944 SLOW_PATH_DECL(slow_path_enumerator_generic_pname)
945 {
946     BEGIN();
947     auto bytecode = pc->as<OpEnumeratorGenericPname>();
948     JSPropertyNameEnumerator* enumerator = jsCast<JSPropertyNameEnumerator*>(GET(bytecode.enumerator).jsValue().asCell());
949     uint32_t index = GET(bytecode.index).jsValue().asUInt32();
950
951     JSString* propertyName = nullptr;
952     if (enumerator->endStructurePropertyIndex() <= index && index < enumerator->endGenericPropertyIndex())
953         propertyName = enumerator->propertyNameAtIndex(index);
954     RETURN(propertyName ? propertyName : jsNull());
955 }
956
957 SLOW_PATH_DECL(slow_path_to_index_string)
958 {
959     BEGIN();
960     auto bytecode = pc->as<OpToIndexString>();
961     RETURN(jsString(exec, Identifier::from(exec, GET(bytecode.index).jsValue().asUInt32()).string()));
962 }
963
964 SLOW_PATH_DECL(slow_path_profile_type_clear_log)
965 {
966     BEGIN();
967     vm.typeProfilerLog()->processLogEntries("LLInt log full."_s);
968     END();
969 }
970
971 SLOW_PATH_DECL(slow_path_unreachable)
972 {
973     BEGIN();
974     UNREACHABLE_FOR_PLATFORM();
975     END();
976 }
977
978 SLOW_PATH_DECL(slow_path_create_lexical_environment)
979 {
980     BEGIN();
981     auto bytecode = pc->as<OpCreateLexicalEnvironment>();
982     int scopeReg = bytecode.scope.offset();
983     JSScope* currentScope = exec->uncheckedR(scopeReg).Register::scope();
984     SymbolTable* symbolTable = jsCast<SymbolTable*>(GET_C(bytecode.symbolTable).jsValue());
985     JSValue initialValue = GET_C(bytecode.initialValue).jsValue();
986     ASSERT(initialValue == jsUndefined() || initialValue == jsTDZValue());
987     JSScope* newScope = JSLexicalEnvironment::create(vm, exec->lexicalGlobalObject(), currentScope, symbolTable, initialValue);
988     RETURN(newScope);
989 }
990
991 SLOW_PATH_DECL(slow_path_push_with_scope)
992 {
993     BEGIN();
994     auto bytecode = pc->as<OpPushWithScope>();
995     JSObject* newScope = GET_C(bytecode.newScope).jsValue().toObject(exec);
996     CHECK_EXCEPTION();
997
998     int scopeReg = bytecode.currentScope.offset();
999     JSScope* currentScope = exec->uncheckedR(scopeReg).Register::scope();
1000     RETURN(JSWithScope::create(vm, exec->lexicalGlobalObject(), currentScope, newScope));
1001 }
1002
1003 SLOW_PATH_DECL(slow_path_resolve_scope_for_hoisting_func_decl_in_eval)
1004 {
1005     BEGIN();
1006     auto bytecode = pc->as<OpResolveScopeForHoistingFuncDeclInEval>();
1007     const Identifier& ident = exec->codeBlock()->identifier(bytecode.property);
1008     JSScope* scope = exec->uncheckedR(bytecode.scope.offset()).Register::scope();
1009     JSValue resolvedScope = JSScope::resolveScopeForHoistingFuncDeclInEval(exec, scope, ident);
1010
1011     CHECK_EXCEPTION();
1012
1013     RETURN(resolvedScope);
1014 }
1015
1016 SLOW_PATH_DECL(slow_path_resolve_scope)
1017 {
1018     BEGIN();
1019     auto bytecode = pc->as<OpResolveScope>();
1020     auto& metadata = bytecode.metadata(exec);
1021     const Identifier& ident = exec->codeBlock()->identifier(bytecode.var);
1022     JSScope* scope = exec->uncheckedR(bytecode.scope.offset()).Register::scope();
1023     JSObject* resolvedScope = JSScope::resolve(exec, scope, ident);
1024     // Proxy can throw an error here, e.g. Proxy in with statement's @unscopables.
1025     CHECK_EXCEPTION();
1026
1027     ResolveType resolveType = metadata.resolveType;
1028
1029     // ModuleVar does not keep the scope register value alive in DFG.
1030     ASSERT(resolveType != ModuleVar);
1031
1032     if (resolveType == UnresolvedProperty || resolveType == UnresolvedPropertyWithVarInjectionChecks) {
1033         if (resolvedScope->isGlobalObject()) {
1034             JSGlobalObject* globalObject = jsCast<JSGlobalObject*>(resolvedScope);
1035             bool hasProperty = globalObject->hasProperty(exec, ident);
1036             CHECK_EXCEPTION();
1037             if (hasProperty) {
1038                 ConcurrentJSLocker locker(exec->codeBlock()->m_lock);
1039                 if (resolveType == UnresolvedProperty)
1040                     metadata.resolveType = GlobalProperty;
1041                 else
1042                     metadata.resolveType = GlobalPropertyWithVarInjectionChecks;
1043
1044                 metadata.globalObject = globalObject;
1045             }
1046         } else if (resolvedScope->isGlobalLexicalEnvironment()) {
1047             JSGlobalLexicalEnvironment* globalLexicalEnvironment = jsCast<JSGlobalLexicalEnvironment*>(resolvedScope);
1048             ConcurrentJSLocker locker(exec->codeBlock()->m_lock);
1049             if (resolveType == UnresolvedProperty)
1050                 metadata.resolveType = GlobalLexicalVar;
1051             else
1052                 metadata.resolveType = GlobalLexicalVarWithVarInjectionChecks;
1053             metadata.globalLexicalEnvironment = globalLexicalEnvironment;
1054         }
1055     }
1056
1057     RETURN(resolvedScope);
1058 }
1059
1060 SLOW_PATH_DECL(slow_path_create_rest)
1061 {
1062     BEGIN();
1063     auto bytecode = pc->as<OpCreateRest>();
1064     unsigned arraySize = GET_C(bytecode.arraySize).jsValue().asUInt32();
1065     JSGlobalObject* globalObject = exec->lexicalGlobalObject();
1066     Structure* structure = globalObject->restParameterStructure();
1067     unsigned numParamsToSkip = bytecode.numParametersToSkip;
1068     JSValue* argumentsToCopyRegion = exec->addressOfArgumentsStart() + numParamsToSkip;
1069     RETURN(constructArray(exec, structure, argumentsToCopyRegion, arraySize));
1070 }
1071
1072 SLOW_PATH_DECL(slow_path_get_by_id_with_this)
1073 {
1074     BEGIN();
1075     auto bytecode = pc->as<OpGetByIdWithThis>();
1076     const Identifier& ident = exec->codeBlock()->identifier(bytecode.property);
1077     JSValue baseValue = GET_C(bytecode.base).jsValue();
1078     JSValue thisVal = GET_C(bytecode.thisValue).jsValue();
1079     PropertySlot slot(thisVal, PropertySlot::PropertySlot::InternalMethodType::Get);
1080     JSValue result = baseValue.get(exec, ident, slot);
1081     RETURN_PROFILED(result);
1082 }
1083
1084 SLOW_PATH_DECL(slow_path_get_by_val_with_this)
1085 {
1086     BEGIN();
1087
1088     auto bytecode = pc->as<OpGetByValWithThis>();
1089     JSValue baseValue = GET_C(bytecode.base).jsValue();
1090     JSValue thisValue = GET_C(bytecode.thisValue).jsValue();
1091     JSValue subscript = GET_C(bytecode.property).jsValue();
1092
1093     if (LIKELY(baseValue.isCell() && subscript.isString())) {
1094         Structure& structure = *baseValue.asCell()->structure(vm);
1095         if (JSCell::canUseFastGetOwnProperty(structure)) {
1096             if (RefPtr<AtomicStringImpl> existingAtomicString = asString(subscript)->toExistingAtomicString(exec)) {
1097                 if (JSValue result = baseValue.asCell()->fastGetOwnProperty(vm, structure, existingAtomicString.get()))
1098                     RETURN_PROFILED(result);
1099             }
1100         }
1101     }
1102     
1103     PropertySlot slot(thisValue, PropertySlot::PropertySlot::InternalMethodType::Get);
1104     if (subscript.isUInt32()) {
1105         uint32_t i = subscript.asUInt32();
1106         if (isJSString(baseValue) && asString(baseValue)->canGetIndex(i))
1107             RETURN_PROFILED(asString(baseValue)->getIndex(exec, i));
1108         
1109         RETURN_PROFILED(baseValue.get(exec, i, slot));
1110     }
1111
1112     baseValue.requireObjectCoercible(exec);
1113     CHECK_EXCEPTION();
1114     auto property = subscript.toPropertyKey(exec);
1115     CHECK_EXCEPTION();
1116     RETURN_PROFILED(baseValue.get(exec, property, slot));
1117 }
1118
1119 SLOW_PATH_DECL(slow_path_put_by_id_with_this)
1120 {
1121     BEGIN();
1122     auto bytecode = pc->as<OpPutByIdWithThis>();
1123     CodeBlock* codeBlock = exec->codeBlock();
1124     const Identifier& ident = codeBlock->identifier(bytecode.property);
1125     JSValue baseValue = GET_C(bytecode.base).jsValue();
1126     JSValue thisVal = GET_C(bytecode.thisValue).jsValue();
1127     JSValue putValue = GET_C(bytecode.value).jsValue();
1128     PutPropertySlot slot(thisVal, codeBlock->isStrictMode(), codeBlock->putByIdContext());
1129     baseValue.putInline(exec, ident, putValue, slot);
1130     END();
1131 }
1132
1133 SLOW_PATH_DECL(slow_path_put_by_val_with_this)
1134 {
1135     BEGIN();
1136     auto bytecode = pc->as<OpPutByValWithThis>();
1137     JSValue baseValue = GET_C(bytecode.base).jsValue();
1138     JSValue thisValue = GET_C(bytecode.thisValue).jsValue();
1139     JSValue subscript = GET_C(bytecode.property).jsValue();
1140     JSValue value = GET_C(bytecode.value).jsValue();
1141     
1142     auto property = subscript.toPropertyKey(exec);
1143     CHECK_EXCEPTION();
1144     PutPropertySlot slot(thisValue, exec->codeBlock()->isStrictMode());
1145     baseValue.put(exec, property, value, slot);
1146     END();
1147 }
1148
1149 SLOW_PATH_DECL(slow_path_define_data_property)
1150 {
1151     BEGIN();
1152     auto bytecode = pc->as<OpDefineDataProperty>();
1153     JSObject* base = asObject(GET_C(bytecode.base).jsValue());
1154     JSValue property = GET_C(bytecode.property).jsValue();
1155     JSValue value = GET_C(bytecode.value).jsValue();
1156     JSValue attributes = GET_C(bytecode.attributes).jsValue();
1157     ASSERT(attributes.isInt32());
1158
1159     auto propertyName = property.toPropertyKey(exec);
1160     CHECK_EXCEPTION();
1161     PropertyDescriptor descriptor = toPropertyDescriptor(value, jsUndefined(), jsUndefined(), DefinePropertyAttributes(attributes.asInt32()));
1162     ASSERT((descriptor.attributes() & PropertyAttribute::Accessor) || (!descriptor.isAccessorDescriptor()));
1163     base->methodTable(vm)->defineOwnProperty(base, exec, propertyName, descriptor, true);
1164     END();
1165 }
1166
1167 SLOW_PATH_DECL(slow_path_define_accessor_property)
1168 {
1169     BEGIN();
1170     auto bytecode = pc->as<OpDefineAccessorProperty>();
1171     JSObject* base = asObject(GET_C(bytecode.base).jsValue());
1172     JSValue property = GET_C(bytecode.property).jsValue();
1173     JSValue getter = GET_C(bytecode.getter).jsValue();
1174     JSValue setter = GET_C(bytecode.setter).jsValue();
1175     JSValue attributes = GET_C(bytecode.attributes).jsValue();
1176     ASSERT(attributes.isInt32());
1177
1178     auto propertyName = property.toPropertyKey(exec);
1179     CHECK_EXCEPTION();
1180     PropertyDescriptor descriptor = toPropertyDescriptor(jsUndefined(), getter, setter, DefinePropertyAttributes(attributes.asInt32()));
1181     ASSERT((descriptor.attributes() & PropertyAttribute::Accessor) || (!descriptor.isAccessorDescriptor()));
1182     base->methodTable(vm)->defineOwnProperty(base, exec, propertyName, descriptor, true);
1183     END();
1184 }
1185
1186 SLOW_PATH_DECL(slow_path_throw_static_error)
1187 {
1188     BEGIN();
1189     auto bytecode = pc->as<OpThrowStaticError>();
1190     JSValue errorMessageValue = GET_C(bytecode.message).jsValue();
1191     RELEASE_ASSERT(errorMessageValue.isString());
1192     String errorMessage = asString(errorMessageValue)->value(exec);
1193     ErrorType errorType = bytecode.errorType;
1194     THROW(createError(exec, errorType, errorMessage));
1195 }
1196
1197 SLOW_PATH_DECL(slow_path_new_array_with_spread)
1198 {
1199     BEGIN();
1200     auto bytecode = pc->as<OpNewArrayWithSpread>();
1201     int numItems = bytecode.argc;
1202     ASSERT(numItems >= 0);
1203     const BitVector& bitVector = exec->codeBlock()->unlinkedCodeBlock()->bitVector(bytecode.bitVector);
1204
1205     JSValue* values = bitwise_cast<JSValue*>(&GET(bytecode.argv));
1206
1207     Checked<unsigned, RecordOverflow> checkedArraySize = 0;
1208     for (int i = 0; i < numItems; i++) {
1209         if (bitVector.get(i)) {
1210             JSValue value = values[-i];
1211             JSFixedArray* array = jsCast<JSFixedArray*>(value);
1212             checkedArraySize += array->size();
1213         } else
1214             checkedArraySize += 1;
1215     }
1216     if (UNLIKELY(checkedArraySize.hasOverflowed()))
1217         THROW(createOutOfMemoryError(exec));
1218
1219     unsigned arraySize = checkedArraySize.unsafeGet();
1220     JSGlobalObject* globalObject = exec->lexicalGlobalObject();
1221     Structure* structure = globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithContiguous);
1222
1223     JSArray* result = JSArray::tryCreate(vm, structure, arraySize);
1224     if (UNLIKELY(!result))
1225         THROW(createOutOfMemoryError(exec));
1226     CHECK_EXCEPTION();
1227
1228     unsigned index = 0;
1229     for (int i = 0; i < numItems; i++) {
1230         JSValue value = values[-i];
1231         if (bitVector.get(i)) {
1232             // We are spreading.
1233             JSFixedArray* array = jsCast<JSFixedArray*>(value);
1234             for (unsigned i = 0; i < array->size(); i++) {
1235                 RELEASE_ASSERT(array->get(i));
1236                 result->putDirectIndex(exec, index, array->get(i));
1237                 CHECK_EXCEPTION();
1238                 ++index;
1239             }
1240         } else {
1241             // We are not spreading.
1242             result->putDirectIndex(exec, index, value);
1243             CHECK_EXCEPTION();
1244             ++index;
1245         }
1246     }
1247
1248     RETURN(result);
1249 }
1250
1251 SLOW_PATH_DECL(slow_path_new_array_buffer)
1252 {
1253     BEGIN();
1254     auto bytecode = pc->as<OpNewArrayBuffer>();
1255     ASSERT(exec->codeBlock()->isConstantRegisterIndex(bytecode.immutableButterfly.offset()));
1256     JSImmutableButterfly* immutableButterfly = bitwise_cast<JSImmutableButterfly*>(GET_C(bytecode.immutableButterfly).jsValue().asCell());
1257     auto& profile = bytecode.metadata(exec).arrayAllocationProfile;
1258
1259     IndexingType indexingMode = profile.selectIndexingType();
1260     Structure* structure = exec->lexicalGlobalObject()->arrayStructureForIndexingTypeDuringAllocation(indexingMode);
1261     ASSERT(isCopyOnWrite(indexingMode));
1262     ASSERT(!structure->outOfLineCapacity());
1263
1264     if (UNLIKELY(immutableButterfly->indexingMode() != indexingMode)) {
1265         auto* newButterfly = JSImmutableButterfly::create(vm, indexingMode, immutableButterfly->length());
1266         for (unsigned i = 0; i < immutableButterfly->length(); ++i)
1267             newButterfly->setIndex(vm, i, immutableButterfly->get(i));
1268         immutableButterfly = newButterfly;
1269         CodeBlock* codeBlock = exec->codeBlock();
1270
1271         // FIXME: This is kinda gross and only works because we can't inline new_array_bufffer in the baseline.
1272         // We also cannot allocate a new butterfly from compilation threads since it's invalid to allocate cells from
1273         // a compilation thread.
1274         WTF::storeStoreFence();
1275         codeBlock->constantRegister(bytecode.immutableButterfly.offset()).set(vm, codeBlock, immutableButterfly);
1276         WTF::storeStoreFence();
1277     }
1278
1279     JSArray* result = CommonSlowPaths::allocateNewArrayBuffer(vm, structure, immutableButterfly);
1280     ASSERT(isCopyOnWrite(result->indexingMode()) || exec->lexicalGlobalObject()->isHavingABadTime());
1281     ArrayAllocationProfile::updateLastAllocationFor(&profile, result);
1282     RETURN(result);
1283 }
1284
1285 SLOW_PATH_DECL(slow_path_spread)
1286 {
1287     BEGIN();
1288
1289     auto bytecode = pc->as<OpSpread>();
1290     JSValue iterable = GET_C(bytecode.argument).jsValue();
1291
1292     if (iterable.isCell() && isJSArray(iterable.asCell())) {
1293         JSArray* array = jsCast<JSArray*>(iterable);
1294         if (array->isIteratorProtocolFastAndNonObservable()) {
1295             // JSFixedArray::createFromArray does not consult the prototype chain,
1296             // so we must be sure that not consulting the prototype chain would
1297             // produce the same value during iteration.
1298             RETURN(JSFixedArray::createFromArray(exec, vm, array));
1299         }
1300     }
1301
1302     JSGlobalObject* globalObject = exec->lexicalGlobalObject();
1303
1304     JSArray* array;
1305     {
1306         JSFunction* iterationFunction = globalObject->iteratorProtocolFunction();
1307         CallData callData;
1308         CallType callType = JSC::getCallData(vm, iterationFunction, callData);
1309         ASSERT(callType != CallType::None);
1310
1311         MarkedArgumentBuffer arguments;
1312         arguments.append(iterable);
1313         ASSERT(!arguments.hasOverflowed());
1314         JSValue arrayResult = call(exec, iterationFunction, callType, callData, jsNull(), arguments);
1315         CHECK_EXCEPTION();
1316         array = jsCast<JSArray*>(arrayResult);
1317     }
1318
1319     RETURN(JSFixedArray::createFromArray(exec, vm, array));
1320 }
1321
1322 } // namespace JSC