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