2 * Copyright (C) 2011, 2013-2016 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 "ButterflyInlines.h"
30 #include "ClonedArguments.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 "DirectArguments.h"
42 #include "FTLForOSREntryJITCode.h"
43 #include "FTLOSREntry.h"
44 #include "HostCallReturnValue.h"
45 #include "GetterSetter.h"
46 #include "Interpreter.h"
48 #include "JITExceptions.h"
49 #include "JSCInlines.h"
50 #include "JSLexicalEnvironment.h"
51 #include "ObjectConstructor.h"
53 #include "ScopedArguments.h"
54 #include "StringConstructor.h"
56 #include "TypeProfilerLog.h"
57 #include "TypedArrayInlines.h"
59 #include <wtf/InlineASM.h>
64 namespace JSC { namespace DFG {
66 template<bool strict, bool direct>
67 static inline void putByVal(ExecState* exec, JSValue baseValue, uint32_t index, JSValue value)
70 NativeCallFrameTracer tracer(&vm, exec);
71 ASSERT(isIndex(index));
73 RELEASE_ASSERT(baseValue.isObject());
74 asObject(baseValue)->putDirectIndex(exec, index, value, 0, strict ? PutDirectIndexShouldThrow : PutDirectIndexShouldNotThrow);
77 if (baseValue.isObject()) {
78 JSObject* object = asObject(baseValue);
79 if (object->canSetIndexQuickly(index)) {
80 object->setIndexQuickly(vm, index, value);
84 object->methodTable(vm)->putByIndex(object, exec, index, value, strict);
88 baseValue.putByIndex(exec, index, value, strict);
91 template<bool strict, bool direct>
92 ALWAYS_INLINE static void JIT_OPERATION operationPutByValInternal(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
95 NativeCallFrameTracer tracer(vm, exec);
97 JSValue baseValue = JSValue::decode(encodedBase);
98 JSValue property = JSValue::decode(encodedProperty);
99 JSValue value = JSValue::decode(encodedValue);
101 if (LIKELY(property.isUInt32())) {
102 // Despite its name, JSValue::isUInt32 will return true only for positive boxed int32_t; all those values are valid array indices.
103 ASSERT(isIndex(property.asUInt32()));
104 putByVal<strict, direct>(exec, baseValue, property.asUInt32(), value);
108 if (property.isDouble()) {
109 double propertyAsDouble = property.asDouble();
110 uint32_t propertyAsUInt32 = static_cast<uint32_t>(propertyAsDouble);
111 if (propertyAsDouble == propertyAsUInt32 && isIndex(propertyAsUInt32)) {
112 putByVal<strict, direct>(exec, baseValue, propertyAsUInt32, value);
117 // Don't put to an object if toString throws an exception.
118 auto propertyName = property.toPropertyKey(exec);
122 PutPropertySlot slot(baseValue, strict);
124 RELEASE_ASSERT(baseValue.isObject());
125 if (Optional<uint32_t> index = parseIndex(propertyName))
126 asObject(baseValue)->putDirectIndex(exec, index.value(), value, 0, strict ? PutDirectIndexShouldThrow : PutDirectIndexShouldNotThrow);
128 asObject(baseValue)->putDirect(*vm, propertyName, value, slot);
130 baseValue.put(exec, propertyName, value, slot);
133 template<typename ViewClass>
134 char* newTypedArrayWithSize(ExecState* exec, Structure* structure, int32_t size)
137 NativeCallFrameTracer tracer(&vm, exec);
139 vm.throwException(exec, createRangeError(exec, ASCIILiteral("Requested length is negative")));
142 return bitwise_cast<char*>(ViewClass::create(exec, structure, size));
147 EncodedJSValue JIT_OPERATION operationToThis(ExecState* exec, EncodedJSValue encodedOp)
149 VM* vm = &exec->vm();
150 NativeCallFrameTracer tracer(vm, exec);
152 return JSValue::encode(JSValue::decode(encodedOp).toThis(exec, NotStrictMode));
155 EncodedJSValue JIT_OPERATION operationToThisStrict(ExecState* exec, EncodedJSValue encodedOp)
157 VM* vm = &exec->vm();
158 NativeCallFrameTracer tracer(vm, exec);
160 return JSValue::encode(JSValue::decode(encodedOp).toThis(exec, StrictMode));
163 JSCell* JIT_OPERATION operationCreateThis(ExecState* exec, JSObject* constructor, int32_t inlineCapacity)
166 NativeCallFrameTracer tracer(&vm, exec);
167 if (constructor->type() == JSFunctionType)
168 return constructEmptyObject(exec, jsCast<JSFunction*>(constructor)->rareData(exec, inlineCapacity)->objectAllocationProfile()->structure());
170 return constructEmptyObject(exec);
173 EncodedJSValue JIT_OPERATION operationValueBitAnd(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
175 VM* vm = &exec->vm();
176 NativeCallFrameTracer tracer(vm, exec);
178 JSValue op1 = JSValue::decode(encodedOp1);
179 JSValue op2 = JSValue::decode(encodedOp2);
181 int32_t a = op1.toInt32(exec);
182 int32_t b = op2.toInt32(exec);
183 return JSValue::encode(jsNumber(a & b));
186 EncodedJSValue JIT_OPERATION operationValueBitOr(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
188 VM* vm = &exec->vm();
189 NativeCallFrameTracer tracer(vm, exec);
191 JSValue op1 = JSValue::decode(encodedOp1);
192 JSValue op2 = JSValue::decode(encodedOp2);
194 int32_t a = op1.toInt32(exec);
195 int32_t b = op2.toInt32(exec);
196 return JSValue::encode(jsNumber(a | b));
199 EncodedJSValue JIT_OPERATION operationValueBitXor(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
201 VM* vm = &exec->vm();
202 NativeCallFrameTracer tracer(vm, exec);
204 JSValue op1 = JSValue::decode(encodedOp1);
205 JSValue op2 = JSValue::decode(encodedOp2);
207 int32_t a = op1.toInt32(exec);
208 int32_t b = op2.toInt32(exec);
209 return JSValue::encode(jsNumber(a ^ b));
212 EncodedJSValue JIT_OPERATION operationValueBitLShift(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
214 VM* vm = &exec->vm();
215 NativeCallFrameTracer tracer(vm, exec);
217 JSValue op1 = JSValue::decode(encodedOp1);
218 JSValue op2 = JSValue::decode(encodedOp2);
220 int32_t a = op1.toInt32(exec);
221 uint32_t b = op2.toUInt32(exec);
222 return JSValue::encode(jsNumber(a << (b & 0x1f)));
225 EncodedJSValue JIT_OPERATION operationValueBitRShift(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
227 VM* vm = &exec->vm();
228 NativeCallFrameTracer tracer(vm, exec);
230 JSValue op1 = JSValue::decode(encodedOp1);
231 JSValue op2 = JSValue::decode(encodedOp2);
233 int32_t a = op1.toInt32(exec);
234 uint32_t b = op2.toUInt32(exec);
235 return JSValue::encode(jsNumber(a >> (b & 0x1f)));
238 EncodedJSValue JIT_OPERATION operationValueBitURShift(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
240 VM* vm = &exec->vm();
241 NativeCallFrameTracer tracer(vm, exec);
243 JSValue op1 = JSValue::decode(encodedOp1);
244 JSValue op2 = JSValue::decode(encodedOp2);
246 uint32_t a = op1.toUInt32(exec);
247 uint32_t b = op2.toUInt32(exec);
248 return JSValue::encode(jsNumber(static_cast<int32_t>(a >> (b & 0x1f))));
251 EncodedJSValue JIT_OPERATION operationValueAdd(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
253 VM* vm = &exec->vm();
254 NativeCallFrameTracer tracer(vm, exec);
256 JSValue op1 = JSValue::decode(encodedOp1);
257 JSValue op2 = JSValue::decode(encodedOp2);
259 return JSValue::encode(jsAdd(exec, op1, op2));
262 EncodedJSValue JIT_OPERATION operationValueAddNotNumber(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
264 VM* vm = &exec->vm();
265 NativeCallFrameTracer tracer(vm, exec);
267 JSValue op1 = JSValue::decode(encodedOp1);
268 JSValue op2 = JSValue::decode(encodedOp2);
270 ASSERT(!op1.isNumber() || !op2.isNumber());
272 if (op1.isString() && !op2.isObject())
273 return JSValue::encode(jsString(exec, asString(op1), op2.toString(exec)));
275 return JSValue::encode(jsAddSlowCase(exec, op1, op2));
278 EncodedJSValue JIT_OPERATION operationValueDiv(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
280 VM* vm = &exec->vm();
281 NativeCallFrameTracer tracer(vm, exec);
283 JSValue op1 = JSValue::decode(encodedOp1);
284 JSValue op2 = JSValue::decode(encodedOp2);
286 double a = op1.toNumber(exec);
287 double b = op2.toNumber(exec);
288 return JSValue::encode(jsNumber(a / b));
291 EncodedJSValue JIT_OPERATION operationValueMul(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
293 VM* vm = &exec->vm();
294 NativeCallFrameTracer tracer(vm, exec);
296 JSValue op1 = JSValue::decode(encodedOp1);
297 JSValue op2 = JSValue::decode(encodedOp2);
299 double a = op1.toNumber(exec);
300 double b = op2.toNumber(exec);
301 return JSValue::encode(jsNumber(a * b));
304 EncodedJSValue JIT_OPERATION operationValueSub(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
306 VM* vm = &exec->vm();
307 NativeCallFrameTracer tracer(vm, exec);
309 JSValue op1 = JSValue::decode(encodedOp1);
310 JSValue op2 = JSValue::decode(encodedOp2);
312 double a = op1.toNumber(exec);
313 double b = op2.toNumber(exec);
314 return JSValue::encode(jsNumber(a - b));
317 static ALWAYS_INLINE EncodedJSValue getByVal(ExecState* exec, JSCell* base, uint32_t index)
320 NativeCallFrameTracer tracer(&vm, exec);
322 if (base->isObject()) {
323 JSObject* object = asObject(base);
324 if (object->canGetIndexQuickly(index))
325 return JSValue::encode(object->getIndexQuickly(index));
328 if (isJSString(base) && asString(base)->canGetIndex(index))
329 return JSValue::encode(asString(base)->getIndex(exec, index));
331 return JSValue::encode(JSValue(base).get(exec, index));
334 EncodedJSValue JIT_OPERATION operationGetByVal(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty)
337 NativeCallFrameTracer tracer(&vm, exec);
339 JSValue baseValue = JSValue::decode(encodedBase);
340 JSValue property = JSValue::decode(encodedProperty);
342 if (LIKELY(baseValue.isCell())) {
343 JSCell* base = baseValue.asCell();
345 if (property.isUInt32()) {
346 return getByVal(exec, base, property.asUInt32());
347 } else if (property.isDouble()) {
348 double propertyAsDouble = property.asDouble();
349 uint32_t propertyAsUInt32 = static_cast<uint32_t>(propertyAsDouble);
350 if (propertyAsUInt32 == propertyAsDouble && isIndex(propertyAsUInt32))
351 return getByVal(exec, base, propertyAsUInt32);
352 } else if (property.isString()) {
353 Structure& structure = *base->structure(vm);
354 if (JSCell::canUseFastGetOwnProperty(structure)) {
355 if (RefPtr<AtomicStringImpl> existingAtomicString = asString(property)->toExistingAtomicString(exec)) {
356 if (JSValue result = base->fastGetOwnProperty(vm, structure, existingAtomicString.get()))
357 return JSValue::encode(result);
363 baseValue.requireObjectCoercible(exec);
365 return JSValue::encode(jsUndefined());
366 auto propertyName = property.toPropertyKey(exec);
368 return JSValue::encode(jsUndefined());
369 return JSValue::encode(baseValue.get(exec, propertyName));
372 EncodedJSValue JIT_OPERATION operationGetByValCell(ExecState* exec, JSCell* base, EncodedJSValue encodedProperty)
375 NativeCallFrameTracer tracer(&vm, exec);
377 JSValue property = JSValue::decode(encodedProperty);
379 if (property.isUInt32())
380 return getByVal(exec, base, property.asUInt32());
381 if (property.isDouble()) {
382 double propertyAsDouble = property.asDouble();
383 uint32_t propertyAsUInt32 = static_cast<uint32_t>(propertyAsDouble);
384 if (propertyAsUInt32 == propertyAsDouble)
385 return getByVal(exec, base, propertyAsUInt32);
386 } else if (property.isString()) {
387 Structure& structure = *base->structure(vm);
388 if (JSCell::canUseFastGetOwnProperty(structure)) {
389 if (RefPtr<AtomicStringImpl> existingAtomicString = asString(property)->toExistingAtomicString(exec)) {
390 if (JSValue result = base->fastGetOwnProperty(vm, structure, existingAtomicString.get()))
391 return JSValue::encode(result);
396 auto propertyName = property.toPropertyKey(exec);
398 return JSValue::encode(jsUndefined());
399 return JSValue::encode(JSValue(base).get(exec, propertyName));
402 ALWAYS_INLINE EncodedJSValue getByValCellInt(ExecState* exec, JSCell* base, int32_t index)
404 VM* vm = &exec->vm();
405 NativeCallFrameTracer tracer(vm, exec);
408 // Go the slowest way possible becase negative indices don't use indexed storage.
409 return JSValue::encode(JSValue(base).get(exec, Identifier::from(exec, index)));
412 // Use this since we know that the value is out of bounds.
413 return JSValue::encode(JSValue(base).get(exec, index));
416 EncodedJSValue JIT_OPERATION operationGetByValArrayInt(ExecState* exec, JSArray* base, int32_t index)
418 return getByValCellInt(exec, base, index);
421 EncodedJSValue JIT_OPERATION operationGetByValStringInt(ExecState* exec, JSString* base, int32_t index)
423 return getByValCellInt(exec, base, index);
426 void JIT_OPERATION operationPutByValStrict(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
428 VM* vm = &exec->vm();
429 NativeCallFrameTracer tracer(vm, exec);
431 operationPutByValInternal<true, false>(exec, encodedBase, encodedProperty, encodedValue);
434 void JIT_OPERATION operationPutByValNonStrict(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
436 VM* vm = &exec->vm();
437 NativeCallFrameTracer tracer(vm, exec);
439 operationPutByValInternal<false, false>(exec, encodedBase, encodedProperty, encodedValue);
442 void JIT_OPERATION operationPutByValCellStrict(ExecState* exec, JSCell* cell, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
444 VM* vm = &exec->vm();
445 NativeCallFrameTracer tracer(vm, exec);
447 operationPutByValInternal<true, false>(exec, JSValue::encode(cell), encodedProperty, encodedValue);
450 void JIT_OPERATION operationPutByValCellNonStrict(ExecState* exec, JSCell* cell, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
452 VM* vm = &exec->vm();
453 NativeCallFrameTracer tracer(vm, exec);
455 operationPutByValInternal<false, false>(exec, JSValue::encode(cell), encodedProperty, encodedValue);
458 void JIT_OPERATION operationPutByValBeyondArrayBoundsStrict(ExecState* exec, JSObject* array, int32_t index, EncodedJSValue encodedValue)
461 NativeCallFrameTracer tracer(&vm, exec);
464 array->putByIndexInline(exec, index, JSValue::decode(encodedValue), true);
468 PutPropertySlot slot(array, true);
469 array->methodTable()->put(
470 array, exec, Identifier::from(exec, index), JSValue::decode(encodedValue), slot);
473 void JIT_OPERATION operationPutByValBeyondArrayBoundsNonStrict(ExecState* exec, JSObject* array, int32_t index, EncodedJSValue encodedValue)
475 VM* vm = &exec->vm();
476 NativeCallFrameTracer tracer(vm, exec);
479 array->putByIndexInline(exec, index, JSValue::decode(encodedValue), false);
483 PutPropertySlot slot(array, false);
484 array->methodTable()->put(
485 array, exec, Identifier::from(exec, index), JSValue::decode(encodedValue), slot);
488 void JIT_OPERATION operationPutDoubleByValBeyondArrayBoundsStrict(ExecState* exec, JSObject* array, int32_t index, double value)
490 VM* vm = &exec->vm();
491 NativeCallFrameTracer tracer(vm, exec);
493 JSValue jsValue = JSValue(JSValue::EncodeAsDouble, value);
496 array->putByIndexInline(exec, index, jsValue, true);
500 PutPropertySlot slot(array, true);
501 array->methodTable()->put(
502 array, exec, Identifier::from(exec, index), jsValue, slot);
505 void JIT_OPERATION operationPutDoubleByValBeyondArrayBoundsNonStrict(ExecState* exec, JSObject* array, int32_t index, double value)
507 VM* vm = &exec->vm();
508 NativeCallFrameTracer tracer(vm, exec);
510 JSValue jsValue = JSValue(JSValue::EncodeAsDouble, value);
513 array->putByIndexInline(exec, index, jsValue, false);
517 PutPropertySlot slot(array, false);
518 array->methodTable()->put(
519 array, exec, Identifier::from(exec, index), jsValue, slot);
522 void JIT_OPERATION operationPutByValDirectStrict(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
524 VM* vm = &exec->vm();
525 NativeCallFrameTracer tracer(vm, exec);
527 operationPutByValInternal<true, true>(exec, encodedBase, encodedProperty, encodedValue);
530 void JIT_OPERATION operationPutByValDirectNonStrict(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
532 VM* vm = &exec->vm();
533 NativeCallFrameTracer tracer(vm, exec);
535 operationPutByValInternal<false, true>(exec, encodedBase, encodedProperty, encodedValue);
538 void JIT_OPERATION operationPutByValDirectCellStrict(ExecState* exec, JSCell* cell, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
540 VM* vm = &exec->vm();
541 NativeCallFrameTracer tracer(vm, exec);
543 operationPutByValInternal<true, true>(exec, JSValue::encode(cell), encodedProperty, encodedValue);
546 void JIT_OPERATION operationPutByValDirectCellNonStrict(ExecState* exec, JSCell* cell, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
548 VM* vm = &exec->vm();
549 NativeCallFrameTracer tracer(vm, exec);
551 operationPutByValInternal<false, true>(exec, JSValue::encode(cell), encodedProperty, encodedValue);
554 void JIT_OPERATION operationPutByValDirectBeyondArrayBoundsStrict(ExecState* exec, JSObject* array, int32_t index, EncodedJSValue encodedValue)
556 VM* vm = &exec->vm();
557 NativeCallFrameTracer tracer(vm, exec);
559 array->putDirectIndex(exec, index, JSValue::decode(encodedValue), 0, PutDirectIndexShouldThrow);
563 PutPropertySlot slot(array, true);
564 array->putDirect(exec->vm(), Identifier::from(exec, index), JSValue::decode(encodedValue), slot);
567 void JIT_OPERATION operationPutByValDirectBeyondArrayBoundsNonStrict(ExecState* exec, JSObject* array, int32_t index, EncodedJSValue encodedValue)
569 VM* vm = &exec->vm();
570 NativeCallFrameTracer tracer(vm, exec);
573 array->putDirectIndex(exec, index, JSValue::decode(encodedValue));
577 PutPropertySlot slot(array, false);
578 array->putDirect(exec->vm(), Identifier::from(exec, index), JSValue::decode(encodedValue), slot);
581 EncodedJSValue JIT_OPERATION operationArrayPush(ExecState* exec, EncodedJSValue encodedValue, JSArray* array)
583 VM* vm = &exec->vm();
584 NativeCallFrameTracer tracer(vm, exec);
586 array->push(exec, JSValue::decode(encodedValue));
587 return JSValue::encode(jsNumber(array->length()));
590 EncodedJSValue JIT_OPERATION operationArrayPushDouble(ExecState* exec, double value, JSArray* array)
592 VM* vm = &exec->vm();
593 NativeCallFrameTracer tracer(vm, exec);
595 array->push(exec, JSValue(JSValue::EncodeAsDouble, value));
596 return JSValue::encode(jsNumber(array->length()));
599 EncodedJSValue JIT_OPERATION operationArrayPop(ExecState* exec, JSArray* array)
601 VM* vm = &exec->vm();
602 NativeCallFrameTracer tracer(vm, exec);
604 return JSValue::encode(array->pop(exec));
607 EncodedJSValue JIT_OPERATION operationArrayPopAndRecoverLength(ExecState* exec, JSArray* array)
609 VM* vm = &exec->vm();
610 NativeCallFrameTracer tracer(vm, exec);
612 array->butterfly()->setPublicLength(array->butterfly()->publicLength() + 1);
614 return JSValue::encode(array->pop(exec));
617 EncodedJSValue JIT_OPERATION operationRegExpExec(ExecState* exec, JSCell* base, JSCell* argument)
620 NativeCallFrameTracer tracer(&vm, exec);
622 if (!base->inherits(RegExpObject::info()))
623 return throwVMTypeError(exec);
626 if (argument->isString())
627 input = asString(argument);
629 input = JSValue(argument).toStringOrNull(exec);
631 return JSValue::encode(jsUndefined());
633 return JSValue::encode(asRegExpObject(base)->exec(exec, input));
636 EncodedJSValue JIT_OPERATION operationRegExpExecGeneric(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedArgument)
639 NativeCallFrameTracer tracer(&vm, exec);
641 JSValue base = JSValue::decode(encodedBase);
642 JSValue argument = JSValue::decode(encodedArgument);
644 if (!base.inherits(RegExpObject::info()))
645 return throwVMTypeError(exec);
647 JSString* input = argument.toStringOrNull(exec);
649 return JSValue::encode(jsUndefined());
650 return JSValue::encode(asRegExpObject(base)->exec(exec, input));
653 size_t JIT_OPERATION operationRegExpTest(ExecState* exec, JSCell* base, JSCell* argument)
656 NativeCallFrameTracer tracer(&vm, exec);
658 if (!base->inherits(RegExpObject::info())) {
659 throwTypeError(exec);
664 if (argument->isString())
665 input = asString(argument);
667 input = JSValue(argument).toStringOrNull(exec);
671 return asRegExpObject(base)->test(exec, input);
674 size_t JIT_OPERATION operationRegExpTestGeneric(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedArgument)
677 NativeCallFrameTracer tracer(&vm, exec);
679 JSValue base = JSValue::decode(encodedBase);
680 JSValue argument = JSValue::decode(encodedArgument);
682 if (!base.inherits(RegExpObject::info())) {
683 throwTypeError(exec);
687 JSString* input = argument.toStringOrNull(exec);
690 return asRegExpObject(base)->test(exec, input);
693 size_t JIT_OPERATION operationCompareStrictEqCell(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
695 VM* vm = &exec->vm();
696 NativeCallFrameTracer tracer(vm, exec);
698 JSValue op1 = JSValue::decode(encodedOp1);
699 JSValue op2 = JSValue::decode(encodedOp2);
701 ASSERT(op1.isCell());
702 ASSERT(op2.isCell());
704 return JSValue::strictEqualSlowCaseInline(exec, op1, op2);
707 size_t JIT_OPERATION operationCompareStrictEq(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
709 VM* vm = &exec->vm();
710 NativeCallFrameTracer tracer(vm, exec);
712 JSValue src1 = JSValue::decode(encodedOp1);
713 JSValue src2 = JSValue::decode(encodedOp2);
715 return JSValue::strictEqual(exec, src1, src2);
718 EncodedJSValue JIT_OPERATION operationToPrimitive(ExecState* exec, EncodedJSValue value)
720 VM* vm = &exec->vm();
721 NativeCallFrameTracer tracer(vm, exec);
723 return JSValue::encode(JSValue::decode(value).toPrimitive(exec));
726 char* JIT_OPERATION operationNewArray(ExecState* exec, Structure* arrayStructure, void* buffer, size_t size)
728 VM* vm = &exec->vm();
729 NativeCallFrameTracer tracer(vm, exec);
731 return bitwise_cast<char*>(constructArray(exec, arrayStructure, static_cast<JSValue*>(buffer), size));
734 char* JIT_OPERATION operationNewEmptyArray(ExecState* exec, Structure* arrayStructure)
736 VM* vm = &exec->vm();
737 NativeCallFrameTracer tracer(vm, exec);
739 return bitwise_cast<char*>(JSArray::create(*vm, arrayStructure));
742 char* JIT_OPERATION operationNewArrayWithSize(ExecState* exec, Structure* arrayStructure, int32_t size)
744 VM* vm = &exec->vm();
745 NativeCallFrameTracer tracer(vm, exec);
747 if (UNLIKELY(size < 0))
748 return bitwise_cast<char*>(exec->vm().throwException(exec, createRangeError(exec, ASCIILiteral("Array size is not a small enough positive integer."))));
750 JSArray* result = JSArray::create(*vm, arrayStructure, size);
751 result->butterfly(); // Ensure that the backing store is in to-space.
752 return bitwise_cast<char*>(result);
755 char* JIT_OPERATION operationNewArrayBuffer(ExecState* exec, Structure* arrayStructure, size_t start, size_t size)
758 NativeCallFrameTracer tracer(&vm, exec);
759 return bitwise_cast<char*>(constructArray(exec, arrayStructure, exec->codeBlock()->constantBuffer(start), size));
762 char* JIT_OPERATION operationNewInt8ArrayWithSize(
763 ExecState* exec, Structure* structure, int32_t length)
765 return newTypedArrayWithSize<JSInt8Array>(exec, structure, length);
768 char* JIT_OPERATION operationNewInt8ArrayWithOneArgument(
769 ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
771 return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSInt8Array>(exec, structure, encodedValue, 0, Nullopt));
774 char* JIT_OPERATION operationNewInt16ArrayWithSize(
775 ExecState* exec, Structure* structure, int32_t length)
777 return newTypedArrayWithSize<JSInt16Array>(exec, structure, length);
780 char* JIT_OPERATION operationNewInt16ArrayWithOneArgument(
781 ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
783 return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSInt16Array>(exec, structure, encodedValue, 0, Nullopt));
786 char* JIT_OPERATION operationNewInt32ArrayWithSize(
787 ExecState* exec, Structure* structure, int32_t length)
789 return newTypedArrayWithSize<JSInt32Array>(exec, structure, length);
792 char* JIT_OPERATION operationNewInt32ArrayWithOneArgument(
793 ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
795 return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSInt32Array>(exec, structure, encodedValue, 0, Nullopt));
798 char* JIT_OPERATION operationNewUint8ArrayWithSize(
799 ExecState* exec, Structure* structure, int32_t length)
801 return newTypedArrayWithSize<JSUint8Array>(exec, structure, length);
804 char* JIT_OPERATION operationNewUint8ArrayWithOneArgument(
805 ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
807 return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSUint8Array>(exec, structure, encodedValue, 0, Nullopt));
810 char* JIT_OPERATION operationNewUint8ClampedArrayWithSize(
811 ExecState* exec, Structure* structure, int32_t length)
813 return newTypedArrayWithSize<JSUint8ClampedArray>(exec, structure, length);
816 char* JIT_OPERATION operationNewUint8ClampedArrayWithOneArgument(
817 ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
819 return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSUint8ClampedArray>(exec, structure, encodedValue, 0, Nullopt));
822 char* JIT_OPERATION operationNewUint16ArrayWithSize(
823 ExecState* exec, Structure* structure, int32_t length)
825 return newTypedArrayWithSize<JSUint16Array>(exec, structure, length);
828 char* JIT_OPERATION operationNewUint16ArrayWithOneArgument(
829 ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
831 return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSUint16Array>(exec, structure, encodedValue, 0, Nullopt));
834 char* JIT_OPERATION operationNewUint32ArrayWithSize(
835 ExecState* exec, Structure* structure, int32_t length)
837 return newTypedArrayWithSize<JSUint32Array>(exec, structure, length);
840 char* JIT_OPERATION operationNewUint32ArrayWithOneArgument(
841 ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
843 return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSUint32Array>(exec, structure, encodedValue, 0, Nullopt));
846 char* JIT_OPERATION operationNewFloat32ArrayWithSize(
847 ExecState* exec, Structure* structure, int32_t length)
849 return newTypedArrayWithSize<JSFloat32Array>(exec, structure, length);
852 char* JIT_OPERATION operationNewFloat32ArrayWithOneArgument(
853 ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
855 return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSFloat32Array>(exec, structure, encodedValue, 0, Nullopt));
858 char* JIT_OPERATION operationNewFloat64ArrayWithSize(
859 ExecState* exec, Structure* structure, int32_t length)
861 return newTypedArrayWithSize<JSFloat64Array>(exec, structure, length);
864 char* JIT_OPERATION operationNewFloat64ArrayWithOneArgument(
865 ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
867 return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSFloat64Array>(exec, structure, encodedValue, 0, Nullopt));
870 JSCell* JIT_OPERATION operationCreateActivationDirect(ExecState* exec, Structure* structure, JSScope* scope, SymbolTable* table, EncodedJSValue initialValueEncoded)
872 JSValue initialValue = JSValue::decode(initialValueEncoded);
873 ASSERT(initialValue == jsUndefined() || initialValue == jsTDZValue());
875 NativeCallFrameTracer tracer(&vm, exec);
876 return JSLexicalEnvironment::create(vm, structure, scope, table, initialValue);
879 JSCell* JIT_OPERATION operationCreateDirectArguments(ExecState* exec, Structure* structure, int32_t length, int32_t minCapacity)
882 NativeCallFrameTracer target(&vm, exec);
883 DirectArguments* result = DirectArguments::create(
884 vm, structure, length, std::max(length, minCapacity));
885 // The caller will store to this object without barriers. Most likely, at this point, this is
886 // still a young object and so no barriers are needed. But it's good to be careful anyway,
887 // since the GC should be allowed to do crazy (like pretenuring, for example).
888 vm.heap.writeBarrier(result);
892 JSCell* JIT_OPERATION operationCreateScopedArguments(ExecState* exec, Structure* structure, Register* argumentStart, int32_t length, JSFunction* callee, JSLexicalEnvironment* scope)
895 NativeCallFrameTracer target(&vm, exec);
897 // We could pass the ScopedArgumentsTable* as an argument. We currently don't because I
898 // didn't feel like changing the max number of arguments for a slow path call from 6 to 7.
899 ScopedArgumentsTable* table = scope->symbolTable()->arguments();
901 return ScopedArguments::createByCopyingFrom(
902 vm, structure, argumentStart, length, callee, table, scope);
905 JSCell* JIT_OPERATION operationCreateClonedArguments(ExecState* exec, Structure* structure, Register* argumentStart, int32_t length, JSFunction* callee)
908 NativeCallFrameTracer target(&vm, exec);
909 return ClonedArguments::createByCopyingFrom(
910 exec, structure, argumentStart, length, callee);
913 JSCell* JIT_OPERATION operationCreateDirectArgumentsDuringExit(ExecState* exec, InlineCallFrame* inlineCallFrame, JSFunction* callee, int32_t argumentCount)
916 NativeCallFrameTracer target(&vm, exec);
918 DeferGCForAWhile deferGC(vm.heap);
920 CodeBlock* codeBlock;
922 codeBlock = baselineCodeBlockForInlineCallFrame(inlineCallFrame);
924 codeBlock = exec->codeBlock();
926 unsigned length = argumentCount - 1;
927 unsigned capacity = std::max(length, static_cast<unsigned>(codeBlock->numParameters() - 1));
928 DirectArguments* result = DirectArguments::create(
929 vm, codeBlock->globalObject()->directArgumentsStructure(), length, capacity);
931 result->callee().set(vm, result, callee);
933 Register* arguments =
934 exec->registers() + (inlineCallFrame ? inlineCallFrame->stackOffset : 0) +
935 CallFrame::argumentOffset(0);
936 for (unsigned i = length; i--;)
937 result->setIndexQuickly(vm, i, arguments[i].jsValue());
942 JSCell* JIT_OPERATION operationCreateClonedArgumentsDuringExit(ExecState* exec, InlineCallFrame* inlineCallFrame, JSFunction* callee, int32_t argumentCount)
945 NativeCallFrameTracer target(&vm, exec);
947 DeferGCForAWhile deferGC(vm.heap);
949 CodeBlock* codeBlock;
951 codeBlock = baselineCodeBlockForInlineCallFrame(inlineCallFrame);
953 codeBlock = exec->codeBlock();
955 unsigned length = argumentCount - 1;
956 ClonedArguments* result = ClonedArguments::createEmpty(
957 vm, codeBlock->globalObject()->outOfBandArgumentsStructure(), callee);
959 Register* arguments =
960 exec->registers() + (inlineCallFrame ? inlineCallFrame->stackOffset : 0) +
961 CallFrame::argumentOffset(0);
962 for (unsigned i = length; i--;)
963 result->putDirectIndex(exec, i, arguments[i].jsValue());
965 result->putDirect(vm, vm.propertyNames->length, jsNumber(length));
970 void JIT_OPERATION operationCopyRest(ExecState* exec, JSCell* arrayAsCell, Register* argumentStart, unsigned numberOfParamsToSkip, unsigned arraySize)
973 JSArray* array = jsCast<JSArray*>(arrayAsCell);
974 ASSERT(arraySize == array->length());
975 array->setLength(exec, arraySize);
976 for (unsigned i = 0; i < arraySize; i++)
977 array->putDirectIndex(exec, i, argumentStart[i + numberOfParamsToSkip].jsValue());
980 size_t JIT_OPERATION operationObjectIsObject(ExecState* exec, JSGlobalObject* globalObject, JSCell* object)
983 NativeCallFrameTracer tracer(&vm, exec);
985 ASSERT(jsDynamicCast<JSObject*>(object));
987 if (object->structure(vm)->masqueradesAsUndefined(globalObject))
989 if (object->type() == JSFunctionType)
991 if (object->inlineTypeFlags() & TypeOfShouldCallGetCallData) {
993 if (object->methodTable(vm)->getCallData(object, callData) != CallTypeNone)
1000 size_t JIT_OPERATION operationObjectIsFunction(ExecState* exec, JSGlobalObject* globalObject, JSCell* object)
1002 VM& vm = exec->vm();
1003 NativeCallFrameTracer tracer(&vm, exec);
1005 ASSERT(jsDynamicCast<JSObject*>(object));
1007 if (object->structure(vm)->masqueradesAsUndefined(globalObject))
1009 if (object->type() == JSFunctionType)
1011 if (object->inlineTypeFlags() & TypeOfShouldCallGetCallData) {
1013 if (object->methodTable(vm)->getCallData(object, callData) != CallTypeNone)
1020 JSCell* JIT_OPERATION operationTypeOfObject(ExecState* exec, JSGlobalObject* globalObject, JSCell* object)
1022 VM& vm = exec->vm();
1023 NativeCallFrameTracer tracer(&vm, exec);
1025 ASSERT(jsDynamicCast<JSObject*>(object));
1027 if (object->structure(vm)->masqueradesAsUndefined(globalObject))
1028 return vm.smallStrings.undefinedString();
1029 if (object->type() == JSFunctionType)
1030 return vm.smallStrings.functionString();
1031 if (object->inlineTypeFlags() & TypeOfShouldCallGetCallData) {
1033 if (object->methodTable(vm)->getCallData(object, callData) != CallTypeNone)
1034 return vm.smallStrings.functionString();
1037 return vm.smallStrings.objectString();
1040 int32_t JIT_OPERATION operationTypeOfObjectAsTypeofType(ExecState* exec, JSGlobalObject* globalObject, JSCell* object)
1042 VM& vm = exec->vm();
1043 NativeCallFrameTracer tracer(&vm, exec);
1045 ASSERT(jsDynamicCast<JSObject*>(object));
1047 if (object->structure(vm)->masqueradesAsUndefined(globalObject))
1048 return static_cast<int32_t>(TypeofType::Undefined);
1049 if (object->type() == JSFunctionType)
1050 return static_cast<int32_t>(TypeofType::Function);
1051 if (object->inlineTypeFlags() & TypeOfShouldCallGetCallData) {
1053 if (object->methodTable(vm)->getCallData(object, callData) != CallTypeNone)
1054 return static_cast<int32_t>(TypeofType::Function);
1057 return static_cast<int32_t>(TypeofType::Object);
1060 char* JIT_OPERATION operationAllocatePropertyStorageWithInitialCapacity(ExecState* exec)
1062 VM& vm = exec->vm();
1063 NativeCallFrameTracer tracer(&vm, exec);
1065 return reinterpret_cast<char*>(
1066 Butterfly::createUninitialized(vm, 0, 0, initialOutOfLineCapacity, false, 0));
1069 char* JIT_OPERATION operationAllocatePropertyStorage(ExecState* exec, size_t newSize)
1071 VM& vm = exec->vm();
1072 NativeCallFrameTracer tracer(&vm, exec);
1074 return reinterpret_cast<char*>(
1075 Butterfly::createUninitialized(vm, 0, 0, newSize, false, 0));
1078 char* JIT_OPERATION operationReallocateButterflyToHavePropertyStorageWithInitialCapacity(ExecState* exec, JSObject* object)
1080 VM& vm = exec->vm();
1081 NativeCallFrameTracer tracer(&vm, exec);
1083 ASSERT(!object->structure()->outOfLineCapacity());
1084 DeferGC deferGC(vm.heap);
1085 Butterfly* result = object->growOutOfLineStorage(vm, 0, initialOutOfLineCapacity);
1086 object->setButterflyWithoutChangingStructure(vm, result);
1087 return reinterpret_cast<char*>(result);
1090 char* JIT_OPERATION operationReallocateButterflyToGrowPropertyStorage(ExecState* exec, JSObject* object, size_t newSize)
1092 VM& vm = exec->vm();
1093 NativeCallFrameTracer tracer(&vm, exec);
1095 DeferGC deferGC(vm.heap);
1096 Butterfly* result = object->growOutOfLineStorage(vm, object->structure()->outOfLineCapacity(), newSize);
1097 object->setButterflyWithoutChangingStructure(vm, result);
1098 return reinterpret_cast<char*>(result);
1101 char* JIT_OPERATION operationEnsureInt32(ExecState* exec, JSCell* cell)
1103 VM& vm = exec->vm();
1104 NativeCallFrameTracer tracer(&vm, exec);
1106 if (!cell->isObject())
1109 return reinterpret_cast<char*>(asObject(cell)->ensureInt32(vm).data());
1112 char* JIT_OPERATION operationEnsureDouble(ExecState* exec, JSCell* cell)
1114 VM& vm = exec->vm();
1115 NativeCallFrameTracer tracer(&vm, exec);
1117 if (!cell->isObject())
1120 return reinterpret_cast<char*>(asObject(cell)->ensureDouble(vm).data());
1123 char* JIT_OPERATION operationEnsureContiguous(ExecState* exec, JSCell* cell)
1125 VM& vm = exec->vm();
1126 NativeCallFrameTracer tracer(&vm, exec);
1128 if (!cell->isObject())
1131 return reinterpret_cast<char*>(asObject(cell)->ensureContiguous(vm).data());
1134 char* JIT_OPERATION operationEnsureArrayStorage(ExecState* exec, JSCell* cell)
1136 VM& vm = exec->vm();
1137 NativeCallFrameTracer tracer(&vm, exec);
1139 if (!cell->isObject())
1142 return reinterpret_cast<char*>(asObject(cell)->ensureArrayStorage(vm));
1145 StringImpl* JIT_OPERATION operationResolveRope(ExecState* exec, JSString* string)
1147 VM& vm = exec->vm();
1148 NativeCallFrameTracer tracer(&vm, exec);
1150 return string->value(exec).impl();
1153 JSString* JIT_OPERATION operationSingleCharacterString(ExecState* exec, int32_t character)
1155 VM& vm = exec->vm();
1156 NativeCallFrameTracer tracer(&vm, exec);
1158 return jsSingleCharacterString(exec, static_cast<UChar>(character));
1161 JSCell* JIT_OPERATION operationNewStringObject(ExecState* exec, JSString* string, Structure* structure)
1163 VM& vm = exec->vm();
1164 NativeCallFrameTracer tracer(&vm, exec);
1166 return StringObject::create(vm, structure, string);
1169 JSCell* JIT_OPERATION operationToStringOnCell(ExecState* exec, JSCell* cell)
1171 VM& vm = exec->vm();
1172 NativeCallFrameTracer tracer(&vm, exec);
1174 return JSValue(cell).toString(exec);
1177 JSCell* JIT_OPERATION operationToString(ExecState* exec, EncodedJSValue value)
1179 VM& vm = exec->vm();
1180 NativeCallFrameTracer tracer(&vm, exec);
1182 return JSValue::decode(value).toString(exec);
1185 JSCell* JIT_OPERATION operationCallStringConstructorOnCell(ExecState* exec, JSCell* cell)
1187 VM& vm = exec->vm();
1188 NativeCallFrameTracer tracer(&vm, exec);
1190 return stringConstructor(exec, cell);
1193 JSCell* JIT_OPERATION operationCallStringConstructor(ExecState* exec, EncodedJSValue value)
1195 VM& vm = exec->vm();
1196 NativeCallFrameTracer tracer(&vm, exec);
1198 return stringConstructor(exec, JSValue::decode(value));
1201 JSCell* JIT_OPERATION operationMakeRope2(ExecState* exec, JSString* left, JSString* right)
1203 VM& vm = exec->vm();
1204 NativeCallFrameTracer tracer(&vm, exec);
1206 if (sumOverflows<int32_t>(left->length(), right->length())) {
1207 throwOutOfMemoryError(exec);
1211 return JSRopeString::create(vm, left, right);
1214 JSCell* JIT_OPERATION operationMakeRope3(ExecState* exec, JSString* a, JSString* b, JSString* c)
1216 VM& vm = exec->vm();
1217 NativeCallFrameTracer tracer(&vm, exec);
1219 if (sumOverflows<int32_t>(a->length(), b->length(), c->length())) {
1220 throwOutOfMemoryError(exec);
1224 return JSRopeString::create(vm, a, b, c);
1227 JSCell* JIT_OPERATION operationStrCat2(ExecState* exec, EncodedJSValue a, EncodedJSValue b)
1229 VM& vm = exec->vm();
1230 NativeCallFrameTracer tracer(&vm, exec);
1232 JSString* str1 = JSValue::decode(a).toString(exec);
1233 ASSERT(!vm.exception()); // Impossible, since we must have been given primitives.
1234 JSString* str2 = JSValue::decode(b).toString(exec);
1235 ASSERT(!vm.exception());
1237 if (sumOverflows<int32_t>(str1->length(), str2->length())) {
1238 throwOutOfMemoryError(exec);
1242 return JSRopeString::create(vm, str1, str2);
1245 JSCell* JIT_OPERATION operationStrCat3(ExecState* exec, EncodedJSValue a, EncodedJSValue b, EncodedJSValue c)
1247 VM& vm = exec->vm();
1248 NativeCallFrameTracer tracer(&vm, exec);
1250 JSString* str1 = JSValue::decode(a).toString(exec);
1251 ASSERT(!vm.exception()); // Impossible, since we must have been given primitives.
1252 JSString* str2 = JSValue::decode(b).toString(exec);
1253 ASSERT(!vm.exception());
1254 JSString* str3 = JSValue::decode(c).toString(exec);
1255 ASSERT(!vm.exception());
1257 if (sumOverflows<int32_t>(str1->length(), str2->length(), str3->length())) {
1258 throwOutOfMemoryError(exec);
1262 return JSRopeString::create(vm, str1, str2, str3);
1265 char* JIT_OPERATION operationFindSwitchImmTargetForDouble(
1266 ExecState* exec, EncodedJSValue encodedValue, size_t tableIndex)
1268 CodeBlock* codeBlock = exec->codeBlock();
1269 SimpleJumpTable& table = codeBlock->switchJumpTable(tableIndex);
1270 JSValue value = JSValue::decode(encodedValue);
1271 ASSERT(value.isDouble());
1272 double asDouble = value.asDouble();
1273 int32_t asInt32 = static_cast<int32_t>(asDouble);
1274 if (asDouble == asInt32)
1275 return static_cast<char*>(table.ctiForValue(asInt32).executableAddress());
1276 return static_cast<char*>(table.ctiDefault.executableAddress());
1279 char* JIT_OPERATION operationSwitchString(ExecState* exec, size_t tableIndex, JSString* string)
1281 VM& vm = exec->vm();
1282 NativeCallFrameTracer tracer(&vm, exec);
1284 return static_cast<char*>(exec->codeBlock()->stringSwitchJumpTable(tableIndex).ctiForValue(string->value(exec).impl()).executableAddress());
1287 int32_t JIT_OPERATION operationSwitchStringAndGetBranchOffset(ExecState* exec, size_t tableIndex, JSString* string)
1289 VM& vm = exec->vm();
1290 NativeCallFrameTracer tracer(&vm, exec);
1292 return exec->codeBlock()->stringSwitchJumpTable(tableIndex).offsetForValue(string->value(exec).impl(), std::numeric_limits<int32_t>::min());
1295 char* JIT_OPERATION operationGetButterfly(ExecState* exec, JSCell* cell)
1297 VM& vm = exec->vm();
1298 NativeCallFrameTracer tracer(&vm, exec);
1300 return bitwise_cast<char*>(jsCast<JSObject*>(cell)->butterfly());
1303 char* JIT_OPERATION operationGetArrayBufferVector(ExecState* exec, JSCell* cell)
1305 VM& vm = exec->vm();
1306 NativeCallFrameTracer tracer(&vm, exec);
1308 return bitwise_cast<char*>(jsCast<JSArrayBufferView*>(cell)->vector());
1311 void JIT_OPERATION operationNotifyWrite(ExecState* exec, WatchpointSet* set)
1313 VM& vm = exec->vm();
1314 NativeCallFrameTracer tracer(&vm, exec);
1316 set->touch("Executed NotifyWrite");
1319 void JIT_OPERATION operationThrowStackOverflowForVarargs(ExecState* exec)
1321 VM& vm = exec->vm();
1322 NativeCallFrameTracer tracer(&vm, exec);
1323 throwStackOverflowError(exec);
1326 int32_t JIT_OPERATION operationSizeOfVarargs(ExecState* exec, EncodedJSValue encodedArguments, int32_t firstVarArgOffset)
1328 VM& vm = exec->vm();
1329 NativeCallFrameTracer tracer(&vm, exec);
1330 JSValue arguments = JSValue::decode(encodedArguments);
1332 return sizeOfVarargs(exec, arguments, firstVarArgOffset);
1335 void JIT_OPERATION operationLoadVarargs(ExecState* exec, int32_t firstElementDest, EncodedJSValue encodedArguments, int32_t offset, int32_t length, int32_t mandatoryMinimum)
1337 VM& vm = exec->vm();
1338 NativeCallFrameTracer tracer(&vm, exec);
1339 JSValue arguments = JSValue::decode(encodedArguments);
1341 loadVarargs(exec, VirtualRegister(firstElementDest), arguments, offset, length);
1343 for (int32_t i = length; i < mandatoryMinimum; ++i)
1344 exec->r(firstElementDest + i) = jsUndefined();
1347 double JIT_OPERATION operationFModOnInts(int32_t a, int32_t b)
1352 #if USE(JSVALUE32_64)
1353 double JIT_OPERATION operationRandom(JSGlobalObject* globalObject)
1355 return globalObject->weakRandomNumber();
1359 JSCell* JIT_OPERATION operationStringFromCharCode(ExecState* exec, int32_t op1)
1361 VM* vm = &exec->vm();
1362 NativeCallFrameTracer tracer(vm, exec);
1363 return JSC::stringFromCharCode(exec, op1);
1366 EncodedJSValue JIT_OPERATION operationStringFromCharCodeUntyped(ExecState* exec, EncodedJSValue encodedValue)
1368 VM* vm = &exec->vm();
1369 NativeCallFrameTracer tracer(vm, exec);
1370 JSValue charValue = JSValue::decode(encodedValue);
1371 int32_t chInt = charValue.toUInt32(exec);
1372 return JSValue::encode(JSC::stringFromCharCode(exec, chInt));
1375 int64_t JIT_OPERATION operationConvertBoxedDoubleToInt52(EncodedJSValue encodedValue)
1377 JSValue value = JSValue::decode(encodedValue);
1378 if (!value.isDouble())
1379 return JSValue::notInt52;
1380 return tryConvertToInt52(value.asDouble());
1383 int64_t JIT_OPERATION operationConvertDoubleToInt52(double value)
1385 return tryConvertToInt52(value);
1388 void JIT_OPERATION operationProcessTypeProfilerLogDFG(ExecState* exec)
1390 exec->vm().typeProfilerLog()->processLogEntries(ASCIILiteral("Log Full, called from inside DFG."));
1393 void JIT_OPERATION debugOperationPrintSpeculationFailure(ExecState* exec, void* debugInfoRaw, void* scratch)
1395 VM* vm = &exec->vm();
1396 NativeCallFrameTracer tracer(vm, exec);
1398 SpeculationFailureDebugInfo* debugInfo = static_cast<SpeculationFailureDebugInfo*>(debugInfoRaw);
1399 CodeBlock* codeBlock = debugInfo->codeBlock;
1400 CodeBlock* alternative = codeBlock->alternative();
1401 dataLog("Speculation failure in ", *codeBlock);
1402 dataLog(" @ exit #", vm->osrExitIndex, " (bc#", debugInfo->bytecodeOffset, ", ", exitKindToString(debugInfo->kind), ") with ");
1405 "executeCounter = ", alternative->jitExecuteCounter(),
1406 ", reoptimizationRetryCounter = ", alternative->reoptimizationRetryCounter(),
1407 ", optimizationDelayCounter = ", alternative->optimizationDelayCounter());
1409 dataLog("no alternative code block (i.e. we've been jettisoned)");
1410 dataLog(", osrExitCounter = ", codeBlock->osrExitCounter(), "\n");
1411 dataLog(" GPRs at time of exit:");
1412 char* scratchPointer = static_cast<char*>(scratch);
1413 for (unsigned i = 0; i < GPRInfo::numberOfRegisters; ++i) {
1414 GPRReg gpr = GPRInfo::toRegister(i);
1415 dataLog(" ", GPRInfo::debugName(gpr), ":", RawPointer(*reinterpret_cast_ptr<void**>(scratchPointer)));
1416 scratchPointer += sizeof(EncodedJSValue);
1419 dataLog(" FPRs at time of exit:");
1420 for (unsigned i = 0; i < FPRInfo::numberOfRegisters; ++i) {
1421 FPRReg fpr = FPRInfo::toRegister(i);
1422 dataLog(" ", FPRInfo::debugName(fpr), ":");
1423 uint64_t bits = *reinterpret_cast_ptr<uint64_t*>(scratchPointer);
1424 double value = *reinterpret_cast_ptr<double*>(scratchPointer);
1425 dataLogF("%llx:%lf", static_cast<long long>(bits), value);
1426 scratchPointer += sizeof(EncodedJSValue);
1431 extern "C" void JIT_OPERATION triggerReoptimizationNow(CodeBlock* codeBlock, OSRExitBase* exit)
1433 // It's sort of preferable that we don't GC while in here. Anyways, doing so wouldn't
1434 // really be profitable.
1435 DeferGCForAWhile deferGC(codeBlock->vm()->heap);
1437 if (Options::verboseOSR())
1438 dataLog(*codeBlock, ": Entered reoptimize\n");
1439 // We must be called with the baseline code block.
1440 ASSERT(JITCode::isBaselineCode(codeBlock->jitType()));
1442 // If I am my own replacement, then reoptimization has already been triggered.
1443 // This can happen in recursive functions.
1444 if (codeBlock->replacement() == codeBlock) {
1445 if (Options::verboseOSR())
1446 dataLog(*codeBlock, ": Not reoptimizing because we've already been jettisoned.\n");
1450 // Otherwise, the replacement must be optimized code. Use this as an opportunity
1451 // to check our logic.
1452 ASSERT(codeBlock->hasOptimizedReplacement());
1453 CodeBlock* optimizedCodeBlock = codeBlock->replacement();
1454 ASSERT(JITCode::isOptimizingJIT(optimizedCodeBlock->jitType()));
1456 bool didTryToEnterIntoInlinedLoops = false;
1457 for (InlineCallFrame* inlineCallFrame = exit->m_codeOrigin.inlineCallFrame; inlineCallFrame; inlineCallFrame = inlineCallFrame->directCaller.inlineCallFrame) {
1458 if (inlineCallFrame->baselineCodeBlock->ownerScriptExecutable()->didTryToEnterInLoop()) {
1459 didTryToEnterIntoInlinedLoops = true;
1464 // In order to trigger reoptimization, one of two things must have happened:
1465 // 1) We exited more than some number of times.
1466 // 2) We exited and got stuck in a loop, and now we're exiting again.
1467 bool didExitABunch = optimizedCodeBlock->shouldReoptimizeNow();
1468 bool didGetStuckInLoop =
1469 (codeBlock->checkIfOptimizationThresholdReached() || didTryToEnterIntoInlinedLoops)
1470 && optimizedCodeBlock->shouldReoptimizeFromLoopNow();
1472 if (!didExitABunch && !didGetStuckInLoop) {
1473 if (Options::verboseOSR())
1474 dataLog(*codeBlock, ": Not reoptimizing ", *optimizedCodeBlock, " because it either didn't exit enough or didn't loop enough after exit.\n");
1475 codeBlock->optimizeAfterLongWarmUp();
1479 optimizedCodeBlock->jettison(Profiler::JettisonDueToOSRExit, CountReoptimization);
1483 static bool shouldTriggerFTLCompile(CodeBlock* codeBlock, JITCode* jitCode)
1485 if (codeBlock->baselineVersion()->m_didFailFTLCompilation) {
1486 if (Options::verboseOSR())
1487 dataLog("Deferring FTL-optimization of ", *codeBlock, " indefinitely because there was an FTL failure.\n");
1488 jitCode->dontOptimizeAnytimeSoon(codeBlock);
1492 if (!codeBlock->hasOptimizedReplacement()
1493 && !jitCode->checkIfOptimizationThresholdReached(codeBlock)) {
1494 if (Options::verboseOSR())
1495 dataLog("Choosing not to FTL-optimize ", *codeBlock, " yet.\n");
1501 static void triggerFTLReplacementCompile(VM* vm, CodeBlock* codeBlock, JITCode* jitCode)
1503 Worklist::State worklistState;
1504 if (Worklist* worklist = existingGlobalFTLWorklistOrNull()) {
1505 worklistState = worklist->completeAllReadyPlansForVM(
1506 *vm, CompilationKey(codeBlock->baselineVersion(), FTLMode));
1508 worklistState = Worklist::NotKnown;
1510 if (worklistState == Worklist::Compiling) {
1511 jitCode->setOptimizationThresholdBasedOnCompilationResult(
1512 codeBlock, CompilationDeferred);
1516 if (codeBlock->hasOptimizedReplacement()) {
1517 // That's great, we've compiled the code - next time we call this function,
1518 // we'll enter that replacement.
1519 jitCode->optimizeSoon(codeBlock);
1523 if (worklistState == Worklist::Compiled) {
1524 // This means that we finished compiling, but failed somehow; in that case the
1525 // thresholds will be set appropriately.
1526 if (Options::verboseOSR())
1527 dataLog("Code block ", *codeBlock, " was compiled but it doesn't have an optimized replacement.\n");
1531 // We need to compile the code.
1533 *vm, codeBlock->newReplacement(), codeBlock, FTLMode, UINT_MAX,
1534 Operands<JSValue>(), ToFTLDeferredCompilationCallback::create());
1536 // If we reached here, the counter has not be reset. Do that now.
1537 jitCode->setOptimizationThresholdBasedOnCompilationResult(
1538 codeBlock, CompilationDeferred);
1541 static void triggerTierUpNowCommon(ExecState* exec, bool inLoop)
1543 VM* vm = &exec->vm();
1544 NativeCallFrameTracer tracer(vm, exec);
1545 DeferGC deferGC(vm->heap);
1546 CodeBlock* codeBlock = exec->codeBlock();
1548 if (codeBlock->jitType() != JITCode::DFGJIT) {
1549 dataLog("Unexpected code block in DFG->FTL tier-up: ", *codeBlock, "\n");
1550 RELEASE_ASSERT_NOT_REACHED();
1553 JITCode* jitCode = codeBlock->jitCode()->dfg();
1555 if (Options::verboseOSR()) {
1557 *codeBlock, ": Entered triggerTierUpNow with executeCounter = ",
1558 jitCode->tierUpCounter, "\n");
1561 jitCode->nestedTriggerIsSet = 1;
1563 if (shouldTriggerFTLCompile(codeBlock, jitCode))
1564 triggerFTLReplacementCompile(vm, codeBlock, jitCode);
1567 void JIT_OPERATION triggerTierUpNow(ExecState* exec)
1569 triggerTierUpNowCommon(exec, false);
1572 void JIT_OPERATION triggerTierUpNowInLoop(ExecState* exec)
1574 triggerTierUpNowCommon(exec, true);
1577 char* JIT_OPERATION triggerOSREntryNow(
1578 ExecState* exec, int32_t bytecodeIndex, int32_t streamIndex)
1580 VM* vm = &exec->vm();
1581 NativeCallFrameTracer tracer(vm, exec);
1582 DeferGC deferGC(vm->heap);
1583 CodeBlock* codeBlock = exec->codeBlock();
1585 if (codeBlock->jitType() != JITCode::DFGJIT) {
1586 dataLog("Unexpected code block in DFG->FTL tier-up: ", *codeBlock, "\n");
1587 RELEASE_ASSERT_NOT_REACHED();
1590 JITCode* jitCode = codeBlock->jitCode()->dfg();
1591 jitCode->nestedTriggerIsSet = 0;
1593 if (Options::verboseOSR()) {
1595 *codeBlock, ": Entered triggerOSREntryNow with executeCounter = ",
1596 jitCode->tierUpCounter, "\n");
1599 // - If we don't have an FTL code block, then try to compile one.
1600 // - If we do have an FTL code block, then try to enter for a while.
1601 // - If we couldn't enter for a while, then trigger OSR entry.
1603 if (!shouldTriggerFTLCompile(codeBlock, jitCode))
1606 if (!jitCode->neverExecutedEntry) {
1607 triggerFTLReplacementCompile(vm, codeBlock, jitCode);
1609 if (!codeBlock->hasOptimizedReplacement())
1612 if (jitCode->osrEntryRetry < Options::ftlOSREntryRetryThreshold()) {
1613 jitCode->osrEntryRetry++;
1618 // It's time to try to compile code for OSR entry.
1619 Worklist::State worklistState;
1620 if (Worklist* worklist = existingGlobalFTLWorklistOrNull()) {
1621 worklistState = worklist->completeAllReadyPlansForVM(
1622 *vm, CompilationKey(codeBlock->baselineVersion(), FTLForOSREntryMode));
1624 worklistState = Worklist::NotKnown;
1626 if (worklistState == Worklist::Compiling) {
1627 jitCode->setOptimizationThresholdBasedOnCompilationResult(
1628 codeBlock, CompilationDeferred);
1632 if (CodeBlock* entryBlock = jitCode->osrEntryBlock()) {
1633 void* address = FTL::prepareOSREntry(
1634 exec, codeBlock, entryBlock, bytecodeIndex, streamIndex);
1636 return static_cast<char*>(address);
1638 if (jitCode->osrEntryRetry < Options::ftlOSREntryRetryThreshold()) {
1639 jitCode->osrEntryRetry++;
1643 FTL::ForOSREntryJITCode* entryCode = entryBlock->jitCode()->ftlForOSREntry();
1644 entryCode->countEntryFailure();
1645 if (entryCode->entryFailureCount() <
1646 Options::ftlOSREntryFailureCountForReoptimization()) {
1647 jitCode->optimizeSoon(codeBlock);
1651 // OSR entry failed. Oh no! This implies that we need to retry. We retry
1652 // without exponential backoff and we only do this for the entry code block.
1653 jitCode->clearOSREntryBlock();
1654 jitCode->osrEntryRetry = 0;
1658 if (worklistState == Worklist::Compiled) {
1659 // This means that compilation failed and we already set the thresholds.
1660 if (Options::verboseOSR())
1661 dataLog("Code block ", *codeBlock, " was compiled but it doesn't have an optimized replacement.\n");
1665 // We aren't compiling and haven't compiled anything for OSR entry. So, try to compile
1667 Operands<JSValue> mustHandleValues;
1668 jitCode->reconstruct(
1669 exec, codeBlock, CodeOrigin(bytecodeIndex), streamIndex, mustHandleValues);
1670 CodeBlock* replacementCodeBlock = codeBlock->newReplacement();
1671 CompilationResult forEntryResult = compile(
1672 *vm, replacementCodeBlock, codeBlock, FTLForOSREntryMode, bytecodeIndex,
1673 mustHandleValues, ToFTLForOSREntryDeferredCompilationCallback::create());
1675 if (jitCode->neverExecutedEntry)
1676 triggerFTLReplacementCompile(vm, codeBlock, jitCode);
1678 if (forEntryResult != CompilationSuccessful) {
1679 jitCode->setOptimizationThresholdBasedOnCompilationResult(
1680 codeBlock, CompilationDeferred);
1684 // It's possible that the for-entry compile already succeeded. In that case OSR
1685 // entry will succeed unless we ran out of stack. It's not clear what we should do.
1686 // We signal to try again after a while if that happens.
1687 void* address = FTL::prepareOSREntry(
1688 exec, codeBlock, jitCode->osrEntryBlock(), bytecodeIndex, streamIndex);
1689 return static_cast<char*>(address);
1692 #endif // ENABLE(FTL_JIT)
1695 } } // namespace JSC::DFG
1697 #endif // ENABLE(DFG_JIT)
1699 #endif // ENABLE(JIT)