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