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