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