[DFG] DFG should handle String#toString
[WebKit-https.git] / Source / JavaScriptCore / dfg / DFGOperations.cpp
1 /*
2  * Copyright (C) 2011-2018 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #include "config.h"
27 #include "DFGOperations.h"
28
29 #include "ArrayConstructor.h"
30 #include "ButterflyInlines.h"
31 #include "ClonedArguments.h"
32 #include "CodeBlock.h"
33 #include "CommonSlowPaths.h"
34 #include "DFGDriver.h"
35 #include "DFGJITCode.h"
36 #include "DFGOSRExit.h"
37 #include "DFGThunks.h"
38 #include "DFGToFTLDeferredCompilationCallback.h"
39 #include "DFGToFTLForOSREntryDeferredCompilationCallback.h"
40 #include "DFGWorklist.h"
41 #include "DefinePropertyAttributes.h"
42 #include "DirectArguments.h"
43 #include "FTLForOSREntryJITCode.h"
44 #include "FTLOSREntry.h"
45 #include "FrameTracers.h"
46 #include "HasOwnPropertyCache.h"
47 #include "HostCallReturnValue.h"
48 #include "Interpreter.h"
49 #include "JIT.h"
50 #include "JITExceptions.h"
51 #include "JSArrayInlines.h"
52 #include "JSCInlines.h"
53 #include "JSFixedArray.h"
54 #include "JSGenericTypedArrayViewConstructorInlines.h"
55 #include "JSGlobalObjectFunctions.h"
56 #include "JSImmutableButterfly.h"
57 #include "JSLexicalEnvironment.h"
58 #include "JSMap.h"
59 #include "JSPropertyNameEnumerator.h"
60 #include "JSSet.h"
61 #include "JSWeakMap.h"
62 #include "JSWeakSet.h"
63 #include "NumberConstructor.h"
64 #include "ObjectConstructor.h"
65 #include "Operations.h"
66 #include "ParseInt.h"
67 #include "RegExpConstructor.h"
68 #include "RegExpMatchesArray.h"
69 #include "RegExpObjectInlines.h"
70 #include "Repatch.h"
71 #include "ScopedArguments.h"
72 #include "StringConstructor.h"
73 #include "SuperSampler.h"
74 #include "Symbol.h"
75 #include "TypeProfilerLog.h"
76 #include "TypedArrayInlines.h"
77 #include "VMInlines.h"
78 #include <wtf/InlineASM.h>
79 #include <wtf/Variant.h>
80
81 #if ENABLE(JIT)
82 #if ENABLE(DFG_JIT)
83
84 namespace JSC { namespace DFG {
85
86 template<bool strict, bool direct>
87 static inline void putByVal(ExecState* exec, VM& vm, JSValue baseValue, uint32_t index, JSValue value)
88 {
89     ASSERT(isIndex(index));
90     if (direct) {
91         RELEASE_ASSERT(baseValue.isObject());
92         asObject(baseValue)->putDirectIndex(exec, index, value, 0, strict ? PutDirectIndexShouldThrow : PutDirectIndexShouldNotThrow);
93         return;
94     }
95     if (baseValue.isObject()) {
96         JSObject* object = asObject(baseValue);
97         if (object->canSetIndexQuickly(index)) {
98             object->setIndexQuickly(vm, index, value);
99             return;
100         }
101
102         object->methodTable(vm)->putByIndex(object, exec, index, value, strict);
103         return;
104     }
105
106     baseValue.putByIndex(exec, index, value, strict);
107 }
108
109 template<bool strict, bool direct>
110 ALWAYS_INLINE static void putByValInternal(ExecState* exec, VM& vm, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
111 {
112     auto scope = DECLARE_THROW_SCOPE(vm);
113
114     JSValue baseValue = JSValue::decode(encodedBase);
115     JSValue property = JSValue::decode(encodedProperty);
116     JSValue value = JSValue::decode(encodedValue);
117
118     if (LIKELY(property.isUInt32())) {
119         // Despite its name, JSValue::isUInt32 will return true only for positive boxed int32_t; all those values are valid array indices.
120         ASSERT(isIndex(property.asUInt32()));
121         scope.release();
122         putByVal<strict, direct>(exec, vm, baseValue, property.asUInt32(), value);
123         return;
124     }
125
126     if (property.isDouble()) {
127         double propertyAsDouble = property.asDouble();
128         uint32_t propertyAsUInt32 = static_cast<uint32_t>(propertyAsDouble);
129         if (propertyAsDouble == propertyAsUInt32 && isIndex(propertyAsUInt32)) {
130             scope.release();
131             putByVal<strict, direct>(exec, vm, baseValue, propertyAsUInt32, value);
132             return;
133         }
134     }
135
136     // Don't put to an object if toString throws an exception.
137     auto propertyName = property.toPropertyKey(exec);
138     RETURN_IF_EXCEPTION(scope, void());
139
140     PutPropertySlot slot(baseValue, strict);
141     if (direct) {
142         RELEASE_ASSERT(baseValue.isObject());
143         JSObject* baseObject = asObject(baseValue);
144         if (std::optional<uint32_t> index = parseIndex(propertyName)) {
145             scope.release();
146             baseObject->putDirectIndex(exec, index.value(), value, 0, strict ? PutDirectIndexShouldThrow : PutDirectIndexShouldNotThrow);
147             return;
148         }
149         scope.release();
150         CommonSlowPaths::putDirectWithReify(vm, exec, baseObject, propertyName, value, slot);
151         return;
152     }
153     scope.release();
154     baseValue.put(exec, propertyName, value, slot);
155 }
156
157 template<bool strict, bool direct>
158 ALWAYS_INLINE static void putByValCellInternal(ExecState* exec, VM& vm, JSCell* base, PropertyName propertyName, JSValue value)
159 {
160     PutPropertySlot slot(base, strict);
161     if (direct) {
162         RELEASE_ASSERT(base->isObject());
163         JSObject* baseObject = asObject(base);
164         if (std::optional<uint32_t> index = parseIndex(propertyName)) {
165             baseObject->putDirectIndex(exec, index.value(), value, 0, strict ? PutDirectIndexShouldThrow : PutDirectIndexShouldNotThrow);
166             return;
167         }
168         CommonSlowPaths::putDirectWithReify(vm, exec, baseObject, propertyName, value, slot);
169         return;
170     }
171     base->putInline(exec, propertyName, value, slot);
172 }
173
174 template<bool strict, bool direct>
175 ALWAYS_INLINE static void putByValCellStringInternal(ExecState* exec, VM& vm, JSCell* base, JSString* property, JSValue value)
176 {
177     auto scope = DECLARE_THROW_SCOPE(vm);
178
179     auto propertyName = property->toIdentifier(exec);
180     RETURN_IF_EXCEPTION(scope, void());
181
182     scope.release();
183     putByValCellInternal<strict, direct>(exec, vm, base, propertyName, value);
184 }
185
186 template<typename ViewClass>
187 char* newTypedArrayWithSize(ExecState* exec, Structure* structure, int32_t size, char* vector)
188 {
189     VM& vm = exec->vm();
190     NativeCallFrameTracer tracer(&vm, exec);
191     auto scope = DECLARE_THROW_SCOPE(vm);
192
193     if (size < 0) {
194         throwException(exec, scope, createRangeError(exec, "Requested length is negative"_s));
195         return 0;
196     }
197     
198     if (vector)
199         return bitwise_cast<char*>(ViewClass::createWithFastVector(exec, structure, size, vector));
200
201     scope.release();
202     return bitwise_cast<char*>(ViewClass::create(exec, structure, size));
203 }
204
205 template <bool strict>
206 static ALWAYS_INLINE void putWithThis(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedThis, EncodedJSValue encodedValue, const Identifier& ident)
207 {
208     JSValue baseValue = JSValue::decode(encodedBase);
209     JSValue thisVal = JSValue::decode(encodedThis);
210     JSValue putValue = JSValue::decode(encodedValue);
211     PutPropertySlot slot(thisVal, strict);
212     baseValue.putInline(exec, ident, putValue, slot);
213 }
214
215 static ALWAYS_INLINE EncodedJSValue parseIntResult(double input)
216 {
217     int asInt = static_cast<int>(input);
218     if (static_cast<double>(asInt) == input)
219         return JSValue::encode(jsNumber(asInt));
220     return JSValue::encode(jsNumber(input));
221 }
222
223 ALWAYS_INLINE static JSValue getByValObject(ExecState* exec, VM& vm, JSObject* base, PropertyName propertyName)
224 {
225     Structure& structure = *base->structure(vm);
226     if (JSCell::canUseFastGetOwnProperty(structure)) {
227         if (JSValue result = base->fastGetOwnProperty(vm, structure, propertyName))
228             return result;
229     }
230     return base->get(exec, propertyName);
231 }
232
233 extern "C" {
234
235 EncodedJSValue JIT_OPERATION operationToThis(ExecState* exec, EncodedJSValue encodedOp)
236 {
237     VM* vm = &exec->vm();
238     NativeCallFrameTracer tracer(vm, exec);
239
240     return JSValue::encode(JSValue::decode(encodedOp).toThis(exec, NotStrictMode));
241 }
242
243 EncodedJSValue JIT_OPERATION operationToThisStrict(ExecState* exec, EncodedJSValue encodedOp)
244 {
245     VM* vm = &exec->vm();
246     NativeCallFrameTracer tracer(vm, exec);
247
248     return JSValue::encode(JSValue::decode(encodedOp).toThis(exec, StrictMode));
249 }
250
251 JSCell* JIT_OPERATION operationObjectCreate(ExecState* exec, EncodedJSValue encodedPrototype)
252 {
253     VM& vm = exec->vm();
254     NativeCallFrameTracer tracer(&vm, exec);
255     auto scope = DECLARE_THROW_SCOPE(vm);
256
257     JSValue prototype = JSValue::decode(encodedPrototype);
258
259     if (!prototype.isObject() && !prototype.isNull()) {
260         throwVMTypeError(exec, scope, "Object prototype may only be an Object or null."_s);
261         return nullptr;
262     }
263
264     if (prototype.isObject()) {
265         scope.release();
266         return constructEmptyObject(exec, asObject(prototype));
267     }
268     scope.release();
269     return constructEmptyObject(exec, exec->lexicalGlobalObject()->nullPrototypeObjectStructure());
270 }
271
272 JSCell* JIT_OPERATION operationObjectCreateObject(ExecState* exec, JSObject* prototype)
273 {
274     VM& vm = exec->vm();
275     NativeCallFrameTracer tracer(&vm, exec);
276     return constructEmptyObject(exec, prototype);
277 }
278
279 JSCell* JIT_OPERATION operationCreateThis(ExecState* exec, JSObject* constructor, uint32_t inlineCapacity)
280 {
281     VM& vm = exec->vm();
282     NativeCallFrameTracer tracer(&vm, exec);
283     auto scope = DECLARE_THROW_SCOPE(vm);
284     if (constructor->type() == JSFunctionType && jsCast<JSFunction*>(constructor)->canUseAllocationProfile()) {
285         auto rareData = jsCast<JSFunction*>(constructor)->ensureRareDataAndAllocationProfile(exec, inlineCapacity);
286         RETURN_IF_EXCEPTION(scope, nullptr);
287         ObjectAllocationProfile* allocationProfile = rareData->objectAllocationProfile();
288         Structure* structure = allocationProfile->structure();
289         JSObject* result = constructEmptyObject(exec, structure);
290         if (structure->hasPolyProto()) {
291             JSObject* prototype = allocationProfile->prototype();
292             ASSERT(prototype == jsCast<JSFunction*>(constructor)->prototypeForConstruction(vm, exec));
293             result->putDirect(vm, knownPolyProtoOffset, prototype);
294             prototype->didBecomePrototype();
295             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");
296         }
297         return result;
298     }
299
300     JSValue proto = constructor->get(exec, vm.propertyNames->prototype);
301     RETURN_IF_EXCEPTION(scope, nullptr);
302     if (proto.isObject())
303         return constructEmptyObject(exec, asObject(proto));
304     return constructEmptyObject(exec);
305 }
306
307 JSCell* JIT_OPERATION operationCallObjectConstructor(ExecState* exec, JSGlobalObject* globalObject, EncodedJSValue encodedTarget)
308 {
309     VM* vm = &exec->vm();
310     NativeCallFrameTracer tracer(vm, exec);
311
312     JSValue value = JSValue::decode(encodedTarget);
313     ASSERT(!value.isObject());
314
315     if (value.isUndefinedOrNull())
316         return constructEmptyObject(exec, globalObject->objectPrototype());
317     return value.toObject(exec, globalObject);
318 }
319
320 JSCell* JIT_OPERATION operationToObject(ExecState* exec, JSGlobalObject* globalObject, EncodedJSValue encodedTarget, UniquedStringImpl* errorMessage)
321 {
322     VM* vm = &exec->vm();
323     NativeCallFrameTracer tracer(vm, exec);
324     auto scope = DECLARE_THROW_SCOPE(*vm);
325
326     JSValue value = JSValue::decode(encodedTarget);
327     ASSERT(!value.isObject());
328
329     if (UNLIKELY(value.isUndefinedOrNull())) {
330         if (errorMessage->length()) {
331             throwVMTypeError(exec, scope, errorMessage);
332             return nullptr;
333         }
334     }
335
336     scope.release();
337     return value.toObject(exec, globalObject);
338 }
339
340 EncodedJSValue JIT_OPERATION operationValueBitAnd(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
341 {
342     VM* vm = &exec->vm();
343     NativeCallFrameTracer tracer(vm, exec);
344     auto scope = DECLARE_THROW_SCOPE(*vm);
345
346     JSValue op1 = JSValue::decode(encodedOp1);
347     JSValue op2 = JSValue::decode(encodedOp2);
348
349     int32_t a = op1.toInt32(exec);
350     RETURN_IF_EXCEPTION(scope, encodedJSValue());
351     scope.release();
352     int32_t b = op2.toInt32(exec);
353     return JSValue::encode(jsNumber(a & b));
354 }
355
356 EncodedJSValue JIT_OPERATION operationValueBitOr(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
357 {
358     VM* vm = &exec->vm();
359     NativeCallFrameTracer tracer(vm, exec);
360     auto scope = DECLARE_THROW_SCOPE(*vm);
361
362     JSValue op1 = JSValue::decode(encodedOp1);
363     JSValue op2 = JSValue::decode(encodedOp2);
364
365     int32_t a = op1.toInt32(exec);
366     RETURN_IF_EXCEPTION(scope, encodedJSValue());
367     scope.release();
368     int32_t b = op2.toInt32(exec);
369     return JSValue::encode(jsNumber(a | b));
370 }
371
372 EncodedJSValue JIT_OPERATION operationValueBitXor(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
373 {
374     VM* vm = &exec->vm();
375     NativeCallFrameTracer tracer(vm, exec);
376     auto scope = DECLARE_THROW_SCOPE(*vm);
377
378     JSValue op1 = JSValue::decode(encodedOp1);
379     JSValue op2 = JSValue::decode(encodedOp2);
380
381     int32_t a = op1.toInt32(exec);
382     RETURN_IF_EXCEPTION(scope, encodedJSValue());
383     scope.release();
384     int32_t b = op2.toInt32(exec);
385     return JSValue::encode(jsNumber(a ^ b));
386 }
387
388 EncodedJSValue JIT_OPERATION operationValueBitLShift(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
389 {
390     VM* vm = &exec->vm();
391     NativeCallFrameTracer tracer(vm, exec);
392     auto scope = DECLARE_THROW_SCOPE(*vm);
393
394     JSValue op1 = JSValue::decode(encodedOp1);
395     JSValue op2 = JSValue::decode(encodedOp2);
396
397     int32_t a = op1.toInt32(exec);
398     RETURN_IF_EXCEPTION(scope, encodedJSValue());
399     scope.release();
400     uint32_t b = op2.toUInt32(exec);
401     return JSValue::encode(jsNumber(a << (b & 0x1f)));
402 }
403
404 EncodedJSValue JIT_OPERATION operationValueBitRShift(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
405 {
406     VM* vm = &exec->vm();
407     NativeCallFrameTracer tracer(vm, exec);
408     auto scope = DECLARE_THROW_SCOPE(*vm);
409
410     JSValue op1 = JSValue::decode(encodedOp1);
411     JSValue op2 = JSValue::decode(encodedOp2);
412
413     int32_t a = op1.toInt32(exec);
414     RETURN_IF_EXCEPTION(scope, encodedJSValue());
415     scope.release();
416     uint32_t b = op2.toUInt32(exec);
417     return JSValue::encode(jsNumber(a >> (b & 0x1f)));
418 }
419
420 EncodedJSValue JIT_OPERATION operationValueBitURShift(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
421 {
422     VM* vm = &exec->vm();
423     NativeCallFrameTracer tracer(vm, exec);
424     auto scope = DECLARE_THROW_SCOPE(*vm);
425
426     JSValue op1 = JSValue::decode(encodedOp1);
427     JSValue op2 = JSValue::decode(encodedOp2);
428
429     uint32_t a = op1.toUInt32(exec);
430     RETURN_IF_EXCEPTION(scope, encodedJSValue());
431     scope.release();
432     uint32_t b = op2.toUInt32(exec);
433     return JSValue::encode(jsNumber(static_cast<int32_t>(a >> (b & 0x1f))));
434 }
435
436 EncodedJSValue JIT_OPERATION operationValueAddNotNumber(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
437 {
438     VM* vm = &exec->vm();
439     NativeCallFrameTracer tracer(vm, exec);
440     
441     JSValue op1 = JSValue::decode(encodedOp1);
442     JSValue op2 = JSValue::decode(encodedOp2);
443     
444     ASSERT(!op1.isNumber() || !op2.isNumber());
445     
446     if (op1.isString() && !op2.isObject())
447         return JSValue::encode(jsString(exec, asString(op1), op2.toString(exec)));
448
449     return JSValue::encode(jsAddSlowCase(exec, op1, op2));
450 }
451
452 EncodedJSValue JIT_OPERATION operationValueDiv(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
453 {
454     VM* vm = &exec->vm();
455     NativeCallFrameTracer tracer(vm, exec);
456     auto scope = DECLARE_THROW_SCOPE(*vm);
457
458     JSValue op1 = JSValue::decode(encodedOp1);
459     JSValue op2 = JSValue::decode(encodedOp2);
460
461     auto leftNumeric = op1.toNumeric(exec);
462     RETURN_IF_EXCEPTION(scope, encodedJSValue());
463     auto rightNumeric = op2.toNumeric(exec);
464     RETURN_IF_EXCEPTION(scope, encodedJSValue());
465
466     if (WTF::holds_alternative<JSBigInt*>(leftNumeric) || WTF::holds_alternative<JSBigInt*>(rightNumeric)) {
467         if (WTF::holds_alternative<JSBigInt*>(leftNumeric) && WTF::holds_alternative<JSBigInt*>(rightNumeric)) {
468             JSBigInt* result = JSBigInt::divide(exec, WTF::get<JSBigInt*>(leftNumeric), WTF::get<JSBigInt*>(rightNumeric));
469             RETURN_IF_EXCEPTION(scope, encodedJSValue());
470             return JSValue::encode(result);
471         }
472
473         return throwVMTypeError(exec, scope, "Invalid operand in BigInt operation.");
474     }
475
476     scope.release();
477
478     double a = WTF::get<double>(leftNumeric);
479     double b = WTF::get<double>(rightNumeric);
480     return JSValue::encode(jsNumber(a / b));
481 }
482
483 double JIT_OPERATION operationArithAbs(ExecState* exec, EncodedJSValue encodedOp1)
484 {
485     VM* vm = &exec->vm();
486     NativeCallFrameTracer tracer(vm, exec);
487     auto scope = DECLARE_THROW_SCOPE(*vm);
488
489     JSValue op1 = JSValue::decode(encodedOp1);
490     double a = op1.toNumber(exec);
491     RETURN_IF_EXCEPTION(scope, PNaN);
492     return fabs(a);
493 }
494
495 uint32_t JIT_OPERATION operationArithClz32(ExecState* exec, EncodedJSValue encodedOp1)
496 {
497     VM* vm = &exec->vm();
498     NativeCallFrameTracer tracer(vm, exec);
499     auto scope = DECLARE_THROW_SCOPE(*vm);
500
501     JSValue op1 = JSValue::decode(encodedOp1);
502     uint32_t value = op1.toUInt32(exec);
503     RETURN_IF_EXCEPTION(scope, 0);
504     return clz32(value);
505 }
506
507 double JIT_OPERATION operationArithFRound(ExecState* exec, EncodedJSValue encodedOp1)
508 {
509     VM* vm = &exec->vm();
510     NativeCallFrameTracer tracer(vm, exec);
511     auto scope = DECLARE_THROW_SCOPE(*vm);
512
513     JSValue op1 = JSValue::decode(encodedOp1);
514     double a = op1.toNumber(exec);
515     RETURN_IF_EXCEPTION(scope, PNaN);
516     return static_cast<float>(a);
517 }
518
519 #define DFG_ARITH_UNARY(capitalizedName, lowerName) \
520 double JIT_OPERATION operationArith##capitalizedName(ExecState* exec, EncodedJSValue encodedOp1) \
521 { \
522     VM* vm = &exec->vm(); \
523     NativeCallFrameTracer tracer(vm, exec); \
524     auto scope = DECLARE_THROW_SCOPE(*vm); \
525     JSValue op1 = JSValue::decode(encodedOp1); \
526     double result = op1.toNumber(exec); \
527     RETURN_IF_EXCEPTION(scope, PNaN); \
528     return JSC::Math::lowerName(result); \
529 }
530     FOR_EACH_DFG_ARITH_UNARY_OP(DFG_ARITH_UNARY)
531 #undef DFG_ARITH_UNARY
532
533 double JIT_OPERATION operationArithSqrt(ExecState* exec, EncodedJSValue encodedOp1)
534 {
535     VM* vm = &exec->vm();
536     NativeCallFrameTracer tracer(vm, exec);
537     auto scope = DECLARE_THROW_SCOPE(*vm);
538
539     JSValue op1 = JSValue::decode(encodedOp1);
540     double a = op1.toNumber(exec);
541     RETURN_IF_EXCEPTION(scope, PNaN);
542     return sqrt(a);
543 }
544
545 EncodedJSValue JIT_OPERATION operationArithRound(ExecState* exec, EncodedJSValue encodedArgument)
546 {
547     VM* vm = &exec->vm();
548     NativeCallFrameTracer tracer(vm, exec);
549     auto scope = DECLARE_THROW_SCOPE(*vm);
550
551     JSValue argument = JSValue::decode(encodedArgument);
552     double valueOfArgument = argument.toNumber(exec);
553     RETURN_IF_EXCEPTION(scope, encodedJSValue());
554     return JSValue::encode(jsNumber(jsRound(valueOfArgument)));
555 }
556
557 EncodedJSValue JIT_OPERATION operationArithFloor(ExecState* exec, EncodedJSValue encodedArgument)
558 {
559     VM* vm = &exec->vm();
560     NativeCallFrameTracer tracer(vm, exec);
561     auto scope = DECLARE_THROW_SCOPE(*vm);
562
563     JSValue argument = JSValue::decode(encodedArgument);
564     double valueOfArgument = argument.toNumber(exec);
565     RETURN_IF_EXCEPTION(scope, encodedJSValue());
566     return JSValue::encode(jsNumber(floor(valueOfArgument)));
567 }
568
569 EncodedJSValue JIT_OPERATION operationArithCeil(ExecState* exec, EncodedJSValue encodedArgument)
570 {
571     VM* vm = &exec->vm();
572     NativeCallFrameTracer tracer(vm, exec);
573     auto scope = DECLARE_THROW_SCOPE(*vm);
574
575     JSValue argument = JSValue::decode(encodedArgument);
576     double valueOfArgument = argument.toNumber(exec);
577     RETURN_IF_EXCEPTION(scope, encodedJSValue());
578     return JSValue::encode(jsNumber(ceil(valueOfArgument)));
579 }
580
581 EncodedJSValue JIT_OPERATION operationArithTrunc(ExecState* exec, EncodedJSValue encodedArgument)
582 {
583     VM* vm = &exec->vm();
584     NativeCallFrameTracer tracer(vm, exec);
585     auto scope = DECLARE_THROW_SCOPE(*vm);
586
587     JSValue argument = JSValue::decode(encodedArgument);
588     double truncatedValueOfArgument = argument.toIntegerPreserveNaN(exec);
589     RETURN_IF_EXCEPTION(scope, encodedJSValue());
590     return JSValue::encode(jsNumber(truncatedValueOfArgument));
591 }
592
593 static ALWAYS_INLINE EncodedJSValue getByVal(ExecState* exec, JSCell* base, uint32_t index)
594 {
595     VM& vm = exec->vm();
596     NativeCallFrameTracer tracer(&vm, exec);
597     
598     if (base->isObject()) {
599         JSObject* object = asObject(base);
600         if (object->canGetIndexQuickly(index))
601             return JSValue::encode(object->getIndexQuickly(index));
602     }
603
604     if (isJSString(base) && asString(base)->canGetIndex(index))
605         return JSValue::encode(asString(base)->getIndex(exec, index));
606
607     return JSValue::encode(JSValue(base).get(exec, index));
608 }
609
610 EncodedJSValue JIT_OPERATION operationGetByVal(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty)
611 {
612     VM& vm = exec->vm();
613     NativeCallFrameTracer tracer(&vm, exec);
614     auto scope = DECLARE_THROW_SCOPE(vm);
615
616     JSValue baseValue = JSValue::decode(encodedBase);
617     JSValue property = JSValue::decode(encodedProperty);
618
619     if (LIKELY(baseValue.isCell())) {
620         JSCell* base = baseValue.asCell();
621
622         if (property.isUInt32()) {
623             scope.release();
624             return getByVal(exec, base, property.asUInt32());
625         }
626         if (property.isDouble()) {
627             double propertyAsDouble = property.asDouble();
628             uint32_t propertyAsUInt32 = static_cast<uint32_t>(propertyAsDouble);
629             if (propertyAsUInt32 == propertyAsDouble && isIndex(propertyAsUInt32)) {
630                 scope.release();
631                 return getByVal(exec, base, propertyAsUInt32);
632             }
633         } else if (property.isString()) {
634             Structure& structure = *base->structure(vm);
635             if (JSCell::canUseFastGetOwnProperty(structure)) {
636                 if (RefPtr<AtomicStringImpl> existingAtomicString = asString(property)->toExistingAtomicString(exec)) {
637                     if (JSValue result = base->fastGetOwnProperty(vm, structure, existingAtomicString.get()))
638                         return JSValue::encode(result);
639                 }
640             }
641         }
642     }
643
644     baseValue.requireObjectCoercible(exec);
645     RETURN_IF_EXCEPTION(scope, encodedJSValue());
646     auto propertyName = property.toPropertyKey(exec);
647     RETURN_IF_EXCEPTION(scope, encodedJSValue());
648     scope.release();
649     return JSValue::encode(baseValue.get(exec, propertyName));
650 }
651
652 EncodedJSValue JIT_OPERATION operationGetByValCell(ExecState* exec, JSCell* base, EncodedJSValue encodedProperty)
653 {
654     VM& vm = exec->vm();
655     NativeCallFrameTracer tracer(&vm, exec);
656     auto scope = DECLARE_THROW_SCOPE(vm);
657
658     JSValue property = JSValue::decode(encodedProperty);
659
660     if (property.isUInt32()) {
661         scope.release();
662         return getByVal(exec, base, property.asUInt32());
663     }
664     if (property.isDouble()) {
665         double propertyAsDouble = property.asDouble();
666         uint32_t propertyAsUInt32 = static_cast<uint32_t>(propertyAsDouble);
667         if (propertyAsUInt32 == propertyAsDouble) {
668             scope.release();
669             return getByVal(exec, base, propertyAsUInt32);
670         }
671     } else if (property.isString()) {
672         Structure& structure = *base->structure(vm);
673         if (JSCell::canUseFastGetOwnProperty(structure)) {
674             if (RefPtr<AtomicStringImpl> existingAtomicString = asString(property)->toExistingAtomicString(exec)) {
675                 if (JSValue result = base->fastGetOwnProperty(vm, structure, existingAtomicString.get()))
676                     return JSValue::encode(result);
677             }
678         }
679     }
680
681     auto propertyName = property.toPropertyKey(exec);
682     RETURN_IF_EXCEPTION(scope, encodedJSValue());
683     scope.release();
684     return JSValue::encode(JSValue(base).get(exec, propertyName));
685 }
686
687 ALWAYS_INLINE EncodedJSValue getByValCellInt(ExecState* exec, JSCell* base, int32_t index)
688 {
689     VM* vm = &exec->vm();
690     NativeCallFrameTracer tracer(vm, exec);
691     
692     if (index < 0) {
693         // Go the slowest way possible because negative indices don't use indexed storage.
694         return JSValue::encode(JSValue(base).get(exec, Identifier::from(exec, index)));
695     }
696
697     // Use this since we know that the value is out of bounds.
698     return JSValue::encode(JSValue(base).get(exec, static_cast<unsigned>(index)));
699 }
700
701 EncodedJSValue JIT_OPERATION operationGetByValObjectInt(ExecState* exec, JSObject* base, int32_t index)
702 {
703     return getByValCellInt(exec, base, index);
704 }
705
706 EncodedJSValue JIT_OPERATION operationGetByValStringInt(ExecState* exec, JSString* base, int32_t index)
707 {
708     return getByValCellInt(exec, base, index);
709 }
710
711 EncodedJSValue JIT_OPERATION operationGetByValObjectString(ExecState* exec, JSCell* base, JSCell* string)
712 {
713     VM& vm = exec->vm();
714     NativeCallFrameTracer tracer(&vm, exec);
715
716     auto scope = DECLARE_THROW_SCOPE(vm);
717
718     auto propertyName = asString(string)->toIdentifier(exec);
719     RETURN_IF_EXCEPTION(scope, encodedJSValue());
720
721     scope.release();
722     return JSValue::encode(getByValObject(exec, vm, asObject(base), propertyName));
723 }
724
725 EncodedJSValue JIT_OPERATION operationGetByValObjectSymbol(ExecState* exec, JSCell* base, JSCell* symbol)
726 {
727     VM& vm = exec->vm();
728     NativeCallFrameTracer tracer(&vm, exec);
729
730     return JSValue::encode(getByValObject(exec, vm, asObject(base), asSymbol(symbol)->privateName()));
731 }
732
733 void JIT_OPERATION operationPutByValStrict(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
734 {
735     VM& vm = exec->vm();
736     NativeCallFrameTracer tracer(&vm, exec);
737     
738     putByValInternal<true, false>(exec, vm, encodedBase, encodedProperty, encodedValue);
739 }
740
741 void JIT_OPERATION operationPutByValNonStrict(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
742 {
743     VM& vm = exec->vm();
744     NativeCallFrameTracer tracer(&vm, exec);
745     
746     putByValInternal<false, false>(exec, vm, encodedBase, encodedProperty, encodedValue);
747 }
748
749 void JIT_OPERATION operationPutByValCellStrict(ExecState* exec, JSCell* cell, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
750 {
751     VM& vm = exec->vm();
752     NativeCallFrameTracer tracer(&vm, exec);
753     
754     putByValInternal<true, false>(exec, vm, JSValue::encode(cell), encodedProperty, encodedValue);
755 }
756
757 void JIT_OPERATION operationPutByValCellNonStrict(ExecState* exec, JSCell* cell, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
758 {
759     VM& vm = exec->vm();
760     NativeCallFrameTracer tracer(&vm, exec);
761     
762     putByValInternal<false, false>(exec, vm, JSValue::encode(cell), encodedProperty, encodedValue);
763 }
764
765 void JIT_OPERATION operationPutByValCellStringStrict(ExecState* exec, JSCell* cell, JSCell* string, EncodedJSValue encodedValue)
766 {
767     VM& vm = exec->vm();
768     NativeCallFrameTracer tracer(&vm, exec);
769
770     putByValCellStringInternal<true, false>(exec, vm, cell, asString(string), JSValue::decode(encodedValue));
771 }
772
773 void JIT_OPERATION operationPutByValCellStringNonStrict(ExecState* exec, JSCell* cell, JSCell* string, EncodedJSValue encodedValue)
774 {
775     VM& vm = exec->vm();
776     NativeCallFrameTracer tracer(&vm, exec);
777
778     putByValCellStringInternal<false, false>(exec, vm, cell, asString(string), JSValue::decode(encodedValue));
779 }
780
781 void JIT_OPERATION operationPutByValCellSymbolStrict(ExecState* exec, JSCell* cell, JSCell* symbol, EncodedJSValue encodedValue)
782 {
783     VM& vm = exec->vm();
784     NativeCallFrameTracer tracer(&vm, exec);
785
786     putByValCellInternal<true, false>(exec, vm, cell, asSymbol(symbol)->privateName(), JSValue::decode(encodedValue));
787 }
788
789 void JIT_OPERATION operationPutByValCellSymbolNonStrict(ExecState* exec, JSCell* cell, JSCell* symbol, EncodedJSValue encodedValue)
790 {
791     VM& vm = exec->vm();
792     NativeCallFrameTracer tracer(&vm, exec);
793
794     putByValCellInternal<false, false>(exec, vm, cell, asSymbol(symbol)->privateName(), JSValue::decode(encodedValue));
795 }
796
797 void JIT_OPERATION operationPutByValBeyondArrayBoundsStrict(ExecState* exec, JSObject* object, int32_t index, EncodedJSValue encodedValue)
798 {
799     VM& vm = exec->vm();
800     NativeCallFrameTracer tracer(&vm, exec);
801     
802     if (index >= 0) {
803         object->putByIndexInline(exec, index, JSValue::decode(encodedValue), true);
804         return;
805     }
806     
807     PutPropertySlot slot(object, true);
808     object->methodTable(vm)->put(
809         object, exec, Identifier::from(exec, index), JSValue::decode(encodedValue), slot);
810 }
811
812 void JIT_OPERATION operationPutByValBeyondArrayBoundsNonStrict(ExecState* exec, JSObject* object, int32_t index, EncodedJSValue encodedValue)
813 {
814     VM* vm = &exec->vm();
815     NativeCallFrameTracer tracer(vm, exec);
816     
817     if (index >= 0) {
818         object->putByIndexInline(exec, index, JSValue::decode(encodedValue), false);
819         return;
820     }
821     
822     PutPropertySlot slot(object, false);
823     object->methodTable(*vm)->put(
824         object, exec, Identifier::from(exec, index), JSValue::decode(encodedValue), slot);
825 }
826
827 void JIT_OPERATION operationPutDoubleByValBeyondArrayBoundsStrict(ExecState* exec, JSObject* object, int32_t index, double value)
828 {
829     VM* vm = &exec->vm();
830     NativeCallFrameTracer tracer(vm, exec);
831     
832     JSValue jsValue = JSValue(JSValue::EncodeAsDouble, value);
833     
834     if (index >= 0) {
835         object->putByIndexInline(exec, index, jsValue, true);
836         return;
837     }
838     
839     PutPropertySlot slot(object, true);
840     object->methodTable(*vm)->put(
841         object, exec, Identifier::from(exec, index), jsValue, slot);
842 }
843
844 void JIT_OPERATION operationPutDoubleByValBeyondArrayBoundsNonStrict(ExecState* exec, JSObject* object, int32_t index, double value)
845 {
846     VM* vm = &exec->vm();
847     NativeCallFrameTracer tracer(vm, exec);
848     
849     JSValue jsValue = JSValue(JSValue::EncodeAsDouble, value);
850     
851     if (index >= 0) {
852         object->putByIndexInline(exec, index, jsValue, false);
853         return;
854     }
855     
856     PutPropertySlot slot(object, false);
857     object->methodTable(*vm)->put(
858         object, exec, Identifier::from(exec, index), jsValue, slot);
859 }
860
861 void JIT_OPERATION operationPutDoubleByValDirectBeyondArrayBoundsStrict(ExecState* exec, JSObject* object, int32_t index, double value)
862 {
863     VM& vm = exec->vm();
864     NativeCallFrameTracer tracer(&vm, exec);
865
866     JSValue jsValue = JSValue(JSValue::EncodeAsDouble, value);
867
868     if (index >= 0) {
869         object->putDirectIndex(exec, index, jsValue, 0, PutDirectIndexShouldThrow);
870         return;
871     }
872
873     PutPropertySlot slot(object, true);
874     CommonSlowPaths::putDirectWithReify(vm, exec, object, Identifier::from(exec, index), jsValue, slot);
875 }
876
877 void JIT_OPERATION operationPutDoubleByValDirectBeyondArrayBoundsNonStrict(ExecState* exec, JSObject* object, int32_t index, double value)
878 {
879     VM& vm = exec->vm();
880     NativeCallFrameTracer tracer(&vm, exec);
881
882     JSValue jsValue = JSValue(JSValue::EncodeAsDouble, value);
883
884     if (index >= 0) {
885         object->putDirectIndex(exec, index, jsValue);
886         return;
887     }
888
889     PutPropertySlot slot(object, false);
890     CommonSlowPaths::putDirectWithReify(vm, exec, object, Identifier::from(exec, index), jsValue, slot);
891 }
892
893 void JIT_OPERATION operationPutByValDirectStrict(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
894 {
895     VM& vm = exec->vm();
896     NativeCallFrameTracer tracer(&vm, exec);
897     
898     putByValInternal<true, true>(exec, vm, encodedBase, encodedProperty, encodedValue);
899 }
900
901 void JIT_OPERATION operationPutByValDirectNonStrict(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
902 {
903     VM& vm = exec->vm();
904     NativeCallFrameTracer tracer(&vm, exec);
905     
906     putByValInternal<false, true>(exec, vm, encodedBase, encodedProperty, encodedValue);
907 }
908
909 void JIT_OPERATION operationPutByValDirectCellStrict(ExecState* exec, JSCell* cell, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
910 {
911     VM& vm = exec->vm();
912     NativeCallFrameTracer tracer(&vm, exec);
913     
914     putByValInternal<true, true>(exec, vm, JSValue::encode(cell), encodedProperty, encodedValue);
915 }
916
917 void JIT_OPERATION operationPutByValDirectCellNonStrict(ExecState* exec, JSCell* cell, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
918 {
919     VM& vm = exec->vm();
920     NativeCallFrameTracer tracer(&vm, exec);
921     
922     putByValInternal<false, true>(exec, vm, JSValue::encode(cell), encodedProperty, encodedValue);
923 }
924
925 void JIT_OPERATION operationPutByValDirectCellStringStrict(ExecState* exec, JSCell* cell, JSCell* string, EncodedJSValue encodedValue)
926 {
927     VM& vm = exec->vm();
928     NativeCallFrameTracer tracer(&vm, exec);
929
930     putByValCellStringInternal<true, true>(exec, vm, cell, asString(string), JSValue::decode(encodedValue));
931 }
932
933 void JIT_OPERATION operationPutByValDirectCellStringNonStrict(ExecState* exec, JSCell* cell, JSCell* string, EncodedJSValue encodedValue)
934 {
935     VM& vm = exec->vm();
936     NativeCallFrameTracer tracer(&vm, exec);
937
938     putByValCellStringInternal<false, true>(exec, vm, cell, asString(string), JSValue::decode(encodedValue));
939 }
940
941 void JIT_OPERATION operationPutByValDirectCellSymbolStrict(ExecState* exec, JSCell* cell, JSCell* symbol, EncodedJSValue encodedValue)
942 {
943     VM& vm = exec->vm();
944     NativeCallFrameTracer tracer(&vm, exec);
945
946     putByValCellInternal<true, true>(exec, vm, cell, asSymbol(symbol)->privateName(), JSValue::decode(encodedValue));
947 }
948
949 void JIT_OPERATION operationPutByValDirectCellSymbolNonStrict(ExecState* exec, JSCell* cell, JSCell* symbol, EncodedJSValue encodedValue)
950 {
951     VM& vm = exec->vm();
952     NativeCallFrameTracer tracer(&vm, exec);
953
954     putByValCellInternal<false, true>(exec, vm, cell, asSymbol(symbol)->privateName(), JSValue::decode(encodedValue));
955 }
956
957 void JIT_OPERATION operationPutByValDirectBeyondArrayBoundsStrict(ExecState* exec, JSObject* object, int32_t index, EncodedJSValue encodedValue)
958 {
959     VM& vm = exec->vm();
960     NativeCallFrameTracer tracer(&vm, exec);
961     if (index >= 0) {
962         object->putDirectIndex(exec, index, JSValue::decode(encodedValue), 0, PutDirectIndexShouldThrow);
963         return;
964     }
965     
966     PutPropertySlot slot(object, true);
967     CommonSlowPaths::putDirectWithReify(vm, exec, object, Identifier::from(exec, index), JSValue::decode(encodedValue), slot);
968 }
969
970 void JIT_OPERATION operationPutByValDirectBeyondArrayBoundsNonStrict(ExecState* exec, JSObject* object, int32_t index, EncodedJSValue encodedValue)
971 {
972     VM& vm = exec->vm();
973     NativeCallFrameTracer tracer(&vm, exec);
974
975     if (index >= 0) {
976         object->putDirectIndex(exec, index, JSValue::decode(encodedValue));
977         return;
978     }
979     
980     PutPropertySlot slot(object, false);
981     CommonSlowPaths::putDirectWithReify(vm, exec, object, Identifier::from(exec, index), JSValue::decode(encodedValue), slot);
982 }
983
984 EncodedJSValue JIT_OPERATION operationArrayPush(ExecState* exec, EncodedJSValue encodedValue, JSArray* array)
985 {
986     VM* vm = &exec->vm();
987     NativeCallFrameTracer tracer(vm, exec);
988     
989     array->pushInline(exec, JSValue::decode(encodedValue));
990     return JSValue::encode(jsNumber(array->length()));
991 }
992
993 EncodedJSValue JIT_OPERATION operationArrayPushDouble(ExecState* exec, double value, JSArray* array)
994 {
995     VM* vm = &exec->vm();
996     NativeCallFrameTracer tracer(vm, exec);
997     
998     array->pushInline(exec, JSValue(JSValue::EncodeAsDouble, value));
999     return JSValue::encode(jsNumber(array->length()));
1000 }
1001
1002 EncodedJSValue JIT_OPERATION operationArrayPushMultiple(ExecState* exec, JSArray* array, void* buffer, int32_t elementCount)
1003 {
1004     VM& vm = exec->vm();
1005     NativeCallFrameTracer tracer(&vm, exec);
1006     auto scope = DECLARE_THROW_SCOPE(vm);
1007
1008     // We assume that multiple JSArray::push calls with ArrayWithInt32/ArrayWithContiguous do not cause JS traps.
1009     // If it can cause any JS interactions, we can call the caller JS function of this function and overwrite the
1010     // content of ScratchBuffer. If the IndexingType is now ArrayWithInt32/ArrayWithContiguous, we can ensure
1011     // that there is no indexed accessors in this object and its prototype chain.
1012     //
1013     // ArrayWithArrayStorage is also OK. It can have indexed accessors. But if you define an indexed accessor, the array's length
1014     // becomes larger than that index. So Array#push never overlaps with this accessor. So accessors are never called unless
1015     // the IndexingType is ArrayWithSlowPutArrayStorage which could have an indexed accessor in a prototype chain.
1016     RELEASE_ASSERT(!shouldUseSlowPut(array->indexingType()));
1017
1018     EncodedJSValue* values = static_cast<EncodedJSValue*>(buffer);
1019     for (int32_t i = 0; i < elementCount; ++i) {
1020         array->pushInline(exec, JSValue::decode(values[i]));
1021         RETURN_IF_EXCEPTION(scope, encodedJSValue());
1022     }
1023     return JSValue::encode(jsNumber(array->length()));
1024 }
1025
1026 EncodedJSValue JIT_OPERATION operationArrayPushDoubleMultiple(ExecState* exec, JSArray* array, void* buffer, int32_t elementCount)
1027 {
1028     VM& vm = exec->vm();
1029     NativeCallFrameTracer tracer(&vm, exec);
1030     auto scope = DECLARE_THROW_SCOPE(vm);
1031
1032     // We assume that multiple JSArray::push calls with ArrayWithDouble do not cause JS traps.
1033     // If it can cause any JS interactions, we can call the caller JS function of this function and overwrite the
1034     // content of ScratchBuffer. If the IndexingType is now ArrayWithDouble, we can ensure
1035     // that there is no indexed accessors in this object and its prototype chain.
1036     ASSERT(array->indexingMode() == ArrayWithDouble);
1037
1038     double* values = static_cast<double*>(buffer);
1039     for (int32_t i = 0; i < elementCount; ++i) {
1040         array->pushInline(exec, JSValue(JSValue::EncodeAsDouble, values[i]));
1041         RETURN_IF_EXCEPTION(scope, encodedJSValue());
1042     }
1043     return JSValue::encode(jsNumber(array->length()));
1044 }
1045
1046 EncodedJSValue JIT_OPERATION operationArrayPop(ExecState* exec, JSArray* array)
1047 {
1048     VM* vm = &exec->vm();
1049     NativeCallFrameTracer tracer(vm, exec);
1050     
1051     return JSValue::encode(array->pop(exec));
1052 }
1053         
1054 EncodedJSValue JIT_OPERATION operationArrayPopAndRecoverLength(ExecState* exec, JSArray* array)
1055 {
1056     VM* vm = &exec->vm();
1057     NativeCallFrameTracer tracer(vm, exec);
1058     
1059     array->butterfly()->setPublicLength(array->butterfly()->publicLength() + 1);
1060     
1061     return JSValue::encode(array->pop(exec));
1062 }
1063         
1064 EncodedJSValue JIT_OPERATION operationRegExpExecString(ExecState* exec, JSGlobalObject* globalObject, RegExpObject* regExpObject, JSString* argument)
1065 {
1066     SuperSamplerScope superSamplerScope(false);
1067     
1068     VM& vm = globalObject->vm();
1069     NativeCallFrameTracer tracer(&vm, exec);
1070     
1071     return JSValue::encode(regExpObject->execInline(exec, globalObject, argument));
1072 }
1073         
1074 EncodedJSValue JIT_OPERATION operationRegExpExec(ExecState* exec, JSGlobalObject* globalObject, RegExpObject* regExpObject, EncodedJSValue encodedArgument)
1075 {
1076     SuperSamplerScope superSamplerScope(false);
1077     
1078     VM& vm = globalObject->vm();
1079     NativeCallFrameTracer tracer(&vm, exec);
1080     auto scope = DECLARE_THROW_SCOPE(vm);
1081     
1082     JSValue argument = JSValue::decode(encodedArgument);
1083
1084     JSString* input = argument.toStringOrNull(exec);
1085     EXCEPTION_ASSERT(!!scope.exception() == !input);
1086     if (!input)
1087         return encodedJSValue();
1088     scope.release();
1089     return JSValue::encode(regExpObject->execInline(exec, globalObject, input));
1090 }
1091         
1092 EncodedJSValue JIT_OPERATION operationRegExpExecGeneric(ExecState* exec, JSGlobalObject* globalObject, EncodedJSValue encodedBase, EncodedJSValue encodedArgument)
1093 {
1094     SuperSamplerScope superSamplerScope(false);
1095     
1096     VM& vm = globalObject->vm();
1097     NativeCallFrameTracer tracer(&vm, exec);
1098     auto scope = DECLARE_THROW_SCOPE(vm);
1099
1100     JSValue base = JSValue::decode(encodedBase);
1101     JSValue argument = JSValue::decode(encodedArgument);
1102     
1103     auto* regexp = jsDynamicCast<RegExpObject*>(vm, base);
1104     if (UNLIKELY(!regexp))
1105         return throwVMTypeError(exec, scope);
1106
1107     JSString* input = argument.toStringOrNull(exec);
1108     EXCEPTION_ASSERT(!!scope.exception() == !input);
1109     if (!input)
1110         return JSValue::encode(jsUndefined());
1111     scope.release();
1112     return JSValue::encode(regexp->exec(exec, globalObject, input));
1113 }
1114
1115 EncodedJSValue JIT_OPERATION operationRegExpExecNonGlobalOrSticky(ExecState* exec, JSGlobalObject* globalObject, RegExp* regExp, JSString* string)
1116 {
1117     SuperSamplerScope superSamplerScope(false);
1118
1119     VM& vm = globalObject->vm();
1120     NativeCallFrameTracer tracer(&vm, exec);
1121
1122     auto scope = DECLARE_THROW_SCOPE(vm);
1123
1124     RegExpConstructor* regExpConstructor = globalObject->regExpConstructor();
1125     String input = string->value(exec);
1126     RETURN_IF_EXCEPTION(scope, { });
1127
1128     unsigned lastIndex = 0;
1129     MatchResult result;
1130     JSArray* array = createRegExpMatchesArray(vm, globalObject, string, input, regExp, lastIndex, result);
1131     if (!array) {
1132         ASSERT(!scope.exception());
1133         return JSValue::encode(jsNull());
1134     }
1135
1136     RETURN_IF_EXCEPTION(scope, { });
1137     regExpConstructor->recordMatch(vm, regExp, string, result);
1138     return JSValue::encode(array);
1139 }
1140
1141 EncodedJSValue JIT_OPERATION operationRegExpMatchFastString(ExecState* exec, JSGlobalObject* globalObject, RegExpObject* regExpObject, JSString* argument)
1142 {
1143     SuperSamplerScope superSamplerScope(false);
1144
1145     VM& vm = globalObject->vm();
1146     NativeCallFrameTracer tracer(&vm, exec);
1147
1148     if (!regExpObject->regExp()->global())
1149         return JSValue::encode(regExpObject->execInline(exec, globalObject, argument));
1150     return JSValue::encode(regExpObject->matchGlobal(exec, globalObject, argument));
1151 }
1152
1153 EncodedJSValue JIT_OPERATION operationRegExpMatchFastGlobalString(ExecState* exec, JSGlobalObject* globalObject, RegExp* regExp, JSString* string)
1154 {
1155     SuperSamplerScope superSamplerScope(false);
1156
1157     VM& vm = globalObject->vm();
1158     NativeCallFrameTracer tracer(&vm, exec);
1159
1160     auto scope = DECLARE_THROW_SCOPE(vm);
1161
1162     ASSERT(regExp->global());
1163
1164     String s = string->value(exec);
1165     RETURN_IF_EXCEPTION(scope, { });
1166
1167     RegExpConstructor* regExpConstructor = globalObject->regExpConstructor();
1168
1169     if (regExp->unicode()) {
1170         unsigned stringLength = s.length();
1171         scope.release();
1172         return JSValue::encode(collectMatches(
1173             vm, exec, string, s, regExpConstructor, regExp,
1174             [&] (size_t end) -> size_t {
1175                 return advanceStringUnicode(s, stringLength, end);
1176             }));
1177     }
1178
1179     scope.release();
1180     return JSValue::encode(collectMatches(
1181         vm, exec, string, s, regExpConstructor, regExp,
1182         [&] (size_t end) -> size_t {
1183             return end + 1;
1184         }));
1185 }
1186
1187 EncodedJSValue JIT_OPERATION operationParseIntNoRadixGeneric(ExecState* exec, EncodedJSValue value)
1188 {
1189     VM& vm = exec->vm();
1190     NativeCallFrameTracer tracer(&vm, exec);
1191
1192     return toStringView(exec, JSValue::decode(value), [&] (StringView view) {
1193         // This version is as if radix was undefined. Hence, undefined.toNumber() === 0.
1194         return parseIntResult(parseInt(view, 0));
1195     });
1196 }
1197
1198 EncodedJSValue JIT_OPERATION operationParseIntStringNoRadix(ExecState* exec, JSString* string)
1199 {
1200     VM& vm = exec->vm();
1201     NativeCallFrameTracer tracer(&vm, exec);
1202     auto scope = DECLARE_THROW_SCOPE(vm);
1203
1204     auto viewWithString = string->viewWithUnderlyingString(exec);
1205     RETURN_IF_EXCEPTION(scope, { });
1206
1207     // This version is as if radix was undefined. Hence, undefined.toNumber() === 0.
1208     return parseIntResult(parseInt(viewWithString.view, 0));
1209 }
1210
1211 EncodedJSValue JIT_OPERATION operationParseIntString(ExecState* exec, JSString* string, int32_t radix)
1212 {
1213     VM& vm = exec->vm();
1214     NativeCallFrameTracer tracer(&vm, exec);
1215     auto scope = DECLARE_THROW_SCOPE(vm);
1216
1217     auto viewWithString = string->viewWithUnderlyingString(exec);
1218     RETURN_IF_EXCEPTION(scope, { });
1219
1220     return parseIntResult(parseInt(viewWithString.view, radix));
1221 }
1222
1223 EncodedJSValue JIT_OPERATION operationParseIntGeneric(ExecState* exec, EncodedJSValue value, int32_t radix)
1224 {
1225     VM& vm = exec->vm();
1226     NativeCallFrameTracer tracer(&vm, exec);
1227
1228     return toStringView(exec, JSValue::decode(value), [&] (StringView view) {
1229         return parseIntResult(parseInt(view, radix));
1230     });
1231 }
1232         
1233 size_t JIT_OPERATION operationRegExpTestString(ExecState* exec, JSGlobalObject* globalObject, RegExpObject* regExpObject, JSString* input)
1234 {
1235     SuperSamplerScope superSamplerScope(false);
1236     
1237     VM& vm = globalObject->vm();
1238     NativeCallFrameTracer tracer(&vm, exec);
1239
1240     return regExpObject->testInline(exec, globalObject, input);
1241 }
1242
1243 size_t JIT_OPERATION operationRegExpTest(ExecState* exec, JSGlobalObject* globalObject, RegExpObject* regExpObject, EncodedJSValue encodedArgument)
1244 {
1245     SuperSamplerScope superSamplerScope(false);
1246     
1247     VM& vm = globalObject->vm();
1248     NativeCallFrameTracer tracer(&vm, exec);
1249
1250     JSValue argument = JSValue::decode(encodedArgument);
1251
1252     JSString* input = argument.toStringOrNull(exec);
1253     if (!input)
1254         return false;
1255     return regExpObject->testInline(exec, globalObject, input);
1256 }
1257
1258 size_t JIT_OPERATION operationRegExpTestGeneric(ExecState* exec, JSGlobalObject* globalObject, EncodedJSValue encodedBase, EncodedJSValue encodedArgument)
1259 {
1260     SuperSamplerScope superSamplerScope(false);
1261     
1262     VM& vm = globalObject->vm();
1263     NativeCallFrameTracer tracer(&vm, exec);
1264     auto scope = DECLARE_THROW_SCOPE(vm);
1265
1266     JSValue base = JSValue::decode(encodedBase);
1267     JSValue argument = JSValue::decode(encodedArgument);
1268
1269     auto* regexp = jsDynamicCast<RegExpObject*>(vm, base);
1270     if (UNLIKELY(!regexp)) {
1271         throwTypeError(exec, scope);
1272         return false;
1273     }
1274
1275     JSString* input = argument.toStringOrNull(exec);
1276     EXCEPTION_ASSERT(!!scope.exception() == !input);
1277     if (!input)
1278         return false;
1279     scope.release();
1280     return regexp->test(exec, globalObject, input);
1281 }
1282
1283 size_t JIT_OPERATION operationCompareStrictEqCell(ExecState* exec, JSCell* op1, JSCell* op2)
1284 {
1285     VM* vm = &exec->vm();
1286     NativeCallFrameTracer tracer(vm, exec);
1287     
1288     return JSValue::strictEqualSlowCaseInline(exec, op1, op2);
1289 }
1290
1291 size_t JIT_OPERATION operationSameValue(ExecState* exec, EncodedJSValue arg1, EncodedJSValue arg2)
1292 {
1293     VM& vm = exec->vm();
1294     NativeCallFrameTracer tracer(&vm, exec);
1295
1296     return sameValue(exec, JSValue::decode(arg1), JSValue::decode(arg2));
1297 }
1298
1299 EncodedJSValue JIT_OPERATION operationToPrimitive(ExecState* exec, EncodedJSValue value)
1300 {
1301     VM* vm = &exec->vm();
1302     NativeCallFrameTracer tracer(vm, exec);
1303     
1304     return JSValue::encode(JSValue::decode(value).toPrimitive(exec));
1305 }
1306
1307 EncodedJSValue JIT_OPERATION operationToNumber(ExecState* exec, EncodedJSValue value)
1308 {
1309     VM* vm = &exec->vm();
1310     NativeCallFrameTracer tracer(vm, exec);
1311
1312     return JSValue::encode(jsNumber(JSValue::decode(value).toNumber(exec)));
1313 }
1314
1315 EncodedJSValue JIT_OPERATION operationGetByValWithThis(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedThis, EncodedJSValue encodedSubscript)
1316 {
1317     VM& vm = exec->vm();
1318     NativeCallFrameTracer tracer(&vm, exec);
1319     auto scope = DECLARE_THROW_SCOPE(vm);
1320
1321     JSValue baseValue = JSValue::decode(encodedBase);
1322     JSValue thisVal = JSValue::decode(encodedThis);
1323     JSValue subscript = JSValue::decode(encodedSubscript);
1324
1325     if (LIKELY(baseValue.isCell() && subscript.isString())) {
1326         Structure& structure = *baseValue.asCell()->structure(vm);
1327         if (JSCell::canUseFastGetOwnProperty(structure)) {
1328             if (RefPtr<AtomicStringImpl> existingAtomicString = asString(subscript)->toExistingAtomicString(exec)) {
1329                 if (JSValue result = baseValue.asCell()->fastGetOwnProperty(vm, structure, existingAtomicString.get()))
1330                     return JSValue::encode(result);
1331             }
1332         }
1333     }
1334     
1335     PropertySlot slot(thisVal, PropertySlot::PropertySlot::InternalMethodType::Get);
1336     if (subscript.isUInt32()) {
1337         uint32_t i = subscript.asUInt32();
1338         if (isJSString(baseValue) && asString(baseValue)->canGetIndex(i))
1339             return JSValue::encode(asString(baseValue)->getIndex(exec, i));
1340         
1341         scope.release();
1342         return JSValue::encode(baseValue.get(exec, i, slot));
1343     }
1344
1345     baseValue.requireObjectCoercible(exec);
1346     RETURN_IF_EXCEPTION(scope, encodedJSValue());
1347
1348     auto property = subscript.toPropertyKey(exec);
1349     RETURN_IF_EXCEPTION(scope, encodedJSValue());
1350     scope.release();
1351     return JSValue::encode(baseValue.get(exec, property, slot));
1352 }
1353
1354 void JIT_OPERATION operationPutByIdWithThisStrict(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedThis, EncodedJSValue encodedValue, UniquedStringImpl* impl)
1355 {
1356     VM& vm = exec->vm();
1357     NativeCallFrameTracer tracer(&vm, exec);
1358
1359     putWithThis<true>(exec, encodedBase, encodedThis, encodedValue, Identifier::fromUid(exec, impl));
1360 }
1361
1362 void JIT_OPERATION operationPutByIdWithThis(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedThis, EncodedJSValue encodedValue, UniquedStringImpl* impl)
1363 {
1364     VM& vm = exec->vm();
1365     NativeCallFrameTracer tracer(&vm, exec);
1366
1367     putWithThis<false>(exec, encodedBase, encodedThis, encodedValue, Identifier::fromUid(exec, impl));
1368 }
1369
1370 void JIT_OPERATION operationPutByValWithThisStrict(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedThis, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue)
1371 {
1372     VM& vm = exec->vm();
1373     NativeCallFrameTracer tracer(&vm, exec);
1374     auto scope = DECLARE_THROW_SCOPE(vm);
1375
1376     Identifier property = JSValue::decode(encodedSubscript).toPropertyKey(exec);
1377     RETURN_IF_EXCEPTION(scope, void());
1378     scope.release();
1379     putWithThis<true>(exec, encodedBase, encodedThis, encodedValue, property);
1380 }
1381
1382 void JIT_OPERATION operationPutByValWithThis(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedThis, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue)
1383 {
1384     VM& vm = exec->vm();
1385     NativeCallFrameTracer tracer(&vm, exec);
1386     auto scope = DECLARE_THROW_SCOPE(vm);
1387
1388     Identifier property = JSValue::decode(encodedSubscript).toPropertyKey(exec);
1389     RETURN_IF_EXCEPTION(scope, void());
1390     scope.release();
1391     putWithThis<false>(exec, encodedBase, encodedThis, encodedValue, property);
1392 }
1393
1394 ALWAYS_INLINE static void defineDataProperty(ExecState* exec, VM& vm, JSObject* base, const Identifier& propertyName, JSValue value, int32_t attributes)
1395 {
1396     PropertyDescriptor descriptor = toPropertyDescriptor(value, jsUndefined(), jsUndefined(), DefinePropertyAttributes(attributes));
1397     ASSERT((descriptor.attributes() & PropertyAttribute::Accessor) || (!descriptor.isAccessorDescriptor()));
1398     if (base->methodTable(vm)->defineOwnProperty == JSObject::defineOwnProperty)
1399         JSObject::defineOwnProperty(base, exec, propertyName, descriptor, true);
1400     else
1401         base->methodTable(vm)->defineOwnProperty(base, exec, propertyName, descriptor, true);
1402 }
1403
1404 void JIT_OPERATION operationDefineDataProperty(ExecState* exec, JSObject* base, EncodedJSValue encodedProperty, EncodedJSValue encodedValue, int32_t attributes)
1405 {
1406     VM& vm = exec->vm();
1407     NativeCallFrameTracer tracer(&vm, exec);
1408     auto scope = DECLARE_THROW_SCOPE(vm);
1409
1410     Identifier propertyName = JSValue::decode(encodedProperty).toPropertyKey(exec);
1411     RETURN_IF_EXCEPTION(scope, void());
1412     scope.release();
1413     defineDataProperty(exec, vm, base, propertyName, JSValue::decode(encodedValue), attributes);
1414 }
1415
1416 void JIT_OPERATION operationDefineDataPropertyString(ExecState* exec, JSObject* base, JSString* property, EncodedJSValue encodedValue, int32_t attributes)
1417 {
1418     VM& vm = exec->vm();
1419     NativeCallFrameTracer tracer(&vm, exec);
1420     auto scope = DECLARE_THROW_SCOPE(vm);
1421
1422     Identifier propertyName = property->toIdentifier(exec);
1423     RETURN_IF_EXCEPTION(scope, void());
1424     scope.release();
1425     defineDataProperty(exec, vm, base, propertyName, JSValue::decode(encodedValue), attributes);
1426 }
1427
1428 void JIT_OPERATION operationDefineDataPropertyStringIdent(ExecState* exec, JSObject* base, UniquedStringImpl* property, EncodedJSValue encodedValue, int32_t attributes)
1429 {
1430     VM& vm = exec->vm();
1431     NativeCallFrameTracer tracer(&vm, exec);
1432     defineDataProperty(exec, vm, base, Identifier::fromUid(&vm, property), JSValue::decode(encodedValue), attributes);
1433 }
1434
1435 void JIT_OPERATION operationDefineDataPropertySymbol(ExecState* exec, JSObject* base, Symbol* property, EncodedJSValue encodedValue, int32_t attributes)
1436 {
1437     VM& vm = exec->vm();
1438     NativeCallFrameTracer tracer(&vm, exec);
1439     defineDataProperty(exec, vm, base, Identifier::fromUid(property->privateName()), JSValue::decode(encodedValue), attributes);
1440 }
1441
1442 ALWAYS_INLINE static void defineAccessorProperty(ExecState* exec, VM& vm, JSObject* base, const Identifier& propertyName, JSObject* getter, JSObject* setter, int32_t attributes)
1443 {
1444     PropertyDescriptor descriptor = toPropertyDescriptor(jsUndefined(), getter, setter, DefinePropertyAttributes(attributes));
1445     ASSERT((descriptor.attributes() & PropertyAttribute::Accessor) || (!descriptor.isAccessorDescriptor()));
1446     if (base->methodTable(vm)->defineOwnProperty == JSObject::defineOwnProperty)
1447         JSObject::defineOwnProperty(base, exec, propertyName, descriptor, true);
1448     else
1449         base->methodTable(vm)->defineOwnProperty(base, exec, propertyName, descriptor, true);
1450 }
1451
1452 void JIT_OPERATION operationDefineAccessorProperty(ExecState* exec, JSObject* base, EncodedJSValue encodedProperty, JSObject* getter, JSObject* setter, int32_t attributes)
1453 {
1454     VM& vm = exec->vm();
1455     NativeCallFrameTracer tracer(&vm, exec);
1456     auto scope = DECLARE_THROW_SCOPE(vm);
1457
1458     Identifier propertyName = JSValue::decode(encodedProperty).toPropertyKey(exec);
1459     RETURN_IF_EXCEPTION(scope, void());
1460     defineAccessorProperty(exec, vm, base, propertyName, getter, setter, attributes);
1461 }
1462
1463 void JIT_OPERATION operationDefineAccessorPropertyString(ExecState* exec, JSObject* base, JSString* property, JSObject* getter, JSObject* setter, int32_t attributes)
1464 {
1465     VM& vm = exec->vm();
1466     NativeCallFrameTracer tracer(&vm, exec);
1467     auto scope = DECLARE_THROW_SCOPE(vm);
1468
1469     Identifier propertyName = property->toIdentifier(exec);
1470     RETURN_IF_EXCEPTION(scope, void());
1471     defineAccessorProperty(exec, vm, base, propertyName, getter, setter, attributes);
1472 }
1473
1474 void JIT_OPERATION operationDefineAccessorPropertyStringIdent(ExecState* exec, JSObject* base, UniquedStringImpl* property, JSObject* getter, JSObject* setter, int32_t attributes)
1475 {
1476     VM& vm = exec->vm();
1477     NativeCallFrameTracer tracer(&vm, exec);
1478     defineAccessorProperty(exec, vm, base, Identifier::fromUid(&vm, property), getter, setter, attributes);
1479 }
1480
1481 void JIT_OPERATION operationDefineAccessorPropertySymbol(ExecState* exec, JSObject* base, Symbol* property, JSObject* getter, JSObject* setter, int32_t attributes)
1482 {
1483     VM& vm = exec->vm();
1484     NativeCallFrameTracer tracer(&vm, exec);
1485     defineAccessorProperty(exec, vm, base, Identifier::fromUid(property->privateName()), getter, setter, attributes);
1486 }
1487
1488 char* JIT_OPERATION operationNewArray(ExecState* exec, Structure* arrayStructure, void* buffer, size_t size)
1489 {
1490     VM* vm = &exec->vm();
1491     NativeCallFrameTracer tracer(vm, exec);
1492     
1493     return bitwise_cast<char*>(constructArray(exec, arrayStructure, static_cast<JSValue*>(buffer), size));
1494 }
1495
1496 char* JIT_OPERATION operationNewEmptyArray(ExecState* exec, Structure* arrayStructure)
1497 {
1498     VM* vm = &exec->vm();
1499     NativeCallFrameTracer tracer(vm, exec);
1500     
1501     return bitwise_cast<char*>(JSArray::create(*vm, arrayStructure));
1502 }
1503
1504 char* JIT_OPERATION operationNewArrayWithSize(ExecState* exec, Structure* arrayStructure, int32_t size, Butterfly* butterfly)
1505 {
1506     VM& vm = exec->vm();
1507     NativeCallFrameTracer tracer(&vm, exec);
1508     auto scope = DECLARE_THROW_SCOPE(vm);
1509
1510     if (UNLIKELY(size < 0))
1511         return bitwise_cast<char*>(throwException(exec, scope, createRangeError(exec, "Array size is not a small enough positive integer."_s)));
1512
1513     JSArray* result;
1514     if (butterfly)
1515         result = JSArray::createWithButterfly(vm, nullptr, arrayStructure, butterfly);
1516     else
1517         result = JSArray::create(vm, arrayStructure, size);
1518     return bitwise_cast<char*>(result);
1519 }
1520
1521 char* JIT_OPERATION operationNewArrayWithSizeAndHint(ExecState* exec, Structure* arrayStructure, int32_t size, int32_t vectorLengthHint, Butterfly* butterfly)
1522 {
1523     VM& vm = exec->vm();
1524     NativeCallFrameTracer tracer(&vm, exec);
1525     auto scope = DECLARE_THROW_SCOPE(vm);
1526
1527     if (UNLIKELY(size < 0))
1528         return bitwise_cast<char*>(throwException(exec, scope, createRangeError(exec, "Array size is not a small enough positive integer."_s)));
1529
1530     JSArray* result;
1531     if (butterfly)
1532         result = JSArray::createWithButterfly(vm, nullptr, arrayStructure, butterfly);
1533     else {
1534         result = JSArray::tryCreate(vm, arrayStructure, size, vectorLengthHint);
1535         RELEASE_ASSERT(result);
1536     }
1537     return bitwise_cast<char*>(result);
1538 }
1539
1540 JSCell* JIT_OPERATION operationNewArrayBuffer(ExecState* exec, Structure* arrayStructure, JSCell* immutableButterflyCell)
1541 {
1542     VM& vm = exec->vm();
1543     NativeCallFrameTracer tracer(&vm, exec);
1544     ASSERT(!arrayStructure->outOfLineCapacity());
1545     auto* immutableButterfly = jsCast<JSImmutableButterfly*>(immutableButterflyCell);
1546     ASSERT(arrayStructure->indexingMode() == immutableButterfly->indexingMode() || hasAnyArrayStorage(arrayStructure->indexingMode()));
1547     auto* result = CommonSlowPaths::allocateNewArrayBuffer(vm, arrayStructure, immutableButterfly);
1548     ASSERT(result->indexingMode() == result->structure(vm)->indexingMode());
1549     ASSERT(result->structure(vm) == arrayStructure);
1550     return result;
1551 }
1552
1553 char* JIT_OPERATION operationNewInt8ArrayWithSize(
1554     ExecState* exec, Structure* structure, int32_t length, char* vector)
1555 {
1556     return newTypedArrayWithSize<JSInt8Array>(exec, structure, length, vector);
1557 }
1558
1559 char* JIT_OPERATION operationNewInt8ArrayWithOneArgument(
1560     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
1561 {
1562     VM& vm = exec->vm();
1563     NativeCallFrameTracer tracer(&vm, exec);
1564     return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSInt8Array>(exec, structure, encodedValue, 0, std::nullopt));
1565 }
1566
1567 char* JIT_OPERATION operationNewInt16ArrayWithSize(
1568     ExecState* exec, Structure* structure, int32_t length, char* vector)
1569 {
1570     return newTypedArrayWithSize<JSInt16Array>(exec, structure, length, vector);
1571 }
1572
1573 char* JIT_OPERATION operationNewInt16ArrayWithOneArgument(
1574     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
1575 {
1576     VM& vm = exec->vm();
1577     NativeCallFrameTracer tracer(&vm, exec);
1578     return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSInt16Array>(exec, structure, encodedValue, 0, std::nullopt));
1579 }
1580
1581 char* JIT_OPERATION operationNewInt32ArrayWithSize(
1582     ExecState* exec, Structure* structure, int32_t length, char* vector)
1583 {
1584     return newTypedArrayWithSize<JSInt32Array>(exec, structure, length, vector);
1585 }
1586
1587 char* JIT_OPERATION operationNewInt32ArrayWithOneArgument(
1588     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
1589 {
1590     VM& vm = exec->vm();
1591     NativeCallFrameTracer tracer(&vm, exec);
1592     return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSInt32Array>(exec, structure, encodedValue, 0, std::nullopt));
1593 }
1594
1595 char* JIT_OPERATION operationNewUint8ArrayWithSize(
1596     ExecState* exec, Structure* structure, int32_t length, char* vector)
1597 {
1598     return newTypedArrayWithSize<JSUint8Array>(exec, structure, length, vector);
1599 }
1600
1601 char* JIT_OPERATION operationNewUint8ArrayWithOneArgument(
1602     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
1603 {
1604     VM& vm = exec->vm();
1605     NativeCallFrameTracer tracer(&vm, exec);
1606     return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSUint8Array>(exec, structure, encodedValue, 0, std::nullopt));
1607 }
1608
1609 char* JIT_OPERATION operationNewUint8ClampedArrayWithSize(
1610     ExecState* exec, Structure* structure, int32_t length, char* vector)
1611 {
1612     return newTypedArrayWithSize<JSUint8ClampedArray>(exec, structure, length, vector);
1613 }
1614
1615 char* JIT_OPERATION operationNewUint8ClampedArrayWithOneArgument(
1616     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
1617 {
1618     VM& vm = exec->vm();
1619     NativeCallFrameTracer tracer(&vm, exec);
1620     return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSUint8ClampedArray>(exec, structure, encodedValue, 0, std::nullopt));
1621 }
1622
1623 char* JIT_OPERATION operationNewUint16ArrayWithSize(
1624     ExecState* exec, Structure* structure, int32_t length, char* vector)
1625 {
1626     return newTypedArrayWithSize<JSUint16Array>(exec, structure, length, vector);
1627 }
1628
1629 char* JIT_OPERATION operationNewUint16ArrayWithOneArgument(
1630     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
1631 {
1632     VM& vm = exec->vm();
1633     NativeCallFrameTracer tracer(&vm, exec);
1634     return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSUint16Array>(exec, structure, encodedValue, 0, std::nullopt));
1635 }
1636
1637 char* JIT_OPERATION operationNewUint32ArrayWithSize(
1638     ExecState* exec, Structure* structure, int32_t length, char* vector)
1639 {
1640     return newTypedArrayWithSize<JSUint32Array>(exec, structure, length, vector);
1641 }
1642
1643 char* JIT_OPERATION operationNewUint32ArrayWithOneArgument(
1644     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
1645 {
1646     VM& vm = exec->vm();
1647     NativeCallFrameTracer tracer(&vm, exec);
1648     return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSUint32Array>(exec, structure, encodedValue, 0, std::nullopt));
1649 }
1650
1651 char* JIT_OPERATION operationNewFloat32ArrayWithSize(
1652     ExecState* exec, Structure* structure, int32_t length, char* vector)
1653 {
1654     return newTypedArrayWithSize<JSFloat32Array>(exec, structure, length, vector);
1655 }
1656
1657 char* JIT_OPERATION operationNewFloat32ArrayWithOneArgument(
1658     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
1659 {
1660     VM& vm = exec->vm();
1661     NativeCallFrameTracer tracer(&vm, exec);
1662     return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSFloat32Array>(exec, structure, encodedValue, 0, std::nullopt));
1663 }
1664
1665 char* JIT_OPERATION operationNewFloat64ArrayWithSize(
1666     ExecState* exec, Structure* structure, int32_t length, char* vector)
1667 {
1668     return newTypedArrayWithSize<JSFloat64Array>(exec, structure, length, vector);
1669 }
1670
1671 char* JIT_OPERATION operationNewFloat64ArrayWithOneArgument(
1672     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
1673 {
1674     VM& vm = exec->vm();
1675     NativeCallFrameTracer tracer(&vm, exec);
1676     return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSFloat64Array>(exec, structure, encodedValue, 0, std::nullopt));
1677 }
1678
1679 JSCell* JIT_OPERATION operationCreateActivationDirect(ExecState* exec, Structure* structure, JSScope* scope, SymbolTable* table, EncodedJSValue initialValueEncoded)
1680 {
1681     JSValue initialValue = JSValue::decode(initialValueEncoded);
1682     ASSERT(initialValue == jsUndefined() || initialValue == jsTDZValue());
1683     VM& vm = exec->vm();
1684     NativeCallFrameTracer tracer(&vm, exec);
1685     return JSLexicalEnvironment::create(vm, structure, scope, table, initialValue);
1686 }
1687
1688 JSCell* JIT_OPERATION operationCreateDirectArguments(ExecState* exec, Structure* structure, uint32_t length, uint32_t minCapacity)
1689 {
1690     VM& vm = exec->vm();
1691     NativeCallFrameTracer target(&vm, exec);
1692     DirectArguments* result = DirectArguments::create(
1693         vm, structure, length, std::max(length, minCapacity));
1694     // The caller will store to this object without barriers. Most likely, at this point, this is
1695     // still a young object and so no barriers are needed. But it's good to be careful anyway,
1696     // since the GC should be allowed to do crazy (like pretenuring, for example).
1697     vm.heap.writeBarrier(result);
1698     return result;
1699 }
1700
1701 JSCell* JIT_OPERATION operationCreateScopedArguments(ExecState* exec, Structure* structure, Register* argumentStart, uint32_t length, JSFunction* callee, JSLexicalEnvironment* scope)
1702 {
1703     VM& vm = exec->vm();
1704     NativeCallFrameTracer target(&vm, exec);
1705     
1706     // We could pass the ScopedArgumentsTable* as an argument. We currently don't because I
1707     // didn't feel like changing the max number of arguments for a slow path call from 6 to 7.
1708     ScopedArgumentsTable* table = scope->symbolTable()->arguments();
1709     
1710     return ScopedArguments::createByCopyingFrom(
1711         vm, structure, argumentStart, length, callee, table, scope);
1712 }
1713
1714 JSCell* JIT_OPERATION operationCreateClonedArguments(ExecState* exec, Structure* structure, Register* argumentStart, uint32_t length, JSFunction* callee)
1715 {
1716     VM& vm = exec->vm();
1717     NativeCallFrameTracer target(&vm, exec);
1718     return ClonedArguments::createByCopyingFrom(
1719         exec, structure, argumentStart, length, callee);
1720 }
1721
1722 JSCell* JIT_OPERATION operationCreateDirectArgumentsDuringExit(ExecState* exec, InlineCallFrame* inlineCallFrame, JSFunction* callee, uint32_t argumentCount)
1723 {
1724     VM& vm = exec->vm();
1725     NativeCallFrameTracer target(&vm, exec);
1726     
1727     DeferGCForAWhile deferGC(vm.heap);
1728     
1729     CodeBlock* codeBlock;
1730     if (inlineCallFrame)
1731         codeBlock = baselineCodeBlockForInlineCallFrame(inlineCallFrame);
1732     else
1733         codeBlock = exec->codeBlock();
1734     
1735     unsigned length = argumentCount - 1;
1736     unsigned capacity = std::max(length, static_cast<unsigned>(codeBlock->numParameters() - 1));
1737     DirectArguments* result = DirectArguments::create(
1738         vm, codeBlock->globalObject()->directArgumentsStructure(), length, capacity);
1739     
1740     result->setCallee(vm, callee);
1741     
1742     Register* arguments =
1743         exec->registers() + (inlineCallFrame ? inlineCallFrame->stackOffset : 0) +
1744         CallFrame::argumentOffset(0);
1745     for (unsigned i = length; i--;)
1746         result->setIndexQuickly(vm, i, arguments[i].jsValue());
1747     
1748     return result;
1749 }
1750
1751 JSCell* JIT_OPERATION operationCreateClonedArgumentsDuringExit(ExecState* exec, InlineCallFrame* inlineCallFrame, JSFunction* callee, uint32_t argumentCount)
1752 {
1753     VM& vm = exec->vm();
1754     NativeCallFrameTracer target(&vm, exec);
1755     
1756     DeferGCForAWhile deferGC(vm.heap);
1757     
1758     CodeBlock* codeBlock;
1759     if (inlineCallFrame)
1760         codeBlock = baselineCodeBlockForInlineCallFrame(inlineCallFrame);
1761     else
1762         codeBlock = exec->codeBlock();
1763     
1764     unsigned length = argumentCount - 1;
1765     ClonedArguments* result = ClonedArguments::createEmpty(
1766         vm, codeBlock->globalObject()->clonedArgumentsStructure(), callee, length);
1767     
1768     Register* arguments =
1769         exec->registers() + (inlineCallFrame ? inlineCallFrame->stackOffset : 0) +
1770         CallFrame::argumentOffset(0);
1771     for (unsigned i = length; i--;)
1772         result->putDirectIndex(exec, i, arguments[i].jsValue());
1773
1774     
1775     return result;
1776 }
1777
1778 JSCell* JIT_OPERATION operationCreateRest(ExecState* exec, Register* argumentStart, unsigned numberOfParamsToSkip, unsigned arraySize)
1779 {
1780     VM* vm = &exec->vm();
1781     NativeCallFrameTracer tracer(vm, exec);
1782
1783     JSGlobalObject* globalObject = exec->lexicalGlobalObject();
1784     Structure* structure = globalObject->restParameterStructure();
1785     static_assert(sizeof(Register) == sizeof(JSValue), "This is a strong assumption here.");
1786     JSValue* argumentsToCopyRegion = bitwise_cast<JSValue*>(argumentStart) + numberOfParamsToSkip;
1787     return constructArray(exec, structure, argumentsToCopyRegion, arraySize);
1788 }
1789
1790 size_t JIT_OPERATION operationObjectIsObject(ExecState* exec, JSGlobalObject* globalObject, JSCell* object)
1791 {
1792     VM& vm = exec->vm();
1793     NativeCallFrameTracer tracer(&vm, exec);
1794
1795     ASSERT(jsDynamicCast<JSObject*>(vm, object));
1796     
1797     if (object->structure(vm)->masqueradesAsUndefined(globalObject))
1798         return false;
1799     if (object->isFunction(vm))
1800         return false;
1801     return true;
1802 }
1803
1804 size_t JIT_OPERATION operationObjectIsFunction(ExecState* exec, JSGlobalObject* globalObject, JSCell* object)
1805 {
1806     VM& vm = exec->vm();
1807     NativeCallFrameTracer tracer(&vm, exec);
1808
1809     ASSERT(jsDynamicCast<JSObject*>(vm, object));
1810     
1811     if (object->structure(vm)->masqueradesAsUndefined(globalObject))
1812         return false;
1813     if (object->isFunction(vm))
1814         return true;
1815     return false;
1816 }
1817
1818 JSCell* JIT_OPERATION operationTypeOfObject(ExecState* exec, JSGlobalObject* globalObject, JSCell* object)
1819 {
1820     VM& vm = exec->vm();
1821     NativeCallFrameTracer tracer(&vm, exec);
1822
1823     ASSERT(jsDynamicCast<JSObject*>(vm, object));
1824     
1825     if (object->structure(vm)->masqueradesAsUndefined(globalObject))
1826         return vm.smallStrings.undefinedString();
1827     if (object->isFunction(vm))
1828         return vm.smallStrings.functionString();
1829     return vm.smallStrings.objectString();
1830 }
1831
1832 int32_t JIT_OPERATION operationTypeOfObjectAsTypeofType(ExecState* exec, JSGlobalObject* globalObject, JSCell* object)
1833 {
1834     VM& vm = exec->vm();
1835     NativeCallFrameTracer tracer(&vm, exec);
1836
1837     ASSERT(jsDynamicCast<JSObject*>(vm, object));
1838     
1839     if (object->structure(vm)->masqueradesAsUndefined(globalObject))
1840         return static_cast<int32_t>(TypeofType::Undefined);
1841     if (object->isFunction(vm))
1842         return static_cast<int32_t>(TypeofType::Function);
1843     return static_cast<int32_t>(TypeofType::Object);
1844 }
1845
1846 char* JIT_OPERATION operationAllocateSimplePropertyStorageWithInitialCapacity(ExecState* exec)
1847 {
1848     VM& vm = exec->vm();
1849     NativeCallFrameTracer tracer(&vm, exec);
1850
1851     return reinterpret_cast<char*>(
1852         Butterfly::createUninitialized(vm, 0, 0, initialOutOfLineCapacity, false, 0));
1853 }
1854
1855 char* JIT_OPERATION operationAllocateSimplePropertyStorage(ExecState* exec, size_t newSize)
1856 {
1857     VM& vm = exec->vm();
1858     NativeCallFrameTracer tracer(&vm, exec);
1859
1860     return reinterpret_cast<char*>(
1861         Butterfly::createUninitialized(vm, 0, 0, newSize, false, 0));
1862 }
1863
1864 char* JIT_OPERATION operationAllocateComplexPropertyStorageWithInitialCapacity(ExecState* exec, JSObject* object)
1865 {
1866     VM& vm = exec->vm();
1867     NativeCallFrameTracer tracer(&vm, exec);
1868
1869     ASSERT(!object->structure(vm)->outOfLineCapacity());
1870     return reinterpret_cast<char*>(
1871         object->allocateMoreOutOfLineStorage(vm, 0, initialOutOfLineCapacity));
1872 }
1873
1874 char* JIT_OPERATION operationAllocateComplexPropertyStorage(ExecState* exec, JSObject* object, size_t newSize)
1875 {
1876     VM& vm = exec->vm();
1877     NativeCallFrameTracer tracer(&vm, exec);
1878
1879     return reinterpret_cast<char*>(
1880         object->allocateMoreOutOfLineStorage(vm, object->structure(vm)->outOfLineCapacity(), newSize));
1881 }
1882
1883 char* JIT_OPERATION operationEnsureInt32(ExecState* exec, JSCell* cell)
1884 {
1885     VM& vm = exec->vm();
1886     NativeCallFrameTracer tracer(&vm, exec);
1887     
1888     if (!cell->isObject())
1889         return 0;
1890
1891     auto* result = reinterpret_cast<char*>(asObject(cell)->tryMakeWritableInt32(vm).data());
1892     ASSERT((!isCopyOnWrite(asObject(cell)->indexingMode()) && hasInt32(cell->indexingMode())) || !result);
1893     return result;
1894 }
1895
1896 char* JIT_OPERATION operationEnsureDouble(ExecState* exec, JSCell* cell)
1897 {
1898     VM& vm = exec->vm();
1899     NativeCallFrameTracer tracer(&vm, exec);
1900     
1901     if (!cell->isObject())
1902         return 0;
1903
1904     auto* result = reinterpret_cast<char*>(asObject(cell)->tryMakeWritableDouble(vm).data());
1905     ASSERT((!isCopyOnWrite(asObject(cell)->indexingMode()) && hasDouble(cell->indexingMode())) || !result);
1906     return result;
1907 }
1908
1909 char* JIT_OPERATION operationEnsureContiguous(ExecState* exec, JSCell* cell)
1910 {
1911     VM& vm = exec->vm();
1912     NativeCallFrameTracer tracer(&vm, exec);
1913     
1914     if (!cell->isObject())
1915         return 0;
1916     
1917     auto* result = reinterpret_cast<char*>(asObject(cell)->tryMakeWritableContiguous(vm).data());
1918     ASSERT((!isCopyOnWrite(asObject(cell)->indexingMode()) && hasContiguous(cell->indexingMode())) || !result);
1919     return result;
1920 }
1921
1922 char* JIT_OPERATION operationEnsureArrayStorage(ExecState* exec, JSCell* cell)
1923 {
1924     VM& vm = exec->vm();
1925     NativeCallFrameTracer tracer(&vm, exec);
1926     
1927     if (!cell->isObject())
1928         return 0;
1929
1930     auto* result = reinterpret_cast<char*>(asObject(cell)->ensureArrayStorage(vm));
1931     ASSERT((!isCopyOnWrite(asObject(cell)->indexingMode()) && hasAnyArrayStorage(cell->indexingMode())) || !result);
1932     return result;
1933 }
1934
1935 EncodedJSValue JIT_OPERATION operationHasGenericProperty(ExecState* exec, EncodedJSValue encodedBaseValue, JSCell* propertyName)
1936 {
1937     VM& vm = exec->vm();
1938     NativeCallFrameTracer tracer(&vm, exec);
1939     JSValue baseValue = JSValue::decode(encodedBaseValue);
1940     if (baseValue.isUndefinedOrNull())
1941         return JSValue::encode(jsBoolean(false));
1942
1943     JSObject* base = baseValue.toObject(exec);
1944     if (!base)
1945         return JSValue::encode(JSValue());
1946     return JSValue::encode(jsBoolean(base->hasPropertyGeneric(exec, asString(propertyName)->toIdentifier(exec), PropertySlot::InternalMethodType::GetOwnProperty)));
1947 }
1948
1949 size_t JIT_OPERATION operationHasIndexedPropertyByInt(ExecState* exec, JSCell* baseCell, int32_t subscript, int32_t internalMethodType)
1950 {
1951     VM& vm = exec->vm();
1952     NativeCallFrameTracer tracer(&vm, exec);
1953     JSObject* object = baseCell->toObject(exec, exec->lexicalGlobalObject());
1954     if (UNLIKELY(subscript < 0)) {
1955         // Go the slowest way possible because negative indices don't use indexed storage.
1956         return object->hasPropertyGeneric(exec, Identifier::from(exec, subscript), static_cast<PropertySlot::InternalMethodType>(internalMethodType));
1957     }
1958     return object->hasPropertyGeneric(exec, subscript, static_cast<PropertySlot::InternalMethodType>(internalMethodType));
1959 }
1960
1961 JSCell* JIT_OPERATION operationGetPropertyEnumerator(ExecState* exec, EncodedJSValue encodedBase)
1962 {
1963     VM& vm = exec->vm();
1964     NativeCallFrameTracer tracer(&vm, exec);
1965     auto scope = DECLARE_THROW_SCOPE(vm);
1966
1967     JSValue base = JSValue::decode(encodedBase);
1968     if (base.isUndefinedOrNull())
1969         return JSPropertyNameEnumerator::create(vm);
1970
1971     JSObject* baseObject = base.toObject(exec);
1972     RETURN_IF_EXCEPTION(scope, { });
1973
1974     scope.release();
1975     return propertyNameEnumerator(exec, baseObject);
1976 }
1977
1978 JSCell* JIT_OPERATION operationGetPropertyEnumeratorCell(ExecState* exec, JSCell* cell)
1979 {
1980     VM& vm = exec->vm();
1981     NativeCallFrameTracer tracer(&vm, exec);
1982     auto scope = DECLARE_THROW_SCOPE(vm);
1983
1984     JSObject* base = cell->toObject(exec, exec->lexicalGlobalObject());
1985     RETURN_IF_EXCEPTION(scope, { });
1986
1987     scope.release();
1988     return propertyNameEnumerator(exec, base);
1989 }
1990
1991 JSCell* JIT_OPERATION operationToIndexString(ExecState* exec, int32_t index)
1992 {
1993     VM& vm = exec->vm();
1994     NativeCallFrameTracer tracer(&vm, exec);
1995     return jsString(exec, Identifier::from(exec, index).string());
1996 }
1997
1998 JSCell* JIT_OPERATION operationNewRegexpWithLastIndex(ExecState* exec, JSCell* regexpPtr, EncodedJSValue encodedLastIndex)
1999 {
2000     VM& vm = exec->vm();
2001     NativeCallFrameTracer tracer(&vm, exec);
2002
2003     RegExp* regexp = static_cast<RegExp*>(regexpPtr);
2004     ASSERT(regexp->isValid());
2005     return RegExpObject::create(vm, exec->lexicalGlobalObject()->regExpStructure(), regexp, JSValue::decode(encodedLastIndex));
2006 }
2007
2008 StringImpl* JIT_OPERATION operationResolveRope(ExecState* exec, JSString* string)
2009 {
2010     VM& vm = exec->vm();
2011     NativeCallFrameTracer tracer(&vm, exec);
2012
2013     return string->value(exec).impl();
2014 }
2015
2016 JSString* JIT_OPERATION operationStringValueOf(ExecState* exec, EncodedJSValue encodedArgument)
2017 {
2018     VM& vm = exec->vm();
2019     NativeCallFrameTracer tracer(&vm, exec);
2020     auto scope = DECLARE_THROW_SCOPE(vm);
2021
2022     JSValue argument = JSValue::decode(encodedArgument);
2023
2024     if (argument.isString())
2025         return asString(argument);
2026
2027     if (auto* stringObject = jsDynamicCast<StringObject*>(vm, argument))
2028         return stringObject->internalValue();
2029
2030     throwVMTypeError(exec, scope);
2031     return nullptr;
2032 }
2033
2034 JSCell* JIT_OPERATION operationStringSubstr(ExecState* exec, JSCell* cell, int32_t from, int32_t span)
2035 {
2036     VM& vm = exec->vm();
2037     NativeCallFrameTracer tracer(&vm, exec);
2038     auto scope = DECLARE_THROW_SCOPE(vm);
2039
2040     auto string = jsCast<JSString*>(cell)->value(exec);
2041     RETURN_IF_EXCEPTION(scope, nullptr);
2042     return jsSubstring(exec, string, from, span);
2043 }
2044
2045 JSString* JIT_OPERATION operationToLowerCase(ExecState* exec, JSString* string, uint32_t failingIndex)
2046 {
2047     VM& vm = exec->vm();
2048     NativeCallFrameTracer tracer(&vm, exec);
2049
2050     auto scope = DECLARE_THROW_SCOPE(vm);
2051
2052     const String& inputString = string->value(exec);
2053     RETURN_IF_EXCEPTION(scope, nullptr);
2054     if (!inputString.length())
2055         return vm.smallStrings.emptyString();
2056
2057     String lowercasedString = inputString.is8Bit() ? inputString.convertToLowercaseWithoutLocaleStartingAtFailingIndex8Bit(failingIndex) : inputString.convertToLowercaseWithoutLocale();
2058     if (lowercasedString.impl() == inputString.impl())
2059         return string;
2060     scope.release();
2061     return jsString(exec, lowercasedString);
2062 }
2063
2064 char* JIT_OPERATION operationInt32ToString(ExecState* exec, int32_t value, int32_t radix)
2065 {
2066     VM& vm = exec->vm();
2067     NativeCallFrameTracer tracer(&vm, exec);
2068
2069     auto scope = DECLARE_THROW_SCOPE(vm);
2070
2071     if (radix < 2 || radix > 36) {
2072         throwVMError(exec, scope, createRangeError(exec, "toString() radix argument must be between 2 and 36"_s));
2073         return nullptr;
2074     }
2075
2076     return reinterpret_cast<char*>(int32ToString(vm, value, radix));
2077 }
2078
2079 char* JIT_OPERATION operationInt52ToString(ExecState* exec, int64_t value, int32_t radix)
2080 {
2081     VM& vm = exec->vm();
2082     NativeCallFrameTracer tracer(&vm, exec);
2083
2084     auto scope = DECLARE_THROW_SCOPE(vm);
2085
2086     if (radix < 2 || radix > 36) {
2087         throwVMError(exec, scope, createRangeError(exec, "toString() radix argument must be between 2 and 36"_s));
2088         return nullptr;
2089     }
2090
2091     return reinterpret_cast<char*>(int52ToString(vm, value, radix));
2092 }
2093
2094 char* JIT_OPERATION operationDoubleToString(ExecState* exec, double value, int32_t radix)
2095 {
2096     VM& vm = exec->vm();
2097     NativeCallFrameTracer tracer(&vm, exec);
2098
2099     auto scope = DECLARE_THROW_SCOPE(vm);
2100
2101     if (radix < 2 || radix > 36) {
2102         throwVMError(exec, scope, createRangeError(exec, "toString() radix argument must be between 2 and 36"_s));
2103         return nullptr;
2104     }
2105
2106     return reinterpret_cast<char*>(numberToString(vm, value, radix));
2107 }
2108
2109 char* JIT_OPERATION operationInt32ToStringWithValidRadix(ExecState* exec, int32_t value, int32_t radix)
2110 {
2111     VM& vm = exec->vm();
2112     NativeCallFrameTracer tracer(&vm, exec);
2113
2114     return reinterpret_cast<char*>(int32ToString(vm, value, radix));
2115 }
2116
2117 char* JIT_OPERATION operationInt52ToStringWithValidRadix(ExecState* exec, int64_t value, int32_t radix)
2118 {
2119     VM& vm = exec->vm();
2120     NativeCallFrameTracer tracer(&vm, exec);
2121
2122     return reinterpret_cast<char*>(int52ToString(vm, value, radix));
2123 }
2124
2125 char* JIT_OPERATION operationDoubleToStringWithValidRadix(ExecState* exec, double value, int32_t radix)
2126 {
2127     VM& vm = exec->vm();
2128     NativeCallFrameTracer tracer(&vm, exec);
2129
2130     return reinterpret_cast<char*>(numberToString(vm, value, radix));
2131 }
2132
2133 JSString* JIT_OPERATION operationSingleCharacterString(ExecState* exec, int32_t character)
2134 {
2135     VM& vm = exec->vm();
2136     NativeCallFrameTracer tracer(&vm, exec);
2137     
2138     return jsSingleCharacterString(exec, static_cast<UChar>(character));
2139 }
2140
2141 JSCell* JIT_OPERATION operationNewStringObject(ExecState* exec, JSString* string, Structure* structure)
2142 {
2143     VM& vm = exec->vm();
2144     NativeCallFrameTracer tracer(&vm, exec);
2145     
2146     return StringObject::create(vm, structure, string);
2147 }
2148
2149 JSString* JIT_OPERATION operationToStringOnCell(ExecState* exec, JSCell* cell)
2150 {
2151     VM& vm = exec->vm();
2152     NativeCallFrameTracer tracer(&vm, exec);
2153     
2154     return JSValue(cell).toString(exec);
2155 }
2156
2157 JSString* JIT_OPERATION operationToString(ExecState* exec, EncodedJSValue value)
2158 {
2159     VM& vm = exec->vm();
2160     NativeCallFrameTracer tracer(&vm, exec);
2161
2162     return JSValue::decode(value).toString(exec);
2163 }
2164
2165 JSString* JIT_OPERATION operationCallStringConstructorOnCell(ExecState* exec, JSCell* cell)
2166 {
2167     VM& vm = exec->vm();
2168     NativeCallFrameTracer tracer(&vm, exec);
2169
2170     return stringConstructor(exec, cell);
2171 }
2172
2173 JSString* JIT_OPERATION operationCallStringConstructor(ExecState* exec, EncodedJSValue value)
2174 {
2175     VM& vm = exec->vm();
2176     NativeCallFrameTracer tracer(&vm, exec);
2177
2178     return stringConstructor(exec, JSValue::decode(value));
2179 }
2180
2181 JSString* JIT_OPERATION operationMakeRope2(ExecState* exec, JSString* left, JSString* right)
2182 {
2183     VM& vm = exec->vm();
2184     NativeCallFrameTracer tracer(&vm, exec);
2185
2186     return jsString(exec, left, right);
2187 }
2188
2189 JSString* JIT_OPERATION operationMakeRope3(ExecState* exec, JSString* a, JSString* b, JSString* c)
2190 {
2191     VM& vm = exec->vm();
2192     NativeCallFrameTracer tracer(&vm, exec);
2193
2194     return jsString(exec, a, b, c);
2195 }
2196
2197 JSString* JIT_OPERATION operationStrCat2(ExecState* exec, EncodedJSValue a, EncodedJSValue b)
2198 {
2199     VM& vm = exec->vm();
2200     NativeCallFrameTracer tracer(&vm, exec);
2201     auto scope = DECLARE_THROW_SCOPE(vm);
2202
2203     ASSERT(!JSValue::decode(a).isSymbol());
2204     ASSERT(!JSValue::decode(b).isSymbol());
2205     JSString* str1 = JSValue::decode(a).toString(exec);
2206     scope.assertNoException(); // Impossible, since we must have been given non-Symbol primitives.
2207     JSString* str2 = JSValue::decode(b).toString(exec);
2208     scope.assertNoException();
2209
2210     scope.release();
2211     return jsString(exec, str1, str2);
2212 }
2213     
2214 JSString* JIT_OPERATION operationStrCat3(ExecState* exec, EncodedJSValue a, EncodedJSValue b, EncodedJSValue c)
2215 {
2216     VM& vm = exec->vm();
2217     NativeCallFrameTracer tracer(&vm, exec);
2218     auto scope = DECLARE_THROW_SCOPE(vm);
2219
2220     ASSERT(!JSValue::decode(a).isSymbol());
2221     ASSERT(!JSValue::decode(b).isSymbol());
2222     ASSERT(!JSValue::decode(c).isSymbol());
2223     JSString* str1 = JSValue::decode(a).toString(exec);
2224     scope.assertNoException(); // Impossible, since we must have been given non-Symbol primitives.
2225     JSString* str2 = JSValue::decode(b).toString(exec);
2226     scope.assertNoException();
2227     JSString* str3 = JSValue::decode(c).toString(exec);
2228     scope.assertNoException();
2229
2230     scope.release();
2231     return jsString(exec, str1, str2, str3);
2232 }
2233
2234 char* JIT_OPERATION operationFindSwitchImmTargetForDouble(
2235     ExecState* exec, EncodedJSValue encodedValue, size_t tableIndex)
2236 {
2237     VM& vm = exec->vm();
2238     NativeCallFrameTracer tracer(&vm, exec);
2239
2240     CodeBlock* codeBlock = exec->codeBlock();
2241     SimpleJumpTable& table = codeBlock->switchJumpTable(tableIndex);
2242     JSValue value = JSValue::decode(encodedValue);
2243     ASSERT(value.isDouble());
2244     double asDouble = value.asDouble();
2245     int32_t asInt32 = static_cast<int32_t>(asDouble);
2246     if (asDouble == asInt32)
2247         return table.ctiForValue(asInt32).executableAddress<char*>();
2248     return table.ctiDefault.executableAddress<char*>();
2249 }
2250
2251 char* JIT_OPERATION operationSwitchString(ExecState* exec, size_t tableIndex, JSString* string)
2252 {
2253     VM& vm = exec->vm();
2254     NativeCallFrameTracer tracer(&vm, exec);
2255
2256     return exec->codeBlock()->stringSwitchJumpTable(tableIndex).ctiForValue(string->value(exec).impl()).executableAddress<char*>();
2257 }
2258
2259 int32_t JIT_OPERATION operationSwitchStringAndGetBranchOffset(ExecState* exec, size_t tableIndex, JSString* string)
2260 {
2261     VM& vm = exec->vm();
2262     NativeCallFrameTracer tracer(&vm, exec);
2263
2264     return exec->codeBlock()->stringSwitchJumpTable(tableIndex).offsetForValue(string->value(exec).impl(), std::numeric_limits<int32_t>::min());
2265 }
2266
2267 uintptr_t JIT_OPERATION operationCompareStringImplLess(StringImpl* a, StringImpl* b)
2268 {
2269     return codePointCompare(a, b) < 0;
2270 }
2271
2272 uintptr_t JIT_OPERATION operationCompareStringImplLessEq(StringImpl* a, StringImpl* b)
2273 {
2274     return codePointCompare(a, b) <= 0;
2275 }
2276
2277 uintptr_t JIT_OPERATION operationCompareStringImplGreater(StringImpl* a, StringImpl* b)
2278 {
2279     return codePointCompare(a, b) > 0;
2280 }
2281
2282 uintptr_t JIT_OPERATION operationCompareStringImplGreaterEq(StringImpl* a, StringImpl* b)
2283 {
2284     return codePointCompare(a, b) >= 0;
2285 }
2286
2287 uintptr_t JIT_OPERATION operationCompareStringLess(ExecState* exec, JSString* a, JSString* b)
2288 {
2289     VM& vm = exec->vm();
2290     NativeCallFrameTracer tracer(&vm, exec);
2291
2292     return codePointCompareLessThan(asString(a)->value(exec), asString(b)->value(exec));
2293 }
2294
2295 uintptr_t JIT_OPERATION operationCompareStringLessEq(ExecState* exec, JSString* a, JSString* b)
2296 {
2297     VM& vm = exec->vm();
2298     NativeCallFrameTracer tracer(&vm, exec);
2299
2300     return !codePointCompareLessThan(asString(b)->value(exec), asString(a)->value(exec));
2301 }
2302
2303 uintptr_t JIT_OPERATION operationCompareStringGreater(ExecState* exec, JSString* a, JSString* b)
2304 {
2305     VM& vm = exec->vm();
2306     NativeCallFrameTracer tracer(&vm, exec);
2307
2308     return codePointCompareLessThan(asString(b)->value(exec), asString(a)->value(exec));
2309 }
2310
2311 uintptr_t JIT_OPERATION operationCompareStringGreaterEq(ExecState* exec, JSString* a, JSString* b)
2312 {
2313     VM& vm = exec->vm();
2314     NativeCallFrameTracer tracer(&vm, exec);
2315
2316     return !codePointCompareLessThan(asString(a)->value(exec), asString(b)->value(exec));
2317 }
2318
2319 void JIT_OPERATION operationNotifyWrite(ExecState* exec, WatchpointSet* set)
2320 {
2321     VM& vm = exec->vm();
2322     NativeCallFrameTracer tracer(&vm, exec);
2323
2324     set->touch(vm, "Executed NotifyWrite");
2325 }
2326
2327 void JIT_OPERATION operationThrowStackOverflowForVarargs(ExecState* exec)
2328 {
2329     VM& vm = exec->vm();
2330     NativeCallFrameTracer tracer(&vm, exec);
2331     auto scope = DECLARE_THROW_SCOPE(vm);
2332     throwStackOverflowError(exec, scope);
2333 }
2334
2335 int32_t JIT_OPERATION operationSizeOfVarargs(ExecState* exec, EncodedJSValue encodedArguments, uint32_t firstVarArgOffset)
2336 {
2337     VM& vm = exec->vm();
2338     NativeCallFrameTracer tracer(&vm, exec);
2339     JSValue arguments = JSValue::decode(encodedArguments);
2340     
2341     return sizeOfVarargs(exec, arguments, firstVarArgOffset);
2342 }
2343
2344 int32_t JIT_OPERATION operationHasOwnProperty(ExecState* exec, JSObject* thisObject, EncodedJSValue encodedKey)
2345 {
2346     VM& vm = exec->vm();
2347     NativeCallFrameTracer tracer(&vm, exec);
2348     auto scope = DECLARE_THROW_SCOPE(vm);
2349
2350     JSValue key = JSValue::decode(encodedKey);
2351     Identifier propertyName = key.toPropertyKey(exec);
2352     RETURN_IF_EXCEPTION(scope, false);
2353
2354     PropertySlot slot(thisObject, PropertySlot::InternalMethodType::GetOwnProperty);
2355     bool result = thisObject->hasOwnProperty(exec, propertyName.impl(), slot);
2356     RETURN_IF_EXCEPTION(scope, false);
2357
2358     HasOwnPropertyCache* hasOwnPropertyCache = vm.hasOwnPropertyCache();
2359     ASSERT(hasOwnPropertyCache);
2360     hasOwnPropertyCache->tryAdd(vm, slot, thisObject, propertyName.impl(), result);
2361     return result;
2362 }
2363
2364 int32_t JIT_OPERATION operationNumberIsInteger(ExecState* exec, EncodedJSValue value)
2365 {
2366     VM& vm = exec->vm();
2367     NativeCallFrameTracer tracer(&vm, exec);
2368     return NumberConstructor::isIntegerImpl(JSValue::decode(value));
2369 }
2370
2371 int32_t JIT_OPERATION operationArrayIndexOfString(ExecState* exec, Butterfly* butterfly, JSString* searchElement, int32_t index)
2372 {
2373     VM& vm = exec->vm();
2374     NativeCallFrameTracer tracer(&vm, exec);
2375     auto scope = DECLARE_THROW_SCOPE(vm);
2376
2377     int32_t length = butterfly->publicLength();
2378     auto data = butterfly->contiguous().data();
2379     for (; index < length; ++index) {
2380         JSValue value = data[index].get();
2381         if (!value || !value.isString())
2382             continue;
2383         auto* string = asString(value);
2384         if (string == searchElement)
2385             return index;
2386         if (string->equal(exec, searchElement))
2387             return index;
2388         RETURN_IF_EXCEPTION(scope, { });
2389     }
2390     return -1;
2391 }
2392
2393 int32_t JIT_OPERATION operationArrayIndexOfValueInt32OrContiguous(ExecState* exec, Butterfly* butterfly, EncodedJSValue encodedValue, int32_t index)
2394 {
2395     VM& vm = exec->vm();
2396     NativeCallFrameTracer tracer(&vm, exec);
2397     auto scope = DECLARE_THROW_SCOPE(vm);
2398
2399     JSValue searchElement = JSValue::decode(encodedValue);
2400
2401     int32_t length = butterfly->publicLength();
2402     auto data = butterfly->contiguous().data();
2403     for (; index < length; ++index) {
2404         JSValue value = data[index].get();
2405         if (!value)
2406             continue;
2407         if (JSValue::strictEqual(exec, searchElement, value))
2408             return index;
2409         RETURN_IF_EXCEPTION(scope, { });
2410     }
2411     return -1;
2412 }
2413
2414 int32_t JIT_OPERATION operationArrayIndexOfValueDouble(ExecState* exec, Butterfly* butterfly, EncodedJSValue encodedValue, int32_t index)
2415 {
2416     VM& vm = exec->vm();
2417     NativeCallFrameTracer tracer(&vm, exec);
2418
2419     JSValue searchElement = JSValue::decode(encodedValue);
2420
2421     if (!searchElement.isNumber())
2422         return -1;
2423     double number = searchElement.asNumber();
2424
2425     int32_t length = butterfly->publicLength();
2426     const double* data = butterfly->contiguousDouble().data();
2427     for (; index < length; ++index) {
2428         // This comparison ignores NaN.
2429         if (data[index] == number)
2430             return index;
2431     }
2432     return -1;
2433 }
2434
2435 void JIT_OPERATION operationLoadVarargs(ExecState* exec, int32_t firstElementDest, EncodedJSValue encodedArguments, uint32_t offset, uint32_t length, uint32_t mandatoryMinimum)
2436 {
2437     VM& vm = exec->vm();
2438     NativeCallFrameTracer tracer(&vm, exec);
2439     JSValue arguments = JSValue::decode(encodedArguments);
2440     
2441     loadVarargs(exec, VirtualRegister(firstElementDest), arguments, offset, length);
2442     
2443     for (uint32_t i = length; i < mandatoryMinimum; ++i)
2444         exec->r(firstElementDest + i) = jsUndefined();
2445 }
2446
2447 double JIT_OPERATION operationFModOnInts(int32_t a, int32_t b)
2448 {
2449     return fmod(a, b);
2450 }
2451
2452 #if USE(JSVALUE32_64)
2453 double JIT_OPERATION operationRandom(JSGlobalObject* globalObject)
2454 {
2455     return globalObject->weakRandomNumber();
2456 }
2457 #endif
2458
2459 JSCell* JIT_OPERATION operationStringFromCharCode(ExecState* exec, int32_t op1)
2460 {
2461     VM* vm = &exec->vm();
2462     NativeCallFrameTracer tracer(vm, exec);
2463     return JSC::stringFromCharCode(exec, op1);
2464 }
2465
2466 EncodedJSValue JIT_OPERATION operationStringFromCharCodeUntyped(ExecState* exec, EncodedJSValue encodedValue)
2467 {
2468     VM* vm = &exec->vm();
2469     NativeCallFrameTracer tracer(vm, exec);
2470     JSValue charValue = JSValue::decode(encodedValue);
2471     int32_t chInt = charValue.toUInt32(exec);
2472     return JSValue::encode(JSC::stringFromCharCode(exec, chInt));
2473 }
2474
2475 int64_t JIT_OPERATION operationConvertBoxedDoubleToInt52(EncodedJSValue encodedValue)
2476 {
2477     JSValue value = JSValue::decode(encodedValue);
2478     if (!value.isDouble())
2479         return JSValue::notInt52;
2480     return tryConvertToInt52(value.asDouble());
2481 }
2482
2483 int64_t JIT_OPERATION operationConvertDoubleToInt52(double value)
2484 {
2485     return tryConvertToInt52(value);
2486 }
2487
2488 char* JIT_OPERATION operationNewRawObject(ExecState* exec, Structure* structure, int32_t length, Butterfly* butterfly)
2489 {
2490     VM& vm = exec->vm();
2491     NativeCallFrameTracer tracer(&vm, exec);
2492
2493     if (!butterfly
2494         && (structure->outOfLineCapacity() || hasIndexedProperties(structure->indexingType()))) {
2495         IndexingHeader header;
2496         header.setVectorLength(length);
2497         header.setPublicLength(0);
2498         
2499         butterfly = Butterfly::create(
2500             vm, nullptr, 0, structure->outOfLineCapacity(),
2501             hasIndexedProperties(structure->indexingType()), header,
2502             length * sizeof(EncodedJSValue));
2503     }
2504
2505     JSObject* result = JSObject::createRawObject(exec, structure, butterfly);
2506     result->butterfly(); // Ensure that the butterfly is in to-space.
2507     return bitwise_cast<char*>(result);
2508 }
2509
2510 JSCell* JIT_OPERATION operationNewObjectWithButterfly(ExecState* exec, Structure* structure, Butterfly* butterfly)
2511 {
2512     VM& vm = exec->vm();
2513     NativeCallFrameTracer tracer(&vm, exec);
2514     
2515     if (!butterfly) {
2516         butterfly = Butterfly::create(
2517             vm, nullptr, 0, structure->outOfLineCapacity(), false, IndexingHeader(), 0);
2518     }
2519     
2520     JSObject* result = JSObject::createRawObject(exec, structure, butterfly);
2521     result->butterfly(); // Ensure that the butterfly is in to-space.
2522     return result;
2523 }
2524
2525 JSCell* JIT_OPERATION operationNewObjectWithButterflyWithIndexingHeaderAndVectorLength(ExecState* exec, Structure* structure, unsigned length, Butterfly* butterfly)
2526 {
2527     VM& vm = exec->vm();
2528     NativeCallFrameTracer tracer(&vm, exec);
2529
2530     IndexingHeader header;
2531     header.setVectorLength(length);
2532     header.setPublicLength(0);
2533     if (butterfly)
2534         *butterfly->indexingHeader() = header;
2535     else {
2536         butterfly = Butterfly::create(
2537             vm, nullptr, 0, structure->outOfLineCapacity(), true, header,
2538             sizeof(EncodedJSValue) * length);
2539     }
2540     
2541     // Paradoxically this may allocate a JSArray. That's totally cool.
2542     JSObject* result = JSObject::createRawObject(exec, structure, butterfly);
2543     result->butterfly(); // Ensure that the butterfly is in to-space.
2544     return result;
2545 }
2546
2547 JSCell* JIT_OPERATION operationNewArrayWithSpreadSlow(ExecState* exec, void* buffer, uint32_t numItems)
2548 {
2549     VM& vm = exec->vm();
2550     NativeCallFrameTracer tracer(&vm, exec);
2551     auto scope = DECLARE_THROW_SCOPE(vm);
2552
2553     EncodedJSValue* values = static_cast<EncodedJSValue*>(buffer);
2554     Checked<unsigned, RecordOverflow> checkedLength = 0;
2555     for (unsigned i = 0; i < numItems; i++) {
2556         JSValue value = JSValue::decode(values[i]);
2557         if (JSFixedArray* array = jsDynamicCast<JSFixedArray*>(vm, value))
2558             checkedLength += array->size();
2559         else
2560             ++checkedLength;
2561     }
2562
2563     if (UNLIKELY(checkedLength.hasOverflowed())) {
2564         throwOutOfMemoryError(exec, scope);
2565         return nullptr;
2566     }
2567
2568     unsigned length = checkedLength.unsafeGet();
2569     JSGlobalObject* globalObject = exec->lexicalGlobalObject();
2570     Structure* structure = globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithContiguous);
2571
2572     JSArray* result = JSArray::tryCreate(vm, structure, length);
2573     if (UNLIKELY(!result)) {
2574         throwOutOfMemoryError(exec, scope);
2575         return nullptr;
2576     }
2577     RETURN_IF_EXCEPTION(scope, nullptr);
2578
2579     unsigned index = 0;
2580     for (unsigned i = 0; i < numItems; i++) {
2581         JSValue value = JSValue::decode(values[i]);
2582         if (JSFixedArray* array = jsDynamicCast<JSFixedArray*>(vm, value)) {
2583             // We are spreading.
2584             for (unsigned i = 0; i < array->size(); i++) {
2585                 result->putDirectIndex(exec, index, array->get(i));
2586                 RETURN_IF_EXCEPTION(scope, nullptr);
2587                 ++index;
2588             }
2589         } else {
2590             // We are not spreading.
2591             result->putDirectIndex(exec, index, value);
2592             RETURN_IF_EXCEPTION(scope, nullptr);
2593             ++index;
2594         }
2595     }
2596
2597     return result;
2598 }
2599
2600 JSCell* operationCreateFixedArray(ExecState* exec, unsigned length)
2601 {
2602     VM& vm = exec->vm();
2603     NativeCallFrameTracer tracer(&vm, exec);
2604     auto scope = DECLARE_THROW_SCOPE(vm);
2605
2606     if (JSFixedArray* result = JSFixedArray::tryCreate(vm, vm.fixedArrayStructure.get(), length))
2607         return result;
2608
2609     throwOutOfMemoryError(exec, scope);
2610     return nullptr;
2611 }
2612
2613 JSCell* JIT_OPERATION operationSpreadGeneric(ExecState* exec, JSCell* iterable)
2614 {
2615     VM& vm = exec->vm();
2616     NativeCallFrameTracer tracer(&vm, exec);
2617
2618     auto throwScope = DECLARE_THROW_SCOPE(vm);
2619
2620     if (isJSArray(iterable)) {
2621         JSArray* array = jsCast<JSArray*>(iterable);
2622         if (array->isIteratorProtocolFastAndNonObservable()) {
2623             throwScope.release();
2624             return JSFixedArray::createFromArray(exec, vm, array);
2625         }
2626     }
2627
2628     // FIXME: we can probably make this path faster by having our caller JS code call directly into
2629     // the iteration protocol builtin: https://bugs.webkit.org/show_bug.cgi?id=164520
2630
2631     JSGlobalObject* globalObject = exec->lexicalGlobalObject();
2632     JSArray* array;
2633     {
2634         JSFunction* iterationFunction = globalObject->iteratorProtocolFunction();
2635         CallData callData;
2636         CallType callType = JSC::getCallData(vm, iterationFunction, callData);
2637         ASSERT(callType != CallType::None);
2638
2639         MarkedArgumentBuffer arguments;
2640         arguments.append(iterable);
2641         ASSERT(!arguments.hasOverflowed());
2642         JSValue arrayResult = call(exec, iterationFunction, callType, callData, jsNull(), arguments);
2643         RETURN_IF_EXCEPTION(throwScope, nullptr);
2644         array = jsCast<JSArray*>(arrayResult);
2645     }
2646
2647     throwScope.release();
2648     return JSFixedArray::createFromArray(exec, vm, array);
2649 }
2650
2651 JSCell* JIT_OPERATION operationSpreadFastArray(ExecState* exec, JSCell* cell)
2652 {
2653     VM& vm = exec->vm();
2654     NativeCallFrameTracer tracer(&vm, exec);
2655
2656     ASSERT(isJSArray(cell));
2657     JSArray* array = jsCast<JSArray*>(cell);
2658     ASSERT(array->isIteratorProtocolFastAndNonObservable());
2659
2660     return JSFixedArray::createFromArray(exec, vm, array);
2661 }
2662
2663 void JIT_OPERATION operationProcessTypeProfilerLogDFG(ExecState* exec) 
2664 {
2665     VM& vm = exec->vm();
2666     NativeCallFrameTracer tracer(&vm, exec);
2667
2668     vm.typeProfilerLog()->processLogEntries("Log Full, called from inside DFG."_s);
2669 }
2670
2671 EncodedJSValue JIT_OPERATION operationResolveScopeForHoistingFuncDeclInEval(ExecState* exec, JSScope* scope, UniquedStringImpl* impl)
2672 {
2673     VM& vm = exec->vm();
2674     NativeCallFrameTracer tracer(&vm, exec);
2675         
2676     JSValue resolvedScope = JSScope::resolveScopeForHoistingFuncDeclInEval(exec, scope, Identifier::fromUid(exec, impl));
2677     return JSValue::encode(resolvedScope);
2678 }
2679     
2680 JSCell* JIT_OPERATION operationResolveScope(ExecState* exec, JSScope* scope, UniquedStringImpl* impl)
2681 {
2682     VM& vm = exec->vm();
2683     NativeCallFrameTracer tracer(&vm, exec);
2684
2685     JSObject* resolvedScope = JSScope::resolve(exec, scope, Identifier::fromUid(exec, impl));
2686     return resolvedScope;
2687 }
2688
2689 EncodedJSValue JIT_OPERATION operationGetDynamicVar(ExecState* exec, JSObject* scope, UniquedStringImpl* impl, unsigned getPutInfoBits)
2690 {
2691     VM& vm = exec->vm();
2692     NativeCallFrameTracer tracer(&vm, exec);
2693     auto throwScope = DECLARE_THROW_SCOPE(vm);
2694
2695     Identifier ident = Identifier::fromUid(exec, impl);
2696     throwScope.release();
2697     return JSValue::encode(scope->getPropertySlot(exec, ident, [&] (bool found, PropertySlot& slot) -> JSValue {
2698         if (!found) {
2699             GetPutInfo getPutInfo(getPutInfoBits);
2700             if (getPutInfo.resolveMode() == ThrowIfNotFound)
2701                 throwException(exec, throwScope, createUndefinedVariableError(exec, ident));
2702             return jsUndefined();
2703         }
2704
2705         if (scope->isGlobalLexicalEnvironment()) {
2706             // When we can't statically prove we need a TDZ check, we must perform the check on the slow path.
2707             JSValue result = slot.getValue(exec, ident);
2708             if (result == jsTDZValue()) {
2709                 throwException(exec, throwScope, createTDZError(exec));
2710                 return jsUndefined();
2711             }
2712             return result;
2713         }
2714
2715         return slot.getValue(exec, ident);
2716     }));
2717 }
2718
2719 void JIT_OPERATION operationPutDynamicVar(ExecState* exec, JSObject* scope, EncodedJSValue value, UniquedStringImpl* impl, unsigned getPutInfoBits)
2720 {
2721     VM& vm = exec->vm();
2722     NativeCallFrameTracer tracer(&vm, exec);
2723     auto throwScope = DECLARE_THROW_SCOPE(vm);
2724
2725     const Identifier& ident = Identifier::fromUid(exec, impl);
2726     GetPutInfo getPutInfo(getPutInfoBits);
2727     bool hasProperty = scope->hasProperty(exec, ident);
2728     RETURN_IF_EXCEPTION(throwScope, void());
2729     if (hasProperty
2730         && scope->isGlobalLexicalEnvironment()
2731         && !isInitialization(getPutInfo.initializationMode())) {
2732         // When we can't statically prove we need a TDZ check, we must perform the check on the slow path.
2733         PropertySlot slot(scope, PropertySlot::InternalMethodType::Get);
2734         JSGlobalLexicalEnvironment::getOwnPropertySlot(scope, exec, ident, slot);
2735         if (slot.getValue(exec, ident) == jsTDZValue()) {
2736             throwException(exec, throwScope, createTDZError(exec));
2737             return;
2738         }
2739     }
2740
2741     if (getPutInfo.resolveMode() == ThrowIfNotFound && !hasProperty) {
2742         throwException(exec, throwScope, createUndefinedVariableError(exec, ident));
2743         return;
2744     }
2745
2746     CodeOrigin origin = exec->codeOrigin();
2747     bool strictMode;
2748     if (origin.inlineCallFrame)
2749         strictMode = origin.inlineCallFrame->baselineCodeBlock->isStrictMode();
2750     else
2751         strictMode = exec->codeBlock()->isStrictMode();
2752     PutPropertySlot slot(scope, strictMode, PutPropertySlot::UnknownContext, isInitialization(getPutInfo.initializationMode()));
2753     throwScope.release();
2754     scope->methodTable(vm)->put(scope, exec, ident, JSValue::decode(value), slot);
2755 }
2756
2757 int32_t JIT_OPERATION operationMapHash(ExecState* exec, EncodedJSValue input)
2758 {
2759     VM& vm = exec->vm();
2760     NativeCallFrameTracer tracer(&vm, exec);
2761
2762     return jsMapHash(exec, vm, JSValue::decode(input));
2763 }
2764
2765 JSCell* JIT_OPERATION operationJSMapFindBucket(ExecState* exec, JSCell* map, EncodedJSValue key, int32_t hash)
2766 {
2767     VM& vm = exec->vm();
2768     NativeCallFrameTracer tracer(&vm, exec);
2769     JSMap::BucketType** bucket = jsCast<JSMap*>(map)->findBucket(exec, JSValue::decode(key), hash);
2770     if (!bucket)
2771         return vm.sentinelMapBucket.get();
2772     return *bucket;
2773 }
2774
2775 JSCell* JIT_OPERATION operationJSSetFindBucket(ExecState* exec, JSCell* map, EncodedJSValue key, int32_t hash)
2776 {
2777     VM& vm = exec->vm();
2778     NativeCallFrameTracer tracer(&vm, exec);
2779     JSSet::BucketType** bucket = jsCast<JSSet*>(map)->findBucket(exec, JSValue::decode(key), hash);
2780     if (!bucket)
2781         return vm.sentinelSetBucket.get();
2782     return *bucket;
2783 }
2784
2785 JSCell* JIT_OPERATION operationSetAdd(ExecState* exec, JSCell* set, EncodedJSValue key, int32_t hash)
2786 {
2787     VM& vm = exec->vm();
2788     NativeCallFrameTracer tracer(&vm, exec);
2789     auto* bucket = jsCast<JSSet*>(set)->addNormalized(exec, JSValue::decode(key), JSValue(), hash);
2790     if (!bucket)
2791         return vm.sentinelSetBucket.get();
2792     return bucket;
2793 }
2794
2795 JSCell* JIT_OPERATION operationMapSet(ExecState* exec, JSCell* map, EncodedJSValue key, EncodedJSValue value, int32_t hash)
2796 {
2797     VM& vm = exec->vm();
2798     NativeCallFrameTracer tracer(&vm, exec);
2799     auto* bucket = jsCast<JSMap*>(map)->addNormalized(exec, JSValue::decode(key), JSValue::decode(value), hash);
2800     if (!bucket)
2801         return vm.sentinelMapBucket.get();
2802     return bucket;
2803 }
2804
2805 void JIT_OPERATION operationWeakSetAdd(ExecState* exec, JSCell* set, JSCell* key, int32_t hash)
2806 {
2807     VM& vm = exec->vm();
2808     NativeCallFrameTracer tracer(&vm, exec);
2809     jsCast<JSWeakSet*>(set)->add(vm, asObject(key), JSValue(), hash);
2810 }
2811
2812 void JIT_OPERATION operationWeakMapSet(ExecState* exec, JSCell* map, JSCell* key, EncodedJSValue value, int32_t hash)
2813 {
2814     VM& vm = exec->vm();
2815     NativeCallFrameTracer tracer(&vm, exec);
2816     jsCast<JSWeakMap*>(map)->add(vm, asObject(key), JSValue::decode(value), hash);
2817 }
2818
2819 EncodedJSValue JIT_OPERATION operationGetPrototypeOfObject(ExecState* exec, JSObject* thisObject)
2820 {
2821     VM& vm = exec->vm();
2822     NativeCallFrameTracer tracer(&vm, exec);
2823     return JSValue::encode(thisObject->getPrototype(vm, exec));
2824 }
2825
2826 EncodedJSValue JIT_OPERATION operationGetPrototypeOf(ExecState* exec, EncodedJSValue encodedValue)
2827 {
2828     VM& vm = exec->vm();
2829     NativeCallFrameTracer tracer(&vm, exec);
2830     auto scope = DECLARE_THROW_SCOPE(vm);
2831
2832     JSValue thisValue = JSValue::decode(encodedValue).toThis(exec, StrictMode);
2833     if (thisValue.isUndefinedOrNull())
2834         return throwVMError(exec, scope, createNotAnObjectError(exec, thisValue));
2835
2836     JSObject* thisObject = jsDynamicCast<JSObject*>(vm, thisValue);
2837     if (!thisObject) {
2838         JSObject* prototype = thisValue.synthesizePrototype(exec);
2839         EXCEPTION_ASSERT(!!scope.exception() == !prototype);
2840         if (UNLIKELY(!prototype))
2841             return JSValue::encode(JSValue());
2842         return JSValue::encode(prototype);
2843     }
2844
2845     scope.release();
2846     return JSValue::encode(thisObject->getPrototype(vm, exec));
2847 }
2848
2849 void JIT_OPERATION operationThrowDFG(ExecState* exec, EncodedJSValue valueToThrow)
2850 {
2851     VM& vm = exec->vm();
2852     NativeCallFrameTracer tracer(&vm, exec);
2853     auto scope = DECLARE_THROW_SCOPE(vm);
2854     scope.throwException(exec, JSValue::decode(valueToThrow));
2855 }
2856
2857 void JIT_OPERATION operationThrowStaticError(ExecState* exec, JSString* message, uint32_t errorType)
2858 {
2859     VM& vm = exec->vm();
2860     NativeCallFrameTracer tracer(&vm, exec);
2861     auto scope = DECLARE_THROW_SCOPE(vm);
2862     String errorMessage = message->value(exec);
2863     scope.throwException(exec, createError(exec, static_cast<ErrorType>(errorType), errorMessage));
2864 }
2865
2866 extern "C" void JIT_OPERATION triggerReoptimizationNow(CodeBlock* codeBlock, CodeBlock* optimizedCodeBlock, OSRExitBase* exit)
2867 {
2868     // It's sort of preferable that we don't GC while in here. Anyways, doing so wouldn't
2869     // really be profitable.
2870     DeferGCForAWhile deferGC(codeBlock->vm()->heap);
2871     
2872     sanitizeStackForVM(codeBlock->vm());
2873
2874     if (Options::verboseOSR())
2875         dataLog(*codeBlock, ": Entered reoptimize\n");
2876     // We must be called with the baseline code block.
2877     ASSERT(JITCode::isBaselineCode(codeBlock->jitType()));
2878
2879     // If I am my own replacement, then reoptimization has already been triggered.
2880     // This can happen in recursive functions.
2881     //
2882     // Note that even if optimizedCodeBlock is an FTLForOSREntry style CodeBlock, this condition is a
2883     // sure bet that we don't have anything else left to do.
2884     CodeBlock* replacement = codeBlock->replacement();
2885     if (!replacement || replacement == codeBlock) {
2886         if (Options::verboseOSR())
2887             dataLog(*codeBlock, ": Not reoptimizing because we've already been jettisoned.\n");
2888         return;
2889     }
2890     
2891     // Otherwise, the replacement must be optimized code. Use this as an opportunity
2892     // to check our logic.
2893     ASSERT(codeBlock->hasOptimizedReplacement());
2894     ASSERT(JITCode::isOptimizingJIT(optimizedCodeBlock->jitType()));
2895     
2896     bool didTryToEnterIntoInlinedLoops = false;
2897     for (InlineCallFrame* inlineCallFrame = exit->m_codeOrigin.inlineCallFrame; inlineCallFrame; inlineCallFrame = inlineCallFrame->directCaller.inlineCallFrame) {
2898         if (inlineCallFrame->baselineCodeBlock->ownerScriptExecutable()->didTryToEnterInLoop()) {
2899             didTryToEnterIntoInlinedLoops = true;
2900             break;
2901         }
2902     }
2903
2904     // In order to trigger reoptimization, one of two things must have happened:
2905     // 1) We exited more than some number of times.
2906     // 2) We exited and got stuck in a loop, and now we're exiting again.
2907     bool didExitABunch = optimizedCodeBlock->shouldReoptimizeNow();
2908     bool didGetStuckInLoop =
2909         (codeBlock->checkIfOptimizationThresholdReached() || didTryToEnterIntoInlinedLoops)
2910         && optimizedCodeBlock->shouldReoptimizeFromLoopNow();
2911     
2912     if (!didExitABunch && !didGetStuckInLoop) {
2913         if (Options::verboseOSR())
2914             dataLog(*codeBlock, ": Not reoptimizing ", *optimizedCodeBlock, " because it either didn't exit enough or didn't loop enough after exit.\n");
2915         codeBlock->optimizeAfterLongWarmUp();
2916         return;
2917     }
2918     
2919     optimizedCodeBlock->jettison(Profiler::JettisonDueToOSRExit, CountReoptimization);
2920 }
2921
2922 #if ENABLE(FTL_JIT)
2923 static bool shouldTriggerFTLCompile(CodeBlock* codeBlock, JITCode* jitCode)
2924 {
2925     if (codeBlock->baselineVersion()->m_didFailFTLCompilation) {
2926         CODEBLOCK_LOG_EVENT(codeBlock, "abortFTLCompile", ());
2927         if (Options::verboseOSR())
2928             dataLog("Deferring FTL-optimization of ", *codeBlock, " indefinitely because there was an FTL failure.\n");
2929         jitCode->dontOptimizeAnytimeSoon(codeBlock);
2930         return false;
2931     }
2932
2933     if (!codeBlock->hasOptimizedReplacement()
2934         && !jitCode->checkIfOptimizationThresholdReached(codeBlock)) {
2935         CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("counter = ", jitCode->tierUpCounter));
2936         if (Options::verboseOSR())
2937             dataLog("Choosing not to FTL-optimize ", *codeBlock, " yet.\n");
2938         return false;
2939     }
2940     return true;
2941 }
2942
2943 static void triggerFTLReplacementCompile(VM* vm, CodeBlock* codeBlock, JITCode* jitCode)
2944 {
2945     if (codeBlock->codeType() == GlobalCode) {
2946         // Global code runs once, so we don't want to do anything. We don't want to defer indefinitely,
2947         // since this may have been spuriously called from tier-up initiated in a loop, and that loop may
2948         // later want to run faster code. Deferring for warm-up seems safest.
2949         jitCode->optimizeAfterWarmUp(codeBlock);
2950         return;
2951     }
2952     
2953     Worklist::State worklistState;
2954     if (Worklist* worklist = existingGlobalFTLWorklistOrNull()) {
2955         worklistState = worklist->completeAllReadyPlansForVM(
2956             *vm, CompilationKey(codeBlock->baselineVersion(), FTLMode));
2957     } else
2958         worklistState = Worklist::NotKnown;
2959     
2960     if (worklistState == Worklist::Compiling) {
2961         CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("still compiling"));
2962         jitCode->setOptimizationThresholdBasedOnCompilationResult(
2963             codeBlock, CompilationDeferred);
2964         return;
2965     }
2966     
2967     if (codeBlock->hasOptimizedReplacement()) {
2968         CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("has replacement"));
2969         // That's great, we've compiled the code - next time we call this function,
2970         // we'll enter that replacement.
2971         jitCode->optimizeSoon(codeBlock);
2972         return;
2973     }
2974     
2975     if (worklistState == Worklist::Compiled) {
2976         CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("compiled and failed"));
2977         // This means that we finished compiling, but failed somehow; in that case the
2978         // thresholds will be set appropriately.
2979         if (Options::verboseOSR())
2980             dataLog("Code block ", *codeBlock, " was compiled but it doesn't have an optimized replacement.\n");
2981         return;
2982     }
2983
2984     CODEBLOCK_LOG_EVENT(codeBlock, "triggerFTLReplacement", ());
2985     // We need to compile the code.
2986     compile(
2987         *vm, codeBlock->newReplacement(), codeBlock, FTLMode, UINT_MAX,
2988         Operands<JSValue>(), ToFTLDeferredCompilationCallback::create());
2989
2990     // If we reached here, the counter has not be reset. Do that now.
2991     jitCode->setOptimizationThresholdBasedOnCompilationResult(
2992         codeBlock, CompilationDeferred);
2993 }
2994
2995 void JIT_OPERATION triggerTierUpNow(ExecState* exec)
2996 {
2997     VM* vm = &exec->vm();
2998     NativeCallFrameTracer tracer(vm, exec);
2999     DeferGCForAWhile deferGC(vm->heap);
3000     CodeBlock* codeBlock = exec->codeBlock();
3001     
3002     sanitizeStackForVM(vm);
3003
3004     if (codeBlock->jitType() != JITCode::DFGJIT) {
3005         dataLog("Unexpected code block in DFG->FTL tier-up: ", *codeBlock, "\n");
3006         RELEASE_ASSERT_NOT_REACHED();
3007     }
3008     
3009     JITCode* jitCode = codeBlock->jitCode()->dfg();
3010     
3011     if (Options::verboseOSR()) {
3012         dataLog(
3013             *codeBlock, ": Entered triggerTierUpNow with executeCounter = ",
3014             jitCode->tierUpCounter, "\n");
3015     }
3016
3017     if (shouldTriggerFTLCompile(codeBlock, jitCode))
3018         triggerFTLReplacementCompile(vm, codeBlock, jitCode);
3019
3020     if (codeBlock->hasOptimizedReplacement()) {
3021         if (jitCode->tierUpEntryTriggers.isEmpty()) {
3022             CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("replacement in place, delaying indefinitely"));
3023             // There is nothing more we can do, the only way this will be entered
3024             // is through the function entry point.
3025             jitCode->dontOptimizeAnytimeSoon(codeBlock);
3026             return;
3027         }
3028         if (jitCode->osrEntryBlock() && jitCode->tierUpEntryTriggers.size() == 1) {
3029             CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("trigger in place, delaying indefinitely"));
3030             // There is only one outer loop and its trigger must have been set
3031             // when the plan completed.
3032             // Exiting the inner loop is useless, we can ignore the counter and leave
3033             // the trigger do its job.
3034             jitCode->dontOptimizeAnytimeSoon(codeBlock);
3035             return;
3036         }
3037     }
3038 }
3039
3040 static char* tierUpCommon(ExecState* exec, unsigned originBytecodeIndex, bool canOSREnterHere)
3041 {
3042     VM* vm = &exec->vm();
3043     CodeBlock* codeBlock = exec->codeBlock();
3044
3045     // Resolve any pending plan for OSR Enter on this function.
3046     Worklist::State worklistState;
3047     if (Worklist* worklist = existingGlobalFTLWorklistOrNull()) {
3048         worklistState = worklist->completeAllReadyPlansForVM(
3049             *vm, CompilationKey(codeBlock->baselineVersion(), FTLForOSREntryMode));
3050     } else
3051         worklistState = Worklist::NotKnown;
3052
3053     JITCode* jitCode = codeBlock->jitCode()->dfg();
3054     
3055     bool triggeredSlowPathToStartCompilation = false;
3056     auto tierUpEntryTriggers = jitCode->tierUpEntryTriggers.find(originBytecodeIndex);
3057     if (tierUpEntryTriggers != jitCode->tierUpEntryTriggers.end()) {
3058         switch (tierUpEntryTriggers->value) {
3059         case JITCode::TriggerReason::DontTrigger:
3060             // The trigger isn't set, we entered because the counter reached its
3061             // threshold.
3062             break;
3063
3064         case JITCode::TriggerReason::CompilationDone:
3065             // The trigger was set because compilation completed. Don't unset it
3066             // so that further DFG executions OSR enter as well.
3067             break;
3068
3069         case JITCode::TriggerReason::StartCompilation:
3070             // We were asked to enter as soon as possible and start compiling an
3071             // entry for the current bytecode location. Unset this trigger so we
3072             // don't continually enter.
3073             tierUpEntryTriggers->value = JITCode::TriggerReason::DontTrigger;
3074             triggeredSlowPathToStartCompilation = true;
3075             break;
3076         }
3077     }
3078
3079     if (worklistState == Worklist::Compiling) {
3080         CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("still compiling"));
3081         jitCode->setOptimizationThresholdBasedOnCompilationResult(codeBlock, CompilationDeferred);
3082         return nullptr;
3083     }
3084
3085     // If we can OSR Enter, do it right away.
3086     if (canOSREnterHere) {
3087         auto iter = jitCode->bytecodeIndexToStreamIndex.find(originBytecodeIndex);
3088         if (iter != jitCode->bytecodeIndexToStreamIndex.end()) {
3089             unsigned streamIndex = iter->value;
3090             if (CodeBlock* entryBlock = jitCode->osrEntryBlock()) {
3091                 if (Options::verboseOSR())
3092                     dataLog("OSR entry: From ", RawPointer(jitCode), " got entry block ", RawPointer(entryBlock), "\n");
3093                 if (void* address = FTL::prepareOSREntry(exec, codeBlock, entryBlock, originBytecodeIndex, streamIndex)) {
3094                     CODEBLOCK_LOG_EVENT(entryBlock, "osrEntry", ("at bc#", originBytecodeIndex));
3095                     return retagCodePtr<char*>(address, JSEntryPtrTag, bitwise_cast<PtrTag>(exec));
3096                 }
3097             }
3098         }
3099     }
3100
3101     if (worklistState == Worklist::Compiled) {
3102         CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("compiled and failed"));
3103         // This means that compilation failed and we already set the thresholds.
3104         if (Options::verboseOSR())
3105             dataLog("Code block ", *codeBlock, " was compiled but it doesn't have an optimized replacement.\n");
3106         return nullptr;
3107     }
3108
3109     // - If we don't have an FTL code block, then try to compile one.
3110     // - If we do have an FTL code block, then try to enter for a while.
3111     // - If we couldn't enter for a while, then trigger OSR entry.
3112
3113     if (!shouldTriggerFTLCompile(codeBlock, jitCode) && !triggeredSlowPathToStartCompilation)
3114         return nullptr;
3115
3116     if (!jitCode->neverExecutedEntry && !triggeredSlowPathToStartCompilation) {
3117         triggerFTLReplacementCompile(vm, codeBlock, jitCode);
3118
3119         if (!codeBlock->hasOptimizedReplacement())
3120             return nullptr;
3121
3122         if (jitCode->osrEntryRetry < Options::ftlOSREntryRetryThreshold()) {
3123             CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("avoiding OSR entry compile"));
3124             jitCode->osrEntryRetry++;
3125             return nullptr;
3126         }
3127     } else
3128         CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("avoiding replacement compile"));
3129
3130     if (CodeBlock* entryBlock = jitCode->osrEntryBlock()) {
3131         if (jitCode->osrEntryRetry < Options::ftlOSREntryRetryThreshold()) {
3132             CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("OSR entry failed, OSR entry threshold not met"));
3133             jitCode->osrEntryRetry++;
3134             jitCode->setOptimizationThresholdBasedOnCompilationResult(
3135                 codeBlock, CompilationDeferred);
3136             return nullptr;
3137         }
3138
3139         FTL::ForOSREntryJITCode* entryCode = entryBlock->jitCode()->ftlForOSREntry();
3140         entryCode->countEntryFailure();
3141         if (entryCode->entryFailureCount() <
3142             Options::ftlOSREntryFailureCountForReoptimization()) {
3143             CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("OSR entry failed"));
3144             jitCode->setOptimizationThresholdBasedOnCompilationResult(
3145                 codeBlock, CompilationDeferred);
3146             return nullptr;
3147         }
3148
3149         // OSR entry failed. Oh no! This implies that we need to retry. We retry
3150         // without exponential backoff and we only do this for the entry code block.
3151         CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("OSR entry failed too many times"));
3152         unsigned osrEntryBytecode = entryBlock->jitCode()->ftlForOSREntry()->bytecodeIndex();
3153         jitCode->clearOSREntryBlock();
3154         jitCode->osrEntryRetry = 0;
3155         jitCode->tierUpEntryTriggers.set(osrEntryBytecode, JITCode::TriggerReason::DontTrigger);
3156         jitCode->setOptimizationThresholdBasedOnCompilationResult(
3157             codeBlock, CompilationDeferred);
3158         return nullptr;
3159     }
3160
3161     // It's time to try to compile code for OSR entry.
3162
3163     if (!triggeredSlowPathToStartCompilation) {
3164
3165         // An inner loop didn't specifically ask for us to kick off a compilation. This means the counter
3166         // crossed its threshold. We either fall through and kick off a compile for originBytecodeIndex,
3167         // or we flag an outer loop to immediately try to compile itself. If there are outer loops,
3168         // we first try to make them compile themselves. But we will eventually fall back to compiling
3169         // a progressively inner loop if it takes too long for control to reach an outer loop.
3170
3171         auto tryTriggerOuterLoopToCompile = [&] {
3172             auto tierUpHierarchyEntry = jitCode->tierUpInLoopHierarchy.find(originBytecodeIndex);
3173             if (tierUpHierarchyEntry == jitCode->tierUpInLoopHierarchy.end())
3174                 return false;
3175
3176             // This vector is ordered from innermost to outermost loop. Every bytecode entry in this vector is
3177             // allowed to do OSR entry. We start with the outermost loop and make our way inwards (hence why we
3178             // iterate the vector in reverse). Our policy is that we will trigger an outer loop to compile
3179             // immediately when program control reaches it. If program control is taking too long to reach that
3180             // outer loop, we progressively move inwards, meaning, we'll eventually trigger some loop that is
3181             // executing to compile. We start with trying to compile outer loops since we believe outer loop
3182             // compilations reveal the best opportunities for optimizing code.
3183             for (auto iter = tierUpHierarchyEntry->value.rbegin(), end = tierUpHierarchyEntry->value.rend(); iter != end; ++iter) {
3184                 unsigned osrEntryCandidate = *iter;
3185
3186                 if (jitCode->tierUpEntryTriggers.get(osrEntryCandidate) == JITCode::TriggerReason::StartCompilation) {
3187                     // This means that we already asked this loop to compile. If we've reached here, it
3188                     // means program control has not yet reached that loop. So it's taking too long to compile.
3189                     // So we move on to asking the inner loop of this loop to compile itself.
3190                     continue;
3191                 }
3192
3193                 // This is where we ask the outer to loop to immediately compile itself if program
3194                 // control reaches it.
3195                 if (Options::verboseOSR())
3196                     dataLog("Inner-loop bc#", originBytecodeIndex, " in ", *codeBlock, " setting parent loop bc#", osrEntryCandidate, "'s trigger and backing off.\n");
3197                 jitCode->tierUpEntryTriggers.set(osrEntryCandidate, JITCode::TriggerReason::StartCompilation);
3198                 return true;
3199             }
3200
3201             return false;
3202         };
3203
3204         if (tryTriggerOuterLoopToCompile()) {
3205             jitCode->setOptimizationThresholdBasedOnCompilationResult(codeBlock, CompilationDeferred);
3206             return nullptr;
3207         }
3208     }
3209
3210     if (!canOSREnterHere) {
3211         jitCode->setOptimizationThresholdBasedOnCompilationResult(codeBlock, CompilationDeferred);
3212         return nullptr;
3213     }
3214
3215     // We aren't compiling and haven't compiled anything for OSR entry. So, try to compile
3216     // something.
3217
3218     auto triggerIterator = jitCode->tierUpEntryTriggers.find(originBytecodeIndex);
3219     if (triggerIterator == jitCode->tierUpEntryTriggers.end()) {
3220         jitCode->setOptimizationThresholdBasedOnCompilationResult(codeBlock, CompilationDeferred);
3221         return nullptr;
3222     }
3223
3224     JITCode::TriggerReason* triggerAddress = &(triggerIterator->value);
3225
3226     Operands<JSValue> mustHandleValues;
3227     unsigned streamIndex = jitCode->bytecodeIndexToStreamIndex.get(originBytecodeIndex);
3228     jitCode->reconstruct(
3229         exec, codeBlock, CodeOrigin(originBytecodeIndex), streamIndex, mustHandleValues);
3230     CodeBlock* replacementCodeBlock = codeBlock->newReplacement();
3231
3232     CODEBLOCK_LOG_EVENT(codeBlock, "triggerFTLOSR", ());
3233     CompilationResult forEntryResult = compile(
3234         *vm, replacementCodeBlock, codeBlock, FTLForOSREntryMode, originBytecodeIndex,
3235         mustHandleValues, ToFTLForOSREntryDeferredCompilationCallback::create(triggerAddress));
3236
3237     if (jitCode->neverExecutedEntry)
3238         triggerFTLReplacementCompile(vm, codeBlock, jitCode);
3239
3240     if (forEntryResult != CompilationSuccessful) {
3241         CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("OSR ecompilation not successful"));
3242         jitCode->setOptimizationThresholdBasedOnCompilationResult(
3243             codeBlock, CompilationDeferred);
3244         return nullptr;
3245     }
3246     
3247     CODEBLOCK_LOG_EVENT(jitCode->osrEntryBlock(), "osrEntry", ("at bc#", originBytecodeIndex));
3248     // It's possible that the for-entry compile already succeeded. In that case OSR
3249     // entry will succeed unless we ran out of stack. It's not clear what we should do.
3250     // We signal to try again after a while if that happens.
3251     if (Options::verboseOSR())
3252         dataLog("Immediate OSR entry: From ", RawPointer(jitCode), " got entry block ", RawPointer(jitCode->osrEntryBlock()), "\n");
3253
3254     void* address = FTL::prepareOSREntry(
3255         exec, codeBlock, jitCode->osrEntryBlock(), originBytecodeIndex, streamIndex);
3256     if (!address)
3257         return nullptr;
3258     return retagCodePtr<char*>(address, JSEntryPtrTag, bitwise_cast<PtrTag>(exec));
3259 }
3260
3261 void JIT_OPERATION triggerTierUpNowInLoop(ExecState* exec, unsigned bytecodeIndex)
3262 {
3263     VM* vm = &exec->vm();
3264     NativeCallFrameTracer tracer(vm, exec);
3265     DeferGCForAWhile deferGC(vm->heap);
3266     CodeBlock* codeBlock = exec->codeBlock();
3267
3268     sanitizeStackForVM(vm);
3269
3270     if (codeBlock->jitType() != JITCode::DFGJIT) {
3271         dataLog("Unexpected code block in DFG->FTL trigger tier up now in loop: ", *codeBlock, "\n");
3272         RELEASE_ASSERT_NOT_REACHED();
3273     }
3274
3275     JITCode* jitCode = codeBlock->jitCode()->dfg();
3276
3277     if (Options::verboseOSR()) {
3278         dataLog(
3279             *codeBlock, ": Entered triggerTierUpNowInLoop with executeCounter = ",
3280             jitCode->tierUpCounter, "\n");
3281     }
3282
3283     if (jitCode->tierUpInLoopHierarchy.contains(bytecodeIndex))
3284         tierUpCommon(exec, bytecodeIndex, false);
3285     else if (shouldTriggerFTLCompile(codeBlock, jitCode))
3286         triggerFTLReplacementCompile(vm, codeBlock, jitCode);
3287
3288     // Since we cannot OSR Enter here, the default "optimizeSoon()" is not useful.
3289     if (codeBlock->hasOptimizedReplacement()) {
3290         CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("OSR in loop failed, deferring"));
3291         jitCode->setOptimizationThresholdBasedOnCompilationResult(codeBlock, CompilationDeferred);
3292     }
3293 }
3294
3295 char* JIT_OPERATION triggerOSREntryNow(ExecState* exec, unsigned bytecodeIndex)
3296 {
3297     VM* vm = &exec->vm();
3298     NativeCallFrameTracer tracer(vm, exec);
3299     DeferGCForAWhile deferGC(vm->heap);
3300     CodeBlock* codeBlock = exec->codeBlock();
3301
3302     sanitizeStackForVM(vm);
3303
3304     if (codeBlock->jitType() != JITCode::DFGJIT) {
3305         dataLog("Unexpected code block in DFG->FTL tier-up: ", *codeBlock, "\n");
3306         RELEASE_ASSERT_NOT_REACHED();
3307     }
3308
3309     JITCode* jitCode = codeBlock->jitCode()->dfg();
3310     jitCode->tierUpEntrySeen.add(bytecodeIndex);
3311
3312     if (Options::verboseOSR()) {
3313         dataLog(
3314             *codeBlock, ": Entered triggerOSREntryNow with executeCounter = ",
3315             jitCode->tierUpCounter, "\n");
3316     }
3317
3318     return tierUpCommon(exec, bytecodeIndex, true);
3319 }
3320
3321 #endif // ENABLE(FTL_JIT)
3322
3323 } // extern "C"
3324 } } // namespace JSC::DFG
3325
3326 #endif // ENABLE(DFG_JIT)
3327
3328 #endif // ENABLE(JIT)