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