constructArray() should always allocate the requested length.
[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 JSCell* JIT_OPERATION operationStringSubstr(ExecState* exec, JSCell* cell, int32_t from, int32_t span)
2017 {
2018     VM& vm = exec->vm();
2019     NativeCallFrameTracer tracer(&vm, exec);
2020     auto scope = DECLARE_THROW_SCOPE(vm);
2021
2022     auto string = jsCast<JSString*>(cell)->value(exec);
2023     RETURN_IF_EXCEPTION(scope, nullptr);
2024     return jsSubstring(exec, string, from, span);
2025 }
2026
2027 JSString* JIT_OPERATION operationToLowerCase(ExecState* exec, JSString* string, uint32_t failingIndex)
2028 {
2029     VM& vm = exec->vm();
2030     NativeCallFrameTracer tracer(&vm, exec);
2031
2032     auto scope = DECLARE_THROW_SCOPE(vm);
2033
2034     const String& inputString = string->value(exec);
2035     RETURN_IF_EXCEPTION(scope, nullptr);
2036     if (!inputString.length())
2037         return vm.smallStrings.emptyString();
2038
2039     String lowercasedString = inputString.is8Bit() ? inputString.convertToLowercaseWithoutLocaleStartingAtFailingIndex8Bit(failingIndex) : inputString.convertToLowercaseWithoutLocale();
2040     if (lowercasedString.impl() == inputString.impl())
2041         return string;
2042     scope.release();
2043     return jsString(exec, lowercasedString);
2044 }
2045
2046 char* JIT_OPERATION operationInt32ToString(ExecState* exec, int32_t value, int32_t radix)
2047 {
2048     VM& vm = exec->vm();
2049     NativeCallFrameTracer tracer(&vm, exec);
2050
2051     auto scope = DECLARE_THROW_SCOPE(vm);
2052
2053     if (radix < 2 || radix > 36) {
2054         throwVMError(exec, scope, createRangeError(exec, "toString() radix argument must be between 2 and 36"_s));
2055         return nullptr;
2056     }
2057
2058     return reinterpret_cast<char*>(int32ToString(vm, value, radix));
2059 }
2060
2061 char* JIT_OPERATION operationInt52ToString(ExecState* exec, int64_t value, int32_t radix)
2062 {
2063     VM& vm = exec->vm();
2064     NativeCallFrameTracer tracer(&vm, exec);
2065
2066     auto scope = DECLARE_THROW_SCOPE(vm);
2067
2068     if (radix < 2 || radix > 36) {
2069         throwVMError(exec, scope, createRangeError(exec, "toString() radix argument must be between 2 and 36"_s));
2070         return nullptr;
2071     }
2072
2073     return reinterpret_cast<char*>(int52ToString(vm, value, radix));
2074 }
2075
2076 char* JIT_OPERATION operationDoubleToString(ExecState* exec, double value, int32_t radix)
2077 {
2078     VM& vm = exec->vm();
2079     NativeCallFrameTracer tracer(&vm, exec);
2080
2081     auto scope = DECLARE_THROW_SCOPE(vm);
2082
2083     if (radix < 2 || radix > 36) {
2084         throwVMError(exec, scope, createRangeError(exec, "toString() radix argument must be between 2 and 36"_s));
2085         return nullptr;
2086     }
2087
2088     return reinterpret_cast<char*>(numberToString(vm, value, radix));
2089 }
2090
2091 char* JIT_OPERATION operationInt32ToStringWithValidRadix(ExecState* exec, int32_t value, int32_t radix)
2092 {
2093     VM& vm = exec->vm();
2094     NativeCallFrameTracer tracer(&vm, exec);
2095
2096     return reinterpret_cast<char*>(int32ToString(vm, value, radix));
2097 }
2098
2099 char* JIT_OPERATION operationInt52ToStringWithValidRadix(ExecState* exec, int64_t value, int32_t radix)
2100 {
2101     VM& vm = exec->vm();
2102     NativeCallFrameTracer tracer(&vm, exec);
2103
2104     return reinterpret_cast<char*>(int52ToString(vm, value, radix));
2105 }
2106
2107 char* JIT_OPERATION operationDoubleToStringWithValidRadix(ExecState* exec, double value, int32_t radix)
2108 {
2109     VM& vm = exec->vm();
2110     NativeCallFrameTracer tracer(&vm, exec);
2111
2112     return reinterpret_cast<char*>(numberToString(vm, value, radix));
2113 }
2114
2115 JSString* JIT_OPERATION operationSingleCharacterString(ExecState* exec, int32_t character)
2116 {
2117     VM& vm = exec->vm();
2118     NativeCallFrameTracer tracer(&vm, exec);
2119     
2120     return jsSingleCharacterString(exec, static_cast<UChar>(character));
2121 }
2122
2123 JSCell* JIT_OPERATION operationNewStringObject(ExecState* exec, JSString* string, Structure* structure)
2124 {
2125     VM& vm = exec->vm();
2126     NativeCallFrameTracer tracer(&vm, exec);
2127     
2128     return StringObject::create(vm, structure, string);
2129 }
2130
2131 JSCell* JIT_OPERATION operationToStringOnCell(ExecState* exec, JSCell* cell)
2132 {
2133     VM& vm = exec->vm();
2134     NativeCallFrameTracer tracer(&vm, exec);
2135     
2136     return JSValue(cell).toString(exec);
2137 }
2138
2139 JSCell* JIT_OPERATION operationToString(ExecState* exec, EncodedJSValue value)
2140 {
2141     VM& vm = exec->vm();
2142     NativeCallFrameTracer tracer(&vm, exec);
2143
2144     return JSValue::decode(value).toString(exec);
2145 }
2146
2147 JSCell* JIT_OPERATION operationCallStringConstructorOnCell(ExecState* exec, JSCell* cell)
2148 {
2149     VM& vm = exec->vm();
2150     NativeCallFrameTracer tracer(&vm, exec);
2151
2152     return stringConstructor(exec, cell);
2153 }
2154
2155 JSCell* JIT_OPERATION operationCallStringConstructor(ExecState* exec, EncodedJSValue value)
2156 {
2157     VM& vm = exec->vm();
2158     NativeCallFrameTracer tracer(&vm, exec);
2159
2160     return stringConstructor(exec, JSValue::decode(value));
2161 }
2162
2163 JSCell* JIT_OPERATION operationMakeRope2(ExecState* exec, JSString* left, JSString* right)
2164 {
2165     VM& vm = exec->vm();
2166     NativeCallFrameTracer tracer(&vm, exec);
2167
2168     return jsString(exec, left, right);
2169 }
2170
2171 JSCell* JIT_OPERATION operationMakeRope3(ExecState* exec, JSString* a, JSString* b, JSString* c)
2172 {
2173     VM& vm = exec->vm();
2174     NativeCallFrameTracer tracer(&vm, exec);
2175
2176     return jsString(exec, a, b, c);
2177 }
2178
2179 JSCell* JIT_OPERATION operationStrCat2(ExecState* exec, EncodedJSValue a, EncodedJSValue b)
2180 {
2181     VM& vm = exec->vm();
2182     NativeCallFrameTracer tracer(&vm, exec);
2183     auto scope = DECLARE_THROW_SCOPE(vm);
2184
2185     ASSERT(!JSValue::decode(a).isSymbol());
2186     ASSERT(!JSValue::decode(b).isSymbol());
2187     JSString* str1 = JSValue::decode(a).toString(exec);
2188     scope.assertNoException(); // Impossible, since we must have been given non-Symbol primitives.
2189     JSString* str2 = JSValue::decode(b).toString(exec);
2190     scope.assertNoException();
2191
2192     scope.release();
2193     return jsString(exec, str1, str2);
2194 }
2195     
2196 JSCell* JIT_OPERATION operationStrCat3(ExecState* exec, EncodedJSValue a, EncodedJSValue b, EncodedJSValue c)
2197 {
2198     VM& vm = exec->vm();
2199     NativeCallFrameTracer tracer(&vm, exec);
2200     auto scope = DECLARE_THROW_SCOPE(vm);
2201
2202     ASSERT(!JSValue::decode(a).isSymbol());
2203     ASSERT(!JSValue::decode(b).isSymbol());
2204     ASSERT(!JSValue::decode(c).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     JSString* str3 = JSValue::decode(c).toString(exec);
2210     scope.assertNoException();
2211
2212     scope.release();
2213     return jsString(exec, str1, str2, str3);
2214 }
2215
2216 char* JIT_OPERATION operationFindSwitchImmTargetForDouble(
2217     ExecState* exec, EncodedJSValue encodedValue, size_t tableIndex)
2218 {
2219     VM& vm = exec->vm();
2220     NativeCallFrameTracer tracer(&vm, exec);
2221
2222     CodeBlock* codeBlock = exec->codeBlock();
2223     SimpleJumpTable& table = codeBlock->switchJumpTable(tableIndex);
2224     JSValue value = JSValue::decode(encodedValue);
2225     ASSERT(value.isDouble());
2226     double asDouble = value.asDouble();
2227     int32_t asInt32 = static_cast<int32_t>(asDouble);
2228     if (asDouble == asInt32)
2229         return table.ctiForValue(asInt32).executableAddress<char*>();
2230     return table.ctiDefault.executableAddress<char*>();
2231 }
2232
2233 char* JIT_OPERATION operationSwitchString(ExecState* exec, size_t tableIndex, JSString* string)
2234 {
2235     VM& vm = exec->vm();
2236     NativeCallFrameTracer tracer(&vm, exec);
2237
2238     return exec->codeBlock()->stringSwitchJumpTable(tableIndex).ctiForValue(string->value(exec).impl()).executableAddress<char*>();
2239 }
2240
2241 int32_t JIT_OPERATION operationSwitchStringAndGetBranchOffset(ExecState* exec, size_t tableIndex, JSString* string)
2242 {
2243     VM& vm = exec->vm();
2244     NativeCallFrameTracer tracer(&vm, exec);
2245
2246     return exec->codeBlock()->stringSwitchJumpTable(tableIndex).offsetForValue(string->value(exec).impl(), std::numeric_limits<int32_t>::min());
2247 }
2248
2249 uintptr_t JIT_OPERATION operationCompareStringImplLess(StringImpl* a, StringImpl* b)
2250 {
2251     return codePointCompare(a, b) < 0;
2252 }
2253
2254 uintptr_t JIT_OPERATION operationCompareStringImplLessEq(StringImpl* a, StringImpl* b)
2255 {
2256     return codePointCompare(a, b) <= 0;
2257 }
2258
2259 uintptr_t JIT_OPERATION operationCompareStringImplGreater(StringImpl* a, StringImpl* b)
2260 {
2261     return codePointCompare(a, b) > 0;
2262 }
2263
2264 uintptr_t JIT_OPERATION operationCompareStringImplGreaterEq(StringImpl* a, StringImpl* b)
2265 {
2266     return codePointCompare(a, b) >= 0;
2267 }
2268
2269 uintptr_t JIT_OPERATION operationCompareStringLess(ExecState* exec, JSString* a, JSString* b)
2270 {
2271     VM& vm = exec->vm();
2272     NativeCallFrameTracer tracer(&vm, exec);
2273
2274     return codePointCompareLessThan(asString(a)->value(exec), asString(b)->value(exec));
2275 }
2276
2277 uintptr_t JIT_OPERATION operationCompareStringLessEq(ExecState* exec, JSString* a, JSString* b)
2278 {
2279     VM& vm = exec->vm();
2280     NativeCallFrameTracer tracer(&vm, exec);
2281
2282     return !codePointCompareLessThan(asString(b)->value(exec), asString(a)->value(exec));
2283 }
2284
2285 uintptr_t JIT_OPERATION operationCompareStringGreater(ExecState* exec, JSString* a, JSString* b)
2286 {
2287     VM& vm = exec->vm();
2288     NativeCallFrameTracer tracer(&vm, exec);
2289
2290     return codePointCompareLessThan(asString(b)->value(exec), asString(a)->value(exec));
2291 }
2292
2293 uintptr_t JIT_OPERATION operationCompareStringGreaterEq(ExecState* exec, JSString* a, JSString* b)
2294 {
2295     VM& vm = exec->vm();
2296     NativeCallFrameTracer tracer(&vm, exec);
2297
2298     return !codePointCompareLessThan(asString(a)->value(exec), asString(b)->value(exec));
2299 }
2300
2301 void JIT_OPERATION operationNotifyWrite(ExecState* exec, WatchpointSet* set)
2302 {
2303     VM& vm = exec->vm();
2304     NativeCallFrameTracer tracer(&vm, exec);
2305
2306     set->touch(vm, "Executed NotifyWrite");
2307 }
2308
2309 void JIT_OPERATION operationThrowStackOverflowForVarargs(ExecState* exec)
2310 {
2311     VM& vm = exec->vm();
2312     NativeCallFrameTracer tracer(&vm, exec);
2313     auto scope = DECLARE_THROW_SCOPE(vm);
2314     throwStackOverflowError(exec, scope);
2315 }
2316
2317 int32_t JIT_OPERATION operationSizeOfVarargs(ExecState* exec, EncodedJSValue encodedArguments, uint32_t firstVarArgOffset)
2318 {
2319     VM& vm = exec->vm();
2320     NativeCallFrameTracer tracer(&vm, exec);
2321     JSValue arguments = JSValue::decode(encodedArguments);
2322     
2323     return sizeOfVarargs(exec, arguments, firstVarArgOffset);
2324 }
2325
2326 int32_t JIT_OPERATION operationHasOwnProperty(ExecState* exec, JSObject* thisObject, EncodedJSValue encodedKey)
2327 {
2328     VM& vm = exec->vm();
2329     NativeCallFrameTracer tracer(&vm, exec);
2330     auto scope = DECLARE_THROW_SCOPE(vm);
2331
2332     JSValue key = JSValue::decode(encodedKey);
2333     Identifier propertyName = key.toPropertyKey(exec);
2334     RETURN_IF_EXCEPTION(scope, false);
2335
2336     PropertySlot slot(thisObject, PropertySlot::InternalMethodType::GetOwnProperty);
2337     bool result = thisObject->hasOwnProperty(exec, propertyName.impl(), slot);
2338     RETURN_IF_EXCEPTION(scope, false);
2339
2340     HasOwnPropertyCache* hasOwnPropertyCache = vm.hasOwnPropertyCache();
2341     ASSERT(hasOwnPropertyCache);
2342     hasOwnPropertyCache->tryAdd(vm, slot, thisObject, propertyName.impl(), result);
2343     return result;
2344 }
2345
2346 int32_t JIT_OPERATION operationNumberIsInteger(ExecState* exec, EncodedJSValue value)
2347 {
2348     VM& vm = exec->vm();
2349     NativeCallFrameTracer tracer(&vm, exec);
2350     return NumberConstructor::isIntegerImpl(JSValue::decode(value));
2351 }
2352
2353 int32_t JIT_OPERATION operationArrayIndexOfString(ExecState* exec, Butterfly* butterfly, JSString* searchElement, int32_t index)
2354 {
2355     VM& vm = exec->vm();
2356     NativeCallFrameTracer tracer(&vm, exec);
2357     auto scope = DECLARE_THROW_SCOPE(vm);
2358
2359     int32_t length = butterfly->publicLength();
2360     auto data = butterfly->contiguous().data();
2361     for (; index < length; ++index) {
2362         JSValue value = data[index].get();
2363         if (!value || !value.isString())
2364             continue;
2365         auto* string = asString(value);
2366         if (string == searchElement)
2367             return index;
2368         if (string->equal(exec, searchElement))
2369             return index;
2370         RETURN_IF_EXCEPTION(scope, { });
2371     }
2372     return -1;
2373 }
2374
2375 int32_t JIT_OPERATION operationArrayIndexOfValueInt32OrContiguous(ExecState* exec, Butterfly* butterfly, EncodedJSValue encodedValue, int32_t index)
2376 {
2377     VM& vm = exec->vm();
2378     NativeCallFrameTracer tracer(&vm, exec);
2379     auto scope = DECLARE_THROW_SCOPE(vm);
2380
2381     JSValue searchElement = JSValue::decode(encodedValue);
2382
2383     int32_t length = butterfly->publicLength();
2384     auto data = butterfly->contiguous().data();
2385     for (; index < length; ++index) {
2386         JSValue value = data[index].get();
2387         if (!value)
2388             continue;
2389         if (JSValue::strictEqual(exec, searchElement, value))
2390             return index;
2391         RETURN_IF_EXCEPTION(scope, { });
2392     }
2393     return -1;
2394 }
2395
2396 int32_t JIT_OPERATION operationArrayIndexOfValueDouble(ExecState* exec, Butterfly* butterfly, EncodedJSValue encodedValue, int32_t index)
2397 {
2398     VM& vm = exec->vm();
2399     NativeCallFrameTracer tracer(&vm, exec);
2400
2401     JSValue searchElement = JSValue::decode(encodedValue);
2402
2403     if (!searchElement.isNumber())
2404         return -1;
2405     double number = searchElement.asNumber();
2406
2407     int32_t length = butterfly->publicLength();
2408     const double* data = butterfly->contiguousDouble().data();
2409     for (; index < length; ++index) {
2410         // This comparison ignores NaN.
2411         if (data[index] == number)
2412             return index;
2413     }
2414     return -1;
2415 }
2416
2417 void JIT_OPERATION operationLoadVarargs(ExecState* exec, int32_t firstElementDest, EncodedJSValue encodedArguments, uint32_t offset, uint32_t length, uint32_t mandatoryMinimum)
2418 {
2419     VM& vm = exec->vm();
2420     NativeCallFrameTracer tracer(&vm, exec);
2421     JSValue arguments = JSValue::decode(encodedArguments);
2422     
2423     loadVarargs(exec, VirtualRegister(firstElementDest), arguments, offset, length);
2424     
2425     for (uint32_t i = length; i < mandatoryMinimum; ++i)
2426         exec->r(firstElementDest + i) = jsUndefined();
2427 }
2428
2429 double JIT_OPERATION operationFModOnInts(int32_t a, int32_t b)
2430 {
2431     return fmod(a, b);
2432 }
2433
2434 #if USE(JSVALUE32_64)
2435 double JIT_OPERATION operationRandom(JSGlobalObject* globalObject)
2436 {
2437     return globalObject->weakRandomNumber();
2438 }
2439 #endif
2440
2441 JSCell* JIT_OPERATION operationStringFromCharCode(ExecState* exec, int32_t op1)
2442 {
2443     VM* vm = &exec->vm();
2444     NativeCallFrameTracer tracer(vm, exec);
2445     return JSC::stringFromCharCode(exec, op1);
2446 }
2447
2448 EncodedJSValue JIT_OPERATION operationStringFromCharCodeUntyped(ExecState* exec, EncodedJSValue encodedValue)
2449 {
2450     VM* vm = &exec->vm();
2451     NativeCallFrameTracer tracer(vm, exec);
2452     JSValue charValue = JSValue::decode(encodedValue);
2453     int32_t chInt = charValue.toUInt32(exec);
2454     return JSValue::encode(JSC::stringFromCharCode(exec, chInt));
2455 }
2456
2457 int64_t JIT_OPERATION operationConvertBoxedDoubleToInt52(EncodedJSValue encodedValue)
2458 {
2459     JSValue value = JSValue::decode(encodedValue);
2460     if (!value.isDouble())
2461         return JSValue::notInt52;
2462     return tryConvertToInt52(value.asDouble());
2463 }
2464
2465 int64_t JIT_OPERATION operationConvertDoubleToInt52(double value)
2466 {
2467     return tryConvertToInt52(value);
2468 }
2469
2470 char* JIT_OPERATION operationNewRawObject(ExecState* exec, Structure* structure, int32_t length, Butterfly* butterfly)
2471 {
2472     VM& vm = exec->vm();
2473     NativeCallFrameTracer tracer(&vm, exec);
2474
2475     if (!butterfly
2476         && (structure->outOfLineCapacity() || hasIndexedProperties(structure->indexingType()))) {
2477         IndexingHeader header;
2478         header.setVectorLength(length);
2479         header.setPublicLength(0);
2480         
2481         butterfly = Butterfly::create(
2482             vm, nullptr, 0, structure->outOfLineCapacity(),
2483             hasIndexedProperties(structure->indexingType()), header,
2484             length * sizeof(EncodedJSValue));
2485     }
2486
2487     JSObject* result = JSObject::createRawObject(exec, structure, butterfly);
2488     result->butterfly(); // Ensure that the butterfly is in to-space.
2489     return bitwise_cast<char*>(result);
2490 }
2491
2492 JSCell* JIT_OPERATION operationNewObjectWithButterfly(ExecState* exec, Structure* structure, Butterfly* butterfly)
2493 {
2494     VM& vm = exec->vm();
2495     NativeCallFrameTracer tracer(&vm, exec);
2496     
2497     if (!butterfly) {
2498         butterfly = Butterfly::create(
2499             vm, nullptr, 0, structure->outOfLineCapacity(), false, IndexingHeader(), 0);
2500     }
2501     
2502     JSObject* result = JSObject::createRawObject(exec, structure, butterfly);
2503     result->butterfly(); // Ensure that the butterfly is in to-space.
2504     return result;
2505 }
2506
2507 JSCell* JIT_OPERATION operationNewObjectWithButterflyWithIndexingHeaderAndVectorLength(ExecState* exec, Structure* structure, unsigned length, Butterfly* butterfly)
2508 {
2509     VM& vm = exec->vm();
2510     NativeCallFrameTracer tracer(&vm, exec);
2511
2512     IndexingHeader header;
2513     header.setVectorLength(length);
2514     header.setPublicLength(0);
2515     if (butterfly)
2516         *butterfly->indexingHeader() = header;
2517     else {
2518         butterfly = Butterfly::create(
2519             vm, nullptr, 0, structure->outOfLineCapacity(), true, header,
2520             sizeof(EncodedJSValue) * length);
2521     }
2522     
2523     // Paradoxically this may allocate a JSArray. That's totally cool.
2524     JSObject* result = JSObject::createRawObject(exec, structure, butterfly);
2525     result->butterfly(); // Ensure that the butterfly is in to-space.
2526     return result;
2527 }
2528
2529 JSCell* JIT_OPERATION operationNewArrayWithSpreadSlow(ExecState* exec, void* buffer, uint32_t numItems)
2530 {
2531     VM& vm = exec->vm();
2532     NativeCallFrameTracer tracer(&vm, exec);
2533     auto scope = DECLARE_THROW_SCOPE(vm);
2534
2535     EncodedJSValue* values = static_cast<EncodedJSValue*>(buffer);
2536     Checked<unsigned, RecordOverflow> checkedLength = 0;
2537     for (unsigned i = 0; i < numItems; i++) {
2538         JSValue value = JSValue::decode(values[i]);
2539         if (JSFixedArray* array = jsDynamicCast<JSFixedArray*>(vm, value))
2540             checkedLength += array->size();
2541         else
2542             ++checkedLength;
2543     }
2544
2545     if (UNLIKELY(checkedLength.hasOverflowed())) {
2546         throwOutOfMemoryError(exec, scope);
2547         return nullptr;
2548     }
2549
2550     unsigned length = checkedLength.unsafeGet();
2551     JSGlobalObject* globalObject = exec->lexicalGlobalObject();
2552     Structure* structure = globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithContiguous);
2553
2554     JSArray* result = JSArray::tryCreate(vm, structure, length);
2555     if (UNLIKELY(!result)) {
2556         throwOutOfMemoryError(exec, scope);
2557         return nullptr;
2558     }
2559     RETURN_IF_EXCEPTION(scope, nullptr);
2560
2561     unsigned index = 0;
2562     for (unsigned i = 0; i < numItems; i++) {
2563         JSValue value = JSValue::decode(values[i]);
2564         if (JSFixedArray* array = jsDynamicCast<JSFixedArray*>(vm, value)) {
2565             // We are spreading.
2566             for (unsigned i = 0; i < array->size(); i++) {
2567                 result->putDirectIndex(exec, index, array->get(i));
2568                 RETURN_IF_EXCEPTION(scope, nullptr);
2569                 ++index;
2570             }
2571         } else {
2572             // We are not spreading.
2573             result->putDirectIndex(exec, index, value);
2574             RETURN_IF_EXCEPTION(scope, nullptr);
2575             ++index;
2576         }
2577     }
2578
2579     return result;
2580 }
2581
2582 JSCell* operationCreateFixedArray(ExecState* exec, unsigned length)
2583 {
2584     VM& vm = exec->vm();
2585     NativeCallFrameTracer tracer(&vm, exec);
2586     auto scope = DECLARE_THROW_SCOPE(vm);
2587
2588     if (JSFixedArray* result = JSFixedArray::tryCreate(vm, vm.fixedArrayStructure.get(), length))
2589         return result;
2590
2591     throwOutOfMemoryError(exec, scope);
2592     return nullptr;
2593 }
2594
2595 JSCell* JIT_OPERATION operationSpreadGeneric(ExecState* exec, JSCell* iterable)
2596 {
2597     VM& vm = exec->vm();
2598     NativeCallFrameTracer tracer(&vm, exec);
2599
2600     auto throwScope = DECLARE_THROW_SCOPE(vm);
2601
2602     if (isJSArray(iterable)) {
2603         JSArray* array = jsCast<JSArray*>(iterable);
2604         if (array->isIteratorProtocolFastAndNonObservable()) {
2605             throwScope.release();
2606             return JSFixedArray::createFromArray(exec, vm, array);
2607         }
2608     }
2609
2610     // FIXME: we can probably make this path faster by having our caller JS code call directly into
2611     // the iteration protocol builtin: https://bugs.webkit.org/show_bug.cgi?id=164520
2612
2613     JSGlobalObject* globalObject = exec->lexicalGlobalObject();
2614     JSArray* array;
2615     {
2616         JSFunction* iterationFunction = globalObject->iteratorProtocolFunction();
2617         CallData callData;
2618         CallType callType = JSC::getCallData(vm, iterationFunction, callData);
2619         ASSERT(callType != CallType::None);
2620
2621         MarkedArgumentBuffer arguments;
2622         arguments.append(iterable);
2623         ASSERT(!arguments.hasOverflowed());
2624         JSValue arrayResult = call(exec, iterationFunction, callType, callData, jsNull(), arguments);
2625         RETURN_IF_EXCEPTION(throwScope, nullptr);
2626         array = jsCast<JSArray*>(arrayResult);
2627     }
2628
2629     throwScope.release();
2630     return JSFixedArray::createFromArray(exec, vm, array);
2631 }
2632
2633 JSCell* JIT_OPERATION operationSpreadFastArray(ExecState* exec, JSCell* cell)
2634 {
2635     VM& vm = exec->vm();
2636     NativeCallFrameTracer tracer(&vm, exec);
2637
2638     ASSERT(isJSArray(cell));
2639     JSArray* array = jsCast<JSArray*>(cell);
2640     ASSERT(array->isIteratorProtocolFastAndNonObservable());
2641
2642     return JSFixedArray::createFromArray(exec, vm, array);
2643 }
2644
2645 void JIT_OPERATION operationProcessTypeProfilerLogDFG(ExecState* exec) 
2646 {
2647     VM& vm = exec->vm();
2648     NativeCallFrameTracer tracer(&vm, exec);
2649
2650     vm.typeProfilerLog()->processLogEntries("Log Full, called from inside DFG."_s);
2651 }
2652
2653 EncodedJSValue JIT_OPERATION operationResolveScopeForHoistingFuncDeclInEval(ExecState* exec, JSScope* scope, UniquedStringImpl* impl)
2654 {
2655     VM& vm = exec->vm();
2656     NativeCallFrameTracer tracer(&vm, exec);
2657         
2658     JSValue resolvedScope = JSScope::resolveScopeForHoistingFuncDeclInEval(exec, scope, Identifier::fromUid(exec, impl));
2659     return JSValue::encode(resolvedScope);
2660 }
2661     
2662 JSCell* JIT_OPERATION operationResolveScope(ExecState* exec, JSScope* scope, UniquedStringImpl* impl)
2663 {
2664     VM& vm = exec->vm();
2665     NativeCallFrameTracer tracer(&vm, exec);
2666
2667     JSObject* resolvedScope = JSScope::resolve(exec, scope, Identifier::fromUid(exec, impl));
2668     return resolvedScope;
2669 }
2670
2671 EncodedJSValue JIT_OPERATION operationGetDynamicVar(ExecState* exec, JSObject* scope, UniquedStringImpl* impl, unsigned getPutInfoBits)
2672 {
2673     VM& vm = exec->vm();
2674     NativeCallFrameTracer tracer(&vm, exec);
2675     auto throwScope = DECLARE_THROW_SCOPE(vm);
2676
2677     Identifier ident = Identifier::fromUid(exec, impl);
2678     throwScope.release();
2679     return JSValue::encode(scope->getPropertySlot(exec, ident, [&] (bool found, PropertySlot& slot) -> JSValue {
2680         if (!found) {
2681             GetPutInfo getPutInfo(getPutInfoBits);
2682             if (getPutInfo.resolveMode() == ThrowIfNotFound)
2683                 throwException(exec, throwScope, createUndefinedVariableError(exec, ident));
2684             return jsUndefined();
2685         }
2686
2687         if (scope->isGlobalLexicalEnvironment()) {
2688             // When we can't statically prove we need a TDZ check, we must perform the check on the slow path.
2689             JSValue result = slot.getValue(exec, ident);
2690             if (result == jsTDZValue()) {
2691                 throwException(exec, throwScope, createTDZError(exec));
2692                 return jsUndefined();
2693             }
2694             return result;
2695         }
2696
2697         return slot.getValue(exec, ident);
2698     }));
2699 }
2700
2701 void JIT_OPERATION operationPutDynamicVar(ExecState* exec, JSObject* scope, EncodedJSValue value, UniquedStringImpl* impl, unsigned getPutInfoBits)
2702 {
2703     VM& vm = exec->vm();
2704     NativeCallFrameTracer tracer(&vm, exec);
2705     auto throwScope = DECLARE_THROW_SCOPE(vm);
2706
2707     const Identifier& ident = Identifier::fromUid(exec, impl);
2708     GetPutInfo getPutInfo(getPutInfoBits);
2709     bool hasProperty = scope->hasProperty(exec, ident);
2710     RETURN_IF_EXCEPTION(throwScope, void());
2711     if (hasProperty
2712         && scope->isGlobalLexicalEnvironment()
2713         && !isInitialization(getPutInfo.initializationMode())) {
2714         // When we can't statically prove we need a TDZ check, we must perform the check on the slow path.
2715         PropertySlot slot(scope, PropertySlot::InternalMethodType::Get);
2716         JSGlobalLexicalEnvironment::getOwnPropertySlot(scope, exec, ident, slot);
2717         if (slot.getValue(exec, ident) == jsTDZValue()) {
2718             throwException(exec, throwScope, createTDZError(exec));
2719             return;
2720         }
2721     }
2722
2723     if (getPutInfo.resolveMode() == ThrowIfNotFound && !hasProperty) {
2724         throwException(exec, throwScope, createUndefinedVariableError(exec, ident));
2725         return;
2726     }
2727
2728     CodeOrigin origin = exec->codeOrigin();
2729     bool strictMode;
2730     if (origin.inlineCallFrame)
2731         strictMode = origin.inlineCallFrame->baselineCodeBlock->isStrictMode();
2732     else
2733         strictMode = exec->codeBlock()->isStrictMode();
2734     PutPropertySlot slot(scope, strictMode, PutPropertySlot::UnknownContext, isInitialization(getPutInfo.initializationMode()));
2735     throwScope.release();
2736     scope->methodTable(vm)->put(scope, exec, ident, JSValue::decode(value), slot);
2737 }
2738
2739 int32_t JIT_OPERATION operationMapHash(ExecState* exec, EncodedJSValue input)
2740 {
2741     VM& vm = exec->vm();
2742     NativeCallFrameTracer tracer(&vm, exec);
2743
2744     return jsMapHash(exec, vm, JSValue::decode(input));
2745 }
2746
2747 JSCell* JIT_OPERATION operationJSMapFindBucket(ExecState* exec, JSCell* map, EncodedJSValue key, int32_t hash)
2748 {
2749     VM& vm = exec->vm();
2750     NativeCallFrameTracer tracer(&vm, exec);
2751     JSMap::BucketType** bucket = jsCast<JSMap*>(map)->findBucket(exec, JSValue::decode(key), hash);
2752     if (!bucket)
2753         return vm.sentinelMapBucket.get();
2754     return *bucket;
2755 }
2756
2757 JSCell* JIT_OPERATION operationJSSetFindBucket(ExecState* exec, JSCell* map, EncodedJSValue key, int32_t hash)
2758 {
2759     VM& vm = exec->vm();
2760     NativeCallFrameTracer tracer(&vm, exec);
2761     JSSet::BucketType** bucket = jsCast<JSSet*>(map)->findBucket(exec, JSValue::decode(key), hash);
2762     if (!bucket)
2763         return vm.sentinelSetBucket.get();
2764     return *bucket;
2765 }
2766
2767 JSCell* JIT_OPERATION operationSetAdd(ExecState* exec, JSCell* set, EncodedJSValue key, int32_t hash)
2768 {
2769     VM& vm = exec->vm();
2770     NativeCallFrameTracer tracer(&vm, exec);
2771     auto* bucket = jsCast<JSSet*>(set)->addNormalized(exec, JSValue::decode(key), JSValue(), hash);
2772     if (!bucket)
2773         return vm.sentinelSetBucket.get();
2774     return bucket;
2775 }
2776
2777 JSCell* JIT_OPERATION operationMapSet(ExecState* exec, JSCell* map, EncodedJSValue key, EncodedJSValue value, int32_t hash)
2778 {
2779     VM& vm = exec->vm();
2780     NativeCallFrameTracer tracer(&vm, exec);
2781     auto* bucket = jsCast<JSMap*>(map)->addNormalized(exec, JSValue::decode(key), JSValue::decode(value), hash);
2782     if (!bucket)
2783         return vm.sentinelMapBucket.get();
2784     return bucket;
2785 }
2786
2787 void JIT_OPERATION operationWeakSetAdd(ExecState* exec, JSCell* set, JSCell* key, int32_t hash)
2788 {
2789     VM& vm = exec->vm();
2790     NativeCallFrameTracer tracer(&vm, exec);
2791     jsCast<JSWeakSet*>(set)->add(vm, asObject(key), JSValue(), hash);
2792 }
2793
2794 void JIT_OPERATION operationWeakMapSet(ExecState* exec, JSCell* map, JSCell* key, EncodedJSValue value, int32_t hash)
2795 {
2796     VM& vm = exec->vm();
2797     NativeCallFrameTracer tracer(&vm, exec);
2798     jsCast<JSWeakMap*>(map)->add(vm, asObject(key), JSValue::decode(value), hash);
2799 }
2800
2801 EncodedJSValue JIT_OPERATION operationGetPrototypeOfObject(ExecState* exec, JSObject* thisObject)
2802 {
2803     VM& vm = exec->vm();
2804     NativeCallFrameTracer tracer(&vm, exec);
2805     return JSValue::encode(thisObject->getPrototype(vm, exec));
2806 }
2807
2808 EncodedJSValue JIT_OPERATION operationGetPrototypeOf(ExecState* exec, EncodedJSValue encodedValue)
2809 {
2810     VM& vm = exec->vm();
2811     NativeCallFrameTracer tracer(&vm, exec);
2812     auto scope = DECLARE_THROW_SCOPE(vm);
2813
2814     JSValue thisValue = JSValue::decode(encodedValue).toThis(exec, StrictMode);
2815     if (thisValue.isUndefinedOrNull())
2816         return throwVMError(exec, scope, createNotAnObjectError(exec, thisValue));
2817
2818     JSObject* thisObject = jsDynamicCast<JSObject*>(vm, thisValue);
2819     if (!thisObject) {
2820         JSObject* prototype = thisValue.synthesizePrototype(exec);
2821         EXCEPTION_ASSERT(!!scope.exception() == !prototype);
2822         if (UNLIKELY(!prototype))
2823             return JSValue::encode(JSValue());
2824         return JSValue::encode(prototype);
2825     }
2826
2827     scope.release();
2828     return JSValue::encode(thisObject->getPrototype(vm, exec));
2829 }
2830
2831 void JIT_OPERATION operationThrowDFG(ExecState* exec, EncodedJSValue valueToThrow)
2832 {
2833     VM& vm = exec->vm();
2834     NativeCallFrameTracer tracer(&vm, exec);
2835     auto scope = DECLARE_THROW_SCOPE(vm);
2836     scope.throwException(exec, JSValue::decode(valueToThrow));
2837 }
2838
2839 void JIT_OPERATION operationThrowStaticError(ExecState* exec, JSString* message, uint32_t errorType)
2840 {
2841     VM& vm = exec->vm();
2842     NativeCallFrameTracer tracer(&vm, exec);
2843     auto scope = DECLARE_THROW_SCOPE(vm);
2844     String errorMessage = message->value(exec);
2845     scope.throwException(exec, createError(exec, static_cast<ErrorType>(errorType), errorMessage));
2846 }
2847
2848 extern "C" void JIT_OPERATION triggerReoptimizationNow(CodeBlock* codeBlock, CodeBlock* optimizedCodeBlock, OSRExitBase* exit)
2849 {
2850     // It's sort of preferable that we don't GC while in here. Anyways, doing so wouldn't
2851     // really be profitable.
2852     DeferGCForAWhile deferGC(codeBlock->vm()->heap);
2853     
2854     sanitizeStackForVM(codeBlock->vm());
2855
2856     if (Options::verboseOSR())
2857         dataLog(*codeBlock, ": Entered reoptimize\n");
2858     // We must be called with the baseline code block.
2859     ASSERT(JITCode::isBaselineCode(codeBlock->jitType()));
2860
2861     // If I am my own replacement, then reoptimization has already been triggered.
2862     // This can happen in recursive functions.
2863     //
2864     // Note that even if optimizedCodeBlock is an FTLForOSREntry style CodeBlock, this condition is a
2865     // sure bet that we don't have anything else left to do.
2866     if (codeBlock->replacement() == codeBlock) {
2867         if (Options::verboseOSR())
2868             dataLog(*codeBlock, ": Not reoptimizing because we've already been jettisoned.\n");
2869         return;
2870     }
2871     
2872     // Otherwise, the replacement must be optimized code. Use this as an opportunity
2873     // to check our logic.
2874     ASSERT(codeBlock->hasOptimizedReplacement());
2875     ASSERT(JITCode::isOptimizingJIT(optimizedCodeBlock->jitType()));
2876     
2877     bool didTryToEnterIntoInlinedLoops = false;
2878     for (InlineCallFrame* inlineCallFrame = exit->m_codeOrigin.inlineCallFrame; inlineCallFrame; inlineCallFrame = inlineCallFrame->directCaller.inlineCallFrame) {
2879         if (inlineCallFrame->baselineCodeBlock->ownerScriptExecutable()->didTryToEnterInLoop()) {
2880             didTryToEnterIntoInlinedLoops = true;
2881             break;
2882         }
2883     }
2884
2885     // In order to trigger reoptimization, one of two things must have happened:
2886     // 1) We exited more than some number of times.
2887     // 2) We exited and got stuck in a loop, and now we're exiting again.
2888     bool didExitABunch = optimizedCodeBlock->shouldReoptimizeNow();
2889     bool didGetStuckInLoop =
2890         (codeBlock->checkIfOptimizationThresholdReached() || didTryToEnterIntoInlinedLoops)
2891         && optimizedCodeBlock->shouldReoptimizeFromLoopNow();
2892     
2893     if (!didExitABunch && !didGetStuckInLoop) {
2894         if (Options::verboseOSR())
2895             dataLog(*codeBlock, ": Not reoptimizing ", *optimizedCodeBlock, " because it either didn't exit enough or didn't loop enough after exit.\n");
2896         codeBlock->optimizeAfterLongWarmUp();
2897         return;
2898     }
2899     
2900     optimizedCodeBlock->jettison(Profiler::JettisonDueToOSRExit, CountReoptimization);
2901 }
2902
2903 #if ENABLE(FTL_JIT)
2904 static bool shouldTriggerFTLCompile(CodeBlock* codeBlock, JITCode* jitCode)
2905 {
2906     if (codeBlock->baselineVersion()->m_didFailFTLCompilation) {
2907         CODEBLOCK_LOG_EVENT(codeBlock, "abortFTLCompile", ());
2908         if (Options::verboseOSR())
2909             dataLog("Deferring FTL-optimization of ", *codeBlock, " indefinitely because there was an FTL failure.\n");
2910         jitCode->dontOptimizeAnytimeSoon(codeBlock);
2911         return false;
2912     }
2913
2914     if (!codeBlock->hasOptimizedReplacement()
2915         && !jitCode->checkIfOptimizationThresholdReached(codeBlock)) {
2916         CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("counter = ", jitCode->tierUpCounter));
2917         if (Options::verboseOSR())
2918             dataLog("Choosing not to FTL-optimize ", *codeBlock, " yet.\n");
2919         return false;
2920     }
2921     return true;
2922 }
2923
2924 static void triggerFTLReplacementCompile(VM* vm, CodeBlock* codeBlock, JITCode* jitCode)
2925 {
2926     if (codeBlock->codeType() == GlobalCode) {
2927         // Global code runs once, so we don't want to do anything. We don't want to defer indefinitely,
2928         // since this may have been spuriously called from tier-up initiated in a loop, and that loop may
2929         // later want to run faster code. Deferring for warm-up seems safest.
2930         jitCode->optimizeAfterWarmUp(codeBlock);
2931         return;
2932     }
2933     
2934     Worklist::State worklistState;
2935     if (Worklist* worklist = existingGlobalFTLWorklistOrNull()) {
2936         worklistState = worklist->completeAllReadyPlansForVM(
2937             *vm, CompilationKey(codeBlock->baselineVersion(), FTLMode));
2938     } else
2939         worklistState = Worklist::NotKnown;
2940     
2941     if (worklistState == Worklist::Compiling) {
2942         CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("still compiling"));
2943         jitCode->setOptimizationThresholdBasedOnCompilationResult(
2944             codeBlock, CompilationDeferred);
2945         return;
2946     }
2947     
2948     if (codeBlock->hasOptimizedReplacement()) {
2949         CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("has replacement"));
2950         // That's great, we've compiled the code - next time we call this function,
2951         // we'll enter that replacement.
2952         jitCode->optimizeSoon(codeBlock);
2953         return;
2954     }
2955     
2956     if (worklistState == Worklist::Compiled) {
2957         CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("compiled and failed"));
2958         // This means that we finished compiling, but failed somehow; in that case the
2959         // thresholds will be set appropriately.
2960         if (Options::verboseOSR())
2961             dataLog("Code block ", *codeBlock, " was compiled but it doesn't have an optimized replacement.\n");
2962         return;
2963     }
2964
2965     CODEBLOCK_LOG_EVENT(codeBlock, "triggerFTLReplacement", ());
2966     // We need to compile the code.
2967     compile(
2968         *vm, codeBlock->newReplacement(), codeBlock, FTLMode, UINT_MAX,
2969         Operands<JSValue>(), ToFTLDeferredCompilationCallback::create());
2970
2971     // If we reached here, the counter has not be reset. Do that now.
2972     jitCode->setOptimizationThresholdBasedOnCompilationResult(
2973         codeBlock, CompilationDeferred);
2974 }
2975
2976 void JIT_OPERATION triggerTierUpNow(ExecState* exec)
2977 {
2978     VM* vm = &exec->vm();
2979     NativeCallFrameTracer tracer(vm, exec);
2980     DeferGCForAWhile deferGC(vm->heap);
2981     CodeBlock* codeBlock = exec->codeBlock();
2982     
2983     sanitizeStackForVM(vm);
2984
2985     if (codeBlock->jitType() != JITCode::DFGJIT) {
2986         dataLog("Unexpected code block in DFG->FTL tier-up: ", *codeBlock, "\n");
2987         RELEASE_ASSERT_NOT_REACHED();
2988     }
2989     
2990     JITCode* jitCode = codeBlock->jitCode()->dfg();
2991     
2992     if (Options::verboseOSR()) {
2993         dataLog(
2994             *codeBlock, ": Entered triggerTierUpNow with executeCounter = ",
2995             jitCode->tierUpCounter, "\n");
2996     }
2997
2998     if (shouldTriggerFTLCompile(codeBlock, jitCode))
2999         triggerFTLReplacementCompile(vm, codeBlock, jitCode);
3000
3001     if (codeBlock->hasOptimizedReplacement()) {
3002         if (jitCode->tierUpEntryTriggers.isEmpty()) {
3003             CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("replacement in place, delaying indefinitely"));
3004             // There is nothing more we can do, the only way this will be entered
3005             // is through the function entry point.
3006             jitCode->dontOptimizeAnytimeSoon(codeBlock);
3007             return;
3008         }
3009         if (jitCode->osrEntryBlock() && jitCode->tierUpEntryTriggers.size() == 1) {
3010             CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("trigger in place, delaying indefinitely"));
3011             // There is only one outer loop and its trigger must have been set
3012             // when the plan completed.
3013             // Exiting the inner loop is useless, we can ignore the counter and leave
3014             // the trigger do its job.
3015             jitCode->dontOptimizeAnytimeSoon(codeBlock);
3016             return;
3017         }
3018     }
3019 }
3020
3021 static char* tierUpCommon(ExecState* exec, unsigned originBytecodeIndex, bool canOSREnterHere)
3022 {
3023     VM* vm = &exec->vm();
3024     CodeBlock* codeBlock = exec->codeBlock();
3025
3026     // Resolve any pending plan for OSR Enter on this function.
3027     Worklist::State worklistState;
3028     if (Worklist* worklist = existingGlobalFTLWorklistOrNull()) {
3029         worklistState = worklist->completeAllReadyPlansForVM(
3030             *vm, CompilationKey(codeBlock->baselineVersion(), FTLForOSREntryMode));
3031     } else
3032         worklistState = Worklist::NotKnown;
3033
3034     JITCode* jitCode = codeBlock->jitCode()->dfg();
3035     
3036     bool triggeredSlowPathToStartCompilation = false;
3037     auto tierUpEntryTriggers = jitCode->tierUpEntryTriggers.find(originBytecodeIndex);
3038     if (tierUpEntryTriggers != jitCode->tierUpEntryTriggers.end()) {
3039         switch (tierUpEntryTriggers->value) {
3040         case JITCode::TriggerReason::DontTrigger:
3041             // The trigger isn't set, we entered because the counter reached its
3042             // threshold.
3043             break;
3044
3045         case JITCode::TriggerReason::CompilationDone:
3046             // The trigger was set because compilation completed. Don't unset it
3047             // so that further DFG executions OSR enter as well.
3048             break;
3049
3050         case JITCode::TriggerReason::StartCompilation:
3051             // We were asked to enter as soon as possible and start compiling an
3052             // entry for the current bytecode location. Unset this trigger so we
3053             // don't continually enter.
3054             tierUpEntryTriggers->value = JITCode::TriggerReason::DontTrigger;
3055             triggeredSlowPathToStartCompilation = true;
3056             break;
3057         }
3058     }
3059
3060     if (worklistState == Worklist::Compiling) {
3061         CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("still compiling"));
3062         jitCode->setOptimizationThresholdBasedOnCompilationResult(codeBlock, CompilationDeferred);
3063         return nullptr;
3064     }
3065
3066     // If we can OSR Enter, do it right away.
3067     if (canOSREnterHere) {
3068         auto iter = jitCode->bytecodeIndexToStreamIndex.find(originBytecodeIndex);
3069         if (iter != jitCode->bytecodeIndexToStreamIndex.end()) {
3070             unsigned streamIndex = iter->value;
3071             if (CodeBlock* entryBlock = jitCode->osrEntryBlock()) {
3072                 if (Options::verboseOSR())
3073                     dataLog("OSR entry: From ", RawPointer(jitCode), " got entry block ", RawPointer(entryBlock), "\n");
3074                 if (void* address = FTL::prepareOSREntry(exec, codeBlock, entryBlock, originBytecodeIndex, streamIndex)) {
3075                     CODEBLOCK_LOG_EVENT(entryBlock, "osrEntry", ("at bc#", originBytecodeIndex));
3076                     return retagCodePtr<char*>(address, JSEntryPtrTag, bitwise_cast<PtrTag>(exec));
3077                 }
3078             }
3079         }
3080     }
3081
3082     if (worklistState == Worklist::Compiled) {
3083         CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("compiled and failed"));
3084         // This means that compilation failed and we already set the thresholds.
3085         if (Options::verboseOSR())
3086             dataLog("Code block ", *codeBlock, " was compiled but it doesn't have an optimized replacement.\n");
3087         return nullptr;
3088     }
3089
3090     // - If we don't have an FTL code block, then try to compile one.
3091     // - If we do have an FTL code block, then try to enter for a while.
3092     // - If we couldn't enter for a while, then trigger OSR entry.
3093
3094     if (!shouldTriggerFTLCompile(codeBlock, jitCode) && !triggeredSlowPathToStartCompilation)
3095         return nullptr;
3096
3097     if (!jitCode->neverExecutedEntry && !triggeredSlowPathToStartCompilation) {
3098         triggerFTLReplacementCompile(vm, codeBlock, jitCode);
3099
3100         if (!codeBlock->hasOptimizedReplacement())
3101             return nullptr;
3102
3103         if (jitCode->osrEntryRetry < Options::ftlOSREntryRetryThreshold()) {
3104             CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("avoiding OSR entry compile"));
3105             jitCode->osrEntryRetry++;
3106             return nullptr;
3107         }
3108     } else
3109         CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("avoiding replacement compile"));
3110
3111     if (CodeBlock* entryBlock = jitCode->osrEntryBlock()) {
3112         if (jitCode->osrEntryRetry < Options::ftlOSREntryRetryThreshold()) {
3113             CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("OSR entry failed, OSR entry threshold not met"));
3114             jitCode->osrEntryRetry++;
3115             jitCode->setOptimizationThresholdBasedOnCompilationResult(
3116                 codeBlock, CompilationDeferred);
3117             return nullptr;
3118         }
3119
3120         FTL::ForOSREntryJITCode* entryCode = entryBlock->jitCode()->ftlForOSREntry();
3121         entryCode->countEntryFailure();
3122         if (entryCode->entryFailureCount() <
3123             Options::ftlOSREntryFailureCountForReoptimization()) {
3124             CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("OSR entry failed"));
3125             jitCode->setOptimizationThresholdBasedOnCompilationResult(
3126                 codeBlock, CompilationDeferred);
3127             return nullptr;
3128         }
3129
3130         // OSR entry failed. Oh no! This implies that we need to retry. We retry
3131         // without exponential backoff and we only do this for the entry code block.
3132         CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("OSR entry failed too many times"));
3133         unsigned osrEntryBytecode = entryBlock->jitCode()->ftlForOSREntry()->bytecodeIndex();
3134         jitCode->clearOSREntryBlock();
3135         jitCode->osrEntryRetry = 0;
3136         jitCode->tierUpEntryTriggers.set(osrEntryBytecode, JITCode::TriggerReason::DontTrigger);
3137         jitCode->setOptimizationThresholdBasedOnCompilationResult(
3138             codeBlock, CompilationDeferred);
3139         return nullptr;
3140     }
3141
3142     // It's time to try to compile code for OSR entry.
3143
3144     if (!triggeredSlowPathToStartCompilation) {
3145
3146         // An inner loop didn't specifically ask for us to kick off a compilation. This means the counter
3147         // crossed its threshold. We either fall through and kick off a compile for originBytecodeIndex,
3148         // or we flag an outer loop to immediately try to compile itself. If there are outer loops,
3149         // we first try to make them compile themselves. But we will eventually fall back to compiling
3150         // a progressively inner loop if it takes too long for control to reach an outer loop.
3151
3152         auto tryTriggerOuterLoopToCompile = [&] {
3153             auto tierUpHierarchyEntry = jitCode->tierUpInLoopHierarchy.find(originBytecodeIndex);
3154             if (tierUpHierarchyEntry == jitCode->tierUpInLoopHierarchy.end())
3155                 return false;
3156
3157             // This vector is ordered from innermost to outermost loop. Every bytecode entry in this vector is
3158             // allowed to do OSR entry. We start with the outermost loop and make our way inwards (hence why we
3159             // iterate the vector in reverse). Our policy is that we will trigger an outer loop to compile
3160             // immediately when program control reaches it. If program control is taking too long to reach that
3161             // outer loop, we progressively move inwards, meaning, we'll eventually trigger some loop that is
3162             // executing to compile. We start with trying to compile outer loops since we believe outer loop
3163             // compilations reveal the best opportunities for optimizing code.
3164             for (auto iter = tierUpHierarchyEntry->value.rbegin(), end = tierUpHierarchyEntry->value.rend(); iter != end; ++iter) {
3165                 unsigned osrEntryCandidate = *iter;
3166
3167                 if (jitCode->tierUpEntryTriggers.get(osrEntryCandidate) == JITCode::TriggerReason::StartCompilation) {
3168                     // This means that we already asked this loop to compile. If we've reached here, it
3169                     // means program control has not yet reached that loop. So it's taking too long to compile.
3170                     // So we move on to asking the inner loop of this loop to compile itself.
3171                     continue;
3172                 }
3173
3174                 // This is where we ask the outer to loop to immediately compile itself if program
3175                 // control reaches it.
3176                 if (Options::verboseOSR())
3177                     dataLog("Inner-loop bc#", originBytecodeIndex, " in ", *codeBlock, " setting parent loop bc#", osrEntryCandidate, "'s trigger and backing off.\n");
3178                 jitCode->tierUpEntryTriggers.set(osrEntryCandidate, JITCode::TriggerReason::StartCompilation);
3179                 return true;
3180             }
3181
3182             return false;
3183         };
3184
3185         if (tryTriggerOuterLoopToCompile()) {
3186             jitCode->setOptimizationThresholdBasedOnCompilationResult(codeBlock, CompilationDeferred);
3187             return nullptr;
3188         }
3189     }
3190
3191     if (!canOSREnterHere) {
3192         jitCode->setOptimizationThresholdBasedOnCompilationResult(codeBlock, CompilationDeferred);
3193         return nullptr;
3194     }
3195
3196     // We aren't compiling and haven't compiled anything for OSR entry. So, try to compile
3197     // something.
3198
3199     auto triggerIterator = jitCode->tierUpEntryTriggers.find(originBytecodeIndex);
3200     if (triggerIterator == jitCode->tierUpEntryTriggers.end()) {
3201         jitCode->setOptimizationThresholdBasedOnCompilationResult(codeBlock, CompilationDeferred);
3202         return nullptr;
3203     }
3204
3205     JITCode::TriggerReason* triggerAddress = &(triggerIterator->value);
3206
3207     Operands<JSValue> mustHandleValues;
3208     unsigned streamIndex = jitCode->bytecodeIndexToStreamIndex.get(originBytecodeIndex);
3209     jitCode->reconstruct(
3210         exec, codeBlock, CodeOrigin(originBytecodeIndex), streamIndex, mustHandleValues);
3211     CodeBlock* replacementCodeBlock = codeBlock->newReplacement();
3212
3213     CODEBLOCK_LOG_EVENT(codeBlock, "triggerFTLOSR", ());
3214     CompilationResult forEntryResult = compile(
3215         *vm, replacementCodeBlock, codeBlock, FTLForOSREntryMode, originBytecodeIndex,
3216         mustHandleValues, ToFTLForOSREntryDeferredCompilationCallback::create(triggerAddress));
3217
3218     if (jitCode->neverExecutedEntry)
3219         triggerFTLReplacementCompile(vm, codeBlock, jitCode);
3220
3221     if (forEntryResult != CompilationSuccessful) {
3222         CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("OSR ecompilation not successful"));
3223         jitCode->setOptimizationThresholdBasedOnCompilationResult(
3224             codeBlock, CompilationDeferred);
3225         return nullptr;
3226     }
3227     
3228     CODEBLOCK_LOG_EVENT(jitCode->osrEntryBlock(), "osrEntry", ("at bc#", originBytecodeIndex));
3229     // It's possible that the for-entry compile already succeeded. In that case OSR
3230     // entry will succeed unless we ran out of stack. It's not clear what we should do.
3231     // We signal to try again after a while if that happens.
3232     if (Options::verboseOSR())
3233         dataLog("Immediate OSR entry: From ", RawPointer(jitCode), " got entry block ", RawPointer(jitCode->osrEntryBlock()), "\n");
3234
3235     void* address = FTL::prepareOSREntry(
3236         exec, codeBlock, jitCode->osrEntryBlock(), originBytecodeIndex, streamIndex);
3237     if (!address)
3238         return nullptr;
3239     return retagCodePtr<char*>(address, JSEntryPtrTag, bitwise_cast<PtrTag>(exec));
3240 }
3241
3242 void JIT_OPERATION triggerTierUpNowInLoop(ExecState* exec, unsigned bytecodeIndex)
3243 {
3244     VM* vm = &exec->vm();
3245     NativeCallFrameTracer tracer(vm, exec);
3246     DeferGCForAWhile deferGC(vm->heap);
3247     CodeBlock* codeBlock = exec->codeBlock();
3248
3249     sanitizeStackForVM(vm);
3250
3251     if (codeBlock->jitType() != JITCode::DFGJIT) {
3252         dataLog("Unexpected code block in DFG->FTL trigger tier up now in loop: ", *codeBlock, "\n");
3253         RELEASE_ASSERT_NOT_REACHED();
3254     }
3255
3256     JITCode* jitCode = codeBlock->jitCode()->dfg();
3257
3258     if (Options::verboseOSR()) {
3259         dataLog(
3260             *codeBlock, ": Entered triggerTierUpNowInLoop with executeCounter = ",
3261             jitCode->tierUpCounter, "\n");
3262     }
3263
3264     if (jitCode->tierUpInLoopHierarchy.contains(bytecodeIndex))
3265         tierUpCommon(exec, bytecodeIndex, false);
3266     else if (shouldTriggerFTLCompile(codeBlock, jitCode))
3267         triggerFTLReplacementCompile(vm, codeBlock, jitCode);
3268
3269     // Since we cannot OSR Enter here, the default "optimizeSoon()" is not useful.
3270     if (codeBlock->hasOptimizedReplacement()) {
3271         CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("OSR in loop failed, deferring"));
3272         jitCode->setOptimizationThresholdBasedOnCompilationResult(codeBlock, CompilationDeferred);
3273     }
3274 }
3275
3276 char* JIT_OPERATION triggerOSREntryNow(ExecState* exec, unsigned bytecodeIndex)
3277 {
3278     VM* vm = &exec->vm();
3279     NativeCallFrameTracer tracer(vm, exec);
3280     DeferGCForAWhile deferGC(vm->heap);
3281     CodeBlock* codeBlock = exec->codeBlock();
3282
3283     sanitizeStackForVM(vm);
3284
3285     if (codeBlock->jitType() != JITCode::DFGJIT) {
3286         dataLog("Unexpected code block in DFG->FTL tier-up: ", *codeBlock, "\n");
3287         RELEASE_ASSERT_NOT_REACHED();
3288     }
3289
3290     JITCode* jitCode = codeBlock->jitCode()->dfg();
3291     jitCode->tierUpEntrySeen.add(bytecodeIndex);
3292
3293     if (Options::verboseOSR()) {
3294         dataLog(
3295             *codeBlock, ": Entered triggerOSREntryNow with executeCounter = ",
3296             jitCode->tierUpCounter, "\n");
3297     }
3298
3299     return tierUpCommon(exec, bytecodeIndex, true);
3300 }
3301
3302 #endif // ENABLE(FTL_JIT)
3303
3304 } // extern "C"
3305 } } // namespace JSC::DFG
3306
3307 #endif // ENABLE(DFG_JIT)
3308
3309 #endif // ENABLE(JIT)