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