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