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