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