0198066b72ce9aacd497d6619f8f63ba42dd830d
[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 operationIsArrayConstructor(ExecState* exec, EncodedJSValue encodedTarget)
701 {
702     VM& vm = exec->vm();
703     NativeCallFrameTracer tracer(&vm, exec);
704
705     return isArrayConstructor(JSValue::decode(encodedTarget));
706 }
707
708 size_t JIT_OPERATION operationIsArrayObject(ExecState* exec, EncodedJSValue encodedTarget)
709 {
710     VM& vm = exec->vm();
711     NativeCallFrameTracer tracer(&vm, exec);
712
713     return isArray(exec, JSValue::decode(encodedTarget));
714 }
715
716 size_t JIT_OPERATION operationCompareStrictEqCell(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
717 {
718     VM* vm = &exec->vm();
719     NativeCallFrameTracer tracer(vm, exec);
720     
721     JSValue op1 = JSValue::decode(encodedOp1);
722     JSValue op2 = JSValue::decode(encodedOp2);
723     
724     ASSERT(op1.isCell());
725     ASSERT(op2.isCell());
726     
727     return JSValue::strictEqualSlowCaseInline(exec, op1, op2);
728 }
729
730 size_t JIT_OPERATION operationCompareStrictEq(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
731 {
732     VM* vm = &exec->vm();
733     NativeCallFrameTracer tracer(vm, exec);
734
735     JSValue src1 = JSValue::decode(encodedOp1);
736     JSValue src2 = JSValue::decode(encodedOp2);
737     
738     return JSValue::strictEqual(exec, src1, src2);
739 }
740
741 EncodedJSValue JIT_OPERATION operationToPrimitive(ExecState* exec, EncodedJSValue value)
742 {
743     VM* vm = &exec->vm();
744     NativeCallFrameTracer tracer(vm, exec);
745     
746     return JSValue::encode(JSValue::decode(value).toPrimitive(exec));
747 }
748
749 EncodedJSValue JIT_OPERATION operationGetByIdWithThis(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedThis, UniquedStringImpl* impl)
750 {
751     VM& vm = exec->vm();
752     NativeCallFrameTracer tracer(&vm, exec);
753
754     JSValue baseValue = JSValue::decode(encodedBase);
755     JSValue thisVal = JSValue::decode(encodedThis);
756     PropertySlot slot(thisVal, PropertySlot::PropertySlot::InternalMethodType::Get);
757     JSValue result = baseValue.get(exec, Identifier::fromUid(exec, impl), slot);
758     return JSValue::encode(result);
759 }
760
761 EncodedJSValue JIT_OPERATION operationGetByValWithThis(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedThis, EncodedJSValue encodedSubscript)
762 {
763     VM& vm = exec->vm();
764     NativeCallFrameTracer tracer(&vm, exec);
765
766     JSValue baseValue = JSValue::decode(encodedBase);
767     JSValue thisVal = JSValue::decode(encodedThis);
768     JSValue subscript = JSValue::decode(encodedSubscript);
769
770     if (LIKELY(baseValue.isCell() && subscript.isString())) {
771         Structure& structure = *baseValue.asCell()->structure(vm);
772         if (JSCell::canUseFastGetOwnProperty(structure)) {
773             if (RefPtr<AtomicStringImpl> existingAtomicString = asString(subscript)->toExistingAtomicString(exec)) {
774                 if (JSValue result = baseValue.asCell()->fastGetOwnProperty(vm, structure, existingAtomicString.get()))
775                     return JSValue::encode(result);
776             }
777         }
778     }
779     
780     PropertySlot slot(thisVal, PropertySlot::PropertySlot::InternalMethodType::Get);
781     if (subscript.isUInt32()) {
782         uint32_t i = subscript.asUInt32();
783         if (isJSString(baseValue) && asString(baseValue)->canGetIndex(i))
784             return JSValue::encode(asString(baseValue)->getIndex(exec, i));
785         
786         return JSValue::encode(baseValue.get(exec, i, slot));
787     }
788
789     baseValue.requireObjectCoercible(exec);
790     if (vm.exception())
791         return JSValue::encode(JSValue());
792
793     auto property = subscript.toPropertyKey(exec);
794     if (vm.exception())
795         return JSValue::encode(JSValue());
796     return JSValue::encode(baseValue.get(exec, property, slot));
797 }
798
799 void JIT_OPERATION operationPutByIdWithThisStrict(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedThis, EncodedJSValue encodedValue, UniquedStringImpl* impl)
800 {
801     VM& vm = exec->vm();
802     NativeCallFrameTracer tracer(&vm, exec);
803
804     putWithThis<true>(exec, encodedBase, encodedThis, encodedValue, Identifier::fromUid(exec, impl));
805 }
806
807 void JIT_OPERATION operationPutByIdWithThis(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedThis, EncodedJSValue encodedValue, UniquedStringImpl* impl)
808 {
809     VM& vm = exec->vm();
810     NativeCallFrameTracer tracer(&vm, exec);
811
812     putWithThis<false>(exec, encodedBase, encodedThis, encodedValue, Identifier::fromUid(exec, impl));
813 }
814
815 void JIT_OPERATION operationPutByValWithThisStrict(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedThis, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue)
816 {
817     VM& vm = exec->vm();
818     NativeCallFrameTracer tracer(&vm, exec);
819
820     Identifier property = JSValue::decode(encodedSubscript).toPropertyKey(exec);
821     if (vm.exception())
822         return;
823     putWithThis<true>(exec, encodedBase, encodedThis, encodedValue, property);
824 }
825
826 void JIT_OPERATION operationPutByValWithThis(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedThis, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue)
827 {
828     VM& vm = exec->vm();
829     NativeCallFrameTracer tracer(&vm, exec);
830
831     Identifier property = JSValue::decode(encodedSubscript).toPropertyKey(exec);
832     if (vm.exception())
833         return;
834     putWithThis<false>(exec, encodedBase, encodedThis, encodedValue, property);
835 }
836
837 char* JIT_OPERATION operationNewArray(ExecState* exec, Structure* arrayStructure, void* buffer, size_t size)
838 {
839     VM* vm = &exec->vm();
840     NativeCallFrameTracer tracer(vm, exec);
841     
842     return bitwise_cast<char*>(constructArray(exec, arrayStructure, static_cast<JSValue*>(buffer), size));
843 }
844
845 char* JIT_OPERATION operationNewEmptyArray(ExecState* exec, Structure* arrayStructure)
846 {
847     VM* vm = &exec->vm();
848     NativeCallFrameTracer tracer(vm, exec);
849     
850     return bitwise_cast<char*>(JSArray::create(*vm, arrayStructure));
851 }
852
853 char* JIT_OPERATION operationNewArrayWithSize(ExecState* exec, Structure* arrayStructure, int32_t size)
854 {
855     VM* vm = &exec->vm();
856     NativeCallFrameTracer tracer(vm, exec);
857
858     if (UNLIKELY(size < 0))
859         return bitwise_cast<char*>(exec->vm().throwException(exec, createRangeError(exec, ASCIILiteral("Array size is not a small enough positive integer."))));
860
861     JSArray* result = JSArray::create(*vm, arrayStructure, size);
862     result->butterfly(); // Ensure that the backing store is in to-space.
863     return bitwise_cast<char*>(result);
864 }
865
866 char* JIT_OPERATION operationNewArrayBuffer(ExecState* exec, Structure* arrayStructure, size_t start, size_t size)
867 {
868     VM& vm = exec->vm();
869     NativeCallFrameTracer tracer(&vm, exec);
870     return bitwise_cast<char*>(constructArray(exec, arrayStructure, exec->codeBlock()->constantBuffer(start), size));
871 }
872
873 char* JIT_OPERATION operationNewInt8ArrayWithSize(
874     ExecState* exec, Structure* structure, int32_t length)
875 {
876     return newTypedArrayWithSize<JSInt8Array>(exec, structure, length);
877 }
878
879 char* JIT_OPERATION operationNewInt8ArrayWithOneArgument(
880     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
881 {
882     VM& vm = exec->vm();
883     NativeCallFrameTracer tracer(&vm, exec);
884     return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSInt8Array>(exec, structure, encodedValue, 0, Nullopt));
885 }
886
887 char* JIT_OPERATION operationNewInt16ArrayWithSize(
888     ExecState* exec, Structure* structure, int32_t length)
889 {
890     return newTypedArrayWithSize<JSInt16Array>(exec, structure, length);
891 }
892
893 char* JIT_OPERATION operationNewInt16ArrayWithOneArgument(
894     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
895 {
896     VM& vm = exec->vm();
897     NativeCallFrameTracer tracer(&vm, exec);
898     return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSInt16Array>(exec, structure, encodedValue, 0, Nullopt));
899 }
900
901 char* JIT_OPERATION operationNewInt32ArrayWithSize(
902     ExecState* exec, Structure* structure, int32_t length)
903 {
904     return newTypedArrayWithSize<JSInt32Array>(exec, structure, length);
905 }
906
907 char* JIT_OPERATION operationNewInt32ArrayWithOneArgument(
908     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
909 {
910     VM& vm = exec->vm();
911     NativeCallFrameTracer tracer(&vm, exec);
912     return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSInt32Array>(exec, structure, encodedValue, 0, Nullopt));
913 }
914
915 char* JIT_OPERATION operationNewUint8ArrayWithSize(
916     ExecState* exec, Structure* structure, int32_t length)
917 {
918     return newTypedArrayWithSize<JSUint8Array>(exec, structure, length);
919 }
920
921 char* JIT_OPERATION operationNewUint8ArrayWithOneArgument(
922     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
923 {
924     VM& vm = exec->vm();
925     NativeCallFrameTracer tracer(&vm, exec);
926     return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSUint8Array>(exec, structure, encodedValue, 0, Nullopt));
927 }
928
929 char* JIT_OPERATION operationNewUint8ClampedArrayWithSize(
930     ExecState* exec, Structure* structure, int32_t length)
931 {
932     return newTypedArrayWithSize<JSUint8ClampedArray>(exec, structure, length);
933 }
934
935 char* JIT_OPERATION operationNewUint8ClampedArrayWithOneArgument(
936     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
937 {
938     VM& vm = exec->vm();
939     NativeCallFrameTracer tracer(&vm, exec);
940     return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSUint8ClampedArray>(exec, structure, encodedValue, 0, Nullopt));
941 }
942
943 char* JIT_OPERATION operationNewUint16ArrayWithSize(
944     ExecState* exec, Structure* structure, int32_t length)
945 {
946     return newTypedArrayWithSize<JSUint16Array>(exec, structure, length);
947 }
948
949 char* JIT_OPERATION operationNewUint16ArrayWithOneArgument(
950     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
951 {
952     VM& vm = exec->vm();
953     NativeCallFrameTracer tracer(&vm, exec);
954     return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSUint16Array>(exec, structure, encodedValue, 0, Nullopt));
955 }
956
957 char* JIT_OPERATION operationNewUint32ArrayWithSize(
958     ExecState* exec, Structure* structure, int32_t length)
959 {
960     return newTypedArrayWithSize<JSUint32Array>(exec, structure, length);
961 }
962
963 char* JIT_OPERATION operationNewUint32ArrayWithOneArgument(
964     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
965 {
966     VM& vm = exec->vm();
967     NativeCallFrameTracer tracer(&vm, exec);
968     return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSUint32Array>(exec, structure, encodedValue, 0, Nullopt));
969 }
970
971 char* JIT_OPERATION operationNewFloat32ArrayWithSize(
972     ExecState* exec, Structure* structure, int32_t length)
973 {
974     return newTypedArrayWithSize<JSFloat32Array>(exec, structure, length);
975 }
976
977 char* JIT_OPERATION operationNewFloat32ArrayWithOneArgument(
978     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
979 {
980     VM& vm = exec->vm();
981     NativeCallFrameTracer tracer(&vm, exec);
982     return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSFloat32Array>(exec, structure, encodedValue, 0, Nullopt));
983 }
984
985 char* JIT_OPERATION operationNewFloat64ArrayWithSize(
986     ExecState* exec, Structure* structure, int32_t length)
987 {
988     return newTypedArrayWithSize<JSFloat64Array>(exec, structure, length);
989 }
990
991 char* JIT_OPERATION operationNewFloat64ArrayWithOneArgument(
992     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
993 {
994     VM& vm = exec->vm();
995     NativeCallFrameTracer tracer(&vm, exec);
996     return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSFloat64Array>(exec, structure, encodedValue, 0, Nullopt));
997 }
998
999 JSCell* JIT_OPERATION operationCreateActivationDirect(ExecState* exec, Structure* structure, JSScope* scope, SymbolTable* table, EncodedJSValue initialValueEncoded)
1000 {
1001     JSValue initialValue = JSValue::decode(initialValueEncoded);
1002     ASSERT(initialValue == jsUndefined() || initialValue == jsTDZValue());
1003     VM& vm = exec->vm();
1004     NativeCallFrameTracer tracer(&vm, exec);
1005     return JSLexicalEnvironment::create(vm, structure, scope, table, initialValue);
1006 }
1007
1008 JSCell* JIT_OPERATION operationCreateDirectArguments(ExecState* exec, Structure* structure, int32_t length, int32_t minCapacity)
1009 {
1010     VM& vm = exec->vm();
1011     NativeCallFrameTracer target(&vm, exec);
1012     DirectArguments* result = DirectArguments::create(
1013         vm, structure, length, std::max(length, minCapacity));
1014     // The caller will store to this object without barriers. Most likely, at this point, this is
1015     // still a young object and so no barriers are needed. But it's good to be careful anyway,
1016     // since the GC should be allowed to do crazy (like pretenuring, for example).
1017     vm.heap.writeBarrier(result);
1018     return result;
1019 }
1020
1021 JSCell* JIT_OPERATION operationCreateScopedArguments(ExecState* exec, Structure* structure, Register* argumentStart, int32_t length, JSFunction* callee, JSLexicalEnvironment* scope)
1022 {
1023     VM& vm = exec->vm();
1024     NativeCallFrameTracer target(&vm, exec);
1025     
1026     // We could pass the ScopedArgumentsTable* as an argument. We currently don't because I
1027     // didn't feel like changing the max number of arguments for a slow path call from 6 to 7.
1028     ScopedArgumentsTable* table = scope->symbolTable()->arguments();
1029     
1030     return ScopedArguments::createByCopyingFrom(
1031         vm, structure, argumentStart, length, callee, table, scope);
1032 }
1033
1034 JSCell* JIT_OPERATION operationCreateClonedArguments(ExecState* exec, Structure* structure, Register* argumentStart, int32_t length, JSFunction* callee)
1035 {
1036     VM& vm = exec->vm();
1037     NativeCallFrameTracer target(&vm, exec);
1038     return ClonedArguments::createByCopyingFrom(
1039         exec, structure, argumentStart, length, callee);
1040 }
1041
1042 JSCell* JIT_OPERATION operationCreateDirectArgumentsDuringExit(ExecState* exec, InlineCallFrame* inlineCallFrame, JSFunction* callee, int32_t argumentCount)
1043 {
1044     VM& vm = exec->vm();
1045     NativeCallFrameTracer target(&vm, exec);
1046     
1047     DeferGCForAWhile deferGC(vm.heap);
1048     
1049     CodeBlock* codeBlock;
1050     if (inlineCallFrame)
1051         codeBlock = baselineCodeBlockForInlineCallFrame(inlineCallFrame);
1052     else
1053         codeBlock = exec->codeBlock();
1054     
1055     unsigned length = argumentCount - 1;
1056     unsigned capacity = std::max(length, static_cast<unsigned>(codeBlock->numParameters() - 1));
1057     DirectArguments* result = DirectArguments::create(
1058         vm, codeBlock->globalObject()->directArgumentsStructure(), length, capacity);
1059     
1060     result->callee().set(vm, result, callee);
1061     
1062     Register* arguments =
1063         exec->registers() + (inlineCallFrame ? inlineCallFrame->stackOffset : 0) +
1064         CallFrame::argumentOffset(0);
1065     for (unsigned i = length; i--;)
1066         result->setIndexQuickly(vm, i, arguments[i].jsValue());
1067     
1068     return result;
1069 }
1070
1071 JSCell* JIT_OPERATION operationCreateClonedArgumentsDuringExit(ExecState* exec, InlineCallFrame* inlineCallFrame, JSFunction* callee, int32_t argumentCount)
1072 {
1073     VM& vm = exec->vm();
1074     NativeCallFrameTracer target(&vm, exec);
1075     
1076     DeferGCForAWhile deferGC(vm.heap);
1077     
1078     CodeBlock* codeBlock;
1079     if (inlineCallFrame)
1080         codeBlock = baselineCodeBlockForInlineCallFrame(inlineCallFrame);
1081     else
1082         codeBlock = exec->codeBlock();
1083     
1084     unsigned length = argumentCount - 1;
1085     ClonedArguments* result = ClonedArguments::createEmpty(
1086         vm, codeBlock->globalObject()->clonedArgumentsStructure(), callee, length);
1087     
1088     Register* arguments =
1089         exec->registers() + (inlineCallFrame ? inlineCallFrame->stackOffset : 0) +
1090         CallFrame::argumentOffset(0);
1091     for (unsigned i = length; i--;)
1092         result->initializeIndex(vm, i, arguments[i].jsValue());
1093
1094     
1095     return result;
1096 }
1097
1098 void JIT_OPERATION operationCopyRest(ExecState* exec, JSCell* arrayAsCell, Register* argumentStart, unsigned numberOfParamsToSkip, unsigned arraySize)
1099 {
1100     VM* vm = &exec->vm();
1101     NativeCallFrameTracer tracer(vm, exec);
1102
1103     ASSERT(arraySize);
1104     JSArray* array = jsCast<JSArray*>(arrayAsCell);
1105     ASSERT(arraySize == array->length());
1106     array->setLength(exec, arraySize);
1107     for (unsigned i = 0; i < arraySize; i++)
1108         array->putDirectIndex(exec, i, argumentStart[i + numberOfParamsToSkip].jsValue());
1109 }
1110
1111 size_t JIT_OPERATION operationObjectIsObject(ExecState* exec, JSGlobalObject* globalObject, JSCell* object)
1112 {
1113     VM& vm = exec->vm();
1114     NativeCallFrameTracer tracer(&vm, exec);
1115
1116     ASSERT(jsDynamicCast<JSObject*>(object));
1117     
1118     if (object->structure(vm)->masqueradesAsUndefined(globalObject))
1119         return false;
1120     if (object->type() == JSFunctionType)
1121         return false;
1122     if (object->inlineTypeFlags() & TypeOfShouldCallGetCallData) {
1123         CallData callData;
1124         if (object->methodTable(vm)->getCallData(object, callData) != CallType::None)
1125             return false;
1126     }
1127     
1128     return true;
1129 }
1130
1131 size_t JIT_OPERATION operationObjectIsFunction(ExecState* exec, JSGlobalObject* globalObject, JSCell* object)
1132 {
1133     VM& vm = exec->vm();
1134     NativeCallFrameTracer tracer(&vm, exec);
1135
1136     ASSERT(jsDynamicCast<JSObject*>(object));
1137     
1138     if (object->structure(vm)->masqueradesAsUndefined(globalObject))
1139         return false;
1140     if (object->type() == JSFunctionType)
1141         return true;
1142     if (object->inlineTypeFlags() & TypeOfShouldCallGetCallData) {
1143         CallData callData;
1144         if (object->methodTable(vm)->getCallData(object, callData) != CallType::None)
1145             return true;
1146     }
1147     
1148     return false;
1149 }
1150
1151 JSCell* JIT_OPERATION operationTypeOfObject(ExecState* exec, JSGlobalObject* globalObject, JSCell* object)
1152 {
1153     VM& vm = exec->vm();
1154     NativeCallFrameTracer tracer(&vm, exec);
1155
1156     ASSERT(jsDynamicCast<JSObject*>(object));
1157     
1158     if (object->structure(vm)->masqueradesAsUndefined(globalObject))
1159         return vm.smallStrings.undefinedString();
1160     if (object->type() == JSFunctionType)
1161         return vm.smallStrings.functionString();
1162     if (object->inlineTypeFlags() & TypeOfShouldCallGetCallData) {
1163         CallData callData;
1164         if (object->methodTable(vm)->getCallData(object, callData) != CallType::None)
1165             return vm.smallStrings.functionString();
1166     }
1167     
1168     return vm.smallStrings.objectString();
1169 }
1170
1171 int32_t JIT_OPERATION operationTypeOfObjectAsTypeofType(ExecState* exec, JSGlobalObject* globalObject, JSCell* object)
1172 {
1173     VM& vm = exec->vm();
1174     NativeCallFrameTracer tracer(&vm, exec);
1175
1176     ASSERT(jsDynamicCast<JSObject*>(object));
1177     
1178     if (object->structure(vm)->masqueradesAsUndefined(globalObject))
1179         return static_cast<int32_t>(TypeofType::Undefined);
1180     if (object->type() == JSFunctionType)
1181         return static_cast<int32_t>(TypeofType::Function);
1182     if (object->inlineTypeFlags() & TypeOfShouldCallGetCallData) {
1183         CallData callData;
1184         if (object->methodTable(vm)->getCallData(object, callData) != CallType::None)
1185             return static_cast<int32_t>(TypeofType::Function);
1186     }
1187     
1188     return static_cast<int32_t>(TypeofType::Object);
1189 }
1190
1191 char* JIT_OPERATION operationAllocatePropertyStorageWithInitialCapacity(ExecState* exec)
1192 {
1193     VM& vm = exec->vm();
1194     NativeCallFrameTracer tracer(&vm, exec);
1195
1196     return reinterpret_cast<char*>(
1197         Butterfly::createUninitialized(vm, 0, 0, initialOutOfLineCapacity, false, 0));
1198 }
1199
1200 char* JIT_OPERATION operationAllocatePropertyStorage(ExecState* exec, size_t newSize)
1201 {
1202     VM& vm = exec->vm();
1203     NativeCallFrameTracer tracer(&vm, exec);
1204
1205     return reinterpret_cast<char*>(
1206         Butterfly::createUninitialized(vm, 0, 0, newSize, false, 0));
1207 }
1208
1209 char* JIT_OPERATION operationEnsureInt32(ExecState* exec, JSCell* cell)
1210 {
1211     VM& vm = exec->vm();
1212     NativeCallFrameTracer tracer(&vm, exec);
1213     
1214     if (!cell->isObject())
1215         return 0;
1216     
1217     return reinterpret_cast<char*>(asObject(cell)->ensureInt32(vm).data());
1218 }
1219
1220 char* JIT_OPERATION operationEnsureDouble(ExecState* exec, JSCell* cell)
1221 {
1222     VM& vm = exec->vm();
1223     NativeCallFrameTracer tracer(&vm, exec);
1224     
1225     if (!cell->isObject())
1226         return 0;
1227     
1228     return reinterpret_cast<char*>(asObject(cell)->ensureDouble(vm).data());
1229 }
1230
1231 char* JIT_OPERATION operationEnsureContiguous(ExecState* exec, JSCell* cell)
1232 {
1233     VM& vm = exec->vm();
1234     NativeCallFrameTracer tracer(&vm, exec);
1235     
1236     if (!cell->isObject())
1237         return 0;
1238     
1239     return reinterpret_cast<char*>(asObject(cell)->ensureContiguous(vm).data());
1240 }
1241
1242 char* JIT_OPERATION operationEnsureArrayStorage(ExecState* exec, JSCell* cell)
1243 {
1244     VM& vm = exec->vm();
1245     NativeCallFrameTracer tracer(&vm, exec);
1246     
1247     if (!cell->isObject())
1248         return 0;
1249
1250     return reinterpret_cast<char*>(asObject(cell)->ensureArrayStorage(vm));
1251 }
1252
1253 StringImpl* JIT_OPERATION operationResolveRope(ExecState* exec, JSString* string)
1254 {
1255     VM& vm = exec->vm();
1256     NativeCallFrameTracer tracer(&vm, exec);
1257
1258     return string->value(exec).impl();
1259 }
1260
1261 JSString* JIT_OPERATION operationSingleCharacterString(ExecState* exec, int32_t character)
1262 {
1263     VM& vm = exec->vm();
1264     NativeCallFrameTracer tracer(&vm, exec);
1265     
1266     return jsSingleCharacterString(exec, static_cast<UChar>(character));
1267 }
1268
1269 JSCell* JIT_OPERATION operationNewStringObject(ExecState* exec, JSString* string, Structure* structure)
1270 {
1271     VM& vm = exec->vm();
1272     NativeCallFrameTracer tracer(&vm, exec);
1273     
1274     return StringObject::create(vm, structure, string);
1275 }
1276
1277 JSCell* JIT_OPERATION operationToStringOnCell(ExecState* exec, JSCell* cell)
1278 {
1279     VM& vm = exec->vm();
1280     NativeCallFrameTracer tracer(&vm, exec);
1281     
1282     return JSValue(cell).toString(exec);
1283 }
1284
1285 JSCell* JIT_OPERATION operationToString(ExecState* exec, EncodedJSValue value)
1286 {
1287     VM& vm = exec->vm();
1288     NativeCallFrameTracer tracer(&vm, exec);
1289
1290     return JSValue::decode(value).toString(exec);
1291 }
1292
1293 JSCell* JIT_OPERATION operationCallStringConstructorOnCell(ExecState* exec, JSCell* cell)
1294 {
1295     VM& vm = exec->vm();
1296     NativeCallFrameTracer tracer(&vm, exec);
1297
1298     return stringConstructor(exec, cell);
1299 }
1300
1301 JSCell* JIT_OPERATION operationCallStringConstructor(ExecState* exec, EncodedJSValue value)
1302 {
1303     VM& vm = exec->vm();
1304     NativeCallFrameTracer tracer(&vm, exec);
1305
1306     return stringConstructor(exec, JSValue::decode(value));
1307 }
1308
1309 JSCell* JIT_OPERATION operationMakeRope2(ExecState* exec, JSString* left, JSString* right)
1310 {
1311     VM& vm = exec->vm();
1312     NativeCallFrameTracer tracer(&vm, exec);
1313
1314     if (sumOverflows<int32_t>(left->length(), right->length())) {
1315         throwOutOfMemoryError(exec);
1316         return nullptr;
1317     }
1318
1319     return JSRopeString::create(vm, left, right);
1320 }
1321
1322 JSCell* JIT_OPERATION operationMakeRope3(ExecState* exec, JSString* a, JSString* b, JSString* c)
1323 {
1324     VM& vm = exec->vm();
1325     NativeCallFrameTracer tracer(&vm, exec);
1326
1327     if (sumOverflows<int32_t>(a->length(), b->length(), c->length())) {
1328         throwOutOfMemoryError(exec);
1329         return nullptr;
1330     }
1331
1332     return JSRopeString::create(vm, a, b, c);
1333 }
1334
1335 JSCell* JIT_OPERATION operationStrCat2(ExecState* exec, EncodedJSValue a, EncodedJSValue b)
1336 {
1337     VM& vm = exec->vm();
1338     NativeCallFrameTracer tracer(&vm, exec);
1339
1340     JSString* str1 = JSValue::decode(a).toString(exec);
1341     ASSERT(!vm.exception()); // Impossible, since we must have been given primitives.
1342     JSString* str2 = JSValue::decode(b).toString(exec);
1343     ASSERT(!vm.exception());
1344
1345     if (sumOverflows<int32_t>(str1->length(), str2->length())) {
1346         throwOutOfMemoryError(exec);
1347         return nullptr;
1348     }
1349
1350     return JSRopeString::create(vm, str1, str2);
1351 }
1352     
1353 JSCell* JIT_OPERATION operationStrCat3(ExecState* exec, EncodedJSValue a, EncodedJSValue b, EncodedJSValue c)
1354 {
1355     VM& vm = exec->vm();
1356     NativeCallFrameTracer tracer(&vm, exec);
1357
1358     JSString* str1 = JSValue::decode(a).toString(exec);
1359     ASSERT(!vm.exception()); // Impossible, since we must have been given primitives.
1360     JSString* str2 = JSValue::decode(b).toString(exec);
1361     ASSERT(!vm.exception());
1362     JSString* str3 = JSValue::decode(c).toString(exec);
1363     ASSERT(!vm.exception());
1364
1365     if (sumOverflows<int32_t>(str1->length(), str2->length(), str3->length())) {
1366         throwOutOfMemoryError(exec);
1367         return nullptr;
1368     }
1369
1370     return JSRopeString::create(vm, str1, str2, str3);
1371 }
1372
1373 char* JIT_OPERATION operationFindSwitchImmTargetForDouble(
1374     ExecState* exec, EncodedJSValue encodedValue, size_t tableIndex)
1375 {
1376     VM& vm = exec->vm();
1377     NativeCallFrameTracer tracer(&vm, exec);
1378
1379     CodeBlock* codeBlock = exec->codeBlock();
1380     SimpleJumpTable& table = codeBlock->switchJumpTable(tableIndex);
1381     JSValue value = JSValue::decode(encodedValue);
1382     ASSERT(value.isDouble());
1383     double asDouble = value.asDouble();
1384     int32_t asInt32 = static_cast<int32_t>(asDouble);
1385     if (asDouble == asInt32)
1386         return static_cast<char*>(table.ctiForValue(asInt32).executableAddress());
1387     return static_cast<char*>(table.ctiDefault.executableAddress());
1388 }
1389
1390 char* JIT_OPERATION operationSwitchString(ExecState* exec, size_t tableIndex, JSString* string)
1391 {
1392     VM& vm = exec->vm();
1393     NativeCallFrameTracer tracer(&vm, exec);
1394
1395     return static_cast<char*>(exec->codeBlock()->stringSwitchJumpTable(tableIndex).ctiForValue(string->value(exec).impl()).executableAddress());
1396 }
1397
1398 int32_t JIT_OPERATION operationSwitchStringAndGetBranchOffset(ExecState* exec, size_t tableIndex, JSString* string)
1399 {
1400     VM& vm = exec->vm();
1401     NativeCallFrameTracer tracer(&vm, exec);
1402
1403     return exec->codeBlock()->stringSwitchJumpTable(tableIndex).offsetForValue(string->value(exec).impl(), std::numeric_limits<int32_t>::min());
1404 }
1405
1406 uintptr_t JIT_OPERATION operationCompareStringImplLess(StringImpl* a, StringImpl* b)
1407 {
1408     return codePointCompare(a, b) < 0;
1409 }
1410
1411 uintptr_t JIT_OPERATION operationCompareStringImplLessEq(StringImpl* a, StringImpl* b)
1412 {
1413     return codePointCompare(a, b) <= 0;
1414 }
1415
1416 uintptr_t JIT_OPERATION operationCompareStringImplGreater(StringImpl* a, StringImpl* b)
1417 {
1418     return codePointCompare(a, b) > 0;
1419 }
1420
1421 uintptr_t JIT_OPERATION operationCompareStringImplGreaterEq(StringImpl* a, StringImpl* b)
1422 {
1423     return codePointCompare(a, b) >= 0;
1424 }
1425
1426 uintptr_t JIT_OPERATION operationCompareStringLess(ExecState* exec, JSString* a, JSString* b)
1427 {
1428     VM& vm = exec->vm();
1429     NativeCallFrameTracer tracer(&vm, exec);
1430
1431     return codePointCompareLessThan(asString(a)->value(exec), asString(b)->value(exec));
1432 }
1433
1434 uintptr_t JIT_OPERATION operationCompareStringLessEq(ExecState* exec, JSString* a, JSString* b)
1435 {
1436     VM& vm = exec->vm();
1437     NativeCallFrameTracer tracer(&vm, exec);
1438
1439     return !codePointCompareLessThan(asString(b)->value(exec), asString(a)->value(exec));
1440 }
1441
1442 uintptr_t JIT_OPERATION operationCompareStringGreater(ExecState* exec, JSString* a, JSString* b)
1443 {
1444     VM& vm = exec->vm();
1445     NativeCallFrameTracer tracer(&vm, exec);
1446
1447     return codePointCompareLessThan(asString(b)->value(exec), asString(a)->value(exec));
1448 }
1449
1450 uintptr_t JIT_OPERATION operationCompareStringGreaterEq(ExecState* exec, JSString* a, JSString* b)
1451 {
1452     VM& vm = exec->vm();
1453     NativeCallFrameTracer tracer(&vm, exec);
1454
1455     return !codePointCompareLessThan(asString(a)->value(exec), asString(b)->value(exec));
1456 }
1457
1458 void JIT_OPERATION operationNotifyWrite(ExecState* exec, WatchpointSet* set)
1459 {
1460     VM& vm = exec->vm();
1461     NativeCallFrameTracer tracer(&vm, exec);
1462
1463     set->touch("Executed NotifyWrite");
1464 }
1465
1466 void JIT_OPERATION operationThrowStackOverflowForVarargs(ExecState* exec)
1467 {
1468     VM& vm = exec->vm();
1469     NativeCallFrameTracer tracer(&vm, exec);
1470     throwStackOverflowError(exec);
1471 }
1472
1473 int32_t JIT_OPERATION operationSizeOfVarargs(ExecState* exec, EncodedJSValue encodedArguments, int32_t firstVarArgOffset)
1474 {
1475     VM& vm = exec->vm();
1476     NativeCallFrameTracer tracer(&vm, exec);
1477     JSValue arguments = JSValue::decode(encodedArguments);
1478     
1479     return sizeOfVarargs(exec, arguments, firstVarArgOffset);
1480 }
1481
1482 void JIT_OPERATION operationLoadVarargs(ExecState* exec, int32_t firstElementDest, EncodedJSValue encodedArguments, int32_t offset, int32_t length, int32_t mandatoryMinimum)
1483 {
1484     VM& vm = exec->vm();
1485     NativeCallFrameTracer tracer(&vm, exec);
1486     JSValue arguments = JSValue::decode(encodedArguments);
1487     
1488     loadVarargs(exec, VirtualRegister(firstElementDest), arguments, offset, length);
1489     
1490     for (int32_t i = length; i < mandatoryMinimum; ++i)
1491         exec->r(firstElementDest + i) = jsUndefined();
1492 }
1493
1494 double JIT_OPERATION operationFModOnInts(int32_t a, int32_t b)
1495 {
1496     return fmod(a, b);
1497 }
1498
1499 #if USE(JSVALUE32_64)
1500 double JIT_OPERATION operationRandom(JSGlobalObject* globalObject)
1501 {
1502     return globalObject->weakRandomNumber();
1503 }
1504 #endif
1505
1506 JSCell* JIT_OPERATION operationStringFromCharCode(ExecState* exec, int32_t op1)
1507 {
1508     VM* vm = &exec->vm();
1509     NativeCallFrameTracer tracer(vm, exec);
1510     return JSC::stringFromCharCode(exec, op1);
1511 }
1512
1513 EncodedJSValue JIT_OPERATION operationStringFromCharCodeUntyped(ExecState* exec, EncodedJSValue encodedValue)
1514 {
1515     VM* vm = &exec->vm();
1516     NativeCallFrameTracer tracer(vm, exec);
1517     JSValue charValue = JSValue::decode(encodedValue);
1518     int32_t chInt = charValue.toUInt32(exec);
1519     return JSValue::encode(JSC::stringFromCharCode(exec, chInt));
1520 }
1521
1522 int64_t JIT_OPERATION operationConvertBoxedDoubleToInt52(EncodedJSValue encodedValue)
1523 {
1524     JSValue value = JSValue::decode(encodedValue);
1525     if (!value.isDouble())
1526         return JSValue::notInt52;
1527     return tryConvertToInt52(value.asDouble());
1528 }
1529
1530 int64_t JIT_OPERATION operationConvertDoubleToInt52(double value)
1531 {
1532     return tryConvertToInt52(value);
1533 }
1534
1535 size_t JIT_OPERATION operationDefaultHasInstance(ExecState* exec, JSCell* value, JSCell* proto) // Returns jsBoolean(True|False) on 64-bit.
1536 {
1537     VM* vm = &exec->vm();
1538     NativeCallFrameTracer tracer(vm, exec);
1539     if (JSObject::defaultHasInstance(exec, value, proto))
1540         return 1;
1541     return 0;
1542 }
1543
1544 char* JIT_OPERATION operationNewRawObject(ExecState* exec, Structure* structure, int32_t length)
1545 {
1546     VM& vm = exec->vm();
1547     NativeCallFrameTracer tracer(&vm, exec);
1548
1549     Butterfly* butterfly;
1550     if (structure->outOfLineCapacity() || hasIndexedProperties(structure->indexingType())) {
1551         IndexingHeader header;
1552         header.setVectorLength(length);
1553         header.setPublicLength(0);
1554         
1555         butterfly = Butterfly::create(
1556             vm, nullptr, 0, structure->outOfLineCapacity(),
1557             hasIndexedProperties(structure->indexingType()), header,
1558             length * sizeof(EncodedJSValue));
1559     } else
1560         butterfly = nullptr;
1561
1562     JSObject* result = JSObject::createRawObject(exec, structure, butterfly);
1563     result->butterfly(); // Ensure that the butterfly is in to-space.
1564     return bitwise_cast<char*>(result);
1565 }
1566
1567 JSCell* JIT_OPERATION operationNewObjectWithButterfly(ExecState* exec, Structure* structure)
1568 {
1569     VM& vm = exec->vm();
1570     NativeCallFrameTracer tracer(&vm, exec);
1571     
1572     Butterfly* butterfly = Butterfly::create(
1573         vm, nullptr, 0, structure->outOfLineCapacity(), false, IndexingHeader(), 0);
1574     
1575     JSObject* result = JSObject::createRawObject(exec, structure, butterfly);
1576     result->butterfly(); // Ensure that the butterfly is in to-space.
1577     return result;
1578 }
1579
1580 JSCell* JIT_OPERATION operationNewObjectWithButterflyWithIndexingHeaderAndVectorLength(ExecState* exec, Structure* structure, unsigned length)
1581 {
1582     VM& vm = exec->vm();
1583     NativeCallFrameTracer tracer(&vm, exec);
1584
1585     IndexingHeader header;
1586     header.setVectorLength(length);
1587     header.setPublicLength(0);
1588     Butterfly* butterfly = Butterfly::create(
1589         vm, nullptr, 0, structure->outOfLineCapacity(), true, header,
1590         sizeof(EncodedJSValue) * length);
1591
1592     // Paradoxically this may allocate a JSArray. That's totally cool.
1593     JSObject* result = JSObject::createRawObject(exec, structure, butterfly);
1594     result->butterfly(); // Ensure that the butterfly is in to-space.
1595     return result;
1596 }
1597
1598 void JIT_OPERATION operationProcessTypeProfilerLogDFG(ExecState* exec) 
1599 {
1600     exec->vm().typeProfilerLog()->processLogEntries(ASCIILiteral("Log Full, called from inside DFG."));
1601 }
1602
1603 void JIT_OPERATION debugOperationPrintSpeculationFailure(ExecState* exec, void* debugInfoRaw, void* scratch)
1604 {
1605     VM* vm = &exec->vm();
1606     NativeCallFrameTracer tracer(vm, exec);
1607     
1608     SpeculationFailureDebugInfo* debugInfo = static_cast<SpeculationFailureDebugInfo*>(debugInfoRaw);
1609     CodeBlock* codeBlock = debugInfo->codeBlock;
1610     CodeBlock* alternative = codeBlock->alternative();
1611     dataLog("Speculation failure in ", *codeBlock);
1612     dataLog(" @ exit #", vm->osrExitIndex, " (bc#", debugInfo->bytecodeOffset, ", ", exitKindToString(debugInfo->kind), ") with ");
1613     if (alternative) {
1614         dataLog(
1615             "executeCounter = ", alternative->jitExecuteCounter(),
1616             ", reoptimizationRetryCounter = ", alternative->reoptimizationRetryCounter(),
1617             ", optimizationDelayCounter = ", alternative->optimizationDelayCounter());
1618     } else
1619         dataLog("no alternative code block (i.e. we've been jettisoned)");
1620     dataLog(", osrExitCounter = ", codeBlock->osrExitCounter(), "\n");
1621     dataLog("    GPRs at time of exit:");
1622     char* scratchPointer = static_cast<char*>(scratch);
1623     for (unsigned i = 0; i < GPRInfo::numberOfRegisters; ++i) {
1624         GPRReg gpr = GPRInfo::toRegister(i);
1625         dataLog(" ", GPRInfo::debugName(gpr), ":", RawPointer(*reinterpret_cast_ptr<void**>(scratchPointer)));
1626         scratchPointer += sizeof(EncodedJSValue);
1627     }
1628     dataLog("\n");
1629     dataLog("    FPRs at time of exit:");
1630     for (unsigned i = 0; i < FPRInfo::numberOfRegisters; ++i) {
1631         FPRReg fpr = FPRInfo::toRegister(i);
1632         dataLog(" ", FPRInfo::debugName(fpr), ":");
1633         uint64_t bits = *reinterpret_cast_ptr<uint64_t*>(scratchPointer);
1634         double value = *reinterpret_cast_ptr<double*>(scratchPointer);
1635         dataLogF("%llx:%lf", static_cast<long long>(bits), value);
1636         scratchPointer += sizeof(EncodedJSValue);
1637     }
1638     dataLog("\n");
1639 }
1640
1641 JSCell* JIT_OPERATION operationResolveScope(ExecState* exec, JSScope* scope, UniquedStringImpl* impl)
1642 {
1643     VM& vm = exec->vm();
1644     NativeCallFrameTracer tracer(&vm, exec);
1645
1646     JSObject* resolvedScope = JSScope::resolve(exec, scope, Identifier::fromUid(exec, impl));
1647     return resolvedScope;
1648 }
1649
1650 EncodedJSValue JIT_OPERATION operationGetDynamicVar(ExecState* exec, JSObject* scope, UniquedStringImpl* impl, unsigned getPutInfoBits)
1651 {
1652     VM& vm = exec->vm();
1653     NativeCallFrameTracer tracer(&vm, exec);
1654
1655     const Identifier& ident = Identifier::fromUid(exec, impl);
1656     GetPutInfo getPutInfo(getPutInfoBits);
1657
1658     PropertySlot slot(scope, PropertySlot::InternalMethodType::Get);
1659     if (!scope->getPropertySlot(exec, ident, slot)) {
1660         if (getPutInfo.resolveMode() == ThrowIfNotFound)
1661             vm.throwException(exec, createUndefinedVariableError(exec, ident));
1662         return JSValue::encode(jsUndefined());
1663     }
1664
1665     if (scope->isGlobalLexicalEnvironment()) {
1666         // When we can't statically prove we need a TDZ check, we must perform the check on the slow path.
1667         JSValue result = slot.getValue(exec, ident);
1668         if (result == jsTDZValue()) {
1669             exec->vm().throwException(exec, createTDZError(exec));
1670             return JSValue::encode(jsUndefined());
1671         }
1672         return JSValue::encode(result);
1673     }
1674
1675     return JSValue::encode(slot.getValue(exec, ident));
1676 }
1677
1678 void JIT_OPERATION operationPutDynamicVar(ExecState* exec, JSObject* scope, EncodedJSValue value, UniquedStringImpl* impl, unsigned getPutInfoBits)
1679 {
1680     VM& vm = exec->vm();
1681     NativeCallFrameTracer tracer(&vm, exec);
1682
1683     const Identifier& ident = Identifier::fromUid(exec, impl);
1684     GetPutInfo getPutInfo(getPutInfoBits);
1685     bool hasProperty = scope->hasProperty(exec, ident);
1686     if (hasProperty
1687         && scope->isGlobalLexicalEnvironment()
1688         && !isInitialization(getPutInfo.initializationMode())) {
1689         // When we can't statically prove we need a TDZ check, we must perform the check on the slow path.
1690         PropertySlot slot(scope, PropertySlot::InternalMethodType::Get);
1691         JSGlobalLexicalEnvironment::getOwnPropertySlot(scope, exec, ident, slot);
1692         if (slot.getValue(exec, ident) == jsTDZValue()) {
1693             exec->vm().throwException(exec, createTDZError(exec));
1694             return;
1695         }
1696     }
1697
1698     if (getPutInfo.resolveMode() == ThrowIfNotFound && !hasProperty) {
1699         exec->vm().throwException(exec, createUndefinedVariableError(exec, ident));
1700         return;
1701     }
1702
1703     CodeOrigin origin = exec->codeOrigin();
1704     bool strictMode;
1705     if (origin.inlineCallFrame)
1706         strictMode = origin.inlineCallFrame->baselineCodeBlock->isStrictMode();
1707     else
1708         strictMode = exec->codeBlock()->isStrictMode();
1709     PutPropertySlot slot(scope, strictMode, PutPropertySlot::UnknownContext, isInitialization(getPutInfo.initializationMode()));
1710     scope->methodTable()->put(scope, exec, ident, JSValue::decode(value), slot);
1711 }
1712
1713 extern "C" void JIT_OPERATION triggerReoptimizationNow(CodeBlock* codeBlock, OSRExitBase* exit)
1714 {
1715     // It's sort of preferable that we don't GC while in here. Anyways, doing so wouldn't
1716     // really be profitable.
1717     DeferGCForAWhile deferGC(codeBlock->vm()->heap);
1718     
1719     if (Options::verboseOSR())
1720         dataLog(*codeBlock, ": Entered reoptimize\n");
1721     // We must be called with the baseline code block.
1722     ASSERT(JITCode::isBaselineCode(codeBlock->jitType()));
1723
1724     // If I am my own replacement, then reoptimization has already been triggered.
1725     // This can happen in recursive functions.
1726     if (codeBlock->replacement() == codeBlock) {
1727         if (Options::verboseOSR())
1728             dataLog(*codeBlock, ": Not reoptimizing because we've already been jettisoned.\n");
1729         return;
1730     }
1731     
1732     // Otherwise, the replacement must be optimized code. Use this as an opportunity
1733     // to check our logic.
1734     ASSERT(codeBlock->hasOptimizedReplacement());
1735     CodeBlock* optimizedCodeBlock = codeBlock->replacement();
1736     ASSERT(JITCode::isOptimizingJIT(optimizedCodeBlock->jitType()));
1737     
1738     bool didTryToEnterIntoInlinedLoops = false;
1739     for (InlineCallFrame* inlineCallFrame = exit->m_codeOrigin.inlineCallFrame; inlineCallFrame; inlineCallFrame = inlineCallFrame->directCaller.inlineCallFrame) {
1740         if (inlineCallFrame->baselineCodeBlock->ownerScriptExecutable()->didTryToEnterInLoop()) {
1741             didTryToEnterIntoInlinedLoops = true;
1742             break;
1743         }
1744     }
1745
1746     // In order to trigger reoptimization, one of two things must have happened:
1747     // 1) We exited more than some number of times.
1748     // 2) We exited and got stuck in a loop, and now we're exiting again.
1749     bool didExitABunch = optimizedCodeBlock->shouldReoptimizeNow();
1750     bool didGetStuckInLoop =
1751         (codeBlock->checkIfOptimizationThresholdReached() || didTryToEnterIntoInlinedLoops)
1752         && optimizedCodeBlock->shouldReoptimizeFromLoopNow();
1753     
1754     if (!didExitABunch && !didGetStuckInLoop) {
1755         if (Options::verboseOSR())
1756             dataLog(*codeBlock, ": Not reoptimizing ", *optimizedCodeBlock, " because it either didn't exit enough or didn't loop enough after exit.\n");
1757         codeBlock->optimizeAfterLongWarmUp();
1758         return;
1759     }
1760
1761     optimizedCodeBlock->jettison(Profiler::JettisonDueToOSRExit, CountReoptimization);
1762 }
1763
1764 #if ENABLE(FTL_JIT)
1765 static bool shouldTriggerFTLCompile(CodeBlock* codeBlock, JITCode* jitCode)
1766 {
1767     if (codeBlock->baselineVersion()->m_didFailFTLCompilation) {
1768         CODEBLOCK_LOG_EVENT(codeBlock, "abortFTLCompile", ());
1769         if (Options::verboseOSR())
1770             dataLog("Deferring FTL-optimization of ", *codeBlock, " indefinitely because there was an FTL failure.\n");
1771         jitCode->dontOptimizeAnytimeSoon(codeBlock);
1772         return false;
1773     }
1774
1775     if (!codeBlock->hasOptimizedReplacement()
1776         && !jitCode->checkIfOptimizationThresholdReached(codeBlock)) {
1777         CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("counter = ", jitCode->tierUpCounter));
1778         if (Options::verboseOSR())
1779             dataLog("Choosing not to FTL-optimize ", *codeBlock, " yet.\n");
1780         return false;
1781     }
1782     return true;
1783 }
1784
1785 static void triggerFTLReplacementCompile(VM* vm, CodeBlock* codeBlock, JITCode* jitCode)
1786 {
1787     Worklist::State worklistState;
1788     if (Worklist* worklist = existingGlobalFTLWorklistOrNull()) {
1789         worklistState = worklist->completeAllReadyPlansForVM(
1790             *vm, CompilationKey(codeBlock->baselineVersion(), FTLMode));
1791     } else
1792         worklistState = Worklist::NotKnown;
1793     
1794     if (worklistState == Worklist::Compiling) {
1795         CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("still compiling"));
1796         jitCode->setOptimizationThresholdBasedOnCompilationResult(
1797             codeBlock, CompilationDeferred);
1798         return;
1799     }
1800     
1801     if (codeBlock->hasOptimizedReplacement()) {
1802         CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("has replacement"));
1803         // That's great, we've compiled the code - next time we call this function,
1804         // we'll enter that replacement.
1805         jitCode->optimizeSoon(codeBlock);
1806         return;
1807     }
1808     
1809     if (worklistState == Worklist::Compiled) {
1810         CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("compiled and failed"));
1811         // This means that we finished compiling, but failed somehow; in that case the
1812         // thresholds will be set appropriately.
1813         if (Options::verboseOSR())
1814             dataLog("Code block ", *codeBlock, " was compiled but it doesn't have an optimized replacement.\n");
1815         return;
1816     }
1817
1818     CODEBLOCK_LOG_EVENT(codeBlock, "triggerFTLReplacement", ());
1819     // We need to compile the code.
1820     compile(
1821         *vm, codeBlock->newReplacement(), codeBlock, FTLMode, UINT_MAX,
1822         Operands<JSValue>(), ToFTLDeferredCompilationCallback::create());
1823
1824     // If we reached here, the counter has not be reset. Do that now.
1825     jitCode->setOptimizationThresholdBasedOnCompilationResult(
1826         codeBlock, CompilationDeferred);
1827 }
1828
1829 void JIT_OPERATION triggerTierUpNow(ExecState* exec)
1830 {
1831     VM* vm = &exec->vm();
1832     NativeCallFrameTracer tracer(vm, exec);
1833     DeferGC deferGC(vm->heap);
1834     CodeBlock* codeBlock = exec->codeBlock();
1835     
1836     if (codeBlock->jitType() != JITCode::DFGJIT) {
1837         dataLog("Unexpected code block in DFG->FTL tier-up: ", *codeBlock, "\n");
1838         RELEASE_ASSERT_NOT_REACHED();
1839     }
1840     
1841     JITCode* jitCode = codeBlock->jitCode()->dfg();
1842     
1843     if (Options::verboseOSR()) {
1844         dataLog(
1845             *codeBlock, ": Entered triggerTierUpNow with executeCounter = ",
1846             jitCode->tierUpCounter, "\n");
1847     }
1848
1849     if (shouldTriggerFTLCompile(codeBlock, jitCode))
1850         triggerFTLReplacementCompile(vm, codeBlock, jitCode);
1851
1852     if (codeBlock->hasOptimizedReplacement()) {
1853         if (jitCode->tierUpEntryTriggers.isEmpty()) {
1854             CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("replacement in place, delaying indefinitely"));
1855             // There is nothing more we can do, the only way this will be entered
1856             // is through the function entry point.
1857             jitCode->dontOptimizeAnytimeSoon(codeBlock);
1858             return;
1859         }
1860         if (jitCode->osrEntryBlock() && jitCode->tierUpEntryTriggers.size() == 1) {
1861             CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("trigger in place, delaying indefinitely"));
1862             // There is only one outer loop and its trigger must have been set
1863             // when the plan completed.
1864             // Exiting the inner loop is useless, we can ignore the counter and leave
1865             // the trigger do its job.
1866             jitCode->dontOptimizeAnytimeSoon(codeBlock);
1867             return;
1868         }
1869     }
1870 }
1871
1872 static char* tierUpCommon(ExecState* exec, unsigned originBytecodeIndex, unsigned osrEntryBytecodeIndex)
1873 {
1874     VM* vm = &exec->vm();
1875     CodeBlock* codeBlock = exec->codeBlock();
1876
1877     // Resolve any pending plan for OSR Enter on this function.
1878     Worklist::State worklistState;
1879     if (Worklist* worklist = existingGlobalFTLWorklistOrNull()) {
1880         worklistState = worklist->completeAllReadyPlansForVM(
1881             *vm, CompilationKey(codeBlock->baselineVersion(), FTLForOSREntryMode));
1882     } else
1883         worklistState = Worklist::NotKnown;
1884
1885     JITCode* jitCode = codeBlock->jitCode()->dfg();
1886     if (worklistState == Worklist::Compiling) {
1887         CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("still compiling"));
1888         jitCode->setOptimizationThresholdBasedOnCompilationResult(
1889             codeBlock, CompilationDeferred);
1890         return nullptr;
1891     }
1892
1893     if (worklistState == Worklist::Compiled) {
1894         CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("compiled and failed"));
1895         // This means that compilation failed and we already set the thresholds.
1896         if (Options::verboseOSR())
1897             dataLog("Code block ", *codeBlock, " was compiled but it doesn't have an optimized replacement.\n");
1898         return nullptr;
1899     }
1900
1901     // If we can OSR Enter, do it right away.
1902     if (originBytecodeIndex == osrEntryBytecodeIndex) {
1903         unsigned streamIndex = jitCode->bytecodeIndexToStreamIndex.get(originBytecodeIndex);
1904         if (CodeBlock* entryBlock = jitCode->osrEntryBlock()) {
1905             if (void* address = FTL::prepareOSREntry(exec, codeBlock, entryBlock, originBytecodeIndex, streamIndex)) {
1906                 CODEBLOCK_LOG_EVENT(entryBlock, "osrEntry", ("at bc#", originBytecodeIndex));
1907                 return static_cast<char*>(address);
1908             }
1909         }
1910     }
1911
1912     // - If we don't have an FTL code block, then try to compile one.
1913     // - If we do have an FTL code block, then try to enter for a while.
1914     // - If we couldn't enter for a while, then trigger OSR entry.
1915
1916     if (!shouldTriggerFTLCompile(codeBlock, jitCode))
1917         return nullptr;
1918
1919     if (!jitCode->neverExecutedEntry) {
1920         triggerFTLReplacementCompile(vm, codeBlock, jitCode);
1921
1922         if (!codeBlock->hasOptimizedReplacement())
1923             return nullptr;
1924
1925         if (jitCode->osrEntryRetry < Options::ftlOSREntryRetryThreshold()) {
1926             CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("avoiding OSR entry compile"));
1927             jitCode->osrEntryRetry++;
1928             return nullptr;
1929         }
1930     } else
1931         CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("avoiding replacement compile"));
1932
1933     // It's time to try to compile code for OSR entry.
1934     if (CodeBlock* entryBlock = jitCode->osrEntryBlock()) {
1935         if (jitCode->osrEntryRetry < Options::ftlOSREntryRetryThreshold()) {
1936             CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("OSR entry failed, OSR entry threshold not met"));
1937             jitCode->osrEntryRetry++;
1938             jitCode->setOptimizationThresholdBasedOnCompilationResult(
1939                 codeBlock, CompilationDeferred);
1940             return nullptr;
1941         }
1942
1943         FTL::ForOSREntryJITCode* entryCode = entryBlock->jitCode()->ftlForOSREntry();
1944         entryCode->countEntryFailure();
1945         if (entryCode->entryFailureCount() <
1946             Options::ftlOSREntryFailureCountForReoptimization()) {
1947             CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("OSR entry failed"));
1948             jitCode->setOptimizationThresholdBasedOnCompilationResult(
1949                 codeBlock, CompilationDeferred);
1950             return nullptr;
1951         }
1952
1953         // OSR entry failed. Oh no! This implies that we need to retry. We retry
1954         // without exponential backoff and we only do this for the entry code block.
1955         CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("OSR entry failed too many times"));
1956         unsigned osrEntryBytecode = entryBlock->jitCode()->ftlForOSREntry()->bytecodeIndex();
1957         jitCode->clearOSREntryBlock();
1958         jitCode->osrEntryRetry = 0;
1959         jitCode->tierUpEntryTriggers.set(osrEntryBytecode, 0);
1960         jitCode->setOptimizationThresholdBasedOnCompilationResult(
1961             codeBlock, CompilationDeferred);
1962         return nullptr;
1963     }
1964
1965     unsigned streamIndex = jitCode->bytecodeIndexToStreamIndex.get(osrEntryBytecodeIndex);
1966     auto tierUpHierarchyEntry = jitCode->tierUpInLoopHierarchy.find(osrEntryBytecodeIndex);
1967     if (tierUpHierarchyEntry != jitCode->tierUpInLoopHierarchy.end()) {
1968         for (unsigned osrEntryCandidate : tierUpHierarchyEntry->value) {
1969             if (jitCode->tierUpEntrySeen.contains(osrEntryCandidate)) {
1970                 osrEntryBytecodeIndex = osrEntryCandidate;
1971                 streamIndex = jitCode->bytecodeIndexToStreamIndex.get(osrEntryBytecodeIndex);
1972             }
1973         }
1974     }
1975
1976     // We aren't compiling and haven't compiled anything for OSR entry. So, try to compile
1977     // something.
1978     auto triggerIterator = jitCode->tierUpEntryTriggers.find(osrEntryBytecodeIndex);
1979     RELEASE_ASSERT(triggerIterator != jitCode->tierUpEntryTriggers.end());
1980     uint8_t* triggerAddress = &(triggerIterator->value);
1981
1982     Operands<JSValue> mustHandleValues;
1983     jitCode->reconstruct(
1984         exec, codeBlock, CodeOrigin(osrEntryBytecodeIndex), streamIndex, mustHandleValues);
1985     CodeBlock* replacementCodeBlock = codeBlock->newReplacement();
1986
1987     CODEBLOCK_LOG_EVENT(codeBlock, "triggerFTLOSR", ());
1988     CompilationResult forEntryResult = compile(
1989         *vm, replacementCodeBlock, codeBlock, FTLForOSREntryMode, osrEntryBytecodeIndex,
1990         mustHandleValues, ToFTLForOSREntryDeferredCompilationCallback::create(triggerAddress));
1991
1992     if (jitCode->neverExecutedEntry)
1993         triggerFTLReplacementCompile(vm, codeBlock, jitCode);
1994
1995     if (forEntryResult != CompilationSuccessful) {
1996         CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("OSR ecompilation not successful"));
1997         jitCode->setOptimizationThresholdBasedOnCompilationResult(
1998             codeBlock, CompilationDeferred);
1999         return nullptr;
2000     }
2001     
2002     CODEBLOCK_LOG_EVENT(jitCode->osrEntryBlock(), "osrEntry", ("at bc#", originBytecodeIndex));
2003     // It's possible that the for-entry compile already succeeded. In that case OSR
2004     // entry will succeed unless we ran out of stack. It's not clear what we should do.
2005     // We signal to try again after a while if that happens.
2006     void* address = FTL::prepareOSREntry(
2007         exec, codeBlock, jitCode->osrEntryBlock(), originBytecodeIndex, streamIndex);
2008     return static_cast<char*>(address);
2009 }
2010
2011 void JIT_OPERATION triggerTierUpNowInLoop(ExecState* exec, unsigned bytecodeIndex)
2012 {
2013     VM* vm = &exec->vm();
2014     NativeCallFrameTracer tracer(vm, exec);
2015     DeferGC deferGC(vm->heap);
2016     CodeBlock* codeBlock = exec->codeBlock();
2017
2018     if (codeBlock->jitType() != JITCode::DFGJIT) {
2019         dataLog("Unexpected code block in DFG->FTL tier-up: ", *codeBlock, "\n");
2020         RELEASE_ASSERT_NOT_REACHED();
2021     }
2022
2023     JITCode* jitCode = codeBlock->jitCode()->dfg();
2024
2025     if (Options::verboseOSR()) {
2026         dataLog(
2027             *codeBlock, ": Entered triggerTierUpNowInLoop with executeCounter = ",
2028             jitCode->tierUpCounter, "\n");
2029     }
2030
2031     auto tierUpHierarchyEntry = jitCode->tierUpInLoopHierarchy.find(bytecodeIndex);
2032     if (tierUpHierarchyEntry != jitCode->tierUpInLoopHierarchy.end()
2033         && !tierUpHierarchyEntry->value.isEmpty()) {
2034         tierUpCommon(exec, bytecodeIndex, tierUpHierarchyEntry->value.first());
2035     } else if (shouldTriggerFTLCompile(codeBlock, jitCode))
2036         triggerFTLReplacementCompile(vm, codeBlock, jitCode);
2037
2038     // Since we cannot OSR Enter here, the default "optimizeSoon()" is not useful.
2039     if (codeBlock->hasOptimizedReplacement()) {
2040         CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("OSR in loop failed, deferring"));
2041         jitCode->setOptimizationThresholdBasedOnCompilationResult(codeBlock, CompilationDeferred);
2042     }
2043 }
2044
2045 char* JIT_OPERATION triggerOSREntryNow(ExecState* exec, unsigned bytecodeIndex)
2046 {
2047     VM* vm = &exec->vm();
2048     NativeCallFrameTracer tracer(vm, exec);
2049     DeferGC deferGC(vm->heap);
2050     CodeBlock* codeBlock = exec->codeBlock();
2051
2052     if (codeBlock->jitType() != JITCode::DFGJIT) {
2053         dataLog("Unexpected code block in DFG->FTL tier-up: ", *codeBlock, "\n");
2054         RELEASE_ASSERT_NOT_REACHED();
2055     }
2056
2057     JITCode* jitCode = codeBlock->jitCode()->dfg();
2058     jitCode->tierUpEntrySeen.add(bytecodeIndex);
2059
2060     if (Options::verboseOSR()) {
2061         dataLog(
2062             *codeBlock, ": Entered triggerOSREntryNow with executeCounter = ",
2063             jitCode->tierUpCounter, "\n");
2064     }
2065
2066     return tierUpCommon(exec, bytecodeIndex, bytecodeIndex);
2067 }
2068
2069 #endif // ENABLE(FTL_JIT)
2070
2071 } // extern "C"
2072 } } // namespace JSC::DFG
2073
2074 #endif // ENABLE(DFG_JIT)
2075
2076 #endif // ENABLE(JIT)