Unreviewed, rolling out r222380.
[WebKit-https.git] / Source / JavaScriptCore / dfg / DFGOperations.cpp
1 /*
2  * Copyright (C) 2011-2017 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 "JSCInlines.h"
53 #include "JSFixedArray.h"
54 #include "JSGenericTypedArrayViewConstructorInlines.h"
55 #include "JSLexicalEnvironment.h"
56 #include "JSMap.h"
57 #include "JSSet.h"
58 #include "JSWeakMap.h"
59 #include "ObjectConstructor.h"
60 #include "Operations.h"
61 #include "ParseInt.h"
62 #include "RegExpObject.h"
63 #include "Repatch.h"
64 #include "ScopedArguments.h"
65 #include "StringConstructor.h"
66 #include "SuperSampler.h"
67 #include "Symbol.h"
68 #include "TypeProfilerLog.h"
69 #include "TypedArrayInlines.h"
70 #include "VMInlines.h"
71 #include <wtf/InlineASM.h>
72
73 #if ENABLE(JIT)
74 #if ENABLE(DFG_JIT)
75
76 namespace JSC { namespace DFG {
77
78 template<bool strict, bool direct>
79 static inline void putByVal(ExecState* exec, VM& vm, JSValue baseValue, uint32_t index, JSValue value)
80 {
81     ASSERT(isIndex(index));
82     if (direct) {
83         RELEASE_ASSERT(baseValue.isObject());
84         asObject(baseValue)->putDirectIndex(exec, index, value, 0, strict ? PutDirectIndexShouldThrow : PutDirectIndexShouldNotThrow);
85         return;
86     }
87     if (baseValue.isObject()) {
88         JSObject* object = asObject(baseValue);
89         if (object->canSetIndexQuickly(index)) {
90             object->setIndexQuickly(vm, index, value);
91             return;
92         }
93
94         object->methodTable(vm)->putByIndex(object, exec, index, value, strict);
95         return;
96     }
97
98     baseValue.putByIndex(exec, index, value, strict);
99 }
100
101 template<bool strict, bool direct>
102 ALWAYS_INLINE static void putByValInternal(ExecState* exec, VM& vm, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
103 {
104     auto scope = DECLARE_THROW_SCOPE(vm);
105
106     JSValue baseValue = JSValue::decode(encodedBase);
107     JSValue property = JSValue::decode(encodedProperty);
108     JSValue value = JSValue::decode(encodedValue);
109
110     if (LIKELY(property.isUInt32())) {
111         // Despite its name, JSValue::isUInt32 will return true only for positive boxed int32_t; all those values are valid array indices.
112         ASSERT(isIndex(property.asUInt32()));
113         scope.release();
114         putByVal<strict, direct>(exec, vm, baseValue, property.asUInt32(), value);
115         return;
116     }
117
118     if (property.isDouble()) {
119         double propertyAsDouble = property.asDouble();
120         uint32_t propertyAsUInt32 = static_cast<uint32_t>(propertyAsDouble);
121         if (propertyAsDouble == propertyAsUInt32 && isIndex(propertyAsUInt32)) {
122             scope.release();
123             putByVal<strict, direct>(exec, vm, baseValue, propertyAsUInt32, value);
124             return;
125         }
126     }
127
128     // Don't put to an object if toString throws an exception.
129     auto propertyName = property.toPropertyKey(exec);
130     RETURN_IF_EXCEPTION(scope, void());
131
132     PutPropertySlot slot(baseValue, strict);
133     if (direct) {
134         RELEASE_ASSERT(baseValue.isObject());
135         if (std::optional<uint32_t> index = parseIndex(propertyName)) {
136             scope.release();
137             asObject(baseValue)->putDirectIndex(exec, index.value(), value, 0, strict ? PutDirectIndexShouldThrow : PutDirectIndexShouldNotThrow);
138             return;
139         }
140         asObject(baseValue)->putDirect(vm, propertyName, value, slot);
141         return;
142     }
143     scope.release();
144     baseValue.put(exec, propertyName, value, slot);
145 }
146
147 template<bool strict, bool direct>
148 ALWAYS_INLINE static void putByValCellInternal(ExecState* exec, VM& vm, JSCell* base, PropertyName propertyName, JSValue value)
149 {
150     PutPropertySlot slot(base, strict);
151     if (direct) {
152         RELEASE_ASSERT(base->isObject());
153         if (std::optional<uint32_t> index = parseIndex(propertyName))
154             asObject(base)->putDirectIndex(exec, index.value(), value, 0, strict ? PutDirectIndexShouldThrow : PutDirectIndexShouldNotThrow);
155         else
156             asObject(base)->putDirect(vm, propertyName, value, slot);
157         return;
158     }
159     base->putInline(exec, propertyName, value, slot);
160 }
161
162 template<bool strict, bool direct>
163 ALWAYS_INLINE static void putByValCellStringInternal(ExecState* exec, VM& vm, JSCell* base, JSString* property, JSValue value)
164 {
165     auto scope = DECLARE_THROW_SCOPE(vm);
166
167     auto propertyName = property->toIdentifier(exec);
168     RETURN_IF_EXCEPTION(scope, void());
169
170     scope.release();
171     putByValCellInternal<strict, direct>(exec, vm, base, propertyName, value);
172 }
173
174 template<typename ViewClass>
175 char* newTypedArrayWithSize(ExecState* exec, Structure* structure, int32_t size, char* vector)
176 {
177     VM& vm = exec->vm();
178     NativeCallFrameTracer tracer(&vm, exec);
179     auto scope = DECLARE_THROW_SCOPE(vm);
180
181     if (size < 0) {
182         throwException(exec, scope, createRangeError(exec, ASCIILiteral("Requested length is negative")));
183         return 0;
184     }
185     
186     if (vector)
187         return bitwise_cast<char*>(ViewClass::createWithFastVector(exec, structure, size, vector));
188
189     scope.release();
190     return bitwise_cast<char*>(ViewClass::create(exec, structure, size));
191 }
192
193 template <bool strict>
194 static ALWAYS_INLINE void putWithThis(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedThis, EncodedJSValue encodedValue, const Identifier& ident)
195 {
196     JSValue baseValue = JSValue::decode(encodedBase);
197     JSValue thisVal = JSValue::decode(encodedThis);
198     JSValue putValue = JSValue::decode(encodedValue);
199     PutPropertySlot slot(thisVal, strict);
200     baseValue.putInline(exec, ident, putValue, slot);
201 }
202
203 static ALWAYS_INLINE EncodedJSValue parseIntResult(double input)
204 {
205     int asInt = static_cast<int>(input);
206     if (static_cast<double>(asInt) == input)
207         return JSValue::encode(jsNumber(asInt));
208     return JSValue::encode(jsNumber(input));
209 }
210
211 ALWAYS_INLINE static JSValue getByValObject(ExecState* exec, VM& vm, JSObject* base, PropertyName propertyName)
212 {
213     Structure& structure = *base->structure(vm);
214     if (JSCell::canUseFastGetOwnProperty(structure)) {
215         if (JSValue result = base->fastGetOwnProperty(vm, structure, propertyName))
216             return result;
217     }
218     return base->get(exec, propertyName);
219 }
220
221 extern "C" {
222
223 EncodedJSValue JIT_OPERATION operationToThis(ExecState* exec, EncodedJSValue encodedOp)
224 {
225     VM* vm = &exec->vm();
226     NativeCallFrameTracer tracer(vm, exec);
227
228     return JSValue::encode(JSValue::decode(encodedOp).toThis(exec, NotStrictMode));
229 }
230
231 EncodedJSValue JIT_OPERATION operationToThisStrict(ExecState* exec, EncodedJSValue encodedOp)
232 {
233     VM* vm = &exec->vm();
234     NativeCallFrameTracer tracer(vm, exec);
235
236     return JSValue::encode(JSValue::decode(encodedOp).toThis(exec, StrictMode));
237 }
238
239 JSCell* JIT_OPERATION operationCreateThis(ExecState* exec, JSObject* constructor, int32_t inlineCapacity)
240 {
241     VM& vm = exec->vm();
242     NativeCallFrameTracer tracer(&vm, exec);
243     auto scope = DECLARE_THROW_SCOPE(vm);
244     if (constructor->type() == JSFunctionType) {
245         auto rareData = jsCast<JSFunction*>(constructor)->rareData(exec, inlineCapacity);
246         RETURN_IF_EXCEPTION(scope, nullptr);
247         return constructEmptyObject(exec, rareData->objectAllocationProfile()->structure());
248     }
249
250     JSValue proto = constructor->get(exec, vm.propertyNames->prototype);
251     RETURN_IF_EXCEPTION(scope, nullptr);
252     if (proto.isObject())
253         return constructEmptyObject(exec, asObject(proto));
254     return constructEmptyObject(exec);
255 }
256
257 JSCell* JIT_OPERATION operationObjectConstructor(ExecState* exec, JSGlobalObject* globalObject, EncodedJSValue encodedTarget)
258 {
259     VM* vm = &exec->vm();
260     NativeCallFrameTracer tracer(vm, exec);
261
262     JSValue value = JSValue::decode(encodedTarget);
263     ASSERT(!value.isObject());
264
265     if (value.isUndefinedOrNull())
266         return constructEmptyObject(exec, globalObject->objectPrototype());
267     return value.toObject(exec, globalObject);
268 }
269
270 EncodedJSValue JIT_OPERATION operationValueBitAnd(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
271 {
272     VM* vm = &exec->vm();
273     NativeCallFrameTracer tracer(vm, exec);
274     auto scope = DECLARE_THROW_SCOPE(*vm);
275
276     JSValue op1 = JSValue::decode(encodedOp1);
277     JSValue op2 = JSValue::decode(encodedOp2);
278
279     int32_t a = op1.toInt32(exec);
280     RETURN_IF_EXCEPTION(scope, encodedJSValue());
281     scope.release();
282     int32_t b = op2.toInt32(exec);
283     return JSValue::encode(jsNumber(a & b));
284 }
285
286 EncodedJSValue JIT_OPERATION operationValueBitOr(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
287 {
288     VM* vm = &exec->vm();
289     NativeCallFrameTracer tracer(vm, exec);
290     auto scope = DECLARE_THROW_SCOPE(*vm);
291
292     JSValue op1 = JSValue::decode(encodedOp1);
293     JSValue op2 = JSValue::decode(encodedOp2);
294
295     int32_t a = op1.toInt32(exec);
296     RETURN_IF_EXCEPTION(scope, encodedJSValue());
297     scope.release();
298     int32_t b = op2.toInt32(exec);
299     return JSValue::encode(jsNumber(a | b));
300 }
301
302 EncodedJSValue JIT_OPERATION operationValueBitXor(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
303 {
304     VM* vm = &exec->vm();
305     NativeCallFrameTracer tracer(vm, exec);
306     auto scope = DECLARE_THROW_SCOPE(*vm);
307
308     JSValue op1 = JSValue::decode(encodedOp1);
309     JSValue op2 = JSValue::decode(encodedOp2);
310
311     int32_t a = op1.toInt32(exec);
312     RETURN_IF_EXCEPTION(scope, encodedJSValue());
313     scope.release();
314     int32_t b = op2.toInt32(exec);
315     return JSValue::encode(jsNumber(a ^ b));
316 }
317
318 EncodedJSValue JIT_OPERATION operationValueBitLShift(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
319 {
320     VM* vm = &exec->vm();
321     NativeCallFrameTracer tracer(vm, exec);
322     auto scope = DECLARE_THROW_SCOPE(*vm);
323
324     JSValue op1 = JSValue::decode(encodedOp1);
325     JSValue op2 = JSValue::decode(encodedOp2);
326
327     int32_t a = op1.toInt32(exec);
328     RETURN_IF_EXCEPTION(scope, encodedJSValue());
329     scope.release();
330     uint32_t b = op2.toUInt32(exec);
331     return JSValue::encode(jsNumber(a << (b & 0x1f)));
332 }
333
334 EncodedJSValue JIT_OPERATION operationValueBitRShift(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
335 {
336     VM* vm = &exec->vm();
337     NativeCallFrameTracer tracer(vm, exec);
338     auto scope = DECLARE_THROW_SCOPE(*vm);
339
340     JSValue op1 = JSValue::decode(encodedOp1);
341     JSValue op2 = JSValue::decode(encodedOp2);
342
343     int32_t a = op1.toInt32(exec);
344     RETURN_IF_EXCEPTION(scope, encodedJSValue());
345     scope.release();
346     uint32_t b = op2.toUInt32(exec);
347     return JSValue::encode(jsNumber(a >> (b & 0x1f)));
348 }
349
350 EncodedJSValue JIT_OPERATION operationValueBitURShift(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
351 {
352     VM* vm = &exec->vm();
353     NativeCallFrameTracer tracer(vm, exec);
354     auto scope = DECLARE_THROW_SCOPE(*vm);
355
356     JSValue op1 = JSValue::decode(encodedOp1);
357     JSValue op2 = JSValue::decode(encodedOp2);
358
359     uint32_t a = op1.toUInt32(exec);
360     RETURN_IF_EXCEPTION(scope, encodedJSValue());
361     scope.release();
362     uint32_t b = op2.toUInt32(exec);
363     return JSValue::encode(jsNumber(static_cast<int32_t>(a >> (b & 0x1f))));
364 }
365
366 EncodedJSValue JIT_OPERATION operationValueAddNotNumber(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
367 {
368     VM* vm = &exec->vm();
369     NativeCallFrameTracer tracer(vm, exec);
370     
371     JSValue op1 = JSValue::decode(encodedOp1);
372     JSValue op2 = JSValue::decode(encodedOp2);
373     
374     ASSERT(!op1.isNumber() || !op2.isNumber());
375     
376     if (op1.isString() && !op2.isObject())
377         return JSValue::encode(jsString(exec, asString(op1), op2.toString(exec)));
378
379     return JSValue::encode(jsAddSlowCase(exec, op1, op2));
380 }
381
382 EncodedJSValue JIT_OPERATION operationValueDiv(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
383 {
384     VM* vm = &exec->vm();
385     NativeCallFrameTracer tracer(vm, exec);
386     auto scope = DECLARE_THROW_SCOPE(*vm);
387
388     JSValue op1 = JSValue::decode(encodedOp1);
389     JSValue op2 = JSValue::decode(encodedOp2);
390
391     double a = op1.toNumber(exec);
392     RETURN_IF_EXCEPTION(scope, encodedJSValue());
393     scope.release();
394     double b = op2.toNumber(exec);
395     return JSValue::encode(jsNumber(a / b));
396 }
397
398 double JIT_OPERATION operationArithAbs(ExecState* exec, EncodedJSValue encodedOp1)
399 {
400     VM* vm = &exec->vm();
401     NativeCallFrameTracer tracer(vm, exec);
402     auto scope = DECLARE_THROW_SCOPE(*vm);
403
404     JSValue op1 = JSValue::decode(encodedOp1);
405     double a = op1.toNumber(exec);
406     RETURN_IF_EXCEPTION(scope, PNaN);
407     return fabs(a);
408 }
409
410 int32_t JIT_OPERATION operationArithClz32(ExecState* exec, EncodedJSValue encodedOp1)
411 {
412     VM* vm = &exec->vm();
413     NativeCallFrameTracer tracer(vm, exec);
414     auto scope = DECLARE_THROW_SCOPE(*vm);
415
416     JSValue op1 = JSValue::decode(encodedOp1);
417     uint32_t value = op1.toUInt32(exec);
418     RETURN_IF_EXCEPTION(scope, 0);
419     return clz32(value);
420 }
421
422 double JIT_OPERATION operationArithFRound(ExecState* exec, EncodedJSValue encodedOp1)
423 {
424     VM* vm = &exec->vm();
425     NativeCallFrameTracer tracer(vm, exec);
426     auto scope = DECLARE_THROW_SCOPE(*vm);
427
428     JSValue op1 = JSValue::decode(encodedOp1);
429     double a = op1.toNumber(exec);
430     RETURN_IF_EXCEPTION(scope, PNaN);
431     return static_cast<float>(a);
432 }
433
434 #define DFG_ARITH_UNARY(capitalizedName, lowerName) \
435 double JIT_OPERATION operationArith##capitalizedName(ExecState* exec, EncodedJSValue encodedOp1) \
436 { \
437     VM* vm = &exec->vm(); \
438     NativeCallFrameTracer tracer(vm, exec); \
439     auto scope = DECLARE_THROW_SCOPE(*vm); \
440     JSValue op1 = JSValue::decode(encodedOp1); \
441     double result = op1.toNumber(exec); \
442     RETURN_IF_EXCEPTION(scope, PNaN); \
443     return JSC::Math::lowerName(result); \
444 }
445     FOR_EACH_DFG_ARITH_UNARY_OP(DFG_ARITH_UNARY)
446 #undef DFG_ARITH_UNARY
447
448 double JIT_OPERATION operationArithSqrt(ExecState* exec, EncodedJSValue encodedOp1)
449 {
450     VM* vm = &exec->vm();
451     NativeCallFrameTracer tracer(vm, exec);
452     auto scope = DECLARE_THROW_SCOPE(*vm);
453
454     JSValue op1 = JSValue::decode(encodedOp1);
455     double a = op1.toNumber(exec);
456     RETURN_IF_EXCEPTION(scope, PNaN);
457     return sqrt(a);
458 }
459
460 EncodedJSValue JIT_OPERATION operationArithRound(ExecState* exec, EncodedJSValue encodedArgument)
461 {
462     VM* vm = &exec->vm();
463     NativeCallFrameTracer tracer(vm, exec);
464     auto scope = DECLARE_THROW_SCOPE(*vm);
465
466     JSValue argument = JSValue::decode(encodedArgument);
467     double valueOfArgument = argument.toNumber(exec);
468     RETURN_IF_EXCEPTION(scope, encodedJSValue());
469     return JSValue::encode(jsNumber(jsRound(valueOfArgument)));
470 }
471
472 EncodedJSValue JIT_OPERATION operationArithFloor(ExecState* exec, EncodedJSValue encodedArgument)
473 {
474     VM* vm = &exec->vm();
475     NativeCallFrameTracer tracer(vm, exec);
476     auto scope = DECLARE_THROW_SCOPE(*vm);
477
478     JSValue argument = JSValue::decode(encodedArgument);
479     double valueOfArgument = argument.toNumber(exec);
480     RETURN_IF_EXCEPTION(scope, encodedJSValue());
481     return JSValue::encode(jsNumber(floor(valueOfArgument)));
482 }
483
484 EncodedJSValue JIT_OPERATION operationArithCeil(ExecState* exec, EncodedJSValue encodedArgument)
485 {
486     VM* vm = &exec->vm();
487     NativeCallFrameTracer tracer(vm, exec);
488     auto scope = DECLARE_THROW_SCOPE(*vm);
489
490     JSValue argument = JSValue::decode(encodedArgument);
491     double valueOfArgument = argument.toNumber(exec);
492     RETURN_IF_EXCEPTION(scope, encodedJSValue());
493     return JSValue::encode(jsNumber(ceil(valueOfArgument)));
494 }
495
496 EncodedJSValue JIT_OPERATION operationArithTrunc(ExecState* exec, EncodedJSValue encodedArgument)
497 {
498     VM* vm = &exec->vm();
499     NativeCallFrameTracer tracer(vm, exec);
500     auto scope = DECLARE_THROW_SCOPE(*vm);
501
502     JSValue argument = JSValue::decode(encodedArgument);
503     double truncatedValueOfArgument = argument.toIntegerPreserveNaN(exec);
504     RETURN_IF_EXCEPTION(scope, encodedJSValue());
505     return JSValue::encode(jsNumber(truncatedValueOfArgument));
506 }
507
508 static ALWAYS_INLINE EncodedJSValue getByVal(ExecState* exec, JSCell* base, uint32_t index)
509 {
510     VM& vm = exec->vm();
511     NativeCallFrameTracer tracer(&vm, exec);
512     
513     if (base->isObject()) {
514         JSObject* object = asObject(base);
515         if (object->canGetIndexQuickly(index))
516             return JSValue::encode(object->getIndexQuickly(index));
517     }
518
519     if (isJSString(base) && asString(base)->canGetIndex(index))
520         return JSValue::encode(asString(base)->getIndex(exec, index));
521
522     return JSValue::encode(JSValue(base).get(exec, index));
523 }
524
525 EncodedJSValue JIT_OPERATION operationGetByVal(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty)
526 {
527     VM& vm = exec->vm();
528     NativeCallFrameTracer tracer(&vm, exec);
529     auto scope = DECLARE_THROW_SCOPE(vm);
530
531     JSValue baseValue = JSValue::decode(encodedBase);
532     JSValue property = JSValue::decode(encodedProperty);
533
534     if (LIKELY(baseValue.isCell())) {
535         JSCell* base = baseValue.asCell();
536
537         if (property.isUInt32()) {
538             scope.release();
539             return getByVal(exec, base, property.asUInt32());
540         }
541         if (property.isDouble()) {
542             double propertyAsDouble = property.asDouble();
543             uint32_t propertyAsUInt32 = static_cast<uint32_t>(propertyAsDouble);
544             if (propertyAsUInt32 == propertyAsDouble && isIndex(propertyAsUInt32)) {
545                 scope.release();
546                 return getByVal(exec, base, propertyAsUInt32);
547             }
548         } else if (property.isString()) {
549             Structure& structure = *base->structure(vm);
550             if (JSCell::canUseFastGetOwnProperty(structure)) {
551                 if (RefPtr<AtomicStringImpl> existingAtomicString = asString(property)->toExistingAtomicString(exec)) {
552                     if (JSValue result = base->fastGetOwnProperty(vm, structure, existingAtomicString.get()))
553                         return JSValue::encode(result);
554                 }
555             }
556         }
557     }
558
559     baseValue.requireObjectCoercible(exec);
560     RETURN_IF_EXCEPTION(scope, encodedJSValue());
561     auto propertyName = property.toPropertyKey(exec);
562     RETURN_IF_EXCEPTION(scope, encodedJSValue());
563     scope.release();
564     return JSValue::encode(baseValue.get(exec, propertyName));
565 }
566
567 EncodedJSValue JIT_OPERATION operationGetByValCell(ExecState* exec, JSCell* base, EncodedJSValue encodedProperty)
568 {
569     VM& vm = exec->vm();
570     NativeCallFrameTracer tracer(&vm, exec);
571     auto scope = DECLARE_THROW_SCOPE(vm);
572
573     JSValue property = JSValue::decode(encodedProperty);
574
575     if (property.isUInt32()) {
576         scope.release();
577         return getByVal(exec, base, property.asUInt32());
578     }
579     if (property.isDouble()) {
580         double propertyAsDouble = property.asDouble();
581         uint32_t propertyAsUInt32 = static_cast<uint32_t>(propertyAsDouble);
582         if (propertyAsUInt32 == propertyAsDouble) {
583             scope.release();
584             return getByVal(exec, base, propertyAsUInt32);
585         }
586     } else if (property.isString()) {
587         Structure& structure = *base->structure(vm);
588         if (JSCell::canUseFastGetOwnProperty(structure)) {
589             if (RefPtr<AtomicStringImpl> existingAtomicString = asString(property)->toExistingAtomicString(exec)) {
590                 if (JSValue result = base->fastGetOwnProperty(vm, structure, existingAtomicString.get()))
591                     return JSValue::encode(result);
592             }
593         }
594     }
595
596     auto propertyName = property.toPropertyKey(exec);
597     RETURN_IF_EXCEPTION(scope, encodedJSValue());
598     scope.release();
599     return JSValue::encode(JSValue(base).get(exec, propertyName));
600 }
601
602 ALWAYS_INLINE EncodedJSValue getByValCellInt(ExecState* exec, JSCell* base, int32_t index)
603 {
604     VM* vm = &exec->vm();
605     NativeCallFrameTracer tracer(vm, exec);
606     
607     if (index < 0) {
608         // Go the slowest way possible becase negative indices don't use indexed storage.
609         return JSValue::encode(JSValue(base).get(exec, Identifier::from(exec, index)));
610     }
611
612     // Use this since we know that the value is out of bounds.
613     return JSValue::encode(JSValue(base).get(exec, static_cast<unsigned>(index)));
614 }
615
616 EncodedJSValue JIT_OPERATION operationGetByValObjectInt(ExecState* exec, JSObject* base, int32_t index)
617 {
618     return getByValCellInt(exec, base, index);
619 }
620
621 EncodedJSValue JIT_OPERATION operationGetByValStringInt(ExecState* exec, JSString* base, int32_t index)
622 {
623     return getByValCellInt(exec, base, index);
624 }
625
626 EncodedJSValue JIT_OPERATION operationGetByValObjectString(ExecState* exec, JSCell* base, JSCell* string)
627 {
628     VM& vm = exec->vm();
629     NativeCallFrameTracer tracer(&vm, exec);
630
631     auto scope = DECLARE_THROW_SCOPE(vm);
632
633     auto propertyName = asString(string)->toIdentifier(exec);
634     RETURN_IF_EXCEPTION(scope, encodedJSValue());
635
636     scope.release();
637     return JSValue::encode(getByValObject(exec, vm, asObject(base), propertyName));
638 }
639
640 EncodedJSValue JIT_OPERATION operationGetByValObjectSymbol(ExecState* exec, JSCell* base, JSCell* symbol)
641 {
642     VM& vm = exec->vm();
643     NativeCallFrameTracer tracer(&vm, exec);
644
645     return JSValue::encode(getByValObject(exec, vm, asObject(base), asSymbol(symbol)->privateName()));
646 }
647
648 void JIT_OPERATION operationPutByValStrict(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
649 {
650     VM& vm = exec->vm();
651     NativeCallFrameTracer tracer(&vm, exec);
652     
653     putByValInternal<true, false>(exec, vm, encodedBase, encodedProperty, encodedValue);
654 }
655
656 void JIT_OPERATION operationPutByValNonStrict(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
657 {
658     VM& vm = exec->vm();
659     NativeCallFrameTracer tracer(&vm, exec);
660     
661     putByValInternal<false, false>(exec, vm, encodedBase, encodedProperty, encodedValue);
662 }
663
664 void JIT_OPERATION operationPutByValCellStrict(ExecState* exec, JSCell* cell, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
665 {
666     VM& vm = exec->vm();
667     NativeCallFrameTracer tracer(&vm, exec);
668     
669     putByValInternal<true, false>(exec, vm, JSValue::encode(cell), encodedProperty, encodedValue);
670 }
671
672 void JIT_OPERATION operationPutByValCellNonStrict(ExecState* exec, JSCell* cell, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
673 {
674     VM& vm = exec->vm();
675     NativeCallFrameTracer tracer(&vm, exec);
676     
677     putByValInternal<false, false>(exec, vm, JSValue::encode(cell), encodedProperty, encodedValue);
678 }
679
680 void JIT_OPERATION operationPutByValCellStringStrict(ExecState* exec, JSCell* cell, JSCell* string, EncodedJSValue encodedValue)
681 {
682     VM& vm = exec->vm();
683     NativeCallFrameTracer tracer(&vm, exec);
684
685     putByValCellStringInternal<true, false>(exec, vm, cell, asString(string), JSValue::decode(encodedValue));
686 }
687
688 void JIT_OPERATION operationPutByValCellStringNonStrict(ExecState* exec, JSCell* cell, JSCell* string, EncodedJSValue encodedValue)
689 {
690     VM& vm = exec->vm();
691     NativeCallFrameTracer tracer(&vm, exec);
692
693     putByValCellStringInternal<false, false>(exec, vm, cell, asString(string), JSValue::decode(encodedValue));
694 }
695
696 void JIT_OPERATION operationPutByValCellSymbolStrict(ExecState* exec, JSCell* cell, JSCell* symbol, EncodedJSValue encodedValue)
697 {
698     VM& vm = exec->vm();
699     NativeCallFrameTracer tracer(&vm, exec);
700
701     putByValCellInternal<true, false>(exec, vm, cell, asSymbol(symbol)->privateName(), JSValue::decode(encodedValue));
702 }
703
704 void JIT_OPERATION operationPutByValCellSymbolNonStrict(ExecState* exec, JSCell* cell, JSCell* symbol, EncodedJSValue encodedValue)
705 {
706     VM& vm = exec->vm();
707     NativeCallFrameTracer tracer(&vm, exec);
708
709     putByValCellInternal<false, false>(exec, vm, cell, asSymbol(symbol)->privateName(), JSValue::decode(encodedValue));
710 }
711
712 void JIT_OPERATION operationPutByValBeyondArrayBoundsStrict(ExecState* exec, JSObject* array, int32_t index, EncodedJSValue encodedValue)
713 {
714     VM& vm = exec->vm();
715     NativeCallFrameTracer tracer(&vm, exec);
716     
717     if (index >= 0) {
718         array->putByIndexInline(exec, index, JSValue::decode(encodedValue), true);
719         return;
720     }
721     
722     PutPropertySlot slot(array, true);
723     array->methodTable(vm)->put(
724         array, exec, Identifier::from(exec, index), JSValue::decode(encodedValue), slot);
725 }
726
727 void JIT_OPERATION operationPutByValBeyondArrayBoundsNonStrict(ExecState* exec, JSObject* array, int32_t index, EncodedJSValue encodedValue)
728 {
729     VM* vm = &exec->vm();
730     NativeCallFrameTracer tracer(vm, exec);
731     
732     if (index >= 0) {
733         array->putByIndexInline(exec, index, JSValue::decode(encodedValue), false);
734         return;
735     }
736     
737     PutPropertySlot slot(array, false);
738     array->methodTable(*vm)->put(
739         array, exec, Identifier::from(exec, index), JSValue::decode(encodedValue), slot);
740 }
741
742 void JIT_OPERATION operationPutDoubleByValBeyondArrayBoundsStrict(ExecState* exec, JSObject* array, int32_t index, double value)
743 {
744     VM* vm = &exec->vm();
745     NativeCallFrameTracer tracer(vm, exec);
746     
747     JSValue jsValue = JSValue(JSValue::EncodeAsDouble, value);
748     
749     if (index >= 0) {
750         array->putByIndexInline(exec, index, jsValue, true);
751         return;
752     }
753     
754     PutPropertySlot slot(array, true);
755     array->methodTable(*vm)->put(
756         array, exec, Identifier::from(exec, index), jsValue, slot);
757 }
758
759 void JIT_OPERATION operationPutDoubleByValBeyondArrayBoundsNonStrict(ExecState* exec, JSObject* array, int32_t index, double value)
760 {
761     VM* vm = &exec->vm();
762     NativeCallFrameTracer tracer(vm, exec);
763     
764     JSValue jsValue = JSValue(JSValue::EncodeAsDouble, value);
765     
766     if (index >= 0) {
767         array->putByIndexInline(exec, index, jsValue, false);
768         return;
769     }
770     
771     PutPropertySlot slot(array, false);
772     array->methodTable(*vm)->put(
773         array, exec, Identifier::from(exec, index), jsValue, slot);
774 }
775
776 void JIT_OPERATION operationPutByValDirectStrict(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
777 {
778     VM& vm = exec->vm();
779     NativeCallFrameTracer tracer(&vm, exec);
780     
781     putByValInternal<true, true>(exec, vm, encodedBase, encodedProperty, encodedValue);
782 }
783
784 void JIT_OPERATION operationPutByValDirectNonStrict(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
785 {
786     VM& vm = exec->vm();
787     NativeCallFrameTracer tracer(&vm, exec);
788     
789     putByValInternal<false, true>(exec, vm, encodedBase, encodedProperty, encodedValue);
790 }
791
792 void JIT_OPERATION operationPutByValDirectCellStrict(ExecState* exec, JSCell* cell, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
793 {
794     VM& vm = exec->vm();
795     NativeCallFrameTracer tracer(&vm, exec);
796     
797     putByValInternal<true, true>(exec, vm, JSValue::encode(cell), encodedProperty, encodedValue);
798 }
799
800 void JIT_OPERATION operationPutByValDirectCellNonStrict(ExecState* exec, JSCell* cell, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
801 {
802     VM& vm = exec->vm();
803     NativeCallFrameTracer tracer(&vm, exec);
804     
805     putByValInternal<false, true>(exec, vm, JSValue::encode(cell), encodedProperty, encodedValue);
806 }
807
808 void JIT_OPERATION operationPutByValDirectCellStringStrict(ExecState* exec, JSCell* cell, JSCell* string, EncodedJSValue encodedValue)
809 {
810     VM& vm = exec->vm();
811     NativeCallFrameTracer tracer(&vm, exec);
812
813     putByValCellStringInternal<true, true>(exec, vm, cell, asString(string), JSValue::decode(encodedValue));
814 }
815
816 void JIT_OPERATION operationPutByValDirectCellStringNonStrict(ExecState* exec, JSCell* cell, JSCell* string, EncodedJSValue encodedValue)
817 {
818     VM& vm = exec->vm();
819     NativeCallFrameTracer tracer(&vm, exec);
820
821     putByValCellStringInternal<false, true>(exec, vm, cell, asString(string), JSValue::decode(encodedValue));
822 }
823
824 void JIT_OPERATION operationPutByValDirectCellSymbolStrict(ExecState* exec, JSCell* cell, JSCell* symbol, EncodedJSValue encodedValue)
825 {
826     VM& vm = exec->vm();
827     NativeCallFrameTracer tracer(&vm, exec);
828
829     putByValCellInternal<true, true>(exec, vm, cell, asSymbol(symbol)->privateName(), JSValue::decode(encodedValue));
830 }
831
832 void JIT_OPERATION operationPutByValDirectCellSymbolNonStrict(ExecState* exec, JSCell* cell, JSCell* symbol, EncodedJSValue encodedValue)
833 {
834     VM& vm = exec->vm();
835     NativeCallFrameTracer tracer(&vm, exec);
836
837     putByValCellInternal<false, true>(exec, vm, cell, asSymbol(symbol)->privateName(), JSValue::decode(encodedValue));
838 }
839
840 void JIT_OPERATION operationPutByValDirectBeyondArrayBoundsStrict(ExecState* exec, JSObject* array, int32_t index, EncodedJSValue encodedValue)
841 {
842     VM& vm = exec->vm();
843     NativeCallFrameTracer tracer(&vm, exec);
844     if (index >= 0) {
845         array->putDirectIndex(exec, index, JSValue::decode(encodedValue), 0, PutDirectIndexShouldThrow);
846         return;
847     }
848     
849     PutPropertySlot slot(array, true);
850     array->putDirect(vm, Identifier::from(exec, index), JSValue::decode(encodedValue), slot);
851 }
852
853 void JIT_OPERATION operationPutByValDirectBeyondArrayBoundsNonStrict(ExecState* exec, JSObject* array, int32_t index, EncodedJSValue encodedValue)
854 {
855     VM& vm = exec->vm();
856     NativeCallFrameTracer tracer(&vm, exec);
857     
858     if (index >= 0) {
859         array->putDirectIndex(exec, index, JSValue::decode(encodedValue));
860         return;
861     }
862     
863     PutPropertySlot slot(array, false);
864     array->putDirect(vm, Identifier::from(exec, index), JSValue::decode(encodedValue), slot);
865 }
866
867 EncodedJSValue JIT_OPERATION operationArrayPush(ExecState* exec, EncodedJSValue encodedValue, JSArray* array)
868 {
869     VM* vm = &exec->vm();
870     NativeCallFrameTracer tracer(vm, exec);
871     
872     array->push(exec, JSValue::decode(encodedValue));
873     return JSValue::encode(jsNumber(array->length()));
874 }
875
876 EncodedJSValue JIT_OPERATION operationArrayPushDouble(ExecState* exec, double value, JSArray* array)
877 {
878     VM* vm = &exec->vm();
879     NativeCallFrameTracer tracer(vm, exec);
880     
881     array->push(exec, JSValue(JSValue::EncodeAsDouble, value));
882     return JSValue::encode(jsNumber(array->length()));
883 }
884
885 EncodedJSValue JIT_OPERATION operationArrayPop(ExecState* exec, JSArray* array)
886 {
887     VM* vm = &exec->vm();
888     NativeCallFrameTracer tracer(vm, exec);
889     
890     return JSValue::encode(array->pop(exec));
891 }
892         
893 EncodedJSValue JIT_OPERATION operationArrayPopAndRecoverLength(ExecState* exec, JSArray* array)
894 {
895     VM* vm = &exec->vm();
896     NativeCallFrameTracer tracer(vm, exec);
897     
898     array->butterfly()->setPublicLength(array->butterfly()->publicLength() + 1);
899     
900     return JSValue::encode(array->pop(exec));
901 }
902         
903 EncodedJSValue JIT_OPERATION operationRegExpExecString(ExecState* exec, JSGlobalObject* globalObject, RegExpObject* regExpObject, JSString* argument)
904 {
905     SuperSamplerScope superSamplerScope(false);
906     
907     VM& vm = globalObject->vm();
908     NativeCallFrameTracer tracer(&vm, exec);
909     
910     return JSValue::encode(regExpObject->execInline(exec, globalObject, argument));
911 }
912         
913 EncodedJSValue JIT_OPERATION operationRegExpExec(ExecState* exec, JSGlobalObject* globalObject, RegExpObject* regExpObject, EncodedJSValue encodedArgument)
914 {
915     SuperSamplerScope superSamplerScope(false);
916     
917     VM& vm = globalObject->vm();
918     NativeCallFrameTracer tracer(&vm, exec);
919     auto scope = DECLARE_THROW_SCOPE(vm);
920     
921     JSValue argument = JSValue::decode(encodedArgument);
922
923     JSString* input = argument.toStringOrNull(exec);
924     EXCEPTION_ASSERT(!!scope.exception() == !input);
925     if (!input)
926         return encodedJSValue();
927     scope.release();
928     return JSValue::encode(regExpObject->execInline(exec, globalObject, input));
929 }
930         
931 EncodedJSValue JIT_OPERATION operationRegExpExecGeneric(ExecState* exec, JSGlobalObject* globalObject, EncodedJSValue encodedBase, EncodedJSValue encodedArgument)
932 {
933     SuperSamplerScope superSamplerScope(false);
934     
935     VM& vm = globalObject->vm();
936     NativeCallFrameTracer tracer(&vm, exec);
937     auto scope = DECLARE_THROW_SCOPE(vm);
938
939     JSValue base = JSValue::decode(encodedBase);
940     JSValue argument = JSValue::decode(encodedArgument);
941     
942     if (!base.inherits(vm, RegExpObject::info()))
943         return throwVMTypeError(exec, scope);
944
945     JSString* input = argument.toStringOrNull(exec);
946     EXCEPTION_ASSERT(!!scope.exception() == !input);
947     if (!input)
948         return JSValue::encode(jsUndefined());
949     scope.release();
950     return JSValue::encode(asRegExpObject(base)->exec(exec, globalObject, input));
951 }
952
953 EncodedJSValue JIT_OPERATION operationWeakMapGet(ExecState* exec, JSCell* weakMap, JSCell* object, int32_t hash)
954 {
955     VM& vm = exec->vm();
956     NativeCallFrameTracer tracer(&vm, exec);
957     return JSValue::encode(jsCast<JSWeakMap*>(weakMap)->inlineGet(asObject(object), hash));
958 }
959
960 EncodedJSValue JIT_OPERATION operationParseIntNoRadixGeneric(ExecState* exec, EncodedJSValue value)
961 {
962     VM& vm = exec->vm();
963     NativeCallFrameTracer tracer(&vm, exec);
964
965     return toStringView(exec, JSValue::decode(value), [&] (StringView view) {
966         // This version is as if radix was undefined. Hence, undefined.toNumber() === 0.
967         return parseIntResult(parseInt(view, 0));
968     });
969 }
970
971 EncodedJSValue JIT_OPERATION operationParseIntStringNoRadix(ExecState* exec, JSString* string)
972 {
973     VM& vm = exec->vm();
974     NativeCallFrameTracer tracer(&vm, exec);
975     auto scope = DECLARE_THROW_SCOPE(vm);
976
977     auto viewWithString = string->viewWithUnderlyingString(exec);
978     RETURN_IF_EXCEPTION(scope, { });
979
980     // This version is as if radix was undefined. Hence, undefined.toNumber() === 0.
981     return parseIntResult(parseInt(viewWithString.view, 0));
982 }
983
984 EncodedJSValue JIT_OPERATION operationParseIntString(ExecState* exec, JSString* string, int32_t radix)
985 {
986     VM& vm = exec->vm();
987     NativeCallFrameTracer tracer(&vm, exec);
988     auto scope = DECLARE_THROW_SCOPE(vm);
989
990     auto viewWithString = string->viewWithUnderlyingString(exec);
991     RETURN_IF_EXCEPTION(scope, { });
992
993     return parseIntResult(parseInt(viewWithString.view, radix));
994 }
995
996 EncodedJSValue JIT_OPERATION operationParseIntGeneric(ExecState* exec, EncodedJSValue value, int32_t radix)
997 {
998     VM& vm = exec->vm();
999     NativeCallFrameTracer tracer(&vm, exec);
1000
1001     return toStringView(exec, JSValue::decode(value), [&] (StringView view) {
1002         return parseIntResult(parseInt(view, radix));
1003     });
1004 }
1005         
1006 size_t JIT_OPERATION operationRegExpTestString(ExecState* exec, JSGlobalObject* globalObject, RegExpObject* regExpObject, JSString* input)
1007 {
1008     SuperSamplerScope superSamplerScope(false);
1009     
1010     VM& vm = globalObject->vm();
1011     NativeCallFrameTracer tracer(&vm, exec);
1012
1013     return regExpObject->testInline(exec, globalObject, input);
1014 }
1015
1016 size_t JIT_OPERATION operationRegExpTest(ExecState* exec, JSGlobalObject* globalObject, RegExpObject* regExpObject, EncodedJSValue encodedArgument)
1017 {
1018     SuperSamplerScope superSamplerScope(false);
1019     
1020     VM& vm = globalObject->vm();
1021     NativeCallFrameTracer tracer(&vm, exec);
1022
1023     JSValue argument = JSValue::decode(encodedArgument);
1024
1025     JSString* input = argument.toStringOrNull(exec);
1026     if (!input)
1027         return false;
1028     return regExpObject->testInline(exec, globalObject, input);
1029 }
1030
1031 size_t JIT_OPERATION operationRegExpTestGeneric(ExecState* exec, JSGlobalObject* globalObject, EncodedJSValue encodedBase, EncodedJSValue encodedArgument)
1032 {
1033     SuperSamplerScope superSamplerScope(false);
1034     
1035     VM& vm = globalObject->vm();
1036     NativeCallFrameTracer tracer(&vm, exec);
1037     auto scope = DECLARE_THROW_SCOPE(vm);
1038
1039     JSValue base = JSValue::decode(encodedBase);
1040     JSValue argument = JSValue::decode(encodedArgument);
1041
1042     if (!base.inherits(vm, RegExpObject::info())) {
1043         throwTypeError(exec, scope);
1044         return false;
1045     }
1046
1047     JSString* input = argument.toStringOrNull(exec);
1048     EXCEPTION_ASSERT(!!scope.exception() == !input);
1049     if (!input)
1050         return false;
1051     scope.release();
1052     return asRegExpObject(base)->test(exec, globalObject, input);
1053 }
1054
1055 size_t JIT_OPERATION operationCompareStrictEqCell(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
1056 {
1057     VM* vm = &exec->vm();
1058     NativeCallFrameTracer tracer(vm, exec);
1059     
1060     JSValue op1 = JSValue::decode(encodedOp1);
1061     JSValue op2 = JSValue::decode(encodedOp2);
1062     
1063     ASSERT(op1.isCell());
1064     ASSERT(op2.isCell());
1065     
1066     return JSValue::strictEqualSlowCaseInline(exec, op1, op2);
1067 }
1068
1069 size_t JIT_OPERATION operationCompareStrictEq(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
1070 {
1071     VM* vm = &exec->vm();
1072     NativeCallFrameTracer tracer(vm, exec);
1073
1074     JSValue src1 = JSValue::decode(encodedOp1);
1075     JSValue src2 = JSValue::decode(encodedOp2);
1076     
1077     return JSValue::strictEqual(exec, src1, src2);
1078 }
1079
1080 EncodedJSValue JIT_OPERATION operationToPrimitive(ExecState* exec, EncodedJSValue value)
1081 {
1082     VM* vm = &exec->vm();
1083     NativeCallFrameTracer tracer(vm, exec);
1084     
1085     return JSValue::encode(JSValue::decode(value).toPrimitive(exec));
1086 }
1087
1088 EncodedJSValue JIT_OPERATION operationToNumber(ExecState* exec, EncodedJSValue value)
1089 {
1090     VM* vm = &exec->vm();
1091     NativeCallFrameTracer tracer(vm, exec);
1092
1093     return JSValue::encode(jsNumber(JSValue::decode(value).toNumber(exec)));
1094 }
1095
1096 EncodedJSValue JIT_OPERATION operationGetByIdWithThis(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedThis, UniquedStringImpl* impl)
1097 {
1098     VM& vm = exec->vm();
1099     NativeCallFrameTracer tracer(&vm, exec);
1100
1101     JSValue baseValue = JSValue::decode(encodedBase);
1102     JSValue thisVal = JSValue::decode(encodedThis);
1103     PropertySlot slot(thisVal, PropertySlot::PropertySlot::InternalMethodType::Get);
1104     JSValue result = baseValue.get(exec, Identifier::fromUid(exec, impl), slot);
1105     return JSValue::encode(result);
1106 }
1107
1108 EncodedJSValue JIT_OPERATION operationGetByValWithThis(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedThis, EncodedJSValue encodedSubscript)
1109 {
1110     VM& vm = exec->vm();
1111     NativeCallFrameTracer tracer(&vm, exec);
1112     auto scope = DECLARE_THROW_SCOPE(vm);
1113
1114     JSValue baseValue = JSValue::decode(encodedBase);
1115     JSValue thisVal = JSValue::decode(encodedThis);
1116     JSValue subscript = JSValue::decode(encodedSubscript);
1117
1118     if (LIKELY(baseValue.isCell() && subscript.isString())) {
1119         Structure& structure = *baseValue.asCell()->structure(vm);
1120         if (JSCell::canUseFastGetOwnProperty(structure)) {
1121             if (RefPtr<AtomicStringImpl> existingAtomicString = asString(subscript)->toExistingAtomicString(exec)) {
1122                 if (JSValue result = baseValue.asCell()->fastGetOwnProperty(vm, structure, existingAtomicString.get()))
1123                     return JSValue::encode(result);
1124             }
1125         }
1126     }
1127     
1128     PropertySlot slot(thisVal, PropertySlot::PropertySlot::InternalMethodType::Get);
1129     if (subscript.isUInt32()) {
1130         uint32_t i = subscript.asUInt32();
1131         if (isJSString(baseValue) && asString(baseValue)->canGetIndex(i))
1132             return JSValue::encode(asString(baseValue)->getIndex(exec, i));
1133         
1134         scope.release();
1135         return JSValue::encode(baseValue.get(exec, i, slot));
1136     }
1137
1138     baseValue.requireObjectCoercible(exec);
1139     RETURN_IF_EXCEPTION(scope, encodedJSValue());
1140
1141     auto property = subscript.toPropertyKey(exec);
1142     RETURN_IF_EXCEPTION(scope, encodedJSValue());
1143     scope.release();
1144     return JSValue::encode(baseValue.get(exec, property, slot));
1145 }
1146
1147 void JIT_OPERATION operationPutByIdWithThisStrict(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedThis, EncodedJSValue encodedValue, UniquedStringImpl* impl)
1148 {
1149     VM& vm = exec->vm();
1150     NativeCallFrameTracer tracer(&vm, exec);
1151
1152     putWithThis<true>(exec, encodedBase, encodedThis, encodedValue, Identifier::fromUid(exec, impl));
1153 }
1154
1155 void JIT_OPERATION operationPutByIdWithThis(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedThis, EncodedJSValue encodedValue, UniquedStringImpl* impl)
1156 {
1157     VM& vm = exec->vm();
1158     NativeCallFrameTracer tracer(&vm, exec);
1159
1160     putWithThis<false>(exec, encodedBase, encodedThis, encodedValue, Identifier::fromUid(exec, impl));
1161 }
1162
1163 void JIT_OPERATION operationPutByValWithThisStrict(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedThis, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue)
1164 {
1165     VM& vm = exec->vm();
1166     NativeCallFrameTracer tracer(&vm, exec);
1167     auto scope = DECLARE_THROW_SCOPE(vm);
1168
1169     Identifier property = JSValue::decode(encodedSubscript).toPropertyKey(exec);
1170     RETURN_IF_EXCEPTION(scope, void());
1171     scope.release();
1172     putWithThis<true>(exec, encodedBase, encodedThis, encodedValue, property);
1173 }
1174
1175 void JIT_OPERATION operationPutByValWithThis(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedThis, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue)
1176 {
1177     VM& vm = exec->vm();
1178     NativeCallFrameTracer tracer(&vm, exec);
1179     auto scope = DECLARE_THROW_SCOPE(vm);
1180
1181     Identifier property = JSValue::decode(encodedSubscript).toPropertyKey(exec);
1182     RETURN_IF_EXCEPTION(scope, void());
1183     scope.release();
1184     putWithThis<false>(exec, encodedBase, encodedThis, encodedValue, property);
1185 }
1186
1187 ALWAYS_INLINE static void defineDataProperty(ExecState* exec, VM& vm, JSObject* base, const Identifier& propertyName, JSValue value, int32_t attributes)
1188 {
1189     PropertyDescriptor descriptor = toPropertyDescriptor(value, jsUndefined(), jsUndefined(), DefinePropertyAttributes(attributes));
1190     ASSERT((descriptor.attributes() & Accessor) || (!descriptor.isAccessorDescriptor()));
1191     if (base->methodTable(vm)->defineOwnProperty == JSObject::defineOwnProperty)
1192         JSObject::defineOwnProperty(base, exec, propertyName, descriptor, true);
1193     else
1194         base->methodTable(vm)->defineOwnProperty(base, exec, propertyName, descriptor, true);
1195 }
1196
1197 void JIT_OPERATION operationDefineDataProperty(ExecState* exec, JSObject* base, EncodedJSValue encodedProperty, EncodedJSValue encodedValue, int32_t attributes)
1198 {
1199     VM& vm = exec->vm();
1200     NativeCallFrameTracer tracer(&vm, exec);
1201     auto scope = DECLARE_THROW_SCOPE(vm);
1202
1203     Identifier propertyName = JSValue::decode(encodedProperty).toPropertyKey(exec);
1204     RETURN_IF_EXCEPTION(scope, void());
1205     scope.release();
1206     defineDataProperty(exec, vm, base, propertyName, JSValue::decode(encodedValue), attributes);
1207 }
1208
1209 void JIT_OPERATION operationDefineDataPropertyString(ExecState* exec, JSObject* base, JSString* property, EncodedJSValue encodedValue, int32_t attributes)
1210 {
1211     VM& vm = exec->vm();
1212     NativeCallFrameTracer tracer(&vm, exec);
1213     auto scope = DECLARE_THROW_SCOPE(vm);
1214
1215     Identifier propertyName = property->toIdentifier(exec);
1216     RETURN_IF_EXCEPTION(scope, void());
1217     scope.release();
1218     defineDataProperty(exec, vm, base, propertyName, JSValue::decode(encodedValue), attributes);
1219 }
1220
1221 void JIT_OPERATION operationDefineDataPropertyStringIdent(ExecState* exec, JSObject* base, UniquedStringImpl* property, EncodedJSValue encodedValue, int32_t attributes)
1222 {
1223     VM& vm = exec->vm();
1224     NativeCallFrameTracer tracer(&vm, exec);
1225     defineDataProperty(exec, vm, base, Identifier::fromUid(&vm, property), JSValue::decode(encodedValue), attributes);
1226 }
1227
1228 void JIT_OPERATION operationDefineDataPropertySymbol(ExecState* exec, JSObject* base, Symbol* property, EncodedJSValue encodedValue, int32_t attributes)
1229 {
1230     VM& vm = exec->vm();
1231     NativeCallFrameTracer tracer(&vm, exec);
1232     defineDataProperty(exec, vm, base, Identifier::fromUid(property->privateName()), JSValue::decode(encodedValue), attributes);
1233 }
1234
1235 ALWAYS_INLINE static void defineAccessorProperty(ExecState* exec, VM& vm, JSObject* base, const Identifier& propertyName, JSObject* getter, JSObject* setter, int32_t attributes)
1236 {
1237     PropertyDescriptor descriptor = toPropertyDescriptor(jsUndefined(), getter, setter, DefinePropertyAttributes(attributes));
1238     ASSERT((descriptor.attributes() & Accessor) || (!descriptor.isAccessorDescriptor()));
1239     if (base->methodTable(vm)->defineOwnProperty == JSObject::defineOwnProperty)
1240         JSObject::defineOwnProperty(base, exec, propertyName, descriptor, true);
1241     else
1242         base->methodTable(vm)->defineOwnProperty(base, exec, propertyName, descriptor, true);
1243 }
1244
1245 void JIT_OPERATION operationDefineAccessorProperty(ExecState* exec, JSObject* base, EncodedJSValue encodedProperty, JSObject* getter, JSObject* setter, int32_t attributes)
1246 {
1247     VM& vm = exec->vm();
1248     NativeCallFrameTracer tracer(&vm, exec);
1249     auto scope = DECLARE_THROW_SCOPE(vm);
1250
1251     Identifier propertyName = JSValue::decode(encodedProperty).toPropertyKey(exec);
1252     RETURN_IF_EXCEPTION(scope, void());
1253     defineAccessorProperty(exec, vm, base, propertyName, getter, setter, attributes);
1254 }
1255
1256 void JIT_OPERATION operationDefineAccessorPropertyString(ExecState* exec, JSObject* base, JSString* property, JSObject* getter, JSObject* setter, int32_t attributes)
1257 {
1258     VM& vm = exec->vm();
1259     NativeCallFrameTracer tracer(&vm, exec);
1260     auto scope = DECLARE_THROW_SCOPE(vm);
1261
1262     Identifier propertyName = property->toIdentifier(exec);
1263     RETURN_IF_EXCEPTION(scope, void());
1264     defineAccessorProperty(exec, vm, base, propertyName, getter, setter, attributes);
1265 }
1266
1267 void JIT_OPERATION operationDefineAccessorPropertyStringIdent(ExecState* exec, JSObject* base, UniquedStringImpl* property, JSObject* getter, JSObject* setter, int32_t attributes)
1268 {
1269     VM& vm = exec->vm();
1270     NativeCallFrameTracer tracer(&vm, exec);
1271     defineAccessorProperty(exec, vm, base, Identifier::fromUid(&vm, property), getter, setter, attributes);
1272 }
1273
1274 void JIT_OPERATION operationDefineAccessorPropertySymbol(ExecState* exec, JSObject* base, Symbol* property, JSObject* getter, JSObject* setter, int32_t attributes)
1275 {
1276     VM& vm = exec->vm();
1277     NativeCallFrameTracer tracer(&vm, exec);
1278     defineAccessorProperty(exec, vm, base, Identifier::fromUid(property->privateName()), getter, setter, attributes);
1279 }
1280
1281 char* JIT_OPERATION operationNewArray(ExecState* exec, Structure* arrayStructure, void* buffer, size_t size)
1282 {
1283     VM* vm = &exec->vm();
1284     NativeCallFrameTracer tracer(vm, exec);
1285     
1286     return bitwise_cast<char*>(constructArray(exec, arrayStructure, static_cast<JSValue*>(buffer), size));
1287 }
1288
1289 char* JIT_OPERATION operationNewEmptyArray(ExecState* exec, Structure* arrayStructure)
1290 {
1291     VM* vm = &exec->vm();
1292     NativeCallFrameTracer tracer(vm, exec);
1293     
1294     return bitwise_cast<char*>(JSArray::create(*vm, arrayStructure));
1295 }
1296
1297 char* JIT_OPERATION operationNewArrayWithSize(ExecState* exec, Structure* arrayStructure, int32_t size, Butterfly* butterfly)
1298 {
1299     VM& vm = exec->vm();
1300     NativeCallFrameTracer tracer(&vm, exec);
1301     auto scope = DECLARE_THROW_SCOPE(vm);
1302
1303     if (UNLIKELY(size < 0))
1304         return bitwise_cast<char*>(throwException(exec, scope, createRangeError(exec, ASCIILiteral("Array size is not a small enough positive integer."))));
1305
1306     JSArray* result;
1307     if (butterfly)
1308         result = JSArray::createWithButterfly(vm, nullptr, arrayStructure, butterfly);
1309     else
1310         result = JSArray::create(vm, arrayStructure, size);
1311     return bitwise_cast<char*>(result);
1312 }
1313
1314 char* JIT_OPERATION operationNewArrayBuffer(ExecState* exec, Structure* arrayStructure, size_t start, size_t size)
1315 {
1316     VM& vm = exec->vm();
1317     NativeCallFrameTracer tracer(&vm, exec);
1318     return bitwise_cast<char*>(constructArray(exec, arrayStructure, exec->codeBlock()->constantBuffer(start), size));
1319 }
1320
1321 char* JIT_OPERATION operationNewInt8ArrayWithSize(
1322     ExecState* exec, Structure* structure, int32_t length, char* vector)
1323 {
1324     return newTypedArrayWithSize<JSInt8Array>(exec, structure, length, vector);
1325 }
1326
1327 char* JIT_OPERATION operationNewInt8ArrayWithOneArgument(
1328     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
1329 {
1330     VM& vm = exec->vm();
1331     NativeCallFrameTracer tracer(&vm, exec);
1332     return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSInt8Array>(exec, structure, encodedValue, 0, std::nullopt));
1333 }
1334
1335 char* JIT_OPERATION operationNewInt16ArrayWithSize(
1336     ExecState* exec, Structure* structure, int32_t length, char* vector)
1337 {
1338     return newTypedArrayWithSize<JSInt16Array>(exec, structure, length, vector);
1339 }
1340
1341 char* JIT_OPERATION operationNewInt16ArrayWithOneArgument(
1342     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
1343 {
1344     VM& vm = exec->vm();
1345     NativeCallFrameTracer tracer(&vm, exec);
1346     return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSInt16Array>(exec, structure, encodedValue, 0, std::nullopt));
1347 }
1348
1349 char* JIT_OPERATION operationNewInt32ArrayWithSize(
1350     ExecState* exec, Structure* structure, int32_t length, char* vector)
1351 {
1352     return newTypedArrayWithSize<JSInt32Array>(exec, structure, length, vector);
1353 }
1354
1355 char* JIT_OPERATION operationNewInt32ArrayWithOneArgument(
1356     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
1357 {
1358     VM& vm = exec->vm();
1359     NativeCallFrameTracer tracer(&vm, exec);
1360     return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSInt32Array>(exec, structure, encodedValue, 0, std::nullopt));
1361 }
1362
1363 char* JIT_OPERATION operationNewUint8ArrayWithSize(
1364     ExecState* exec, Structure* structure, int32_t length, char* vector)
1365 {
1366     return newTypedArrayWithSize<JSUint8Array>(exec, structure, length, vector);
1367 }
1368
1369 char* JIT_OPERATION operationNewUint8ArrayWithOneArgument(
1370     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
1371 {
1372     VM& vm = exec->vm();
1373     NativeCallFrameTracer tracer(&vm, exec);
1374     return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSUint8Array>(exec, structure, encodedValue, 0, std::nullopt));
1375 }
1376
1377 char* JIT_OPERATION operationNewUint8ClampedArrayWithSize(
1378     ExecState* exec, Structure* structure, int32_t length, char* vector)
1379 {
1380     return newTypedArrayWithSize<JSUint8ClampedArray>(exec, structure, length, vector);
1381 }
1382
1383 char* JIT_OPERATION operationNewUint8ClampedArrayWithOneArgument(
1384     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
1385 {
1386     VM& vm = exec->vm();
1387     NativeCallFrameTracer tracer(&vm, exec);
1388     return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSUint8ClampedArray>(exec, structure, encodedValue, 0, std::nullopt));
1389 }
1390
1391 char* JIT_OPERATION operationNewUint16ArrayWithSize(
1392     ExecState* exec, Structure* structure, int32_t length, char* vector)
1393 {
1394     return newTypedArrayWithSize<JSUint16Array>(exec, structure, length, vector);
1395 }
1396
1397 char* JIT_OPERATION operationNewUint16ArrayWithOneArgument(
1398     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
1399 {
1400     VM& vm = exec->vm();
1401     NativeCallFrameTracer tracer(&vm, exec);
1402     return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSUint16Array>(exec, structure, encodedValue, 0, std::nullopt));
1403 }
1404
1405 char* JIT_OPERATION operationNewUint32ArrayWithSize(
1406     ExecState* exec, Structure* structure, int32_t length, char* vector)
1407 {
1408     return newTypedArrayWithSize<JSUint32Array>(exec, structure, length, vector);
1409 }
1410
1411 char* JIT_OPERATION operationNewUint32ArrayWithOneArgument(
1412     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
1413 {
1414     VM& vm = exec->vm();
1415     NativeCallFrameTracer tracer(&vm, exec);
1416     return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSUint32Array>(exec, structure, encodedValue, 0, std::nullopt));
1417 }
1418
1419 char* JIT_OPERATION operationNewFloat32ArrayWithSize(
1420     ExecState* exec, Structure* structure, int32_t length, char* vector)
1421 {
1422     return newTypedArrayWithSize<JSFloat32Array>(exec, structure, length, vector);
1423 }
1424
1425 char* JIT_OPERATION operationNewFloat32ArrayWithOneArgument(
1426     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
1427 {
1428     VM& vm = exec->vm();
1429     NativeCallFrameTracer tracer(&vm, exec);
1430     return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSFloat32Array>(exec, structure, encodedValue, 0, std::nullopt));
1431 }
1432
1433 char* JIT_OPERATION operationNewFloat64ArrayWithSize(
1434     ExecState* exec, Structure* structure, int32_t length, char* vector)
1435 {
1436     return newTypedArrayWithSize<JSFloat64Array>(exec, structure, length, vector);
1437 }
1438
1439 char* JIT_OPERATION operationNewFloat64ArrayWithOneArgument(
1440     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
1441 {
1442     VM& vm = exec->vm();
1443     NativeCallFrameTracer tracer(&vm, exec);
1444     return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSFloat64Array>(exec, structure, encodedValue, 0, std::nullopt));
1445 }
1446
1447 JSCell* JIT_OPERATION operationCreateActivationDirect(ExecState* exec, Structure* structure, JSScope* scope, SymbolTable* table, EncodedJSValue initialValueEncoded)
1448 {
1449     JSValue initialValue = JSValue::decode(initialValueEncoded);
1450     ASSERT(initialValue == jsUndefined() || initialValue == jsTDZValue());
1451     VM& vm = exec->vm();
1452     NativeCallFrameTracer tracer(&vm, exec);
1453     return JSLexicalEnvironment::create(vm, structure, scope, table, initialValue);
1454 }
1455
1456 JSCell* JIT_OPERATION operationCreateDirectArguments(ExecState* exec, Structure* structure, int32_t length, int32_t minCapacity)
1457 {
1458     VM& vm = exec->vm();
1459     NativeCallFrameTracer target(&vm, exec);
1460     DirectArguments* result = DirectArguments::create(
1461         vm, structure, length, std::max(length, minCapacity));
1462     // The caller will store to this object without barriers. Most likely, at this point, this is
1463     // still a young object and so no barriers are needed. But it's good to be careful anyway,
1464     // since the GC should be allowed to do crazy (like pretenuring, for example).
1465     vm.heap.writeBarrier(result);
1466     return result;
1467 }
1468
1469 JSCell* JIT_OPERATION operationCreateScopedArguments(ExecState* exec, Structure* structure, Register* argumentStart, int32_t length, JSFunction* callee, JSLexicalEnvironment* scope)
1470 {
1471     VM& vm = exec->vm();
1472     NativeCallFrameTracer target(&vm, exec);
1473     
1474     // We could pass the ScopedArgumentsTable* as an argument. We currently don't because I
1475     // didn't feel like changing the max number of arguments for a slow path call from 6 to 7.
1476     ScopedArgumentsTable* table = scope->symbolTable()->arguments();
1477     
1478     return ScopedArguments::createByCopyingFrom(
1479         vm, structure, argumentStart, length, callee, table, scope);
1480 }
1481
1482 JSCell* JIT_OPERATION operationCreateClonedArguments(ExecState* exec, Structure* structure, Register* argumentStart, int32_t length, JSFunction* callee)
1483 {
1484     VM& vm = exec->vm();
1485     NativeCallFrameTracer target(&vm, exec);
1486     return ClonedArguments::createByCopyingFrom(
1487         exec, structure, argumentStart, length, callee);
1488 }
1489
1490 JSCell* JIT_OPERATION operationCreateDirectArgumentsDuringExit(ExecState* exec, InlineCallFrame* inlineCallFrame, JSFunction* callee, int32_t argumentCount)
1491 {
1492     VM& vm = exec->vm();
1493     NativeCallFrameTracer target(&vm, exec);
1494     
1495     DeferGCForAWhile deferGC(vm.heap);
1496     
1497     CodeBlock* codeBlock;
1498     if (inlineCallFrame)
1499         codeBlock = baselineCodeBlockForInlineCallFrame(inlineCallFrame);
1500     else
1501         codeBlock = exec->codeBlock();
1502     
1503     unsigned length = argumentCount - 1;
1504     unsigned capacity = std::max(length, static_cast<unsigned>(codeBlock->numParameters() - 1));
1505     DirectArguments* result = DirectArguments::create(
1506         vm, codeBlock->globalObject()->directArgumentsStructure(), length, capacity);
1507     
1508     result->callee().set(vm, result, callee);
1509     
1510     Register* arguments =
1511         exec->registers() + (inlineCallFrame ? inlineCallFrame->stackOffset : 0) +
1512         CallFrame::argumentOffset(0);
1513     for (unsigned i = length; i--;)
1514         result->setIndexQuickly(vm, i, arguments[i].jsValue());
1515     
1516     return result;
1517 }
1518
1519 JSCell* JIT_OPERATION operationCreateClonedArgumentsDuringExit(ExecState* exec, InlineCallFrame* inlineCallFrame, JSFunction* callee, int32_t argumentCount)
1520 {
1521     VM& vm = exec->vm();
1522     NativeCallFrameTracer target(&vm, exec);
1523     
1524     DeferGCForAWhile deferGC(vm.heap);
1525     
1526     CodeBlock* codeBlock;
1527     if (inlineCallFrame)
1528         codeBlock = baselineCodeBlockForInlineCallFrame(inlineCallFrame);
1529     else
1530         codeBlock = exec->codeBlock();
1531     
1532     unsigned length = argumentCount - 1;
1533     ClonedArguments* result = ClonedArguments::createEmpty(
1534         vm, codeBlock->globalObject()->clonedArgumentsStructure(), callee, length);
1535     
1536     Register* arguments =
1537         exec->registers() + (inlineCallFrame ? inlineCallFrame->stackOffset : 0) +
1538         CallFrame::argumentOffset(0);
1539     for (unsigned i = length; i--;)
1540         result->putDirectIndex(exec, i, arguments[i].jsValue());
1541
1542     
1543     return result;
1544 }
1545
1546 JSCell* JIT_OPERATION operationCreateRest(ExecState* exec, Register* argumentStart, unsigned numberOfParamsToSkip, unsigned arraySize)
1547 {
1548     VM* vm = &exec->vm();
1549     NativeCallFrameTracer tracer(vm, exec);
1550
1551     JSGlobalObject* globalObject = exec->lexicalGlobalObject();
1552     Structure* structure = globalObject->restParameterStructure();
1553     static_assert(sizeof(Register) == sizeof(JSValue), "This is a strong assumption here.");
1554     JSValue* argumentsToCopyRegion = bitwise_cast<JSValue*>(argumentStart) + numberOfParamsToSkip;
1555     return constructArray(exec, structure, argumentsToCopyRegion, arraySize);
1556 }
1557
1558 size_t JIT_OPERATION operationObjectIsObject(ExecState* exec, JSGlobalObject* globalObject, JSCell* object)
1559 {
1560     VM& vm = exec->vm();
1561     NativeCallFrameTracer tracer(&vm, exec);
1562
1563     ASSERT(jsDynamicCast<JSObject*>(vm, object));
1564     
1565     if (object->structure(vm)->masqueradesAsUndefined(globalObject))
1566         return false;
1567     if (object->type() == JSFunctionType)
1568         return false;
1569     if (object->inlineTypeFlags() & TypeOfShouldCallGetCallData) {
1570         CallData callData;
1571         if (object->methodTable(vm)->getCallData(object, callData) != CallType::None)
1572             return false;
1573     }
1574     
1575     return true;
1576 }
1577
1578 size_t JIT_OPERATION operationObjectIsFunction(ExecState* exec, JSGlobalObject* globalObject, JSCell* object)
1579 {
1580     VM& vm = exec->vm();
1581     NativeCallFrameTracer tracer(&vm, exec);
1582
1583     ASSERT(jsDynamicCast<JSObject*>(vm, object));
1584     
1585     if (object->structure(vm)->masqueradesAsUndefined(globalObject))
1586         return false;
1587     if (object->type() == JSFunctionType)
1588         return true;
1589     if (object->inlineTypeFlags() & TypeOfShouldCallGetCallData) {
1590         CallData callData;
1591         if (object->methodTable(vm)->getCallData(object, callData) != CallType::None)
1592             return true;
1593     }
1594     
1595     return false;
1596 }
1597
1598 JSCell* JIT_OPERATION operationTypeOfObject(ExecState* exec, JSGlobalObject* globalObject, JSCell* object)
1599 {
1600     VM& vm = exec->vm();
1601     NativeCallFrameTracer tracer(&vm, exec);
1602
1603     ASSERT(jsDynamicCast<JSObject*>(vm, object));
1604     
1605     if (object->structure(vm)->masqueradesAsUndefined(globalObject))
1606         return vm.smallStrings.undefinedString();
1607     if (object->type() == JSFunctionType)
1608         return vm.smallStrings.functionString();
1609     if (object->inlineTypeFlags() & TypeOfShouldCallGetCallData) {
1610         CallData callData;
1611         if (object->methodTable(vm)->getCallData(object, callData) != CallType::None)
1612             return vm.smallStrings.functionString();
1613     }
1614     
1615     return vm.smallStrings.objectString();
1616 }
1617
1618 int32_t JIT_OPERATION operationTypeOfObjectAsTypeofType(ExecState* exec, JSGlobalObject* globalObject, JSCell* object)
1619 {
1620     VM& vm = exec->vm();
1621     NativeCallFrameTracer tracer(&vm, exec);
1622
1623     ASSERT(jsDynamicCast<JSObject*>(vm, object));
1624     
1625     if (object->structure(vm)->masqueradesAsUndefined(globalObject))
1626         return static_cast<int32_t>(TypeofType::Undefined);
1627     if (object->type() == JSFunctionType)
1628         return static_cast<int32_t>(TypeofType::Function);
1629     if (object->inlineTypeFlags() & TypeOfShouldCallGetCallData) {
1630         CallData callData;
1631         if (object->methodTable(vm)->getCallData(object, callData) != CallType::None)
1632             return static_cast<int32_t>(TypeofType::Function);
1633     }
1634     
1635     return static_cast<int32_t>(TypeofType::Object);
1636 }
1637
1638 char* JIT_OPERATION operationAllocateSimplePropertyStorageWithInitialCapacity(ExecState* exec)
1639 {
1640     VM& vm = exec->vm();
1641     NativeCallFrameTracer tracer(&vm, exec);
1642
1643     return reinterpret_cast<char*>(
1644         Butterfly::createUninitialized(vm, 0, 0, initialOutOfLineCapacity, false, 0));
1645 }
1646
1647 char* JIT_OPERATION operationAllocateSimplePropertyStorage(ExecState* exec, size_t newSize)
1648 {
1649     VM& vm = exec->vm();
1650     NativeCallFrameTracer tracer(&vm, exec);
1651
1652     return reinterpret_cast<char*>(
1653         Butterfly::createUninitialized(vm, 0, 0, newSize, false, 0));
1654 }
1655
1656 char* JIT_OPERATION operationAllocateComplexPropertyStorageWithInitialCapacity(ExecState* exec, JSObject* object)
1657 {
1658     VM& vm = exec->vm();
1659     NativeCallFrameTracer tracer(&vm, exec);
1660
1661     ASSERT(!object->structure()->outOfLineCapacity());
1662     return reinterpret_cast<char*>(
1663         object->allocateMoreOutOfLineStorage(vm, 0, initialOutOfLineCapacity));
1664 }
1665
1666 char* JIT_OPERATION operationAllocateComplexPropertyStorage(ExecState* exec, JSObject* object, size_t newSize)
1667 {
1668     VM& vm = exec->vm();
1669     NativeCallFrameTracer tracer(&vm, exec);
1670
1671     return reinterpret_cast<char*>(
1672         object->allocateMoreOutOfLineStorage(vm, object->structure()->outOfLineCapacity(), newSize));
1673 }
1674
1675 char* JIT_OPERATION operationEnsureInt32(ExecState* exec, JSCell* cell)
1676 {
1677     VM& vm = exec->vm();
1678     NativeCallFrameTracer tracer(&vm, exec);
1679     
1680     if (!cell->isObject())
1681         return 0;
1682     
1683     return reinterpret_cast<char*>(asObject(cell)->ensureInt32(vm).data());
1684 }
1685
1686 char* JIT_OPERATION operationEnsureDouble(ExecState* exec, JSCell* cell)
1687 {
1688     VM& vm = exec->vm();
1689     NativeCallFrameTracer tracer(&vm, exec);
1690     
1691     if (!cell->isObject())
1692         return 0;
1693     
1694     return reinterpret_cast<char*>(asObject(cell)->ensureDouble(vm).data());
1695 }
1696
1697 char* JIT_OPERATION operationEnsureContiguous(ExecState* exec, JSCell* cell)
1698 {
1699     VM& vm = exec->vm();
1700     NativeCallFrameTracer tracer(&vm, exec);
1701     
1702     if (!cell->isObject())
1703         return 0;
1704     
1705     return reinterpret_cast<char*>(asObject(cell)->ensureContiguous(vm).data());
1706 }
1707
1708 char* JIT_OPERATION operationEnsureArrayStorage(ExecState* exec, JSCell* cell)
1709 {
1710     VM& vm = exec->vm();
1711     NativeCallFrameTracer tracer(&vm, exec);
1712     
1713     if (!cell->isObject())
1714         return 0;
1715
1716     return reinterpret_cast<char*>(asObject(cell)->ensureArrayStorage(vm));
1717 }
1718
1719 StringImpl* JIT_OPERATION operationResolveRope(ExecState* exec, JSString* string)
1720 {
1721     VM& vm = exec->vm();
1722     NativeCallFrameTracer tracer(&vm, exec);
1723
1724     return string->value(exec).impl();
1725 }
1726
1727 JSString* JIT_OPERATION operationToLowerCase(ExecState* exec, JSString* string, uint32_t failingIndex)
1728 {
1729     VM& vm = exec->vm();
1730     NativeCallFrameTracer tracer(&vm, exec);
1731
1732     auto scope = DECLARE_THROW_SCOPE(vm);
1733
1734     const String& inputString = string->value(exec);
1735     RETURN_IF_EXCEPTION(scope, nullptr);
1736     if (!inputString.length())
1737         return vm.smallStrings.emptyString();
1738
1739     String lowercasedString = inputString.is8Bit() ? inputString.convertToLowercaseWithoutLocaleStartingAtFailingIndex8Bit(failingIndex) : inputString.convertToLowercaseWithoutLocale();
1740     if (lowercasedString.impl() == inputString.impl())
1741         return string;
1742     scope.release();
1743     return jsString(exec, lowercasedString);
1744 }
1745
1746 char* JIT_OPERATION operationInt32ToString(ExecState* exec, int32_t value, int32_t radix)
1747 {
1748     VM& vm = exec->vm();
1749     NativeCallFrameTracer tracer(&vm, exec);
1750
1751     auto scope = DECLARE_THROW_SCOPE(vm);
1752
1753     if (radix < 2 || radix > 36) {
1754         throwVMError(exec, scope, createRangeError(exec, ASCIILiteral("toString() radix argument must be between 2 and 36")));
1755         return nullptr;
1756     }
1757
1758     return reinterpret_cast<char*>(int32ToString(vm, value, radix));
1759 }
1760
1761 char* JIT_OPERATION operationInt52ToString(ExecState* exec, int64_t value, int32_t radix)
1762 {
1763     VM& vm = exec->vm();
1764     NativeCallFrameTracer tracer(&vm, exec);
1765
1766     auto scope = DECLARE_THROW_SCOPE(vm);
1767
1768     if (radix < 2 || radix > 36) {
1769         throwVMError(exec, scope, createRangeError(exec, ASCIILiteral("toString() radix argument must be between 2 and 36")));
1770         return nullptr;
1771     }
1772
1773     return reinterpret_cast<char*>(int52ToString(vm, value, radix));
1774 }
1775
1776 char* JIT_OPERATION operationDoubleToString(ExecState* exec, double value, int32_t radix)
1777 {
1778     VM& vm = exec->vm();
1779     NativeCallFrameTracer tracer(&vm, exec);
1780
1781     auto scope = DECLARE_THROW_SCOPE(vm);
1782
1783     if (radix < 2 || radix > 36) {
1784         throwVMError(exec, scope, createRangeError(exec, ASCIILiteral("toString() radix argument must be between 2 and 36")));
1785         return nullptr;
1786     }
1787
1788     return reinterpret_cast<char*>(numberToString(vm, value, radix));
1789 }
1790
1791 char* JIT_OPERATION operationInt32ToStringWithValidRadix(ExecState* exec, int32_t value, int32_t radix)
1792 {
1793     VM& vm = exec->vm();
1794     NativeCallFrameTracer tracer(&vm, exec);
1795
1796     return reinterpret_cast<char*>(int32ToString(vm, value, radix));
1797 }
1798
1799 char* JIT_OPERATION operationInt52ToStringWithValidRadix(ExecState* exec, int64_t value, int32_t radix)
1800 {
1801     VM& vm = exec->vm();
1802     NativeCallFrameTracer tracer(&vm, exec);
1803
1804     return reinterpret_cast<char*>(int52ToString(vm, value, radix));
1805 }
1806
1807 char* JIT_OPERATION operationDoubleToStringWithValidRadix(ExecState* exec, double value, int32_t radix)
1808 {
1809     VM& vm = exec->vm();
1810     NativeCallFrameTracer tracer(&vm, exec);
1811
1812     return reinterpret_cast<char*>(numberToString(vm, value, radix));
1813 }
1814
1815 JSString* JIT_OPERATION operationSingleCharacterString(ExecState* exec, int32_t character)
1816 {
1817     VM& vm = exec->vm();
1818     NativeCallFrameTracer tracer(&vm, exec);
1819     
1820     return jsSingleCharacterString(exec, static_cast<UChar>(character));
1821 }
1822
1823 JSCell* JIT_OPERATION operationNewStringObject(ExecState* exec, JSString* string, Structure* structure)
1824 {
1825     VM& vm = exec->vm();
1826     NativeCallFrameTracer tracer(&vm, exec);
1827     
1828     return StringObject::create(vm, structure, string);
1829 }
1830
1831 JSCell* JIT_OPERATION operationToStringOnCell(ExecState* exec, JSCell* cell)
1832 {
1833     VM& vm = exec->vm();
1834     NativeCallFrameTracer tracer(&vm, exec);
1835     
1836     return JSValue(cell).toString(exec);
1837 }
1838
1839 JSCell* JIT_OPERATION operationToString(ExecState* exec, EncodedJSValue value)
1840 {
1841     VM& vm = exec->vm();
1842     NativeCallFrameTracer tracer(&vm, exec);
1843
1844     return JSValue::decode(value).toString(exec);
1845 }
1846
1847 JSCell* JIT_OPERATION operationCallStringConstructorOnCell(ExecState* exec, JSCell* cell)
1848 {
1849     VM& vm = exec->vm();
1850     NativeCallFrameTracer tracer(&vm, exec);
1851
1852     return stringConstructor(exec, cell);
1853 }
1854
1855 JSCell* JIT_OPERATION operationCallStringConstructor(ExecState* exec, EncodedJSValue value)
1856 {
1857     VM& vm = exec->vm();
1858     NativeCallFrameTracer tracer(&vm, exec);
1859
1860     return stringConstructor(exec, JSValue::decode(value));
1861 }
1862
1863 JSCell* JIT_OPERATION operationMakeRope2(ExecState* exec, JSString* left, JSString* right)
1864 {
1865     VM& vm = exec->vm();
1866     NativeCallFrameTracer tracer(&vm, exec);
1867
1868     return jsString(exec, left, right);
1869 }
1870
1871 JSCell* JIT_OPERATION operationMakeRope3(ExecState* exec, JSString* a, JSString* b, JSString* c)
1872 {
1873     VM& vm = exec->vm();
1874     NativeCallFrameTracer tracer(&vm, exec);
1875
1876     return jsString(exec, a, b, c);
1877 }
1878
1879 JSCell* JIT_OPERATION operationStrCat2(ExecState* exec, EncodedJSValue a, EncodedJSValue b)
1880 {
1881     VM& vm = exec->vm();
1882     NativeCallFrameTracer tracer(&vm, exec);
1883     auto scope = DECLARE_THROW_SCOPE(vm);
1884
1885     JSString* str1 = JSValue::decode(a).toString(exec);
1886     scope.assertNoException(); // Impossible, since we must have been given primitives.
1887     JSString* str2 = JSValue::decode(b).toString(exec);
1888     scope.assertNoException();
1889
1890     scope.release();
1891     return jsString(exec, str1, str2);
1892 }
1893     
1894 JSCell* JIT_OPERATION operationStrCat3(ExecState* exec, EncodedJSValue a, EncodedJSValue b, EncodedJSValue c)
1895 {
1896     VM& vm = exec->vm();
1897     NativeCallFrameTracer tracer(&vm, exec);
1898     auto scope = DECLARE_THROW_SCOPE(vm);
1899
1900     JSString* str1 = JSValue::decode(a).toString(exec);
1901     scope.assertNoException(); // Impossible, since we must have been given primitives.
1902     JSString* str2 = JSValue::decode(b).toString(exec);
1903     scope.assertNoException();
1904     JSString* str3 = JSValue::decode(c).toString(exec);
1905     scope.assertNoException();
1906
1907     scope.release();
1908     return jsString(exec, str1, str2, str3);
1909 }
1910
1911 char* JIT_OPERATION operationFindSwitchImmTargetForDouble(
1912     ExecState* exec, EncodedJSValue encodedValue, size_t tableIndex)
1913 {
1914     VM& vm = exec->vm();
1915     NativeCallFrameTracer tracer(&vm, exec);
1916
1917     CodeBlock* codeBlock = exec->codeBlock();
1918     SimpleJumpTable& table = codeBlock->switchJumpTable(tableIndex);
1919     JSValue value = JSValue::decode(encodedValue);
1920     ASSERT(value.isDouble());
1921     double asDouble = value.asDouble();
1922     int32_t asInt32 = static_cast<int32_t>(asDouble);
1923     if (asDouble == asInt32)
1924         return static_cast<char*>(table.ctiForValue(asInt32).executableAddress());
1925     return static_cast<char*>(table.ctiDefault.executableAddress());
1926 }
1927
1928 char* JIT_OPERATION operationSwitchString(ExecState* exec, size_t tableIndex, JSString* string)
1929 {
1930     VM& vm = exec->vm();
1931     NativeCallFrameTracer tracer(&vm, exec);
1932
1933     return static_cast<char*>(exec->codeBlock()->stringSwitchJumpTable(tableIndex).ctiForValue(string->value(exec).impl()).executableAddress());
1934 }
1935
1936 int32_t JIT_OPERATION operationSwitchStringAndGetBranchOffset(ExecState* exec, size_t tableIndex, JSString* string)
1937 {
1938     VM& vm = exec->vm();
1939     NativeCallFrameTracer tracer(&vm, exec);
1940
1941     return exec->codeBlock()->stringSwitchJumpTable(tableIndex).offsetForValue(string->value(exec).impl(), std::numeric_limits<int32_t>::min());
1942 }
1943
1944 uintptr_t JIT_OPERATION operationCompareStringImplLess(StringImpl* a, StringImpl* b)
1945 {
1946     return codePointCompare(a, b) < 0;
1947 }
1948
1949 uintptr_t JIT_OPERATION operationCompareStringImplLessEq(StringImpl* a, StringImpl* b)
1950 {
1951     return codePointCompare(a, b) <= 0;
1952 }
1953
1954 uintptr_t JIT_OPERATION operationCompareStringImplGreater(StringImpl* a, StringImpl* b)
1955 {
1956     return codePointCompare(a, b) > 0;
1957 }
1958
1959 uintptr_t JIT_OPERATION operationCompareStringImplGreaterEq(StringImpl* a, StringImpl* b)
1960 {
1961     return codePointCompare(a, b) >= 0;
1962 }
1963
1964 uintptr_t JIT_OPERATION operationCompareStringLess(ExecState* exec, JSString* a, JSString* b)
1965 {
1966     VM& vm = exec->vm();
1967     NativeCallFrameTracer tracer(&vm, exec);
1968
1969     return codePointCompareLessThan(asString(a)->value(exec), asString(b)->value(exec));
1970 }
1971
1972 uintptr_t JIT_OPERATION operationCompareStringLessEq(ExecState* exec, JSString* a, JSString* b)
1973 {
1974     VM& vm = exec->vm();
1975     NativeCallFrameTracer tracer(&vm, exec);
1976
1977     return !codePointCompareLessThan(asString(b)->value(exec), asString(a)->value(exec));
1978 }
1979
1980 uintptr_t JIT_OPERATION operationCompareStringGreater(ExecState* exec, JSString* a, JSString* b)
1981 {
1982     VM& vm = exec->vm();
1983     NativeCallFrameTracer tracer(&vm, exec);
1984
1985     return codePointCompareLessThan(asString(b)->value(exec), asString(a)->value(exec));
1986 }
1987
1988 uintptr_t JIT_OPERATION operationCompareStringGreaterEq(ExecState* exec, JSString* a, JSString* b)
1989 {
1990     VM& vm = exec->vm();
1991     NativeCallFrameTracer tracer(&vm, exec);
1992
1993     return !codePointCompareLessThan(asString(a)->value(exec), asString(b)->value(exec));
1994 }
1995
1996 void JIT_OPERATION operationNotifyWrite(ExecState* exec, WatchpointSet* set)
1997 {
1998     VM& vm = exec->vm();
1999     NativeCallFrameTracer tracer(&vm, exec);
2000
2001     set->touch(vm, "Executed NotifyWrite");
2002 }
2003
2004 void JIT_OPERATION operationThrowStackOverflowForVarargs(ExecState* exec)
2005 {
2006     VM& vm = exec->vm();
2007     NativeCallFrameTracer tracer(&vm, exec);
2008     auto scope = DECLARE_THROW_SCOPE(vm);
2009     throwStackOverflowError(exec, scope);
2010 }
2011
2012 int32_t JIT_OPERATION operationSizeOfVarargs(ExecState* exec, EncodedJSValue encodedArguments, int32_t firstVarArgOffset)
2013 {
2014     VM& vm = exec->vm();
2015     NativeCallFrameTracer tracer(&vm, exec);
2016     JSValue arguments = JSValue::decode(encodedArguments);
2017     
2018     return sizeOfVarargs(exec, arguments, firstVarArgOffset);
2019 }
2020
2021 int32_t JIT_OPERATION operationHasOwnProperty(ExecState* exec, JSObject* thisObject, EncodedJSValue encodedKey)
2022 {
2023     VM& vm = exec->vm();
2024     NativeCallFrameTracer tracer(&vm, exec);
2025     auto scope = DECLARE_THROW_SCOPE(vm);
2026
2027     JSValue key = JSValue::decode(encodedKey);
2028     Identifier propertyName = key.toPropertyKey(exec);
2029     RETURN_IF_EXCEPTION(scope, false);
2030
2031     PropertySlot slot(thisObject, PropertySlot::InternalMethodType::GetOwnProperty);
2032     bool result = thisObject->hasOwnProperty(exec, propertyName.impl(), slot);
2033     RETURN_IF_EXCEPTION(scope, false);
2034
2035     HasOwnPropertyCache* hasOwnPropertyCache = vm.hasOwnPropertyCache();
2036     ASSERT(hasOwnPropertyCache);
2037     hasOwnPropertyCache->tryAdd(vm, slot, thisObject, propertyName.impl(), result);
2038     return result;
2039 }
2040
2041 int32_t JIT_OPERATION operationArrayIndexOfString(ExecState* exec, Butterfly* butterfly, JSString* searchElement, int32_t index)
2042 {
2043     VM& vm = exec->vm();
2044     NativeCallFrameTracer tracer(&vm, exec);
2045     auto scope = DECLARE_THROW_SCOPE(vm);
2046
2047     int32_t length = butterfly->publicLength();
2048     auto data = butterfly->contiguous().data();
2049     for (; index < length; ++index) {
2050         JSValue value = data[index].get();
2051         if (!value || !value.isString())
2052             continue;
2053         auto* string = asString(value);
2054         if (string == searchElement)
2055             return index;
2056         if (string->equal(exec, searchElement))
2057             return index;
2058         RETURN_IF_EXCEPTION(scope, { });
2059     }
2060     return -1;
2061 }
2062
2063 int32_t JIT_OPERATION operationArrayIndexOfValueInt32OrContiguous(ExecState* exec, Butterfly* butterfly, EncodedJSValue encodedValue, int32_t index)
2064 {
2065     VM& vm = exec->vm();
2066     NativeCallFrameTracer tracer(&vm, exec);
2067     auto scope = DECLARE_THROW_SCOPE(vm);
2068
2069     JSValue searchElement = JSValue::decode(encodedValue);
2070
2071     int32_t length = butterfly->publicLength();
2072     auto data = butterfly->contiguous().data();
2073     for (; index < length; ++index) {
2074         JSValue value = data[index].get();
2075         if (!value)
2076             continue;
2077         if (JSValue::strictEqual(exec, searchElement, value))
2078             return index;
2079         RETURN_IF_EXCEPTION(scope, { });
2080     }
2081     return -1;
2082 }
2083
2084 int32_t JIT_OPERATION operationArrayIndexOfValueDouble(ExecState* exec, Butterfly* butterfly, EncodedJSValue encodedValue, int32_t index)
2085 {
2086     VM& vm = exec->vm();
2087     NativeCallFrameTracer tracer(&vm, exec);
2088
2089     JSValue searchElement = JSValue::decode(encodedValue);
2090
2091     if (!searchElement.isNumber())
2092         return -1;
2093     double number = searchElement.asNumber();
2094
2095     int32_t length = butterfly->publicLength();
2096     const double* data = butterfly->contiguousDouble().data();
2097     for (; index < length; ++index) {
2098         // This comparison ignores NaN.
2099         if (data[index] == number)
2100             return index;
2101     }
2102     return -1;
2103 }
2104
2105 void JIT_OPERATION operationLoadVarargs(ExecState* exec, int32_t firstElementDest, EncodedJSValue encodedArguments, int32_t offset, int32_t length, int32_t mandatoryMinimum)
2106 {
2107     VM& vm = exec->vm();
2108     NativeCallFrameTracer tracer(&vm, exec);
2109     JSValue arguments = JSValue::decode(encodedArguments);
2110     
2111     loadVarargs(exec, VirtualRegister(firstElementDest), arguments, offset, length);
2112     
2113     for (int32_t i = length; i < mandatoryMinimum; ++i)
2114         exec->r(firstElementDest + i) = jsUndefined();
2115 }
2116
2117 double JIT_OPERATION operationFModOnInts(int32_t a, int32_t b)
2118 {
2119     return fmod(a, b);
2120 }
2121
2122 #if USE(JSVALUE32_64)
2123 double JIT_OPERATION operationRandom(JSGlobalObject* globalObject)
2124 {
2125     return globalObject->weakRandomNumber();
2126 }
2127 #endif
2128
2129 JSCell* JIT_OPERATION operationStringFromCharCode(ExecState* exec, int32_t op1)
2130 {
2131     VM* vm = &exec->vm();
2132     NativeCallFrameTracer tracer(vm, exec);
2133     return JSC::stringFromCharCode(exec, op1);
2134 }
2135
2136 EncodedJSValue JIT_OPERATION operationStringFromCharCodeUntyped(ExecState* exec, EncodedJSValue encodedValue)
2137 {
2138     VM* vm = &exec->vm();
2139     NativeCallFrameTracer tracer(vm, exec);
2140     JSValue charValue = JSValue::decode(encodedValue);
2141     int32_t chInt = charValue.toUInt32(exec);
2142     return JSValue::encode(JSC::stringFromCharCode(exec, chInt));
2143 }
2144
2145 int64_t JIT_OPERATION operationConvertBoxedDoubleToInt52(EncodedJSValue encodedValue)
2146 {
2147     JSValue value = JSValue::decode(encodedValue);
2148     if (!value.isDouble())
2149         return JSValue::notInt52;
2150     return tryConvertToInt52(value.asDouble());
2151 }
2152
2153 int64_t JIT_OPERATION operationConvertDoubleToInt52(double value)
2154 {
2155     return tryConvertToInt52(value);
2156 }
2157
2158 size_t JIT_OPERATION operationDefaultHasInstance(ExecState* exec, JSCell* value, JSCell* proto) // Returns jsBoolean(True|False) on 64-bit.
2159 {
2160     VM* vm = &exec->vm();
2161     NativeCallFrameTracer tracer(vm, exec);
2162     if (JSObject::defaultHasInstance(exec, value, proto))
2163         return 1;
2164     return 0;
2165 }
2166
2167 char* JIT_OPERATION operationNewRawObject(ExecState* exec, Structure* structure, int32_t length, Butterfly* butterfly)
2168 {
2169     VM& vm = exec->vm();
2170     NativeCallFrameTracer tracer(&vm, exec);
2171
2172     if (!butterfly
2173         && (structure->outOfLineCapacity() || hasIndexedProperties(structure->indexingType()))) {
2174         IndexingHeader header;
2175         header.setVectorLength(length);
2176         header.setPublicLength(0);
2177         
2178         butterfly = Butterfly::create(
2179             vm, nullptr, 0, structure->outOfLineCapacity(),
2180             hasIndexedProperties(structure->indexingType()), header,
2181             length * sizeof(EncodedJSValue));
2182     }
2183
2184     JSObject* result = JSObject::createRawObject(exec, structure, butterfly);
2185     result->butterfly(); // Ensure that the butterfly is in to-space.
2186     return bitwise_cast<char*>(result);
2187 }
2188
2189 JSCell* JIT_OPERATION operationNewObjectWithButterfly(ExecState* exec, Structure* structure, Butterfly* butterfly)
2190 {
2191     VM& vm = exec->vm();
2192     NativeCallFrameTracer tracer(&vm, exec);
2193     
2194     if (!butterfly) {
2195         butterfly = Butterfly::create(
2196             vm, nullptr, 0, structure->outOfLineCapacity(), false, IndexingHeader(), 0);
2197     }
2198     
2199     JSObject* result = JSObject::createRawObject(exec, structure, butterfly);
2200     result->butterfly(); // Ensure that the butterfly is in to-space.
2201     return result;
2202 }
2203
2204 JSCell* JIT_OPERATION operationNewObjectWithButterflyWithIndexingHeaderAndVectorLength(ExecState* exec, Structure* structure, unsigned length, Butterfly* butterfly)
2205 {
2206     VM& vm = exec->vm();
2207     NativeCallFrameTracer tracer(&vm, exec);
2208
2209     IndexingHeader header;
2210     header.setVectorLength(length);
2211     header.setPublicLength(0);
2212     if (butterfly)
2213         *butterfly->indexingHeader() = header;
2214     else {
2215         butterfly = Butterfly::create(
2216             vm, nullptr, 0, structure->outOfLineCapacity(), true, header,
2217             sizeof(EncodedJSValue) * length);
2218     }
2219     
2220     // Paradoxically this may allocate a JSArray. That's totally cool.
2221     JSObject* result = JSObject::createRawObject(exec, structure, butterfly);
2222     result->butterfly(); // Ensure that the butterfly is in to-space.
2223     return result;
2224 }
2225
2226 JSCell* JIT_OPERATION operationNewArrayWithSpreadSlow(ExecState* exec, void* buffer, uint32_t numItems)
2227 {
2228     VM& vm = exec->vm();
2229     NativeCallFrameTracer tracer(&vm, exec);
2230     auto scope = DECLARE_THROW_SCOPE(vm);
2231
2232     EncodedJSValue* values = static_cast<EncodedJSValue*>(buffer);
2233     Checked<unsigned, RecordOverflow> checkedLength = 0;
2234     for (unsigned i = 0; i < numItems; i++) {
2235         JSValue value = JSValue::decode(values[i]);
2236         if (JSFixedArray* array = jsDynamicCast<JSFixedArray*>(vm, value))
2237             checkedLength += array->size();
2238         else
2239             ++checkedLength;
2240     }
2241
2242     if (UNLIKELY(checkedLength.hasOverflowed())) {
2243         throwOutOfMemoryError(exec, scope);
2244         return nullptr;
2245     }
2246
2247     unsigned length = checkedLength.unsafeGet();
2248     JSGlobalObject* globalObject = exec->lexicalGlobalObject();
2249     Structure* structure = globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithContiguous);
2250
2251     JSArray* result = JSArray::tryCreate(vm, structure, length);
2252     if (UNLIKELY(!result)) {
2253         throwOutOfMemoryError(exec, scope);
2254         return nullptr;
2255     }
2256     RETURN_IF_EXCEPTION(scope, nullptr);
2257
2258     unsigned index = 0;
2259     for (unsigned i = 0; i < numItems; i++) {
2260         JSValue value = JSValue::decode(values[i]);
2261         if (JSFixedArray* array = jsDynamicCast<JSFixedArray*>(vm, value)) {
2262             // We are spreading.
2263             for (unsigned i = 0; i < array->size(); i++) {
2264                 result->putDirectIndex(exec, index, array->get(i));
2265                 RETURN_IF_EXCEPTION(scope, nullptr);
2266                 ++index;
2267             }
2268         } else {
2269             // We are not spreading.
2270             result->putDirectIndex(exec, index, value);
2271             RETURN_IF_EXCEPTION(scope, nullptr);
2272             ++index;
2273         }
2274     }
2275
2276     return result;
2277 }
2278
2279 JSCell* JIT_OPERATION operationSpreadGeneric(ExecState* exec, JSCell* iterable)
2280 {
2281     VM& vm = exec->vm();
2282     NativeCallFrameTracer tracer(&vm, exec);
2283
2284     auto throwScope = DECLARE_THROW_SCOPE(vm);
2285
2286     if (isJSArray(iterable)) {
2287         JSArray* array = jsCast<JSArray*>(iterable);
2288         if (array->isIteratorProtocolFastAndNonObservable()) {
2289             throwScope.release();
2290             return JSFixedArray::createFromArray(exec, vm, array);
2291         }
2292     }
2293
2294     // FIXME: we can probably make this path faster by having our caller JS code call directly into
2295     // the iteration protocol builtin: https://bugs.webkit.org/show_bug.cgi?id=164520
2296
2297     JSGlobalObject* globalObject = exec->lexicalGlobalObject();
2298     JSArray* array;
2299     {
2300         JSFunction* iterationFunction = globalObject->iteratorProtocolFunction();
2301         CallData callData;
2302         CallType callType = JSC::getCallData(iterationFunction, callData);
2303         ASSERT(callType != CallType::None);
2304
2305         MarkedArgumentBuffer arguments;
2306         arguments.append(iterable);
2307         JSValue arrayResult = call(exec, iterationFunction, callType, callData, jsNull(), arguments);
2308         RETURN_IF_EXCEPTION(throwScope, nullptr);
2309         array = jsCast<JSArray*>(arrayResult);
2310     }
2311
2312     throwScope.release();
2313     return JSFixedArray::createFromArray(exec, vm, array);
2314 }
2315
2316 JSCell* JIT_OPERATION operationSpreadFastArray(ExecState* exec, JSCell* cell)
2317 {
2318     VM& vm = exec->vm();
2319     NativeCallFrameTracer tracer(&vm, exec);
2320
2321     ASSERT(isJSArray(cell));
2322     JSArray* array = jsCast<JSArray*>(cell);
2323     ASSERT(array->isIteratorProtocolFastAndNonObservable());
2324
2325     return JSFixedArray::createFromArray(exec, vm, array);
2326 }
2327
2328 void JIT_OPERATION operationProcessTypeProfilerLogDFG(ExecState* exec) 
2329 {
2330     VM& vm = exec->vm();
2331     NativeCallFrameTracer tracer(&vm, exec);
2332
2333     vm.typeProfilerLog()->processLogEntries(ASCIILiteral("Log Full, called from inside DFG."));
2334 }
2335
2336 EncodedJSValue JIT_OPERATION operationResolveScopeForHoistingFuncDeclInEval(ExecState* exec, JSScope* scope, UniquedStringImpl* impl)
2337 {
2338     VM& vm = exec->vm();
2339     NativeCallFrameTracer tracer(&vm, exec);
2340         
2341     JSValue resolvedScope = JSScope::resolveScopeForHoistingFuncDeclInEval(exec, scope, Identifier::fromUid(exec, impl));
2342     return JSValue::encode(resolvedScope);
2343 }
2344     
2345 JSCell* JIT_OPERATION operationResolveScope(ExecState* exec, JSScope* scope, UniquedStringImpl* impl)
2346 {
2347     VM& vm = exec->vm();
2348     NativeCallFrameTracer tracer(&vm, exec);
2349
2350     JSObject* resolvedScope = JSScope::resolve(exec, scope, Identifier::fromUid(exec, impl));
2351     return resolvedScope;
2352 }
2353
2354 EncodedJSValue JIT_OPERATION operationGetDynamicVar(ExecState* exec, JSObject* scope, UniquedStringImpl* impl, unsigned getPutInfoBits)
2355 {
2356     VM& vm = exec->vm();
2357     NativeCallFrameTracer tracer(&vm, exec);
2358     auto throwScope = DECLARE_THROW_SCOPE(vm);
2359
2360     Identifier ident = Identifier::fromUid(exec, impl);
2361     throwScope.release();
2362     return JSValue::encode(scope->getPropertySlot(exec, ident, [&] (bool found, PropertySlot& slot) -> JSValue {
2363         if (!found) {
2364             GetPutInfo getPutInfo(getPutInfoBits);
2365             if (getPutInfo.resolveMode() == ThrowIfNotFound)
2366                 throwException(exec, throwScope, createUndefinedVariableError(exec, ident));
2367             return jsUndefined();
2368         }
2369
2370         if (scope->isGlobalLexicalEnvironment()) {
2371             // When we can't statically prove we need a TDZ check, we must perform the check on the slow path.
2372             JSValue result = slot.getValue(exec, ident);
2373             if (result == jsTDZValue()) {
2374                 throwException(exec, throwScope, createTDZError(exec));
2375                 return jsUndefined();
2376             }
2377             return result;
2378         }
2379
2380         return slot.getValue(exec, ident);
2381     }));
2382 }
2383
2384 void JIT_OPERATION operationPutDynamicVar(ExecState* exec, JSObject* scope, EncodedJSValue value, UniquedStringImpl* impl, unsigned getPutInfoBits)
2385 {
2386     VM& vm = exec->vm();
2387     NativeCallFrameTracer tracer(&vm, exec);
2388     auto throwScope = DECLARE_THROW_SCOPE(vm);
2389
2390     const Identifier& ident = Identifier::fromUid(exec, impl);
2391     GetPutInfo getPutInfo(getPutInfoBits);
2392     bool hasProperty = scope->hasProperty(exec, ident);
2393     RETURN_IF_EXCEPTION(throwScope, void());
2394     if (hasProperty
2395         && scope->isGlobalLexicalEnvironment()
2396         && !isInitialization(getPutInfo.initializationMode())) {
2397         // When we can't statically prove we need a TDZ check, we must perform the check on the slow path.
2398         PropertySlot slot(scope, PropertySlot::InternalMethodType::Get);
2399         JSGlobalLexicalEnvironment::getOwnPropertySlot(scope, exec, ident, slot);
2400         if (slot.getValue(exec, ident) == jsTDZValue()) {
2401             throwException(exec, throwScope, createTDZError(exec));
2402             return;
2403         }
2404     }
2405
2406     if (getPutInfo.resolveMode() == ThrowIfNotFound && !hasProperty) {
2407         throwException(exec, throwScope, createUndefinedVariableError(exec, ident));
2408         return;
2409     }
2410
2411     CodeOrigin origin = exec->codeOrigin();
2412     bool strictMode;
2413     if (origin.inlineCallFrame)
2414         strictMode = origin.inlineCallFrame->baselineCodeBlock->isStrictMode();
2415     else
2416         strictMode = exec->codeBlock()->isStrictMode();
2417     PutPropertySlot slot(scope, strictMode, PutPropertySlot::UnknownContext, isInitialization(getPutInfo.initializationMode()));
2418     throwScope.release();
2419     scope->methodTable(vm)->put(scope, exec, ident, JSValue::decode(value), slot);
2420 }
2421
2422 int32_t JIT_OPERATION operationMapHash(ExecState* exec, EncodedJSValue input)
2423 {
2424     VM& vm = exec->vm();
2425     NativeCallFrameTracer tracer(&vm, exec);
2426
2427     return jsMapHash(exec, vm, normalizeMapKey(JSValue::decode(input)));
2428 }
2429
2430 JSCell* JIT_OPERATION operationJSMapFindBucket(ExecState* exec, JSCell* map, EncodedJSValue key, int32_t hash)
2431 {
2432     VM& vm = exec->vm();
2433     NativeCallFrameTracer tracer(&vm, exec);
2434     JSMap::BucketType** bucket = jsCast<JSMap*>(map)->findBucket(exec, normalizeMapKey(JSValue::decode(key)), hash);
2435     if (!bucket)
2436         return vm.sentinelMapBucket.get();
2437     return *bucket;
2438 }
2439
2440 JSCell* JIT_OPERATION operationJSSetFindBucket(ExecState* exec, JSCell* map, EncodedJSValue key, int32_t hash)
2441 {
2442     VM& vm = exec->vm();
2443     NativeCallFrameTracer tracer(&vm, exec);
2444     JSSet::BucketType** bucket = jsCast<JSSet*>(map)->findBucket(exec, normalizeMapKey(JSValue::decode(key)), hash);
2445     if (!bucket)
2446         return vm.sentinelSetBucket.get();
2447     return *bucket;
2448 }
2449
2450 void JIT_OPERATION operationThrowDFG(ExecState* exec, EncodedJSValue valueToThrow)
2451 {
2452     VM& vm = exec->vm();
2453     NativeCallFrameTracer tracer(&vm, exec);
2454     auto scope = DECLARE_THROW_SCOPE(vm);
2455     scope.throwException(exec, JSValue::decode(valueToThrow));
2456 }
2457
2458 void JIT_OPERATION operationThrowStaticError(ExecState* exec, JSString* message, uint32_t errorType)
2459 {
2460     VM& vm = exec->vm();
2461     NativeCallFrameTracer tracer(&vm, exec);
2462     auto scope = DECLARE_THROW_SCOPE(vm);
2463     String errorMessage = message->value(exec);
2464     scope.throwException(exec, createError(exec, static_cast<ErrorType>(errorType), errorMessage));
2465 }
2466
2467 extern "C" void JIT_OPERATION triggerReoptimizationNow(CodeBlock* codeBlock, OSRExitBase* exit)
2468 {
2469     // It's sort of preferable that we don't GC while in here. Anyways, doing so wouldn't
2470     // really be profitable.
2471     DeferGCForAWhile deferGC(codeBlock->vm()->heap);
2472     
2473     if (Options::verboseOSR())
2474         dataLog(*codeBlock, ": Entered reoptimize\n");
2475     // We must be called with the baseline code block.
2476     ASSERT(JITCode::isBaselineCode(codeBlock->jitType()));
2477
2478     // If I am my own replacement, then reoptimization has already been triggered.
2479     // This can happen in recursive functions.
2480     if (codeBlock->replacement() == codeBlock) {
2481         if (Options::verboseOSR())
2482             dataLog(*codeBlock, ": Not reoptimizing because we've already been jettisoned.\n");
2483         return;
2484     }
2485     
2486     // Otherwise, the replacement must be optimized code. Use this as an opportunity
2487     // to check our logic.
2488     ASSERT(codeBlock->hasOptimizedReplacement());
2489     CodeBlock* optimizedCodeBlock = codeBlock->replacement();
2490     ASSERT(JITCode::isOptimizingJIT(optimizedCodeBlock->jitType()));
2491     
2492     bool didTryToEnterIntoInlinedLoops = false;
2493     for (InlineCallFrame* inlineCallFrame = exit->m_codeOrigin.inlineCallFrame; inlineCallFrame; inlineCallFrame = inlineCallFrame->directCaller.inlineCallFrame) {
2494         if (inlineCallFrame->baselineCodeBlock->ownerScriptExecutable()->didTryToEnterInLoop()) {
2495             didTryToEnterIntoInlinedLoops = true;
2496             break;
2497         }
2498     }
2499
2500     // In order to trigger reoptimization, one of two things must have happened:
2501     // 1) We exited more than some number of times.
2502     // 2) We exited and got stuck in a loop, and now we're exiting again.
2503     bool didExitABunch = optimizedCodeBlock->shouldReoptimizeNow();
2504     bool didGetStuckInLoop =
2505         (codeBlock->checkIfOptimizationThresholdReached() || didTryToEnterIntoInlinedLoops)
2506         && optimizedCodeBlock->shouldReoptimizeFromLoopNow();
2507     
2508     if (!didExitABunch && !didGetStuckInLoop) {
2509         if (Options::verboseOSR())
2510             dataLog(*codeBlock, ": Not reoptimizing ", *optimizedCodeBlock, " because it either didn't exit enough or didn't loop enough after exit.\n");
2511         codeBlock->optimizeAfterLongWarmUp();
2512         return;
2513     }
2514
2515     optimizedCodeBlock->jettison(Profiler::JettisonDueToOSRExit, CountReoptimization);
2516 }
2517
2518 #if ENABLE(FTL_JIT)
2519 static bool shouldTriggerFTLCompile(CodeBlock* codeBlock, JITCode* jitCode)
2520 {
2521     if (codeBlock->baselineVersion()->m_didFailFTLCompilation) {
2522         CODEBLOCK_LOG_EVENT(codeBlock, "abortFTLCompile", ());
2523         if (Options::verboseOSR())
2524             dataLog("Deferring FTL-optimization of ", *codeBlock, " indefinitely because there was an FTL failure.\n");
2525         jitCode->dontOptimizeAnytimeSoon(codeBlock);
2526         return false;
2527     }
2528
2529     if (!codeBlock->hasOptimizedReplacement()
2530         && !jitCode->checkIfOptimizationThresholdReached(codeBlock)) {
2531         CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("counter = ", jitCode->tierUpCounter));
2532         if (Options::verboseOSR())
2533             dataLog("Choosing not to FTL-optimize ", *codeBlock, " yet.\n");
2534         return false;
2535     }
2536     return true;
2537 }
2538
2539 static void triggerFTLReplacementCompile(VM* vm, CodeBlock* codeBlock, JITCode* jitCode)
2540 {
2541     if (codeBlock->codeType() == GlobalCode) {
2542         // Global code runs once, so we don't want to do anything. We don't want to defer indefinitely,
2543         // since this may have been spuriously called from tier-up initiated in a loop, and that loop may
2544         // later want to run faster code. Deferring for warm-up seems safest.
2545         jitCode->optimizeAfterWarmUp(codeBlock);
2546         return;
2547     }
2548     
2549     Worklist::State worklistState;
2550     if (Worklist* worklist = existingGlobalFTLWorklistOrNull()) {
2551         worklistState = worklist->completeAllReadyPlansForVM(
2552             *vm, CompilationKey(codeBlock->baselineVersion(), FTLMode));
2553     } else
2554         worklistState = Worklist::NotKnown;
2555     
2556     if (worklistState == Worklist::Compiling) {
2557         CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("still compiling"));
2558         jitCode->setOptimizationThresholdBasedOnCompilationResult(
2559             codeBlock, CompilationDeferred);
2560         return;
2561     }
2562     
2563     if (codeBlock->hasOptimizedReplacement()) {
2564         CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("has replacement"));
2565         // That's great, we've compiled the code - next time we call this function,
2566         // we'll enter that replacement.
2567         jitCode->optimizeSoon(codeBlock);
2568         return;
2569     }
2570     
2571     if (worklistState == Worklist::Compiled) {
2572         CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("compiled and failed"));
2573         // This means that we finished compiling, but failed somehow; in that case the
2574         // thresholds will be set appropriately.
2575         if (Options::verboseOSR())
2576             dataLog("Code block ", *codeBlock, " was compiled but it doesn't have an optimized replacement.\n");
2577         return;
2578     }
2579
2580     CODEBLOCK_LOG_EVENT(codeBlock, "triggerFTLReplacement", ());
2581     // We need to compile the code.
2582     compile(
2583         *vm, codeBlock->newReplacement(), codeBlock, FTLMode, UINT_MAX,
2584         Operands<JSValue>(), ToFTLDeferredCompilationCallback::create());
2585
2586     // If we reached here, the counter has not be reset. Do that now.
2587     jitCode->setOptimizationThresholdBasedOnCompilationResult(
2588         codeBlock, CompilationDeferred);
2589 }
2590
2591 void JIT_OPERATION triggerTierUpNow(ExecState* exec)
2592 {
2593     VM* vm = &exec->vm();
2594     NativeCallFrameTracer tracer(vm, exec);
2595     DeferGCForAWhile deferGC(vm->heap);
2596     CodeBlock* codeBlock = exec->codeBlock();
2597     
2598     if (codeBlock->jitType() != JITCode::DFGJIT) {
2599         dataLog("Unexpected code block in DFG->FTL tier-up: ", *codeBlock, "\n");
2600         RELEASE_ASSERT_NOT_REACHED();
2601     }
2602     
2603     JITCode* jitCode = codeBlock->jitCode()->dfg();
2604     
2605     if (Options::verboseOSR()) {
2606         dataLog(
2607             *codeBlock, ": Entered triggerTierUpNow with executeCounter = ",
2608             jitCode->tierUpCounter, "\n");
2609     }
2610
2611     if (shouldTriggerFTLCompile(codeBlock, jitCode))
2612         triggerFTLReplacementCompile(vm, codeBlock, jitCode);
2613
2614     if (codeBlock->hasOptimizedReplacement()) {
2615         if (jitCode->tierUpEntryTriggers.isEmpty()) {
2616             CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("replacement in place, delaying indefinitely"));
2617             // There is nothing more we can do, the only way this will be entered
2618             // is through the function entry point.
2619             jitCode->dontOptimizeAnytimeSoon(codeBlock);
2620             return;
2621         }
2622         if (jitCode->osrEntryBlock() && jitCode->tierUpEntryTriggers.size() == 1) {
2623             CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("trigger in place, delaying indefinitely"));
2624             // There is only one outer loop and its trigger must have been set
2625             // when the plan completed.
2626             // Exiting the inner loop is useless, we can ignore the counter and leave
2627             // the trigger do its job.
2628             jitCode->dontOptimizeAnytimeSoon(codeBlock);
2629             return;
2630         }
2631     }
2632 }
2633
2634 static char* tierUpCommon(ExecState* exec, unsigned originBytecodeIndex, unsigned osrEntryBytecodeIndex)
2635 {
2636     VM* vm = &exec->vm();
2637     CodeBlock* codeBlock = exec->codeBlock();
2638
2639     // Resolve any pending plan for OSR Enter on this function.
2640     Worklist::State worklistState;
2641     if (Worklist* worklist = existingGlobalFTLWorklistOrNull()) {
2642         worklistState = worklist->completeAllReadyPlansForVM(
2643             *vm, CompilationKey(codeBlock->baselineVersion(), FTLForOSREntryMode));
2644     } else
2645         worklistState = Worklist::NotKnown;
2646
2647     JITCode* jitCode = codeBlock->jitCode()->dfg();
2648
2649     // The following is only true for triggerTierUpNowInLoop, which can never
2650     // be an OSR entry.
2651     bool canOSRFromHere = originBytecodeIndex == osrEntryBytecodeIndex;
2652
2653     bool triggeredSlowPathToStartCompilation = false;
2654     auto tierUpEntryTriggers = jitCode->tierUpEntryTriggers.find(originBytecodeIndex);
2655     if (tierUpEntryTriggers != jitCode->tierUpEntryTriggers.end()) {
2656         switch (tierUpEntryTriggers->value) {
2657         case JITCode::TriggerReason::DontTrigger:
2658             // The trigger isn't set, we entered because the counter reached its
2659             // threshold.
2660             break;
2661
2662         case JITCode::TriggerReason::CompilationDone:
2663             // The trigger was set because compilation completed. Don't unset it
2664             // so that further DFG executions OSR enters as well.
2665             RELEASE_ASSERT(canOSRFromHere);
2666             break;
2667
2668         case JITCode::TriggerReason::StartCompilation:
2669             // We were asked to enter as soon as possible and start compiling an
2670             // entry for the current bytecode location. Unset this trigger so we
2671             // don't continually enter.
2672             RELEASE_ASSERT(canOSRFromHere);
2673             tierUpEntryTriggers->value = JITCode::TriggerReason::DontTrigger;
2674             triggeredSlowPathToStartCompilation = true;
2675             break;
2676         }
2677     }
2678
2679     if (worklistState == Worklist::Compiling) {
2680         CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("still compiling"));
2681         jitCode->setOptimizationThresholdBasedOnCompilationResult(
2682             codeBlock, CompilationDeferred);
2683         return nullptr;
2684     }
2685
2686     if (worklistState == Worklist::Compiled) {
2687         CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("compiled and failed"));
2688         // This means that compilation failed and we already set the thresholds.
2689         if (Options::verboseOSR())
2690             dataLog("Code block ", *codeBlock, " was compiled but it doesn't have an optimized replacement.\n");
2691         return nullptr;
2692     }
2693
2694     // If we can OSR Enter, do it right away.
2695     if (canOSRFromHere) {
2696         unsigned streamIndex = jitCode->bytecodeIndexToStreamIndex.get(originBytecodeIndex);
2697         if (CodeBlock* entryBlock = jitCode->osrEntryBlock()) {
2698             if (Options::verboseOSR())
2699                 dataLog("OSR entry: From ", RawPointer(jitCode), " got entry block ", RawPointer(entryBlock), "\n");
2700             if (void* address = FTL::prepareOSREntry(exec, codeBlock, entryBlock, originBytecodeIndex, streamIndex)) {
2701                 CODEBLOCK_LOG_EVENT(entryBlock, "osrEntry", ("at bc#", originBytecodeIndex));
2702                 return static_cast<char*>(address);
2703             }
2704         }
2705     }
2706
2707     // - If we don't have an FTL code block, then try to compile one.
2708     // - If we do have an FTL code block, then try to enter for a while.
2709     // - If we couldn't enter for a while, then trigger OSR entry.
2710
2711     if (!shouldTriggerFTLCompile(codeBlock, jitCode) && !triggeredSlowPathToStartCompilation)
2712         return nullptr;
2713
2714     if (!jitCode->neverExecutedEntry && !triggeredSlowPathToStartCompilation) {
2715         triggerFTLReplacementCompile(vm, codeBlock, jitCode);
2716
2717         if (!codeBlock->hasOptimizedReplacement())
2718             return nullptr;
2719
2720         if (jitCode->osrEntryRetry < Options::ftlOSREntryRetryThreshold()) {
2721             CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("avoiding OSR entry compile"));
2722             jitCode->osrEntryRetry++;
2723             return nullptr;
2724         }
2725     } else
2726         CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("avoiding replacement compile"));
2727
2728     // It's time to try to compile code for OSR entry.
2729     if (CodeBlock* entryBlock = jitCode->osrEntryBlock()) {
2730         if (jitCode->osrEntryRetry < Options::ftlOSREntryRetryThreshold()) {
2731             CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("OSR entry failed, OSR entry threshold not met"));
2732             jitCode->osrEntryRetry++;
2733             jitCode->setOptimizationThresholdBasedOnCompilationResult(
2734                 codeBlock, CompilationDeferred);
2735             return nullptr;
2736         }
2737
2738         FTL::ForOSREntryJITCode* entryCode = entryBlock->jitCode()->ftlForOSREntry();
2739         entryCode->countEntryFailure();
2740         if (entryCode->entryFailureCount() <
2741             Options::ftlOSREntryFailureCountForReoptimization()) {
2742             CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("OSR entry failed"));
2743             jitCode->setOptimizationThresholdBasedOnCompilationResult(
2744                 codeBlock, CompilationDeferred);
2745             return nullptr;
2746         }
2747
2748         // OSR entry failed. Oh no! This implies that we need to retry. We retry
2749         // without exponential backoff and we only do this for the entry code block.
2750         CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("OSR entry failed too many times"));
2751         unsigned osrEntryBytecode = entryBlock->jitCode()->ftlForOSREntry()->bytecodeIndex();
2752         jitCode->clearOSREntryBlock();
2753         jitCode->osrEntryRetry = 0;
2754         jitCode->tierUpEntryTriggers.set(osrEntryBytecode, JITCode::TriggerReason::DontTrigger);
2755         jitCode->setOptimizationThresholdBasedOnCompilationResult(
2756             codeBlock, CompilationDeferred);
2757         return nullptr;
2758     }
2759
2760     if (!canOSRFromHere) {
2761         // We can't OSR from here, or even start a compilation because doing so
2762         // calls jitCode->reconstruct which would get the wrong state.
2763         if (Options::verboseOSR())
2764             dataLog("Non-OSR-able bc#", originBytecodeIndex, " in ", *codeBlock, " setting parent loop bc#", osrEntryBytecodeIndex, "'s trigger and backing off.\n");
2765         jitCode->tierUpEntryTriggers.set(osrEntryBytecodeIndex, JITCode::TriggerReason::StartCompilation);
2766         jitCode->setOptimizationThresholdBasedOnCompilationResult(codeBlock, CompilationDeferred);
2767         return nullptr;
2768     }
2769
2770     unsigned streamIndex = jitCode->bytecodeIndexToStreamIndex.get(osrEntryBytecodeIndex);
2771
2772     if (!triggeredSlowPathToStartCompilation) {
2773         auto tierUpHierarchyEntry = jitCode->tierUpInLoopHierarchy.find(osrEntryBytecodeIndex);
2774         if (tierUpHierarchyEntry != jitCode->tierUpInLoopHierarchy.end()) {
2775             for (unsigned osrEntryCandidate : tierUpHierarchyEntry->value) {
2776                 if (jitCode->tierUpEntrySeen.contains(osrEntryCandidate)) {
2777                     // Ask an enclosing loop to compile, instead of doing so here.
2778                     if (Options::verboseOSR())
2779                         dataLog("Inner-loop bc#", originBytecodeIndex, " in ", *codeBlock, " setting parent loop bc#", osrEntryCandidate, "'s trigger and backing off.\n");
2780                     jitCode->tierUpEntryTriggers.set(osrEntryCandidate, JITCode::TriggerReason::StartCompilation);
2781                     jitCode->setOptimizationThresholdBasedOnCompilationResult(codeBlock, CompilationDeferred);
2782                     return nullptr;
2783                 }
2784             }
2785         }
2786     }
2787
2788     // We aren't compiling and haven't compiled anything for OSR entry. So, try to compile
2789     // something.
2790     auto triggerIterator = jitCode->tierUpEntryTriggers.find(osrEntryBytecodeIndex);
2791     RELEASE_ASSERT(triggerIterator != jitCode->tierUpEntryTriggers.end());
2792     JITCode::TriggerReason* triggerAddress = &(triggerIterator->value);
2793
2794     Operands<JSValue> mustHandleValues;
2795     jitCode->reconstruct(
2796         exec, codeBlock, CodeOrigin(osrEntryBytecodeIndex), streamIndex, mustHandleValues);
2797     CodeBlock* replacementCodeBlock = codeBlock->newReplacement();
2798
2799     CODEBLOCK_LOG_EVENT(codeBlock, "triggerFTLOSR", ());
2800     CompilationResult forEntryResult = compile(
2801         *vm, replacementCodeBlock, codeBlock, FTLForOSREntryMode, osrEntryBytecodeIndex,
2802         mustHandleValues, ToFTLForOSREntryDeferredCompilationCallback::create(triggerAddress));
2803
2804     if (jitCode->neverExecutedEntry)
2805         triggerFTLReplacementCompile(vm, codeBlock, jitCode);
2806
2807     if (forEntryResult != CompilationSuccessful) {
2808         CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("OSR ecompilation not successful"));
2809         jitCode->setOptimizationThresholdBasedOnCompilationResult(
2810             codeBlock, CompilationDeferred);
2811         return nullptr;
2812     }
2813     
2814     CODEBLOCK_LOG_EVENT(jitCode->osrEntryBlock(), "osrEntry", ("at bc#", originBytecodeIndex));
2815     // It's possible that the for-entry compile already succeeded. In that case OSR
2816     // entry will succeed unless we ran out of stack. It's not clear what we should do.
2817     // We signal to try again after a while if that happens.
2818     if (Options::verboseOSR())
2819         dataLog("Immediate OSR entry: From ", RawPointer(jitCode), " got entry block ", RawPointer(jitCode->osrEntryBlock()), "\n");
2820     void* address = FTL::prepareOSREntry(
2821         exec, codeBlock, jitCode->osrEntryBlock(), originBytecodeIndex, streamIndex);
2822     return static_cast<char*>(address);
2823 }
2824
2825 void JIT_OPERATION triggerTierUpNowInLoop(ExecState* exec, unsigned bytecodeIndex)
2826 {
2827     VM* vm = &exec->vm();
2828     NativeCallFrameTracer tracer(vm, exec);
2829     DeferGCForAWhile deferGC(vm->heap);
2830     CodeBlock* codeBlock = exec->codeBlock();
2831
2832     if (codeBlock->jitType() != JITCode::DFGJIT) {
2833         dataLog("Unexpected code block in DFG->FTL tier-up: ", *codeBlock, "\n");
2834         RELEASE_ASSERT_NOT_REACHED();
2835     }
2836
2837     JITCode* jitCode = codeBlock->jitCode()->dfg();
2838
2839     if (Options::verboseOSR()) {
2840         dataLog(
2841             *codeBlock, ": Entered triggerTierUpNowInLoop with executeCounter = ",
2842             jitCode->tierUpCounter, "\n");
2843     }
2844
2845     auto tierUpHierarchyEntry = jitCode->tierUpInLoopHierarchy.find(bytecodeIndex);
2846     if (tierUpHierarchyEntry != jitCode->tierUpInLoopHierarchy.end()
2847         && !tierUpHierarchyEntry->value.isEmpty()) {
2848         tierUpCommon(exec, bytecodeIndex, tierUpHierarchyEntry->value.first());
2849     } else if (shouldTriggerFTLCompile(codeBlock, jitCode))
2850         triggerFTLReplacementCompile(vm, codeBlock, jitCode);
2851
2852     // Since we cannot OSR Enter here, the default "optimizeSoon()" is not useful.
2853     if (codeBlock->hasOptimizedReplacement()) {
2854         CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("OSR in loop failed, deferring"));
2855         jitCode->setOptimizationThresholdBasedOnCompilationResult(codeBlock, CompilationDeferred);
2856     }
2857 }
2858
2859 char* JIT_OPERATION triggerOSREntryNow(ExecState* exec, unsigned bytecodeIndex)
2860 {
2861     VM* vm = &exec->vm();
2862     NativeCallFrameTracer tracer(vm, exec);
2863     DeferGCForAWhile deferGC(vm->heap);
2864     CodeBlock* codeBlock = exec->codeBlock();
2865
2866     if (codeBlock->jitType() != JITCode::DFGJIT) {
2867         dataLog("Unexpected code block in DFG->FTL tier-up: ", *codeBlock, "\n");
2868         RELEASE_ASSERT_NOT_REACHED();
2869     }
2870
2871     JITCode* jitCode = codeBlock->jitCode()->dfg();
2872     jitCode->tierUpEntrySeen.add(bytecodeIndex);
2873
2874     if (Options::verboseOSR()) {
2875         dataLog(
2876             *codeBlock, ": Entered triggerOSREntryNow with executeCounter = ",
2877             jitCode->tierUpCounter, "\n");
2878     }
2879
2880     return tierUpCommon(exec, bytecodeIndex, bytecodeIndex);
2881 }
2882
2883 #endif // ENABLE(FTL_JIT)
2884
2885 } // extern "C"
2886 } } // namespace JSC::DFG
2887
2888 #endif // ENABLE(DFG_JIT)
2889
2890 #endif // ENABLE(JIT)