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