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