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