2 * Copyright (C) 2011-2017 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 "ArrayConstructor.h"
30 #include "ButterflyInlines.h"
31 #include "ClonedArguments.h"
32 #include "CodeBlock.h"
33 #include "CommonSlowPaths.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 "DefinePropertyAttributes.h"
42 #include "DirectArguments.h"
43 #include "FTLForOSREntryJITCode.h"
44 #include "FTLOSREntry.h"
45 #include "FrameTracers.h"
46 #include "HasOwnPropertyCache.h"
47 #include "HostCallReturnValue.h"
48 #include "Interpreter.h"
50 #include "JITExceptions.h"
51 #include "JSArrayInlines.h"
52 #include "JSCInlines.h"
53 #include "JSFixedArray.h"
54 #include "JSGenericTypedArrayViewConstructorInlines.h"
55 #include "JSGlobalObjectFunctions.h"
56 #include "JSLexicalEnvironment.h"
59 #include "JSWeakMap.h"
60 #include "ObjectConstructor.h"
61 #include "Operations.h"
63 #include "RegExpObject.h"
65 #include "ScopedArguments.h"
66 #include "StringConstructor.h"
67 #include "SuperSampler.h"
69 #include "TypeProfilerLog.h"
70 #include "TypedArrayInlines.h"
71 #include "VMInlines.h"
72 #include <wtf/InlineASM.h>
77 namespace JSC { namespace DFG {
79 template<bool strict, bool direct>
80 static inline void putByVal(ExecState* exec, VM& vm, JSValue baseValue, uint32_t index, JSValue value)
82 ASSERT(isIndex(index));
84 RELEASE_ASSERT(baseValue.isObject());
85 asObject(baseValue)->putDirectIndex(exec, index, value, 0, strict ? PutDirectIndexShouldThrow : PutDirectIndexShouldNotThrow);
88 if (baseValue.isObject()) {
89 JSObject* object = asObject(baseValue);
90 if (object->canSetIndexQuickly(index)) {
91 object->setIndexQuickly(vm, index, value);
95 object->methodTable(vm)->putByIndex(object, exec, index, value, strict);
99 baseValue.putByIndex(exec, index, value, strict);
102 template<bool strict, bool direct>
103 ALWAYS_INLINE static void putByValInternal(ExecState* exec, VM& vm, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
105 auto scope = DECLARE_THROW_SCOPE(vm);
107 JSValue baseValue = JSValue::decode(encodedBase);
108 JSValue property = JSValue::decode(encodedProperty);
109 JSValue value = JSValue::decode(encodedValue);
111 if (LIKELY(property.isUInt32())) {
112 // Despite its name, JSValue::isUInt32 will return true only for positive boxed int32_t; all those values are valid array indices.
113 ASSERT(isIndex(property.asUInt32()));
115 putByVal<strict, direct>(exec, vm, baseValue, property.asUInt32(), value);
119 if (property.isDouble()) {
120 double propertyAsDouble = property.asDouble();
121 uint32_t propertyAsUInt32 = static_cast<uint32_t>(propertyAsDouble);
122 if (propertyAsDouble == propertyAsUInt32 && isIndex(propertyAsUInt32)) {
124 putByVal<strict, direct>(exec, vm, baseValue, propertyAsUInt32, value);
129 // Don't put to an object if toString throws an exception.
130 auto propertyName = property.toPropertyKey(exec);
131 RETURN_IF_EXCEPTION(scope, void());
133 PutPropertySlot slot(baseValue, strict);
135 RELEASE_ASSERT(baseValue.isObject());
136 if (std::optional<uint32_t> index = parseIndex(propertyName)) {
138 asObject(baseValue)->putDirectIndex(exec, index.value(), value, 0, strict ? PutDirectIndexShouldThrow : PutDirectIndexShouldNotThrow);
141 asObject(baseValue)->putDirect(vm, propertyName, value, slot);
145 baseValue.put(exec, propertyName, value, slot);
148 template<bool strict, bool direct>
149 ALWAYS_INLINE static void putByValCellInternal(ExecState* exec, VM& vm, JSCell* base, PropertyName propertyName, JSValue value)
151 PutPropertySlot slot(base, strict);
153 RELEASE_ASSERT(base->isObject());
154 if (std::optional<uint32_t> index = parseIndex(propertyName))
155 asObject(base)->putDirectIndex(exec, index.value(), value, 0, strict ? PutDirectIndexShouldThrow : PutDirectIndexShouldNotThrow);
157 asObject(base)->putDirect(vm, propertyName, value, slot);
160 base->putInline(exec, propertyName, value, slot);
163 template<bool strict, bool direct>
164 ALWAYS_INLINE static void putByValCellStringInternal(ExecState* exec, VM& vm, JSCell* base, JSString* property, JSValue value)
166 auto scope = DECLARE_THROW_SCOPE(vm);
168 auto propertyName = property->toIdentifier(exec);
169 RETURN_IF_EXCEPTION(scope, void());
172 putByValCellInternal<strict, direct>(exec, vm, base, propertyName, value);
175 template<typename ViewClass>
176 char* newTypedArrayWithSize(ExecState* exec, Structure* structure, int32_t size, char* vector)
179 NativeCallFrameTracer tracer(&vm, exec);
180 auto scope = DECLARE_THROW_SCOPE(vm);
183 throwException(exec, scope, createRangeError(exec, ASCIILiteral("Requested length is negative")));
188 return bitwise_cast<char*>(ViewClass::createWithFastVector(exec, structure, size, vector));
191 return bitwise_cast<char*>(ViewClass::create(exec, structure, size));
194 template <bool strict>
195 static ALWAYS_INLINE void putWithThis(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedThis, EncodedJSValue encodedValue, const Identifier& ident)
197 JSValue baseValue = JSValue::decode(encodedBase);
198 JSValue thisVal = JSValue::decode(encodedThis);
199 JSValue putValue = JSValue::decode(encodedValue);
200 PutPropertySlot slot(thisVal, strict);
201 baseValue.putInline(exec, ident, putValue, slot);
204 static ALWAYS_INLINE EncodedJSValue parseIntResult(double input)
206 int asInt = static_cast<int>(input);
207 if (static_cast<double>(asInt) == input)
208 return JSValue::encode(jsNumber(asInt));
209 return JSValue::encode(jsNumber(input));
212 ALWAYS_INLINE static JSValue getByValObject(ExecState* exec, VM& vm, JSObject* base, PropertyName propertyName)
214 Structure& structure = *base->structure(vm);
215 if (JSCell::canUseFastGetOwnProperty(structure)) {
216 if (JSValue result = base->fastGetOwnProperty(vm, structure, propertyName))
219 return base->get(exec, propertyName);
224 EncodedJSValue JIT_OPERATION operationToThis(ExecState* exec, EncodedJSValue encodedOp)
226 VM* vm = &exec->vm();
227 NativeCallFrameTracer tracer(vm, exec);
229 return JSValue::encode(JSValue::decode(encodedOp).toThis(exec, NotStrictMode));
232 EncodedJSValue JIT_OPERATION operationToThisStrict(ExecState* exec, EncodedJSValue encodedOp)
234 VM* vm = &exec->vm();
235 NativeCallFrameTracer tracer(vm, exec);
237 return JSValue::encode(JSValue::decode(encodedOp).toThis(exec, StrictMode));
240 JSCell* JIT_OPERATION operationCreateThis(ExecState* exec, JSObject* constructor, int32_t inlineCapacity)
243 NativeCallFrameTracer tracer(&vm, exec);
244 auto scope = DECLARE_THROW_SCOPE(vm);
245 if (constructor->type() == JSFunctionType) {
246 auto rareData = jsCast<JSFunction*>(constructor)->rareData(exec, inlineCapacity);
247 RETURN_IF_EXCEPTION(scope, nullptr);
248 Structure* structure = rareData->objectAllocationProfile()->structure();
249 JSObject* result = constructEmptyObject(exec, structure);
250 if (structure->hasPolyProto()) {
251 JSObject* prototype = jsCast<JSFunction*>(constructor)->prototypeForConstruction(vm, exec);
252 result->putDirect(vm, knownPolyProtoOffset, prototype);
253 prototype->didBecomePrototype();
254 ASSERT_WITH_MESSAGE(!hasIndexedProperties(result->indexingType()), "We rely on JSFinalObject not starting out with an indexing type otherwise we would potentially need to convert to slow put storage");
259 JSValue proto = constructor->get(exec, vm.propertyNames->prototype);
260 RETURN_IF_EXCEPTION(scope, nullptr);
261 if (proto.isObject())
262 return constructEmptyObject(exec, asObject(proto));
263 return constructEmptyObject(exec);
266 JSCell* JIT_OPERATION operationCallObjectConstructor(ExecState* exec, JSGlobalObject* globalObject, EncodedJSValue encodedTarget)
268 VM* vm = &exec->vm();
269 NativeCallFrameTracer tracer(vm, exec);
271 JSValue value = JSValue::decode(encodedTarget);
272 ASSERT(!value.isObject());
274 if (value.isUndefinedOrNull())
275 return constructEmptyObject(exec, globalObject->objectPrototype());
276 return value.toObject(exec, globalObject);
279 JSCell* JIT_OPERATION operationToObject(ExecState* exec, JSGlobalObject* globalObject, EncodedJSValue encodedTarget, UniquedStringImpl* errorMessage)
281 VM* vm = &exec->vm();
282 NativeCallFrameTracer tracer(vm, exec);
283 auto scope = DECLARE_THROW_SCOPE(*vm);
285 JSValue value = JSValue::decode(encodedTarget);
286 ASSERT(!value.isObject());
288 if (UNLIKELY(value.isUndefinedOrNull())) {
289 if (errorMessage->length()) {
290 throwVMTypeError(exec, scope, errorMessage);
296 return value.toObject(exec, globalObject);
299 EncodedJSValue JIT_OPERATION operationValueBitAnd(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
301 VM* vm = &exec->vm();
302 NativeCallFrameTracer tracer(vm, exec);
303 auto scope = DECLARE_THROW_SCOPE(*vm);
305 JSValue op1 = JSValue::decode(encodedOp1);
306 JSValue op2 = JSValue::decode(encodedOp2);
308 int32_t a = op1.toInt32(exec);
309 RETURN_IF_EXCEPTION(scope, encodedJSValue());
311 int32_t b = op2.toInt32(exec);
312 return JSValue::encode(jsNumber(a & b));
315 EncodedJSValue JIT_OPERATION operationValueBitOr(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
317 VM* vm = &exec->vm();
318 NativeCallFrameTracer tracer(vm, exec);
319 auto scope = DECLARE_THROW_SCOPE(*vm);
321 JSValue op1 = JSValue::decode(encodedOp1);
322 JSValue op2 = JSValue::decode(encodedOp2);
324 int32_t a = op1.toInt32(exec);
325 RETURN_IF_EXCEPTION(scope, encodedJSValue());
327 int32_t b = op2.toInt32(exec);
328 return JSValue::encode(jsNumber(a | b));
331 EncodedJSValue JIT_OPERATION operationValueBitXor(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
333 VM* vm = &exec->vm();
334 NativeCallFrameTracer tracer(vm, exec);
335 auto scope = DECLARE_THROW_SCOPE(*vm);
337 JSValue op1 = JSValue::decode(encodedOp1);
338 JSValue op2 = JSValue::decode(encodedOp2);
340 int32_t a = op1.toInt32(exec);
341 RETURN_IF_EXCEPTION(scope, encodedJSValue());
343 int32_t b = op2.toInt32(exec);
344 return JSValue::encode(jsNumber(a ^ b));
347 EncodedJSValue JIT_OPERATION operationValueBitLShift(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
349 VM* vm = &exec->vm();
350 NativeCallFrameTracer tracer(vm, exec);
351 auto scope = DECLARE_THROW_SCOPE(*vm);
353 JSValue op1 = JSValue::decode(encodedOp1);
354 JSValue op2 = JSValue::decode(encodedOp2);
356 int32_t a = op1.toInt32(exec);
357 RETURN_IF_EXCEPTION(scope, encodedJSValue());
359 uint32_t b = op2.toUInt32(exec);
360 return JSValue::encode(jsNumber(a << (b & 0x1f)));
363 EncodedJSValue JIT_OPERATION operationValueBitRShift(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
365 VM* vm = &exec->vm();
366 NativeCallFrameTracer tracer(vm, exec);
367 auto scope = DECLARE_THROW_SCOPE(*vm);
369 JSValue op1 = JSValue::decode(encodedOp1);
370 JSValue op2 = JSValue::decode(encodedOp2);
372 int32_t a = op1.toInt32(exec);
373 RETURN_IF_EXCEPTION(scope, encodedJSValue());
375 uint32_t b = op2.toUInt32(exec);
376 return JSValue::encode(jsNumber(a >> (b & 0x1f)));
379 EncodedJSValue JIT_OPERATION operationValueBitURShift(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
381 VM* vm = &exec->vm();
382 NativeCallFrameTracer tracer(vm, exec);
383 auto scope = DECLARE_THROW_SCOPE(*vm);
385 JSValue op1 = JSValue::decode(encodedOp1);
386 JSValue op2 = JSValue::decode(encodedOp2);
388 uint32_t a = op1.toUInt32(exec);
389 RETURN_IF_EXCEPTION(scope, encodedJSValue());
391 uint32_t b = op2.toUInt32(exec);
392 return JSValue::encode(jsNumber(static_cast<int32_t>(a >> (b & 0x1f))));
395 EncodedJSValue JIT_OPERATION operationValueAddNotNumber(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
397 VM* vm = &exec->vm();
398 NativeCallFrameTracer tracer(vm, exec);
400 JSValue op1 = JSValue::decode(encodedOp1);
401 JSValue op2 = JSValue::decode(encodedOp2);
403 ASSERT(!op1.isNumber() || !op2.isNumber());
405 if (op1.isString() && !op2.isObject())
406 return JSValue::encode(jsString(exec, asString(op1), op2.toString(exec)));
408 return JSValue::encode(jsAddSlowCase(exec, op1, op2));
411 EncodedJSValue JIT_OPERATION operationValueDiv(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
413 VM* vm = &exec->vm();
414 NativeCallFrameTracer tracer(vm, exec);
415 auto scope = DECLARE_THROW_SCOPE(*vm);
417 JSValue op1 = JSValue::decode(encodedOp1);
418 JSValue op2 = JSValue::decode(encodedOp2);
420 double a = op1.toNumber(exec);
421 RETURN_IF_EXCEPTION(scope, encodedJSValue());
423 double b = op2.toNumber(exec);
424 return JSValue::encode(jsNumber(a / b));
427 double JIT_OPERATION operationArithAbs(ExecState* exec, EncodedJSValue encodedOp1)
429 VM* vm = &exec->vm();
430 NativeCallFrameTracer tracer(vm, exec);
431 auto scope = DECLARE_THROW_SCOPE(*vm);
433 JSValue op1 = JSValue::decode(encodedOp1);
434 double a = op1.toNumber(exec);
435 RETURN_IF_EXCEPTION(scope, PNaN);
439 int32_t JIT_OPERATION operationArithClz32(ExecState* exec, EncodedJSValue encodedOp1)
441 VM* vm = &exec->vm();
442 NativeCallFrameTracer tracer(vm, exec);
443 auto scope = DECLARE_THROW_SCOPE(*vm);
445 JSValue op1 = JSValue::decode(encodedOp1);
446 uint32_t value = op1.toUInt32(exec);
447 RETURN_IF_EXCEPTION(scope, 0);
451 double JIT_OPERATION operationArithFRound(ExecState* exec, EncodedJSValue encodedOp1)
453 VM* vm = &exec->vm();
454 NativeCallFrameTracer tracer(vm, exec);
455 auto scope = DECLARE_THROW_SCOPE(*vm);
457 JSValue op1 = JSValue::decode(encodedOp1);
458 double a = op1.toNumber(exec);
459 RETURN_IF_EXCEPTION(scope, PNaN);
460 return static_cast<float>(a);
463 #define DFG_ARITH_UNARY(capitalizedName, lowerName) \
464 double JIT_OPERATION operationArith##capitalizedName(ExecState* exec, EncodedJSValue encodedOp1) \
466 VM* vm = &exec->vm(); \
467 NativeCallFrameTracer tracer(vm, exec); \
468 auto scope = DECLARE_THROW_SCOPE(*vm); \
469 JSValue op1 = JSValue::decode(encodedOp1); \
470 double result = op1.toNumber(exec); \
471 RETURN_IF_EXCEPTION(scope, PNaN); \
472 return JSC::Math::lowerName(result); \
474 FOR_EACH_DFG_ARITH_UNARY_OP(DFG_ARITH_UNARY)
475 #undef DFG_ARITH_UNARY
477 double JIT_OPERATION operationArithSqrt(ExecState* exec, EncodedJSValue encodedOp1)
479 VM* vm = &exec->vm();
480 NativeCallFrameTracer tracer(vm, exec);
481 auto scope = DECLARE_THROW_SCOPE(*vm);
483 JSValue op1 = JSValue::decode(encodedOp1);
484 double a = op1.toNumber(exec);
485 RETURN_IF_EXCEPTION(scope, PNaN);
489 EncodedJSValue JIT_OPERATION operationArithRound(ExecState* exec, EncodedJSValue encodedArgument)
491 VM* vm = &exec->vm();
492 NativeCallFrameTracer tracer(vm, exec);
493 auto scope = DECLARE_THROW_SCOPE(*vm);
495 JSValue argument = JSValue::decode(encodedArgument);
496 double valueOfArgument = argument.toNumber(exec);
497 RETURN_IF_EXCEPTION(scope, encodedJSValue());
498 return JSValue::encode(jsNumber(jsRound(valueOfArgument)));
501 EncodedJSValue JIT_OPERATION operationArithFloor(ExecState* exec, EncodedJSValue encodedArgument)
503 VM* vm = &exec->vm();
504 NativeCallFrameTracer tracer(vm, exec);
505 auto scope = DECLARE_THROW_SCOPE(*vm);
507 JSValue argument = JSValue::decode(encodedArgument);
508 double valueOfArgument = argument.toNumber(exec);
509 RETURN_IF_EXCEPTION(scope, encodedJSValue());
510 return JSValue::encode(jsNumber(floor(valueOfArgument)));
513 EncodedJSValue JIT_OPERATION operationArithCeil(ExecState* exec, EncodedJSValue encodedArgument)
515 VM* vm = &exec->vm();
516 NativeCallFrameTracer tracer(vm, exec);
517 auto scope = DECLARE_THROW_SCOPE(*vm);
519 JSValue argument = JSValue::decode(encodedArgument);
520 double valueOfArgument = argument.toNumber(exec);
521 RETURN_IF_EXCEPTION(scope, encodedJSValue());
522 return JSValue::encode(jsNumber(ceil(valueOfArgument)));
525 EncodedJSValue JIT_OPERATION operationArithTrunc(ExecState* exec, EncodedJSValue encodedArgument)
527 VM* vm = &exec->vm();
528 NativeCallFrameTracer tracer(vm, exec);
529 auto scope = DECLARE_THROW_SCOPE(*vm);
531 JSValue argument = JSValue::decode(encodedArgument);
532 double truncatedValueOfArgument = argument.toIntegerPreserveNaN(exec);
533 RETURN_IF_EXCEPTION(scope, encodedJSValue());
534 return JSValue::encode(jsNumber(truncatedValueOfArgument));
537 static ALWAYS_INLINE EncodedJSValue getByVal(ExecState* exec, JSCell* base, uint32_t index)
540 NativeCallFrameTracer tracer(&vm, exec);
542 if (base->isObject()) {
543 JSObject* object = asObject(base);
544 if (object->canGetIndexQuickly(index))
545 return JSValue::encode(object->getIndexQuickly(index));
548 if (isJSString(base) && asString(base)->canGetIndex(index))
549 return JSValue::encode(asString(base)->getIndex(exec, index));
551 return JSValue::encode(JSValue(base).get(exec, index));
554 EncodedJSValue JIT_OPERATION operationGetByVal(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty)
557 NativeCallFrameTracer tracer(&vm, exec);
558 auto scope = DECLARE_THROW_SCOPE(vm);
560 JSValue baseValue = JSValue::decode(encodedBase);
561 JSValue property = JSValue::decode(encodedProperty);
563 if (LIKELY(baseValue.isCell())) {
564 JSCell* base = baseValue.asCell();
566 if (property.isUInt32()) {
568 return getByVal(exec, base, property.asUInt32());
570 if (property.isDouble()) {
571 double propertyAsDouble = property.asDouble();
572 uint32_t propertyAsUInt32 = static_cast<uint32_t>(propertyAsDouble);
573 if (propertyAsUInt32 == propertyAsDouble && isIndex(propertyAsUInt32)) {
575 return getByVal(exec, base, propertyAsUInt32);
577 } else if (property.isString()) {
578 Structure& structure = *base->structure(vm);
579 if (JSCell::canUseFastGetOwnProperty(structure)) {
580 if (RefPtr<AtomicStringImpl> existingAtomicString = asString(property)->toExistingAtomicString(exec)) {
581 if (JSValue result = base->fastGetOwnProperty(vm, structure, existingAtomicString.get()))
582 return JSValue::encode(result);
588 baseValue.requireObjectCoercible(exec);
589 RETURN_IF_EXCEPTION(scope, encodedJSValue());
590 auto propertyName = property.toPropertyKey(exec);
591 RETURN_IF_EXCEPTION(scope, encodedJSValue());
593 return JSValue::encode(baseValue.get(exec, propertyName));
596 EncodedJSValue JIT_OPERATION operationGetByValCell(ExecState* exec, JSCell* base, EncodedJSValue encodedProperty)
599 NativeCallFrameTracer tracer(&vm, exec);
600 auto scope = DECLARE_THROW_SCOPE(vm);
602 JSValue property = JSValue::decode(encodedProperty);
604 if (property.isUInt32()) {
606 return getByVal(exec, base, property.asUInt32());
608 if (property.isDouble()) {
609 double propertyAsDouble = property.asDouble();
610 uint32_t propertyAsUInt32 = static_cast<uint32_t>(propertyAsDouble);
611 if (propertyAsUInt32 == propertyAsDouble) {
613 return getByVal(exec, base, propertyAsUInt32);
615 } else if (property.isString()) {
616 Structure& structure = *base->structure(vm);
617 if (JSCell::canUseFastGetOwnProperty(structure)) {
618 if (RefPtr<AtomicStringImpl> existingAtomicString = asString(property)->toExistingAtomicString(exec)) {
619 if (JSValue result = base->fastGetOwnProperty(vm, structure, existingAtomicString.get()))
620 return JSValue::encode(result);
625 auto propertyName = property.toPropertyKey(exec);
626 RETURN_IF_EXCEPTION(scope, encodedJSValue());
628 return JSValue::encode(JSValue(base).get(exec, propertyName));
631 ALWAYS_INLINE EncodedJSValue getByValCellInt(ExecState* exec, JSCell* base, int32_t index)
633 VM* vm = &exec->vm();
634 NativeCallFrameTracer tracer(vm, exec);
637 // Go the slowest way possible becase negative indices don't use indexed storage.
638 return JSValue::encode(JSValue(base).get(exec, Identifier::from(exec, index)));
641 // Use this since we know that the value is out of bounds.
642 return JSValue::encode(JSValue(base).get(exec, static_cast<unsigned>(index)));
645 EncodedJSValue JIT_OPERATION operationGetByValObjectInt(ExecState* exec, JSObject* base, int32_t index)
647 return getByValCellInt(exec, base, index);
650 EncodedJSValue JIT_OPERATION operationGetByValStringInt(ExecState* exec, JSString* base, int32_t index)
652 return getByValCellInt(exec, base, index);
655 EncodedJSValue JIT_OPERATION operationGetByValObjectString(ExecState* exec, JSCell* base, JSCell* string)
658 NativeCallFrameTracer tracer(&vm, exec);
660 auto scope = DECLARE_THROW_SCOPE(vm);
662 auto propertyName = asString(string)->toIdentifier(exec);
663 RETURN_IF_EXCEPTION(scope, encodedJSValue());
666 return JSValue::encode(getByValObject(exec, vm, asObject(base), propertyName));
669 EncodedJSValue JIT_OPERATION operationGetByValObjectSymbol(ExecState* exec, JSCell* base, JSCell* symbol)
672 NativeCallFrameTracer tracer(&vm, exec);
674 return JSValue::encode(getByValObject(exec, vm, asObject(base), asSymbol(symbol)->privateName()));
677 void JIT_OPERATION operationPutByValStrict(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
680 NativeCallFrameTracer tracer(&vm, exec);
682 putByValInternal<true, false>(exec, vm, encodedBase, encodedProperty, encodedValue);
685 void JIT_OPERATION operationPutByValNonStrict(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
688 NativeCallFrameTracer tracer(&vm, exec);
690 putByValInternal<false, false>(exec, vm, encodedBase, encodedProperty, encodedValue);
693 void JIT_OPERATION operationPutByValCellStrict(ExecState* exec, JSCell* cell, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
696 NativeCallFrameTracer tracer(&vm, exec);
698 putByValInternal<true, false>(exec, vm, JSValue::encode(cell), encodedProperty, encodedValue);
701 void JIT_OPERATION operationPutByValCellNonStrict(ExecState* exec, JSCell* cell, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
704 NativeCallFrameTracer tracer(&vm, exec);
706 putByValInternal<false, false>(exec, vm, JSValue::encode(cell), encodedProperty, encodedValue);
709 void JIT_OPERATION operationPutByValCellStringStrict(ExecState* exec, JSCell* cell, JSCell* string, EncodedJSValue encodedValue)
712 NativeCallFrameTracer tracer(&vm, exec);
714 putByValCellStringInternal<true, false>(exec, vm, cell, asString(string), JSValue::decode(encodedValue));
717 void JIT_OPERATION operationPutByValCellStringNonStrict(ExecState* exec, JSCell* cell, JSCell* string, EncodedJSValue encodedValue)
720 NativeCallFrameTracer tracer(&vm, exec);
722 putByValCellStringInternal<false, false>(exec, vm, cell, asString(string), JSValue::decode(encodedValue));
725 void JIT_OPERATION operationPutByValCellSymbolStrict(ExecState* exec, JSCell* cell, JSCell* symbol, EncodedJSValue encodedValue)
728 NativeCallFrameTracer tracer(&vm, exec);
730 putByValCellInternal<true, false>(exec, vm, cell, asSymbol(symbol)->privateName(), JSValue::decode(encodedValue));
733 void JIT_OPERATION operationPutByValCellSymbolNonStrict(ExecState* exec, JSCell* cell, JSCell* symbol, EncodedJSValue encodedValue)
736 NativeCallFrameTracer tracer(&vm, exec);
738 putByValCellInternal<false, false>(exec, vm, cell, asSymbol(symbol)->privateName(), JSValue::decode(encodedValue));
741 void JIT_OPERATION operationPutByValBeyondArrayBoundsStrict(ExecState* exec, JSObject* array, int32_t index, EncodedJSValue encodedValue)
744 NativeCallFrameTracer tracer(&vm, exec);
747 array->putByIndexInline(exec, index, JSValue::decode(encodedValue), true);
751 PutPropertySlot slot(array, true);
752 array->methodTable(vm)->put(
753 array, exec, Identifier::from(exec, index), JSValue::decode(encodedValue), slot);
756 void JIT_OPERATION operationPutByValBeyondArrayBoundsNonStrict(ExecState* exec, JSObject* array, int32_t index, EncodedJSValue encodedValue)
758 VM* vm = &exec->vm();
759 NativeCallFrameTracer tracer(vm, exec);
762 array->putByIndexInline(exec, index, JSValue::decode(encodedValue), false);
766 PutPropertySlot slot(array, false);
767 array->methodTable(*vm)->put(
768 array, exec, Identifier::from(exec, index), JSValue::decode(encodedValue), slot);
771 void JIT_OPERATION operationPutDoubleByValBeyondArrayBoundsStrict(ExecState* exec, JSObject* array, int32_t index, double value)
773 VM* vm = &exec->vm();
774 NativeCallFrameTracer tracer(vm, exec);
776 JSValue jsValue = JSValue(JSValue::EncodeAsDouble, value);
779 array->putByIndexInline(exec, index, jsValue, true);
783 PutPropertySlot slot(array, true);
784 array->methodTable(*vm)->put(
785 array, exec, Identifier::from(exec, index), jsValue, slot);
788 void JIT_OPERATION operationPutDoubleByValBeyondArrayBoundsNonStrict(ExecState* exec, JSObject* array, int32_t index, double value)
790 VM* vm = &exec->vm();
791 NativeCallFrameTracer tracer(vm, exec);
793 JSValue jsValue = JSValue(JSValue::EncodeAsDouble, value);
796 array->putByIndexInline(exec, index, jsValue, false);
800 PutPropertySlot slot(array, false);
801 array->methodTable(*vm)->put(
802 array, exec, Identifier::from(exec, index), jsValue, slot);
805 void JIT_OPERATION operationPutByValDirectStrict(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
808 NativeCallFrameTracer tracer(&vm, exec);
810 putByValInternal<true, true>(exec, vm, encodedBase, encodedProperty, encodedValue);
813 void JIT_OPERATION operationPutByValDirectNonStrict(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
816 NativeCallFrameTracer tracer(&vm, exec);
818 putByValInternal<false, true>(exec, vm, encodedBase, encodedProperty, encodedValue);
821 void JIT_OPERATION operationPutByValDirectCellStrict(ExecState* exec, JSCell* cell, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
824 NativeCallFrameTracer tracer(&vm, exec);
826 putByValInternal<true, true>(exec, vm, JSValue::encode(cell), encodedProperty, encodedValue);
829 void JIT_OPERATION operationPutByValDirectCellNonStrict(ExecState* exec, JSCell* cell, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
832 NativeCallFrameTracer tracer(&vm, exec);
834 putByValInternal<false, true>(exec, vm, JSValue::encode(cell), encodedProperty, encodedValue);
837 void JIT_OPERATION operationPutByValDirectCellStringStrict(ExecState* exec, JSCell* cell, JSCell* string, EncodedJSValue encodedValue)
840 NativeCallFrameTracer tracer(&vm, exec);
842 putByValCellStringInternal<true, true>(exec, vm, cell, asString(string), JSValue::decode(encodedValue));
845 void JIT_OPERATION operationPutByValDirectCellStringNonStrict(ExecState* exec, JSCell* cell, JSCell* string, EncodedJSValue encodedValue)
848 NativeCallFrameTracer tracer(&vm, exec);
850 putByValCellStringInternal<false, true>(exec, vm, cell, asString(string), JSValue::decode(encodedValue));
853 void JIT_OPERATION operationPutByValDirectCellSymbolStrict(ExecState* exec, JSCell* cell, JSCell* symbol, EncodedJSValue encodedValue)
856 NativeCallFrameTracer tracer(&vm, exec);
858 putByValCellInternal<true, true>(exec, vm, cell, asSymbol(symbol)->privateName(), JSValue::decode(encodedValue));
861 void JIT_OPERATION operationPutByValDirectCellSymbolNonStrict(ExecState* exec, JSCell* cell, JSCell* symbol, EncodedJSValue encodedValue)
864 NativeCallFrameTracer tracer(&vm, exec);
866 putByValCellInternal<false, true>(exec, vm, cell, asSymbol(symbol)->privateName(), JSValue::decode(encodedValue));
869 void JIT_OPERATION operationPutByValDirectBeyondArrayBoundsStrict(ExecState* exec, JSObject* array, int32_t index, EncodedJSValue encodedValue)
872 NativeCallFrameTracer tracer(&vm, exec);
874 array->putDirectIndex(exec, index, JSValue::decode(encodedValue), 0, PutDirectIndexShouldThrow);
878 PutPropertySlot slot(array, true);
879 array->putDirect(vm, Identifier::from(exec, index), JSValue::decode(encodedValue), slot);
882 void JIT_OPERATION operationPutByValDirectBeyondArrayBoundsNonStrict(ExecState* exec, JSObject* array, int32_t index, EncodedJSValue encodedValue)
885 NativeCallFrameTracer tracer(&vm, exec);
888 array->putDirectIndex(exec, index, JSValue::decode(encodedValue));
892 PutPropertySlot slot(array, false);
893 array->putDirect(vm, Identifier::from(exec, index), JSValue::decode(encodedValue), slot);
896 EncodedJSValue JIT_OPERATION operationArrayPush(ExecState* exec, EncodedJSValue encodedValue, JSArray* array)
898 VM* vm = &exec->vm();
899 NativeCallFrameTracer tracer(vm, exec);
901 array->pushInline(exec, JSValue::decode(encodedValue));
902 return JSValue::encode(jsNumber(array->length()));
905 EncodedJSValue JIT_OPERATION operationArrayPushDouble(ExecState* exec, double value, JSArray* array)
907 VM* vm = &exec->vm();
908 NativeCallFrameTracer tracer(vm, exec);
910 array->pushInline(exec, JSValue(JSValue::EncodeAsDouble, value));
911 return JSValue::encode(jsNumber(array->length()));
914 EncodedJSValue JIT_OPERATION operationArrayPushMultiple(ExecState* exec, JSArray* array, void* buffer, int32_t elementCount)
917 NativeCallFrameTracer tracer(&vm, exec);
918 auto scope = DECLARE_THROW_SCOPE(vm);
920 // We assume that multiple JSArray::push calls with ArrayWithInt32/ArrayWithContiguous do not cause JS traps.
921 // If it can cause any JS interactions, we can call the caller JS function of this function and overwrite the
922 // content of ScratchBuffer. If the IndexingType is now ArrayWithInt32/ArrayWithContiguous, we can ensure
923 // that there is no indexed accessors in this object and its prototype chain.
925 // ArrayWithArrayStorage is also OK. It can have indexed accessors. But if you define an indexed accessor, the array's length
926 // becomes larger than that index. So Array#push never overlaps with this accessor. So accessors are never called unless
927 // the IndexingType is ArrayWithSlowPutArrayStorage which could have an indexed accessor in a prototype chain.
928 RELEASE_ASSERT(!shouldUseSlowPut(array->indexingType()));
930 EncodedJSValue* values = static_cast<EncodedJSValue*>(buffer);
931 for (int32_t i = 0; i < elementCount; ++i) {
932 array->pushInline(exec, JSValue::decode(values[i]));
933 RETURN_IF_EXCEPTION(scope, encodedJSValue());
935 return JSValue::encode(jsNumber(array->length()));
938 EncodedJSValue JIT_OPERATION operationArrayPushDoubleMultiple(ExecState* exec, JSArray* array, void* buffer, int32_t elementCount)
941 NativeCallFrameTracer tracer(&vm, exec);
942 auto scope = DECLARE_THROW_SCOPE(vm);
944 // We assume that multiple JSArray::push calls with ArrayWithDouble do not cause JS traps.
945 // If it can cause any JS interactions, we can call the caller JS function of this function and overwrite the
946 // content of ScratchBuffer. If the IndexingType is now ArrayWithDouble, we can ensure
947 // that there is no indexed accessors in this object and its prototype chain.
948 ASSERT(array->indexingType() == ArrayWithDouble);
950 double* values = static_cast<double*>(buffer);
951 for (int32_t i = 0; i < elementCount; ++i) {
952 array->pushInline(exec, JSValue(JSValue::EncodeAsDouble, values[i]));
953 RETURN_IF_EXCEPTION(scope, encodedJSValue());
955 return JSValue::encode(jsNumber(array->length()));
958 EncodedJSValue JIT_OPERATION operationArrayPop(ExecState* exec, JSArray* array)
960 VM* vm = &exec->vm();
961 NativeCallFrameTracer tracer(vm, exec);
963 return JSValue::encode(array->pop(exec));
966 EncodedJSValue JIT_OPERATION operationArrayPopAndRecoverLength(ExecState* exec, JSArray* array)
968 VM* vm = &exec->vm();
969 NativeCallFrameTracer tracer(vm, exec);
971 array->butterfly()->setPublicLength(array->butterfly()->publicLength() + 1);
973 return JSValue::encode(array->pop(exec));
976 EncodedJSValue JIT_OPERATION operationRegExpExecString(ExecState* exec, JSGlobalObject* globalObject, RegExpObject* regExpObject, JSString* argument)
978 SuperSamplerScope superSamplerScope(false);
980 VM& vm = globalObject->vm();
981 NativeCallFrameTracer tracer(&vm, exec);
983 return JSValue::encode(regExpObject->execInline(exec, globalObject, argument));
986 EncodedJSValue JIT_OPERATION operationRegExpExec(ExecState* exec, JSGlobalObject* globalObject, RegExpObject* regExpObject, EncodedJSValue encodedArgument)
988 SuperSamplerScope superSamplerScope(false);
990 VM& vm = globalObject->vm();
991 NativeCallFrameTracer tracer(&vm, exec);
992 auto scope = DECLARE_THROW_SCOPE(vm);
994 JSValue argument = JSValue::decode(encodedArgument);
996 JSString* input = argument.toStringOrNull(exec);
997 EXCEPTION_ASSERT(!!scope.exception() == !input);
999 return encodedJSValue();
1001 return JSValue::encode(regExpObject->execInline(exec, globalObject, input));
1004 EncodedJSValue JIT_OPERATION operationRegExpExecGeneric(ExecState* exec, JSGlobalObject* globalObject, EncodedJSValue encodedBase, EncodedJSValue encodedArgument)
1006 SuperSamplerScope superSamplerScope(false);
1008 VM& vm = globalObject->vm();
1009 NativeCallFrameTracer tracer(&vm, exec);
1010 auto scope = DECLARE_THROW_SCOPE(vm);
1012 JSValue base = JSValue::decode(encodedBase);
1013 JSValue argument = JSValue::decode(encodedArgument);
1015 if (!base.inherits(vm, RegExpObject::info()))
1016 return throwVMTypeError(exec, scope);
1018 JSString* input = argument.toStringOrNull(exec);
1019 EXCEPTION_ASSERT(!!scope.exception() == !input);
1021 return JSValue::encode(jsUndefined());
1023 return JSValue::encode(asRegExpObject(base)->exec(exec, globalObject, input));
1026 EncodedJSValue JIT_OPERATION operationWeakMapGet(ExecState* exec, JSCell* weakMap, JSCell* object, int32_t hash)
1028 VM& vm = exec->vm();
1029 NativeCallFrameTracer tracer(&vm, exec);
1030 return JSValue::encode(jsCast<JSWeakMap*>(weakMap)->inlineGet(asObject(object), hash));
1033 EncodedJSValue JIT_OPERATION operationParseIntNoRadixGeneric(ExecState* exec, EncodedJSValue value)
1035 VM& vm = exec->vm();
1036 NativeCallFrameTracer tracer(&vm, exec);
1038 return toStringView(exec, JSValue::decode(value), [&] (StringView view) {
1039 // This version is as if radix was undefined. Hence, undefined.toNumber() === 0.
1040 return parseIntResult(parseInt(view, 0));
1044 EncodedJSValue JIT_OPERATION operationParseIntStringNoRadix(ExecState* exec, JSString* string)
1046 VM& vm = exec->vm();
1047 NativeCallFrameTracer tracer(&vm, exec);
1048 auto scope = DECLARE_THROW_SCOPE(vm);
1050 auto viewWithString = string->viewWithUnderlyingString(exec);
1051 RETURN_IF_EXCEPTION(scope, { });
1053 // This version is as if radix was undefined. Hence, undefined.toNumber() === 0.
1054 return parseIntResult(parseInt(viewWithString.view, 0));
1057 EncodedJSValue JIT_OPERATION operationParseIntString(ExecState* exec, JSString* string, int32_t radix)
1059 VM& vm = exec->vm();
1060 NativeCallFrameTracer tracer(&vm, exec);
1061 auto scope = DECLARE_THROW_SCOPE(vm);
1063 auto viewWithString = string->viewWithUnderlyingString(exec);
1064 RETURN_IF_EXCEPTION(scope, { });
1066 return parseIntResult(parseInt(viewWithString.view, radix));
1069 EncodedJSValue JIT_OPERATION operationParseIntGeneric(ExecState* exec, EncodedJSValue value, int32_t radix)
1071 VM& vm = exec->vm();
1072 NativeCallFrameTracer tracer(&vm, exec);
1074 return toStringView(exec, JSValue::decode(value), [&] (StringView view) {
1075 return parseIntResult(parseInt(view, radix));
1079 size_t JIT_OPERATION operationRegExpTestString(ExecState* exec, JSGlobalObject* globalObject, RegExpObject* regExpObject, JSString* input)
1081 SuperSamplerScope superSamplerScope(false);
1083 VM& vm = globalObject->vm();
1084 NativeCallFrameTracer tracer(&vm, exec);
1086 return regExpObject->testInline(exec, globalObject, input);
1089 size_t JIT_OPERATION operationRegExpTest(ExecState* exec, JSGlobalObject* globalObject, RegExpObject* regExpObject, EncodedJSValue encodedArgument)
1091 SuperSamplerScope superSamplerScope(false);
1093 VM& vm = globalObject->vm();
1094 NativeCallFrameTracer tracer(&vm, exec);
1096 JSValue argument = JSValue::decode(encodedArgument);
1098 JSString* input = argument.toStringOrNull(exec);
1101 return regExpObject->testInline(exec, globalObject, input);
1104 size_t JIT_OPERATION operationRegExpTestGeneric(ExecState* exec, JSGlobalObject* globalObject, EncodedJSValue encodedBase, EncodedJSValue encodedArgument)
1106 SuperSamplerScope superSamplerScope(false);
1108 VM& vm = globalObject->vm();
1109 NativeCallFrameTracer tracer(&vm, exec);
1110 auto scope = DECLARE_THROW_SCOPE(vm);
1112 JSValue base = JSValue::decode(encodedBase);
1113 JSValue argument = JSValue::decode(encodedArgument);
1115 if (!base.inherits(vm, RegExpObject::info())) {
1116 throwTypeError(exec, scope);
1120 JSString* input = argument.toStringOrNull(exec);
1121 EXCEPTION_ASSERT(!!scope.exception() == !input);
1125 return asRegExpObject(base)->test(exec, globalObject, input);
1128 size_t JIT_OPERATION operationCompareStrictEqCell(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
1130 VM* vm = &exec->vm();
1131 NativeCallFrameTracer tracer(vm, exec);
1133 JSValue op1 = JSValue::decode(encodedOp1);
1134 JSValue op2 = JSValue::decode(encodedOp2);
1136 ASSERT(op1.isCell());
1137 ASSERT(op2.isCell());
1139 return JSValue::strictEqualSlowCaseInline(exec, op1, op2);
1142 size_t JIT_OPERATION operationCompareStrictEq(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
1144 VM* vm = &exec->vm();
1145 NativeCallFrameTracer tracer(vm, exec);
1147 JSValue src1 = JSValue::decode(encodedOp1);
1148 JSValue src2 = JSValue::decode(encodedOp2);
1150 return JSValue::strictEqual(exec, src1, src2);
1153 EncodedJSValue JIT_OPERATION operationToPrimitive(ExecState* exec, EncodedJSValue value)
1155 VM* vm = &exec->vm();
1156 NativeCallFrameTracer tracer(vm, exec);
1158 return JSValue::encode(JSValue::decode(value).toPrimitive(exec));
1161 EncodedJSValue JIT_OPERATION operationToNumber(ExecState* exec, EncodedJSValue value)
1163 VM* vm = &exec->vm();
1164 NativeCallFrameTracer tracer(vm, exec);
1166 return JSValue::encode(jsNumber(JSValue::decode(value).toNumber(exec)));
1169 EncodedJSValue JIT_OPERATION operationGetByIdWithThis(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedThis, UniquedStringImpl* impl)
1171 VM& vm = exec->vm();
1172 NativeCallFrameTracer tracer(&vm, exec);
1174 JSValue baseValue = JSValue::decode(encodedBase);
1175 JSValue thisVal = JSValue::decode(encodedThis);
1176 PropertySlot slot(thisVal, PropertySlot::PropertySlot::InternalMethodType::Get);
1177 JSValue result = baseValue.get(exec, Identifier::fromUid(exec, impl), slot);
1178 return JSValue::encode(result);
1181 EncodedJSValue JIT_OPERATION operationGetByValWithThis(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedThis, EncodedJSValue encodedSubscript)
1183 VM& vm = exec->vm();
1184 NativeCallFrameTracer tracer(&vm, exec);
1185 auto scope = DECLARE_THROW_SCOPE(vm);
1187 JSValue baseValue = JSValue::decode(encodedBase);
1188 JSValue thisVal = JSValue::decode(encodedThis);
1189 JSValue subscript = JSValue::decode(encodedSubscript);
1191 if (LIKELY(baseValue.isCell() && subscript.isString())) {
1192 Structure& structure = *baseValue.asCell()->structure(vm);
1193 if (JSCell::canUseFastGetOwnProperty(structure)) {
1194 if (RefPtr<AtomicStringImpl> existingAtomicString = asString(subscript)->toExistingAtomicString(exec)) {
1195 if (JSValue result = baseValue.asCell()->fastGetOwnProperty(vm, structure, existingAtomicString.get()))
1196 return JSValue::encode(result);
1201 PropertySlot slot(thisVal, PropertySlot::PropertySlot::InternalMethodType::Get);
1202 if (subscript.isUInt32()) {
1203 uint32_t i = subscript.asUInt32();
1204 if (isJSString(baseValue) && asString(baseValue)->canGetIndex(i))
1205 return JSValue::encode(asString(baseValue)->getIndex(exec, i));
1208 return JSValue::encode(baseValue.get(exec, i, slot));
1211 baseValue.requireObjectCoercible(exec);
1212 RETURN_IF_EXCEPTION(scope, encodedJSValue());
1214 auto property = subscript.toPropertyKey(exec);
1215 RETURN_IF_EXCEPTION(scope, encodedJSValue());
1217 return JSValue::encode(baseValue.get(exec, property, slot));
1220 void JIT_OPERATION operationPutByIdWithThisStrict(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedThis, EncodedJSValue encodedValue, UniquedStringImpl* impl)
1222 VM& vm = exec->vm();
1223 NativeCallFrameTracer tracer(&vm, exec);
1225 putWithThis<true>(exec, encodedBase, encodedThis, encodedValue, Identifier::fromUid(exec, impl));
1228 void JIT_OPERATION operationPutByIdWithThis(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedThis, EncodedJSValue encodedValue, UniquedStringImpl* impl)
1230 VM& vm = exec->vm();
1231 NativeCallFrameTracer tracer(&vm, exec);
1233 putWithThis<false>(exec, encodedBase, encodedThis, encodedValue, Identifier::fromUid(exec, impl));
1236 void JIT_OPERATION operationPutByValWithThisStrict(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedThis, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue)
1238 VM& vm = exec->vm();
1239 NativeCallFrameTracer tracer(&vm, exec);
1240 auto scope = DECLARE_THROW_SCOPE(vm);
1242 Identifier property = JSValue::decode(encodedSubscript).toPropertyKey(exec);
1243 RETURN_IF_EXCEPTION(scope, void());
1245 putWithThis<true>(exec, encodedBase, encodedThis, encodedValue, property);
1248 void JIT_OPERATION operationPutByValWithThis(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedThis, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue)
1250 VM& vm = exec->vm();
1251 NativeCallFrameTracer tracer(&vm, exec);
1252 auto scope = DECLARE_THROW_SCOPE(vm);
1254 Identifier property = JSValue::decode(encodedSubscript).toPropertyKey(exec);
1255 RETURN_IF_EXCEPTION(scope, void());
1257 putWithThis<false>(exec, encodedBase, encodedThis, encodedValue, property);
1260 ALWAYS_INLINE static void defineDataProperty(ExecState* exec, VM& vm, JSObject* base, const Identifier& propertyName, JSValue value, int32_t attributes)
1262 PropertyDescriptor descriptor = toPropertyDescriptor(value, jsUndefined(), jsUndefined(), DefinePropertyAttributes(attributes));
1263 ASSERT((descriptor.attributes() & PropertyAttribute::Accessor) || (!descriptor.isAccessorDescriptor()));
1264 if (base->methodTable(vm)->defineOwnProperty == JSObject::defineOwnProperty)
1265 JSObject::defineOwnProperty(base, exec, propertyName, descriptor, true);
1267 base->methodTable(vm)->defineOwnProperty(base, exec, propertyName, descriptor, true);
1270 void JIT_OPERATION operationDefineDataProperty(ExecState* exec, JSObject* base, EncodedJSValue encodedProperty, EncodedJSValue encodedValue, int32_t attributes)
1272 VM& vm = exec->vm();
1273 NativeCallFrameTracer tracer(&vm, exec);
1274 auto scope = DECLARE_THROW_SCOPE(vm);
1276 Identifier propertyName = JSValue::decode(encodedProperty).toPropertyKey(exec);
1277 RETURN_IF_EXCEPTION(scope, void());
1279 defineDataProperty(exec, vm, base, propertyName, JSValue::decode(encodedValue), attributes);
1282 void JIT_OPERATION operationDefineDataPropertyString(ExecState* exec, JSObject* base, JSString* property, EncodedJSValue encodedValue, int32_t attributes)
1284 VM& vm = exec->vm();
1285 NativeCallFrameTracer tracer(&vm, exec);
1286 auto scope = DECLARE_THROW_SCOPE(vm);
1288 Identifier propertyName = property->toIdentifier(exec);
1289 RETURN_IF_EXCEPTION(scope, void());
1291 defineDataProperty(exec, vm, base, propertyName, JSValue::decode(encodedValue), attributes);
1294 void JIT_OPERATION operationDefineDataPropertyStringIdent(ExecState* exec, JSObject* base, UniquedStringImpl* property, EncodedJSValue encodedValue, int32_t attributes)
1296 VM& vm = exec->vm();
1297 NativeCallFrameTracer tracer(&vm, exec);
1298 defineDataProperty(exec, vm, base, Identifier::fromUid(&vm, property), JSValue::decode(encodedValue), attributes);
1301 void JIT_OPERATION operationDefineDataPropertySymbol(ExecState* exec, JSObject* base, Symbol* property, EncodedJSValue encodedValue, int32_t attributes)
1303 VM& vm = exec->vm();
1304 NativeCallFrameTracer tracer(&vm, exec);
1305 defineDataProperty(exec, vm, base, Identifier::fromUid(property->privateName()), JSValue::decode(encodedValue), attributes);
1308 ALWAYS_INLINE static void defineAccessorProperty(ExecState* exec, VM& vm, JSObject* base, const Identifier& propertyName, JSObject* getter, JSObject* setter, int32_t attributes)
1310 PropertyDescriptor descriptor = toPropertyDescriptor(jsUndefined(), getter, setter, DefinePropertyAttributes(attributes));
1311 ASSERT((descriptor.attributes() & PropertyAttribute::Accessor) || (!descriptor.isAccessorDescriptor()));
1312 if (base->methodTable(vm)->defineOwnProperty == JSObject::defineOwnProperty)
1313 JSObject::defineOwnProperty(base, exec, propertyName, descriptor, true);
1315 base->methodTable(vm)->defineOwnProperty(base, exec, propertyName, descriptor, true);
1318 void JIT_OPERATION operationDefineAccessorProperty(ExecState* exec, JSObject* base, EncodedJSValue encodedProperty, JSObject* getter, JSObject* setter, int32_t attributes)
1320 VM& vm = exec->vm();
1321 NativeCallFrameTracer tracer(&vm, exec);
1322 auto scope = DECLARE_THROW_SCOPE(vm);
1324 Identifier propertyName = JSValue::decode(encodedProperty).toPropertyKey(exec);
1325 RETURN_IF_EXCEPTION(scope, void());
1326 defineAccessorProperty(exec, vm, base, propertyName, getter, setter, attributes);
1329 void JIT_OPERATION operationDefineAccessorPropertyString(ExecState* exec, JSObject* base, JSString* property, JSObject* getter, JSObject* setter, int32_t attributes)
1331 VM& vm = exec->vm();
1332 NativeCallFrameTracer tracer(&vm, exec);
1333 auto scope = DECLARE_THROW_SCOPE(vm);
1335 Identifier propertyName = property->toIdentifier(exec);
1336 RETURN_IF_EXCEPTION(scope, void());
1337 defineAccessorProperty(exec, vm, base, propertyName, getter, setter, attributes);
1340 void JIT_OPERATION operationDefineAccessorPropertyStringIdent(ExecState* exec, JSObject* base, UniquedStringImpl* property, JSObject* getter, JSObject* setter, int32_t attributes)
1342 VM& vm = exec->vm();
1343 NativeCallFrameTracer tracer(&vm, exec);
1344 defineAccessorProperty(exec, vm, base, Identifier::fromUid(&vm, property), getter, setter, attributes);
1347 void JIT_OPERATION operationDefineAccessorPropertySymbol(ExecState* exec, JSObject* base, Symbol* property, JSObject* getter, JSObject* setter, int32_t attributes)
1349 VM& vm = exec->vm();
1350 NativeCallFrameTracer tracer(&vm, exec);
1351 defineAccessorProperty(exec, vm, base, Identifier::fromUid(property->privateName()), getter, setter, attributes);
1354 char* JIT_OPERATION operationNewArray(ExecState* exec, Structure* arrayStructure, void* buffer, size_t size)
1356 VM* vm = &exec->vm();
1357 NativeCallFrameTracer tracer(vm, exec);
1359 return bitwise_cast<char*>(constructArray(exec, arrayStructure, static_cast<JSValue*>(buffer), size));
1362 char* JIT_OPERATION operationNewEmptyArray(ExecState* exec, Structure* arrayStructure)
1364 VM* vm = &exec->vm();
1365 NativeCallFrameTracer tracer(vm, exec);
1367 return bitwise_cast<char*>(JSArray::create(*vm, arrayStructure));
1370 char* JIT_OPERATION operationNewArrayWithSize(ExecState* exec, Structure* arrayStructure, int32_t size, Butterfly* butterfly)
1372 VM& vm = exec->vm();
1373 NativeCallFrameTracer tracer(&vm, exec);
1374 auto scope = DECLARE_THROW_SCOPE(vm);
1376 if (UNLIKELY(size < 0))
1377 return bitwise_cast<char*>(throwException(exec, scope, createRangeError(exec, ASCIILiteral("Array size is not a small enough positive integer."))));
1381 result = JSArray::createWithButterfly(vm, nullptr, arrayStructure, butterfly);
1383 result = JSArray::create(vm, arrayStructure, size);
1384 return bitwise_cast<char*>(result);
1387 char* JIT_OPERATION operationNewArrayWithSizeAndHint(ExecState* exec, Structure* arrayStructure, int32_t size, int32_t vectorLengthHint, Butterfly* butterfly)
1389 VM& vm = exec->vm();
1390 NativeCallFrameTracer tracer(&vm, exec);
1391 auto scope = DECLARE_THROW_SCOPE(vm);
1393 if (UNLIKELY(size < 0))
1394 return bitwise_cast<char*>(throwException(exec, scope, createRangeError(exec, ASCIILiteral("Array size is not a small enough positive integer."))));
1398 result = JSArray::createWithButterfly(vm, nullptr, arrayStructure, butterfly);
1400 result = JSArray::tryCreate(vm, arrayStructure, size, vectorLengthHint);
1403 return bitwise_cast<char*>(result);
1406 char* JIT_OPERATION operationNewArrayBuffer(ExecState* exec, Structure* arrayStructure, size_t start, size_t size)
1408 VM& vm = exec->vm();
1409 NativeCallFrameTracer tracer(&vm, exec);
1410 return bitwise_cast<char*>(constructArray(exec, arrayStructure, exec->codeBlock()->constantBuffer(start), size));
1413 char* JIT_OPERATION operationNewInt8ArrayWithSize(
1414 ExecState* exec, Structure* structure, int32_t length, char* vector)
1416 return newTypedArrayWithSize<JSInt8Array>(exec, structure, length, vector);
1419 char* JIT_OPERATION operationNewInt8ArrayWithOneArgument(
1420 ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
1422 VM& vm = exec->vm();
1423 NativeCallFrameTracer tracer(&vm, exec);
1424 return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSInt8Array>(exec, structure, encodedValue, 0, std::nullopt));
1427 char* JIT_OPERATION operationNewInt16ArrayWithSize(
1428 ExecState* exec, Structure* structure, int32_t length, char* vector)
1430 return newTypedArrayWithSize<JSInt16Array>(exec, structure, length, vector);
1433 char* JIT_OPERATION operationNewInt16ArrayWithOneArgument(
1434 ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
1436 VM& vm = exec->vm();
1437 NativeCallFrameTracer tracer(&vm, exec);
1438 return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSInt16Array>(exec, structure, encodedValue, 0, std::nullopt));
1441 char* JIT_OPERATION operationNewInt32ArrayWithSize(
1442 ExecState* exec, Structure* structure, int32_t length, char* vector)
1444 return newTypedArrayWithSize<JSInt32Array>(exec, structure, length, vector);
1447 char* JIT_OPERATION operationNewInt32ArrayWithOneArgument(
1448 ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
1450 VM& vm = exec->vm();
1451 NativeCallFrameTracer tracer(&vm, exec);
1452 return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSInt32Array>(exec, structure, encodedValue, 0, std::nullopt));
1455 char* JIT_OPERATION operationNewUint8ArrayWithSize(
1456 ExecState* exec, Structure* structure, int32_t length, char* vector)
1458 return newTypedArrayWithSize<JSUint8Array>(exec, structure, length, vector);
1461 char* JIT_OPERATION operationNewUint8ArrayWithOneArgument(
1462 ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
1464 VM& vm = exec->vm();
1465 NativeCallFrameTracer tracer(&vm, exec);
1466 return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSUint8Array>(exec, structure, encodedValue, 0, std::nullopt));
1469 char* JIT_OPERATION operationNewUint8ClampedArrayWithSize(
1470 ExecState* exec, Structure* structure, int32_t length, char* vector)
1472 return newTypedArrayWithSize<JSUint8ClampedArray>(exec, structure, length, vector);
1475 char* JIT_OPERATION operationNewUint8ClampedArrayWithOneArgument(
1476 ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
1478 VM& vm = exec->vm();
1479 NativeCallFrameTracer tracer(&vm, exec);
1480 return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSUint8ClampedArray>(exec, structure, encodedValue, 0, std::nullopt));
1483 char* JIT_OPERATION operationNewUint16ArrayWithSize(
1484 ExecState* exec, Structure* structure, int32_t length, char* vector)
1486 return newTypedArrayWithSize<JSUint16Array>(exec, structure, length, vector);
1489 char* JIT_OPERATION operationNewUint16ArrayWithOneArgument(
1490 ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
1492 VM& vm = exec->vm();
1493 NativeCallFrameTracer tracer(&vm, exec);
1494 return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSUint16Array>(exec, structure, encodedValue, 0, std::nullopt));
1497 char* JIT_OPERATION operationNewUint32ArrayWithSize(
1498 ExecState* exec, Structure* structure, int32_t length, char* vector)
1500 return newTypedArrayWithSize<JSUint32Array>(exec, structure, length, vector);
1503 char* JIT_OPERATION operationNewUint32ArrayWithOneArgument(
1504 ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
1506 VM& vm = exec->vm();
1507 NativeCallFrameTracer tracer(&vm, exec);
1508 return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSUint32Array>(exec, structure, encodedValue, 0, std::nullopt));
1511 char* JIT_OPERATION operationNewFloat32ArrayWithSize(
1512 ExecState* exec, Structure* structure, int32_t length, char* vector)
1514 return newTypedArrayWithSize<JSFloat32Array>(exec, structure, length, vector);
1517 char* JIT_OPERATION operationNewFloat32ArrayWithOneArgument(
1518 ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
1520 VM& vm = exec->vm();
1521 NativeCallFrameTracer tracer(&vm, exec);
1522 return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSFloat32Array>(exec, structure, encodedValue, 0, std::nullopt));
1525 char* JIT_OPERATION operationNewFloat64ArrayWithSize(
1526 ExecState* exec, Structure* structure, int32_t length, char* vector)
1528 return newTypedArrayWithSize<JSFloat64Array>(exec, structure, length, vector);
1531 char* JIT_OPERATION operationNewFloat64ArrayWithOneArgument(
1532 ExecState* exec, Structure* structure, EncodedJSValue encodedValue)
1534 VM& vm = exec->vm();
1535 NativeCallFrameTracer tracer(&vm, exec);
1536 return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSFloat64Array>(exec, structure, encodedValue, 0, std::nullopt));
1539 JSCell* JIT_OPERATION operationCreateActivationDirect(ExecState* exec, Structure* structure, JSScope* scope, SymbolTable* table, EncodedJSValue initialValueEncoded)
1541 JSValue initialValue = JSValue::decode(initialValueEncoded);
1542 ASSERT(initialValue == jsUndefined() || initialValue == jsTDZValue());
1543 VM& vm = exec->vm();
1544 NativeCallFrameTracer tracer(&vm, exec);
1545 return JSLexicalEnvironment::create(vm, structure, scope, table, initialValue);
1548 JSCell* JIT_OPERATION operationCreateDirectArguments(ExecState* exec, Structure* structure, int32_t length, int32_t minCapacity)
1550 VM& vm = exec->vm();
1551 NativeCallFrameTracer target(&vm, exec);
1552 DirectArguments* result = DirectArguments::create(
1553 vm, structure, length, std::max(length, minCapacity));
1554 // The caller will store to this object without barriers. Most likely, at this point, this is
1555 // still a young object and so no barriers are needed. But it's good to be careful anyway,
1556 // since the GC should be allowed to do crazy (like pretenuring, for example).
1557 vm.heap.writeBarrier(result);
1561 JSCell* JIT_OPERATION operationCreateScopedArguments(ExecState* exec, Structure* structure, Register* argumentStart, int32_t length, JSFunction* callee, JSLexicalEnvironment* scope)
1563 VM& vm = exec->vm();
1564 NativeCallFrameTracer target(&vm, exec);
1566 // We could pass the ScopedArgumentsTable* as an argument. We currently don't because I
1567 // didn't feel like changing the max number of arguments for a slow path call from 6 to 7.
1568 ScopedArgumentsTable* table = scope->symbolTable()->arguments();
1570 return ScopedArguments::createByCopyingFrom(
1571 vm, structure, argumentStart, length, callee, table, scope);
1574 JSCell* JIT_OPERATION operationCreateClonedArguments(ExecState* exec, Structure* structure, Register* argumentStart, int32_t length, JSFunction* callee)
1576 VM& vm = exec->vm();
1577 NativeCallFrameTracer target(&vm, exec);
1578 return ClonedArguments::createByCopyingFrom(
1579 exec, structure, argumentStart, length, callee);
1582 JSCell* JIT_OPERATION operationCreateDirectArgumentsDuringExit(ExecState* exec, InlineCallFrame* inlineCallFrame, JSFunction* callee, int32_t argumentCount)
1584 VM& vm = exec->vm();
1585 NativeCallFrameTracer target(&vm, exec);
1587 DeferGCForAWhile deferGC(vm.heap);
1589 CodeBlock* codeBlock;
1590 if (inlineCallFrame)
1591 codeBlock = baselineCodeBlockForInlineCallFrame(inlineCallFrame);
1593 codeBlock = exec->codeBlock();
1595 unsigned length = argumentCount - 1;
1596 unsigned capacity = std::max(length, static_cast<unsigned>(codeBlock->numParameters() - 1));
1597 DirectArguments* result = DirectArguments::create(
1598 vm, codeBlock->globalObject()->directArgumentsStructure(), length, capacity);
1600 result->callee().set(vm, result, callee);
1602 Register* arguments =
1603 exec->registers() + (inlineCallFrame ? inlineCallFrame->stackOffset : 0) +
1604 CallFrame::argumentOffset(0);
1605 for (unsigned i = length; i--;)
1606 result->setIndexQuickly(vm, i, arguments[i].jsValue());
1611 JSCell* JIT_OPERATION operationCreateClonedArgumentsDuringExit(ExecState* exec, InlineCallFrame* inlineCallFrame, JSFunction* callee, int32_t argumentCount)
1613 VM& vm = exec->vm();
1614 NativeCallFrameTracer target(&vm, exec);
1616 DeferGCForAWhile deferGC(vm.heap);
1618 CodeBlock* codeBlock;
1619 if (inlineCallFrame)
1620 codeBlock = baselineCodeBlockForInlineCallFrame(inlineCallFrame);
1622 codeBlock = exec->codeBlock();
1624 unsigned length = argumentCount - 1;
1625 ClonedArguments* result = ClonedArguments::createEmpty(
1626 vm, codeBlock->globalObject()->clonedArgumentsStructure(), callee, length);
1628 Register* arguments =
1629 exec->registers() + (inlineCallFrame ? inlineCallFrame->stackOffset : 0) +
1630 CallFrame::argumentOffset(0);
1631 for (unsigned i = length; i--;)
1632 result->putDirectIndex(exec, i, arguments[i].jsValue());
1638 JSCell* JIT_OPERATION operationCreateRest(ExecState* exec, Register* argumentStart, unsigned numberOfParamsToSkip, unsigned arraySize)
1640 VM* vm = &exec->vm();
1641 NativeCallFrameTracer tracer(vm, exec);
1643 JSGlobalObject* globalObject = exec->lexicalGlobalObject();
1644 Structure* structure = globalObject->restParameterStructure();
1645 static_assert(sizeof(Register) == sizeof(JSValue), "This is a strong assumption here.");
1646 JSValue* argumentsToCopyRegion = bitwise_cast<JSValue*>(argumentStart) + numberOfParamsToSkip;
1647 return constructArray(exec, structure, argumentsToCopyRegion, arraySize);
1650 size_t JIT_OPERATION operationObjectIsObject(ExecState* exec, JSGlobalObject* globalObject, JSCell* object)
1652 VM& vm = exec->vm();
1653 NativeCallFrameTracer tracer(&vm, exec);
1655 ASSERT(jsDynamicCast<JSObject*>(vm, object));
1657 if (object->structure(vm)->masqueradesAsUndefined(globalObject))
1659 if (object->type() == JSFunctionType)
1661 if (object->inlineTypeFlags() & TypeOfShouldCallGetCallData) {
1663 if (object->methodTable(vm)->getCallData(object, callData) != CallType::None)
1670 size_t JIT_OPERATION operationObjectIsFunction(ExecState* exec, JSGlobalObject* globalObject, JSCell* object)
1672 VM& vm = exec->vm();
1673 NativeCallFrameTracer tracer(&vm, exec);
1675 ASSERT(jsDynamicCast<JSObject*>(vm, object));
1677 if (object->structure(vm)->masqueradesAsUndefined(globalObject))
1679 if (object->type() == JSFunctionType)
1681 if (object->inlineTypeFlags() & TypeOfShouldCallGetCallData) {
1683 if (object->methodTable(vm)->getCallData(object, callData) != CallType::None)
1690 JSCell* JIT_OPERATION operationTypeOfObject(ExecState* exec, JSGlobalObject* globalObject, JSCell* object)
1692 VM& vm = exec->vm();
1693 NativeCallFrameTracer tracer(&vm, exec);
1695 ASSERT(jsDynamicCast<JSObject*>(vm, object));
1697 if (object->structure(vm)->masqueradesAsUndefined(globalObject))
1698 return vm.smallStrings.undefinedString();
1699 if (object->type() == JSFunctionType)
1700 return vm.smallStrings.functionString();
1701 if (object->inlineTypeFlags() & TypeOfShouldCallGetCallData) {
1703 if (object->methodTable(vm)->getCallData(object, callData) != CallType::None)
1704 return vm.smallStrings.functionString();
1707 return vm.smallStrings.objectString();
1710 int32_t JIT_OPERATION operationTypeOfObjectAsTypeofType(ExecState* exec, JSGlobalObject* globalObject, JSCell* object)
1712 VM& vm = exec->vm();
1713 NativeCallFrameTracer tracer(&vm, exec);
1715 ASSERT(jsDynamicCast<JSObject*>(vm, object));
1717 if (object->structure(vm)->masqueradesAsUndefined(globalObject))
1718 return static_cast<int32_t>(TypeofType::Undefined);
1719 if (object->type() == JSFunctionType)
1720 return static_cast<int32_t>(TypeofType::Function);
1721 if (object->inlineTypeFlags() & TypeOfShouldCallGetCallData) {
1723 if (object->methodTable(vm)->getCallData(object, callData) != CallType::None)
1724 return static_cast<int32_t>(TypeofType::Function);
1727 return static_cast<int32_t>(TypeofType::Object);
1730 char* JIT_OPERATION operationAllocateSimplePropertyStorageWithInitialCapacity(ExecState* exec)
1732 VM& vm = exec->vm();
1733 NativeCallFrameTracer tracer(&vm, exec);
1735 return reinterpret_cast<char*>(
1736 Butterfly::createUninitialized(vm, 0, 0, initialOutOfLineCapacity, false, 0));
1739 char* JIT_OPERATION operationAllocateSimplePropertyStorage(ExecState* exec, size_t newSize)
1741 VM& vm = exec->vm();
1742 NativeCallFrameTracer tracer(&vm, exec);
1744 return reinterpret_cast<char*>(
1745 Butterfly::createUninitialized(vm, 0, 0, newSize, false, 0));
1748 char* JIT_OPERATION operationAllocateComplexPropertyStorageWithInitialCapacity(ExecState* exec, JSObject* object)
1750 VM& vm = exec->vm();
1751 NativeCallFrameTracer tracer(&vm, exec);
1753 ASSERT(!object->structure()->outOfLineCapacity());
1754 return reinterpret_cast<char*>(
1755 object->allocateMoreOutOfLineStorage(vm, 0, initialOutOfLineCapacity));
1758 char* JIT_OPERATION operationAllocateComplexPropertyStorage(ExecState* exec, JSObject* object, size_t newSize)
1760 VM& vm = exec->vm();
1761 NativeCallFrameTracer tracer(&vm, exec);
1763 return reinterpret_cast<char*>(
1764 object->allocateMoreOutOfLineStorage(vm, object->structure()->outOfLineCapacity(), newSize));
1767 char* JIT_OPERATION operationEnsureInt32(ExecState* exec, JSCell* cell)
1769 VM& vm = exec->vm();
1770 NativeCallFrameTracer tracer(&vm, exec);
1772 if (!cell->isObject())
1775 return reinterpret_cast<char*>(asObject(cell)->ensureInt32(vm).data());
1778 char* JIT_OPERATION operationEnsureDouble(ExecState* exec, JSCell* cell)
1780 VM& vm = exec->vm();
1781 NativeCallFrameTracer tracer(&vm, exec);
1783 if (!cell->isObject())
1786 return reinterpret_cast<char*>(asObject(cell)->ensureDouble(vm).data());
1789 char* JIT_OPERATION operationEnsureContiguous(ExecState* exec, JSCell* cell)
1791 VM& vm = exec->vm();
1792 NativeCallFrameTracer tracer(&vm, exec);
1794 if (!cell->isObject())
1797 return reinterpret_cast<char*>(asObject(cell)->ensureContiguous(vm).data());
1800 char* JIT_OPERATION operationEnsureArrayStorage(ExecState* exec, JSCell* cell)
1802 VM& vm = exec->vm();
1803 NativeCallFrameTracer tracer(&vm, exec);
1805 if (!cell->isObject())
1808 return reinterpret_cast<char*>(asObject(cell)->ensureArrayStorage(vm));
1811 StringImpl* JIT_OPERATION operationResolveRope(ExecState* exec, JSString* string)
1813 VM& vm = exec->vm();
1814 NativeCallFrameTracer tracer(&vm, exec);
1816 return string->value(exec).impl();
1819 JSCell* JIT_OPERATION operationStringSubstr(ExecState* exec, JSCell* cell, int32_t from, int32_t span)
1821 VM& vm = exec->vm();
1822 NativeCallFrameTracer tracer(&vm, exec);
1823 auto scope = DECLARE_THROW_SCOPE(vm);
1825 auto string = jsCast<JSString*>(cell)->value(exec);
1826 RETURN_IF_EXCEPTION(scope, nullptr);
1827 return jsSubstring(exec, string, from, span);
1830 JSString* JIT_OPERATION operationToLowerCase(ExecState* exec, JSString* string, uint32_t failingIndex)
1832 VM& vm = exec->vm();
1833 NativeCallFrameTracer tracer(&vm, exec);
1835 auto scope = DECLARE_THROW_SCOPE(vm);
1837 const String& inputString = string->value(exec);
1838 RETURN_IF_EXCEPTION(scope, nullptr);
1839 if (!inputString.length())
1840 return vm.smallStrings.emptyString();
1842 String lowercasedString = inputString.is8Bit() ? inputString.convertToLowercaseWithoutLocaleStartingAtFailingIndex8Bit(failingIndex) : inputString.convertToLowercaseWithoutLocale();
1843 if (lowercasedString.impl() == inputString.impl())
1846 return jsString(exec, lowercasedString);
1849 char* JIT_OPERATION operationInt32ToString(ExecState* exec, int32_t value, int32_t radix)
1851 VM& vm = exec->vm();
1852 NativeCallFrameTracer tracer(&vm, exec);
1854 auto scope = DECLARE_THROW_SCOPE(vm);
1856 if (radix < 2 || radix > 36) {
1857 throwVMError(exec, scope, createRangeError(exec, ASCIILiteral("toString() radix argument must be between 2 and 36")));
1861 return reinterpret_cast<char*>(int32ToString(vm, value, radix));
1864 char* JIT_OPERATION operationInt52ToString(ExecState* exec, int64_t value, int32_t radix)
1866 VM& vm = exec->vm();
1867 NativeCallFrameTracer tracer(&vm, exec);
1869 auto scope = DECLARE_THROW_SCOPE(vm);
1871 if (radix < 2 || radix > 36) {
1872 throwVMError(exec, scope, createRangeError(exec, ASCIILiteral("toString() radix argument must be between 2 and 36")));
1876 return reinterpret_cast<char*>(int52ToString(vm, value, radix));
1879 char* JIT_OPERATION operationDoubleToString(ExecState* exec, double value, int32_t radix)
1881 VM& vm = exec->vm();
1882 NativeCallFrameTracer tracer(&vm, exec);
1884 auto scope = DECLARE_THROW_SCOPE(vm);
1886 if (radix < 2 || radix > 36) {
1887 throwVMError(exec, scope, createRangeError(exec, ASCIILiteral("toString() radix argument must be between 2 and 36")));
1891 return reinterpret_cast<char*>(numberToString(vm, value, radix));
1894 char* JIT_OPERATION operationInt32ToStringWithValidRadix(ExecState* exec, int32_t value, int32_t radix)
1896 VM& vm = exec->vm();
1897 NativeCallFrameTracer tracer(&vm, exec);
1899 return reinterpret_cast<char*>(int32ToString(vm, value, radix));
1902 char* JIT_OPERATION operationInt52ToStringWithValidRadix(ExecState* exec, int64_t value, int32_t radix)
1904 VM& vm = exec->vm();
1905 NativeCallFrameTracer tracer(&vm, exec);
1907 return reinterpret_cast<char*>(int52ToString(vm, value, radix));
1910 char* JIT_OPERATION operationDoubleToStringWithValidRadix(ExecState* exec, double value, int32_t radix)
1912 VM& vm = exec->vm();
1913 NativeCallFrameTracer tracer(&vm, exec);
1915 return reinterpret_cast<char*>(numberToString(vm, value, radix));
1918 JSString* JIT_OPERATION operationSingleCharacterString(ExecState* exec, int32_t character)
1920 VM& vm = exec->vm();
1921 NativeCallFrameTracer tracer(&vm, exec);
1923 return jsSingleCharacterString(exec, static_cast<UChar>(character));
1926 JSCell* JIT_OPERATION operationNewStringObject(ExecState* exec, JSString* string, Structure* structure)
1928 VM& vm = exec->vm();
1929 NativeCallFrameTracer tracer(&vm, exec);
1931 return StringObject::create(vm, structure, string);
1934 JSCell* JIT_OPERATION operationToStringOnCell(ExecState* exec, JSCell* cell)
1936 VM& vm = exec->vm();
1937 NativeCallFrameTracer tracer(&vm, exec);
1939 return JSValue(cell).toString(exec);
1942 JSCell* JIT_OPERATION operationToString(ExecState* exec, EncodedJSValue value)
1944 VM& vm = exec->vm();
1945 NativeCallFrameTracer tracer(&vm, exec);
1947 return JSValue::decode(value).toString(exec);
1950 JSCell* JIT_OPERATION operationCallStringConstructorOnCell(ExecState* exec, JSCell* cell)
1952 VM& vm = exec->vm();
1953 NativeCallFrameTracer tracer(&vm, exec);
1955 return stringConstructor(exec, cell);
1958 JSCell* JIT_OPERATION operationCallStringConstructor(ExecState* exec, EncodedJSValue value)
1960 VM& vm = exec->vm();
1961 NativeCallFrameTracer tracer(&vm, exec);
1963 return stringConstructor(exec, JSValue::decode(value));
1966 JSCell* JIT_OPERATION operationMakeRope2(ExecState* exec, JSString* left, JSString* right)
1968 VM& vm = exec->vm();
1969 NativeCallFrameTracer tracer(&vm, exec);
1971 return jsString(exec, left, right);
1974 JSCell* JIT_OPERATION operationMakeRope3(ExecState* exec, JSString* a, JSString* b, JSString* c)
1976 VM& vm = exec->vm();
1977 NativeCallFrameTracer tracer(&vm, exec);
1979 return jsString(exec, a, b, c);
1982 JSCell* JIT_OPERATION operationStrCat2(ExecState* exec, EncodedJSValue a, EncodedJSValue b)
1984 VM& vm = exec->vm();
1985 NativeCallFrameTracer tracer(&vm, exec);
1986 auto scope = DECLARE_THROW_SCOPE(vm);
1988 ASSERT(!JSValue::decode(a).isSymbol());
1989 ASSERT(!JSValue::decode(b).isSymbol());
1990 JSString* str1 = JSValue::decode(a).toString(exec);
1991 scope.assertNoException(); // Impossible, since we must have been given non-Symbol primitives.
1992 JSString* str2 = JSValue::decode(b).toString(exec);
1993 scope.assertNoException();
1996 return jsString(exec, str1, str2);
1999 JSCell* JIT_OPERATION operationStrCat3(ExecState* exec, EncodedJSValue a, EncodedJSValue b, EncodedJSValue c)
2001 VM& vm = exec->vm();
2002 NativeCallFrameTracer tracer(&vm, exec);
2003 auto scope = DECLARE_THROW_SCOPE(vm);
2005 ASSERT(!JSValue::decode(a).isSymbol());
2006 ASSERT(!JSValue::decode(b).isSymbol());
2007 ASSERT(!JSValue::decode(c).isSymbol());
2008 JSString* str1 = JSValue::decode(a).toString(exec);
2009 scope.assertNoException(); // Impossible, since we must have been given non-Symbol primitives.
2010 JSString* str2 = JSValue::decode(b).toString(exec);
2011 scope.assertNoException();
2012 JSString* str3 = JSValue::decode(c).toString(exec);
2013 scope.assertNoException();
2016 return jsString(exec, str1, str2, str3);
2019 char* JIT_OPERATION operationFindSwitchImmTargetForDouble(
2020 ExecState* exec, EncodedJSValue encodedValue, size_t tableIndex)
2022 VM& vm = exec->vm();
2023 NativeCallFrameTracer tracer(&vm, exec);
2025 CodeBlock* codeBlock = exec->codeBlock();
2026 SimpleJumpTable& table = codeBlock->switchJumpTable(tableIndex);
2027 JSValue value = JSValue::decode(encodedValue);
2028 ASSERT(value.isDouble());
2029 double asDouble = value.asDouble();
2030 int32_t asInt32 = static_cast<int32_t>(asDouble);
2031 if (asDouble == asInt32)
2032 return static_cast<char*>(table.ctiForValue(asInt32).executableAddress());
2033 return static_cast<char*>(table.ctiDefault.executableAddress());
2036 char* JIT_OPERATION operationSwitchString(ExecState* exec, size_t tableIndex, JSString* string)
2038 VM& vm = exec->vm();
2039 NativeCallFrameTracer tracer(&vm, exec);
2041 return static_cast<char*>(exec->codeBlock()->stringSwitchJumpTable(tableIndex).ctiForValue(string->value(exec).impl()).executableAddress());
2044 int32_t JIT_OPERATION operationSwitchStringAndGetBranchOffset(ExecState* exec, size_t tableIndex, JSString* string)
2046 VM& vm = exec->vm();
2047 NativeCallFrameTracer tracer(&vm, exec);
2049 return exec->codeBlock()->stringSwitchJumpTable(tableIndex).offsetForValue(string->value(exec).impl(), std::numeric_limits<int32_t>::min());
2052 uintptr_t JIT_OPERATION operationCompareStringImplLess(StringImpl* a, StringImpl* b)
2054 return codePointCompare(a, b) < 0;
2057 uintptr_t JIT_OPERATION operationCompareStringImplLessEq(StringImpl* a, StringImpl* b)
2059 return codePointCompare(a, b) <= 0;
2062 uintptr_t JIT_OPERATION operationCompareStringImplGreater(StringImpl* a, StringImpl* b)
2064 return codePointCompare(a, b) > 0;
2067 uintptr_t JIT_OPERATION operationCompareStringImplGreaterEq(StringImpl* a, StringImpl* b)
2069 return codePointCompare(a, b) >= 0;
2072 uintptr_t JIT_OPERATION operationCompareStringLess(ExecState* exec, JSString* a, JSString* b)
2074 VM& vm = exec->vm();
2075 NativeCallFrameTracer tracer(&vm, exec);
2077 return codePointCompareLessThan(asString(a)->value(exec), asString(b)->value(exec));
2080 uintptr_t JIT_OPERATION operationCompareStringLessEq(ExecState* exec, JSString* a, JSString* b)
2082 VM& vm = exec->vm();
2083 NativeCallFrameTracer tracer(&vm, exec);
2085 return !codePointCompareLessThan(asString(b)->value(exec), asString(a)->value(exec));
2088 uintptr_t JIT_OPERATION operationCompareStringGreater(ExecState* exec, JSString* a, JSString* b)
2090 VM& vm = exec->vm();
2091 NativeCallFrameTracer tracer(&vm, exec);
2093 return codePointCompareLessThan(asString(b)->value(exec), asString(a)->value(exec));
2096 uintptr_t JIT_OPERATION operationCompareStringGreaterEq(ExecState* exec, JSString* a, JSString* b)
2098 VM& vm = exec->vm();
2099 NativeCallFrameTracer tracer(&vm, exec);
2101 return !codePointCompareLessThan(asString(a)->value(exec), asString(b)->value(exec));
2104 void JIT_OPERATION operationNotifyWrite(ExecState* exec, WatchpointSet* set)
2106 VM& vm = exec->vm();
2107 NativeCallFrameTracer tracer(&vm, exec);
2109 set->touch(vm, "Executed NotifyWrite");
2112 void JIT_OPERATION operationThrowStackOverflowForVarargs(ExecState* exec)
2114 VM& vm = exec->vm();
2115 NativeCallFrameTracer tracer(&vm, exec);
2116 auto scope = DECLARE_THROW_SCOPE(vm);
2117 throwStackOverflowError(exec, scope);
2120 int32_t JIT_OPERATION operationSizeOfVarargs(ExecState* exec, EncodedJSValue encodedArguments, int32_t firstVarArgOffset)
2122 VM& vm = exec->vm();
2123 NativeCallFrameTracer tracer(&vm, exec);
2124 JSValue arguments = JSValue::decode(encodedArguments);
2126 return sizeOfVarargs(exec, arguments, firstVarArgOffset);
2129 int32_t JIT_OPERATION operationHasOwnProperty(ExecState* exec, JSObject* thisObject, EncodedJSValue encodedKey)
2131 VM& vm = exec->vm();
2132 NativeCallFrameTracer tracer(&vm, exec);
2133 auto scope = DECLARE_THROW_SCOPE(vm);
2135 JSValue key = JSValue::decode(encodedKey);
2136 Identifier propertyName = key.toPropertyKey(exec);
2137 RETURN_IF_EXCEPTION(scope, false);
2139 PropertySlot slot(thisObject, PropertySlot::InternalMethodType::GetOwnProperty);
2140 bool result = thisObject->hasOwnProperty(exec, propertyName.impl(), slot);
2141 RETURN_IF_EXCEPTION(scope, false);
2143 HasOwnPropertyCache* hasOwnPropertyCache = vm.hasOwnPropertyCache();
2144 ASSERT(hasOwnPropertyCache);
2145 hasOwnPropertyCache->tryAdd(vm, slot, thisObject, propertyName.impl(), result);
2149 int32_t JIT_OPERATION operationArrayIndexOfString(ExecState* exec, Butterfly* butterfly, JSString* searchElement, int32_t index)
2151 VM& vm = exec->vm();
2152 NativeCallFrameTracer tracer(&vm, exec);
2153 auto scope = DECLARE_THROW_SCOPE(vm);
2155 int32_t length = butterfly->publicLength();
2156 auto data = butterfly->contiguous().data();
2157 for (; index < length; ++index) {
2158 JSValue value = data[index].get();
2159 if (!value || !value.isString())
2161 auto* string = asString(value);
2162 if (string == searchElement)
2164 if (string->equal(exec, searchElement))
2166 RETURN_IF_EXCEPTION(scope, { });
2171 int32_t JIT_OPERATION operationArrayIndexOfValueInt32OrContiguous(ExecState* exec, Butterfly* butterfly, EncodedJSValue encodedValue, int32_t index)
2173 VM& vm = exec->vm();
2174 NativeCallFrameTracer tracer(&vm, exec);
2175 auto scope = DECLARE_THROW_SCOPE(vm);
2177 JSValue searchElement = JSValue::decode(encodedValue);
2179 int32_t length = butterfly->publicLength();
2180 auto data = butterfly->contiguous().data();
2181 for (; index < length; ++index) {
2182 JSValue value = data[index].get();
2185 if (JSValue::strictEqual(exec, searchElement, value))
2187 RETURN_IF_EXCEPTION(scope, { });
2192 int32_t JIT_OPERATION operationArrayIndexOfValueDouble(ExecState* exec, Butterfly* butterfly, EncodedJSValue encodedValue, int32_t index)
2194 VM& vm = exec->vm();
2195 NativeCallFrameTracer tracer(&vm, exec);
2197 JSValue searchElement = JSValue::decode(encodedValue);
2199 if (!searchElement.isNumber())
2201 double number = searchElement.asNumber();
2203 int32_t length = butterfly->publicLength();
2204 const double* data = butterfly->contiguousDouble().data();
2205 for (; index < length; ++index) {
2206 // This comparison ignores NaN.
2207 if (data[index] == number)
2213 void JIT_OPERATION operationLoadVarargs(ExecState* exec, int32_t firstElementDest, EncodedJSValue encodedArguments, int32_t offset, int32_t length, int32_t mandatoryMinimum)
2215 VM& vm = exec->vm();
2216 NativeCallFrameTracer tracer(&vm, exec);
2217 JSValue arguments = JSValue::decode(encodedArguments);
2219 loadVarargs(exec, VirtualRegister(firstElementDest), arguments, offset, length);
2221 for (int32_t i = length; i < mandatoryMinimum; ++i)
2222 exec->r(firstElementDest + i) = jsUndefined();
2225 double JIT_OPERATION operationFModOnInts(int32_t a, int32_t b)
2230 #if USE(JSVALUE32_64)
2231 double JIT_OPERATION operationRandom(JSGlobalObject* globalObject)
2233 return globalObject->weakRandomNumber();
2237 JSCell* JIT_OPERATION operationStringFromCharCode(ExecState* exec, int32_t op1)
2239 VM* vm = &exec->vm();
2240 NativeCallFrameTracer tracer(vm, exec);
2241 return JSC::stringFromCharCode(exec, op1);
2244 EncodedJSValue JIT_OPERATION operationStringFromCharCodeUntyped(ExecState* exec, EncodedJSValue encodedValue)
2246 VM* vm = &exec->vm();
2247 NativeCallFrameTracer tracer(vm, exec);
2248 JSValue charValue = JSValue::decode(encodedValue);
2249 int32_t chInt = charValue.toUInt32(exec);
2250 return JSValue::encode(JSC::stringFromCharCode(exec, chInt));
2253 int64_t JIT_OPERATION operationConvertBoxedDoubleToInt52(EncodedJSValue encodedValue)
2255 JSValue value = JSValue::decode(encodedValue);
2256 if (!value.isDouble())
2257 return JSValue::notInt52;
2258 return tryConvertToInt52(value.asDouble());
2261 int64_t JIT_OPERATION operationConvertDoubleToInt52(double value)
2263 return tryConvertToInt52(value);
2266 size_t JIT_OPERATION operationDefaultHasInstance(ExecState* exec, JSCell* value, JSCell* proto) // Returns jsBoolean(True|False) on 64-bit.
2268 VM* vm = &exec->vm();
2269 NativeCallFrameTracer tracer(vm, exec);
2270 if (JSObject::defaultHasInstance(exec, value, proto))
2275 char* JIT_OPERATION operationNewRawObject(ExecState* exec, Structure* structure, int32_t length, Butterfly* butterfly)
2277 VM& vm = exec->vm();
2278 NativeCallFrameTracer tracer(&vm, exec);
2281 && (structure->outOfLineCapacity() || hasIndexedProperties(structure->indexingType()))) {
2282 IndexingHeader header;
2283 header.setVectorLength(length);
2284 header.setPublicLength(0);
2286 butterfly = Butterfly::create(
2287 vm, nullptr, 0, structure->outOfLineCapacity(),
2288 hasIndexedProperties(structure->indexingType()), header,
2289 length * sizeof(EncodedJSValue));
2292 JSObject* result = JSObject::createRawObject(exec, structure, butterfly);
2293 result->butterfly(); // Ensure that the butterfly is in to-space.
2294 return bitwise_cast<char*>(result);
2297 JSCell* JIT_OPERATION operationNewObjectWithButterfly(ExecState* exec, Structure* structure, Butterfly* butterfly)
2299 VM& vm = exec->vm();
2300 NativeCallFrameTracer tracer(&vm, exec);
2303 butterfly = Butterfly::create(
2304 vm, nullptr, 0, structure->outOfLineCapacity(), false, IndexingHeader(), 0);
2307 JSObject* result = JSObject::createRawObject(exec, structure, butterfly);
2308 result->butterfly(); // Ensure that the butterfly is in to-space.
2312 JSCell* JIT_OPERATION operationNewObjectWithButterflyWithIndexingHeaderAndVectorLength(ExecState* exec, Structure* structure, unsigned length, Butterfly* butterfly)
2314 VM& vm = exec->vm();
2315 NativeCallFrameTracer tracer(&vm, exec);
2317 IndexingHeader header;
2318 header.setVectorLength(length);
2319 header.setPublicLength(0);
2321 *butterfly->indexingHeader() = header;
2323 butterfly = Butterfly::create(
2324 vm, nullptr, 0, structure->outOfLineCapacity(), true, header,
2325 sizeof(EncodedJSValue) * length);
2328 // Paradoxically this may allocate a JSArray. That's totally cool.
2329 JSObject* result = JSObject::createRawObject(exec, structure, butterfly);
2330 result->butterfly(); // Ensure that the butterfly is in to-space.
2334 JSCell* JIT_OPERATION operationNewArrayWithSpreadSlow(ExecState* exec, void* buffer, uint32_t numItems)
2336 VM& vm = exec->vm();
2337 NativeCallFrameTracer tracer(&vm, exec);
2338 auto scope = DECLARE_THROW_SCOPE(vm);
2340 EncodedJSValue* values = static_cast<EncodedJSValue*>(buffer);
2341 Checked<unsigned, RecordOverflow> checkedLength = 0;
2342 for (unsigned i = 0; i < numItems; i++) {
2343 JSValue value = JSValue::decode(values[i]);
2344 if (JSFixedArray* array = jsDynamicCast<JSFixedArray*>(vm, value))
2345 checkedLength += array->size();
2350 if (UNLIKELY(checkedLength.hasOverflowed())) {
2351 throwOutOfMemoryError(exec, scope);
2355 unsigned length = checkedLength.unsafeGet();
2356 JSGlobalObject* globalObject = exec->lexicalGlobalObject();
2357 Structure* structure = globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithContiguous);
2359 JSArray* result = JSArray::tryCreate(vm, structure, length);
2360 if (UNLIKELY(!result)) {
2361 throwOutOfMemoryError(exec, scope);
2364 RETURN_IF_EXCEPTION(scope, nullptr);
2367 for (unsigned i = 0; i < numItems; i++) {
2368 JSValue value = JSValue::decode(values[i]);
2369 if (JSFixedArray* array = jsDynamicCast<JSFixedArray*>(vm, value)) {
2370 // We are spreading.
2371 for (unsigned i = 0; i < array->size(); i++) {
2372 result->putDirectIndex(exec, index, array->get(i));
2373 RETURN_IF_EXCEPTION(scope, nullptr);
2377 // We are not spreading.
2378 result->putDirectIndex(exec, index, value);
2379 RETURN_IF_EXCEPTION(scope, nullptr);
2387 JSCell* JIT_OPERATION operationSpreadGeneric(ExecState* exec, JSCell* iterable)
2389 VM& vm = exec->vm();
2390 NativeCallFrameTracer tracer(&vm, exec);
2392 auto throwScope = DECLARE_THROW_SCOPE(vm);
2394 if (isJSArray(iterable)) {
2395 JSArray* array = jsCast<JSArray*>(iterable);
2396 if (array->isIteratorProtocolFastAndNonObservable()) {
2397 throwScope.release();
2398 return JSFixedArray::createFromArray(exec, vm, array);
2402 // FIXME: we can probably make this path faster by having our caller JS code call directly into
2403 // the iteration protocol builtin: https://bugs.webkit.org/show_bug.cgi?id=164520
2405 JSGlobalObject* globalObject = exec->lexicalGlobalObject();
2408 JSFunction* iterationFunction = globalObject->iteratorProtocolFunction();
2410 CallType callType = JSC::getCallData(iterationFunction, callData);
2411 ASSERT(callType != CallType::None);
2413 MarkedArgumentBuffer arguments;
2414 arguments.append(iterable);
2415 ASSERT(!arguments.hasOverflowed());
2416 JSValue arrayResult = call(exec, iterationFunction, callType, callData, jsNull(), arguments);
2417 RETURN_IF_EXCEPTION(throwScope, nullptr);
2418 array = jsCast<JSArray*>(arrayResult);
2421 throwScope.release();
2422 return JSFixedArray::createFromArray(exec, vm, array);
2425 JSCell* JIT_OPERATION operationSpreadFastArray(ExecState* exec, JSCell* cell)
2427 VM& vm = exec->vm();
2428 NativeCallFrameTracer tracer(&vm, exec);
2430 ASSERT(isJSArray(cell));
2431 JSArray* array = jsCast<JSArray*>(cell);
2432 ASSERT(array->isIteratorProtocolFastAndNonObservable());
2434 return JSFixedArray::createFromArray(exec, vm, array);
2437 void JIT_OPERATION operationProcessTypeProfilerLogDFG(ExecState* exec)
2439 VM& vm = exec->vm();
2440 NativeCallFrameTracer tracer(&vm, exec);
2442 vm.typeProfilerLog()->processLogEntries(ASCIILiteral("Log Full, called from inside DFG."));
2445 EncodedJSValue JIT_OPERATION operationResolveScopeForHoistingFuncDeclInEval(ExecState* exec, JSScope* scope, UniquedStringImpl* impl)
2447 VM& vm = exec->vm();
2448 NativeCallFrameTracer tracer(&vm, exec);
2450 JSValue resolvedScope = JSScope::resolveScopeForHoistingFuncDeclInEval(exec, scope, Identifier::fromUid(exec, impl));
2451 return JSValue::encode(resolvedScope);
2454 JSCell* JIT_OPERATION operationResolveScope(ExecState* exec, JSScope* scope, UniquedStringImpl* impl)
2456 VM& vm = exec->vm();
2457 NativeCallFrameTracer tracer(&vm, exec);
2459 JSObject* resolvedScope = JSScope::resolve(exec, scope, Identifier::fromUid(exec, impl));
2460 return resolvedScope;
2463 EncodedJSValue JIT_OPERATION operationGetDynamicVar(ExecState* exec, JSObject* scope, UniquedStringImpl* impl, unsigned getPutInfoBits)
2465 VM& vm = exec->vm();
2466 NativeCallFrameTracer tracer(&vm, exec);
2467 auto throwScope = DECLARE_THROW_SCOPE(vm);
2469 Identifier ident = Identifier::fromUid(exec, impl);
2470 throwScope.release();
2471 return JSValue::encode(scope->getPropertySlot(exec, ident, [&] (bool found, PropertySlot& slot) -> JSValue {
2473 GetPutInfo getPutInfo(getPutInfoBits);
2474 if (getPutInfo.resolveMode() == ThrowIfNotFound)
2475 throwException(exec, throwScope, createUndefinedVariableError(exec, ident));
2476 return jsUndefined();
2479 if (scope->isGlobalLexicalEnvironment()) {
2480 // When we can't statically prove we need a TDZ check, we must perform the check on the slow path.
2481 JSValue result = slot.getValue(exec, ident);
2482 if (result == jsTDZValue()) {
2483 throwException(exec, throwScope, createTDZError(exec));
2484 return jsUndefined();
2489 return slot.getValue(exec, ident);
2493 void JIT_OPERATION operationPutDynamicVar(ExecState* exec, JSObject* scope, EncodedJSValue value, UniquedStringImpl* impl, unsigned getPutInfoBits)
2495 VM& vm = exec->vm();
2496 NativeCallFrameTracer tracer(&vm, exec);
2497 auto throwScope = DECLARE_THROW_SCOPE(vm);
2499 const Identifier& ident = Identifier::fromUid(exec, impl);
2500 GetPutInfo getPutInfo(getPutInfoBits);
2501 bool hasProperty = scope->hasProperty(exec, ident);
2502 RETURN_IF_EXCEPTION(throwScope, void());
2504 && scope->isGlobalLexicalEnvironment()
2505 && !isInitialization(getPutInfo.initializationMode())) {
2506 // When we can't statically prove we need a TDZ check, we must perform the check on the slow path.
2507 PropertySlot slot(scope, PropertySlot::InternalMethodType::Get);
2508 JSGlobalLexicalEnvironment::getOwnPropertySlot(scope, exec, ident, slot);
2509 if (slot.getValue(exec, ident) == jsTDZValue()) {
2510 throwException(exec, throwScope, createTDZError(exec));
2515 if (getPutInfo.resolveMode() == ThrowIfNotFound && !hasProperty) {
2516 throwException(exec, throwScope, createUndefinedVariableError(exec, ident));
2520 CodeOrigin origin = exec->codeOrigin();
2522 if (origin.inlineCallFrame)
2523 strictMode = origin.inlineCallFrame->baselineCodeBlock->isStrictMode();
2525 strictMode = exec->codeBlock()->isStrictMode();
2526 PutPropertySlot slot(scope, strictMode, PutPropertySlot::UnknownContext, isInitialization(getPutInfo.initializationMode()));
2527 throwScope.release();
2528 scope->methodTable(vm)->put(scope, exec, ident, JSValue::decode(value), slot);
2531 int32_t JIT_OPERATION operationMapHash(ExecState* exec, EncodedJSValue input)
2533 VM& vm = exec->vm();
2534 NativeCallFrameTracer tracer(&vm, exec);
2536 return jsMapHash(exec, vm, JSValue::decode(input));
2539 JSCell* JIT_OPERATION operationJSMapFindBucket(ExecState* exec, JSCell* map, EncodedJSValue key, int32_t hash)
2541 VM& vm = exec->vm();
2542 NativeCallFrameTracer tracer(&vm, exec);
2543 JSMap::BucketType** bucket = jsCast<JSMap*>(map)->findBucket(exec, JSValue::decode(key), hash);
2545 return vm.sentinelMapBucket.get();
2549 JSCell* JIT_OPERATION operationJSSetFindBucket(ExecState* exec, JSCell* map, EncodedJSValue key, int32_t hash)
2551 VM& vm = exec->vm();
2552 NativeCallFrameTracer tracer(&vm, exec);
2553 JSSet::BucketType** bucket = jsCast<JSSet*>(map)->findBucket(exec, JSValue::decode(key), hash);
2555 return vm.sentinelSetBucket.get();
2559 void JIT_OPERATION operationSetAdd(ExecState* exec, JSCell* set, EncodedJSValue key, int32_t hash)
2561 VM& vm = exec->vm();
2562 NativeCallFrameTracer tracer(&vm, exec);
2563 jsCast<JSSet*>(set)->addNormalized(exec, JSValue::decode(key), JSValue(), hash);
2566 void JIT_OPERATION operationMapSet(ExecState* exec, JSCell* map, EncodedJSValue key, EncodedJSValue value, int32_t hash)
2568 VM& vm = exec->vm();
2569 NativeCallFrameTracer tracer(&vm, exec);
2570 jsCast<JSMap*>(map)->addNormalized(exec, JSValue::decode(key), JSValue::decode(value), hash);
2573 EncodedJSValue JIT_OPERATION operationGetPrototypeOfObject(ExecState* exec, JSObject* thisObject)
2575 VM& vm = exec->vm();
2576 NativeCallFrameTracer tracer(&vm, exec);
2577 return JSValue::encode(thisObject->getPrototype(vm, exec));
2580 EncodedJSValue JIT_OPERATION operationGetPrototypeOf(ExecState* exec, EncodedJSValue encodedValue)
2582 VM& vm = exec->vm();
2583 NativeCallFrameTracer tracer(&vm, exec);
2584 auto scope = DECLARE_THROW_SCOPE(vm);
2586 JSValue thisValue = JSValue::decode(encodedValue).toThis(exec, StrictMode);
2587 if (thisValue.isUndefinedOrNull())
2588 return throwVMError(exec, scope, createNotAnObjectError(exec, thisValue));
2590 JSObject* thisObject = jsDynamicCast<JSObject*>(vm, thisValue);
2592 JSObject* prototype = thisValue.synthesizePrototype(exec);
2593 EXCEPTION_ASSERT(!!scope.exception() == !prototype);
2594 if (UNLIKELY(!prototype))
2595 return JSValue::encode(JSValue());
2596 return JSValue::encode(prototype);
2600 return JSValue::encode(thisObject->getPrototype(vm, exec));
2603 void JIT_OPERATION operationThrowDFG(ExecState* exec, EncodedJSValue valueToThrow)
2605 VM& vm = exec->vm();
2606 NativeCallFrameTracer tracer(&vm, exec);
2607 auto scope = DECLARE_THROW_SCOPE(vm);
2608 scope.throwException(exec, JSValue::decode(valueToThrow));
2611 void JIT_OPERATION operationThrowStaticError(ExecState* exec, JSString* message, uint32_t errorType)
2613 VM& vm = exec->vm();
2614 NativeCallFrameTracer tracer(&vm, exec);
2615 auto scope = DECLARE_THROW_SCOPE(vm);
2616 String errorMessage = message->value(exec);
2617 scope.throwException(exec, createError(exec, static_cast<ErrorType>(errorType), errorMessage));
2620 extern "C" void JIT_OPERATION triggerReoptimizationNow(CodeBlock* codeBlock, OSRExitBase* exit)
2622 // It's sort of preferable that we don't GC while in here. Anyways, doing so wouldn't
2623 // really be profitable.
2624 DeferGCForAWhile deferGC(codeBlock->vm()->heap);
2626 sanitizeStackForVM(codeBlock->vm());
2628 if (Options::verboseOSR())
2629 dataLog(*codeBlock, ": Entered reoptimize\n");
2630 // We must be called with the baseline code block.
2631 ASSERT(JITCode::isBaselineCode(codeBlock->jitType()));
2633 // If I am my own replacement, then reoptimization has already been triggered.
2634 // This can happen in recursive functions.
2635 if (codeBlock->replacement() == codeBlock) {
2636 if (Options::verboseOSR())
2637 dataLog(*codeBlock, ": Not reoptimizing because we've already been jettisoned.\n");
2641 // Otherwise, the replacement must be optimized code. Use this as an opportunity
2642 // to check our logic.
2643 ASSERT(codeBlock->hasOptimizedReplacement());
2644 CodeBlock* optimizedCodeBlock = codeBlock->replacement();
2645 ASSERT(JITCode::isOptimizingJIT(optimizedCodeBlock->jitType()));
2647 bool didTryToEnterIntoInlinedLoops = false;
2648 for (InlineCallFrame* inlineCallFrame = exit->m_codeOrigin.inlineCallFrame; inlineCallFrame; inlineCallFrame = inlineCallFrame->directCaller.inlineCallFrame) {
2649 if (inlineCallFrame->baselineCodeBlock->ownerScriptExecutable()->didTryToEnterInLoop()) {
2650 didTryToEnterIntoInlinedLoops = true;
2655 // In order to trigger reoptimization, one of two things must have happened:
2656 // 1) We exited more than some number of times.
2657 // 2) We exited and got stuck in a loop, and now we're exiting again.
2658 bool didExitABunch = optimizedCodeBlock->shouldReoptimizeNow();
2659 bool didGetStuckInLoop =
2660 (codeBlock->checkIfOptimizationThresholdReached() || didTryToEnterIntoInlinedLoops)
2661 && optimizedCodeBlock->shouldReoptimizeFromLoopNow();
2663 if (!didExitABunch && !didGetStuckInLoop) {
2664 if (Options::verboseOSR())
2665 dataLog(*codeBlock, ": Not reoptimizing ", *optimizedCodeBlock, " because it either didn't exit enough or didn't loop enough after exit.\n");
2666 codeBlock->optimizeAfterLongWarmUp();
2670 optimizedCodeBlock->jettison(Profiler::JettisonDueToOSRExit, CountReoptimization);
2674 static bool shouldTriggerFTLCompile(CodeBlock* codeBlock, JITCode* jitCode)
2676 if (codeBlock->baselineVersion()->m_didFailFTLCompilation) {
2677 CODEBLOCK_LOG_EVENT(codeBlock, "abortFTLCompile", ());
2678 if (Options::verboseOSR())
2679 dataLog("Deferring FTL-optimization of ", *codeBlock, " indefinitely because there was an FTL failure.\n");
2680 jitCode->dontOptimizeAnytimeSoon(codeBlock);
2684 if (!codeBlock->hasOptimizedReplacement()
2685 && !jitCode->checkIfOptimizationThresholdReached(codeBlock)) {
2686 CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("counter = ", jitCode->tierUpCounter));
2687 if (Options::verboseOSR())
2688 dataLog("Choosing not to FTL-optimize ", *codeBlock, " yet.\n");
2694 static void triggerFTLReplacementCompile(VM* vm, CodeBlock* codeBlock, JITCode* jitCode)
2696 if (codeBlock->codeType() == GlobalCode) {
2697 // Global code runs once, so we don't want to do anything. We don't want to defer indefinitely,
2698 // since this may have been spuriously called from tier-up initiated in a loop, and that loop may
2699 // later want to run faster code. Deferring for warm-up seems safest.
2700 jitCode->optimizeAfterWarmUp(codeBlock);
2704 Worklist::State worklistState;
2705 if (Worklist* worklist = existingGlobalFTLWorklistOrNull()) {
2706 worklistState = worklist->completeAllReadyPlansForVM(
2707 *vm, CompilationKey(codeBlock->baselineVersion(), FTLMode));
2709 worklistState = Worklist::NotKnown;
2711 if (worklistState == Worklist::Compiling) {
2712 CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("still compiling"));
2713 jitCode->setOptimizationThresholdBasedOnCompilationResult(
2714 codeBlock, CompilationDeferred);
2718 if (codeBlock->hasOptimizedReplacement()) {
2719 CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("has replacement"));
2720 // That's great, we've compiled the code - next time we call this function,
2721 // we'll enter that replacement.
2722 jitCode->optimizeSoon(codeBlock);
2726 if (worklistState == Worklist::Compiled) {
2727 CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("compiled and failed"));
2728 // This means that we finished compiling, but failed somehow; in that case the
2729 // thresholds will be set appropriately.
2730 if (Options::verboseOSR())
2731 dataLog("Code block ", *codeBlock, " was compiled but it doesn't have an optimized replacement.\n");
2735 CODEBLOCK_LOG_EVENT(codeBlock, "triggerFTLReplacement", ());
2736 // We need to compile the code.
2738 *vm, codeBlock->newReplacement(), codeBlock, FTLMode, UINT_MAX,
2739 Operands<JSValue>(), ToFTLDeferredCompilationCallback::create());
2741 // If we reached here, the counter has not be reset. Do that now.
2742 jitCode->setOptimizationThresholdBasedOnCompilationResult(
2743 codeBlock, CompilationDeferred);
2746 void JIT_OPERATION triggerTierUpNow(ExecState* exec)
2748 VM* vm = &exec->vm();
2749 NativeCallFrameTracer tracer(vm, exec);
2750 DeferGCForAWhile deferGC(vm->heap);
2751 CodeBlock* codeBlock = exec->codeBlock();
2753 sanitizeStackForVM(vm);
2755 if (codeBlock->jitType() != JITCode::DFGJIT) {
2756 dataLog("Unexpected code block in DFG->FTL tier-up: ", *codeBlock, "\n");
2757 RELEASE_ASSERT_NOT_REACHED();
2760 JITCode* jitCode = codeBlock->jitCode()->dfg();
2762 if (Options::verboseOSR()) {
2764 *codeBlock, ": Entered triggerTierUpNow with executeCounter = ",
2765 jitCode->tierUpCounter, "\n");
2768 if (shouldTriggerFTLCompile(codeBlock, jitCode))
2769 triggerFTLReplacementCompile(vm, codeBlock, jitCode);
2771 if (codeBlock->hasOptimizedReplacement()) {
2772 if (jitCode->tierUpEntryTriggers.isEmpty()) {
2773 CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("replacement in place, delaying indefinitely"));
2774 // There is nothing more we can do, the only way this will be entered
2775 // is through the function entry point.
2776 jitCode->dontOptimizeAnytimeSoon(codeBlock);
2779 if (jitCode->osrEntryBlock() && jitCode->tierUpEntryTriggers.size() == 1) {
2780 CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("trigger in place, delaying indefinitely"));
2781 // There is only one outer loop and its trigger must have been set
2782 // when the plan completed.
2783 // Exiting the inner loop is useless, we can ignore the counter and leave
2784 // the trigger do its job.
2785 jitCode->dontOptimizeAnytimeSoon(codeBlock);
2791 static char* tierUpCommon(ExecState* exec, unsigned originBytecodeIndex, unsigned osrEntryBytecodeIndex)
2793 VM* vm = &exec->vm();
2794 CodeBlock* codeBlock = exec->codeBlock();
2796 // Resolve any pending plan for OSR Enter on this function.
2797 Worklist::State worklistState;
2798 if (Worklist* worklist = existingGlobalFTLWorklistOrNull()) {
2799 worklistState = worklist->completeAllReadyPlansForVM(
2800 *vm, CompilationKey(codeBlock->baselineVersion(), FTLForOSREntryMode));
2802 worklistState = Worklist::NotKnown;
2804 JITCode* jitCode = codeBlock->jitCode()->dfg();
2806 // The following is only true for triggerTierUpNowInLoop, which can never
2808 bool canOSRFromHere = originBytecodeIndex == osrEntryBytecodeIndex;
2810 bool triggeredSlowPathToStartCompilation = false;
2811 auto tierUpEntryTriggers = jitCode->tierUpEntryTriggers.find(originBytecodeIndex);
2812 if (tierUpEntryTriggers != jitCode->tierUpEntryTriggers.end()) {
2813 switch (tierUpEntryTriggers->value) {
2814 case JITCode::TriggerReason::DontTrigger:
2815 // The trigger isn't set, we entered because the counter reached its
2819 case JITCode::TriggerReason::CompilationDone:
2820 // The trigger was set because compilation completed. Don't unset it
2821 // so that further DFG executions OSR enters as well.
2822 RELEASE_ASSERT(canOSRFromHere);
2825 case JITCode::TriggerReason::StartCompilation:
2826 // We were asked to enter as soon as possible and start compiling an
2827 // entry for the current bytecode location. Unset this trigger so we
2828 // don't continually enter.
2829 RELEASE_ASSERT(canOSRFromHere);
2830 tierUpEntryTriggers->value = JITCode::TriggerReason::DontTrigger;
2831 triggeredSlowPathToStartCompilation = true;
2836 if (worklistState == Worklist::Compiling) {
2837 CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("still compiling"));
2838 jitCode->setOptimizationThresholdBasedOnCompilationResult(
2839 codeBlock, CompilationDeferred);
2843 if (worklistState == Worklist::Compiled) {
2844 CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("compiled and failed"));
2845 // This means that compilation failed and we already set the thresholds.
2846 if (Options::verboseOSR())
2847 dataLog("Code block ", *codeBlock, " was compiled but it doesn't have an optimized replacement.\n");
2851 // If we can OSR Enter, do it right away.
2852 if (canOSRFromHere) {
2853 unsigned streamIndex = jitCode->bytecodeIndexToStreamIndex.get(originBytecodeIndex);
2854 if (CodeBlock* entryBlock = jitCode->osrEntryBlock()) {
2855 if (Options::verboseOSR())
2856 dataLog("OSR entry: From ", RawPointer(jitCode), " got entry block ", RawPointer(entryBlock), "\n");
2857 if (void* address = FTL::prepareOSREntry(exec, codeBlock, entryBlock, originBytecodeIndex, streamIndex)) {
2858 CODEBLOCK_LOG_EVENT(entryBlock, "osrEntry", ("at bc#", originBytecodeIndex));
2859 return static_cast<char*>(address);
2864 // - If we don't have an FTL code block, then try to compile one.
2865 // - If we do have an FTL code block, then try to enter for a while.
2866 // - If we couldn't enter for a while, then trigger OSR entry.
2868 if (!shouldTriggerFTLCompile(codeBlock, jitCode) && !triggeredSlowPathToStartCompilation)
2871 if (!jitCode->neverExecutedEntry && !triggeredSlowPathToStartCompilation) {
2872 triggerFTLReplacementCompile(vm, codeBlock, jitCode);
2874 if (!codeBlock->hasOptimizedReplacement())
2877 if (jitCode->osrEntryRetry < Options::ftlOSREntryRetryThreshold()) {
2878 CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("avoiding OSR entry compile"));
2879 jitCode->osrEntryRetry++;
2883 CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("avoiding replacement compile"));
2885 // It's time to try to compile code for OSR entry.
2886 if (CodeBlock* entryBlock = jitCode->osrEntryBlock()) {
2887 if (jitCode->osrEntryRetry < Options::ftlOSREntryRetryThreshold()) {
2888 CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("OSR entry failed, OSR entry threshold not met"));
2889 jitCode->osrEntryRetry++;
2890 jitCode->setOptimizationThresholdBasedOnCompilationResult(
2891 codeBlock, CompilationDeferred);
2895 FTL::ForOSREntryJITCode* entryCode = entryBlock->jitCode()->ftlForOSREntry();
2896 entryCode->countEntryFailure();
2897 if (entryCode->entryFailureCount() <
2898 Options::ftlOSREntryFailureCountForReoptimization()) {
2899 CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("OSR entry failed"));
2900 jitCode->setOptimizationThresholdBasedOnCompilationResult(
2901 codeBlock, CompilationDeferred);
2905 // OSR entry failed. Oh no! This implies that we need to retry. We retry
2906 // without exponential backoff and we only do this for the entry code block.
2907 CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("OSR entry failed too many times"));
2908 unsigned osrEntryBytecode = entryBlock->jitCode()->ftlForOSREntry()->bytecodeIndex();
2909 jitCode->clearOSREntryBlock();
2910 jitCode->osrEntryRetry = 0;
2911 jitCode->tierUpEntryTriggers.set(osrEntryBytecode, JITCode::TriggerReason::DontTrigger);
2912 jitCode->setOptimizationThresholdBasedOnCompilationResult(
2913 codeBlock, CompilationDeferred);
2917 if (!canOSRFromHere) {
2918 // We can't OSR from here, or even start a compilation because doing so
2919 // calls jitCode->reconstruct which would get the wrong state.
2920 if (Options::verboseOSR())
2921 dataLog("Non-OSR-able bc#", originBytecodeIndex, " in ", *codeBlock, " setting parent loop bc#", osrEntryBytecodeIndex, "'s trigger and backing off.\n");
2922 jitCode->tierUpEntryTriggers.set(osrEntryBytecodeIndex, JITCode::TriggerReason::StartCompilation);
2923 jitCode->setOptimizationThresholdBasedOnCompilationResult(codeBlock, CompilationDeferred);
2927 unsigned streamIndex = jitCode->bytecodeIndexToStreamIndex.get(osrEntryBytecodeIndex);
2929 if (!triggeredSlowPathToStartCompilation) {
2930 auto tierUpHierarchyEntry = jitCode->tierUpInLoopHierarchy.find(osrEntryBytecodeIndex);
2931 if (tierUpHierarchyEntry != jitCode->tierUpInLoopHierarchy.end()) {
2932 for (unsigned osrEntryCandidate : tierUpHierarchyEntry->value) {
2933 if (jitCode->tierUpEntrySeen.contains(osrEntryCandidate)) {
2934 // Ask an enclosing loop to compile, instead of doing so here.
2935 if (Options::verboseOSR())
2936 dataLog("Inner-loop bc#", originBytecodeIndex, " in ", *codeBlock, " setting parent loop bc#", osrEntryCandidate, "'s trigger and backing off.\n");
2937 jitCode->tierUpEntryTriggers.set(osrEntryCandidate, JITCode::TriggerReason::StartCompilation);
2938 jitCode->setOptimizationThresholdBasedOnCompilationResult(codeBlock, CompilationDeferred);
2945 // We aren't compiling and haven't compiled anything for OSR entry. So, try to compile
2947 auto triggerIterator = jitCode->tierUpEntryTriggers.find(osrEntryBytecodeIndex);
2948 RELEASE_ASSERT(triggerIterator != jitCode->tierUpEntryTriggers.end());
2949 JITCode::TriggerReason* triggerAddress = &(triggerIterator->value);
2951 Operands<JSValue> mustHandleValues;
2952 jitCode->reconstruct(
2953 exec, codeBlock, CodeOrigin(osrEntryBytecodeIndex), streamIndex, mustHandleValues);
2954 CodeBlock* replacementCodeBlock = codeBlock->newReplacement();
2956 CODEBLOCK_LOG_EVENT(codeBlock, "triggerFTLOSR", ());
2957 CompilationResult forEntryResult = compile(
2958 *vm, replacementCodeBlock, codeBlock, FTLForOSREntryMode, osrEntryBytecodeIndex,
2959 mustHandleValues, ToFTLForOSREntryDeferredCompilationCallback::create(triggerAddress));
2961 if (jitCode->neverExecutedEntry)
2962 triggerFTLReplacementCompile(vm, codeBlock, jitCode);
2964 if (forEntryResult != CompilationSuccessful) {
2965 CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("OSR ecompilation not successful"));
2966 jitCode->setOptimizationThresholdBasedOnCompilationResult(
2967 codeBlock, CompilationDeferred);
2971 CODEBLOCK_LOG_EVENT(jitCode->osrEntryBlock(), "osrEntry", ("at bc#", originBytecodeIndex));
2972 // It's possible that the for-entry compile already succeeded. In that case OSR
2973 // entry will succeed unless we ran out of stack. It's not clear what we should do.
2974 // We signal to try again after a while if that happens.
2975 if (Options::verboseOSR())
2976 dataLog("Immediate OSR entry: From ", RawPointer(jitCode), " got entry block ", RawPointer(jitCode->osrEntryBlock()), "\n");
2977 void* address = FTL::prepareOSREntry(
2978 exec, codeBlock, jitCode->osrEntryBlock(), originBytecodeIndex, streamIndex);
2979 return static_cast<char*>(address);
2982 void JIT_OPERATION triggerTierUpNowInLoop(ExecState* exec, unsigned bytecodeIndex)
2984 VM* vm = &exec->vm();
2985 NativeCallFrameTracer tracer(vm, exec);
2986 DeferGCForAWhile deferGC(vm->heap);
2987 CodeBlock* codeBlock = exec->codeBlock();
2989 sanitizeStackForVM(vm);
2991 if (codeBlock->jitType() != JITCode::DFGJIT) {
2992 dataLog("Unexpected code block in DFG->FTL tier-up: ", *codeBlock, "\n");
2993 RELEASE_ASSERT_NOT_REACHED();
2996 JITCode* jitCode = codeBlock->jitCode()->dfg();
2998 if (Options::verboseOSR()) {
3000 *codeBlock, ": Entered triggerTierUpNowInLoop with executeCounter = ",
3001 jitCode->tierUpCounter, "\n");
3004 auto tierUpHierarchyEntry = jitCode->tierUpInLoopHierarchy.find(bytecodeIndex);
3005 if (tierUpHierarchyEntry != jitCode->tierUpInLoopHierarchy.end()
3006 && !tierUpHierarchyEntry->value.isEmpty()) {
3007 tierUpCommon(exec, bytecodeIndex, tierUpHierarchyEntry->value.first());
3008 } else if (shouldTriggerFTLCompile(codeBlock, jitCode))
3009 triggerFTLReplacementCompile(vm, codeBlock, jitCode);
3011 // Since we cannot OSR Enter here, the default "optimizeSoon()" is not useful.
3012 if (codeBlock->hasOptimizedReplacement()) {
3013 CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("OSR in loop failed, deferring"));
3014 jitCode->setOptimizationThresholdBasedOnCompilationResult(codeBlock, CompilationDeferred);
3018 char* JIT_OPERATION triggerOSREntryNow(ExecState* exec, unsigned bytecodeIndex)
3020 VM* vm = &exec->vm();
3021 NativeCallFrameTracer tracer(vm, exec);
3022 DeferGCForAWhile deferGC(vm->heap);
3023 CodeBlock* codeBlock = exec->codeBlock();
3025 sanitizeStackForVM(vm);
3027 if (codeBlock->jitType() != JITCode::DFGJIT) {
3028 dataLog("Unexpected code block in DFG->FTL tier-up: ", *codeBlock, "\n");
3029 RELEASE_ASSERT_NOT_REACHED();
3032 JITCode* jitCode = codeBlock->jitCode()->dfg();
3033 jitCode->tierUpEntrySeen.add(bytecodeIndex);
3035 if (Options::verboseOSR()) {
3037 *codeBlock, ": Entered triggerOSREntryNow with executeCounter = ",
3038 jitCode->tierUpCounter, "\n");
3041 return tierUpCommon(exec, bytecodeIndex, bytecodeIndex);
3044 #endif // ENABLE(FTL_JIT)
3047 } } // namespace JSC::DFG
3049 #endif // ENABLE(DFG_JIT)
3051 #endif // ENABLE(JIT)