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