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