afc4cd3cba6475a7520cdc650205d16335ba70dc
[WebKit-https.git] / Source / JavaScriptCore / dfg / DFGOperations.cpp
1 /*
2  * Copyright (C) 2011, 2013-2015 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 "Symbol.h"
56 #include "TypeProfilerLog.h"
57 #include "TypedArrayInlines.h"
58 #include "VM.h"
59 #include <wtf/InlineASM.h>
60
61 #if ENABLE(JIT)
62 #if ENABLE(DFG_JIT)
63
64 namespace JSC { namespace DFG {
65
66 template<bool strict, bool direct>
67 static inline void putByVal(ExecState* exec, JSValue baseValue, uint32_t index, JSValue value)
68 {
69     VM& vm = exec->vm();
70     NativeCallFrameTracer tracer(&vm, exec);
71     ASSERT(isIndex(index));
72     if (direct) {
73         RELEASE_ASSERT(baseValue.isObject());
74         asObject(baseValue)->putDirectIndex(exec, index, value, 0, strict ? PutDirectIndexShouldThrow : PutDirectIndexShouldNotThrow);
75         return;
76     }
77     if (baseValue.isObject()) {
78         JSObject* object = asObject(baseValue);
79         if (object->canSetIndexQuickly(index)) {
80             object->setIndexQuickly(vm, index, value);
81             return;
82         }
83
84         object->methodTable(vm)->putByIndex(object, exec, index, value, strict);
85         return;
86     }
87
88     baseValue.putByIndex(exec, index, value, strict);
89 }
90
91 template<bool strict, bool direct>
92 ALWAYS_INLINE static void JIT_OPERATION operationPutByValInternal(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
93 {
94     VM* vm = &exec->vm();
95     NativeCallFrameTracer tracer(vm, exec);
96
97     JSValue baseValue = JSValue::decode(encodedBase);
98     JSValue property = JSValue::decode(encodedProperty);
99     JSValue value = JSValue::decode(encodedValue);
100
101     if (LIKELY(property.isUInt32())) {
102         // Despite its name, JSValue::isUInt32 will return true only for positive boxed int32_t; all those values are valid array indices.
103         ASSERT(isIndex(property.asUInt32()));
104         putByVal<strict, direct>(exec, baseValue, property.asUInt32(), value);
105         return;
106     }
107
108     if (property.isDouble()) {
109         double propertyAsDouble = property.asDouble();
110         uint32_t propertyAsUInt32 = static_cast<uint32_t>(propertyAsDouble);
111         if (propertyAsDouble == propertyAsUInt32 && isIndex(propertyAsUInt32)) {
112             putByVal<strict, direct>(exec, baseValue, propertyAsUInt32, value);
113             return;
114         }
115     }
116
117     // Don't put to an object if toString throws an exception.
118     auto propertyName = property.toPropertyKey(exec);
119     if (vm->exception())
120         return;
121
122     PutPropertySlot slot(baseValue, strict);
123     if (direct) {
124         RELEASE_ASSERT(baseValue.isObject());
125         if (Optional<uint32_t> index = parseIndex(propertyName))
126             asObject(baseValue)->putDirectIndex(exec, index.value(), value, 0, strict ? PutDirectIndexShouldThrow : PutDirectIndexShouldNotThrow);
127         else
128             asObject(baseValue)->putDirect(*vm, propertyName, value, slot);
129     } else
130         baseValue.put(exec, propertyName, value, slot);
131 }
132
133 template<typename ViewClass>
134 char* newTypedArrayWithSize(ExecState* exec, Structure* structure, int32_t size)
135 {
136     VM& vm = exec->vm();
137     NativeCallFrameTracer tracer(&vm, exec);
138     if (size < 0) {
139         vm.throwException(exec, createRangeError(exec, ASCIILiteral("Requested length is negative")));
140         return 0;
141     }
142     return bitwise_cast<char*>(ViewClass::create(exec, structure, size));
143 }
144
145 extern "C" {
146
147 EncodedJSValue JIT_OPERATION operationToThis(ExecState* exec, EncodedJSValue encodedOp)
148 {
149     VM* vm = &exec->vm();
150     NativeCallFrameTracer tracer(vm, exec);
151
152     return JSValue::encode(JSValue::decode(encodedOp).toThis(exec, NotStrictMode));
153 }
154
155 EncodedJSValue JIT_OPERATION operationToThisStrict(ExecState* exec, EncodedJSValue encodedOp)
156 {
157     VM* vm = &exec->vm();
158     NativeCallFrameTracer tracer(vm, exec);
159
160     return JSValue::encode(JSValue::decode(encodedOp).toThis(exec, StrictMode));
161 }
162
163 JSCell* JIT_OPERATION operationCreateThis(ExecState* exec, JSObject* constructor, int32_t inlineCapacity)
164 {
165     VM& vm = exec->vm();
166     NativeCallFrameTracer tracer(&vm, exec);
167
168 #if !ASSERT_DISABLED
169     ConstructData constructData;
170     ASSERT(jsCast<JSFunction*>(constructor)->methodTable(vm)->getConstructData(jsCast<JSFunction*>(constructor), constructData) == ConstructTypeJS);
171 #endif
172     
173     return constructEmptyObject(exec, jsCast<JSFunction*>(constructor)->rareData(exec, inlineCapacity)->allocationProfile()->structure());
174 }
175
176 EncodedJSValue JIT_OPERATION operationValueAdd(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
177 {
178     VM* vm = &exec->vm();
179     NativeCallFrameTracer tracer(vm, exec);
180     
181     JSValue op1 = JSValue::decode(encodedOp1);
182     JSValue op2 = JSValue::decode(encodedOp2);
183     
184     return JSValue::encode(jsAdd(exec, op1, op2));
185 }
186
187 EncodedJSValue JIT_OPERATION operationValueAddNotNumber(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
188 {
189     VM* vm = &exec->vm();
190     NativeCallFrameTracer tracer(vm, exec);
191     
192     JSValue op1 = JSValue::decode(encodedOp1);
193     JSValue op2 = JSValue::decode(encodedOp2);
194     
195     ASSERT(!op1.isNumber() || !op2.isNumber());
196     
197     if (op1.isString() && !op2.isObject())
198         return JSValue::encode(jsString(exec, asString(op1), op2.toString(exec)));
199
200     return JSValue::encode(jsAddSlowCase(exec, op1, op2));
201 }
202
203 EncodedJSValue JIT_OPERATION operationValueSub(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
204 {
205     VM* vm = &exec->vm();
206     NativeCallFrameTracer tracer(vm, exec);
207     
208     JSValue op1 = JSValue::decode(encodedOp1);
209     JSValue op2 = JSValue::decode(encodedOp2);
210
211     double a = op1.toNumber(exec);
212     double b = op2.toNumber(exec);
213     return JSValue::encode(jsNumber(a - b));
214 }
215
216 static ALWAYS_INLINE EncodedJSValue getByVal(ExecState* exec, JSCell* base, uint32_t index)
217 {
218     VM& vm = exec->vm();
219     NativeCallFrameTracer tracer(&vm, exec);
220     
221     if (base->isObject()) {
222         JSObject* object = asObject(base);
223         if (object->canGetIndexQuickly(index))
224             return JSValue::encode(object->getIndexQuickly(index));
225     }
226
227     if (isJSString(base) && asString(base)->canGetIndex(index))
228         return JSValue::encode(asString(base)->getIndex(exec, index));
229
230     return JSValue::encode(JSValue(base).get(exec, index));
231 }
232
233 EncodedJSValue JIT_OPERATION operationGetByVal(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty)
234 {
235     VM& vm = exec->vm();
236     NativeCallFrameTracer tracer(&vm, exec);
237     
238     JSValue baseValue = JSValue::decode(encodedBase);
239     JSValue property = JSValue::decode(encodedProperty);
240
241     if (LIKELY(baseValue.isCell())) {
242         JSCell* base = baseValue.asCell();
243
244         if (property.isUInt32()) {
245             return getByVal(exec, base, property.asUInt32());
246         } else if (property.isDouble()) {
247             double propertyAsDouble = property.asDouble();
248             uint32_t propertyAsUInt32 = static_cast<uint32_t>(propertyAsDouble);
249             if (propertyAsUInt32 == propertyAsDouble && isIndex(propertyAsUInt32))
250                 return getByVal(exec, base, propertyAsUInt32);
251         } else if (property.isString()) {
252             Structure& structure = *base->structure(vm);
253             if (JSCell::canUseFastGetOwnProperty(structure)) {
254                 if (RefPtr<AtomicStringImpl> existingAtomicString = asString(property)->toExistingAtomicString(exec)) {
255                     if (JSValue result = base->fastGetOwnProperty(vm, structure, existingAtomicString.get()))
256                         return JSValue::encode(result);
257                 }
258             }
259         }
260     }
261
262     baseValue.requireObjectCoercible(exec);
263     if (exec->hadException())
264         return JSValue::encode(jsUndefined());
265     auto propertyName = property.toPropertyKey(exec);
266     if (exec->hadException())
267         return JSValue::encode(jsUndefined());
268     return JSValue::encode(baseValue.get(exec, propertyName));
269 }
270
271 EncodedJSValue JIT_OPERATION operationGetByValCell(ExecState* exec, JSCell* base, EncodedJSValue encodedProperty)
272 {
273     VM& vm = exec->vm();
274     NativeCallFrameTracer tracer(&vm, exec);
275     
276     JSValue property = JSValue::decode(encodedProperty);
277
278     if (property.isUInt32())
279         return getByVal(exec, base, property.asUInt32());
280     if (property.isDouble()) {
281         double propertyAsDouble = property.asDouble();
282         uint32_t propertyAsUInt32 = static_cast<uint32_t>(propertyAsDouble);
283         if (propertyAsUInt32 == propertyAsDouble)
284             return getByVal(exec, base, propertyAsUInt32);
285     } else if (property.isString()) {
286         Structure& structure = *base->structure(vm);
287         if (JSCell::canUseFastGetOwnProperty(structure)) {
288             if (RefPtr<AtomicStringImpl> existingAtomicString = asString(property)->toExistingAtomicString(exec)) {
289                 if (JSValue result = base->fastGetOwnProperty(vm, structure, existingAtomicString.get()))
290                     return JSValue::encode(result);
291             }
292         }
293     }
294
295     auto propertyName = property.toPropertyKey(exec);
296     if (exec->hadException())
297         return JSValue::encode(jsUndefined());
298     return JSValue::encode(JSValue(base).get(exec, propertyName));
299 }
300
301 ALWAYS_INLINE EncodedJSValue getByValCellInt(ExecState* exec, JSCell* base, int32_t index)
302 {
303     VM* vm = &exec->vm();
304     NativeCallFrameTracer tracer(vm, exec);
305     
306     if (index < 0) {
307         // Go the slowest way possible becase negative indices don't use indexed storage.
308         return JSValue::encode(JSValue(base).get(exec, Identifier::from(exec, index)));
309     }
310
311     // Use this since we know that the value is out of bounds.
312     return JSValue::encode(JSValue(base).get(exec, index));
313 }
314
315 EncodedJSValue JIT_OPERATION operationGetByValArrayInt(ExecState* exec, JSArray* base, int32_t index)
316 {
317     return getByValCellInt(exec, base, index);
318 }
319
320 EncodedJSValue JIT_OPERATION operationGetByValStringInt(ExecState* exec, JSString* base, int32_t index)
321 {
322     return getByValCellInt(exec, base, index);
323 }
324
325 void JIT_OPERATION operationPutByValStrict(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
326 {
327     VM* vm = &exec->vm();
328     NativeCallFrameTracer tracer(vm, exec);
329     
330     operationPutByValInternal<true, false>(exec, encodedBase, encodedProperty, encodedValue);
331 }
332
333 void JIT_OPERATION operationPutByValNonStrict(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
334 {
335     VM* vm = &exec->vm();
336     NativeCallFrameTracer tracer(vm, exec);
337     
338     operationPutByValInternal<false, false>(exec, encodedBase, encodedProperty, encodedValue);
339 }
340
341 void JIT_OPERATION operationPutByValCellStrict(ExecState* exec, JSCell* cell, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
342 {
343     VM* vm = &exec->vm();
344     NativeCallFrameTracer tracer(vm, exec);
345     
346     operationPutByValInternal<true, false>(exec, JSValue::encode(cell), encodedProperty, encodedValue);
347 }
348
349 void JIT_OPERATION operationPutByValCellNonStrict(ExecState* exec, JSCell* cell, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
350 {
351     VM* vm = &exec->vm();
352     NativeCallFrameTracer tracer(vm, exec);
353     
354     operationPutByValInternal<false, false>(exec, JSValue::encode(cell), encodedProperty, encodedValue);
355 }
356
357 void JIT_OPERATION operationPutByValBeyondArrayBoundsStrict(ExecState* exec, JSObject* array, int32_t index, EncodedJSValue encodedValue)
358 {
359     VM& vm = exec->vm();
360     NativeCallFrameTracer tracer(&vm, exec);
361     
362     if (index >= 0) {
363         array->putByIndexInline(exec, index, JSValue::decode(encodedValue), true);
364         return;
365     }
366     
367     PutPropertySlot slot(array, true);
368     array->methodTable()->put(
369         array, exec, Identifier::from(exec, index), JSValue::decode(encodedValue), slot);
370 }
371
372 void JIT_OPERATION operationPutByValBeyondArrayBoundsNonStrict(ExecState* exec, JSObject* array, int32_t index, EncodedJSValue encodedValue)
373 {
374     VM* vm = &exec->vm();
375     NativeCallFrameTracer tracer(vm, exec);
376     
377     if (index >= 0) {
378         array->putByIndexInline(exec, index, JSValue::decode(encodedValue), false);
379         return;
380     }
381     
382     PutPropertySlot slot(array, false);
383     array->methodTable()->put(
384         array, exec, Identifier::from(exec, index), JSValue::decode(encodedValue), slot);
385 }
386
387 void JIT_OPERATION operationPutDoubleByValBeyondArrayBoundsStrict(ExecState* exec, JSObject* array, int32_t index, double value)
388 {
389     VM* vm = &exec->vm();
390     NativeCallFrameTracer tracer(vm, exec);
391     
392     JSValue jsValue = JSValue(JSValue::EncodeAsDouble, value);
393     
394     if (index >= 0) {
395         array->putByIndexInline(exec, index, jsValue, true);
396         return;
397     }
398     
399     PutPropertySlot slot(array, true);
400     array->methodTable()->put(
401         array, exec, Identifier::from(exec, index), jsValue, slot);
402 }
403
404 void JIT_OPERATION operationPutDoubleByValBeyondArrayBoundsNonStrict(ExecState* exec, JSObject* array, int32_t index, double value)
405 {
406     VM* vm = &exec->vm();
407     NativeCallFrameTracer tracer(vm, exec);
408     
409     JSValue jsValue = JSValue(JSValue::EncodeAsDouble, value);
410     
411     if (index >= 0) {
412         array->putByIndexInline(exec, index, jsValue, false);
413         return;
414     }
415     
416     PutPropertySlot slot(array, false);
417     array->methodTable()->put(
418         array, exec, Identifier::from(exec, index), jsValue, slot);
419 }
420
421 void JIT_OPERATION operationPutByValDirectStrict(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
422 {
423     VM* vm = &exec->vm();
424     NativeCallFrameTracer tracer(vm, exec);
425     
426     operationPutByValInternal<true, true>(exec, encodedBase, encodedProperty, encodedValue);
427 }
428
429 void JIT_OPERATION operationPutByValDirectNonStrict(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
430 {
431     VM* vm = &exec->vm();
432     NativeCallFrameTracer tracer(vm, exec);
433     
434     operationPutByValInternal<false, true>(exec, encodedBase, encodedProperty, encodedValue);
435 }
436
437 void JIT_OPERATION operationPutByValDirectCellStrict(ExecState* exec, JSCell* cell, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
438 {
439     VM* vm = &exec->vm();
440     NativeCallFrameTracer tracer(vm, exec);
441     
442     operationPutByValInternal<true, true>(exec, JSValue::encode(cell), encodedProperty, encodedValue);
443 }
444
445 void JIT_OPERATION operationPutByValDirectCellNonStrict(ExecState* exec, JSCell* cell, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
446 {
447     VM* vm = &exec->vm();
448     NativeCallFrameTracer tracer(vm, exec);
449     
450     operationPutByValInternal<false, true>(exec, JSValue::encode(cell), encodedProperty, encodedValue);
451 }
452
453 void JIT_OPERATION operationPutByValDirectBeyondArrayBoundsStrict(ExecState* exec, JSObject* array, int32_t index, EncodedJSValue encodedValue)
454 {
455     VM* vm = &exec->vm();
456     NativeCallFrameTracer tracer(vm, exec);
457     if (index >= 0) {
458         array->putDirectIndex(exec, index, JSValue::decode(encodedValue), 0, PutDirectIndexShouldThrow);
459         return;
460     }
461     
462     PutPropertySlot slot(array, true);
463     array->putDirect(exec->vm(), Identifier::from(exec, index), JSValue::decode(encodedValue), slot);
464 }
465
466 void JIT_OPERATION operationPutByValDirectBeyondArrayBoundsNonStrict(ExecState* exec, JSObject* array, int32_t index, EncodedJSValue encodedValue)
467 {
468     VM* vm = &exec->vm();
469     NativeCallFrameTracer tracer(vm, exec);
470     
471     if (index >= 0) {
472         array->putDirectIndex(exec, index, JSValue::decode(encodedValue));
473         return;
474     }
475     
476     PutPropertySlot slot(array, false);
477     array->putDirect(exec->vm(), Identifier::from(exec, index), JSValue::decode(encodedValue), slot);
478 }
479
480 EncodedJSValue JIT_OPERATION operationArrayPush(ExecState* exec, EncodedJSValue encodedValue, JSArray* array)
481 {
482     VM* vm = &exec->vm();
483     NativeCallFrameTracer tracer(vm, exec);
484     
485     array->push(exec, JSValue::decode(encodedValue));
486     return JSValue::encode(jsNumber(array->length()));
487 }
488
489 EncodedJSValue JIT_OPERATION operationArrayPushDouble(ExecState* exec, double value, JSArray* array)
490 {
491     VM* vm = &exec->vm();
492     NativeCallFrameTracer tracer(vm, exec);
493     
494     array->push(exec, JSValue(JSValue::EncodeAsDouble, value));
495     return JSValue::encode(jsNumber(array->length()));
496 }
497
498 EncodedJSValue JIT_OPERATION operationArrayPop(ExecState* exec, JSArray* array)
499 {
500     VM* vm = &exec->vm();
501     NativeCallFrameTracer tracer(vm, exec);
502     
503     return JSValue::encode(array->pop(exec));
504 }
505         
506 EncodedJSValue JIT_OPERATION operationArrayPopAndRecoverLength(ExecState* exec, JSArray* array)
507 {
508     VM* vm = &exec->vm();
509     NativeCallFrameTracer tracer(vm, exec);
510     
511     array->butterfly()->setPublicLength(array->butterfly()->publicLength() + 1);
512     
513     return JSValue::encode(array->pop(exec));
514 }
515         
516 EncodedJSValue JIT_OPERATION operationRegExpExec(ExecState* exec, JSCell* base, JSCell* argument)
517 {
518     VM& vm = exec->vm();
519     NativeCallFrameTracer tracer(&vm, exec);
520     
521     if (!base->inherits(RegExpObject::info()))
522         return throwVMTypeError(exec);
523
524     ASSERT(argument->isString() || argument->isObject());
525     JSString* input = argument->isString() ? asString(argument) : asObject(argument)->toString(exec);
526     return JSValue::encode(asRegExpObject(base)->exec(exec, input));
527 }
528         
529 size_t JIT_OPERATION operationRegExpTest(ExecState* exec, JSCell* base, JSCell* argument)
530 {
531     VM& vm = exec->vm();
532     NativeCallFrameTracer tracer(&vm, exec);
533
534     if (!base->inherits(RegExpObject::info())) {
535         throwTypeError(exec);
536         return false;
537     }
538
539     ASSERT(argument->isString() || argument->isObject());
540     JSString* input = argument->isString() ? asString(argument) : asObject(argument)->toString(exec);
541     return asRegExpObject(base)->test(exec, input);
542 }
543
544 size_t JIT_OPERATION operationCompareStrictEqCell(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
545 {
546     VM* vm = &exec->vm();
547     NativeCallFrameTracer tracer(vm, exec);
548     
549     JSValue op1 = JSValue::decode(encodedOp1);
550     JSValue op2 = JSValue::decode(encodedOp2);
551     
552     ASSERT(op1.isCell());
553     ASSERT(op2.isCell());
554     
555     return JSValue::strictEqualSlowCaseInline(exec, op1, op2);
556 }
557
558 size_t JIT_OPERATION operationCompareStrictEq(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
559 {
560     VM* vm = &exec->vm();
561     NativeCallFrameTracer tracer(vm, exec);
562
563     JSValue src1 = JSValue::decode(encodedOp1);
564     JSValue src2 = JSValue::decode(encodedOp2);
565     
566     return JSValue::strictEqual(exec, src1, src2);
567 }
568
569 EncodedJSValue JIT_OPERATION operationToPrimitive(ExecState* exec, EncodedJSValue value)
570 {
571     VM* vm = &exec->vm();
572     NativeCallFrameTracer tracer(vm, exec);
573     
574     return JSValue::encode(JSValue::decode(value).toPrimitive(exec));
575 }
576
577 char* JIT_OPERATION operationNewArray(ExecState* exec, Structure* arrayStructure, void* buffer, size_t size)
578 {
579     VM* vm = &exec->vm();
580     NativeCallFrameTracer tracer(vm, exec);
581     
582     return bitwise_cast<char*>(constructArray(exec, arrayStructure, static_cast<JSValue*>(buffer), size));
583 }
584
585 char* JIT_OPERATION operationNewEmptyArray(ExecState* exec, Structure* arrayStructure)
586 {
587     VM* vm = &exec->vm();
588     NativeCallFrameTracer tracer(vm, exec);
589     
590     return bitwise_cast<char*>(JSArray::create(*vm, arrayStructure));
591 }
592
593 char* JIT_OPERATION operationNewArrayWithSize(ExecState* exec, Structure* arrayStructure, int32_t size)
594 {
595     VM* vm = &exec->vm();
596     NativeCallFrameTracer tracer(vm, exec);
597
598     if (UNLIKELY(size < 0))
599         return bitwise_cast<char*>(exec->vm().throwException(exec, createRangeError(exec, ASCIILiteral("Array size is not a small enough positive integer."))));
600
601     JSArray* result = JSArray::create(*vm, arrayStructure, size);
602     result->butterfly(); // Ensure that the backing store is in to-space.
603     return bitwise_cast<char*>(result);
604 }
605
606 char* JIT_OPERATION operationNewArrayBuffer(ExecState* exec, Structure* arrayStructure, size_t start, size_t size)
607 {
608     VM& vm = exec->vm();
609     NativeCallFrameTracer tracer(&vm, exec);
610     return bitwise_cast<char*>(constructArray(exec, arrayStructure, exec->codeBlock()->constantBuffer(start), size));
611 }
612
613 char* JIT_OPERATION operationNewInt8ArrayWithSize(
614     ExecState* exec, Structure* structure, int32_t length)
615 {
616     return newTypedArrayWithSize<JSInt8Array>(exec, structure, length);
617 }
618
619 char* JIT_OPERATION operationNewInt8ArrayWithOneArgument(
620     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
621 {
622     return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSInt8Array>(exec, structure, encodedValue, 0, Nullopt));
623 }
624
625 char* JIT_OPERATION operationNewInt16ArrayWithSize(
626     ExecState* exec, Structure* structure, int32_t length)
627 {
628     return newTypedArrayWithSize<JSInt16Array>(exec, structure, length);
629 }
630
631 char* JIT_OPERATION operationNewInt16ArrayWithOneArgument(
632     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
633 {
634     return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSInt16Array>(exec, structure, encodedValue, 0, Nullopt));
635 }
636
637 char* JIT_OPERATION operationNewInt32ArrayWithSize(
638     ExecState* exec, Structure* structure, int32_t length)
639 {
640     return newTypedArrayWithSize<JSInt32Array>(exec, structure, length);
641 }
642
643 char* JIT_OPERATION operationNewInt32ArrayWithOneArgument(
644     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
645 {
646     return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSInt32Array>(exec, structure, encodedValue, 0, Nullopt));
647 }
648
649 char* JIT_OPERATION operationNewUint8ArrayWithSize(
650     ExecState* exec, Structure* structure, int32_t length)
651 {
652     return newTypedArrayWithSize<JSUint8Array>(exec, structure, length);
653 }
654
655 char* JIT_OPERATION operationNewUint8ArrayWithOneArgument(
656     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
657 {
658     return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSUint8Array>(exec, structure, encodedValue, 0, Nullopt));
659 }
660
661 char* JIT_OPERATION operationNewUint8ClampedArrayWithSize(
662     ExecState* exec, Structure* structure, int32_t length)
663 {
664     return newTypedArrayWithSize<JSUint8ClampedArray>(exec, structure, length);
665 }
666
667 char* JIT_OPERATION operationNewUint8ClampedArrayWithOneArgument(
668     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
669 {
670     return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSUint8ClampedArray>(exec, structure, encodedValue, 0, Nullopt));
671 }
672
673 char* JIT_OPERATION operationNewUint16ArrayWithSize(
674     ExecState* exec, Structure* structure, int32_t length)
675 {
676     return newTypedArrayWithSize<JSUint16Array>(exec, structure, length);
677 }
678
679 char* JIT_OPERATION operationNewUint16ArrayWithOneArgument(
680     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
681 {
682     return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSUint16Array>(exec, structure, encodedValue, 0, Nullopt));
683 }
684
685 char* JIT_OPERATION operationNewUint32ArrayWithSize(
686     ExecState* exec, Structure* structure, int32_t length)
687 {
688     return newTypedArrayWithSize<JSUint32Array>(exec, structure, length);
689 }
690
691 char* JIT_OPERATION operationNewUint32ArrayWithOneArgument(
692     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
693 {
694     return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSUint32Array>(exec, structure, encodedValue, 0, Nullopt));
695 }
696
697 char* JIT_OPERATION operationNewFloat32ArrayWithSize(
698     ExecState* exec, Structure* structure, int32_t length)
699 {
700     return newTypedArrayWithSize<JSFloat32Array>(exec, structure, length);
701 }
702
703 char* JIT_OPERATION operationNewFloat32ArrayWithOneArgument(
704     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
705 {
706     return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSFloat32Array>(exec, structure, encodedValue, 0, Nullopt));
707 }
708
709 char* JIT_OPERATION operationNewFloat64ArrayWithSize(
710     ExecState* exec, Structure* structure, int32_t length)
711 {
712     return newTypedArrayWithSize<JSFloat64Array>(exec, structure, length);
713 }
714
715 char* JIT_OPERATION operationNewFloat64ArrayWithOneArgument(
716     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
717 {
718     return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSFloat64Array>(exec, structure, encodedValue, 0, Nullopt));
719 }
720
721 JSCell* JIT_OPERATION operationCreateActivationDirect(ExecState* exec, Structure* structure, JSScope* scope, SymbolTable* table, EncodedJSValue initialValueEncoded)
722 {
723     JSValue initialValue = JSValue::decode(initialValueEncoded);
724     ASSERT(initialValue == jsUndefined() || initialValue == jsTDZValue());
725     VM& vm = exec->vm();
726     NativeCallFrameTracer tracer(&vm, exec);
727     return JSLexicalEnvironment::create(vm, structure, scope, table, initialValue);
728 }
729
730 JSCell* JIT_OPERATION operationCreateDirectArguments(ExecState* exec, Structure* structure, int32_t length, int32_t minCapacity)
731 {
732     VM& vm = exec->vm();
733     NativeCallFrameTracer target(&vm, exec);
734     DirectArguments* result = DirectArguments::create(
735         vm, structure, length, std::max(length, minCapacity));
736     // The caller will store to this object without barriers. Most likely, at this point, this is
737     // still a young object and so no barriers are needed. But it's good to be careful anyway,
738     // since the GC should be allowed to do crazy (like pretenuring, for example).
739     vm.heap.writeBarrier(result);
740     return result;
741 }
742
743 JSCell* JIT_OPERATION operationCreateScopedArguments(ExecState* exec, Structure* structure, Register* argumentStart, int32_t length, JSFunction* callee, JSLexicalEnvironment* scope)
744 {
745     VM& vm = exec->vm();
746     NativeCallFrameTracer target(&vm, exec);
747     
748     // We could pass the ScopedArgumentsTable* as an argument. We currently don't because I
749     // didn't feel like changing the max number of arguments for a slow path call from 6 to 7.
750     ScopedArgumentsTable* table = scope->symbolTable()->arguments();
751     
752     return ScopedArguments::createByCopyingFrom(
753         vm, structure, argumentStart, length, callee, table, scope);
754 }
755
756 JSCell* JIT_OPERATION operationCreateClonedArguments(ExecState* exec, Structure* structure, Register* argumentStart, int32_t length, JSFunction* callee)
757 {
758     VM& vm = exec->vm();
759     NativeCallFrameTracer target(&vm, exec);
760     return ClonedArguments::createByCopyingFrom(
761         exec, structure, argumentStart, length, callee);
762 }
763
764 JSCell* JIT_OPERATION operationCreateDirectArgumentsDuringExit(ExecState* exec, InlineCallFrame* inlineCallFrame, JSFunction* callee, int32_t argumentCount)
765 {
766     VM& vm = exec->vm();
767     NativeCallFrameTracer target(&vm, exec);
768     
769     DeferGCForAWhile deferGC(vm.heap);
770     
771     CodeBlock* codeBlock;
772     if (inlineCallFrame)
773         codeBlock = baselineCodeBlockForInlineCallFrame(inlineCallFrame);
774     else
775         codeBlock = exec->codeBlock();
776     
777     unsigned length = argumentCount - 1;
778     unsigned capacity = std::max(length, static_cast<unsigned>(codeBlock->numParameters() - 1));
779     DirectArguments* result = DirectArguments::create(
780         vm, codeBlock->globalObject()->directArgumentsStructure(), length, capacity);
781     
782     result->callee().set(vm, result, callee);
783     
784     Register* arguments =
785         exec->registers() + (inlineCallFrame ? inlineCallFrame->stackOffset : 0) +
786         CallFrame::argumentOffset(0);
787     for (unsigned i = length; i--;)
788         result->setIndexQuickly(vm, i, arguments[i].jsValue());
789     
790     return result;
791 }
792
793 JSCell* JIT_OPERATION operationCreateClonedArgumentsDuringExit(ExecState* exec, InlineCallFrame* inlineCallFrame, JSFunction* callee, int32_t argumentCount)
794 {
795     VM& vm = exec->vm();
796     NativeCallFrameTracer target(&vm, exec);
797     
798     DeferGCForAWhile deferGC(vm.heap);
799     
800     CodeBlock* codeBlock;
801     if (inlineCallFrame)
802         codeBlock = baselineCodeBlockForInlineCallFrame(inlineCallFrame);
803     else
804         codeBlock = exec->codeBlock();
805     
806     unsigned length = argumentCount - 1;
807     ClonedArguments* result = ClonedArguments::createEmpty(
808         vm, codeBlock->globalObject()->outOfBandArgumentsStructure(), callee);
809     
810     Register* arguments =
811         exec->registers() + (inlineCallFrame ? inlineCallFrame->stackOffset : 0) +
812         CallFrame::argumentOffset(0);
813     for (unsigned i = length; i--;)
814         result->putDirectIndex(exec, i, arguments[i].jsValue());
815     
816     result->putDirect(vm, vm.propertyNames->length, jsNumber(length));
817     
818     return result;
819 }
820
821 void JIT_OPERATION operationCopyRest(ExecState* exec, JSCell* arrayAsCell, Register* argumentStart, unsigned numberOfParamsToSkip, unsigned numberOfArguments)
822 {
823     RELEASE_ASSERT(numberOfArguments > numberOfParamsToSkip); // We should only call this from JIT code when this condition is true.
824     JSArray* array = jsCast<JSArray*>(arrayAsCell);
825     unsigned arraySize = numberOfArguments - numberOfParamsToSkip;
826     array->setLength(exec, arraySize);
827     for (unsigned i = 0; i < arraySize; i++)
828         array->putDirectIndex(exec, i, argumentStart[i + numberOfParamsToSkip].jsValue());
829 }
830
831 size_t JIT_OPERATION operationObjectIsObject(ExecState* exec, JSGlobalObject* globalObject, JSCell* object)
832 {
833     VM& vm = exec->vm();
834     NativeCallFrameTracer tracer(&vm, exec);
835
836     ASSERT(jsDynamicCast<JSObject*>(object));
837     
838     if (object->structure(vm)->masqueradesAsUndefined(globalObject))
839         return false;
840     if (object->type() == JSFunctionType)
841         return false;
842     if (object->inlineTypeFlags() & TypeOfShouldCallGetCallData) {
843         CallData callData;
844         if (object->methodTable(vm)->getCallData(object, callData) != CallTypeNone)
845             return false;
846     }
847     
848     return true;
849 }
850
851 size_t JIT_OPERATION operationObjectIsFunction(ExecState* exec, JSGlobalObject* globalObject, JSCell* object)
852 {
853     VM& vm = exec->vm();
854     NativeCallFrameTracer tracer(&vm, exec);
855
856     ASSERT(jsDynamicCast<JSObject*>(object));
857     
858     if (object->structure(vm)->masqueradesAsUndefined(globalObject))
859         return false;
860     if (object->type() == JSFunctionType)
861         return true;
862     if (object->inlineTypeFlags() & TypeOfShouldCallGetCallData) {
863         CallData callData;
864         if (object->methodTable(vm)->getCallData(object, callData) != CallTypeNone)
865             return true;
866     }
867     
868     return false;
869 }
870
871 JSCell* JIT_OPERATION operationTypeOfObject(ExecState* exec, JSGlobalObject* globalObject, JSCell* object)
872 {
873     VM& vm = exec->vm();
874     NativeCallFrameTracer tracer(&vm, exec);
875
876     ASSERT(jsDynamicCast<JSObject*>(object));
877     
878     if (object->structure(vm)->masqueradesAsUndefined(globalObject))
879         return vm.smallStrings.undefinedString();
880     if (object->type() == JSFunctionType)
881         return vm.smallStrings.functionString();
882     if (object->inlineTypeFlags() & TypeOfShouldCallGetCallData) {
883         CallData callData;
884         if (object->methodTable(vm)->getCallData(object, callData) != CallTypeNone)
885             return vm.smallStrings.functionString();
886     }
887     
888     return vm.smallStrings.objectString();
889 }
890
891 int32_t JIT_OPERATION operationTypeOfObjectAsTypeofType(ExecState* exec, JSGlobalObject* globalObject, JSCell* object)
892 {
893     VM& vm = exec->vm();
894     NativeCallFrameTracer tracer(&vm, exec);
895
896     ASSERT(jsDynamicCast<JSObject*>(object));
897     
898     if (object->structure(vm)->masqueradesAsUndefined(globalObject))
899         return static_cast<int32_t>(TypeofType::Undefined);
900     if (object->type() == JSFunctionType)
901         return static_cast<int32_t>(TypeofType::Function);
902     if (object->inlineTypeFlags() & TypeOfShouldCallGetCallData) {
903         CallData callData;
904         if (object->methodTable(vm)->getCallData(object, callData) != CallTypeNone)
905             return static_cast<int32_t>(TypeofType::Function);
906     }
907     
908     return static_cast<int32_t>(TypeofType::Object);
909 }
910
911 char* JIT_OPERATION operationAllocatePropertyStorageWithInitialCapacity(ExecState* exec)
912 {
913     VM& vm = exec->vm();
914     NativeCallFrameTracer tracer(&vm, exec);
915
916     return reinterpret_cast<char*>(
917         Butterfly::createUninitialized(vm, 0, 0, initialOutOfLineCapacity, false, 0));
918 }
919
920 char* JIT_OPERATION operationAllocatePropertyStorage(ExecState* exec, size_t newSize)
921 {
922     VM& vm = exec->vm();
923     NativeCallFrameTracer tracer(&vm, exec);
924
925     return reinterpret_cast<char*>(
926         Butterfly::createUninitialized(vm, 0, 0, newSize, false, 0));
927 }
928
929 char* JIT_OPERATION operationReallocateButterflyToHavePropertyStorageWithInitialCapacity(ExecState* exec, JSObject* object)
930 {
931     VM& vm = exec->vm();
932     NativeCallFrameTracer tracer(&vm, exec);
933
934     ASSERT(!object->structure()->outOfLineCapacity());
935     DeferGC deferGC(vm.heap);
936     Butterfly* result = object->growOutOfLineStorage(vm, 0, initialOutOfLineCapacity);
937     object->setButterflyWithoutChangingStructure(vm, result);
938     return reinterpret_cast<char*>(result);
939 }
940
941 char* JIT_OPERATION operationReallocateButterflyToGrowPropertyStorage(ExecState* exec, JSObject* object, size_t newSize)
942 {
943     VM& vm = exec->vm();
944     NativeCallFrameTracer tracer(&vm, exec);
945
946     DeferGC deferGC(vm.heap);
947     Butterfly* result = object->growOutOfLineStorage(vm, object->structure()->outOfLineCapacity(), newSize);
948     object->setButterflyWithoutChangingStructure(vm, result);
949     return reinterpret_cast<char*>(result);
950 }
951
952 char* JIT_OPERATION operationEnsureInt32(ExecState* exec, JSCell* cell)
953 {
954     VM& vm = exec->vm();
955     NativeCallFrameTracer tracer(&vm, exec);
956     
957     if (!cell->isObject())
958         return 0;
959     
960     return reinterpret_cast<char*>(asObject(cell)->ensureInt32(vm).data());
961 }
962
963 char* JIT_OPERATION operationEnsureDouble(ExecState* exec, JSCell* cell)
964 {
965     VM& vm = exec->vm();
966     NativeCallFrameTracer tracer(&vm, exec);
967     
968     if (!cell->isObject())
969         return 0;
970     
971     return reinterpret_cast<char*>(asObject(cell)->ensureDouble(vm).data());
972 }
973
974 char* JIT_OPERATION operationEnsureContiguous(ExecState* exec, JSCell* cell)
975 {
976     VM& vm = exec->vm();
977     NativeCallFrameTracer tracer(&vm, exec);
978     
979     if (!cell->isObject())
980         return 0;
981     
982     return reinterpret_cast<char*>(asObject(cell)->ensureContiguous(vm).data());
983 }
984
985 char* JIT_OPERATION operationEnsureArrayStorage(ExecState* exec, JSCell* cell)
986 {
987     VM& vm = exec->vm();
988     NativeCallFrameTracer tracer(&vm, exec);
989     
990     if (!cell->isObject())
991         return 0;
992
993     return reinterpret_cast<char*>(asObject(cell)->ensureArrayStorage(vm));
994 }
995
996 StringImpl* JIT_OPERATION operationResolveRope(ExecState* exec, JSString* string)
997 {
998     VM& vm = exec->vm();
999     NativeCallFrameTracer tracer(&vm, exec);
1000
1001     return string->value(exec).impl();
1002 }
1003
1004 JSString* JIT_OPERATION operationSingleCharacterString(ExecState* exec, int32_t character)
1005 {
1006     VM& vm = exec->vm();
1007     NativeCallFrameTracer tracer(&vm, exec);
1008     
1009     return jsSingleCharacterString(exec, static_cast<UChar>(character));
1010 }
1011
1012 JSCell* JIT_OPERATION operationNewStringObject(ExecState* exec, JSString* string, Structure* structure)
1013 {
1014     VM& vm = exec->vm();
1015     NativeCallFrameTracer tracer(&vm, exec);
1016     
1017     return StringObject::create(vm, structure, string);
1018 }
1019
1020 JSCell* JIT_OPERATION operationToStringOnCell(ExecState* exec, JSCell* cell)
1021 {
1022     VM& vm = exec->vm();
1023     NativeCallFrameTracer tracer(&vm, exec);
1024     
1025     return JSValue(cell).toString(exec);
1026 }
1027
1028 JSCell* JIT_OPERATION operationToString(ExecState* exec, EncodedJSValue value)
1029 {
1030     VM& vm = exec->vm();
1031     NativeCallFrameTracer tracer(&vm, exec);
1032
1033     return JSValue::decode(value).toString(exec);
1034 }
1035
1036 JSCell* JIT_OPERATION operationCallStringConstructorOnCell(ExecState* exec, JSCell* cell)
1037 {
1038     VM& vm = exec->vm();
1039     NativeCallFrameTracer tracer(&vm, exec);
1040
1041     return stringConstructor(exec, cell);
1042 }
1043
1044 JSCell* JIT_OPERATION operationCallStringConstructor(ExecState* exec, EncodedJSValue value)
1045 {
1046     VM& vm = exec->vm();
1047     NativeCallFrameTracer tracer(&vm, exec);
1048
1049     return stringConstructor(exec, JSValue::decode(value));
1050 }
1051
1052 JSCell* JIT_OPERATION operationMakeRope2(ExecState* exec, JSString* left, JSString* right)
1053 {
1054     VM& vm = exec->vm();
1055     NativeCallFrameTracer tracer(&vm, exec);
1056
1057     if (sumOverflows<int32_t>(left->length(), right->length())) {
1058         throwOutOfMemoryError(exec);
1059         return nullptr;
1060     }
1061
1062     return JSRopeString::create(vm, left, right);
1063 }
1064
1065 JSCell* JIT_OPERATION operationMakeRope3(ExecState* exec, JSString* a, JSString* b, JSString* c)
1066 {
1067     VM& vm = exec->vm();
1068     NativeCallFrameTracer tracer(&vm, exec);
1069
1070     if (sumOverflows<int32_t>(a->length(), b->length(), c->length())) {
1071         throwOutOfMemoryError(exec);
1072         return nullptr;
1073     }
1074
1075     return JSRopeString::create(vm, a, b, c);
1076 }
1077
1078 JSCell* JIT_OPERATION operationStrCat2(ExecState* exec, EncodedJSValue a, EncodedJSValue b)
1079 {
1080     VM& vm = exec->vm();
1081     NativeCallFrameTracer tracer(&vm, exec);
1082
1083     JSString* str1 = JSValue::decode(a).toString(exec);
1084     ASSERT(!exec->hadException()); // Impossible, since we must have been given primitives.
1085     JSString* str2 = JSValue::decode(b).toString(exec);
1086     ASSERT(!exec->hadException());
1087
1088     if (sumOverflows<int32_t>(str1->length(), str2->length())) {
1089         throwOutOfMemoryError(exec);
1090         return nullptr;
1091     }
1092
1093     return JSRopeString::create(vm, str1, str2);
1094 }
1095     
1096 JSCell* JIT_OPERATION operationStrCat3(ExecState* exec, EncodedJSValue a, EncodedJSValue b, EncodedJSValue c)
1097 {
1098     VM& vm = exec->vm();
1099     NativeCallFrameTracer tracer(&vm, exec);
1100
1101     JSString* str1 = JSValue::decode(a).toString(exec);
1102     ASSERT(!exec->hadException()); // Impossible, since we must have been given primitives.
1103     JSString* str2 = JSValue::decode(b).toString(exec);
1104     ASSERT(!exec->hadException());
1105     JSString* str3 = JSValue::decode(c).toString(exec);
1106     ASSERT(!exec->hadException());
1107
1108     if (sumOverflows<int32_t>(str1->length(), str2->length(), str3->length())) {
1109         throwOutOfMemoryError(exec);
1110         return nullptr;
1111     }
1112
1113     return JSRopeString::create(vm, str1, str2, str3);
1114 }
1115
1116 char* JIT_OPERATION operationFindSwitchImmTargetForDouble(
1117     ExecState* exec, EncodedJSValue encodedValue, size_t tableIndex)
1118 {
1119     CodeBlock* codeBlock = exec->codeBlock();
1120     SimpleJumpTable& table = codeBlock->switchJumpTable(tableIndex);
1121     JSValue value = JSValue::decode(encodedValue);
1122     ASSERT(value.isDouble());
1123     double asDouble = value.asDouble();
1124     int32_t asInt32 = static_cast<int32_t>(asDouble);
1125     if (asDouble == asInt32)
1126         return static_cast<char*>(table.ctiForValue(asInt32).executableAddress());
1127     return static_cast<char*>(table.ctiDefault.executableAddress());
1128 }
1129
1130 char* JIT_OPERATION operationSwitchString(ExecState* exec, size_t tableIndex, JSString* string)
1131 {
1132     VM& vm = exec->vm();
1133     NativeCallFrameTracer tracer(&vm, exec);
1134
1135     return static_cast<char*>(exec->codeBlock()->stringSwitchJumpTable(tableIndex).ctiForValue(string->value(exec).impl()).executableAddress());
1136 }
1137
1138 int32_t JIT_OPERATION operationSwitchStringAndGetBranchOffset(ExecState* exec, size_t tableIndex, JSString* string)
1139 {
1140     VM& vm = exec->vm();
1141     NativeCallFrameTracer tracer(&vm, exec);
1142
1143     return exec->codeBlock()->stringSwitchJumpTable(tableIndex).offsetForValue(string->value(exec).impl(), std::numeric_limits<int32_t>::min());
1144 }
1145
1146 char* JIT_OPERATION operationGetButterfly(ExecState* exec, JSCell* cell)
1147 {
1148     VM& vm = exec->vm();
1149     NativeCallFrameTracer tracer(&vm, exec);
1150
1151     dataLog("Ran the barrier.\n");
1152
1153     return bitwise_cast<char*>(jsCast<JSObject*>(cell)->butterfly());
1154 }
1155
1156 char* JIT_OPERATION operationGetArrayBufferVector(ExecState* exec, JSCell* cell)
1157 {
1158     VM& vm = exec->vm();
1159     NativeCallFrameTracer tracer(&vm, exec);
1160
1161     return bitwise_cast<char*>(jsCast<JSArrayBufferView*>(cell)->vector());
1162 }
1163
1164 void JIT_OPERATION operationNotifyWrite(ExecState* exec, WatchpointSet* set)
1165 {
1166     VM& vm = exec->vm();
1167     NativeCallFrameTracer tracer(&vm, exec);
1168
1169     set->touch("Executed NotifyWrite");
1170 }
1171
1172 void JIT_OPERATION operationThrowStackOverflowForVarargs(ExecState* exec)
1173 {
1174     VM& vm = exec->vm();
1175     NativeCallFrameTracer tracer(&vm, exec);
1176     throwStackOverflowError(exec);
1177 }
1178
1179 int32_t JIT_OPERATION operationSizeOfVarargs(ExecState* exec, EncodedJSValue encodedArguments, int32_t firstVarArgOffset)
1180 {
1181     VM& vm = exec->vm();
1182     NativeCallFrameTracer tracer(&vm, exec);
1183     JSValue arguments = JSValue::decode(encodedArguments);
1184     
1185     return sizeOfVarargs(exec, arguments, firstVarArgOffset);
1186 }
1187
1188 void JIT_OPERATION operationLoadVarargs(ExecState* exec, int32_t firstElementDest, EncodedJSValue encodedArguments, int32_t offset, int32_t length, int32_t mandatoryMinimum)
1189 {
1190     VM& vm = exec->vm();
1191     NativeCallFrameTracer tracer(&vm, exec);
1192     JSValue arguments = JSValue::decode(encodedArguments);
1193     
1194     loadVarargs(exec, VirtualRegister(firstElementDest), arguments, offset, length);
1195     
1196     for (int32_t i = length; i < mandatoryMinimum; ++i)
1197         exec->r(firstElementDest + i) = jsUndefined();
1198 }
1199
1200 double JIT_OPERATION operationFModOnInts(int32_t a, int32_t b)
1201 {
1202     return fmod(a, b);
1203 }
1204
1205 JSCell* JIT_OPERATION operationStringFromCharCode(ExecState* exec, int32_t op1)
1206 {
1207     VM* vm = &exec->vm();
1208     NativeCallFrameTracer tracer(vm, exec);
1209     return JSC::stringFromCharCode(exec, op1);
1210 }
1211
1212 int64_t JIT_OPERATION operationConvertBoxedDoubleToInt52(EncodedJSValue encodedValue)
1213 {
1214     JSValue value = JSValue::decode(encodedValue);
1215     if (!value.isDouble())
1216         return JSValue::notInt52;
1217     return tryConvertToInt52(value.asDouble());
1218 }
1219
1220 int64_t JIT_OPERATION operationConvertDoubleToInt52(double value)
1221 {
1222     return tryConvertToInt52(value);
1223 }
1224
1225 void JIT_OPERATION operationProcessTypeProfilerLogDFG(ExecState* exec) 
1226 {
1227     exec->vm().typeProfilerLog()->processLogEntries(ASCIILiteral("Log Full, called from inside DFG."));
1228 }
1229
1230 void JIT_OPERATION debugOperationPrintSpeculationFailure(ExecState* exec, void* debugInfoRaw, void* scratch)
1231 {
1232     VM* vm = &exec->vm();
1233     NativeCallFrameTracer tracer(vm, exec);
1234     
1235     SpeculationFailureDebugInfo* debugInfo = static_cast<SpeculationFailureDebugInfo*>(debugInfoRaw);
1236     CodeBlock* codeBlock = debugInfo->codeBlock;
1237     CodeBlock* alternative = codeBlock->alternative();
1238     dataLog("Speculation failure in ", *codeBlock);
1239     dataLog(" @ exit #", vm->osrExitIndex, " (bc#", debugInfo->bytecodeOffset, ", ", exitKindToString(debugInfo->kind), ") with ");
1240     if (alternative) {
1241         dataLog(
1242             "executeCounter = ", alternative->jitExecuteCounter(),
1243             ", reoptimizationRetryCounter = ", alternative->reoptimizationRetryCounter(),
1244             ", optimizationDelayCounter = ", alternative->optimizationDelayCounter());
1245     } else
1246         dataLog("no alternative code block (i.e. we've been jettisoned)");
1247     dataLog(", osrExitCounter = ", codeBlock->osrExitCounter(), "\n");
1248     dataLog("    GPRs at time of exit:");
1249     char* scratchPointer = static_cast<char*>(scratch);
1250     for (unsigned i = 0; i < GPRInfo::numberOfRegisters; ++i) {
1251         GPRReg gpr = GPRInfo::toRegister(i);
1252         dataLog(" ", GPRInfo::debugName(gpr), ":", RawPointer(*reinterpret_cast_ptr<void**>(scratchPointer)));
1253         scratchPointer += sizeof(EncodedJSValue);
1254     }
1255     dataLog("\n");
1256     dataLog("    FPRs at time of exit:");
1257     for (unsigned i = 0; i < FPRInfo::numberOfRegisters; ++i) {
1258         FPRReg fpr = FPRInfo::toRegister(i);
1259         dataLog(" ", FPRInfo::debugName(fpr), ":");
1260         uint64_t bits = *reinterpret_cast_ptr<uint64_t*>(scratchPointer);
1261         double value = *reinterpret_cast_ptr<double*>(scratchPointer);
1262         dataLogF("%llx:%lf", static_cast<long long>(bits), value);
1263         scratchPointer += sizeof(EncodedJSValue);
1264     }
1265     dataLog("\n");
1266 }
1267
1268 extern "C" void JIT_OPERATION triggerReoptimizationNow(CodeBlock* codeBlock, OSRExitBase* exit)
1269 {
1270     // It's sort of preferable that we don't GC while in here. Anyways, doing so wouldn't
1271     // really be profitable.
1272     DeferGCForAWhile deferGC(codeBlock->vm()->heap);
1273     
1274     if (Options::verboseOSR())
1275         dataLog(*codeBlock, ": Entered reoptimize\n");
1276     // We must be called with the baseline code block.
1277     ASSERT(JITCode::isBaselineCode(codeBlock->jitType()));
1278
1279     // If I am my own replacement, then reoptimization has already been triggered.
1280     // This can happen in recursive functions.
1281     if (codeBlock->replacement() == codeBlock) {
1282         if (Options::verboseOSR())
1283             dataLog(*codeBlock, ": Not reoptimizing because we've already been jettisoned.\n");
1284         return;
1285     }
1286     
1287     // Otherwise, the replacement must be optimized code. Use this as an opportunity
1288     // to check our logic.
1289     ASSERT(codeBlock->hasOptimizedReplacement());
1290     CodeBlock* optimizedCodeBlock = codeBlock->replacement();
1291     ASSERT(JITCode::isOptimizingJIT(optimizedCodeBlock->jitType()));
1292     
1293     bool didTryToEnterIntoInlinedLoops = false;
1294     for (InlineCallFrame* inlineCallFrame = exit->m_codeOrigin.inlineCallFrame; inlineCallFrame; inlineCallFrame = inlineCallFrame->directCaller.inlineCallFrame) {
1295         if (inlineCallFrame->baselineCodeBlock->ownerScriptExecutable()->didTryToEnterInLoop()) {
1296             didTryToEnterIntoInlinedLoops = true;
1297             break;
1298         }
1299     }
1300
1301     // In order to trigger reoptimization, one of two things must have happened:
1302     // 1) We exited more than some number of times.
1303     // 2) We exited and got stuck in a loop, and now we're exiting again.
1304     bool didExitABunch = optimizedCodeBlock->shouldReoptimizeNow();
1305     bool didGetStuckInLoop =
1306         (codeBlock->checkIfOptimizationThresholdReached() || didTryToEnterIntoInlinedLoops)
1307         && optimizedCodeBlock->shouldReoptimizeFromLoopNow();
1308     
1309     if (!didExitABunch && !didGetStuckInLoop) {
1310         if (Options::verboseOSR())
1311             dataLog(*codeBlock, ": Not reoptimizing ", *optimizedCodeBlock, " because it either didn't exit enough or didn't loop enough after exit.\n");
1312         codeBlock->optimizeAfterLongWarmUp();
1313         return;
1314     }
1315
1316     optimizedCodeBlock->jettison(Profiler::JettisonDueToOSRExit, CountReoptimization);
1317 }
1318
1319 #if ENABLE(FTL_JIT)
1320 static void triggerFTLReplacementCompile(VM* vm, CodeBlock* codeBlock, JITCode* jitCode)
1321 {
1322     if (codeBlock->baselineVersion()->m_didFailFTLCompilation) {
1323         if (Options::verboseOSR())
1324             dataLog("Deferring FTL-optimization of ", *codeBlock, " indefinitely because there was an FTL failure.\n");
1325         jitCode->dontOptimizeAnytimeSoon(codeBlock);
1326         return;
1327     }
1328     
1329     if (!jitCode->checkIfOptimizationThresholdReached(codeBlock)) {
1330         if (Options::verboseOSR())
1331             dataLog("Choosing not to FTL-optimize ", *codeBlock, " yet.\n");
1332         return;
1333     }
1334     
1335     Worklist::State worklistState;
1336     if (Worklist* worklist = existingGlobalFTLWorklistOrNull()) {
1337         worklistState = worklist->completeAllReadyPlansForVM(
1338             *vm, CompilationKey(codeBlock->baselineVersion(), FTLMode));
1339     } else
1340         worklistState = Worklist::NotKnown;
1341     
1342     if (worklistState == Worklist::Compiling) {
1343         jitCode->setOptimizationThresholdBasedOnCompilationResult(
1344             codeBlock, CompilationDeferred);
1345         return;
1346     }
1347     
1348     if (codeBlock->hasOptimizedReplacement()) {
1349         // That's great, we've compiled the code - next time we call this function,
1350         // we'll enter that replacement.
1351         jitCode->optimizeSoon(codeBlock);
1352         return;
1353     }
1354     
1355     if (worklistState == Worklist::Compiled) {
1356         // This means that we finished compiling, but failed somehow; in that case the
1357         // thresholds will be set appropriately.
1358         if (Options::verboseOSR())
1359             dataLog("Code block ", *codeBlock, " was compiled but it doesn't have an optimized replacement.\n");
1360         return;
1361     }
1362
1363     // We need to compile the code.
1364     compile(
1365         *vm, codeBlock->newReplacement(), codeBlock, FTLMode, UINT_MAX,
1366         Operands<JSValue>(), ToFTLDeferredCompilationCallback::create());
1367 }
1368
1369 static void triggerTierUpNowCommon(ExecState* exec, bool inLoop)
1370 {
1371     VM* vm = &exec->vm();
1372     NativeCallFrameTracer tracer(vm, exec);
1373     DeferGC deferGC(vm->heap);
1374     CodeBlock* codeBlock = exec->codeBlock();
1375     
1376     if (codeBlock->jitType() != JITCode::DFGJIT) {
1377         dataLog("Unexpected code block in DFG->FTL tier-up: ", *codeBlock, "\n");
1378         RELEASE_ASSERT_NOT_REACHED();
1379     }
1380     
1381     JITCode* jitCode = codeBlock->jitCode()->dfg();
1382     
1383     if (Options::verboseOSR()) {
1384         dataLog(
1385             *codeBlock, ": Entered triggerTierUpNow with executeCounter = ",
1386             jitCode->tierUpCounter, "\n");
1387     }
1388     if (inLoop)
1389         jitCode->nestedTriggerIsSet = 1;
1390
1391     triggerFTLReplacementCompile(vm, codeBlock, jitCode);
1392 }
1393
1394 void JIT_OPERATION triggerTierUpNow(ExecState* exec)
1395 {
1396     triggerTierUpNowCommon(exec, false);
1397 }
1398
1399 void JIT_OPERATION triggerTierUpNowInLoop(ExecState* exec)
1400 {
1401     triggerTierUpNowCommon(exec, true);
1402 }
1403
1404 char* JIT_OPERATION triggerOSREntryNow(
1405     ExecState* exec, int32_t bytecodeIndex, int32_t streamIndex)
1406 {
1407     VM* vm = &exec->vm();
1408     NativeCallFrameTracer tracer(vm, exec);
1409     DeferGC deferGC(vm->heap);
1410     CodeBlock* codeBlock = exec->codeBlock();
1411     
1412     if (codeBlock->jitType() != JITCode::DFGJIT) {
1413         dataLog("Unexpected code block in DFG->FTL tier-up: ", *codeBlock, "\n");
1414         RELEASE_ASSERT_NOT_REACHED();
1415     }
1416     
1417     JITCode* jitCode = codeBlock->jitCode()->dfg();
1418     jitCode->nestedTriggerIsSet = 0;
1419     
1420     if (Options::verboseOSR()) {
1421         dataLog(
1422             *codeBlock, ": Entered triggerOSREntryNow with executeCounter = ",
1423             jitCode->tierUpCounter, "\n");
1424     }
1425     
1426     // - If we don't have an FTL code block, then try to compile one.
1427     // - If we do have an FTL code block, then try to enter for a while.
1428     // - If we couldn't enter for a while, then trigger OSR entry.
1429     
1430     triggerFTLReplacementCompile(vm, codeBlock, jitCode);
1431
1432     if (!codeBlock->hasOptimizedReplacement())
1433         return 0;
1434     
1435     if (jitCode->osrEntryRetry < Options::ftlOSREntryRetryThreshold()) {
1436         jitCode->osrEntryRetry++;
1437         return 0;
1438     }
1439     
1440     // It's time to try to compile code for OSR entry.
1441     Worklist::State worklistState;
1442     if (Worklist* worklist = existingGlobalFTLWorklistOrNull()) {
1443         worklistState = worklist->completeAllReadyPlansForVM(
1444             *vm, CompilationKey(codeBlock->baselineVersion(), FTLForOSREntryMode));
1445     } else
1446         worklistState = Worklist::NotKnown;
1447     
1448     if (worklistState == Worklist::Compiling)
1449         return 0;
1450     
1451     if (CodeBlock* entryBlock = jitCode->osrEntryBlock()) {
1452         void* address = FTL::prepareOSREntry(
1453             exec, codeBlock, entryBlock, bytecodeIndex, streamIndex);
1454         if (address)
1455             return static_cast<char*>(address);
1456         
1457         FTL::ForOSREntryJITCode* entryCode = entryBlock->jitCode()->ftlForOSREntry();
1458         entryCode->countEntryFailure();
1459         if (entryCode->entryFailureCount() <
1460             Options::ftlOSREntryFailureCountForReoptimization())
1461             return 0;
1462         
1463         // OSR entry failed. Oh no! This implies that we need to retry. We retry
1464         // without exponential backoff and we only do this for the entry code block.
1465         jitCode->clearOSREntryBlock();
1466         jitCode->osrEntryRetry = 0;
1467         return 0;
1468     }
1469     
1470     if (worklistState == Worklist::Compiled) {
1471         // This means that compilation failed and we already set the thresholds.
1472         if (Options::verboseOSR())
1473             dataLog("Code block ", *codeBlock, " was compiled but it doesn't have an optimized replacement.\n");
1474         return 0;
1475     }
1476
1477     // We aren't compiling and haven't compiled anything for OSR entry. So, try to compile
1478     // something.
1479     Operands<JSValue> mustHandleValues;
1480     jitCode->reconstruct(
1481         exec, codeBlock, CodeOrigin(bytecodeIndex), streamIndex, mustHandleValues);
1482     CodeBlock* replacementCodeBlock = codeBlock->newReplacement();
1483     CompilationResult forEntryResult = compile(
1484         *vm, replacementCodeBlock, codeBlock, FTLForOSREntryMode, bytecodeIndex,
1485         mustHandleValues, ToFTLForOSREntryDeferredCompilationCallback::create());
1486     
1487     if (forEntryResult != CompilationSuccessful)
1488         return 0;
1489
1490     // It's possible that the for-entry compile already succeeded. In that case OSR
1491     // entry will succeed unless we ran out of stack. It's not clear what we should do.
1492     // We signal to try again after a while if that happens.
1493     void* address = FTL::prepareOSREntry(
1494         exec, codeBlock, jitCode->osrEntryBlock(), bytecodeIndex, streamIndex);
1495     return static_cast<char*>(address);
1496 }
1497 #endif // ENABLE(FTL_JIT)
1498
1499 } // extern "C"
1500 } } // namespace JSC::DFG
1501
1502 #endif // ENABLE(DFG_JIT)
1503
1504 #endif // ENABLE(JIT)