b31b6fcdc42228f7297009a7e273100bf5538c61
[WebKit.git] / Source / JavaScriptCore / dfg / DFGOperations.cpp
1 /*
2  * Copyright (C) 2011, 2013 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 "DFGOSRExit.h"
36 #include "DFGThunks.h"
37 #include "DFGToFTLDeferredCompilationCallback.h"
38 #include "DFGToFTLForOSREntryDeferredCompilationCallback.h"
39 #include "DFGWorklist.h"
40 #include "FTLForOSREntryJITCode.h"
41 #include "FTLOSREntry.h"
42 #include "HostCallReturnValue.h"
43 #include "GetterSetter.h"
44 #include "Interpreter.h"
45 #include "JIT.h"
46 #include "JITExceptions.h"
47 #include "JITOperationWrappers.h"
48 #include "JSActivation.h"
49 #include "VM.h"
50 #include "JSNameScope.h"
51 #include "NameInstance.h"
52 #include "ObjectConstructor.h"
53 #include "Operations.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()->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(exec, property.toString(exec)->value(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, "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, "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, "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, "Invalid array length argument (fractional lengths not allowed)"));
192             return 0;
193         }
194     }
195     
196     if (length < 0) {
197         vm.throwException(exec, createRangeError(exec, "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()->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 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             if (JSValue result = base->fastGetOwnProperty(exec, asString(property)->value(exec)))
299                 return JSValue::encode(result);
300         }
301     }
302
303     if (isName(property))
304         return JSValue::encode(baseValue.get(exec, jsCast<NameInstance*>(property.asCell())->privateName()));
305
306     Identifier ident(exec, property.toString(exec)->value(exec));
307     return JSValue::encode(baseValue.get(exec, ident));
308 }
309
310 EncodedJSValue JIT_OPERATION operationGetByValCell(ExecState* exec, JSCell* base, EncodedJSValue encodedProperty)
311 {
312     VM* vm = &exec->vm();
313     NativeCallFrameTracer tracer(vm, exec);
314     
315     JSValue property = JSValue::decode(encodedProperty);
316
317     if (property.isUInt32())
318         return getByVal(exec, base, property.asUInt32());
319     if (property.isDouble()) {
320         double propertyAsDouble = property.asDouble();
321         uint32_t propertyAsUInt32 = static_cast<uint32_t>(propertyAsDouble);
322         if (propertyAsUInt32 == propertyAsDouble)
323             return getByVal(exec, base, propertyAsUInt32);
324     } else if (property.isString()) {
325         if (JSValue result = base->fastGetOwnProperty(exec, asString(property)->value(exec)))
326             return JSValue::encode(result);
327     }
328
329     if (isName(property))
330         return JSValue::encode(JSValue(base).get(exec, jsCast<NameInstance*>(property.asCell())->privateName()));
331
332     Identifier ident(exec, property.toString(exec)->value(exec));
333     return JSValue::encode(JSValue(base).get(exec, ident));
334 }
335
336 ALWAYS_INLINE EncodedJSValue getByValCellInt(ExecState* exec, JSCell* base, int32_t index)
337 {
338     VM* vm = &exec->vm();
339     NativeCallFrameTracer tracer(vm, exec);
340     
341     if (index < 0) {
342         // Go the slowest way possible becase negative indices don't use indexed storage.
343         return JSValue::encode(JSValue(base).get(exec, Identifier::from(exec, index)));
344     }
345
346     // Use this since we know that the value is out of bounds.
347     return JSValue::encode(JSValue(base).get(exec, index));
348 }
349
350 EncodedJSValue JIT_OPERATION operationGetByValArrayInt(ExecState* exec, JSArray* base, int32_t index)
351 {
352     return getByValCellInt(exec, base, index);
353 }
354
355 EncodedJSValue JIT_OPERATION operationGetByValStringInt(ExecState* exec, JSString* base, int32_t index)
356 {
357     return getByValCellInt(exec, base, index);
358 }
359
360 void JIT_OPERATION operationPutByValStrict(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
361 {
362     VM* vm = &exec->vm();
363     NativeCallFrameTracer tracer(vm, exec);
364     
365     operationPutByValInternal<true, false>(exec, encodedBase, encodedProperty, encodedValue);
366 }
367
368 void JIT_OPERATION operationPutByValNonStrict(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
369 {
370     VM* vm = &exec->vm();
371     NativeCallFrameTracer tracer(vm, exec);
372     
373     operationPutByValInternal<false, false>(exec, encodedBase, encodedProperty, encodedValue);
374 }
375
376 void JIT_OPERATION operationPutByValCellStrict(ExecState* exec, JSCell* cell, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
377 {
378     VM* vm = &exec->vm();
379     NativeCallFrameTracer tracer(vm, exec);
380     
381     operationPutByValInternal<true, false>(exec, JSValue::encode(cell), encodedProperty, encodedValue);
382 }
383
384 void JIT_OPERATION operationPutByValCellNonStrict(ExecState* exec, JSCell* cell, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
385 {
386     VM* vm = &exec->vm();
387     NativeCallFrameTracer tracer(vm, exec);
388     
389     operationPutByValInternal<false, false>(exec, JSValue::encode(cell), encodedProperty, encodedValue);
390 }
391
392 void JIT_OPERATION operationPutByValBeyondArrayBoundsStrict(ExecState* exec, JSObject* array, int32_t index, EncodedJSValue encodedValue)
393 {
394     VM* vm = &exec->vm();
395     NativeCallFrameTracer tracer(vm, exec);
396     
397     if (index >= 0) {
398         array->putByIndexInline(exec, index, JSValue::decode(encodedValue), true);
399         return;
400     }
401     
402     PutPropertySlot slot(array, true);
403     array->methodTable()->put(
404         array, exec, Identifier::from(exec, index), JSValue::decode(encodedValue), slot);
405 }
406
407 void JIT_OPERATION operationPutByValBeyondArrayBoundsNonStrict(ExecState* exec, JSObject* array, int32_t index, EncodedJSValue encodedValue)
408 {
409     VM* vm = &exec->vm();
410     NativeCallFrameTracer tracer(vm, exec);
411     
412     if (index >= 0) {
413         array->putByIndexInline(exec, index, JSValue::decode(encodedValue), false);
414         return;
415     }
416     
417     PutPropertySlot slot(array, false);
418     array->methodTable()->put(
419         array, exec, Identifier::from(exec, index), JSValue::decode(encodedValue), slot);
420 }
421
422 void JIT_OPERATION operationPutDoubleByValBeyondArrayBoundsStrict(ExecState* exec, JSObject* array, int32_t index, double value)
423 {
424     VM* vm = &exec->vm();
425     NativeCallFrameTracer tracer(vm, exec);
426     
427     JSValue jsValue = JSValue(JSValue::EncodeAsDouble, value);
428     
429     if (index >= 0) {
430         array->putByIndexInline(exec, index, jsValue, true);
431         return;
432     }
433     
434     PutPropertySlot slot(array, true);
435     array->methodTable()->put(
436         array, exec, Identifier::from(exec, index), jsValue, slot);
437 }
438
439 void JIT_OPERATION operationPutDoubleByValBeyondArrayBoundsNonStrict(ExecState* exec, JSObject* array, int32_t index, double value)
440 {
441     VM* vm = &exec->vm();
442     NativeCallFrameTracer tracer(vm, exec);
443     
444     JSValue jsValue = JSValue(JSValue::EncodeAsDouble, value);
445     
446     if (index >= 0) {
447         array->putByIndexInline(exec, index, jsValue, false);
448         return;
449     }
450     
451     PutPropertySlot slot(array, false);
452     array->methodTable()->put(
453         array, exec, Identifier::from(exec, index), jsValue, slot);
454 }
455
456 void JIT_OPERATION operationPutByValDirectStrict(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
457 {
458     VM* vm = &exec->vm();
459     NativeCallFrameTracer tracer(vm, exec);
460     
461     operationPutByValInternal<true, true>(exec, encodedBase, encodedProperty, encodedValue);
462 }
463
464 void JIT_OPERATION operationPutByValDirectNonStrict(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
465 {
466     VM* vm = &exec->vm();
467     NativeCallFrameTracer tracer(vm, exec);
468     
469     operationPutByValInternal<false, true>(exec, encodedBase, encodedProperty, encodedValue);
470 }
471
472 void JIT_OPERATION operationPutByValDirectCellStrict(ExecState* exec, JSCell* cell, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
473 {
474     VM* vm = &exec->vm();
475     NativeCallFrameTracer tracer(vm, exec);
476     
477     operationPutByValInternal<true, true>(exec, JSValue::encode(cell), encodedProperty, encodedValue);
478 }
479
480 void JIT_OPERATION operationPutByValDirectCellNonStrict(ExecState* exec, JSCell* cell, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
481 {
482     VM* vm = &exec->vm();
483     NativeCallFrameTracer tracer(vm, exec);
484     
485     operationPutByValInternal<false, true>(exec, JSValue::encode(cell), encodedProperty, encodedValue);
486 }
487
488 void JIT_OPERATION operationPutByValDirectBeyondArrayBoundsStrict(ExecState* exec, JSObject* array, int32_t index, EncodedJSValue encodedValue)
489 {
490     VM* vm = &exec->vm();
491     NativeCallFrameTracer tracer(vm, exec);
492     if (index >= 0) {
493         array->putDirectIndex(exec, index, JSValue::decode(encodedValue), 0, PutDirectIndexShouldThrow);
494         return;
495     }
496     
497     PutPropertySlot slot(array, true);
498     array->putDirect(exec->vm(), Identifier::from(exec, index), JSValue::decode(encodedValue), slot);
499 }
500
501 void JIT_OPERATION operationPutByValDirectBeyondArrayBoundsNonStrict(ExecState* exec, JSObject* array, int32_t index, EncodedJSValue encodedValue)
502 {
503     VM* vm = &exec->vm();
504     NativeCallFrameTracer tracer(vm, exec);
505     
506     if (index >= 0) {
507         array->putDirectIndex(exec, index, JSValue::decode(encodedValue));
508         return;
509     }
510     
511     PutPropertySlot slot(array, false);
512     array->putDirect(exec->vm(), Identifier::from(exec, index), JSValue::decode(encodedValue), slot);
513 }
514
515 EncodedJSValue JIT_OPERATION operationArrayPush(ExecState* exec, EncodedJSValue encodedValue, JSArray* array)
516 {
517     VM* vm = &exec->vm();
518     NativeCallFrameTracer tracer(vm, exec);
519     
520     array->push(exec, JSValue::decode(encodedValue));
521     return JSValue::encode(jsNumber(array->length()));
522 }
523
524 EncodedJSValue JIT_OPERATION operationArrayPushDouble(ExecState* exec, double value, JSArray* array)
525 {
526     VM* vm = &exec->vm();
527     NativeCallFrameTracer tracer(vm, exec);
528     
529     array->push(exec, JSValue(JSValue::EncodeAsDouble, value));
530     return JSValue::encode(jsNumber(array->length()));
531 }
532
533 EncodedJSValue JIT_OPERATION operationArrayPop(ExecState* exec, JSArray* array)
534 {
535     VM* vm = &exec->vm();
536     NativeCallFrameTracer tracer(vm, exec);
537     
538     return JSValue::encode(array->pop(exec));
539 }
540         
541 EncodedJSValue JIT_OPERATION operationArrayPopAndRecoverLength(ExecState* exec, JSArray* array)
542 {
543     VM* vm = &exec->vm();
544     NativeCallFrameTracer tracer(vm, exec);
545     
546     array->butterfly()->setPublicLength(array->butterfly()->publicLength() + 1);
547     
548     return JSValue::encode(array->pop(exec));
549 }
550         
551 EncodedJSValue JIT_OPERATION operationRegExpExec(ExecState* exec, JSCell* base, JSCell* argument)
552 {
553     VM& vm = exec->vm();
554     NativeCallFrameTracer tracer(&vm, exec);
555     
556     if (!base->inherits(RegExpObject::info()))
557         return throwVMTypeError(exec);
558
559     ASSERT(argument->isString() || argument->isObject());
560     JSString* input = argument->isString() ? asString(argument) : asObject(argument)->toString(exec);
561     return JSValue::encode(asRegExpObject(base)->exec(exec, input));
562 }
563         
564 size_t JIT_OPERATION operationRegExpTest(ExecState* exec, JSCell* base, JSCell* argument)
565 {
566     VM& vm = exec->vm();
567     NativeCallFrameTracer tracer(&vm, exec);
568
569     if (!base->inherits(RegExpObject::info())) {
570         throwTypeError(exec);
571         return false;
572     }
573
574     ASSERT(argument->isString() || argument->isObject());
575     JSString* input = argument->isString() ? asString(argument) : asObject(argument)->toString(exec);
576     return asRegExpObject(base)->test(exec, input);
577 }
578
579 size_t JIT_OPERATION operationCompareStrictEqCell(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
580 {
581     VM* vm = &exec->vm();
582     NativeCallFrameTracer tracer(vm, exec);
583     
584     JSValue op1 = JSValue::decode(encodedOp1);
585     JSValue op2 = JSValue::decode(encodedOp2);
586     
587     ASSERT(op1.isCell());
588     ASSERT(op2.isCell());
589     
590     return JSValue::strictEqualSlowCaseInline(exec, op1, op2);
591 }
592
593 size_t JIT_OPERATION operationCompareStrictEq(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
594 {
595     VM* vm = &exec->vm();
596     NativeCallFrameTracer tracer(vm, exec);
597
598     JSValue src1 = JSValue::decode(encodedOp1);
599     JSValue src2 = JSValue::decode(encodedOp2);
600     
601     return JSValue::strictEqual(exec, src1, src2);
602 }
603
604 EncodedJSValue JIT_OPERATION operationToPrimitive(ExecState* exec, EncodedJSValue value)
605 {
606     VM* vm = &exec->vm();
607     NativeCallFrameTracer tracer(vm, exec);
608     
609     return JSValue::encode(JSValue::decode(value).toPrimitive(exec));
610 }
611
612 char* JIT_OPERATION operationNewArray(ExecState* exec, Structure* arrayStructure, void* buffer, size_t size)
613 {
614     VM* vm = &exec->vm();
615     NativeCallFrameTracer tracer(vm, exec);
616     
617     return bitwise_cast<char*>(constructArray(exec, arrayStructure, static_cast<JSValue*>(buffer), size));
618 }
619
620 char* JIT_OPERATION operationNewEmptyArray(ExecState* exec, Structure* arrayStructure)
621 {
622     VM* vm = &exec->vm();
623     NativeCallFrameTracer tracer(vm, exec);
624     
625     return bitwise_cast<char*>(JSArray::create(*vm, arrayStructure));
626 }
627
628 char* JIT_OPERATION operationNewArrayWithSize(ExecState* exec, Structure* arrayStructure, int32_t size)
629 {
630     VM* vm = &exec->vm();
631     NativeCallFrameTracer tracer(vm, exec);
632
633     if (UNLIKELY(size < 0))
634         return bitwise_cast<char*>(exec->vm().throwException(exec, createRangeError(exec, ASCIILiteral("Array size is not a small enough positive integer."))));
635
636     return bitwise_cast<char*>(JSArray::create(*vm, arrayStructure, size));
637 }
638
639 char* JIT_OPERATION operationNewArrayBuffer(ExecState* exec, Structure* arrayStructure, size_t start, size_t size)
640 {
641     VM& vm = exec->vm();
642     NativeCallFrameTracer tracer(&vm, exec);
643     return bitwise_cast<char*>(constructArray(exec, arrayStructure, exec->codeBlock()->constantBuffer(start), size));
644 }
645
646 char* JIT_OPERATION operationNewInt8ArrayWithSize(
647     ExecState* exec, Structure* structure, int32_t length)
648 {
649     return newTypedArrayWithSize<JSInt8Array>(exec, structure, length);
650 }
651
652 char* JIT_OPERATION operationNewInt8ArrayWithOneArgument(
653     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
654 {
655     return newTypedArrayWithOneArgument<JSInt8Array>(exec, structure, encodedValue);
656 }
657
658 char* JIT_OPERATION operationNewInt16ArrayWithSize(
659     ExecState* exec, Structure* structure, int32_t length)
660 {
661     return newTypedArrayWithSize<JSInt16Array>(exec, structure, length);
662 }
663
664 char* JIT_OPERATION operationNewInt16ArrayWithOneArgument(
665     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
666 {
667     return newTypedArrayWithOneArgument<JSInt16Array>(exec, structure, encodedValue);
668 }
669
670 char* JIT_OPERATION operationNewInt32ArrayWithSize(
671     ExecState* exec, Structure* structure, int32_t length)
672 {
673     return newTypedArrayWithSize<JSInt32Array>(exec, structure, length);
674 }
675
676 char* JIT_OPERATION operationNewInt32ArrayWithOneArgument(
677     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
678 {
679     return newTypedArrayWithOneArgument<JSInt32Array>(exec, structure, encodedValue);
680 }
681
682 char* JIT_OPERATION operationNewUint8ArrayWithSize(
683     ExecState* exec, Structure* structure, int32_t length)
684 {
685     return newTypedArrayWithSize<JSUint8Array>(exec, structure, length);
686 }
687
688 char* JIT_OPERATION operationNewUint8ArrayWithOneArgument(
689     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
690 {
691     return newTypedArrayWithOneArgument<JSUint8Array>(exec, structure, encodedValue);
692 }
693
694 char* JIT_OPERATION operationNewUint8ClampedArrayWithSize(
695     ExecState* exec, Structure* structure, int32_t length)
696 {
697     return newTypedArrayWithSize<JSUint8ClampedArray>(exec, structure, length);
698 }
699
700 char* JIT_OPERATION operationNewUint8ClampedArrayWithOneArgument(
701     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
702 {
703     return newTypedArrayWithOneArgument<JSUint8ClampedArray>(exec, structure, encodedValue);
704 }
705
706 char* JIT_OPERATION operationNewUint16ArrayWithSize(
707     ExecState* exec, Structure* structure, int32_t length)
708 {
709     return newTypedArrayWithSize<JSUint16Array>(exec, structure, length);
710 }
711
712 char* JIT_OPERATION operationNewUint16ArrayWithOneArgument(
713     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
714 {
715     return newTypedArrayWithOneArgument<JSUint16Array>(exec, structure, encodedValue);
716 }
717
718 char* JIT_OPERATION operationNewUint32ArrayWithSize(
719     ExecState* exec, Structure* structure, int32_t length)
720 {
721     return newTypedArrayWithSize<JSUint32Array>(exec, structure, length);
722 }
723
724 char* JIT_OPERATION operationNewUint32ArrayWithOneArgument(
725     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
726 {
727     return newTypedArrayWithOneArgument<JSUint32Array>(exec, structure, encodedValue);
728 }
729
730 char* JIT_OPERATION operationNewFloat32ArrayWithSize(
731     ExecState* exec, Structure* structure, int32_t length)
732 {
733     return newTypedArrayWithSize<JSFloat32Array>(exec, structure, length);
734 }
735
736 char* JIT_OPERATION operationNewFloat32ArrayWithOneArgument(
737     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
738 {
739     return newTypedArrayWithOneArgument<JSFloat32Array>(exec, structure, encodedValue);
740 }
741
742 char* JIT_OPERATION operationNewFloat64ArrayWithSize(
743     ExecState* exec, Structure* structure, int32_t length)
744 {
745     return newTypedArrayWithSize<JSFloat64Array>(exec, structure, length);
746 }
747
748 char* JIT_OPERATION operationNewFloat64ArrayWithOneArgument(
749     ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
750 {
751     return newTypedArrayWithOneArgument<JSFloat64Array>(exec, structure, encodedValue);
752 }
753
754 JSCell* JIT_OPERATION operationCreateInlinedArguments(
755     ExecState* exec, InlineCallFrame* inlineCallFrame)
756 {
757     VM& vm = exec->vm();
758     NativeCallFrameTracer tracer(&vm, exec);
759     // NB: This needs to be exceedingly careful with top call frame tracking, since it
760     // may be called from OSR exit, while the state of the call stack is bizarre.
761     Arguments* result = Arguments::create(vm, exec, inlineCallFrame);
762     ASSERT(!vm.exception());
763     return result;
764 }
765
766 void JIT_OPERATION operationTearOffInlinedArguments(
767     ExecState* exec, JSCell* argumentsCell, JSCell* activationCell, InlineCallFrame* inlineCallFrame)
768 {
769     ASSERT_UNUSED(activationCell, !activationCell); // Currently, we don't inline functions with activations.
770     jsCast<Arguments*>(argumentsCell)->tearOff(exec, inlineCallFrame);
771 }
772
773 EncodedJSValue JIT_OPERATION operationGetArgumentByVal(ExecState* exec, int32_t argumentsRegister, int32_t index)
774 {
775     VM& vm = exec->vm();
776     NativeCallFrameTracer tracer(&vm, exec);
777
778     JSValue argumentsValue = exec->uncheckedR(argumentsRegister).jsValue();
779     
780     // If there are no arguments, and we're accessing out of bounds, then we have to create the
781     // arguments in case someone has installed a getter on a numeric property.
782     if (!argumentsValue)
783         exec->uncheckedR(argumentsRegister) = argumentsValue = Arguments::create(exec->vm(), exec);
784     
785     return JSValue::encode(argumentsValue.get(exec, index));
786 }
787
788 EncodedJSValue JIT_OPERATION operationGetInlinedArgumentByVal(
789     ExecState* exec, int32_t argumentsRegister, InlineCallFrame* inlineCallFrame, 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 =
800             Arguments::create(exec->vm(), exec, inlineCallFrame);
801     }
802     
803     return JSValue::encode(argumentsValue.get(exec, index));
804 }
805
806 JSCell* JIT_OPERATION operationNewFunctionNoCheck(ExecState* exec, JSCell* functionExecutable)
807 {
808     ASSERT(functionExecutable->inherits(FunctionExecutable::info()));
809     VM& vm = exec->vm();
810     NativeCallFrameTracer tracer(&vm, exec);
811     return JSFunction::create(vm, static_cast<FunctionExecutable*>(functionExecutable), exec->scope());
812 }
813
814 size_t JIT_OPERATION operationIsObject(ExecState* exec, EncodedJSValue value)
815 {
816     return jsIsObjectType(exec, JSValue::decode(value));
817 }
818
819 size_t JIT_OPERATION operationIsFunction(EncodedJSValue value)
820 {
821     return jsIsFunctionType(JSValue::decode(value));
822 }
823
824 JSCell* JIT_OPERATION operationTypeOf(ExecState* exec, JSCell* value)
825 {
826     return jsTypeStringForValue(exec, JSValue(value)).asCell();
827 }
828
829 char* JIT_OPERATION operationAllocatePropertyStorageWithInitialCapacity(ExecState* exec)
830 {
831     VM& vm = exec->vm();
832     NativeCallFrameTracer tracer(&vm, exec);
833
834     return reinterpret_cast<char*>(
835         Butterfly::createUninitialized(vm, 0, 0, initialOutOfLineCapacity, false, 0));
836 }
837
838 char* JIT_OPERATION operationAllocatePropertyStorage(ExecState* exec, size_t newSize)
839 {
840     VM& vm = exec->vm();
841     NativeCallFrameTracer tracer(&vm, exec);
842
843     return reinterpret_cast<char*>(
844         Butterfly::createUninitialized(vm, 0, 0, newSize, false, 0));
845 }
846
847 char* JIT_OPERATION operationReallocateButterflyToHavePropertyStorageWithInitialCapacity(ExecState* exec, JSObject* object)
848 {
849     VM& vm = exec->vm();
850     NativeCallFrameTracer tracer(&vm, exec);
851
852     ASSERT(!object->structure()->outOfLineCapacity());
853     DeferGC deferGC(vm.heap);
854     Butterfly* result = object->growOutOfLineStorage(vm, 0, initialOutOfLineCapacity);
855     object->setButterflyWithoutChangingStructure(vm, result);
856     return reinterpret_cast<char*>(result);
857 }
858
859 char* JIT_OPERATION operationReallocateButterflyToGrowPropertyStorage(ExecState* exec, JSObject* object, size_t newSize)
860 {
861     VM& vm = exec->vm();
862     NativeCallFrameTracer tracer(&vm, exec);
863
864     DeferGC deferGC(vm.heap);
865     Butterfly* result = object->growOutOfLineStorage(vm, object->structure()->outOfLineCapacity(), newSize);
866     object->setButterflyWithoutChangingStructure(vm, result);
867     return reinterpret_cast<char*>(result);
868 }
869
870 char* JIT_OPERATION operationEnsureInt32(ExecState* exec, JSCell* cell)
871 {
872     VM& vm = exec->vm();
873     NativeCallFrameTracer tracer(&vm, exec);
874     
875     if (!cell->isObject())
876         return 0;
877     
878     return reinterpret_cast<char*>(asObject(cell)->ensureInt32(vm).data());
879 }
880
881 char* JIT_OPERATION operationEnsureDouble(ExecState* exec, JSCell* cell)
882 {
883     VM& vm = exec->vm();
884     NativeCallFrameTracer tracer(&vm, exec);
885     
886     if (!cell->isObject())
887         return 0;
888     
889     return reinterpret_cast<char*>(asObject(cell)->ensureDouble(vm).data());
890 }
891
892 char* JIT_OPERATION operationEnsureContiguous(ExecState* exec, JSCell* cell)
893 {
894     VM& vm = exec->vm();
895     NativeCallFrameTracer tracer(&vm, exec);
896     
897     if (!cell->isObject())
898         return 0;
899     
900     return reinterpret_cast<char*>(asObject(cell)->ensureContiguous(vm).data());
901 }
902
903 char* JIT_OPERATION operationRageEnsureContiguous(ExecState* exec, JSCell* cell)
904 {
905     VM& vm = exec->vm();
906     NativeCallFrameTracer tracer(&vm, exec);
907     
908     if (!cell->isObject())
909         return 0;
910     
911     return reinterpret_cast<char*>(asObject(cell)->rageEnsureContiguous(vm).data());
912 }
913
914 char* JIT_OPERATION operationEnsureArrayStorage(ExecState* exec, JSCell* cell)
915 {
916     VM& vm = exec->vm();
917     NativeCallFrameTracer tracer(&vm, exec);
918     
919     if (!cell->isObject())
920         return 0;
921
922     return reinterpret_cast<char*>(asObject(cell)->ensureArrayStorage(vm));
923 }
924
925 StringImpl* JIT_OPERATION operationResolveRope(ExecState* exec, JSString* string)
926 {
927     VM& vm = exec->vm();
928     NativeCallFrameTracer tracer(&vm, exec);
929
930     return string->value(exec).impl();
931 }
932
933 JSString* JIT_OPERATION operationSingleCharacterString(ExecState* exec, int32_t character)
934 {
935     VM& vm = exec->vm();
936     NativeCallFrameTracer tracer(&vm, exec);
937     
938     return jsSingleCharacterString(exec, static_cast<UChar>(character));
939 }
940
941 JSCell* JIT_OPERATION operationNewStringObject(ExecState* exec, JSString* string, Structure* structure)
942 {
943     VM& vm = exec->vm();
944     NativeCallFrameTracer tracer(&vm, exec);
945     
946     return StringObject::create(vm, structure, string);
947 }
948
949 JSCell* JIT_OPERATION operationToStringOnCell(ExecState* exec, JSCell* cell)
950 {
951     VM& vm = exec->vm();
952     NativeCallFrameTracer tracer(&vm, exec);
953     
954     return JSValue(cell).toString(exec);
955 }
956
957 JSCell* JIT_OPERATION operationToString(ExecState* exec, EncodedJSValue value)
958 {
959     VM& vm = exec->vm();
960     NativeCallFrameTracer tracer(&vm, exec);
961
962     return JSValue::decode(value).toString(exec);
963 }
964
965 JSCell* JIT_OPERATION operationMakeRope2(ExecState* exec, JSString* left, JSString* right)
966 {
967     VM& vm = exec->vm();
968     NativeCallFrameTracer tracer(&vm, exec);
969
970     return JSRopeString::create(vm, left, right);
971 }
972
973 JSCell* JIT_OPERATION operationMakeRope3(ExecState* exec, JSString* a, JSString* b, JSString* c)
974 {
975     VM& vm = exec->vm();
976     NativeCallFrameTracer tracer(&vm, exec);
977
978     return JSRopeString::create(vm, a, b, c);
979 }
980
981 char* JIT_OPERATION operationFindSwitchImmTargetForDouble(
982     ExecState* exec, EncodedJSValue encodedValue, size_t tableIndex)
983 {
984     CodeBlock* codeBlock = exec->codeBlock();
985     SimpleJumpTable& table = codeBlock->switchJumpTable(tableIndex);
986     JSValue value = JSValue::decode(encodedValue);
987     ASSERT(value.isDouble());
988     double asDouble = value.asDouble();
989     int32_t asInt32 = static_cast<int32_t>(asDouble);
990     if (asDouble == asInt32)
991         return static_cast<char*>(table.ctiForValue(asInt32).executableAddress());
992     return static_cast<char*>(table.ctiDefault.executableAddress());
993 }
994
995 char* JIT_OPERATION operationSwitchString(ExecState* exec, size_t tableIndex, JSString* string)
996 {
997     VM& vm = exec->vm();
998     NativeCallFrameTracer tracer(&vm, exec);
999
1000     return static_cast<char*>(exec->codeBlock()->stringSwitchJumpTable(tableIndex).ctiForValue(string->value(exec).impl()).executableAddress());
1001 }
1002
1003 void JIT_OPERATION operationInvalidate(ExecState* exec, VariableWatchpointSet* set)
1004 {
1005     VM& vm = exec->vm();
1006     NativeCallFrameTracer tracer(&vm, exec);
1007
1008     set->invalidate();
1009 }
1010
1011 double JIT_OPERATION operationFModOnInts(int32_t a, int32_t b)
1012 {
1013     return fmod(a, b);
1014 }
1015
1016 JSCell* JIT_OPERATION operationStringFromCharCode(ExecState* exec, int32_t op1)
1017 {
1018     VM* vm = &exec->vm();
1019     NativeCallFrameTracer tracer(vm, exec);
1020     return JSC::stringFromCharCode(exec, op1);
1021 }
1022
1023 size_t JIT_OPERATION dfgConvertJSValueToInt32(ExecState* exec, EncodedJSValue value)
1024 {
1025     VM* vm = &exec->vm();
1026     NativeCallFrameTracer tracer(vm, exec);
1027     
1028     // toInt32/toUInt32 return the same value; we want the value zero extended to fill the register.
1029     return JSValue::decode(value).toUInt32(exec);
1030 }
1031
1032 void JIT_OPERATION debugOperationPrintSpeculationFailure(ExecState* exec, void* debugInfoRaw, void* scratch)
1033 {
1034     VM* vm = &exec->vm();
1035     NativeCallFrameTracer tracer(vm, exec);
1036     
1037     SpeculationFailureDebugInfo* debugInfo = static_cast<SpeculationFailureDebugInfo*>(debugInfoRaw);
1038     CodeBlock* codeBlock = debugInfo->codeBlock;
1039     CodeBlock* alternative = codeBlock->alternative();
1040     dataLog(
1041         "Speculation failure in ", *codeBlock, " with ");
1042     if (alternative) {
1043         dataLog(
1044             "executeCounter = ", alternative->jitExecuteCounter(),
1045             ", reoptimizationRetryCounter = ", alternative->reoptimizationRetryCounter(),
1046             ", optimizationDelayCounter = ", alternative->optimizationDelayCounter());
1047     } else
1048         dataLog("no alternative code block (i.e. we've been jettisoned)");
1049     dataLog(", osrExitCounter = ", codeBlock->osrExitCounter(), "\n");
1050     dataLog("    GPRs at time of exit:");
1051     char* scratchPointer = static_cast<char*>(scratch);
1052     for (unsigned i = 0; i < GPRInfo::numberOfRegisters; ++i) {
1053         GPRReg gpr = GPRInfo::toRegister(i);
1054         dataLog(" ", GPRInfo::debugName(gpr), ":", RawPointer(*reinterpret_cast_ptr<void**>(scratchPointer)));
1055         scratchPointer += sizeof(EncodedJSValue);
1056     }
1057     dataLog("\n");
1058     dataLog("    FPRs at time of exit:");
1059     for (unsigned i = 0; i < FPRInfo::numberOfRegisters; ++i) {
1060         FPRReg fpr = FPRInfo::toRegister(i);
1061         dataLog(" ", FPRInfo::debugName(fpr), ":");
1062         uint64_t bits = *reinterpret_cast_ptr<uint64_t*>(scratchPointer);
1063         double value = *reinterpret_cast_ptr<double*>(scratchPointer);
1064         dataLogF("%llx:%lf", static_cast<long long>(bits), value);
1065         scratchPointer += sizeof(EncodedJSValue);
1066     }
1067     dataLog("\n");
1068 }
1069
1070 extern "C" void JIT_OPERATION triggerReoptimizationNow(CodeBlock* codeBlock)
1071 {
1072     // It's sort of preferable that we don't GC while in here. Anyways, doing so wouldn't
1073     // really be profitable.
1074     DeferGCForAWhile deferGC(codeBlock->vm()->heap);
1075     
1076     if (Options::verboseOSR())
1077         dataLog(*codeBlock, ": Entered reoptimize\n");
1078     // We must be called with the baseline code block.
1079     ASSERT(JITCode::isBaselineCode(codeBlock->jitType()));
1080
1081     // If I am my own replacement, then reoptimization has already been triggered.
1082     // This can happen in recursive functions.
1083     if (codeBlock->replacement() == codeBlock) {
1084         if (Options::verboseOSR())
1085             dataLog(*codeBlock, ": Not reoptimizing because we've already been jettisoned.\n");
1086         return;
1087     }
1088     
1089     // Otherwise, the replacement must be optimized code. Use this as an opportunity
1090     // to check our logic.
1091     ASSERT(codeBlock->hasOptimizedReplacement());
1092     CodeBlock* optimizedCodeBlock = codeBlock->replacement();
1093     ASSERT(JITCode::isOptimizingJIT(optimizedCodeBlock->jitType()));
1094
1095     // In order to trigger reoptimization, one of two things must have happened:
1096     // 1) We exited more than some number of times.
1097     // 2) We exited and got stuck in a loop, and now we're exiting again.
1098     bool didExitABunch = optimizedCodeBlock->shouldReoptimizeNow();
1099     bool didGetStuckInLoop =
1100         codeBlock->checkIfOptimizationThresholdReached()
1101         && optimizedCodeBlock->shouldReoptimizeFromLoopNow();
1102     
1103     if (!didExitABunch && !didGetStuckInLoop) {
1104         if (Options::verboseOSR())
1105             dataLog(*codeBlock, ": Not reoptimizing ", *optimizedCodeBlock, " because it either didn't exit enough or didn't loop enough after exit.\n");
1106         codeBlock->optimizeAfterLongWarmUp();
1107         return;
1108     }
1109
1110     optimizedCodeBlock->jettison(CountReoptimization);
1111 }
1112
1113 #if ENABLE(FTL_JIT)
1114 void JIT_OPERATION triggerTierUpNow(ExecState* exec)
1115 {
1116     VM* vm = &exec->vm();
1117     NativeCallFrameTracer tracer(vm, exec);
1118     DeferGC deferGC(vm->heap);
1119     CodeBlock* codeBlock = exec->codeBlock();
1120     
1121     JITCode* jitCode = codeBlock->jitCode()->dfg();
1122     
1123     if (Options::verboseOSR()) {
1124         dataLog(
1125             *codeBlock, ": Entered triggerTierUpNow with executeCounter = ",
1126             jitCode->tierUpCounter, "\n");
1127     }
1128     
1129     if (codeBlock->baselineVersion()->m_didFailFTLCompilation) {
1130         if (Options::verboseOSR())
1131             dataLog("Deferring FTL-optimization of ", *codeBlock, " indefinitely because there was an FTL failure.\n");
1132         jitCode->dontOptimizeAnytimeSoon(codeBlock);
1133         return;
1134     }
1135     
1136     if (!jitCode->checkIfOptimizationThresholdReached(codeBlock)) {
1137         if (Options::verboseOSR())
1138             dataLog("Choosing not to FTL-optimize ", *codeBlock, " yet.\n");
1139         return;
1140     }
1141     
1142     Worklist::State worklistState;
1143     if (Worklist* worklist = vm->worklist.get()) {
1144         worklistState = worklist->completeAllReadyPlansForVM(
1145             *vm, CompilationKey(codeBlock->baselineVersion(), FTLMode));
1146     } else
1147         worklistState = Worklist::NotKnown;
1148     
1149     if (worklistState == Worklist::Compiling) {
1150         jitCode->setOptimizationThresholdBasedOnCompilationResult(
1151             codeBlock, CompilationDeferred);
1152         return;
1153     }
1154     
1155     if (codeBlock->hasOptimizedReplacement()) {
1156         // That's great, we've compiled the code - next time we call this function,
1157         // we'll enter that replacement.
1158         jitCode->optimizeSoon(codeBlock);
1159         return;
1160     }
1161     
1162     if (worklistState == Worklist::Compiled) {
1163         // This means that we finished compiling, but failed somehow; in that case the
1164         // thresholds will be set appropriately.
1165         if (Options::verboseOSR())
1166             dataLog("Code block ", *codeBlock, " was compiled but it doesn't have an optimized replacement.\n");
1167         return;
1168     }
1169
1170     // We need to compile the code.
1171     compile(
1172         *vm, codeBlock->newReplacement().get(), FTLMode, UINT_MAX, Operands<JSValue>(),
1173         ToFTLDeferredCompilationCallback::create(codeBlock), vm->ensureWorklist());
1174 }
1175
1176 char* JIT_OPERATION triggerOSREntryNow(
1177     ExecState* exec, int32_t bytecodeIndex, int32_t streamIndex)
1178 {
1179     VM* vm = &exec->vm();
1180     NativeCallFrameTracer tracer(vm, exec);
1181     DeferGC deferGC(vm->heap);
1182     CodeBlock* codeBlock = exec->codeBlock();
1183     
1184     JITCode* jitCode = codeBlock->jitCode()->dfg();
1185     
1186     if (Options::verboseOSR()) {
1187         dataLog(
1188             *codeBlock, ": Entered triggerTierUpNow with executeCounter = ",
1189             jitCode->tierUpCounter, "\n");
1190     }
1191     
1192     if (codeBlock->baselineVersion()->m_didFailFTLCompilation) {
1193         if (Options::verboseOSR())
1194             dataLog("Deferring FTL-optimization of ", *codeBlock, " indefinitely because there was an FTL failure.\n");
1195         jitCode->dontOptimizeAnytimeSoon(codeBlock);
1196         return 0;
1197     }
1198     
1199     if (!jitCode->checkIfOptimizationThresholdReached(codeBlock)) {
1200         if (Options::verboseOSR())
1201             dataLog("Choosing not to FTL-optimize ", *codeBlock, " yet.\n");
1202         return 0;
1203     }
1204     
1205     Worklist::State worklistState;
1206     if (Worklist* worklist = vm->worklist.get()) {
1207         worklistState = worklist->completeAllReadyPlansForVM(
1208             *vm, CompilationKey(codeBlock->baselineVersion(), FTLForOSREntryMode));
1209     } else
1210         worklistState = Worklist::NotKnown;
1211     
1212     if (worklistState == Worklist::Compiling) {
1213         ASSERT(!jitCode->osrEntryBlock);
1214         jitCode->setOptimizationThresholdBasedOnCompilationResult(
1215             codeBlock, CompilationDeferred);
1216         return 0;
1217     }
1218     
1219     if (CodeBlock* entryBlock = jitCode->osrEntryBlock.get()) {
1220         void* address = FTL::prepareOSREntry(
1221             exec, codeBlock, entryBlock, bytecodeIndex, streamIndex);
1222         if (address) {
1223             jitCode->optimizeSoon(codeBlock);
1224             return static_cast<char*>(address);
1225         }
1226         
1227         FTL::ForOSREntryJITCode* entryCode = entryBlock->jitCode()->ftlForOSREntry();
1228         entryCode->countEntryFailure();
1229         if (entryCode->entryFailureCount() <
1230             Options::ftlOSREntryFailureCountForReoptimization()) {
1231             
1232             jitCode->optimizeSoon(codeBlock);
1233             return 0;
1234         }
1235         
1236         // OSR entry failed. Oh no! This implies that we need to retry. We retry
1237         // without exponential backoff and we only do this for the entry code block.
1238         jitCode->osrEntryBlock.clear();
1239         
1240         jitCode->optimizeAfterWarmUp(codeBlock);
1241         return 0;
1242     }
1243     
1244     if (worklistState == Worklist::Compiled) {
1245         // This means that compilation failed and we already set the thresholds.
1246         if (Options::verboseOSR())
1247             dataLog("Code block ", *codeBlock, " was compiled but it doesn't have an optimized replacement.\n");
1248         return 0;
1249     }
1250
1251     // The first order of business is to trigger a for-entry compile.
1252     Operands<JSValue> mustHandleValues;
1253     jitCode->reconstruct(
1254         exec, codeBlock, CodeOrigin(bytecodeIndex), streamIndex, mustHandleValues);
1255     CompilationResult forEntryResult = DFG::compile(
1256         *vm, codeBlock->newReplacement().get(), FTLForOSREntryMode, bytecodeIndex,
1257         mustHandleValues, ToFTLForOSREntryDeferredCompilationCallback::create(codeBlock),
1258         vm->ensureWorklist());
1259     
1260     // But we also want to trigger a replacement compile. Of course, we don't want to
1261     // trigger it if we don't need to. Note that this is kind of weird because we might
1262     // have just finished an FTL compile and that compile failed or was invalidated.
1263     // But this seems uncommon enough that we sort of don't care. It's certainly sound
1264     // to fire off another compile right now so long as we're not already compiling and
1265     // we don't already have an optimized replacement. Note, we don't do this for
1266     // obviously bad cases like global code, where we know that there is a slim chance
1267     // of this code being invoked ever again.
1268     CompilationKey keyForReplacement(codeBlock->baselineVersion(), FTLMode);
1269     if (codeBlock->codeType() != GlobalCode
1270         && !codeBlock->hasOptimizedReplacement()
1271         && (!vm->worklist.get()
1272             || vm->worklist->compilationState(keyForReplacement) == Worklist::NotKnown)) {
1273         compile(
1274             *vm, codeBlock->newReplacement().get(), FTLMode, UINT_MAX, Operands<JSValue>(),
1275             ToFTLDeferredCompilationCallback::create(codeBlock), vm->ensureWorklist());
1276     }
1277     
1278     if (forEntryResult != CompilationSuccessful)
1279         return 0;
1280     
1281     // It's possible that the for-entry compile already succeeded. In that case OSR
1282     // entry will succeed unless we ran out of stack. It's not clear what we should do.
1283     // We signal to try again after a while if that happens.
1284     void* address = FTL::prepareOSREntry(
1285         exec, codeBlock, jitCode->osrEntryBlock.get(), bytecodeIndex, streamIndex);
1286     if (address)
1287         jitCode->optimizeSoon(codeBlock);
1288     else
1289         jitCode->optimizeAfterWarmUp(codeBlock);
1290     return static_cast<char*>(address);
1291 }
1292
1293 // FIXME: Make calls work well. Currently they're a pure regression.
1294 // https://bugs.webkit.org/show_bug.cgi?id=113621
1295 EncodedJSValue JIT_OPERATION operationFTLCall(ExecState* exec)
1296 {
1297     ExecState* callerExec = exec->callerFrame();
1298     
1299     VM* vm = &callerExec->vm();
1300     NativeCallFrameTracer tracer(vm, callerExec);
1301     
1302     JSValue callee = exec->calleeAsValue();
1303     CallData callData;
1304     CallType callType = getCallData(callee, callData);
1305     if (callType == CallTypeNone) {
1306         vm->throwException(callerExec, createNotAFunctionError(callerExec, callee));
1307         return JSValue::encode(jsUndefined());
1308     }
1309     
1310     return JSValue::encode(call(callerExec, callee, callType, callData, exec->thisValue(), exec));
1311 }
1312
1313 // FIXME: Make calls work well. Currently they're a pure regression.
1314 // https://bugs.webkit.org/show_bug.cgi?id=113621
1315 EncodedJSValue JIT_OPERATION operationFTLConstruct(ExecState* exec)
1316 {
1317     ExecState* callerExec = exec->callerFrame();
1318     
1319     VM* vm = &callerExec->vm();
1320     NativeCallFrameTracer tracer(vm, callerExec);
1321     
1322     JSValue callee = exec->calleeAsValue();
1323     ConstructData constructData;
1324     ConstructType constructType = getConstructData(callee, constructData);
1325     if (constructType == ConstructTypeNone) {
1326         vm->throwException(callerExec, createNotAFunctionError(callerExec, callee));
1327         return JSValue::encode(jsUndefined());
1328     }
1329     
1330     return JSValue::encode(construct(callerExec, callee, constructType, constructData, exec));
1331 }
1332 #endif // ENABLE(FTL_JIT)
1333
1334 } // extern "C"
1335 } } // namespace JSC::DFG
1336
1337 #endif // ENABLE(DFG_JIT)
1338
1339 #endif // ENABLE(JIT)