Added RETURN_IF_EXCEPTION() macro and use it for exception checks.
[WebKit-https.git] / Source / JavaScriptCore / dfg / DFGOperations.cpp
1 /*
2  * Copyright (C) 2011, 2013-2016 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 "DirectArguments.h"
42 #include "FTLForOSREntryJITCode.h"
43 #include "FTLOSREntry.h"
44 #include "HasOwnPropertyCache.h"
45 #include "HostCallReturnValue.h"
46 #include "Interpreter.h"
47 #include "JIT.h"
48 #include "JITExceptions.h"
49 #include "JSCInlines.h"
50 #include "JSGenericTypedArrayViewConstructorInlines.h"
51 #include "JSLexicalEnvironment.h"
52 #include "JSMap.h"
53 #include "JSSet.h"
54 #include "ObjectConstructor.h"
55 #include "Operations.h"
56 #include "RegExpObject.h"
57 #include "Repatch.h"
58 #include "ScopedArguments.h"
59 #include "StringConstructor.h"
60 #include "SuperSampler.h"
61 #include "Symbol.h"
62 #include "TypeProfilerLog.h"
63 #include "TypedArrayInlines.h"
64 #include "VMInlines.h"
65 #include <wtf/InlineASM.h>
66
67 #if ENABLE(JIT)
68 #if ENABLE(DFG_JIT)
69
70 namespace JSC { namespace DFG {
71
72 template<bool strict, bool direct>
73 static inline void putByVal(ExecState* exec, JSValue baseValue, uint32_t index, JSValue value)
74 {
75     VM& vm = exec->vm();
76     NativeCallFrameTracer tracer(&vm, exec);
77     ASSERT(isIndex(index));
78     if (direct) {
79         RELEASE_ASSERT(baseValue.isObject());
80         asObject(baseValue)->putDirectIndex(exec, index, value, 0, strict ? PutDirectIndexShouldThrow : PutDirectIndexShouldNotThrow);
81         return;
82     }
83     if (baseValue.isObject()) {
84         JSObject* object = asObject(baseValue);
85         if (object->canSetIndexQuickly(index)) {
86             object->setIndexQuickly(vm, index, value);
87             return;
88         }
89
90         object->methodTable(vm)->putByIndex(object, exec, index, value, strict);
91         return;
92     }
93
94     baseValue.putByIndex(exec, index, value, strict);
95 }
96
97 template<bool strict, bool direct>
98 ALWAYS_INLINE static void JIT_OPERATION operationPutByValInternal(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
99 {
100     VM* vm = &exec->vm();
101     auto scope = DECLARE_THROW_SCOPE(*vm);
102     NativeCallFrameTracer tracer(vm, exec);
103
104     JSValue baseValue = JSValue::decode(encodedBase);
105     JSValue property = JSValue::decode(encodedProperty);
106     JSValue value = JSValue::decode(encodedValue);
107
108     if (LIKELY(property.isUInt32())) {
109         // Despite its name, JSValue::isUInt32 will return true only for positive boxed int32_t; all those values are valid array indices.
110         ASSERT(isIndex(property.asUInt32()));
111         putByVal<strict, direct>(exec, baseValue, property.asUInt32(), value);
112         return;
113     }
114
115     if (property.isDouble()) {
116         double propertyAsDouble = property.asDouble();
117         uint32_t propertyAsUInt32 = static_cast<uint32_t>(propertyAsDouble);
118         if (propertyAsDouble == propertyAsUInt32 && isIndex(propertyAsUInt32)) {
119             putByVal<strict, direct>(exec, baseValue, propertyAsUInt32, value);
120             return;
121         }
122     }
123
124     // Don't put to an object if toString throws an exception.
125     auto propertyName = property.toPropertyKey(exec);
126     RETURN_IF_EXCEPTION(scope, void());
127
128     PutPropertySlot slot(baseValue, strict);
129     if (direct) {
130         RELEASE_ASSERT(baseValue.isObject());
131         if (Optional<uint32_t> index = parseIndex(propertyName))
132             asObject(baseValue)->putDirectIndex(exec, index.value(), value, 0, strict ? PutDirectIndexShouldThrow : PutDirectIndexShouldNotThrow);
133         else
134             asObject(baseValue)->putDirect(*vm, propertyName, value, slot);
135     } else
136         baseValue.put(exec, propertyName, value, slot);
137 }
138
139 template<typename ViewClass>
140 char* newTypedArrayWithSize(ExecState* exec, Structure* structure, int32_t size, char* vector)
141 {
142     VM& vm = exec->vm();
143     NativeCallFrameTracer tracer(&vm, exec);
144     auto scope = DECLARE_THROW_SCOPE(vm);
145
146     if (size < 0) {
147         throwException(exec, scope, createRangeError(exec, ASCIILiteral("Requested length is negative")));
148         return 0;
149     }
150     
151     if (vector)
152         return bitwise_cast<char*>(ViewClass::createWithFastVector(exec, structure, size, vector));
153     
154     return bitwise_cast<char*>(ViewClass::create(exec, structure, size));
155 }
156
157 template <bool strict>
158 static ALWAYS_INLINE void putWithThis(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedThis, EncodedJSValue encodedValue, const Identifier& ident)
159 {
160     JSValue baseValue = JSValue::decode(encodedBase);
161     JSValue thisVal = JSValue::decode(encodedThis);
162     JSValue putValue = JSValue::decode(encodedValue);
163     PutPropertySlot slot(thisVal, strict);
164     baseValue.putInline(exec, ident, putValue, slot);
165 }
166
167 extern "C" {
168
169 EncodedJSValue JIT_OPERATION operationToThis(ExecState* exec, EncodedJSValue encodedOp)
170 {
171     VM* vm = &exec->vm();
172     NativeCallFrameTracer tracer(vm, exec);
173
174     return JSValue::encode(JSValue::decode(encodedOp).toThis(exec, NotStrictMode));
175 }
176
177 EncodedJSValue JIT_OPERATION operationToThisStrict(ExecState* exec, EncodedJSValue encodedOp)
178 {
179     VM* vm = &exec->vm();
180     NativeCallFrameTracer tracer(vm, exec);
181
182     return JSValue::encode(JSValue::decode(encodedOp).toThis(exec, StrictMode));
183 }
184
185 JSCell* JIT_OPERATION operationCreateThis(ExecState* exec, JSObject* constructor, int32_t inlineCapacity)
186 {
187     VM& vm = exec->vm();
188     NativeCallFrameTracer tracer(&vm, exec);
189     auto scope = DECLARE_THROW_SCOPE(vm);
190     if (constructor->type() == JSFunctionType)
191         return constructEmptyObject(exec, jsCast<JSFunction*>(constructor)->rareData(exec, inlineCapacity)->objectAllocationProfile()->structure());
192
193     JSValue proto = constructor->get(exec, exec->propertyNames().prototype);
194     RETURN_IF_EXCEPTION(scope, nullptr);
195     if (proto.isObject())
196         return constructEmptyObject(exec, asObject(proto));
197     return constructEmptyObject(exec);
198 }
199
200 JSCell* JIT_OPERATION operationObjectConstructor(ExecState* exec, JSGlobalObject* globalObject, EncodedJSValue encodedTarget)
201 {
202     VM* vm = &exec->vm();
203     NativeCallFrameTracer tracer(vm, exec);
204
205     JSValue value = JSValue::decode(encodedTarget);
206     ASSERT(!value.isObject());
207
208     if (value.isUndefinedOrNull())
209         return constructEmptyObject(exec, globalObject->objectPrototype());
210     return value.toObject(exec, globalObject);
211 }
212
213 EncodedJSValue JIT_OPERATION operationValueBitAnd(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
214 {
215     VM* vm = &exec->vm();
216     NativeCallFrameTracer tracer(vm, exec);
217     auto scope = DECLARE_THROW_SCOPE(*vm);
218
219     JSValue op1 = JSValue::decode(encodedOp1);
220     JSValue op2 = JSValue::decode(encodedOp2);
221
222     int32_t a = op1.toInt32(exec);
223     RETURN_IF_EXCEPTION(scope, encodedJSValue());
224     int32_t b = op2.toInt32(exec);
225     return JSValue::encode(jsNumber(a & b));
226 }
227
228 EncodedJSValue JIT_OPERATION operationValueBitOr(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
229 {
230     VM* vm = &exec->vm();
231     NativeCallFrameTracer tracer(vm, exec);
232     auto scope = DECLARE_THROW_SCOPE(*vm);
233
234     JSValue op1 = JSValue::decode(encodedOp1);
235     JSValue op2 = JSValue::decode(encodedOp2);
236
237     int32_t a = op1.toInt32(exec);
238     RETURN_IF_EXCEPTION(scope, encodedJSValue());
239     int32_t b = op2.toInt32(exec);
240     return JSValue::encode(jsNumber(a | b));
241 }
242
243 EncodedJSValue JIT_OPERATION operationValueBitXor(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
244 {
245     VM* vm = &exec->vm();
246     NativeCallFrameTracer tracer(vm, exec);
247     auto scope = DECLARE_THROW_SCOPE(*vm);
248
249     JSValue op1 = JSValue::decode(encodedOp1);
250     JSValue op2 = JSValue::decode(encodedOp2);
251
252     int32_t a = op1.toInt32(exec);
253     RETURN_IF_EXCEPTION(scope, encodedJSValue());
254     int32_t b = op2.toInt32(exec);
255     return JSValue::encode(jsNumber(a ^ b));
256 }
257
258 EncodedJSValue JIT_OPERATION operationValueBitLShift(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
259 {
260     VM* vm = &exec->vm();
261     NativeCallFrameTracer tracer(vm, exec);
262     auto scope = DECLARE_THROW_SCOPE(*vm);
263
264     JSValue op1 = JSValue::decode(encodedOp1);
265     JSValue op2 = JSValue::decode(encodedOp2);
266
267     int32_t a = op1.toInt32(exec);
268     RETURN_IF_EXCEPTION(scope, encodedJSValue());
269     uint32_t b = op2.toUInt32(exec);
270     return JSValue::encode(jsNumber(a << (b & 0x1f)));
271 }
272
273 EncodedJSValue JIT_OPERATION operationValueBitRShift(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
274 {
275     VM* vm = &exec->vm();
276     NativeCallFrameTracer tracer(vm, exec);
277     auto scope = DECLARE_THROW_SCOPE(*vm);
278
279     JSValue op1 = JSValue::decode(encodedOp1);
280     JSValue op2 = JSValue::decode(encodedOp2);
281
282     int32_t a = op1.toInt32(exec);
283     RETURN_IF_EXCEPTION(scope, encodedJSValue());
284     uint32_t b = op2.toUInt32(exec);
285     return JSValue::encode(jsNumber(a >> (b & 0x1f)));
286 }
287
288 EncodedJSValue JIT_OPERATION operationValueBitURShift(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
289 {
290     VM* vm = &exec->vm();
291     NativeCallFrameTracer tracer(vm, exec);
292     auto scope = DECLARE_THROW_SCOPE(*vm);
293
294     JSValue op1 = JSValue::decode(encodedOp1);
295     JSValue op2 = JSValue::decode(encodedOp2);
296
297     uint32_t a = op1.toUInt32(exec);
298     RETURN_IF_EXCEPTION(scope, encodedJSValue());
299     uint32_t b = op2.toUInt32(exec);
300     return JSValue::encode(jsNumber(static_cast<int32_t>(a >> (b & 0x1f))));
301 }
302
303 EncodedJSValue JIT_OPERATION operationValueAddNotNumber(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
304 {
305     VM* vm = &exec->vm();
306     NativeCallFrameTracer tracer(vm, exec);
307     
308     JSValue op1 = JSValue::decode(encodedOp1);
309     JSValue op2 = JSValue::decode(encodedOp2);
310     
311     ASSERT(!op1.isNumber() || !op2.isNumber());
312     
313     if (op1.isString() && !op2.isObject())
314         return JSValue::encode(jsString(exec, asString(op1), op2.toString(exec)));
315
316     return JSValue::encode(jsAddSlowCase(exec, op1, op2));
317 }
318
319 EncodedJSValue JIT_OPERATION operationValueDiv(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
320 {
321     VM* vm = &exec->vm();
322     NativeCallFrameTracer tracer(vm, exec);
323     auto scope = DECLARE_THROW_SCOPE(*vm);
324
325     JSValue op1 = JSValue::decode(encodedOp1);
326     JSValue op2 = JSValue::decode(encodedOp2);
327
328     double a = op1.toNumber(exec);
329     RETURN_IF_EXCEPTION(scope, encodedJSValue());
330     double b = op2.toNumber(exec);
331     return JSValue::encode(jsNumber(a / b));
332 }
333
334 double JIT_OPERATION operationArithAbs(ExecState* exec, EncodedJSValue encodedOp1)
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     double a = op1.toNumber(exec);
342     RETURN_IF_EXCEPTION(scope, PNaN);
343     return fabs(a);
344 }
345
346 int32_t JIT_OPERATION operationArithClz32(ExecState* exec, EncodedJSValue encodedOp1)
347 {
348     VM* vm = &exec->vm();
349     NativeCallFrameTracer tracer(vm, exec);
350     auto scope = DECLARE_THROW_SCOPE(*vm);
351
352     JSValue op1 = JSValue::decode(encodedOp1);
353     uint32_t value = op1.toUInt32(exec);
354     RETURN_IF_EXCEPTION(scope, 0);
355     return clz32(value);
356 }
357
358 double JIT_OPERATION operationArithCos(ExecState* exec, EncodedJSValue encodedOp1)
359 {
360     VM* vm = &exec->vm();
361     NativeCallFrameTracer tracer(vm, exec);
362     auto scope = DECLARE_THROW_SCOPE(*vm);
363
364     JSValue op1 = JSValue::decode(encodedOp1);
365     double a = op1.toNumber(exec);
366     RETURN_IF_EXCEPTION(scope, encodedJSValue());
367     return cos(a);
368 }
369
370 double JIT_OPERATION operationArithFRound(ExecState* exec, EncodedJSValue encodedOp1)
371 {
372     VM* vm = &exec->vm();
373     NativeCallFrameTracer tracer(vm, exec);
374     auto scope = DECLARE_THROW_SCOPE(*vm);
375
376     JSValue op1 = JSValue::decode(encodedOp1);
377     double a = op1.toNumber(exec);
378     RETURN_IF_EXCEPTION(scope, PNaN);
379     return static_cast<float>(a);
380 }
381
382 double JIT_OPERATION operationArithLog(ExecState* exec, EncodedJSValue encodedOp1)
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     double a = op1.toNumber(exec);
390     RETURN_IF_EXCEPTION(scope, PNaN);
391     return log(a);
392 }
393
394 double JIT_OPERATION operationArithSin(ExecState* exec, EncodedJSValue encodedOp1)
395 {
396     VM* vm = &exec->vm();
397     NativeCallFrameTracer tracer(vm, exec);
398     auto scope = DECLARE_THROW_SCOPE(*vm);
399
400     JSValue op1 = JSValue::decode(encodedOp1);
401     double a = op1.toNumber(exec);
402     RETURN_IF_EXCEPTION(scope, PNaN);
403     return sin(a);
404 }
405
406 double JIT_OPERATION operationArithSqrt(ExecState* exec, EncodedJSValue encodedOp1)
407 {
408     VM* vm = &exec->vm();
409     NativeCallFrameTracer tracer(vm, exec);
410     auto scope = DECLARE_THROW_SCOPE(*vm);
411
412     JSValue op1 = JSValue::decode(encodedOp1);
413     double a = op1.toNumber(exec);
414     RETURN_IF_EXCEPTION(scope, PNaN);
415     return sqrt(a);
416 }
417
418 double JIT_OPERATION operationArithTan(ExecState* exec, EncodedJSValue encodedOp1)
419 {
420     VM* vm = &exec->vm();
421     NativeCallFrameTracer tracer(vm, exec);
422     auto scope = DECLARE_THROW_SCOPE(*vm);
423
424     JSValue op1 = JSValue::decode(encodedOp1);
425     double a = op1.toNumber(exec);
426     RETURN_IF_EXCEPTION(scope, encodedJSValue());
427     return tan(a);
428 }
429
430 EncodedJSValue JIT_OPERATION operationArithRound(ExecState* exec, EncodedJSValue encodedArgument)
431 {
432     VM* vm = &exec->vm();
433     NativeCallFrameTracer tracer(vm, exec);
434     auto scope = DECLARE_THROW_SCOPE(*vm);
435
436     JSValue argument = JSValue::decode(encodedArgument);
437     double valueOfArgument = argument.toNumber(exec);
438     RETURN_IF_EXCEPTION(scope, encodedJSValue());
439     return JSValue::encode(jsNumber(jsRound(valueOfArgument)));
440 }
441
442 EncodedJSValue JIT_OPERATION operationArithFloor(ExecState* exec, EncodedJSValue encodedArgument)
443 {
444     VM* vm = &exec->vm();
445     NativeCallFrameTracer tracer(vm, exec);
446     auto scope = DECLARE_THROW_SCOPE(*vm);
447
448     JSValue argument = JSValue::decode(encodedArgument);
449     double valueOfArgument = argument.toNumber(exec);
450     RETURN_IF_EXCEPTION(scope, encodedJSValue());
451     return JSValue::encode(jsNumber(floor(valueOfArgument)));
452 }
453
454 EncodedJSValue JIT_OPERATION operationArithCeil(ExecState* exec, EncodedJSValue encodedArgument)
455 {
456     VM* vm = &exec->vm();
457     NativeCallFrameTracer tracer(vm, exec);
458     auto scope = DECLARE_THROW_SCOPE(*vm);
459
460     JSValue argument = JSValue::decode(encodedArgument);
461     double valueOfArgument = argument.toNumber(exec);
462     RETURN_IF_EXCEPTION(scope, encodedJSValue());
463     return JSValue::encode(jsNumber(ceil(valueOfArgument)));
464 }
465
466 EncodedJSValue JIT_OPERATION operationArithTrunc(ExecState* exec, EncodedJSValue encodedArgument)
467 {
468     VM* vm = &exec->vm();
469     NativeCallFrameTracer tracer(vm, exec);
470     auto scope = DECLARE_THROW_SCOPE(*vm);
471
472     JSValue argument = JSValue::decode(encodedArgument);
473     double truncatedValueOfArgument = argument.toIntegerPreserveNaN(exec);
474     RETURN_IF_EXCEPTION(scope, encodedJSValue());
475     return JSValue::encode(jsNumber(truncatedValueOfArgument));
476 }
477
478 static ALWAYS_INLINE EncodedJSValue getByVal(ExecState* exec, JSCell* base, uint32_t index)
479 {
480     VM& vm = exec->vm();
481     NativeCallFrameTracer tracer(&vm, exec);
482     
483     if (base->isObject()) {
484         JSObject* object = asObject(base);
485         if (object->canGetIndexQuickly(index))
486             return JSValue::encode(object->getIndexQuickly(index));
487     }
488
489     if (isJSString(base) && asString(base)->canGetIndex(index))
490         return JSValue::encode(asString(base)->getIndex(exec, index));
491
492     return JSValue::encode(JSValue(base).get(exec, index));
493 }
494
495 EncodedJSValue JIT_OPERATION operationGetByVal(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty)
496 {
497     VM& vm = exec->vm();
498     NativeCallFrameTracer tracer(&vm, exec);
499     auto scope = DECLARE_THROW_SCOPE(vm);
500
501     JSValue baseValue = JSValue::decode(encodedBase);
502     JSValue property = JSValue::decode(encodedProperty);
503
504     if (LIKELY(baseValue.isCell())) {
505         JSCell* base = baseValue.asCell();
506
507         if (property.isUInt32()) {
508             return getByVal(exec, base, property.asUInt32());
509         } else if (property.isDouble()) {
510             double propertyAsDouble = property.asDouble();
511             uint32_t propertyAsUInt32 = static_cast<uint32_t>(propertyAsDouble);
512             if (propertyAsUInt32 == propertyAsDouble && isIndex(propertyAsUInt32))
513                 return getByVal(exec, base, propertyAsUInt32);
514         } else if (property.isString()) {
515             Structure& structure = *base->structure(vm);
516             if (JSCell::canUseFastGetOwnProperty(structure)) {
517                 if (RefPtr<AtomicStringImpl> existingAtomicString = asString(property)->toExistingAtomicString(exec)) {
518                     if (JSValue result = base->fastGetOwnProperty(vm, structure, existingAtomicString.get()))
519                         return JSValue::encode(result);
520                 }
521             }
522         }
523     }
524
525     baseValue.requireObjectCoercible(exec);
526     RETURN_IF_EXCEPTION(scope, encodedJSValue());
527     auto propertyName = property.toPropertyKey(exec);
528     RETURN_IF_EXCEPTION(scope, encodedJSValue());
529     return JSValue::encode(baseValue.get(exec, propertyName));
530 }
531
532 EncodedJSValue JIT_OPERATION operationGetByValCell(ExecState* exec, JSCell* base, EncodedJSValue encodedProperty)
533 {
534     VM& vm = exec->vm();
535     NativeCallFrameTracer tracer(&vm, exec);
536     auto scope = DECLARE_THROW_SCOPE(vm);
537
538     JSValue property = JSValue::decode(encodedProperty);
539
540     if (property.isUInt32())
541         return getByVal(exec, base, property.asUInt32());
542     if (property.isDouble()) {
543         double propertyAsDouble = property.asDouble();
544         uint32_t propertyAsUInt32 = static_cast<uint32_t>(propertyAsDouble);
545         if (propertyAsUInt32 == propertyAsDouble)
546             return getByVal(exec, base, propertyAsUInt32);
547     } else if (property.isString()) {
548         Structure& structure = *base->structure(vm);
549         if (JSCell::canUseFastGetOwnProperty(structure)) {
550             if (RefPtr<AtomicStringImpl> existingAtomicString = asString(property)->toExistingAtomicString(exec)) {
551                 if (JSValue result = base->fastGetOwnProperty(vm, structure, existingAtomicString.get()))
552                     return JSValue::encode(result);
553             }
554         }
555     }
556
557     auto propertyName = property.toPropertyKey(exec);
558     RETURN_IF_EXCEPTION(scope, encodedJSValue());
559     return JSValue::encode(JSValue(base).get(exec, propertyName));
560 }
561
562 ALWAYS_INLINE EncodedJSValue getByValCellInt(ExecState* exec, JSCell* base, int32_t index)
563 {
564     VM* vm = &exec->vm();
565     NativeCallFrameTracer tracer(vm, exec);
566     
567     if (index < 0) {
568         // Go the slowest way possible becase negative indices don't use indexed storage.
569         return JSValue::encode(JSValue(base).get(exec, Identifier::from(exec, index)));
570     }
571
572     // Use this since we know that the value is out of bounds.
573     return JSValue::encode(JSValue(base).get(exec, static_cast<unsigned>(index)));
574 }
575
576 EncodedJSValue JIT_OPERATION operationGetByValArrayInt(ExecState* exec, JSArray* base, int32_t index)
577 {
578     return getByValCellInt(exec, base, index);
579 }
580
581 EncodedJSValue JIT_OPERATION operationGetByValStringInt(ExecState* exec, JSString* base, int32_t index)
582 {
583     return getByValCellInt(exec, base, index);
584 }
585
586 void JIT_OPERATION operationPutByValStrict(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
587 {
588     VM* vm = &exec->vm();
589     NativeCallFrameTracer tracer(vm, exec);
590     
591     operationPutByValInternal<true, false>(exec, encodedBase, encodedProperty, encodedValue);
592 }
593
594 void JIT_OPERATION operationPutByValNonStrict(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
595 {
596     VM* vm = &exec->vm();
597     NativeCallFrameTracer tracer(vm, exec);
598     
599     operationPutByValInternal<false, false>(exec, encodedBase, encodedProperty, encodedValue);
600 }
601
602 void JIT_OPERATION operationPutByValCellStrict(ExecState* exec, JSCell* cell, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
603 {
604     VM* vm = &exec->vm();
605     NativeCallFrameTracer tracer(vm, exec);
606     
607     operationPutByValInternal<true, false>(exec, JSValue::encode(cell), encodedProperty, encodedValue);
608 }
609
610 void JIT_OPERATION operationPutByValCellNonStrict(ExecState* exec, JSCell* cell, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
611 {
612     VM* vm = &exec->vm();
613     NativeCallFrameTracer tracer(vm, exec);
614     
615     operationPutByValInternal<false, false>(exec, JSValue::encode(cell), encodedProperty, encodedValue);
616 }
617
618 void JIT_OPERATION operationPutByValBeyondArrayBoundsStrict(ExecState* exec, JSObject* array, int32_t index, EncodedJSValue encodedValue)
619 {
620     VM& vm = exec->vm();
621     NativeCallFrameTracer tracer(&vm, exec);
622     
623     if (index >= 0) {
624         array->putByIndexInline(exec, index, JSValue::decode(encodedValue), true);
625         return;
626     }
627     
628     PutPropertySlot slot(array, true);
629     array->methodTable()->put(
630         array, exec, Identifier::from(exec, index), JSValue::decode(encodedValue), slot);
631 }
632
633 void JIT_OPERATION operationPutByValBeyondArrayBoundsNonStrict(ExecState* exec, JSObject* array, int32_t index, EncodedJSValue encodedValue)
634 {
635     VM* vm = &exec->vm();
636     NativeCallFrameTracer tracer(vm, exec);
637     
638     if (index >= 0) {
639         array->putByIndexInline(exec, index, JSValue::decode(encodedValue), false);
640         return;
641     }
642     
643     PutPropertySlot slot(array, false);
644     array->methodTable()->put(
645         array, exec, Identifier::from(exec, index), JSValue::decode(encodedValue), slot);
646 }
647
648 void JIT_OPERATION operationPutDoubleByValBeyondArrayBoundsStrict(ExecState* exec, JSObject* array, int32_t index, double value)
649 {
650     VM* vm = &exec->vm();
651     NativeCallFrameTracer tracer(vm, exec);
652     
653     JSValue jsValue = JSValue(JSValue::EncodeAsDouble, value);
654     
655     if (index >= 0) {
656         array->putByIndexInline(exec, index, jsValue, true);
657         return;
658     }
659     
660     PutPropertySlot slot(array, true);
661     array->methodTable()->put(
662         array, exec, Identifier::from(exec, index), jsValue, slot);
663 }
664
665 void JIT_OPERATION operationPutDoubleByValBeyondArrayBoundsNonStrict(ExecState* exec, JSObject* array, int32_t index, double value)
666 {
667     VM* vm = &exec->vm();
668     NativeCallFrameTracer tracer(vm, exec);
669     
670     JSValue jsValue = JSValue(JSValue::EncodeAsDouble, value);
671     
672     if (index >= 0) {
673         array->putByIndexInline(exec, index, jsValue, false);
674         return;
675     }
676     
677     PutPropertySlot slot(array, false);
678     array->methodTable()->put(
679         array, exec, Identifier::from(exec, index), jsValue, slot);
680 }
681
682 void JIT_OPERATION operationPutByValDirectStrict(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
683 {
684     VM* vm = &exec->vm();
685     NativeCallFrameTracer tracer(vm, exec);
686     
687     operationPutByValInternal<true, true>(exec, encodedBase, encodedProperty, encodedValue);
688 }
689
690 void JIT_OPERATION operationPutByValDirectNonStrict(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
691 {
692     VM* vm = &exec->vm();
693     NativeCallFrameTracer tracer(vm, exec);
694     
695     operationPutByValInternal<false, true>(exec, encodedBase, encodedProperty, encodedValue);
696 }
697
698 void JIT_OPERATION operationPutByValDirectCellStrict(ExecState* exec, JSCell* cell, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
699 {
700     VM* vm = &exec->vm();
701     NativeCallFrameTracer tracer(vm, exec);
702     
703     operationPutByValInternal<true, true>(exec, JSValue::encode(cell), encodedProperty, encodedValue);
704 }
705
706 void JIT_OPERATION operationPutByValDirectCellNonStrict(ExecState* exec, JSCell* cell, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
707 {
708     VM* vm = &exec->vm();
709     NativeCallFrameTracer tracer(vm, exec);
710     
711     operationPutByValInternal<false, true>(exec, JSValue::encode(cell), encodedProperty, encodedValue);
712 }
713
714 void JIT_OPERATION operationPutByValDirectBeyondArrayBoundsStrict(ExecState* exec, JSObject* array, int32_t index, EncodedJSValue encodedValue)
715 {
716     VM* vm = &exec->vm();
717     NativeCallFrameTracer tracer(vm, exec);
718     if (index >= 0) {
719         array->putDirectIndex(exec, index, JSValue::decode(encodedValue), 0, PutDirectIndexShouldThrow);
720         return;
721     }
722     
723     PutPropertySlot slot(array, true);
724     array->putDirect(exec->vm(), Identifier::from(exec, index), JSValue::decode(encodedValue), slot);
725 }
726
727 void JIT_OPERATION operationPutByValDirectBeyondArrayBoundsNonStrict(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->putDirectIndex(exec, index, JSValue::decode(encodedValue));
734         return;
735     }
736     
737     PutPropertySlot slot(array, false);
738     array->putDirect(exec->vm(), Identifier::from(exec, index), JSValue::decode(encodedValue), slot);
739 }
740
741 EncodedJSValue JIT_OPERATION operationArrayPush(ExecState* exec, EncodedJSValue encodedValue, JSArray* array)
742 {
743     VM* vm = &exec->vm();
744     NativeCallFrameTracer tracer(vm, exec);
745     
746     array->push(exec, JSValue::decode(encodedValue));
747     return JSValue::encode(jsNumber(array->length()));
748 }
749
750 EncodedJSValue JIT_OPERATION operationArrayPushDouble(ExecState* exec, double value, JSArray* array)
751 {
752     VM* vm = &exec->vm();
753     NativeCallFrameTracer tracer(vm, exec);
754     
755     array->push(exec, JSValue(JSValue::EncodeAsDouble, value));
756     return JSValue::encode(jsNumber(array->length()));
757 }
758
759 EncodedJSValue JIT_OPERATION operationArrayPop(ExecState* exec, JSArray* array)
760 {
761     VM* vm = &exec->vm();
762     NativeCallFrameTracer tracer(vm, exec);
763     
764     return JSValue::encode(array->pop(exec));
765 }
766         
767 EncodedJSValue JIT_OPERATION operationArrayPopAndRecoverLength(ExecState* exec, JSArray* array)
768 {
769     VM* vm = &exec->vm();
770     NativeCallFrameTracer tracer(vm, exec);
771     
772     array->butterfly()->setPublicLength(array->butterfly()->publicLength() + 1);
773     
774     return JSValue::encode(array->pop(exec));
775 }
776         
777 EncodedJSValue JIT_OPERATION operationRegExpExecString(ExecState* exec, JSGlobalObject* globalObject, RegExpObject* regExpObject, JSString* argument)
778 {
779     SuperSamplerScope superSamplerScope(false);
780     
781     VM& vm = globalObject->vm();
782     NativeCallFrameTracer tracer(&vm, exec);
783     
784     return JSValue::encode(regExpObject->execInline(exec, globalObject, argument));
785 }
786         
787 EncodedJSValue JIT_OPERATION operationRegExpExec(ExecState* exec, JSGlobalObject* globalObject, RegExpObject* regExpObject, EncodedJSValue encodedArgument)
788 {
789     SuperSamplerScope superSamplerScope(false);
790     
791     VM& vm = globalObject->vm();
792     NativeCallFrameTracer tracer(&vm, exec);
793     
794     JSValue argument = JSValue::decode(encodedArgument);
795
796     JSString* input = argument.toStringOrNull(exec);
797     if (!input)
798         return JSValue::encode(jsUndefined());
799     return JSValue::encode(regExpObject->execInline(exec, globalObject, input));
800 }
801         
802 EncodedJSValue JIT_OPERATION operationRegExpExecGeneric(ExecState* exec, JSGlobalObject* globalObject, EncodedJSValue encodedBase, EncodedJSValue encodedArgument)
803 {
804     SuperSamplerScope superSamplerScope(false);
805     
806     VM& vm = globalObject->vm();
807     NativeCallFrameTracer tracer(&vm, exec);
808     auto scope = DECLARE_THROW_SCOPE(vm);
809
810     JSValue base = JSValue::decode(encodedBase);
811     JSValue argument = JSValue::decode(encodedArgument);
812     
813     if (!base.inherits(RegExpObject::info()))
814         return throwVMTypeError(exec, scope);
815
816     JSString* input = argument.toStringOrNull(exec);
817     if (!input)
818         return JSValue::encode(jsUndefined());
819     return JSValue::encode(asRegExpObject(base)->exec(exec, globalObject, input));
820 }
821         
822 size_t JIT_OPERATION operationRegExpTestString(ExecState* exec, JSGlobalObject* globalObject, RegExpObject* regExpObject, JSString* input)
823 {
824     SuperSamplerScope superSamplerScope(false);
825     
826     VM& vm = globalObject->vm();
827     NativeCallFrameTracer tracer(&vm, exec);
828
829     return regExpObject->testInline(exec, globalObject, input);
830 }
831
832 size_t JIT_OPERATION operationRegExpTest(ExecState* exec, JSGlobalObject* globalObject, RegExpObject* regExpObject, EncodedJSValue encodedArgument)
833 {
834     SuperSamplerScope superSamplerScope(false);
835     
836     VM& vm = globalObject->vm();
837     NativeCallFrameTracer tracer(&vm, exec);
838
839     JSValue argument = JSValue::decode(encodedArgument);
840
841     JSString* input = argument.toStringOrNull(exec);
842     if (!input)
843         return false;
844     return regExpObject->testInline(exec, globalObject, input);
845 }
846
847 size_t JIT_OPERATION operationRegExpTestGeneric(ExecState* exec, JSGlobalObject* globalObject, EncodedJSValue encodedBase, EncodedJSValue encodedArgument)
848 {
849     SuperSamplerScope superSamplerScope(false);
850     
851     VM& vm = globalObject->vm();
852     NativeCallFrameTracer tracer(&vm, exec);
853     auto scope = DECLARE_THROW_SCOPE(vm);
854
855     JSValue base = JSValue::decode(encodedBase);
856     JSValue argument = JSValue::decode(encodedArgument);
857
858     if (!base.inherits(RegExpObject::info())) {
859         throwTypeError(exec, scope);
860         return false;
861     }
862
863     JSString* input = argument.toStringOrNull(exec);
864     if (!input)
865         return false;
866     return asRegExpObject(base)->test(exec, globalObject, input);
867 }
868
869 size_t JIT_OPERATION operationCompareStrictEqCell(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
870 {
871     VM* vm = &exec->vm();
872     NativeCallFrameTracer tracer(vm, exec);
873     
874     JSValue op1 = JSValue::decode(encodedOp1);
875     JSValue op2 = JSValue::decode(encodedOp2);
876     
877     ASSERT(op1.isCell());
878     ASSERT(op2.isCell());
879     
880     return JSValue::strictEqualSlowCaseInline(exec, op1, op2);
881 }
882
883 size_t JIT_OPERATION operationCompareStrictEq(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
884 {
885     VM* vm = &exec->vm();
886     NativeCallFrameTracer tracer(vm, exec);
887
888     JSValue src1 = JSValue::decode(encodedOp1);
889     JSValue src2 = JSValue::decode(encodedOp2);
890     
891     return JSValue::strictEqual(exec, src1, src2);
892 }
893
894 EncodedJSValue JIT_OPERATION operationToPrimitive(ExecState* exec, EncodedJSValue value)
895 {
896     VM* vm = &exec->vm();
897     NativeCallFrameTracer tracer(vm, exec);
898     
899     return JSValue::encode(JSValue::decode(value).toPrimitive(exec));
900 }
901
902 EncodedJSValue JIT_OPERATION operationToNumber(ExecState* exec, EncodedJSValue value)
903 {
904     VM* vm = &exec->vm();
905     NativeCallFrameTracer tracer(vm, exec);
906
907     return JSValue::encode(jsNumber(JSValue::decode(value).toNumber(exec)));
908 }
909
910 EncodedJSValue JIT_OPERATION operationGetByIdWithThis(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedThis, UniquedStringImpl* impl)
911 {
912     VM& vm = exec->vm();
913     NativeCallFrameTracer tracer(&vm, exec);
914
915     JSValue baseValue = JSValue::decode(encodedBase);
916     JSValue thisVal = JSValue::decode(encodedThis);
917     PropertySlot slot(thisVal, PropertySlot::PropertySlot::InternalMethodType::Get);
918     JSValue result = baseValue.get(exec, Identifier::fromUid(exec, impl), slot);
919     return JSValue::encode(result);
920 }
921
922 EncodedJSValue JIT_OPERATION operationGetByValWithThis(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedThis, EncodedJSValue encodedSubscript)
923 {
924     VM& vm = exec->vm();
925     NativeCallFrameTracer tracer(&vm, exec);
926     auto scope = DECLARE_THROW_SCOPE(vm);
927
928     JSValue baseValue = JSValue::decode(encodedBase);
929     JSValue thisVal = JSValue::decode(encodedThis);
930     JSValue subscript = JSValue::decode(encodedSubscript);
931
932     if (LIKELY(baseValue.isCell() && subscript.isString())) {
933         Structure& structure = *baseValue.asCell()->structure(vm);
934         if (JSCell::canUseFastGetOwnProperty(structure)) {
935             if (RefPtr<AtomicStringImpl> existingAtomicString = asString(subscript)->toExistingAtomicString(exec)) {
936                 if (JSValue result = baseValue.asCell()->fastGetOwnProperty(vm, structure, existingAtomicString.get()))
937                     return JSValue::encode(result);
938             }
939         }
940     }
941     
942     PropertySlot slot(thisVal, PropertySlot::PropertySlot::InternalMethodType::Get);
943     if (subscript.isUInt32()) {
944         uint32_t i = subscript.asUInt32();
945         if (isJSString(baseValue) && asString(baseValue)->canGetIndex(i))
946             return JSValue::encode(asString(baseValue)->getIndex(exec, i));
947         
948         return JSValue::encode(baseValue.get(exec, i, slot));
949     }
950
951     baseValue.requireObjectCoercible(exec);
952     RETURN_IF_EXCEPTION(scope, encodedJSValue());
953
954     auto property = subscript.toPropertyKey(exec);
955     RETURN_IF_EXCEPTION(scope, encodedJSValue());
956     return JSValue::encode(baseValue.get(exec, property, slot));
957 }
958
959 void JIT_OPERATION operationPutByIdWithThisStrict(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedThis, EncodedJSValue encodedValue, UniquedStringImpl* impl)
960 {
961     VM& vm = exec->vm();
962     NativeCallFrameTracer tracer(&vm, exec);
963
964     putWithThis<true>(exec, encodedBase, encodedThis, encodedValue, Identifier::fromUid(exec, impl));
965 }
966
967 void JIT_OPERATION operationPutByIdWithThis(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedThis, EncodedJSValue encodedValue, UniquedStringImpl* impl)
968 {
969     VM& vm = exec->vm();
970     NativeCallFrameTracer tracer(&vm, exec);
971
972     putWithThis<false>(exec, encodedBase, encodedThis, encodedValue, Identifier::fromUid(exec, impl));
973 }
974
975 void JIT_OPERATION operationPutByValWithThisStrict(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedThis, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue)
976 {
977     VM& vm = exec->vm();
978     NativeCallFrameTracer tracer(&vm, exec);
979     auto scope = DECLARE_THROW_SCOPE(vm);
980
981     Identifier property = JSValue::decode(encodedSubscript).toPropertyKey(exec);
982     RETURN_IF_EXCEPTION(scope, void());
983     putWithThis<true>(exec, encodedBase, encodedThis, encodedValue, property);
984 }
985
986 void JIT_OPERATION operationPutByValWithThis(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedThis, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue)
987 {
988     VM& vm = exec->vm();
989     NativeCallFrameTracer tracer(&vm, exec);
990     auto scope = DECLARE_THROW_SCOPE(vm);
991
992     Identifier property = JSValue::decode(encodedSubscript).toPropertyKey(exec);
993     RETURN_IF_EXCEPTION(scope, void());
994     putWithThis<false>(exec, encodedBase, encodedThis, encodedValue, property);
995 }
996
997 char* JIT_OPERATION operationNewArray(ExecState* exec, Structure* arrayStructure, void* buffer, size_t size)
998 {
999     VM* vm = &exec->vm();
1000     NativeCallFrameTracer tracer(vm, exec);
1001     
1002     return bitwise_cast<char*>(constructArray(exec, arrayStructure, static_cast<JSValue*>(buffer), size));
1003 }
1004
1005 char* JIT_OPERATION operationNewEmptyArray(ExecState* exec, Structure* arrayStructure)
1006 {
1007     VM* vm = &exec->vm();
1008     NativeCallFrameTracer tracer(vm, exec);
1009     
1010     return bitwise_cast<char*>(JSArray::create(*vm, arrayStructure));
1011 }
1012
1013 char* JIT_OPERATION operationNewArrayWithSize(ExecState* exec, Structure* arrayStructure, int32_t size, Butterfly* butterfly)
1014 {
1015     VM& vm = exec->vm();
1016     NativeCallFrameTracer tracer(&vm, exec);
1017     auto scope = DECLARE_THROW_SCOPE(vm);
1018
1019     if (UNLIKELY(size < 0))
1020         return bitwise_cast<char*>(throwException(exec, scope, createRangeError(exec, ASCIILiteral("Array size is not a small enough positive integer."))));
1021
1022     JSArray* result;
1023     if (butterfly)
1024         result = JSArray::createWithButterfly(vm, arrayStructure, butterfly);
1025     else
1026         result = JSArray::create(vm, arrayStructure, size);
1027     return bitwise_cast<char*>(result);
1028 }
1029
1030 char* JIT_OPERATION operationNewArrayBuffer(ExecState* exec, Structure* arrayStructure, size_t start, size_t size)
1031 {
1032     VM& vm = exec->vm();
1033     NativeCallFrameTracer tracer(&vm, exec);
1034     return bitwise_cast<char*>(constructArray(exec, arrayStructure, exec->codeBlock()->constantBuffer(start), size));
1035 }
1036
1037 char* JIT_OPERATION operationNewInt8ArrayWithSize(
1038     ExecState* exec, Structure* structure, int32_t length, char* vector)
1039 {
1040     return newTypedArrayWithSize<JSInt8Array>(exec, structure, length, vector);
1041 }
1042
1043 char* JIT_OPERATION operationNewInt8ArrayWithOneArgument(
1044     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
1045 {
1046     VM& vm = exec->vm();
1047     NativeCallFrameTracer tracer(&vm, exec);
1048     return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSInt8Array>(exec, structure, encodedValue, 0, Nullopt));
1049 }
1050
1051 char* JIT_OPERATION operationNewInt16ArrayWithSize(
1052     ExecState* exec, Structure* structure, int32_t length, char* vector)
1053 {
1054     return newTypedArrayWithSize<JSInt16Array>(exec, structure, length, vector);
1055 }
1056
1057 char* JIT_OPERATION operationNewInt16ArrayWithOneArgument(
1058     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
1059 {
1060     VM& vm = exec->vm();
1061     NativeCallFrameTracer tracer(&vm, exec);
1062     return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSInt16Array>(exec, structure, encodedValue, 0, Nullopt));
1063 }
1064
1065 char* JIT_OPERATION operationNewInt32ArrayWithSize(
1066     ExecState* exec, Structure* structure, int32_t length, char* vector)
1067 {
1068     return newTypedArrayWithSize<JSInt32Array>(exec, structure, length, vector);
1069 }
1070
1071 char* JIT_OPERATION operationNewInt32ArrayWithOneArgument(
1072     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
1073 {
1074     VM& vm = exec->vm();
1075     NativeCallFrameTracer tracer(&vm, exec);
1076     return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSInt32Array>(exec, structure, encodedValue, 0, Nullopt));
1077 }
1078
1079 char* JIT_OPERATION operationNewUint8ArrayWithSize(
1080     ExecState* exec, Structure* structure, int32_t length, char* vector)
1081 {
1082     return newTypedArrayWithSize<JSUint8Array>(exec, structure, length, vector);
1083 }
1084
1085 char* JIT_OPERATION operationNewUint8ArrayWithOneArgument(
1086     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
1087 {
1088     VM& vm = exec->vm();
1089     NativeCallFrameTracer tracer(&vm, exec);
1090     return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSUint8Array>(exec, structure, encodedValue, 0, Nullopt));
1091 }
1092
1093 char* JIT_OPERATION operationNewUint8ClampedArrayWithSize(
1094     ExecState* exec, Structure* structure, int32_t length, char* vector)
1095 {
1096     return newTypedArrayWithSize<JSUint8ClampedArray>(exec, structure, length, vector);
1097 }
1098
1099 char* JIT_OPERATION operationNewUint8ClampedArrayWithOneArgument(
1100     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
1101 {
1102     VM& vm = exec->vm();
1103     NativeCallFrameTracer tracer(&vm, exec);
1104     return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSUint8ClampedArray>(exec, structure, encodedValue, 0, Nullopt));
1105 }
1106
1107 char* JIT_OPERATION operationNewUint16ArrayWithSize(
1108     ExecState* exec, Structure* structure, int32_t length, char* vector)
1109 {
1110     return newTypedArrayWithSize<JSUint16Array>(exec, structure, length, vector);
1111 }
1112
1113 char* JIT_OPERATION operationNewUint16ArrayWithOneArgument(
1114     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
1115 {
1116     VM& vm = exec->vm();
1117     NativeCallFrameTracer tracer(&vm, exec);
1118     return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSUint16Array>(exec, structure, encodedValue, 0, Nullopt));
1119 }
1120
1121 char* JIT_OPERATION operationNewUint32ArrayWithSize(
1122     ExecState* exec, Structure* structure, int32_t length, char* vector)
1123 {
1124     return newTypedArrayWithSize<JSUint32Array>(exec, structure, length, vector);
1125 }
1126
1127 char* JIT_OPERATION operationNewUint32ArrayWithOneArgument(
1128     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
1129 {
1130     VM& vm = exec->vm();
1131     NativeCallFrameTracer tracer(&vm, exec);
1132     return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSUint32Array>(exec, structure, encodedValue, 0, Nullopt));
1133 }
1134
1135 char* JIT_OPERATION operationNewFloat32ArrayWithSize(
1136     ExecState* exec, Structure* structure, int32_t length, char* vector)
1137 {
1138     return newTypedArrayWithSize<JSFloat32Array>(exec, structure, length, vector);
1139 }
1140
1141 char* JIT_OPERATION operationNewFloat32ArrayWithOneArgument(
1142     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
1143 {
1144     VM& vm = exec->vm();
1145     NativeCallFrameTracer tracer(&vm, exec);
1146     return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSFloat32Array>(exec, structure, encodedValue, 0, Nullopt));
1147 }
1148
1149 char* JIT_OPERATION operationNewFloat64ArrayWithSize(
1150     ExecState* exec, Structure* structure, int32_t length, char* vector)
1151 {
1152     return newTypedArrayWithSize<JSFloat64Array>(exec, structure, length, vector);
1153 }
1154
1155 char* JIT_OPERATION operationNewFloat64ArrayWithOneArgument(
1156     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
1157 {
1158     VM& vm = exec->vm();
1159     NativeCallFrameTracer tracer(&vm, exec);
1160     return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSFloat64Array>(exec, structure, encodedValue, 0, Nullopt));
1161 }
1162
1163 JSCell* JIT_OPERATION operationCreateActivationDirect(ExecState* exec, Structure* structure, JSScope* scope, SymbolTable* table, EncodedJSValue initialValueEncoded)
1164 {
1165     JSValue initialValue = JSValue::decode(initialValueEncoded);
1166     ASSERT(initialValue == jsUndefined() || initialValue == jsTDZValue());
1167     VM& vm = exec->vm();
1168     NativeCallFrameTracer tracer(&vm, exec);
1169     return JSLexicalEnvironment::create(vm, structure, scope, table, initialValue);
1170 }
1171
1172 JSCell* JIT_OPERATION operationCreateDirectArguments(ExecState* exec, Structure* structure, int32_t length, int32_t minCapacity)
1173 {
1174     VM& vm = exec->vm();
1175     NativeCallFrameTracer target(&vm, exec);
1176     DirectArguments* result = DirectArguments::create(
1177         vm, structure, length, std::max(length, minCapacity));
1178     // The caller will store to this object without barriers. Most likely, at this point, this is
1179     // still a young object and so no barriers are needed. But it's good to be careful anyway,
1180     // since the GC should be allowed to do crazy (like pretenuring, for example).
1181     vm.heap.writeBarrier(result);
1182     return result;
1183 }
1184
1185 JSCell* JIT_OPERATION operationCreateScopedArguments(ExecState* exec, Structure* structure, Register* argumentStart, int32_t length, JSFunction* callee, JSLexicalEnvironment* scope)
1186 {
1187     VM& vm = exec->vm();
1188     NativeCallFrameTracer target(&vm, exec);
1189     
1190     // We could pass the ScopedArgumentsTable* as an argument. We currently don't because I
1191     // didn't feel like changing the max number of arguments for a slow path call from 6 to 7.
1192     ScopedArgumentsTable* table = scope->symbolTable()->arguments();
1193     
1194     return ScopedArguments::createByCopyingFrom(
1195         vm, structure, argumentStart, length, callee, table, scope);
1196 }
1197
1198 JSCell* JIT_OPERATION operationCreateClonedArguments(ExecState* exec, Structure* structure, Register* argumentStart, int32_t length, JSFunction* callee)
1199 {
1200     VM& vm = exec->vm();
1201     NativeCallFrameTracer target(&vm, exec);
1202     return ClonedArguments::createByCopyingFrom(
1203         exec, structure, argumentStart, length, callee);
1204 }
1205
1206 JSCell* JIT_OPERATION operationCreateDirectArgumentsDuringExit(ExecState* exec, InlineCallFrame* inlineCallFrame, JSFunction* callee, int32_t argumentCount)
1207 {
1208     VM& vm = exec->vm();
1209     NativeCallFrameTracer target(&vm, exec);
1210     
1211     DeferGCForAWhile deferGC(vm.heap);
1212     
1213     CodeBlock* codeBlock;
1214     if (inlineCallFrame)
1215         codeBlock = baselineCodeBlockForInlineCallFrame(inlineCallFrame);
1216     else
1217         codeBlock = exec->codeBlock();
1218     
1219     unsigned length = argumentCount - 1;
1220     unsigned capacity = std::max(length, static_cast<unsigned>(codeBlock->numParameters() - 1));
1221     DirectArguments* result = DirectArguments::create(
1222         vm, codeBlock->globalObject()->directArgumentsStructure(), length, capacity);
1223     
1224     result->callee().set(vm, result, callee);
1225     
1226     Register* arguments =
1227         exec->registers() + (inlineCallFrame ? inlineCallFrame->stackOffset : 0) +
1228         CallFrame::argumentOffset(0);
1229     for (unsigned i = length; i--;)
1230         result->setIndexQuickly(vm, i, arguments[i].jsValue());
1231     
1232     return result;
1233 }
1234
1235 JSCell* JIT_OPERATION operationCreateClonedArgumentsDuringExit(ExecState* exec, InlineCallFrame* inlineCallFrame, JSFunction* callee, int32_t argumentCount)
1236 {
1237     VM& vm = exec->vm();
1238     NativeCallFrameTracer target(&vm, exec);
1239     
1240     DeferGCForAWhile deferGC(vm.heap);
1241     
1242     CodeBlock* codeBlock;
1243     if (inlineCallFrame)
1244         codeBlock = baselineCodeBlockForInlineCallFrame(inlineCallFrame);
1245     else
1246         codeBlock = exec->codeBlock();
1247     
1248     unsigned length = argumentCount - 1;
1249     ClonedArguments* result = ClonedArguments::createEmpty(
1250         vm, codeBlock->globalObject()->clonedArgumentsStructure(), callee, length);
1251     
1252     Register* arguments =
1253         exec->registers() + (inlineCallFrame ? inlineCallFrame->stackOffset : 0) +
1254         CallFrame::argumentOffset(0);
1255     for (unsigned i = length; i--;)
1256         result->initializeIndex(vm, i, arguments[i].jsValue());
1257
1258     
1259     return result;
1260 }
1261
1262 JSCell* JIT_OPERATION operationCreateRest(ExecState* exec, Register* argumentStart, unsigned numberOfParamsToSkip, unsigned arraySize)
1263 {
1264     VM* vm = &exec->vm();
1265     NativeCallFrameTracer tracer(vm, exec);
1266
1267     JSGlobalObject* globalObject = exec->lexicalGlobalObject();
1268     Structure* structure = globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithContiguous);
1269     static_assert(sizeof(Register) == sizeof(JSValue), "This is a strong assumption here.");
1270     JSValue* argumentsToCopyRegion = bitwise_cast<JSValue*>(argumentStart) + numberOfParamsToSkip;
1271     return constructArray(exec, structure, argumentsToCopyRegion, arraySize);
1272 }
1273
1274 size_t JIT_OPERATION operationObjectIsObject(ExecState* exec, JSGlobalObject* globalObject, JSCell* object)
1275 {
1276     VM& vm = exec->vm();
1277     NativeCallFrameTracer tracer(&vm, exec);
1278
1279     ASSERT(jsDynamicCast<JSObject*>(object));
1280     
1281     if (object->structure(vm)->masqueradesAsUndefined(globalObject))
1282         return false;
1283     if (object->type() == JSFunctionType)
1284         return false;
1285     if (object->inlineTypeFlags() & TypeOfShouldCallGetCallData) {
1286         CallData callData;
1287         if (object->methodTable(vm)->getCallData(object, callData) != CallType::None)
1288             return false;
1289     }
1290     
1291     return true;
1292 }
1293
1294 size_t JIT_OPERATION operationObjectIsFunction(ExecState* exec, JSGlobalObject* globalObject, JSCell* object)
1295 {
1296     VM& vm = exec->vm();
1297     NativeCallFrameTracer tracer(&vm, exec);
1298
1299     ASSERT(jsDynamicCast<JSObject*>(object));
1300     
1301     if (object->structure(vm)->masqueradesAsUndefined(globalObject))
1302         return false;
1303     if (object->type() == JSFunctionType)
1304         return true;
1305     if (object->inlineTypeFlags() & TypeOfShouldCallGetCallData) {
1306         CallData callData;
1307         if (object->methodTable(vm)->getCallData(object, callData) != CallType::None)
1308             return true;
1309     }
1310     
1311     return false;
1312 }
1313
1314 JSCell* JIT_OPERATION operationTypeOfObject(ExecState* exec, JSGlobalObject* globalObject, JSCell* object)
1315 {
1316     VM& vm = exec->vm();
1317     NativeCallFrameTracer tracer(&vm, exec);
1318
1319     ASSERT(jsDynamicCast<JSObject*>(object));
1320     
1321     if (object->structure(vm)->masqueradesAsUndefined(globalObject))
1322         return vm.smallStrings.undefinedString();
1323     if (object->type() == JSFunctionType)
1324         return vm.smallStrings.functionString();
1325     if (object->inlineTypeFlags() & TypeOfShouldCallGetCallData) {
1326         CallData callData;
1327         if (object->methodTable(vm)->getCallData(object, callData) != CallType::None)
1328             return vm.smallStrings.functionString();
1329     }
1330     
1331     return vm.smallStrings.objectString();
1332 }
1333
1334 int32_t JIT_OPERATION operationTypeOfObjectAsTypeofType(ExecState* exec, JSGlobalObject* globalObject, JSCell* object)
1335 {
1336     VM& vm = exec->vm();
1337     NativeCallFrameTracer tracer(&vm, exec);
1338
1339     ASSERT(jsDynamicCast<JSObject*>(object));
1340     
1341     if (object->structure(vm)->masqueradesAsUndefined(globalObject))
1342         return static_cast<int32_t>(TypeofType::Undefined);
1343     if (object->type() == JSFunctionType)
1344         return static_cast<int32_t>(TypeofType::Function);
1345     if (object->inlineTypeFlags() & TypeOfShouldCallGetCallData) {
1346         CallData callData;
1347         if (object->methodTable(vm)->getCallData(object, callData) != CallType::None)
1348             return static_cast<int32_t>(TypeofType::Function);
1349     }
1350     
1351     return static_cast<int32_t>(TypeofType::Object);
1352 }
1353
1354 char* JIT_OPERATION operationAllocatePropertyStorageWithInitialCapacity(ExecState* exec)
1355 {
1356     VM& vm = exec->vm();
1357     NativeCallFrameTracer tracer(&vm, exec);
1358
1359     return reinterpret_cast<char*>(
1360         Butterfly::createUninitialized(vm, 0, 0, initialOutOfLineCapacity, false, 0));
1361 }
1362
1363 char* JIT_OPERATION operationAllocatePropertyStorage(ExecState* exec, size_t newSize)
1364 {
1365     VM& vm = exec->vm();
1366     NativeCallFrameTracer tracer(&vm, exec);
1367
1368     return reinterpret_cast<char*>(
1369         Butterfly::createUninitialized(vm, 0, 0, newSize, false, 0));
1370 }
1371
1372 char* JIT_OPERATION operationEnsureInt32(ExecState* exec, JSCell* cell)
1373 {
1374     VM& vm = exec->vm();
1375     NativeCallFrameTracer tracer(&vm, exec);
1376     
1377     if (!cell->isObject())
1378         return 0;
1379     
1380     return reinterpret_cast<char*>(asObject(cell)->ensureInt32(vm).data());
1381 }
1382
1383 char* JIT_OPERATION operationEnsureDouble(ExecState* exec, JSCell* cell)
1384 {
1385     VM& vm = exec->vm();
1386     NativeCallFrameTracer tracer(&vm, exec);
1387     
1388     if (!cell->isObject())
1389         return 0;
1390     
1391     return reinterpret_cast<char*>(asObject(cell)->ensureDouble(vm).data());
1392 }
1393
1394 char* JIT_OPERATION operationEnsureContiguous(ExecState* exec, JSCell* cell)
1395 {
1396     VM& vm = exec->vm();
1397     NativeCallFrameTracer tracer(&vm, exec);
1398     
1399     if (!cell->isObject())
1400         return 0;
1401     
1402     return reinterpret_cast<char*>(asObject(cell)->ensureContiguous(vm).data());
1403 }
1404
1405 char* JIT_OPERATION operationEnsureArrayStorage(ExecState* exec, JSCell* cell)
1406 {
1407     VM& vm = exec->vm();
1408     NativeCallFrameTracer tracer(&vm, exec);
1409     
1410     if (!cell->isObject())
1411         return 0;
1412
1413     return reinterpret_cast<char*>(asObject(cell)->ensureArrayStorage(vm));
1414 }
1415
1416 StringImpl* JIT_OPERATION operationResolveRope(ExecState* exec, JSString* string)
1417 {
1418     VM& vm = exec->vm();
1419     NativeCallFrameTracer tracer(&vm, exec);
1420
1421     return string->value(exec).impl();
1422 }
1423
1424 JSString* JIT_OPERATION operationSingleCharacterString(ExecState* exec, int32_t character)
1425 {
1426     VM& vm = exec->vm();
1427     NativeCallFrameTracer tracer(&vm, exec);
1428     
1429     return jsSingleCharacterString(exec, static_cast<UChar>(character));
1430 }
1431
1432 JSCell* JIT_OPERATION operationNewStringObject(ExecState* exec, JSString* string, Structure* structure)
1433 {
1434     VM& vm = exec->vm();
1435     NativeCallFrameTracer tracer(&vm, exec);
1436     
1437     return StringObject::create(vm, structure, string);
1438 }
1439
1440 JSCell* JIT_OPERATION operationToStringOnCell(ExecState* exec, JSCell* cell)
1441 {
1442     VM& vm = exec->vm();
1443     NativeCallFrameTracer tracer(&vm, exec);
1444     
1445     return JSValue(cell).toString(exec);
1446 }
1447
1448 JSCell* JIT_OPERATION operationToString(ExecState* exec, EncodedJSValue value)
1449 {
1450     VM& vm = exec->vm();
1451     NativeCallFrameTracer tracer(&vm, exec);
1452
1453     return JSValue::decode(value).toString(exec);
1454 }
1455
1456 JSCell* JIT_OPERATION operationCallStringConstructorOnCell(ExecState* exec, JSCell* cell)
1457 {
1458     VM& vm = exec->vm();
1459     NativeCallFrameTracer tracer(&vm, exec);
1460
1461     return stringConstructor(exec, cell);
1462 }
1463
1464 JSCell* JIT_OPERATION operationCallStringConstructor(ExecState* exec, EncodedJSValue value)
1465 {
1466     VM& vm = exec->vm();
1467     NativeCallFrameTracer tracer(&vm, exec);
1468
1469     return stringConstructor(exec, JSValue::decode(value));
1470 }
1471
1472 JSCell* JIT_OPERATION operationMakeRope2(ExecState* exec, JSString* left, JSString* right)
1473 {
1474     VM& vm = exec->vm();
1475     NativeCallFrameTracer tracer(&vm, exec);
1476
1477     return jsString(exec, left, right);
1478 }
1479
1480 JSCell* JIT_OPERATION operationMakeRope3(ExecState* exec, JSString* a, JSString* b, JSString* c)
1481 {
1482     VM& vm = exec->vm();
1483     NativeCallFrameTracer tracer(&vm, exec);
1484
1485     return jsString(exec, a, b, c);
1486 }
1487
1488 JSCell* JIT_OPERATION operationStrCat2(ExecState* exec, EncodedJSValue a, EncodedJSValue b)
1489 {
1490     VM& vm = exec->vm();
1491     NativeCallFrameTracer tracer(&vm, exec);
1492     auto scope = DECLARE_THROW_SCOPE(vm);
1493
1494     JSString* str1 = JSValue::decode(a).toString(exec);
1495     ASSERT(!scope.exception()); // Impossible, since we must have been given primitives.
1496     JSString* str2 = JSValue::decode(b).toString(exec);
1497     ASSERT(!scope.exception());
1498
1499     scope.release();
1500     return jsString(exec, str1, str2);
1501 }
1502     
1503 JSCell* JIT_OPERATION operationStrCat3(ExecState* exec, EncodedJSValue a, EncodedJSValue b, EncodedJSValue c)
1504 {
1505     VM& vm = exec->vm();
1506     NativeCallFrameTracer tracer(&vm, exec);
1507     auto scope = DECLARE_THROW_SCOPE(vm);
1508
1509     JSString* str1 = JSValue::decode(a).toString(exec);
1510     ASSERT(!scope.exception()); // Impossible, since we must have been given primitives.
1511     JSString* str2 = JSValue::decode(b).toString(exec);
1512     ASSERT(!scope.exception());
1513     JSString* str3 = JSValue::decode(c).toString(exec);
1514     ASSERT(!scope.exception());
1515
1516     scope.release();
1517     return jsString(exec, str1, str2, str3);
1518 }
1519
1520 char* JIT_OPERATION operationFindSwitchImmTargetForDouble(
1521     ExecState* exec, EncodedJSValue encodedValue, size_t tableIndex)
1522 {
1523     VM& vm = exec->vm();
1524     NativeCallFrameTracer tracer(&vm, exec);
1525
1526     CodeBlock* codeBlock = exec->codeBlock();
1527     SimpleJumpTable& table = codeBlock->switchJumpTable(tableIndex);
1528     JSValue value = JSValue::decode(encodedValue);
1529     ASSERT(value.isDouble());
1530     double asDouble = value.asDouble();
1531     int32_t asInt32 = static_cast<int32_t>(asDouble);
1532     if (asDouble == asInt32)
1533         return static_cast<char*>(table.ctiForValue(asInt32).executableAddress());
1534     return static_cast<char*>(table.ctiDefault.executableAddress());
1535 }
1536
1537 char* JIT_OPERATION operationSwitchString(ExecState* exec, size_t tableIndex, JSString* string)
1538 {
1539     VM& vm = exec->vm();
1540     NativeCallFrameTracer tracer(&vm, exec);
1541
1542     return static_cast<char*>(exec->codeBlock()->stringSwitchJumpTable(tableIndex).ctiForValue(string->value(exec).impl()).executableAddress());
1543 }
1544
1545 int32_t JIT_OPERATION operationSwitchStringAndGetBranchOffset(ExecState* exec, size_t tableIndex, JSString* string)
1546 {
1547     VM& vm = exec->vm();
1548     NativeCallFrameTracer tracer(&vm, exec);
1549
1550     return exec->codeBlock()->stringSwitchJumpTable(tableIndex).offsetForValue(string->value(exec).impl(), std::numeric_limits<int32_t>::min());
1551 }
1552
1553 uintptr_t JIT_OPERATION operationCompareStringImplLess(StringImpl* a, StringImpl* b)
1554 {
1555     return codePointCompare(a, b) < 0;
1556 }
1557
1558 uintptr_t JIT_OPERATION operationCompareStringImplLessEq(StringImpl* a, StringImpl* b)
1559 {
1560     return codePointCompare(a, b) <= 0;
1561 }
1562
1563 uintptr_t JIT_OPERATION operationCompareStringImplGreater(StringImpl* a, StringImpl* b)
1564 {
1565     return codePointCompare(a, b) > 0;
1566 }
1567
1568 uintptr_t JIT_OPERATION operationCompareStringImplGreaterEq(StringImpl* a, StringImpl* b)
1569 {
1570     return codePointCompare(a, b) >= 0;
1571 }
1572
1573 uintptr_t JIT_OPERATION operationCompareStringLess(ExecState* exec, JSString* a, JSString* b)
1574 {
1575     VM& vm = exec->vm();
1576     NativeCallFrameTracer tracer(&vm, exec);
1577
1578     return codePointCompareLessThan(asString(a)->value(exec), asString(b)->value(exec));
1579 }
1580
1581 uintptr_t JIT_OPERATION operationCompareStringLessEq(ExecState* exec, JSString* a, JSString* b)
1582 {
1583     VM& vm = exec->vm();
1584     NativeCallFrameTracer tracer(&vm, exec);
1585
1586     return !codePointCompareLessThan(asString(b)->value(exec), asString(a)->value(exec));
1587 }
1588
1589 uintptr_t JIT_OPERATION operationCompareStringGreater(ExecState* exec, JSString* a, JSString* b)
1590 {
1591     VM& vm = exec->vm();
1592     NativeCallFrameTracer tracer(&vm, exec);
1593
1594     return codePointCompareLessThan(asString(b)->value(exec), asString(a)->value(exec));
1595 }
1596
1597 uintptr_t JIT_OPERATION operationCompareStringGreaterEq(ExecState* exec, JSString* a, JSString* b)
1598 {
1599     VM& vm = exec->vm();
1600     NativeCallFrameTracer tracer(&vm, exec);
1601
1602     return !codePointCompareLessThan(asString(a)->value(exec), asString(b)->value(exec));
1603 }
1604
1605 void JIT_OPERATION operationNotifyWrite(ExecState* exec, WatchpointSet* set)
1606 {
1607     VM& vm = exec->vm();
1608     NativeCallFrameTracer tracer(&vm, exec);
1609
1610     set->touch(vm, "Executed NotifyWrite");
1611 }
1612
1613 void JIT_OPERATION operationThrowStackOverflowForVarargs(ExecState* exec)
1614 {
1615     VM& vm = exec->vm();
1616     NativeCallFrameTracer tracer(&vm, exec);
1617     auto scope = DECLARE_THROW_SCOPE(vm);
1618     throwStackOverflowError(exec, scope);
1619 }
1620
1621 int32_t JIT_OPERATION operationSizeOfVarargs(ExecState* exec, EncodedJSValue encodedArguments, int32_t firstVarArgOffset)
1622 {
1623     VM& vm = exec->vm();
1624     NativeCallFrameTracer tracer(&vm, exec);
1625     JSValue arguments = JSValue::decode(encodedArguments);
1626     
1627     return sizeOfVarargs(exec, arguments, firstVarArgOffset);
1628 }
1629
1630 int32_t JIT_OPERATION operationHasOwnProperty(ExecState* exec, JSObject* thisObject, EncodedJSValue encodedKey)
1631 {
1632     VM& vm = exec->vm();
1633     NativeCallFrameTracer tracer(&vm, exec);
1634     auto scope = DECLARE_THROW_SCOPE(vm);
1635
1636     JSValue key = JSValue::decode(encodedKey);
1637     Identifier propertyName = key.toPropertyKey(exec);
1638     RETURN_IF_EXCEPTION(scope, false);
1639
1640     PropertySlot slot(thisObject, PropertySlot::InternalMethodType::GetOwnProperty);
1641     bool result = thisObject->hasOwnProperty(exec, propertyName.impl(), slot);
1642     RETURN_IF_EXCEPTION(scope, false);
1643
1644     HasOwnPropertyCache* hasOwnPropertyCache = vm.hasOwnPropertyCache();
1645     ASSERT(hasOwnPropertyCache);
1646     hasOwnPropertyCache->tryAdd(vm, slot, thisObject, propertyName.impl(), result);
1647     return result;
1648 }
1649
1650 void JIT_OPERATION operationLoadVarargs(ExecState* exec, int32_t firstElementDest, EncodedJSValue encodedArguments, int32_t offset, int32_t length, int32_t mandatoryMinimum)
1651 {
1652     VM& vm = exec->vm();
1653     NativeCallFrameTracer tracer(&vm, exec);
1654     JSValue arguments = JSValue::decode(encodedArguments);
1655     
1656     loadVarargs(exec, VirtualRegister(firstElementDest), arguments, offset, length);
1657     
1658     for (int32_t i = length; i < mandatoryMinimum; ++i)
1659         exec->r(firstElementDest + i) = jsUndefined();
1660 }
1661
1662 double JIT_OPERATION operationFModOnInts(int32_t a, int32_t b)
1663 {
1664     return fmod(a, b);
1665 }
1666
1667 #if USE(JSVALUE32_64)
1668 double JIT_OPERATION operationRandom(JSGlobalObject* globalObject)
1669 {
1670     return globalObject->weakRandomNumber();
1671 }
1672 #endif
1673
1674 JSCell* JIT_OPERATION operationStringFromCharCode(ExecState* exec, int32_t op1)
1675 {
1676     VM* vm = &exec->vm();
1677     NativeCallFrameTracer tracer(vm, exec);
1678     return JSC::stringFromCharCode(exec, op1);
1679 }
1680
1681 EncodedJSValue JIT_OPERATION operationStringFromCharCodeUntyped(ExecState* exec, EncodedJSValue encodedValue)
1682 {
1683     VM* vm = &exec->vm();
1684     NativeCallFrameTracer tracer(vm, exec);
1685     JSValue charValue = JSValue::decode(encodedValue);
1686     int32_t chInt = charValue.toUInt32(exec);
1687     return JSValue::encode(JSC::stringFromCharCode(exec, chInt));
1688 }
1689
1690 int64_t JIT_OPERATION operationConvertBoxedDoubleToInt52(EncodedJSValue encodedValue)
1691 {
1692     JSValue value = JSValue::decode(encodedValue);
1693     if (!value.isDouble())
1694         return JSValue::notInt52;
1695     return tryConvertToInt52(value.asDouble());
1696 }
1697
1698 int64_t JIT_OPERATION operationConvertDoubleToInt52(double value)
1699 {
1700     return tryConvertToInt52(value);
1701 }
1702
1703 size_t JIT_OPERATION operationDefaultHasInstance(ExecState* exec, JSCell* value, JSCell* proto) // Returns jsBoolean(True|False) on 64-bit.
1704 {
1705     VM* vm = &exec->vm();
1706     NativeCallFrameTracer tracer(vm, exec);
1707     if (JSObject::defaultHasInstance(exec, value, proto))
1708         return 1;
1709     return 0;
1710 }
1711
1712 char* JIT_OPERATION operationNewRawObject(ExecState* exec, Structure* structure, int32_t length, Butterfly* butterfly)
1713 {
1714     VM& vm = exec->vm();
1715     NativeCallFrameTracer tracer(&vm, exec);
1716
1717     if (!butterfly
1718         && (structure->outOfLineCapacity() || hasIndexedProperties(structure->indexingType()))) {
1719         IndexingHeader header;
1720         header.setVectorLength(length);
1721         header.setPublicLength(0);
1722         
1723         butterfly = Butterfly::create(
1724             vm, nullptr, 0, structure->outOfLineCapacity(),
1725             hasIndexedProperties(structure->indexingType()), header,
1726             length * sizeof(EncodedJSValue));
1727     }
1728
1729     JSObject* result = JSObject::createRawObject(exec, structure, butterfly);
1730     result->butterfly(); // Ensure that the butterfly is in to-space.
1731     return bitwise_cast<char*>(result);
1732 }
1733
1734 JSCell* JIT_OPERATION operationNewObjectWithButterfly(ExecState* exec, Structure* structure, Butterfly* butterfly)
1735 {
1736     VM& vm = exec->vm();
1737     NativeCallFrameTracer tracer(&vm, exec);
1738     
1739     if (!butterfly) {
1740         butterfly = Butterfly::create(
1741             vm, nullptr, 0, structure->outOfLineCapacity(), false, IndexingHeader(), 0);
1742     }
1743     
1744     JSObject* result = JSObject::createRawObject(exec, structure, butterfly);
1745     result->butterfly(); // Ensure that the butterfly is in to-space.
1746     return result;
1747 }
1748
1749 JSCell* JIT_OPERATION operationNewObjectWithButterflyWithIndexingHeaderAndVectorLength(ExecState* exec, Structure* structure, unsigned length, Butterfly* butterfly)
1750 {
1751     VM& vm = exec->vm();
1752     NativeCallFrameTracer tracer(&vm, exec);
1753
1754     IndexingHeader header;
1755     header.setVectorLength(length);
1756     header.setPublicLength(0);
1757     if (butterfly)
1758         *butterfly->indexingHeader() = header;
1759     else {
1760         butterfly = Butterfly::create(
1761             vm, nullptr, 0, structure->outOfLineCapacity(), true, header,
1762             sizeof(EncodedJSValue) * length);
1763     }
1764     
1765     // Paradoxically this may allocate a JSArray. That's totally cool.
1766     JSObject* result = JSObject::createRawObject(exec, structure, butterfly);
1767     result->butterfly(); // Ensure that the butterfly is in to-space.
1768     return result;
1769 }
1770
1771 void JIT_OPERATION operationProcessTypeProfilerLogDFG(ExecState* exec) 
1772 {
1773     VM& vm = exec->vm();
1774     NativeCallFrameTracer tracer(&vm, exec);
1775
1776     vm.typeProfilerLog()->processLogEntries(ASCIILiteral("Log Full, called from inside DFG."));
1777 }
1778
1779 void JIT_OPERATION debugOperationPrintSpeculationFailure(ExecState* exec, void* debugInfoRaw, void* scratch)
1780 {
1781     VM* vm = &exec->vm();
1782     NativeCallFrameTracer tracer(vm, exec);
1783     
1784     SpeculationFailureDebugInfo* debugInfo = static_cast<SpeculationFailureDebugInfo*>(debugInfoRaw);
1785     CodeBlock* codeBlock = debugInfo->codeBlock;
1786     CodeBlock* alternative = codeBlock->alternative();
1787     dataLog("Speculation failure in ", *codeBlock);
1788     dataLog(" @ exit #", vm->osrExitIndex, " (bc#", debugInfo->bytecodeOffset, ", ", exitKindToString(debugInfo->kind), ") with ");
1789     if (alternative) {
1790         dataLog(
1791             "executeCounter = ", alternative->jitExecuteCounter(),
1792             ", reoptimizationRetryCounter = ", alternative->reoptimizationRetryCounter(),
1793             ", optimizationDelayCounter = ", alternative->optimizationDelayCounter());
1794     } else
1795         dataLog("no alternative code block (i.e. we've been jettisoned)");
1796     dataLog(", osrExitCounter = ", codeBlock->osrExitCounter(), "\n");
1797     dataLog("    GPRs at time of exit:");
1798     char* scratchPointer = static_cast<char*>(scratch);
1799     for (unsigned i = 0; i < GPRInfo::numberOfRegisters; ++i) {
1800         GPRReg gpr = GPRInfo::toRegister(i);
1801         dataLog(" ", GPRInfo::debugName(gpr), ":", RawPointer(*reinterpret_cast_ptr<void**>(scratchPointer)));
1802         scratchPointer += sizeof(EncodedJSValue);
1803     }
1804     dataLog("\n");
1805     dataLog("    FPRs at time of exit:");
1806     for (unsigned i = 0; i < FPRInfo::numberOfRegisters; ++i) {
1807         FPRReg fpr = FPRInfo::toRegister(i);
1808         dataLog(" ", FPRInfo::debugName(fpr), ":");
1809         uint64_t bits = *reinterpret_cast_ptr<uint64_t*>(scratchPointer);
1810         double value = *reinterpret_cast_ptr<double*>(scratchPointer);
1811         dataLogF("%llx:%lf", static_cast<long long>(bits), value);
1812         scratchPointer += sizeof(EncodedJSValue);
1813     }
1814     dataLog("\n");
1815 }
1816
1817 JSCell* JIT_OPERATION operationResolveScope(ExecState* exec, JSScope* scope, UniquedStringImpl* impl)
1818 {
1819     VM& vm = exec->vm();
1820     NativeCallFrameTracer tracer(&vm, exec);
1821
1822     JSObject* resolvedScope = JSScope::resolve(exec, scope, Identifier::fromUid(exec, impl));
1823     return resolvedScope;
1824 }
1825
1826 EncodedJSValue JIT_OPERATION operationGetDynamicVar(ExecState* exec, JSObject* scope, UniquedStringImpl* impl, unsigned getPutInfoBits)
1827 {
1828     VM& vm = exec->vm();
1829     NativeCallFrameTracer tracer(&vm, exec);
1830     auto throwScope = DECLARE_THROW_SCOPE(vm);
1831
1832     Identifier ident = Identifier::fromUid(exec, impl);
1833     return JSValue::encode(scope->getPropertySlot(exec, ident, [&] (bool found, PropertySlot& slot) -> JSValue {
1834         if (!found) {
1835             GetPutInfo getPutInfo(getPutInfoBits);
1836             if (getPutInfo.resolveMode() == ThrowIfNotFound)
1837                 throwException(exec, throwScope, createUndefinedVariableError(exec, ident));
1838             return jsUndefined();
1839         }
1840
1841         if (scope->isGlobalLexicalEnvironment()) {
1842             // When we can't statically prove we need a TDZ check, we must perform the check on the slow path.
1843             JSValue result = slot.getValue(exec, ident);
1844             if (result == jsTDZValue()) {
1845                 throwException(exec, throwScope, createTDZError(exec));
1846                 return jsUndefined();
1847             }
1848             return result;
1849         }
1850
1851         return slot.getValue(exec, ident);
1852     }));
1853 }
1854
1855 void JIT_OPERATION operationPutDynamicVar(ExecState* exec, JSObject* scope, EncodedJSValue value, UniquedStringImpl* impl, unsigned getPutInfoBits)
1856 {
1857     VM& vm = exec->vm();
1858     NativeCallFrameTracer tracer(&vm, exec);
1859     auto throwScope = DECLARE_THROW_SCOPE(vm);
1860
1861     const Identifier& ident = Identifier::fromUid(exec, impl);
1862     GetPutInfo getPutInfo(getPutInfoBits);
1863     bool hasProperty = scope->hasProperty(exec, ident);
1864     if (hasProperty
1865         && scope->isGlobalLexicalEnvironment()
1866         && !isInitialization(getPutInfo.initializationMode())) {
1867         // When we can't statically prove we need a TDZ check, we must perform the check on the slow path.
1868         PropertySlot slot(scope, PropertySlot::InternalMethodType::Get);
1869         JSGlobalLexicalEnvironment::getOwnPropertySlot(scope, exec, ident, slot);
1870         if (slot.getValue(exec, ident) == jsTDZValue()) {
1871             throwException(exec, throwScope, createTDZError(exec));
1872             return;
1873         }
1874     }
1875
1876     if (getPutInfo.resolveMode() == ThrowIfNotFound && !hasProperty) {
1877         throwException(exec, throwScope, createUndefinedVariableError(exec, ident));
1878         return;
1879     }
1880
1881     CodeOrigin origin = exec->codeOrigin();
1882     bool strictMode;
1883     if (origin.inlineCallFrame)
1884         strictMode = origin.inlineCallFrame->baselineCodeBlock->isStrictMode();
1885     else
1886         strictMode = exec->codeBlock()->isStrictMode();
1887     PutPropertySlot slot(scope, strictMode, PutPropertySlot::UnknownContext, isInitialization(getPutInfo.initializationMode()));
1888     scope->methodTable()->put(scope, exec, ident, JSValue::decode(value), slot);
1889 }
1890
1891 int32_t JIT_OPERATION operationMapHash(ExecState* exec, EncodedJSValue input)
1892 {
1893     VM& vm = exec->vm();
1894     NativeCallFrameTracer tracer(&vm, exec);
1895
1896     return jsMapHash(exec, vm, normalizeMapKey(JSValue::decode(input)));
1897 }
1898
1899 JSCell* JIT_OPERATION operationJSMapFindBucket(ExecState* exec, JSCell* map, EncodedJSValue key, int32_t hash)
1900 {
1901     VM& vm = exec->vm();
1902     NativeCallFrameTracer tracer(&vm, exec);
1903     JSMap::BucketType** bucket = jsCast<JSMap*>(map)->findBucket(exec, normalizeMapKey(JSValue::decode(key)), hash);
1904     if (!bucket)
1905         return nullptr;
1906     return *bucket;
1907 }
1908
1909 JSCell* JIT_OPERATION operationJSSetFindBucket(ExecState* exec, JSCell* map, EncodedJSValue key, int32_t hash)
1910 {
1911     VM& vm = exec->vm();
1912     NativeCallFrameTracer tracer(&vm, exec);
1913     JSSet::BucketType** bucket = jsCast<JSSet*>(map)->findBucket(exec, normalizeMapKey(JSValue::decode(key)), hash);
1914     if (!bucket)
1915         return nullptr;
1916     return *bucket;
1917 }
1918
1919 extern "C" void JIT_OPERATION triggerReoptimizationNow(CodeBlock* codeBlock, OSRExitBase* exit)
1920 {
1921     // It's sort of preferable that we don't GC while in here. Anyways, doing so wouldn't
1922     // really be profitable.
1923     DeferGCForAWhile deferGC(codeBlock->vm()->heap);
1924     
1925     if (Options::verboseOSR())
1926         dataLog(*codeBlock, ": Entered reoptimize\n");
1927     // We must be called with the baseline code block.
1928     ASSERT(JITCode::isBaselineCode(codeBlock->jitType()));
1929
1930     // If I am my own replacement, then reoptimization has already been triggered.
1931     // This can happen in recursive functions.
1932     if (codeBlock->replacement() == codeBlock) {
1933         if (Options::verboseOSR())
1934             dataLog(*codeBlock, ": Not reoptimizing because we've already been jettisoned.\n");
1935         return;
1936     }
1937     
1938     // Otherwise, the replacement must be optimized code. Use this as an opportunity
1939     // to check our logic.
1940     ASSERT(codeBlock->hasOptimizedReplacement());
1941     CodeBlock* optimizedCodeBlock = codeBlock->replacement();
1942     ASSERT(JITCode::isOptimizingJIT(optimizedCodeBlock->jitType()));
1943     
1944     bool didTryToEnterIntoInlinedLoops = false;
1945     for (InlineCallFrame* inlineCallFrame = exit->m_codeOrigin.inlineCallFrame; inlineCallFrame; inlineCallFrame = inlineCallFrame->directCaller.inlineCallFrame) {
1946         if (inlineCallFrame->baselineCodeBlock->ownerScriptExecutable()->didTryToEnterInLoop()) {
1947             didTryToEnterIntoInlinedLoops = true;
1948             break;
1949         }
1950     }
1951
1952     // In order to trigger reoptimization, one of two things must have happened:
1953     // 1) We exited more than some number of times.
1954     // 2) We exited and got stuck in a loop, and now we're exiting again.
1955     bool didExitABunch = optimizedCodeBlock->shouldReoptimizeNow();
1956     bool didGetStuckInLoop =
1957         (codeBlock->checkIfOptimizationThresholdReached() || didTryToEnterIntoInlinedLoops)
1958         && optimizedCodeBlock->shouldReoptimizeFromLoopNow();
1959     
1960     if (!didExitABunch && !didGetStuckInLoop) {
1961         if (Options::verboseOSR())
1962             dataLog(*codeBlock, ": Not reoptimizing ", *optimizedCodeBlock, " because it either didn't exit enough or didn't loop enough after exit.\n");
1963         codeBlock->optimizeAfterLongWarmUp();
1964         return;
1965     }
1966
1967     optimizedCodeBlock->jettison(Profiler::JettisonDueToOSRExit, CountReoptimization);
1968 }
1969
1970 #if ENABLE(FTL_JIT)
1971 static bool shouldTriggerFTLCompile(CodeBlock* codeBlock, JITCode* jitCode)
1972 {
1973     if (codeBlock->baselineVersion()->m_didFailFTLCompilation) {
1974         CODEBLOCK_LOG_EVENT(codeBlock, "abortFTLCompile", ());
1975         if (Options::verboseOSR())
1976             dataLog("Deferring FTL-optimization of ", *codeBlock, " indefinitely because there was an FTL failure.\n");
1977         jitCode->dontOptimizeAnytimeSoon(codeBlock);
1978         return false;
1979     }
1980
1981     if (!codeBlock->hasOptimizedReplacement()
1982         && !jitCode->checkIfOptimizationThresholdReached(codeBlock)) {
1983         CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("counter = ", jitCode->tierUpCounter));
1984         if (Options::verboseOSR())
1985             dataLog("Choosing not to FTL-optimize ", *codeBlock, " yet.\n");
1986         return false;
1987     }
1988     return true;
1989 }
1990
1991 static void triggerFTLReplacementCompile(VM* vm, CodeBlock* codeBlock, JITCode* jitCode)
1992 {
1993     Worklist::State worklistState;
1994     if (Worklist* worklist = existingGlobalFTLWorklistOrNull()) {
1995         worklistState = worklist->completeAllReadyPlansForVM(
1996             *vm, CompilationKey(codeBlock->baselineVersion(), FTLMode));
1997     } else
1998         worklistState = Worklist::NotKnown;
1999     
2000     if (worklistState == Worklist::Compiling) {
2001         CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("still compiling"));
2002         jitCode->setOptimizationThresholdBasedOnCompilationResult(
2003             codeBlock, CompilationDeferred);
2004         return;
2005     }
2006     
2007     if (codeBlock->hasOptimizedReplacement()) {
2008         CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("has replacement"));
2009         // That's great, we've compiled the code - next time we call this function,
2010         // we'll enter that replacement.
2011         jitCode->optimizeSoon(codeBlock);
2012         return;
2013     }
2014     
2015     if (worklistState == Worklist::Compiled) {
2016         CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("compiled and failed"));
2017         // This means that we finished compiling, but failed somehow; in that case the
2018         // thresholds will be set appropriately.
2019         if (Options::verboseOSR())
2020             dataLog("Code block ", *codeBlock, " was compiled but it doesn't have an optimized replacement.\n");
2021         return;
2022     }
2023
2024     CODEBLOCK_LOG_EVENT(codeBlock, "triggerFTLReplacement", ());
2025     // We need to compile the code.
2026     compile(
2027         *vm, codeBlock->newReplacement(), codeBlock, FTLMode, UINT_MAX,
2028         Operands<JSValue>(), ToFTLDeferredCompilationCallback::create());
2029
2030     // If we reached here, the counter has not be reset. Do that now.
2031     jitCode->setOptimizationThresholdBasedOnCompilationResult(
2032         codeBlock, CompilationDeferred);
2033 }
2034
2035 void JIT_OPERATION triggerTierUpNow(ExecState* exec)
2036 {
2037     VM* vm = &exec->vm();
2038     NativeCallFrameTracer tracer(vm, exec);
2039     DeferGCForAWhile deferGC(vm->heap);
2040     CodeBlock* codeBlock = exec->codeBlock();
2041     
2042     if (codeBlock->jitType() != JITCode::DFGJIT) {
2043         dataLog("Unexpected code block in DFG->FTL tier-up: ", *codeBlock, "\n");
2044         RELEASE_ASSERT_NOT_REACHED();
2045     }
2046     
2047     JITCode* jitCode = codeBlock->jitCode()->dfg();
2048     
2049     if (Options::verboseOSR()) {
2050         dataLog(
2051             *codeBlock, ": Entered triggerTierUpNow with executeCounter = ",
2052             jitCode->tierUpCounter, "\n");
2053     }
2054
2055     if (shouldTriggerFTLCompile(codeBlock, jitCode))
2056         triggerFTLReplacementCompile(vm, codeBlock, jitCode);
2057
2058     if (codeBlock->hasOptimizedReplacement()) {
2059         if (jitCode->tierUpEntryTriggers.isEmpty()) {
2060             CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("replacement in place, delaying indefinitely"));
2061             // There is nothing more we can do, the only way this will be entered
2062             // is through the function entry point.
2063             jitCode->dontOptimizeAnytimeSoon(codeBlock);
2064             return;
2065         }
2066         if (jitCode->osrEntryBlock() && jitCode->tierUpEntryTriggers.size() == 1) {
2067             CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("trigger in place, delaying indefinitely"));
2068             // There is only one outer loop and its trigger must have been set
2069             // when the plan completed.
2070             // Exiting the inner loop is useless, we can ignore the counter and leave
2071             // the trigger do its job.
2072             jitCode->dontOptimizeAnytimeSoon(codeBlock);
2073             return;
2074         }
2075     }
2076 }
2077
2078 static char* tierUpCommon(ExecState* exec, unsigned originBytecodeIndex, unsigned osrEntryBytecodeIndex)
2079 {
2080     VM* vm = &exec->vm();
2081     CodeBlock* codeBlock = exec->codeBlock();
2082
2083     // Resolve any pending plan for OSR Enter on this function.
2084     Worklist::State worklistState;
2085     if (Worklist* worklist = existingGlobalFTLWorklistOrNull()) {
2086         worklistState = worklist->completeAllReadyPlansForVM(
2087             *vm, CompilationKey(codeBlock->baselineVersion(), FTLForOSREntryMode));
2088     } else
2089         worklistState = Worklist::NotKnown;
2090
2091     JITCode* jitCode = codeBlock->jitCode()->dfg();
2092     if (worklistState == Worklist::Compiling) {
2093         CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("still compiling"));
2094         jitCode->setOptimizationThresholdBasedOnCompilationResult(
2095             codeBlock, CompilationDeferred);
2096         return nullptr;
2097     }
2098
2099     if (worklistState == Worklist::Compiled) {
2100         CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("compiled and failed"));
2101         // This means that compilation failed and we already set the thresholds.
2102         if (Options::verboseOSR())
2103             dataLog("Code block ", *codeBlock, " was compiled but it doesn't have an optimized replacement.\n");
2104         return nullptr;
2105     }
2106
2107     // If we can OSR Enter, do it right away.
2108     if (originBytecodeIndex == osrEntryBytecodeIndex) {
2109         unsigned streamIndex = jitCode->bytecodeIndexToStreamIndex.get(originBytecodeIndex);
2110         if (CodeBlock* entryBlock = jitCode->osrEntryBlock()) {
2111             if (void* address = FTL::prepareOSREntry(exec, codeBlock, entryBlock, originBytecodeIndex, streamIndex)) {
2112                 CODEBLOCK_LOG_EVENT(entryBlock, "osrEntry", ("at bc#", originBytecodeIndex));
2113                 return static_cast<char*>(address);
2114             }
2115         }
2116     }
2117
2118     // - If we don't have an FTL code block, then try to compile one.
2119     // - If we do have an FTL code block, then try to enter for a while.
2120     // - If we couldn't enter for a while, then trigger OSR entry.
2121
2122     if (!shouldTriggerFTLCompile(codeBlock, jitCode))
2123         return nullptr;
2124
2125     if (!jitCode->neverExecutedEntry) {
2126         triggerFTLReplacementCompile(vm, codeBlock, jitCode);
2127
2128         if (!codeBlock->hasOptimizedReplacement())
2129             return nullptr;
2130
2131         if (jitCode->osrEntryRetry < Options::ftlOSREntryRetryThreshold()) {
2132             CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("avoiding OSR entry compile"));
2133             jitCode->osrEntryRetry++;
2134             return nullptr;
2135         }
2136     } else
2137         CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("avoiding replacement compile"));
2138
2139     // It's time to try to compile code for OSR entry.
2140     if (CodeBlock* entryBlock = jitCode->osrEntryBlock()) {
2141         if (jitCode->osrEntryRetry < Options::ftlOSREntryRetryThreshold()) {
2142             CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("OSR entry failed, OSR entry threshold not met"));
2143             jitCode->osrEntryRetry++;
2144             jitCode->setOptimizationThresholdBasedOnCompilationResult(
2145                 codeBlock, CompilationDeferred);
2146             return nullptr;
2147         }
2148
2149         FTL::ForOSREntryJITCode* entryCode = entryBlock->jitCode()->ftlForOSREntry();
2150         entryCode->countEntryFailure();
2151         if (entryCode->entryFailureCount() <
2152             Options::ftlOSREntryFailureCountForReoptimization()) {
2153             CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("OSR entry failed"));
2154             jitCode->setOptimizationThresholdBasedOnCompilationResult(
2155                 codeBlock, CompilationDeferred);
2156             return nullptr;
2157         }
2158
2159         // OSR entry failed. Oh no! This implies that we need to retry. We retry
2160         // without exponential backoff and we only do this for the entry code block.
2161         CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("OSR entry failed too many times"));
2162         unsigned osrEntryBytecode = entryBlock->jitCode()->ftlForOSREntry()->bytecodeIndex();
2163         jitCode->clearOSREntryBlock();
2164         jitCode->osrEntryRetry = 0;
2165         jitCode->tierUpEntryTriggers.set(osrEntryBytecode, 0);
2166         jitCode->setOptimizationThresholdBasedOnCompilationResult(
2167             codeBlock, CompilationDeferred);
2168         return nullptr;
2169     }
2170
2171     unsigned streamIndex = jitCode->bytecodeIndexToStreamIndex.get(osrEntryBytecodeIndex);
2172     auto tierUpHierarchyEntry = jitCode->tierUpInLoopHierarchy.find(osrEntryBytecodeIndex);
2173     if (tierUpHierarchyEntry != jitCode->tierUpInLoopHierarchy.end()) {
2174         for (unsigned osrEntryCandidate : tierUpHierarchyEntry->value) {
2175             if (jitCode->tierUpEntrySeen.contains(osrEntryCandidate)) {
2176                 osrEntryBytecodeIndex = osrEntryCandidate;
2177                 streamIndex = jitCode->bytecodeIndexToStreamIndex.get(osrEntryBytecodeIndex);
2178             }
2179         }
2180     }
2181
2182     // We aren't compiling and haven't compiled anything for OSR entry. So, try to compile
2183     // something.
2184     auto triggerIterator = jitCode->tierUpEntryTriggers.find(osrEntryBytecodeIndex);
2185     RELEASE_ASSERT(triggerIterator != jitCode->tierUpEntryTriggers.end());
2186     uint8_t* triggerAddress = &(triggerIterator->value);
2187
2188     Operands<JSValue> mustHandleValues;
2189     jitCode->reconstruct(
2190         exec, codeBlock, CodeOrigin(osrEntryBytecodeIndex), streamIndex, mustHandleValues);
2191     CodeBlock* replacementCodeBlock = codeBlock->newReplacement();
2192
2193     CODEBLOCK_LOG_EVENT(codeBlock, "triggerFTLOSR", ());
2194     CompilationResult forEntryResult = compile(
2195         *vm, replacementCodeBlock, codeBlock, FTLForOSREntryMode, osrEntryBytecodeIndex,
2196         mustHandleValues, ToFTLForOSREntryDeferredCompilationCallback::create(triggerAddress));
2197
2198     if (jitCode->neverExecutedEntry)
2199         triggerFTLReplacementCompile(vm, codeBlock, jitCode);
2200
2201     if (forEntryResult != CompilationSuccessful) {
2202         CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("OSR ecompilation not successful"));
2203         jitCode->setOptimizationThresholdBasedOnCompilationResult(
2204             codeBlock, CompilationDeferred);
2205         return nullptr;
2206     }
2207     
2208     CODEBLOCK_LOG_EVENT(jitCode->osrEntryBlock(), "osrEntry", ("at bc#", originBytecodeIndex));
2209     // It's possible that the for-entry compile already succeeded. In that case OSR
2210     // entry will succeed unless we ran out of stack. It's not clear what we should do.
2211     // We signal to try again after a while if that happens.
2212     void* address = FTL::prepareOSREntry(
2213         exec, codeBlock, jitCode->osrEntryBlock(), originBytecodeIndex, streamIndex);
2214     return static_cast<char*>(address);
2215 }
2216
2217 void JIT_OPERATION triggerTierUpNowInLoop(ExecState* exec, unsigned bytecodeIndex)
2218 {
2219     VM* vm = &exec->vm();
2220     NativeCallFrameTracer tracer(vm, exec);
2221     DeferGCForAWhile deferGC(vm->heap);
2222     CodeBlock* codeBlock = exec->codeBlock();
2223
2224     if (codeBlock->jitType() != JITCode::DFGJIT) {
2225         dataLog("Unexpected code block in DFG->FTL tier-up: ", *codeBlock, "\n");
2226         RELEASE_ASSERT_NOT_REACHED();
2227     }
2228
2229     JITCode* jitCode = codeBlock->jitCode()->dfg();
2230
2231     if (Options::verboseOSR()) {
2232         dataLog(
2233             *codeBlock, ": Entered triggerTierUpNowInLoop with executeCounter = ",
2234             jitCode->tierUpCounter, "\n");
2235     }
2236
2237     auto tierUpHierarchyEntry = jitCode->tierUpInLoopHierarchy.find(bytecodeIndex);
2238     if (tierUpHierarchyEntry != jitCode->tierUpInLoopHierarchy.end()
2239         && !tierUpHierarchyEntry->value.isEmpty()) {
2240         tierUpCommon(exec, bytecodeIndex, tierUpHierarchyEntry->value.first());
2241     } else if (shouldTriggerFTLCompile(codeBlock, jitCode))
2242         triggerFTLReplacementCompile(vm, codeBlock, jitCode);
2243
2244     // Since we cannot OSR Enter here, the default "optimizeSoon()" is not useful.
2245     if (codeBlock->hasOptimizedReplacement()) {
2246         CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("OSR in loop failed, deferring"));
2247         jitCode->setOptimizationThresholdBasedOnCompilationResult(codeBlock, CompilationDeferred);
2248     }
2249 }
2250
2251 char* JIT_OPERATION triggerOSREntryNow(ExecState* exec, unsigned bytecodeIndex)
2252 {
2253     VM* vm = &exec->vm();
2254     NativeCallFrameTracer tracer(vm, exec);
2255     DeferGCForAWhile deferGC(vm->heap);
2256     CodeBlock* codeBlock = exec->codeBlock();
2257
2258     if (codeBlock->jitType() != JITCode::DFGJIT) {
2259         dataLog("Unexpected code block in DFG->FTL tier-up: ", *codeBlock, "\n");
2260         RELEASE_ASSERT_NOT_REACHED();
2261     }
2262
2263     JITCode* jitCode = codeBlock->jitCode()->dfg();
2264     jitCode->tierUpEntrySeen.add(bytecodeIndex);
2265
2266     if (Options::verboseOSR()) {
2267         dataLog(
2268             *codeBlock, ": Entered triggerOSREntryNow with executeCounter = ",
2269             jitCode->tierUpCounter, "\n");
2270     }
2271
2272     return tierUpCommon(exec, bytecodeIndex, bytecodeIndex);
2273 }
2274
2275 #endif // ENABLE(FTL_JIT)
2276
2277 } // extern "C"
2278 } } // namespace JSC::DFG
2279
2280 #endif // ENABLE(DFG_JIT)
2281
2282 #endif // ENABLE(JIT)