2 * Copyright (C) 2011, 2013, 2014 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
27 #include "DFGOperations.h"
29 #include "Arguments.h"
30 #include "ButterflyInlines.h"
31 #include "CodeBlock.h"
32 #include "CommonSlowPaths.h"
33 #include "CopiedSpaceInlines.h"
34 #include "DFGDriver.h"
35 #include "DFGJITCode.h"
36 #include "DFGOSRExit.h"
37 #include "DFGThunks.h"
38 #include "DFGToFTLDeferredCompilationCallback.h"
39 #include "DFGToFTLForOSREntryDeferredCompilationCallback.h"
40 #include "DFGWorklist.h"
41 #include "FTLForOSREntryJITCode.h"
42 #include "FTLOSREntry.h"
43 #include "HostCallReturnValue.h"
44 #include "GetterSetter.h"
45 #include "Interpreter.h"
47 #include "JITExceptions.h"
48 #include "JSActivation.h"
50 #include "JSNameScope.h"
51 #include "NameInstance.h"
52 #include "ObjectConstructor.h"
53 #include "JSCInlines.h"
55 #include "StringConstructor.h"
56 #include "TypedArrayInlines.h"
57 #include <wtf/InlineASM.h>
62 namespace JSC
{ namespace DFG
{
64 template<bool strict
, bool direct
>
65 static inline void putByVal(ExecState
* exec
, JSValue baseValue
, uint32_t index
, JSValue value
)
68 NativeCallFrameTracer
tracer(&vm
, exec
);
70 RELEASE_ASSERT(baseValue
.isObject());
71 asObject(baseValue
)->putDirectIndex(exec
, index
, value
, 0, strict
? PutDirectIndexShouldThrow
: PutDirectIndexShouldNotThrow
);
74 if (baseValue
.isObject()) {
75 JSObject
* object
= asObject(baseValue
);
76 if (object
->canSetIndexQuickly(index
)) {
77 object
->setIndexQuickly(vm
, index
, value
);
81 object
->methodTable(vm
)->putByIndex(object
, exec
, index
, value
, strict
);
85 baseValue
.putByIndex(exec
, index
, value
, strict
);
88 template<bool strict
, bool direct
>
89 ALWAYS_INLINE
static void JIT_OPERATION
operationPutByValInternal(ExecState
* exec
, EncodedJSValue encodedBase
, EncodedJSValue encodedProperty
, EncodedJSValue encodedValue
)
92 NativeCallFrameTracer
tracer(vm
, exec
);
94 JSValue baseValue
= JSValue::decode(encodedBase
);
95 JSValue property
= JSValue::decode(encodedProperty
);
96 JSValue value
= JSValue::decode(encodedValue
);
98 if (LIKELY(property
.isUInt32())) {
99 putByVal
<strict
, direct
>(exec
, baseValue
, property
.asUInt32(), value
);
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
);
112 if (isName(property
)) {
113 PutPropertySlot
slot(baseValue
, strict
);
115 RELEASE_ASSERT(baseValue
.isObject());
116 asObject(baseValue
)->putDirect(*vm
, jsCast
<NameInstance
*>(property
.asCell())->privateName(), value
, slot
);
118 baseValue
.put(exec
, jsCast
<NameInstance
*>(property
.asCell())->privateName(), value
, slot
);
122 // Don't put to an object if toString throws an exception.
123 Identifier ident
= property
.toString(exec
)->toIdentifier(exec
);
124 if (!vm
->exception()) {
125 PutPropertySlot
slot(baseValue
, strict
);
127 RELEASE_ASSERT(baseValue
.isObject());
128 asObject(baseValue
)->putDirect(*vm
, jsCast
<NameInstance
*>(property
.asCell())->privateName(), value
, slot
);
130 baseValue
.put(exec
, ident
, value
, slot
);
134 template<typename ViewClass
>
135 char* newTypedArrayWithSize(ExecState
* exec
, Structure
* structure
, int32_t size
)
138 NativeCallFrameTracer
tracer(&vm
, exec
);
140 vm
.throwException(exec
, createRangeError(exec
, "Requested length is negative"));
143 return bitwise_cast
<char*>(ViewClass::create(exec
, structure
, size
));
146 template<typename ViewClass
>
147 char* newTypedArrayWithOneArgument(
148 ExecState
* exec
, Structure
* structure
, EncodedJSValue encodedValue
)
151 NativeCallFrameTracer
tracer(&vm
, exec
);
153 JSValue value
= JSValue::decode(encodedValue
);
155 if (JSArrayBuffer
* jsBuffer
= jsDynamicCast
<JSArrayBuffer
*>(value
)) {
156 RefPtr
<ArrayBuffer
> buffer
= jsBuffer
->impl();
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"));
162 return bitwise_cast
<char*>(
164 exec
, structure
, buffer
, 0, buffer
->byteLength() / ViewClass::elementSize
));
167 if (JSObject
* object
= jsDynamicCast
<JSObject
*>(value
)) {
168 unsigned length
= object
->get(exec
, vm
.propertyNames
->length
).toUInt32(exec
);
169 if (exec
->hadException())
172 ViewClass
* result
= ViewClass::createUninitialized(exec
, structure
, length
);
176 if (!result
->set(exec
, object
, 0, length
))
179 return bitwise_cast
<char*>(result
);
184 length
= value
.asInt32();
185 else if (!value
.isNumber()) {
186 vm
.throwException(exec
, createTypeError(exec
, "Invalid array length argument"));
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)"));
197 vm
.throwException(exec
, createRangeError(exec
, "Requested length is negative"));
201 return bitwise_cast
<char*>(ViewClass::create(exec
, structure
, length
));
206 EncodedJSValue JIT_OPERATION
operationToThis(ExecState
* exec
, EncodedJSValue encodedOp
)
208 VM
* vm
= &exec
->vm();
209 NativeCallFrameTracer
tracer(vm
, exec
);
211 return JSValue::encode(JSValue::decode(encodedOp
).toThis(exec
, NotStrictMode
));
214 EncodedJSValue JIT_OPERATION
operationToThisStrict(ExecState
* exec
, EncodedJSValue encodedOp
)
216 VM
* vm
= &exec
->vm();
217 NativeCallFrameTracer
tracer(vm
, exec
);
219 return JSValue::encode(JSValue::decode(encodedOp
).toThis(exec
, StrictMode
));
222 JSCell
* JIT_OPERATION
operationCreateThis(ExecState
* exec
, JSObject
* constructor
, int32_t inlineCapacity
)
225 NativeCallFrameTracer
tracer(&vm
, exec
);
228 ConstructData constructData
;
229 ASSERT(jsCast
<JSFunction
*>(constructor
)->methodTable(vm
)->getConstructData(jsCast
<JSFunction
*>(constructor
), constructData
) == ConstructTypeJS
);
232 return constructEmptyObject(exec
, jsCast
<JSFunction
*>(constructor
)->allocationProfile(exec
, inlineCapacity
)->structure());
235 EncodedJSValue JIT_OPERATION
operationValueAdd(ExecState
* exec
, EncodedJSValue encodedOp1
, EncodedJSValue encodedOp2
)
237 VM
* vm
= &exec
->vm();
238 NativeCallFrameTracer
tracer(vm
, exec
);
240 JSValue op1
= JSValue::decode(encodedOp1
);
241 JSValue op2
= JSValue::decode(encodedOp2
);
243 return JSValue::encode(jsAdd(exec
, op1
, op2
));
246 EncodedJSValue JIT_OPERATION
operationValueAddNotNumber(ExecState
* exec
, EncodedJSValue encodedOp1
, EncodedJSValue encodedOp2
)
248 VM
* vm
= &exec
->vm();
249 NativeCallFrameTracer
tracer(vm
, exec
);
251 JSValue op1
= JSValue::decode(encodedOp1
);
252 JSValue op2
= JSValue::decode(encodedOp2
);
254 ASSERT(!op1
.isNumber() || !op2
.isNumber());
256 if (op1
.isString() && !op2
.isObject())
257 return JSValue::encode(jsString(exec
, asString(op1
), op2
.toString(exec
)));
259 return JSValue::encode(jsAddSlowCase(exec
, op1
, op2
));
262 static ALWAYS_INLINE EncodedJSValue
getByVal(ExecState
* exec
, JSCell
* base
, uint32_t index
)
265 NativeCallFrameTracer
tracer(&vm
, exec
);
267 if (base
->isObject()) {
268 JSObject
* object
= asObject(base
);
269 if (object
->canGetIndexQuickly(index
))
270 return JSValue::encode(object
->getIndexQuickly(index
));
273 if (isJSString(base
) && asString(base
)->canGetIndex(index
))
274 return JSValue::encode(asString(base
)->getIndex(exec
, index
));
276 return JSValue::encode(JSValue(base
).get(exec
, index
));
279 EncodedJSValue JIT_OPERATION
operationGetByVal(ExecState
* exec
, EncodedJSValue encodedBase
, EncodedJSValue encodedProperty
)
282 NativeCallFrameTracer
tracer(&vm
, exec
);
284 JSValue baseValue
= JSValue::decode(encodedBase
);
285 JSValue property
= JSValue::decode(encodedProperty
);
287 if (LIKELY(baseValue
.isCell())) {
288 JSCell
* base
= baseValue
.asCell();
290 if (property
.isUInt32()) {
291 return getByVal(exec
, base
, property
.asUInt32());
292 } else if (property
.isDouble()) {
293 double propertyAsDouble
= property
.asDouble();
294 uint32_t propertyAsUInt32
= static_cast<uint32_t>(propertyAsDouble
);
295 if (propertyAsUInt32
== propertyAsDouble
)
296 return getByVal(exec
, base
, propertyAsUInt32
);
297 } else if (property
.isString()) {
298 Structure
& structure
= *base
->structure(vm
);
299 if (JSCell::canUseFastGetOwnProperty(structure
)) {
300 if (JSValue result
= base
->fastGetOwnProperty(vm
, structure
, asString(property
)->value(exec
)))
301 return JSValue::encode(result
);
306 if (isName(property
))
307 return JSValue::encode(baseValue
.get(exec
, jsCast
<NameInstance
*>(property
.asCell())->privateName()));
309 Identifier ident
= property
.toString(exec
)->toIdentifier(exec
);
310 return JSValue::encode(baseValue
.get(exec
, ident
));
313 EncodedJSValue JIT_OPERATION
operationGetByValCell(ExecState
* exec
, JSCell
* base
, EncodedJSValue encodedProperty
)
316 NativeCallFrameTracer
tracer(&vm
, exec
);
318 JSValue property
= JSValue::decode(encodedProperty
);
320 if (property
.isUInt32())
321 return getByVal(exec
, base
, property
.asUInt32());
322 if (property
.isDouble()) {
323 double propertyAsDouble
= property
.asDouble();
324 uint32_t propertyAsUInt32
= static_cast<uint32_t>(propertyAsDouble
);
325 if (propertyAsUInt32
== propertyAsDouble
)
326 return getByVal(exec
, base
, propertyAsUInt32
);
327 } else if (property
.isString()) {
328 Structure
& structure
= *base
->structure(vm
);
329 if (JSCell::canUseFastGetOwnProperty(structure
)) {
330 if (JSValue result
= base
->fastGetOwnProperty(vm
, structure
, asString(property
)->value(exec
)))
331 return JSValue::encode(result
);
335 if (isName(property
))
336 return JSValue::encode(JSValue(base
).get(exec
, jsCast
<NameInstance
*>(property
.asCell())->privateName()));
338 Identifier ident
= property
.toString(exec
)->toIdentifier(exec
);
339 return JSValue::encode(JSValue(base
).get(exec
, ident
));
342 ALWAYS_INLINE EncodedJSValue
getByValCellInt(ExecState
* exec
, JSCell
* base
, int32_t index
)
344 VM
* vm
= &exec
->vm();
345 NativeCallFrameTracer
tracer(vm
, exec
);
348 // Go the slowest way possible becase negative indices don't use indexed storage.
349 return JSValue::encode(JSValue(base
).get(exec
, Identifier::from(exec
, index
)));
352 // Use this since we know that the value is out of bounds.
353 return JSValue::encode(JSValue(base
).get(exec
, index
));
356 EncodedJSValue JIT_OPERATION
operationGetByValArrayInt(ExecState
* exec
, JSArray
* base
, int32_t index
)
358 return getByValCellInt(exec
, base
, index
);
361 EncodedJSValue JIT_OPERATION
operationGetByValStringInt(ExecState
* exec
, JSString
* base
, int32_t index
)
363 return getByValCellInt(exec
, base
, index
);
366 void JIT_OPERATION
operationPutByValStrict(ExecState
* exec
, EncodedJSValue encodedBase
, EncodedJSValue encodedProperty
, EncodedJSValue encodedValue
)
368 VM
* vm
= &exec
->vm();
369 NativeCallFrameTracer
tracer(vm
, exec
);
371 operationPutByValInternal
<true, false>(exec
, encodedBase
, encodedProperty
, encodedValue
);
374 void JIT_OPERATION
operationPutByValNonStrict(ExecState
* exec
, EncodedJSValue encodedBase
, EncodedJSValue encodedProperty
, EncodedJSValue encodedValue
)
376 VM
* vm
= &exec
->vm();
377 NativeCallFrameTracer
tracer(vm
, exec
);
379 operationPutByValInternal
<false, false>(exec
, encodedBase
, encodedProperty
, encodedValue
);
382 void JIT_OPERATION
operationPutByValCellStrict(ExecState
* exec
, JSCell
* cell
, EncodedJSValue encodedProperty
, EncodedJSValue encodedValue
)
384 VM
* vm
= &exec
->vm();
385 NativeCallFrameTracer
tracer(vm
, exec
);
387 operationPutByValInternal
<true, false>(exec
, JSValue::encode(cell
), encodedProperty
, encodedValue
);
390 void JIT_OPERATION
operationPutByValCellNonStrict(ExecState
* exec
, JSCell
* cell
, EncodedJSValue encodedProperty
, EncodedJSValue encodedValue
)
392 VM
* vm
= &exec
->vm();
393 NativeCallFrameTracer
tracer(vm
, exec
);
395 operationPutByValInternal
<false, false>(exec
, JSValue::encode(cell
), encodedProperty
, encodedValue
);
398 void JIT_OPERATION
operationPutByValBeyondArrayBoundsStrict(ExecState
* exec
, JSObject
* array
, int32_t index
, EncodedJSValue encodedValue
)
401 NativeCallFrameTracer
tracer(&vm
, exec
);
404 array
->putByIndexInline(exec
, index
, JSValue::decode(encodedValue
), true);
408 PutPropertySlot
slot(array
, true);
409 array
->methodTable()->put(
410 array
, exec
, Identifier::from(exec
, index
), JSValue::decode(encodedValue
), slot
);
413 void JIT_OPERATION
operationPutByValBeyondArrayBoundsNonStrict(ExecState
* exec
, JSObject
* array
, int32_t index
, EncodedJSValue encodedValue
)
415 VM
* vm
= &exec
->vm();
416 NativeCallFrameTracer
tracer(vm
, exec
);
419 array
->putByIndexInline(exec
, index
, JSValue::decode(encodedValue
), false);
423 PutPropertySlot
slot(array
, false);
424 array
->methodTable()->put(
425 array
, exec
, Identifier::from(exec
, index
), JSValue::decode(encodedValue
), slot
);
428 void JIT_OPERATION
operationPutDoubleByValBeyondArrayBoundsStrict(ExecState
* exec
, JSObject
* array
, int32_t index
, double value
)
430 VM
* vm
= &exec
->vm();
431 NativeCallFrameTracer
tracer(vm
, exec
);
433 JSValue jsValue
= JSValue(JSValue::EncodeAsDouble
, value
);
436 array
->putByIndexInline(exec
, index
, jsValue
, true);
440 PutPropertySlot
slot(array
, true);
441 array
->methodTable()->put(
442 array
, exec
, Identifier::from(exec
, index
), jsValue
, slot
);
445 void JIT_OPERATION
operationPutDoubleByValBeyondArrayBoundsNonStrict(ExecState
* exec
, JSObject
* array
, int32_t index
, double value
)
447 VM
* vm
= &exec
->vm();
448 NativeCallFrameTracer
tracer(vm
, exec
);
450 JSValue jsValue
= JSValue(JSValue::EncodeAsDouble
, value
);
453 array
->putByIndexInline(exec
, index
, jsValue
, false);
457 PutPropertySlot
slot(array
, false);
458 array
->methodTable()->put(
459 array
, exec
, Identifier::from(exec
, index
), jsValue
, slot
);
462 void JIT_OPERATION
operationPutByValDirectStrict(ExecState
* exec
, EncodedJSValue encodedBase
, EncodedJSValue encodedProperty
, EncodedJSValue encodedValue
)
464 VM
* vm
= &exec
->vm();
465 NativeCallFrameTracer
tracer(vm
, exec
);
467 operationPutByValInternal
<true, true>(exec
, encodedBase
, encodedProperty
, encodedValue
);
470 void JIT_OPERATION
operationPutByValDirectNonStrict(ExecState
* exec
, EncodedJSValue encodedBase
, EncodedJSValue encodedProperty
, EncodedJSValue encodedValue
)
472 VM
* vm
= &exec
->vm();
473 NativeCallFrameTracer
tracer(vm
, exec
);
475 operationPutByValInternal
<false, true>(exec
, encodedBase
, encodedProperty
, encodedValue
);
478 void JIT_OPERATION
operationPutByValDirectCellStrict(ExecState
* exec
, JSCell
* cell
, EncodedJSValue encodedProperty
, EncodedJSValue encodedValue
)
480 VM
* vm
= &exec
->vm();
481 NativeCallFrameTracer
tracer(vm
, exec
);
483 operationPutByValInternal
<true, true>(exec
, JSValue::encode(cell
), encodedProperty
, encodedValue
);
486 void JIT_OPERATION
operationPutByValDirectCellNonStrict(ExecState
* exec
, JSCell
* cell
, EncodedJSValue encodedProperty
, EncodedJSValue encodedValue
)
488 VM
* vm
= &exec
->vm();
489 NativeCallFrameTracer
tracer(vm
, exec
);
491 operationPutByValInternal
<false, true>(exec
, JSValue::encode(cell
), encodedProperty
, encodedValue
);
494 void JIT_OPERATION
operationPutByValDirectBeyondArrayBoundsStrict(ExecState
* exec
, JSObject
* array
, int32_t index
, EncodedJSValue encodedValue
)
496 VM
* vm
= &exec
->vm();
497 NativeCallFrameTracer
tracer(vm
, exec
);
499 array
->putDirectIndex(exec
, index
, JSValue::decode(encodedValue
), 0, PutDirectIndexShouldThrow
);
503 PutPropertySlot
slot(array
, true);
504 array
->putDirect(exec
->vm(), Identifier::from(exec
, index
), JSValue::decode(encodedValue
), slot
);
507 void JIT_OPERATION
operationPutByValDirectBeyondArrayBoundsNonStrict(ExecState
* exec
, JSObject
* array
, int32_t index
, EncodedJSValue encodedValue
)
509 VM
* vm
= &exec
->vm();
510 NativeCallFrameTracer
tracer(vm
, exec
);
513 array
->putDirectIndex(exec
, index
, JSValue::decode(encodedValue
));
517 PutPropertySlot
slot(array
, false);
518 array
->putDirect(exec
->vm(), Identifier::from(exec
, index
), JSValue::decode(encodedValue
), slot
);
521 EncodedJSValue JIT_OPERATION
operationArrayPush(ExecState
* exec
, EncodedJSValue encodedValue
, JSArray
* array
)
523 VM
* vm
= &exec
->vm();
524 NativeCallFrameTracer
tracer(vm
, exec
);
526 array
->push(exec
, JSValue::decode(encodedValue
));
527 return JSValue::encode(jsNumber(array
->length()));
530 EncodedJSValue JIT_OPERATION
operationArrayPushDouble(ExecState
* exec
, double value
, JSArray
* array
)
532 VM
* vm
= &exec
->vm();
533 NativeCallFrameTracer
tracer(vm
, exec
);
535 array
->push(exec
, JSValue(JSValue::EncodeAsDouble
, value
));
536 return JSValue::encode(jsNumber(array
->length()));
539 EncodedJSValue JIT_OPERATION
operationArrayPop(ExecState
* exec
, JSArray
* array
)
541 VM
* vm
= &exec
->vm();
542 NativeCallFrameTracer
tracer(vm
, exec
);
544 return JSValue::encode(array
->pop(exec
));
547 EncodedJSValue JIT_OPERATION
operationArrayPopAndRecoverLength(ExecState
* exec
, JSArray
* array
)
549 VM
* vm
= &exec
->vm();
550 NativeCallFrameTracer
tracer(vm
, exec
);
552 array
->butterfly()->setPublicLength(array
->butterfly()->publicLength() + 1);
554 return JSValue::encode(array
->pop(exec
));
557 EncodedJSValue JIT_OPERATION
operationRegExpExec(ExecState
* exec
, JSCell
* base
, JSCell
* argument
)
560 NativeCallFrameTracer
tracer(&vm
, exec
);
562 if (!base
->inherits(RegExpObject::info()))
563 return throwVMTypeError(exec
);
565 ASSERT(argument
->isString() || argument
->isObject());
566 JSString
* input
= argument
->isString() ? asString(argument
) : asObject(argument
)->toString(exec
);
567 return JSValue::encode(asRegExpObject(base
)->exec(exec
, input
));
570 size_t JIT_OPERATION
operationRegExpTest(ExecState
* exec
, JSCell
* base
, JSCell
* argument
)
573 NativeCallFrameTracer
tracer(&vm
, exec
);
575 if (!base
->inherits(RegExpObject::info())) {
576 throwTypeError(exec
);
580 ASSERT(argument
->isString() || argument
->isObject());
581 JSString
* input
= argument
->isString() ? asString(argument
) : asObject(argument
)->toString(exec
);
582 return asRegExpObject(base
)->test(exec
, input
);
585 size_t JIT_OPERATION
operationCompareStrictEqCell(ExecState
* exec
, EncodedJSValue encodedOp1
, EncodedJSValue encodedOp2
)
587 VM
* vm
= &exec
->vm();
588 NativeCallFrameTracer
tracer(vm
, exec
);
590 JSValue op1
= JSValue::decode(encodedOp1
);
591 JSValue op2
= JSValue::decode(encodedOp2
);
593 ASSERT(op1
.isCell());
594 ASSERT(op2
.isCell());
596 return JSValue::strictEqualSlowCaseInline(exec
, op1
, op2
);
599 size_t JIT_OPERATION
operationCompareStrictEq(ExecState
* exec
, EncodedJSValue encodedOp1
, EncodedJSValue encodedOp2
)
601 VM
* vm
= &exec
->vm();
602 NativeCallFrameTracer
tracer(vm
, exec
);
604 JSValue src1
= JSValue::decode(encodedOp1
);
605 JSValue src2
= JSValue::decode(encodedOp2
);
607 return JSValue::strictEqual(exec
, src1
, src2
);
610 EncodedJSValue JIT_OPERATION
operationToPrimitive(ExecState
* exec
, EncodedJSValue value
)
612 VM
* vm
= &exec
->vm();
613 NativeCallFrameTracer
tracer(vm
, exec
);
615 return JSValue::encode(JSValue::decode(value
).toPrimitive(exec
));
618 char* JIT_OPERATION
operationNewArray(ExecState
* exec
, Structure
* arrayStructure
, void* buffer
, size_t size
)
620 VM
* vm
= &exec
->vm();
621 NativeCallFrameTracer
tracer(vm
, exec
);
623 return bitwise_cast
<char*>(constructArray(exec
, arrayStructure
, static_cast<JSValue
*>(buffer
), size
));
626 char* JIT_OPERATION
operationNewEmptyArray(ExecState
* exec
, Structure
* arrayStructure
)
628 VM
* vm
= &exec
->vm();
629 NativeCallFrameTracer
tracer(vm
, exec
);
631 return bitwise_cast
<char*>(JSArray::create(*vm
, arrayStructure
));
634 char* JIT_OPERATION
operationNewArrayWithSize(ExecState
* exec
, Structure
* arrayStructure
, int32_t size
)
636 VM
* vm
= &exec
->vm();
637 NativeCallFrameTracer
tracer(vm
, exec
);
639 if (UNLIKELY(size
< 0))
640 return bitwise_cast
<char*>(exec
->vm().throwException(exec
, createRangeError(exec
, ASCIILiteral("Array size is not a small enough positive integer."))));
642 return bitwise_cast
<char*>(JSArray::create(*vm
, arrayStructure
, size
));
645 char* JIT_OPERATION
operationNewArrayBuffer(ExecState
* exec
, Structure
* arrayStructure
, size_t start
, size_t size
)
648 NativeCallFrameTracer
tracer(&vm
, exec
);
649 return bitwise_cast
<char*>(constructArray(exec
, arrayStructure
, exec
->codeBlock()->constantBuffer(start
), size
));
652 char* JIT_OPERATION
operationNewInt8ArrayWithSize(
653 ExecState
* exec
, Structure
* structure
, int32_t length
)
655 return newTypedArrayWithSize
<JSInt8Array
>(exec
, structure
, length
);
658 char* JIT_OPERATION
operationNewInt8ArrayWithOneArgument(
659 ExecState
* exec
, Structure
* structure
, EncodedJSValue encodedValue
)
661 return newTypedArrayWithOneArgument
<JSInt8Array
>(exec
, structure
, encodedValue
);
664 char* JIT_OPERATION
operationNewInt16ArrayWithSize(
665 ExecState
* exec
, Structure
* structure
, int32_t length
)
667 return newTypedArrayWithSize
<JSInt16Array
>(exec
, structure
, length
);
670 char* JIT_OPERATION
operationNewInt16ArrayWithOneArgument(
671 ExecState
* exec
, Structure
* structure
, EncodedJSValue encodedValue
)
673 return newTypedArrayWithOneArgument
<JSInt16Array
>(exec
, structure
, encodedValue
);
676 char* JIT_OPERATION
operationNewInt32ArrayWithSize(
677 ExecState
* exec
, Structure
* structure
, int32_t length
)
679 return newTypedArrayWithSize
<JSInt32Array
>(exec
, structure
, length
);
682 char* JIT_OPERATION
operationNewInt32ArrayWithOneArgument(
683 ExecState
* exec
, Structure
* structure
, EncodedJSValue encodedValue
)
685 return newTypedArrayWithOneArgument
<JSInt32Array
>(exec
, structure
, encodedValue
);
688 char* JIT_OPERATION
operationNewUint8ArrayWithSize(
689 ExecState
* exec
, Structure
* structure
, int32_t length
)
691 return newTypedArrayWithSize
<JSUint8Array
>(exec
, structure
, length
);
694 char* JIT_OPERATION
operationNewUint8ArrayWithOneArgument(
695 ExecState
* exec
, Structure
* structure
, EncodedJSValue encodedValue
)
697 return newTypedArrayWithOneArgument
<JSUint8Array
>(exec
, structure
, encodedValue
);
700 char* JIT_OPERATION
operationNewUint8ClampedArrayWithSize(
701 ExecState
* exec
, Structure
* structure
, int32_t length
)
703 return newTypedArrayWithSize
<JSUint8ClampedArray
>(exec
, structure
, length
);
706 char* JIT_OPERATION
operationNewUint8ClampedArrayWithOneArgument(
707 ExecState
* exec
, Structure
* structure
, EncodedJSValue encodedValue
)
709 return newTypedArrayWithOneArgument
<JSUint8ClampedArray
>(exec
, structure
, encodedValue
);
712 char* JIT_OPERATION
operationNewUint16ArrayWithSize(
713 ExecState
* exec
, Structure
* structure
, int32_t length
)
715 return newTypedArrayWithSize
<JSUint16Array
>(exec
, structure
, length
);
718 char* JIT_OPERATION
operationNewUint16ArrayWithOneArgument(
719 ExecState
* exec
, Structure
* structure
, EncodedJSValue encodedValue
)
721 return newTypedArrayWithOneArgument
<JSUint16Array
>(exec
, structure
, encodedValue
);
724 char* JIT_OPERATION
operationNewUint32ArrayWithSize(
725 ExecState
* exec
, Structure
* structure
, int32_t length
)
727 return newTypedArrayWithSize
<JSUint32Array
>(exec
, structure
, length
);
730 char* JIT_OPERATION
operationNewUint32ArrayWithOneArgument(
731 ExecState
* exec
, Structure
* structure
, EncodedJSValue encodedValue
)
733 return newTypedArrayWithOneArgument
<JSUint32Array
>(exec
, structure
, encodedValue
);
736 char* JIT_OPERATION
operationNewFloat32ArrayWithSize(
737 ExecState
* exec
, Structure
* structure
, int32_t length
)
739 return newTypedArrayWithSize
<JSFloat32Array
>(exec
, structure
, length
);
742 char* JIT_OPERATION
operationNewFloat32ArrayWithOneArgument(
743 ExecState
* exec
, Structure
* structure
, EncodedJSValue encodedValue
)
745 return newTypedArrayWithOneArgument
<JSFloat32Array
>(exec
, structure
, encodedValue
);
748 char* JIT_OPERATION
operationNewFloat64ArrayWithSize(
749 ExecState
* exec
, Structure
* structure
, int32_t length
)
751 return newTypedArrayWithSize
<JSFloat64Array
>(exec
, structure
, length
);
754 char* JIT_OPERATION
operationNewFloat64ArrayWithOneArgument(
755 ExecState
* exec
, Structure
* structure
, EncodedJSValue encodedValue
)
757 return newTypedArrayWithOneArgument
<JSFloat64Array
>(exec
, structure
, encodedValue
);
760 JSCell
* JIT_OPERATION
operationCreateInlinedArguments(
761 ExecState
* exec
, InlineCallFrame
* inlineCallFrame
)
764 NativeCallFrameTracer
tracer(&vm
, exec
);
765 // NB: This needs to be exceedingly careful with top call frame tracking, since it
766 // may be called from OSR exit, while the state of the call stack is bizarre.
767 Arguments
* result
= Arguments::create(vm
, exec
, inlineCallFrame
);
768 ASSERT(!vm
.exception());
772 JSCell
* JIT_OPERATION
operationCreateInlinedArgumentsDuringOSRExit(ExecState
* exec
, InlineCallFrame
* inlineCallFrame
)
774 DeferGCForAWhile(exec
->vm().heap
);
775 return operationCreateInlinedArguments(exec
, inlineCallFrame
);
778 void JIT_OPERATION
operationTearOffInlinedArguments(
779 ExecState
* exec
, JSCell
* argumentsCell
, JSCell
* activationCell
, InlineCallFrame
* inlineCallFrame
)
781 ASSERT_UNUSED(activationCell
, !activationCell
); // Currently, we don't inline functions with activations.
782 jsCast
<Arguments
*>(argumentsCell
)->tearOff(exec
, inlineCallFrame
);
785 EncodedJSValue JIT_OPERATION
operationGetArgumentByVal(ExecState
* exec
, int32_t argumentsRegister
, int32_t index
)
788 NativeCallFrameTracer
tracer(&vm
, exec
);
790 JSValue argumentsValue
= exec
->uncheckedR(argumentsRegister
).jsValue();
792 // If there are no arguments, and we're accessing out of bounds, then we have to create the
793 // arguments in case someone has installed a getter on a numeric property.
795 exec
->uncheckedR(argumentsRegister
) = argumentsValue
= Arguments::create(exec
->vm(), exec
);
797 return JSValue::encode(argumentsValue
.get(exec
, index
));
800 EncodedJSValue JIT_OPERATION
operationGetInlinedArgumentByVal(
801 ExecState
* exec
, int32_t argumentsRegister
, InlineCallFrame
* inlineCallFrame
, int32_t index
)
804 NativeCallFrameTracer
tracer(&vm
, exec
);
806 JSValue argumentsValue
= exec
->uncheckedR(argumentsRegister
).jsValue();
808 // If there are no arguments, and we're accessing out of bounds, then we have to create the
809 // arguments in case someone has installed a getter on a numeric property.
810 if (!argumentsValue
) {
811 exec
->uncheckedR(argumentsRegister
) = argumentsValue
=
812 Arguments::create(exec
->vm(), exec
, inlineCallFrame
);
815 return JSValue::encode(argumentsValue
.get(exec
, index
));
818 JSCell
* JIT_OPERATION
operationNewFunctionNoCheck(ExecState
* exec
, JSCell
* functionExecutable
)
820 ASSERT(functionExecutable
->inherits(FunctionExecutable::info()));
822 NativeCallFrameTracer
tracer(&vm
, exec
);
823 return JSFunction::create(vm
, static_cast<FunctionExecutable
*>(functionExecutable
), exec
->scope());
826 size_t JIT_OPERATION
operationIsObject(ExecState
* exec
, EncodedJSValue value
)
828 return jsIsObjectType(exec
, JSValue::decode(value
));
831 size_t JIT_OPERATION
operationIsFunction(EncodedJSValue value
)
833 return jsIsFunctionType(JSValue::decode(value
));
836 JSCell
* JIT_OPERATION
operationTypeOf(ExecState
* exec
, JSCell
* value
)
839 NativeCallFrameTracer
tracer(&vm
, exec
);
840 return jsTypeStringForValue(exec
, JSValue(value
)).asCell();
843 char* JIT_OPERATION
operationAllocatePropertyStorageWithInitialCapacity(ExecState
* exec
)
846 NativeCallFrameTracer
tracer(&vm
, exec
);
848 return reinterpret_cast<char*>(
849 Butterfly::createUninitialized(vm
, 0, 0, initialOutOfLineCapacity
, false, 0));
852 char* JIT_OPERATION
operationAllocatePropertyStorage(ExecState
* exec
, size_t newSize
)
855 NativeCallFrameTracer
tracer(&vm
, exec
);
857 return reinterpret_cast<char*>(
858 Butterfly::createUninitialized(vm
, 0, 0, newSize
, false, 0));
861 char* JIT_OPERATION
operationReallocateButterflyToHavePropertyStorageWithInitialCapacity(ExecState
* exec
, JSObject
* object
)
864 NativeCallFrameTracer
tracer(&vm
, exec
);
866 ASSERT(!object
->structure()->outOfLineCapacity());
867 DeferGC
deferGC(vm
.heap
);
868 Butterfly
* result
= object
->growOutOfLineStorage(vm
, 0, initialOutOfLineCapacity
);
869 object
->setButterflyWithoutChangingStructure(vm
, result
);
870 return reinterpret_cast<char*>(result
);
873 char* JIT_OPERATION
operationReallocateButterflyToGrowPropertyStorage(ExecState
* exec
, JSObject
* object
, size_t newSize
)
876 NativeCallFrameTracer
tracer(&vm
, exec
);
878 DeferGC
deferGC(vm
.heap
);
879 Butterfly
* result
= object
->growOutOfLineStorage(vm
, object
->structure()->outOfLineCapacity(), newSize
);
880 object
->setButterflyWithoutChangingStructure(vm
, result
);
881 return reinterpret_cast<char*>(result
);
884 char* JIT_OPERATION
operationEnsureInt32(ExecState
* exec
, JSCell
* cell
)
887 NativeCallFrameTracer
tracer(&vm
, exec
);
889 if (!cell
->isObject())
892 return reinterpret_cast<char*>(asObject(cell
)->ensureInt32(vm
).data());
895 char* JIT_OPERATION
operationEnsureDouble(ExecState
* exec
, JSCell
* cell
)
898 NativeCallFrameTracer
tracer(&vm
, exec
);
900 if (!cell
->isObject())
903 return reinterpret_cast<char*>(asObject(cell
)->ensureDouble(vm
).data());
906 char* JIT_OPERATION
operationEnsureContiguous(ExecState
* exec
, JSCell
* cell
)
909 NativeCallFrameTracer
tracer(&vm
, exec
);
911 if (!cell
->isObject())
914 return reinterpret_cast<char*>(asObject(cell
)->ensureContiguous(vm
).data());
917 char* JIT_OPERATION
operationRageEnsureContiguous(ExecState
* exec
, JSCell
* cell
)
920 NativeCallFrameTracer
tracer(&vm
, exec
);
922 if (!cell
->isObject())
925 return reinterpret_cast<char*>(asObject(cell
)->rageEnsureContiguous(vm
).data());
928 char* JIT_OPERATION
operationEnsureArrayStorage(ExecState
* exec
, JSCell
* cell
)
931 NativeCallFrameTracer
tracer(&vm
, exec
);
933 if (!cell
->isObject())
936 return reinterpret_cast<char*>(asObject(cell
)->ensureArrayStorage(vm
));
939 StringImpl
* JIT_OPERATION
operationResolveRope(ExecState
* exec
, JSString
* string
)
942 NativeCallFrameTracer
tracer(&vm
, exec
);
944 return string
->value(exec
).impl();
947 JSString
* JIT_OPERATION
operationSingleCharacterString(ExecState
* exec
, int32_t character
)
950 NativeCallFrameTracer
tracer(&vm
, exec
);
952 return jsSingleCharacterString(exec
, static_cast<UChar
>(character
));
955 JSCell
* JIT_OPERATION
operationNewStringObject(ExecState
* exec
, JSString
* string
, Structure
* structure
)
958 NativeCallFrameTracer
tracer(&vm
, exec
);
960 return StringObject::create(vm
, structure
, string
);
963 JSCell
* JIT_OPERATION
operationToStringOnCell(ExecState
* exec
, JSCell
* cell
)
966 NativeCallFrameTracer
tracer(&vm
, exec
);
968 return JSValue(cell
).toString(exec
);
971 JSCell
* JIT_OPERATION
operationToString(ExecState
* exec
, EncodedJSValue value
)
974 NativeCallFrameTracer
tracer(&vm
, exec
);
976 return JSValue::decode(value
).toString(exec
);
979 JSCell
* JIT_OPERATION
operationMakeRope2(ExecState
* exec
, JSString
* left
, JSString
* right
)
982 NativeCallFrameTracer
tracer(&vm
, exec
);
984 if (sumOverflows
<int32_t>(left
->length(), right
->length())) {
985 throwOutOfMemoryError(exec
);
989 return JSRopeString::create(vm
, left
, right
);
992 JSCell
* JIT_OPERATION
operationMakeRope3(ExecState
* exec
, JSString
* a
, JSString
* b
, JSString
* c
)
995 NativeCallFrameTracer
tracer(&vm
, exec
);
997 if (sumOverflows
<int32_t>(a
->length(), b
->length(), c
->length())) {
998 throwOutOfMemoryError(exec
);
1002 return JSRopeString::create(vm
, a
, b
, c
);
1005 char* JIT_OPERATION
operationFindSwitchImmTargetForDouble(
1006 ExecState
* exec
, EncodedJSValue encodedValue
, size_t tableIndex
)
1008 CodeBlock
* codeBlock
= exec
->codeBlock();
1009 SimpleJumpTable
& table
= codeBlock
->switchJumpTable(tableIndex
);
1010 JSValue value
= JSValue::decode(encodedValue
);
1011 ASSERT(value
.isDouble());
1012 double asDouble
= value
.asDouble();
1013 int32_t asInt32
= static_cast<int32_t>(asDouble
);
1014 if (asDouble
== asInt32
)
1015 return static_cast<char*>(table
.ctiForValue(asInt32
).executableAddress());
1016 return static_cast<char*>(table
.ctiDefault
.executableAddress());
1019 char* JIT_OPERATION
operationSwitchString(ExecState
* exec
, size_t tableIndex
, JSString
* string
)
1021 VM
& vm
= exec
->vm();
1022 NativeCallFrameTracer
tracer(&vm
, exec
);
1024 return static_cast<char*>(exec
->codeBlock()->stringSwitchJumpTable(tableIndex
).ctiForValue(string
->value(exec
).impl()).executableAddress());
1027 void JIT_OPERATION
operationNotifyWrite(ExecState
* exec
, VariableWatchpointSet
* set
, EncodedJSValue encodedValue
)
1029 VM
& vm
= exec
->vm();
1030 NativeCallFrameTracer
tracer(&vm
, exec
);
1031 JSValue value
= JSValue::decode(encodedValue
);
1033 set
->notifyWrite(vm
, value
);
1036 double JIT_OPERATION
operationFModOnInts(int32_t a
, int32_t b
)
1041 JSCell
* JIT_OPERATION
operationStringFromCharCode(ExecState
* exec
, int32_t op1
)
1043 VM
* vm
= &exec
->vm();
1044 NativeCallFrameTracer
tracer(vm
, exec
);
1045 return JSC::stringFromCharCode(exec
, op1
);
1048 int64_t JIT_OPERATION
operationConvertBoxedDoubleToInt52(EncodedJSValue encodedValue
)
1050 JSValue value
= JSValue::decode(encodedValue
);
1051 if (!value
.isDouble())
1052 return JSValue::notInt52
;
1053 return tryConvertToInt52(value
.asDouble());
1056 int64_t JIT_OPERATION
operationConvertDoubleToInt52(double value
)
1058 return tryConvertToInt52(value
);
1061 size_t JIT_OPERATION
dfgConvertJSValueToInt32(ExecState
* exec
, EncodedJSValue value
)
1063 VM
* vm
= &exec
->vm();
1064 NativeCallFrameTracer
tracer(vm
, exec
);
1066 // toInt32/toUInt32 return the same value; we want the value zero extended to fill the register.
1067 return JSValue::decode(value
).toUInt32(exec
);
1070 void JIT_OPERATION
debugOperationPrintSpeculationFailure(ExecState
* exec
, void* debugInfoRaw
, void* scratch
)
1072 VM
* vm
= &exec
->vm();
1073 NativeCallFrameTracer
tracer(vm
, exec
);
1075 SpeculationFailureDebugInfo
* debugInfo
= static_cast<SpeculationFailureDebugInfo
*>(debugInfoRaw
);
1076 CodeBlock
* codeBlock
= debugInfo
->codeBlock
;
1077 CodeBlock
* alternative
= codeBlock
->alternative();
1078 dataLog("Speculation failure in ", *codeBlock
);
1079 dataLog(" @ exit #", vm
->osrExitIndex
, " (bc#", debugInfo
->bytecodeOffset
, ", ", exitKindToString(debugInfo
->kind
), ") with ");
1082 "executeCounter = ", alternative
->jitExecuteCounter(),
1083 ", reoptimizationRetryCounter = ", alternative
->reoptimizationRetryCounter(),
1084 ", optimizationDelayCounter = ", alternative
->optimizationDelayCounter());
1086 dataLog("no alternative code block (i.e. we've been jettisoned)");
1087 dataLog(", osrExitCounter = ", codeBlock
->osrExitCounter(), "\n");
1088 dataLog(" GPRs at time of exit:");
1089 char* scratchPointer
= static_cast<char*>(scratch
);
1090 for (unsigned i
= 0; i
< GPRInfo::numberOfRegisters
; ++i
) {
1091 GPRReg gpr
= GPRInfo::toRegister(i
);
1092 dataLog(" ", GPRInfo::debugName(gpr
), ":", RawPointer(*reinterpret_cast_ptr
<void**>(scratchPointer
)));
1093 scratchPointer
+= sizeof(EncodedJSValue
);
1096 dataLog(" FPRs at time of exit:");
1097 for (unsigned i
= 0; i
< FPRInfo::numberOfRegisters
; ++i
) {
1098 FPRReg fpr
= FPRInfo::toRegister(i
);
1099 dataLog(" ", FPRInfo::debugName(fpr
), ":");
1100 uint64_t bits
= *reinterpret_cast_ptr
<uint64_t*>(scratchPointer
);
1101 double value
= *reinterpret_cast_ptr
<double*>(scratchPointer
);
1102 dataLogF("%llx:%lf", static_cast<long long>(bits
), value
);
1103 scratchPointer
+= sizeof(EncodedJSValue
);
1108 extern "C" void JIT_OPERATION
triggerReoptimizationNow(CodeBlock
* codeBlock
)
1110 // It's sort of preferable that we don't GC while in here. Anyways, doing so wouldn't
1111 // really be profitable.
1112 DeferGCForAWhile
deferGC(codeBlock
->vm()->heap
);
1114 if (Options::verboseOSR())
1115 dataLog(*codeBlock
, ": Entered reoptimize\n");
1116 // We must be called with the baseline code block.
1117 ASSERT(JITCode::isBaselineCode(codeBlock
->jitType()));
1119 // If I am my own replacement, then reoptimization has already been triggered.
1120 // This can happen in recursive functions.
1121 if (codeBlock
->replacement() == codeBlock
) {
1122 if (Options::verboseOSR())
1123 dataLog(*codeBlock
, ": Not reoptimizing because we've already been jettisoned.\n");
1127 // Otherwise, the replacement must be optimized code. Use this as an opportunity
1128 // to check our logic.
1129 ASSERT(codeBlock
->hasOptimizedReplacement());
1130 CodeBlock
* optimizedCodeBlock
= codeBlock
->replacement();
1131 ASSERT(JITCode::isOptimizingJIT(optimizedCodeBlock
->jitType()));
1133 // In order to trigger reoptimization, one of two things must have happened:
1134 // 1) We exited more than some number of times.
1135 // 2) We exited and got stuck in a loop, and now we're exiting again.
1136 bool didExitABunch
= optimizedCodeBlock
->shouldReoptimizeNow();
1137 bool didGetStuckInLoop
=
1138 codeBlock
->checkIfOptimizationThresholdReached()
1139 && optimizedCodeBlock
->shouldReoptimizeFromLoopNow();
1141 if (!didExitABunch
&& !didGetStuckInLoop
) {
1142 if (Options::verboseOSR())
1143 dataLog(*codeBlock
, ": Not reoptimizing ", *optimizedCodeBlock
, " because it either didn't exit enough or didn't loop enough after exit.\n");
1144 codeBlock
->optimizeAfterLongWarmUp();
1148 optimizedCodeBlock
->jettison(Profiler::JettisonDueToOSRExit
, CountReoptimization
);
1152 static void triggerFTLReplacementCompile(VM
* vm
, CodeBlock
* codeBlock
, JITCode
* jitCode
)
1154 if (codeBlock
->baselineVersion()->m_didFailFTLCompilation
) {
1155 if (Options::verboseOSR())
1156 dataLog("Deferring FTL-optimization of ", *codeBlock
, " indefinitely because there was an FTL failure.\n");
1157 jitCode
->dontOptimizeAnytimeSoon(codeBlock
);
1161 if (!jitCode
->checkIfOptimizationThresholdReached(codeBlock
)) {
1162 if (Options::verboseOSR())
1163 dataLog("Choosing not to FTL-optimize ", *codeBlock
, " yet.\n");
1167 Worklist::State worklistState
;
1168 if (Worklist
* worklist
= existingGlobalFTLWorklistOrNull()) {
1169 worklistState
= worklist
->completeAllReadyPlansForVM(
1170 *vm
, CompilationKey(codeBlock
->baselineVersion(), FTLMode
));
1172 worklistState
= Worklist::NotKnown
;
1174 if (worklistState
== Worklist::Compiling
) {
1175 jitCode
->setOptimizationThresholdBasedOnCompilationResult(
1176 codeBlock
, CompilationDeferred
);
1180 if (codeBlock
->hasOptimizedReplacement()) {
1181 // That's great, we've compiled the code - next time we call this function,
1182 // we'll enter that replacement.
1183 jitCode
->optimizeSoon(codeBlock
);
1187 if (worklistState
== Worklist::Compiled
) {
1188 // This means that we finished compiling, but failed somehow; in that case the
1189 // thresholds will be set appropriately.
1190 if (Options::verboseOSR())
1191 dataLog("Code block ", *codeBlock
, " was compiled but it doesn't have an optimized replacement.\n");
1195 // We need to compile the code.
1197 *vm
, codeBlock
->newReplacement().get(), codeBlock
, FTLMode
, UINT_MAX
,
1198 Operands
<JSValue
>(), ToFTLDeferredCompilationCallback::create(codeBlock
));
1201 void JIT_OPERATION
triggerTierUpNow(ExecState
* exec
)
1203 VM
* vm
= &exec
->vm();
1204 NativeCallFrameTracer
tracer(vm
, exec
);
1205 DeferGC
deferGC(vm
->heap
);
1206 CodeBlock
* codeBlock
= exec
->codeBlock();
1208 JITCode
* jitCode
= codeBlock
->jitCode()->dfg();
1210 if (Options::verboseOSR()) {
1212 *codeBlock
, ": Entered triggerTierUpNow with executeCounter = ",
1213 jitCode
->tierUpCounter
, "\n");
1216 triggerFTLReplacementCompile(vm
, codeBlock
, jitCode
);
1219 char* JIT_OPERATION
triggerOSREntryNow(
1220 ExecState
* exec
, int32_t bytecodeIndex
, int32_t streamIndex
)
1222 VM
* vm
= &exec
->vm();
1223 NativeCallFrameTracer
tracer(vm
, exec
);
1224 DeferGC
deferGC(vm
->heap
);
1225 CodeBlock
* codeBlock
= exec
->codeBlock();
1227 JITCode
* jitCode
= codeBlock
->jitCode()->dfg();
1229 if (Options::verboseOSR()) {
1231 *codeBlock
, ": Entered triggerTierUpNow with executeCounter = ",
1232 jitCode
->tierUpCounter
, "\n");
1235 // - If we don't have an FTL code block, then try to compile one.
1236 // - If we do have an FTL code block, then try to enter for a while.
1237 // - If we couldn't enter for a while, then trigger OSR entry.
1239 triggerFTLReplacementCompile(vm
, codeBlock
, jitCode
);
1241 if (!codeBlock
->hasOptimizedReplacement())
1244 if (jitCode
->osrEntryRetry
< Options::ftlOSREntryRetryThreshold()) {
1245 jitCode
->osrEntryRetry
++;
1249 // It's time to try to compile code for OSR entry.
1250 Worklist::State worklistState
;
1251 if (Worklist
* worklist
= existingGlobalFTLWorklistOrNull()) {
1252 worklistState
= worklist
->completeAllReadyPlansForVM(
1253 *vm
, CompilationKey(codeBlock
->baselineVersion(), FTLForOSREntryMode
));
1255 worklistState
= Worklist::NotKnown
;
1257 if (worklistState
== Worklist::Compiling
)
1260 if (CodeBlock
* entryBlock
= jitCode
->osrEntryBlock
.get()) {
1261 void* address
= FTL::prepareOSREntry(
1262 exec
, codeBlock
, entryBlock
, bytecodeIndex
, streamIndex
);
1264 return static_cast<char*>(address
);
1266 FTL::ForOSREntryJITCode
* entryCode
= entryBlock
->jitCode()->ftlForOSREntry();
1267 entryCode
->countEntryFailure();
1268 if (entryCode
->entryFailureCount() <
1269 Options::ftlOSREntryFailureCountForReoptimization())
1272 // OSR entry failed. Oh no! This implies that we need to retry. We retry
1273 // without exponential backoff and we only do this for the entry code block.
1274 jitCode
->osrEntryBlock
.clear();
1275 jitCode
->osrEntryRetry
= 0;
1279 if (worklistState
== Worklist::Compiled
) {
1280 // This means that compilation failed and we already set the thresholds.
1281 if (Options::verboseOSR())
1282 dataLog("Code block ", *codeBlock
, " was compiled but it doesn't have an optimized replacement.\n");
1286 // We aren't compiling and haven't compiled anything for OSR entry. So, try to compile
1288 Operands
<JSValue
> mustHandleValues
;
1289 jitCode
->reconstruct(
1290 exec
, codeBlock
, CodeOrigin(bytecodeIndex
), streamIndex
, mustHandleValues
);
1291 RefPtr
<CodeBlock
> replacementCodeBlock
= codeBlock
->newReplacement();
1292 CompilationResult forEntryResult
= compile(
1293 *vm
, replacementCodeBlock
.get(), codeBlock
, FTLForOSREntryMode
, bytecodeIndex
,
1294 mustHandleValues
, ToFTLForOSREntryDeferredCompilationCallback::create(codeBlock
));
1296 if (forEntryResult
!= CompilationSuccessful
) {
1297 ASSERT(forEntryResult
== CompilationDeferred
|| replacementCodeBlock
->hasOneRef());
1301 // It's possible that the for-entry compile already succeeded. In that case OSR
1302 // entry will succeed unless we ran out of stack. It's not clear what we should do.
1303 // We signal to try again after a while if that happens.
1304 void* address
= FTL::prepareOSREntry(
1305 exec
, codeBlock
, jitCode
->osrEntryBlock
.get(), bytecodeIndex
, streamIndex
);
1306 return static_cast<char*>(address
);
1308 #endif // ENABLE(FTL_JIT)
1311 } } // namespace JSC::DFG
1313 #endif // ENABLE(DFG_JIT)
1315 #endif // ENABLE(JIT)