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