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