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