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