1/*
2 * Copyright (C) 2011-2019 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "config.h"
27#include "DFGOperations.h"
28
29#include "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 "DateInstance.h"
42#include "DefinePropertyAttributes.h"
43#include "DirectArguments.h"
44#include "EvalCodeBlock.h"
45#include "FTLForOSREntryJITCode.h"
46#include "FTLOSREntry.h"
47#include "FrameTracers.h"
48#include "HasOwnPropertyCache.h"
49#include "HostCallReturnValue.h"
50#include "Interpreter.h"
51#include "JIT.h"
52#include "JITExceptions.h"
53#include "JSArrayInlines.h"
54#include "JSAsyncGenerator.h"
55#include "JSBigInt.h"
56#include "JSCInlines.h"
57#include "JSFixedArray.h"
58#include "JSGenericTypedArrayViewConstructorInlines.h"
59#include "JSGlobalObjectFunctions.h"
60#include "JSImmutableButterfly.h"
61#include "JSInternalPromise.h"
62#include "JSInternalPromiseConstructor.h"
63#include "JSLexicalEnvironment.h"
64#include "JSMap.h"
65#include "JSPromiseConstructor.h"
66#include "JSPropertyNameEnumerator.h"
67#include "JSSet.h"
68#include "JSWeakMap.h"
69#include "JSWeakSet.h"
70#include "ModuleProgramCodeBlock.h"
71#include "NumberConstructor.h"
72#include "ObjectConstructor.h"
73#include "Operations.h"
74#include "ParseInt.h"
75#include "ProgramCodeBlock.h"
76#include "RegExpGlobalDataInlines.h"
77#include "RegExpMatchesArray.h"
78#include "RegExpObjectInlines.h"
79#include "Repatch.h"
80#include "ScopedArguments.h"
81#include "StringConstructor.h"
82#include "StringPrototypeInlines.h"
83#include "SuperSampler.h"
84#include "Symbol.h"
85#include "TypeProfilerLog.h"
86#include "TypedArrayInlines.h"
87#include "VMInlines.h"
88#include <wtf/InlineASM.h>
89#include <wtf/Variant.h>
90
91#if ENABLE(JIT)
92#if ENABLE(DFG_JIT)
93
94IGNORE_WARNINGS_BEGIN("frame-address")
95
96namespace JSC { namespace DFG {
97
98template<bool strict, bool direct>
99static inline void putByVal(JSGlobalObject* globalObject, VM& vm, JSValue baseValue, uint32_t index, JSValue value)
100{
101 ASSERT(isIndex(index));
102 if (direct) {
103 RELEASE_ASSERT(baseValue.isObject());
104 asObject(baseValue)->putDirectIndex(globalObject, index, value, 0, strict ? PutDirectIndexShouldThrow : PutDirectIndexShouldNotThrow);
105 return;
106 }
107 if (baseValue.isObject()) {
108 JSObject* object = asObject(baseValue);
109 if (object->canSetIndexQuickly(index, value)) {
110 object->setIndexQuickly(vm, index, value);
111 return;
112 }
113
114 object->methodTable(vm)->putByIndex(object, globalObject, index, value, strict);
115 return;
116 }
117
118 baseValue.putByIndex(globalObject, index, value, strict);
119}
120
121template<bool strict, bool direct>
122ALWAYS_INLINE static void putByValInternal(JSGlobalObject* globalObject, VM& vm, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
123{
124 auto scope = DECLARE_THROW_SCOPE(vm);
125
126 JSValue baseValue = JSValue::decode(encodedBase);
127 JSValue property = JSValue::decode(encodedProperty);
128 JSValue value = JSValue::decode(encodedValue);
129
130 if (LIKELY(property.isUInt32())) {
131 // Despite its name, JSValue::isUInt32 will return true only for positive boxed int32_t; all those values are valid array indices.
132 ASSERT(isIndex(property.asUInt32()));
133 scope.release();
134 putByVal<strict, direct>(globalObject, vm, baseValue, property.asUInt32(), value);
135 return;
136 }
137
138 if (property.isDouble()) {
139 double propertyAsDouble = property.asDouble();
140 uint32_t propertyAsUInt32 = static_cast<uint32_t>(propertyAsDouble);
141 if (propertyAsDouble == propertyAsUInt32 && isIndex(propertyAsUInt32)) {
142 scope.release();
143 putByVal<strict, direct>(globalObject, vm, baseValue, propertyAsUInt32, value);
144 return;
145 }
146 }
147
148 // Don't put to an object if toString throws an exception.
149 auto propertyName = property.toPropertyKey(globalObject);
150 RETURN_IF_EXCEPTION(scope, void());
151
152 PutPropertySlot slot(baseValue, strict);
153 if (direct) {
154 RELEASE_ASSERT(baseValue.isObject());
155 JSObject* baseObject = asObject(baseValue);
156 if (Optional<uint32_t> index = parseIndex(propertyName)) {
157 scope.release();
158 baseObject->putDirectIndex(globalObject, index.value(), value, 0, strict ? PutDirectIndexShouldThrow : PutDirectIndexShouldNotThrow);
159 return;
160 }
161 scope.release();
162 CommonSlowPaths::putDirectWithReify(vm, globalObject, baseObject, propertyName, value, slot);
163 return;
164 }
165 scope.release();
166 baseValue.put(globalObject, propertyName, value, slot);
167}
168
169template<bool strict, bool direct>
170ALWAYS_INLINE static void putByValCellInternal(JSGlobalObject* globalObject, VM& vm, JSCell* base, PropertyName propertyName, JSValue value)
171{
172 PutPropertySlot slot(base, strict);
173 if (direct) {
174 RELEASE_ASSERT(base->isObject());
175 JSObject* baseObject = asObject(base);
176 if (Optional<uint32_t> index = parseIndex(propertyName)) {
177 baseObject->putDirectIndex(globalObject, index.value(), value, 0, strict ? PutDirectIndexShouldThrow : PutDirectIndexShouldNotThrow);
178 return;
179 }
180 CommonSlowPaths::putDirectWithReify(vm, globalObject, baseObject, propertyName, value, slot);
181 return;
182 }
183 base->putInline(globalObject, propertyName, value, slot);
184}
185
186template<bool strict, bool direct>
187ALWAYS_INLINE static void putByValCellStringInternal(JSGlobalObject* globalObject, VM& vm, JSCell* base, JSString* property, JSValue value)
188{
189 auto scope = DECLARE_THROW_SCOPE(vm);
190
191 auto propertyName = property->toIdentifier(globalObject);
192 RETURN_IF_EXCEPTION(scope, void());
193
194 scope.release();
195 putByValCellInternal<strict, direct>(globalObject, vm, base, propertyName, value);
196}
197
198template<typename ViewClass>
199char* newTypedArrayWithSize(JSGlobalObject* globalObject, VM& vm, Structure* structure, int32_t size, char* vector)
200{
201 auto scope = DECLARE_THROW_SCOPE(vm);
202
203 if (size < 0) {
204 throwException(globalObject, scope, createRangeError(globalObject, "Requested length is negative"_s));
205 return 0;
206 }
207
208 if (vector)
209 return bitwise_cast<char*>(ViewClass::createWithFastVector(globalObject, structure, size, untagArrayPtr(vector, size)));
210
211 RELEASE_AND_RETURN(scope, bitwise_cast<char*>(ViewClass::create(globalObject, structure, size)));
212}
213
214template <bool strict>
215static ALWAYS_INLINE void putWithThis(JSGlobalObject* globalObject, EncodedJSValue encodedBase, EncodedJSValue encodedThis, EncodedJSValue encodedValue, const Identifier& ident)
216{
217 JSValue baseValue = JSValue::decode(encodedBase);
218 JSValue thisVal = JSValue::decode(encodedThis);
219 JSValue putValue = JSValue::decode(encodedValue);
220 PutPropertySlot slot(thisVal, strict);
221 baseValue.putInline(globalObject, ident, putValue, slot);
222}
223
224template<typename BigIntOperation, typename NumberOperation>
225static ALWAYS_INLINE EncodedJSValue binaryOp(JSGlobalObject* globalObject, VM& vm, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, BigIntOperation&& bigIntOp, NumberOperation&& numberOp, const char* errorMessage)
226{
227 auto scope = DECLARE_THROW_SCOPE(vm);
228
229 JSValue op1 = JSValue::decode(encodedOp1);
230 JSValue op2 = JSValue::decode(encodedOp2);
231
232 auto leftNumeric = op1.toNumeric(globalObject);
233 RETURN_IF_EXCEPTION(scope, encodedJSValue());
234 auto rightNumeric = op2.toNumeric(globalObject);
235 RETURN_IF_EXCEPTION(scope, encodedJSValue());
236
237 if (WTF::holds_alternative<JSBigInt*>(leftNumeric) || WTF::holds_alternative<JSBigInt*>(rightNumeric)) {
238 if (WTF::holds_alternative<JSBigInt*>(leftNumeric) && WTF::holds_alternative<JSBigInt*>(rightNumeric))
239 RELEASE_AND_RETURN(scope, JSValue::encode(bigIntOp(globalObject, WTF::get<JSBigInt*>(leftNumeric), WTF::get<JSBigInt*>(rightNumeric))));
240
241 return throwVMTypeError(globalObject, scope, errorMessage);
242 }
243
244 scope.release();
245
246 return JSValue::encode(jsNumber(numberOp(WTF::get<double>(leftNumeric), WTF::get<double>(rightNumeric))));
247}
248
249template<typename BigIntOperation, typename Int32Operation>
250static ALWAYS_INLINE EncodedJSValue bitwiseBinaryOp(JSGlobalObject* globalObject, VM& vm, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, BigIntOperation&& bigIntOp, Int32Operation&& int32Op, const char* errorMessage)
251{
252 auto scope = DECLARE_THROW_SCOPE(vm);
253
254 JSValue op1 = JSValue::decode(encodedOp1);
255 JSValue op2 = JSValue::decode(encodedOp2);
256
257 auto leftNumeric = op1.toBigIntOrInt32(globalObject);
258 RETURN_IF_EXCEPTION(scope, encodedJSValue());
259 auto rightNumeric = op2.toBigIntOrInt32(globalObject);
260 RETURN_IF_EXCEPTION(scope, encodedJSValue());
261
262 if (WTF::holds_alternative<JSBigInt*>(leftNumeric) || WTF::holds_alternative<JSBigInt*>(rightNumeric)) {
263 if (WTF::holds_alternative<JSBigInt*>(leftNumeric) && WTF::holds_alternative<JSBigInt*>(rightNumeric))
264 RELEASE_AND_RETURN(scope, JSValue::encode(bigIntOp(globalObject, WTF::get<JSBigInt*>(leftNumeric), WTF::get<JSBigInt*>(rightNumeric))));
265
266 return throwVMTypeError(globalObject, scope, errorMessage);
267 }
268
269 scope.release();
270
271 return JSValue::encode(jsNumber(int32Op(WTF::get<int32_t>(leftNumeric), WTF::get<int32_t>(rightNumeric))));
272}
273
274static ALWAYS_INLINE EncodedJSValue parseIntResult(double input)
275{
276 int asInt = static_cast<int>(input);
277 if (static_cast<double>(asInt) == input)
278 return JSValue::encode(jsNumber(asInt));
279 return JSValue::encode(jsNumber(input));
280}
281
282ALWAYS_INLINE static JSValue getByValObject(JSGlobalObject* globalObject, VM& vm, JSObject* base, PropertyName propertyName)
283{
284 Structure& structure = *base->structure(vm);
285 if (JSCell::canUseFastGetOwnProperty(structure)) {
286 if (JSValue result = base->fastGetOwnProperty(vm, structure, propertyName))
287 return result;
288 }
289 return base->get(globalObject, propertyName);
290}
291
292extern "C" {
293
294EncodedJSValue JIT_OPERATION operationToThis(JSGlobalObject* globalObject, EncodedJSValue encodedOp)
295{
296 VM& vm = globalObject->vm();
297 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
298 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
299
300 return JSValue::encode(JSValue::decode(encodedOp).toThis(globalObject, NotStrictMode));
301}
302
303EncodedJSValue JIT_OPERATION operationToThisStrict(JSGlobalObject* globalObject, EncodedJSValue encodedOp)
304{
305 VM& vm = globalObject->vm();
306 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
307 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
308
309 return JSValue::encode(JSValue::decode(encodedOp).toThis(globalObject, StrictMode));
310}
311
312JSArray* JIT_OPERATION operationObjectKeys(JSGlobalObject* globalObject, EncodedJSValue encodedObject)
313{
314 VM& vm = globalObject->vm();
315 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
316 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
317 auto scope = DECLARE_THROW_SCOPE(vm);
318
319 JSObject* object = JSValue::decode(encodedObject).toObject(globalObject);
320 RETURN_IF_EXCEPTION(scope, nullptr);
321 scope.release();
322 return ownPropertyKeys(globalObject, object, PropertyNameMode::Strings, DontEnumPropertiesMode::Exclude);
323}
324
325JSArray* JIT_OPERATION operationObjectKeysObject(JSGlobalObject* globalObject, JSObject* object)
326{
327 VM& vm = globalObject->vm();
328 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
329 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
330 return ownPropertyKeys(globalObject, object, PropertyNameMode::Strings, DontEnumPropertiesMode::Exclude);
331}
332
333JSCell* JIT_OPERATION operationObjectCreate(JSGlobalObject* globalObject, EncodedJSValue encodedPrototype)
334{
335 VM& vm = globalObject->vm();
336 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
337 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
338 auto scope = DECLARE_THROW_SCOPE(vm);
339
340 JSValue prototype = JSValue::decode(encodedPrototype);
341
342 if (!prototype.isObject() && !prototype.isNull()) {
343 throwVMTypeError(globalObject, scope, "Object prototype may only be an Object or null."_s);
344 return nullptr;
345 }
346
347 if (prototype.isObject())
348 RELEASE_AND_RETURN(scope, constructEmptyObject(globalObject, asObject(prototype)));
349 RELEASE_AND_RETURN(scope, constructEmptyObject(vm, globalObject->nullPrototypeObjectStructure()));
350}
351
352JSCell* JIT_OPERATION operationObjectCreateObject(JSGlobalObject* globalObject, JSObject* prototype)
353{
354 VM& vm = globalObject->vm();
355 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
356 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
357 return constructEmptyObject(globalObject, prototype);
358}
359
360JSCell* JIT_OPERATION operationCreateThis(JSGlobalObject* globalObject, JSObject* constructor, uint32_t inlineCapacity)
361{
362 VM& vm = globalObject->vm();
363 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
364 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
365 auto scope = DECLARE_THROW_SCOPE(vm);
366 if (constructor->type() == JSFunctionType && jsCast<JSFunction*>(constructor)->canUseAllocationProfile()) {
367 auto rareData = jsCast<JSFunction*>(constructor)->ensureRareDataAndAllocationProfile(globalObject, inlineCapacity);
368 scope.releaseAssertNoException();
369 ObjectAllocationProfileWithPrototype* allocationProfile = rareData->objectAllocationProfile();
370 Structure* structure = allocationProfile->structure();
371 JSObject* result = constructEmptyObject(vm, structure);
372 if (structure->hasPolyProto()) {
373 JSObject* prototype = allocationProfile->prototype();
374 ASSERT(prototype == jsCast<JSFunction*>(constructor)->prototypeForConstruction(vm, globalObject));
375 result->putDirect(vm, knownPolyProtoOffset, prototype);
376 prototype->didBecomePrototype();
377 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");
378 }
379 return result;
380 }
381
382 JSValue proto = constructor->get(globalObject, vm.propertyNames->prototype);
383 RETURN_IF_EXCEPTION(scope, nullptr);
384 if (proto.isObject())
385 return constructEmptyObject(globalObject, asObject(proto));
386 return constructEmptyObject(globalObject);
387}
388
389JSCell* JIT_OPERATION operationCreatePromise(JSGlobalObject* globalObject, JSObject* constructor)
390{
391 VM& vm = globalObject->vm();
392 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
393 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
394 auto scope = DECLARE_THROW_SCOPE(vm);
395 Structure* structure = InternalFunction::createSubclassStructure(globalObject, globalObject->promiseConstructor(), constructor, globalObject->promiseStructure());
396 RETURN_IF_EXCEPTION(scope, nullptr);
397 RELEASE_AND_RETURN(scope, JSPromise::create(vm, structure));
398}
399
400JSCell* JIT_OPERATION operationCreateInternalPromise(JSGlobalObject* globalObject, JSObject* constructor)
401{
402 VM& vm = globalObject->vm();
403 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
404 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
405 auto scope = DECLARE_THROW_SCOPE(vm);
406 Structure* structure = InternalFunction::createSubclassStructure(globalObject, globalObject->internalPromiseConstructor(), constructor, globalObject->internalPromiseStructure());
407 RETURN_IF_EXCEPTION(scope, nullptr);
408 RELEASE_AND_RETURN(scope, JSInternalPromise::create(vm, structure));
409}
410
411JSCell* JIT_OPERATION operationCreateGenerator(JSGlobalObject* globalObject, JSObject* constructor)
412{
413 VM& vm = globalObject->vm();
414 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
415 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
416 auto scope = DECLARE_THROW_SCOPE(vm);
417 Structure* structure = InternalFunction::createSubclassStructure(globalObject, nullptr, constructor, globalObject->generatorStructure());
418 RETURN_IF_EXCEPTION(scope, nullptr);
419 RELEASE_AND_RETURN(scope, JSGenerator::create(vm, structure));
420}
421
422JSCell* JIT_OPERATION operationCreateAsyncGenerator(JSGlobalObject* globalObject, JSObject* constructor)
423{
424 VM& vm = globalObject->vm();
425 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
426 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
427 auto scope = DECLARE_THROW_SCOPE(vm);
428 Structure* structure = InternalFunction::createSubclassStructure(globalObject, nullptr, constructor, globalObject->asyncGeneratorStructure());
429 RETURN_IF_EXCEPTION(scope, nullptr);
430 RELEASE_AND_RETURN(scope, JSAsyncGenerator::create(vm, structure));
431}
432
433JSCell* JIT_OPERATION operationCallObjectConstructor(JSGlobalObject* globalObject, EncodedJSValue encodedTarget)
434{
435 VM& vm = globalObject->vm();
436 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
437 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
438
439 JSValue value = JSValue::decode(encodedTarget);
440 ASSERT(!value.isObject());
441
442 if (value.isUndefinedOrNull())
443 return constructEmptyObject(globalObject, globalObject->objectPrototype());
444 return value.toObject(globalObject);
445}
446
447JSCell* JIT_OPERATION operationToObject(JSGlobalObject* globalObject, EncodedJSValue encodedTarget, UniquedStringImpl* errorMessage)
448{
449 VM& vm = globalObject->vm();
450 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
451 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
452 auto scope = DECLARE_THROW_SCOPE(vm);
453
454 JSValue value = JSValue::decode(encodedTarget);
455 ASSERT(!value.isObject());
456
457 if (UNLIKELY(value.isUndefinedOrNull())) {
458 if (errorMessage->length()) {
459 throwVMTypeError(globalObject, scope, errorMessage);
460 return nullptr;
461 }
462 }
463
464 RELEASE_AND_RETURN(scope, value.toObject(globalObject));
465}
466
467EncodedJSValue JIT_OPERATION operationValueMod(JSGlobalObject* globalObject, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
468{
469 VM& vm = globalObject->vm();
470 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
471 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
472
473 auto bigIntOp = [] (JSGlobalObject* globalObject, JSBigInt* left, JSBigInt* right) -> JSBigInt* {
474 return JSBigInt::remainder(globalObject, left, right);
475 };
476
477 auto numberOp = [] (double left, double right) -> double {
478 return jsMod(left, right);
479 };
480
481 return binaryOp(globalObject, vm, encodedOp1, encodedOp2, bigIntOp, numberOp, "Invalid mix of BigInt and other type in remainder operation.");
482}
483
484EncodedJSValue JIT_OPERATION operationInc(JSGlobalObject* globalObject, EncodedJSValue encodedOp1)
485{
486 VM& vm = globalObject->vm();
487 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
488 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
489 auto scope = DECLARE_THROW_SCOPE(vm);
490
491 JSValue op1 = JSValue::decode(encodedOp1);
492
493 auto operandNumeric = op1.toNumeric(globalObject);
494 RETURN_IF_EXCEPTION(scope, encodedJSValue());
495
496 if (WTF::holds_alternative<JSBigInt*>(operandNumeric))
497 RELEASE_AND_RETURN(scope, JSValue::encode(JSBigInt::inc(globalObject, WTF::get<JSBigInt*>(operandNumeric))));
498
499 double value = WTF::get<double>(operandNumeric);
500 return JSValue::encode(jsNumber(value + 1));
501}
502
503EncodedJSValue JIT_OPERATION operationDec(JSGlobalObject* globalObject, EncodedJSValue encodedOp1)
504{
505 VM& vm = globalObject->vm();
506 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
507 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
508 auto scope = DECLARE_THROW_SCOPE(vm);
509
510 JSValue op1 = JSValue::decode(encodedOp1);
511
512 auto operandNumeric = op1.toNumeric(globalObject);
513 RETURN_IF_EXCEPTION(scope, encodedJSValue());
514
515 if (WTF::holds_alternative<JSBigInt*>(operandNumeric))
516 RELEASE_AND_RETURN(scope, JSValue::encode(JSBigInt::dec(globalObject, WTF::get<JSBigInt*>(operandNumeric))));
517
518 double value = WTF::get<double>(operandNumeric);
519 return JSValue::encode(jsNumber(value - 1));
520}
521
522EncodedJSValue JIT_OPERATION operationValueBitNot(JSGlobalObject* globalObject, EncodedJSValue encodedOp1)
523{
524 VM& vm = globalObject->vm();
525 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
526 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
527 auto scope = DECLARE_THROW_SCOPE(vm);
528
529 JSValue op1 = JSValue::decode(encodedOp1);
530
531 auto operandNumeric = op1.toBigIntOrInt32(globalObject);
532 RETURN_IF_EXCEPTION(scope, encodedJSValue());
533
534 if (WTF::holds_alternative<JSBigInt*>(operandNumeric))
535 RELEASE_AND_RETURN(scope, JSValue::encode(JSBigInt::bitwiseNot(globalObject, WTF::get<JSBigInt*>(operandNumeric))));
536
537 return JSValue::encode(jsNumber(~WTF::get<int32_t>(operandNumeric)));
538}
539
540EncodedJSValue JIT_OPERATION operationValueBitAnd(JSGlobalObject* globalObject, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
541{
542 VM& vm = globalObject->vm();
543 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
544 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
545
546 auto bigIntOp = [] (JSGlobalObject* globalObject, JSBigInt* left, JSBigInt* right) -> JSBigInt* {
547 return JSBigInt::bitwiseAnd(globalObject, left, right);
548 };
549
550 auto int32Op = [] (int32_t left, int32_t right) -> int32_t {
551 return left & right;
552 };
553
554 return bitwiseBinaryOp(globalObject, vm, encodedOp1, encodedOp2, bigIntOp, int32Op, "Invalid mix of BigInt and other type in bitwise 'and' operation."_s);
555}
556
557EncodedJSValue JIT_OPERATION operationValueBitOr(JSGlobalObject* globalObject, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
558{
559 VM& vm = globalObject->vm();
560 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
561 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
562
563 auto bigIntOp = [] (JSGlobalObject* globalObject, JSBigInt* left, JSBigInt* right) -> JSBigInt* {
564 return JSBigInt::bitwiseOr(globalObject, left, right);
565 };
566
567 auto int32Op = [] (int32_t left, int32_t right) -> int32_t {
568 return left | right;
569 };
570
571 return bitwiseBinaryOp(globalObject, vm, encodedOp1, encodedOp2, bigIntOp, int32Op, "Invalid mix of BigInt and other type in bitwise 'or' operation."_s);
572}
573
574EncodedJSValue JIT_OPERATION operationValueBitXor(JSGlobalObject* globalObject, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
575{
576 VM& vm = globalObject->vm();
577 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
578 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
579
580 auto bigIntOp = [] (JSGlobalObject* globalObject, JSBigInt* left, JSBigInt* right) -> JSBigInt* {
581 return JSBigInt::bitwiseXor(globalObject, left, right);
582 };
583
584 auto int32Op = [] (int32_t left, int32_t right) -> int32_t {
585 return left ^ right;
586 };
587
588 return bitwiseBinaryOp(globalObject, vm, encodedOp1, encodedOp2, bigIntOp, int32Op, "Invalid mix of BigInt and other type in bitwise 'xor' operation."_s);
589}
590
591EncodedJSValue JIT_OPERATION operationValueBitLShift(JSGlobalObject* globalObject, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
592{
593 VM& vm = globalObject->vm();
594 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
595 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
596
597 auto bigIntOp = [] (JSGlobalObject* globalObject, JSBigInt* left, JSBigInt* right) -> JSBigInt* {
598 return JSBigInt::leftShift(globalObject, left, right);
599 };
600
601 auto int32Op = [] (int32_t left, int32_t right) -> int32_t {
602 return left << (right & 0x1f);
603 };
604
605 return bitwiseBinaryOp(globalObject, vm, encodedOp1, encodedOp2, bigIntOp, int32Op, "Invalid mix of BigInt and other type in left shift operation."_s);
606}
607
608EncodedJSValue JIT_OPERATION operationValueBitRShift(JSGlobalObject* globalObject, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
609{
610 VM& vm = globalObject->vm();
611 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
612 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
613
614 auto bigIntOp = [] (JSGlobalObject* globalObject, JSBigInt* left, JSBigInt* right) -> JSBigInt* {
615 return JSBigInt::signedRightShift(globalObject, left, right);
616 };
617
618 auto int32Op = [] (int32_t left, int32_t right) -> int32_t {
619 return left >> (right & 0x1f);
620 };
621
622 return bitwiseBinaryOp(globalObject, vm, encodedOp1, encodedOp2, bigIntOp, int32Op, "Invalid mix of BigInt and other type in signed right shift operation."_s);
623}
624
625EncodedJSValue JIT_OPERATION operationValueBitURShift(JSGlobalObject* globalObject, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
626{
627 VM& vm = globalObject->vm();
628 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
629 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
630 auto scope = DECLARE_THROW_SCOPE(vm);
631
632 JSValue op1 = JSValue::decode(encodedOp1);
633 JSValue op2 = JSValue::decode(encodedOp2);
634
635 uint32_t a = op1.toUInt32(globalObject);
636 RETURN_IF_EXCEPTION(scope, encodedJSValue());
637 scope.release();
638 uint32_t b = op2.toUInt32(globalObject);
639 return JSValue::encode(jsNumber(static_cast<int32_t>(a >> (b & 0x1f))));
640}
641
642EncodedJSValue JIT_OPERATION operationValueAddNotNumber(JSGlobalObject* globalObject, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
643{
644 VM& vm = globalObject->vm();
645 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
646 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
647
648 JSValue op1 = JSValue::decode(encodedOp1);
649 JSValue op2 = JSValue::decode(encodedOp2);
650
651 return JSValue::encode(jsAddNonNumber(globalObject, op1, op2));
652}
653
654EncodedJSValue JIT_OPERATION operationValueDiv(JSGlobalObject* globalObject, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
655{
656 VM& vm = globalObject->vm();
657 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
658 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
659
660 auto bigIntOp = [] (JSGlobalObject* globalObject, JSBigInt* left, JSBigInt* right) -> JSBigInt* {
661 return JSBigInt::divide(globalObject, left, right);
662 };
663
664 auto numberOp = [] (double left, double right) -> double {
665 return left / right;
666 };
667
668 return binaryOp(globalObject, vm, encodedOp1, encodedOp2, bigIntOp, numberOp, "Invalid mix of BigInt and other type in division operation.");
669}
670
671EncodedJSValue JIT_OPERATION operationValuePow(JSGlobalObject* globalObject, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
672{
673 VM& vm = globalObject->vm();
674 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
675 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
676
677 auto bigIntOp = [] (JSGlobalObject* globalObject, JSBigInt* left, JSBigInt* right) -> JSBigInt* {
678 return JSBigInt::exponentiate(globalObject, left, right);
679 };
680
681 auto numberOp = [] (double left, double right) -> double {
682 return operationMathPow(left, right);
683 };
684
685 return binaryOp(globalObject, vm, encodedOp1, encodedOp2, bigIntOp, numberOp, "Invalid mix of BigInt and other type in exponentiation operation."_s);
686}
687
688double JIT_OPERATION operationArithAbs(JSGlobalObject* globalObject, EncodedJSValue encodedOp1)
689{
690 VM& vm = globalObject->vm();
691 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
692 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
693 auto scope = DECLARE_THROW_SCOPE(vm);
694
695 JSValue op1 = JSValue::decode(encodedOp1);
696 double a = op1.toNumber(globalObject);
697 RETURN_IF_EXCEPTION(scope, PNaN);
698 return fabs(a);
699}
700
701uint32_t JIT_OPERATION operationArithClz32(JSGlobalObject* globalObject, EncodedJSValue encodedOp1)
702{
703 VM& vm = globalObject->vm();
704 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
705 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
706 auto scope = DECLARE_THROW_SCOPE(vm);
707
708 JSValue op1 = JSValue::decode(encodedOp1);
709 uint32_t value = op1.toUInt32(globalObject);
710 RETURN_IF_EXCEPTION(scope, 0);
711 return clz(value);
712}
713
714double JIT_OPERATION operationArithFRound(JSGlobalObject* globalObject, EncodedJSValue encodedOp1)
715{
716 VM& vm = globalObject->vm();
717 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
718 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
719 auto scope = DECLARE_THROW_SCOPE(vm);
720
721 JSValue op1 = JSValue::decode(encodedOp1);
722 double a = op1.toNumber(globalObject);
723 RETURN_IF_EXCEPTION(scope, PNaN);
724 return static_cast<float>(a);
725}
726
727#define DFG_ARITH_UNARY(capitalizedName, lowerName) \
728double JIT_OPERATION operationArith##capitalizedName(JSGlobalObject* globalObject, EncodedJSValue encodedOp1) \
729{ \
730 VM& vm = globalObject->vm(); \
731 CallFrame* callFrame = DECLARE_CALL_FRAME(vm); \
732 JITOperationPrologueCallFrameTracer tracer(vm, callFrame); \
733 auto scope = DECLARE_THROW_SCOPE(vm); \
734 JSValue op1 = JSValue::decode(encodedOp1); \
735 double result = op1.toNumber(globalObject); \
736 RETURN_IF_EXCEPTION(scope, PNaN); \
737 return JSC::Math::lowerName(result); \
738}
739 FOR_EACH_DFG_ARITH_UNARY_OP(DFG_ARITH_UNARY)
740#undef DFG_ARITH_UNARY
741
742double JIT_OPERATION operationArithSqrt(JSGlobalObject* globalObject, EncodedJSValue encodedOp1)
743{
744 VM& vm = globalObject->vm();
745 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
746 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
747 auto scope = DECLARE_THROW_SCOPE(vm);
748
749 JSValue op1 = JSValue::decode(encodedOp1);
750 double a = op1.toNumber(globalObject);
751 RETURN_IF_EXCEPTION(scope, PNaN);
752 return sqrt(a);
753}
754
755EncodedJSValue JIT_OPERATION operationArithRound(JSGlobalObject* globalObject, EncodedJSValue encodedArgument)
756{
757 VM& vm = globalObject->vm();
758 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
759 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
760 auto scope = DECLARE_THROW_SCOPE(vm);
761
762 JSValue argument = JSValue::decode(encodedArgument);
763 double valueOfArgument = argument.toNumber(globalObject);
764 RETURN_IF_EXCEPTION(scope, encodedJSValue());
765 return JSValue::encode(jsNumber(jsRound(valueOfArgument)));
766}
767
768EncodedJSValue JIT_OPERATION operationArithFloor(JSGlobalObject* globalObject, EncodedJSValue encodedArgument)
769{
770 VM& vm = globalObject->vm();
771 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
772 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
773 auto scope = DECLARE_THROW_SCOPE(vm);
774
775 JSValue argument = JSValue::decode(encodedArgument);
776 double valueOfArgument = argument.toNumber(globalObject);
777 RETURN_IF_EXCEPTION(scope, encodedJSValue());
778 return JSValue::encode(jsNumber(floor(valueOfArgument)));
779}
780
781EncodedJSValue JIT_OPERATION operationArithCeil(JSGlobalObject* globalObject, EncodedJSValue encodedArgument)
782{
783 VM& vm = globalObject->vm();
784 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
785 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
786 auto scope = DECLARE_THROW_SCOPE(vm);
787
788 JSValue argument = JSValue::decode(encodedArgument);
789 double valueOfArgument = argument.toNumber(globalObject);
790 RETURN_IF_EXCEPTION(scope, encodedJSValue());
791 return JSValue::encode(jsNumber(ceil(valueOfArgument)));
792}
793
794EncodedJSValue JIT_OPERATION operationArithTrunc(JSGlobalObject* globalObject, EncodedJSValue encodedArgument)
795{
796 VM& vm = globalObject->vm();
797 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
798 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
799 auto scope = DECLARE_THROW_SCOPE(vm);
800
801 JSValue argument = JSValue::decode(encodedArgument);
802 double truncatedValueOfArgument = argument.toIntegerPreserveNaN(globalObject);
803 RETURN_IF_EXCEPTION(scope, encodedJSValue());
804 return JSValue::encode(jsNumber(truncatedValueOfArgument));
805}
806
807static ALWAYS_INLINE EncodedJSValue getByVal(JSGlobalObject* globalObject, JSCell* base, uint32_t index)
808{
809 if (base->isObject()) {
810 JSObject* object = asObject(base);
811 if (object->canGetIndexQuickly(index))
812 return JSValue::encode(object->getIndexQuickly(index));
813 }
814
815 if (isJSString(base) && asString(base)->canGetIndex(index))
816 return JSValue::encode(asString(base)->getIndex(globalObject, index));
817
818 return JSValue::encode(JSValue(base).get(globalObject, index));
819}
820
821EncodedJSValue JIT_OPERATION operationGetByVal(JSGlobalObject* globalObject, EncodedJSValue encodedBase, EncodedJSValue encodedProperty)
822{
823 VM& vm = globalObject->vm();
824 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
825 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
826 auto scope = DECLARE_THROW_SCOPE(vm);
827
828 JSValue baseValue = JSValue::decode(encodedBase);
829 JSValue property = JSValue::decode(encodedProperty);
830
831 if (LIKELY(baseValue.isCell())) {
832 JSCell* base = baseValue.asCell();
833
834 if (property.isUInt32())
835 RELEASE_AND_RETURN(scope, getByVal(globalObject, base, property.asUInt32()));
836
837 if (property.isDouble()) {
838 double propertyAsDouble = property.asDouble();
839 uint32_t propertyAsUInt32 = static_cast<uint32_t>(propertyAsDouble);
840 if (propertyAsUInt32 == propertyAsDouble && isIndex(propertyAsUInt32))
841 RELEASE_AND_RETURN(scope, getByVal(globalObject, base, propertyAsUInt32));
842
843 } else if (property.isString()) {
844 Structure& structure = *base->structure(vm);
845 if (JSCell::canUseFastGetOwnProperty(structure)) {
846 RefPtr<AtomStringImpl> existingAtomString = asString(property)->toExistingAtomString(globalObject);
847 RETURN_IF_EXCEPTION(scope, encodedJSValue());
848 if (existingAtomString) {
849 if (JSValue result = base->fastGetOwnProperty(vm, structure, existingAtomString.get()))
850 return JSValue::encode(result);
851 }
852 }
853 }
854 }
855
856 baseValue.requireObjectCoercible(globalObject);
857 RETURN_IF_EXCEPTION(scope, encodedJSValue());
858 auto propertyName = property.toPropertyKey(globalObject);
859 RETURN_IF_EXCEPTION(scope, encodedJSValue());
860 RELEASE_AND_RETURN(scope, JSValue::encode(baseValue.get(globalObject, propertyName)));
861}
862
863EncodedJSValue JIT_OPERATION operationGetByValCell(JSGlobalObject* globalObject, JSCell* base, EncodedJSValue encodedProperty)
864{
865 VM& vm = globalObject->vm();
866 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
867 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
868 auto scope = DECLARE_THROW_SCOPE(vm);
869
870 JSValue property = JSValue::decode(encodedProperty);
871
872 if (property.isUInt32())
873 RELEASE_AND_RETURN(scope, getByVal(globalObject, base, property.asUInt32()));
874
875 if (property.isDouble()) {
876 double propertyAsDouble = property.asDouble();
877 uint32_t propertyAsUInt32 = static_cast<uint32_t>(propertyAsDouble);
878 if (propertyAsUInt32 == propertyAsDouble)
879 RELEASE_AND_RETURN(scope, getByVal(globalObject, base, propertyAsUInt32));
880
881 } else if (property.isString()) {
882 Structure& structure = *base->structure(vm);
883 if (JSCell::canUseFastGetOwnProperty(structure)) {
884 RefPtr<AtomStringImpl> existingAtomString = asString(property)->toExistingAtomString(globalObject);
885 RETURN_IF_EXCEPTION(scope, encodedJSValue());
886 if (existingAtomString) {
887 if (JSValue result = base->fastGetOwnProperty(vm, structure, existingAtomString.get()))
888 return JSValue::encode(result);
889 }
890 }
891 }
892
893 auto propertyName = property.toPropertyKey(globalObject);
894 RETURN_IF_EXCEPTION(scope, encodedJSValue());
895 RELEASE_AND_RETURN(scope, JSValue::encode(JSValue(base).get(globalObject, propertyName)));
896}
897
898ALWAYS_INLINE EncodedJSValue getByValCellInt(JSGlobalObject* globalObject, VM& vm, JSCell* base, int32_t index)
899{
900 if (index < 0) {
901 // Go the slowest way possible because negative indices don't use indexed storage.
902 return JSValue::encode(JSValue(base).get(globalObject, Identifier::from(vm, index)));
903 }
904
905 // Use this since we know that the value is out of bounds.
906 return JSValue::encode(JSValue(base).get(globalObject, static_cast<unsigned>(index)));
907}
908
909EncodedJSValue JIT_OPERATION operationGetByValObjectInt(JSGlobalObject* globalObject, JSObject* base, int32_t index)
910{
911 VM& vm = globalObject->vm();
912 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
913 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
914
915 return getByValCellInt(globalObject, vm, base, index);
916}
917
918EncodedJSValue JIT_OPERATION operationGetByValStringInt(JSGlobalObject* globalObject, JSString* base, int32_t index)
919{
920 VM& vm = globalObject->vm();
921 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
922 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
923
924 return getByValCellInt(globalObject, vm, base, index);
925}
926
927EncodedJSValue JIT_OPERATION operationGetByValObjectString(JSGlobalObject* globalObject, JSCell* base, JSCell* string)
928{
929 VM& vm = globalObject->vm();
930 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
931 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
932
933 auto scope = DECLARE_THROW_SCOPE(vm);
934
935 auto propertyName = asString(string)->toIdentifier(globalObject);
936 RETURN_IF_EXCEPTION(scope, encodedJSValue());
937
938 RELEASE_AND_RETURN(scope, JSValue::encode(getByValObject(globalObject, vm, asObject(base), propertyName)));
939}
940
941EncodedJSValue JIT_OPERATION operationGetByValObjectSymbol(JSGlobalObject* globalObject, JSCell* base, JSCell* symbol)
942{
943 VM& vm = globalObject->vm();
944 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
945 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
946
947 auto propertyName = asSymbol(symbol)->privateName();
948 return JSValue::encode(getByValObject(globalObject, vm, asObject(base), propertyName));
949}
950
951void JIT_OPERATION operationPutByValStrict(JSGlobalObject* globalObject, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
952{
953 VM& vm = globalObject->vm();
954 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
955 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
956
957 putByValInternal<true, false>(globalObject, vm, encodedBase, encodedProperty, encodedValue);
958}
959
960void JIT_OPERATION operationPutByValNonStrict(JSGlobalObject* globalObject, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
961{
962 VM& vm = globalObject->vm();
963 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
964 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
965
966 putByValInternal<false, false>(globalObject, vm, encodedBase, encodedProperty, encodedValue);
967}
968
969void JIT_OPERATION operationPutByValCellStrict(JSGlobalObject* globalObject, JSCell* cell, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
970{
971 VM& vm = globalObject->vm();
972 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
973 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
974
975 putByValInternal<true, false>(globalObject, vm, JSValue::encode(cell), encodedProperty, encodedValue);
976}
977
978void JIT_OPERATION operationPutByValCellNonStrict(JSGlobalObject* globalObject, JSCell* cell, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
979{
980 VM& vm = globalObject->vm();
981 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
982 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
983
984 putByValInternal<false, false>(globalObject, vm, JSValue::encode(cell), encodedProperty, encodedValue);
985}
986
987void JIT_OPERATION operationPutByValCellStringStrict(JSGlobalObject* globalObject, JSCell* cell, JSCell* string, EncodedJSValue encodedValue)
988{
989 VM& vm = globalObject->vm();
990 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
991 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
992
993 putByValCellStringInternal<true, false>(globalObject, vm, cell, asString(string), JSValue::decode(encodedValue));
994}
995
996void JIT_OPERATION operationPutByValCellStringNonStrict(JSGlobalObject* globalObject, JSCell* cell, JSCell* string, EncodedJSValue encodedValue)
997{
998 VM& vm = globalObject->vm();
999 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1000 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1001
1002 putByValCellStringInternal<false, false>(globalObject, vm, cell, asString(string), JSValue::decode(encodedValue));
1003}
1004
1005void JIT_OPERATION operationPutByValCellSymbolStrict(JSGlobalObject* globalObject, JSCell* cell, JSCell* symbol, EncodedJSValue encodedValue)
1006{
1007 VM& vm = globalObject->vm();
1008 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1009 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1010
1011 auto propertyName = asSymbol(symbol)->privateName();
1012 putByValCellInternal<true, false>(globalObject, vm, cell, propertyName, JSValue::decode(encodedValue));
1013}
1014
1015void JIT_OPERATION operationPutByValCellSymbolNonStrict(JSGlobalObject* globalObject, JSCell* cell, JSCell* symbol, EncodedJSValue encodedValue)
1016{
1017 VM& vm = globalObject->vm();
1018 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1019 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1020
1021 auto propertyName = asSymbol(symbol)->privateName();
1022 putByValCellInternal<false, false>(globalObject, vm, cell, propertyName, JSValue::decode(encodedValue));
1023}
1024
1025void JIT_OPERATION operationPutByValBeyondArrayBoundsStrict(JSGlobalObject* globalObject, JSObject* object, int32_t index, EncodedJSValue encodedValue)
1026{
1027 VM& vm = globalObject->vm();
1028 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1029 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1030
1031 if (index >= 0) {
1032 object->putByIndexInline(globalObject, index, JSValue::decode(encodedValue), true);
1033 return;
1034 }
1035
1036 PutPropertySlot slot(object, true);
1037 object->methodTable(vm)->put(
1038 object, globalObject, Identifier::from(vm, index), JSValue::decode(encodedValue), slot);
1039}
1040
1041void JIT_OPERATION operationPutByValBeyondArrayBoundsNonStrict(JSGlobalObject* globalObject, JSObject* object, int32_t index, EncodedJSValue encodedValue)
1042{
1043 VM& vm = globalObject->vm();
1044 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1045 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1046
1047 if (index >= 0) {
1048 object->putByIndexInline(globalObject, index, JSValue::decode(encodedValue), false);
1049 return;
1050 }
1051
1052 PutPropertySlot slot(object, false);
1053 object->methodTable(vm)->put(
1054 object, globalObject, Identifier::from(vm, index), JSValue::decode(encodedValue), slot);
1055}
1056
1057void JIT_OPERATION operationPutDoubleByValBeyondArrayBoundsStrict(JSGlobalObject* globalObject, JSObject* object, int32_t index, double value)
1058{
1059 VM& vm = globalObject->vm();
1060 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1061 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1062
1063 JSValue jsValue = JSValue(JSValue::EncodeAsDouble, value);
1064
1065 if (index >= 0) {
1066 object->putByIndexInline(globalObject, index, jsValue, true);
1067 return;
1068 }
1069
1070 PutPropertySlot slot(object, true);
1071 object->methodTable(vm)->put(
1072 object, globalObject, Identifier::from(vm, index), jsValue, slot);
1073}
1074
1075void JIT_OPERATION operationPutDoubleByValBeyondArrayBoundsNonStrict(JSGlobalObject* globalObject, JSObject* object, int32_t index, double value)
1076{
1077 VM& vm = globalObject->vm();
1078 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1079 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1080
1081 JSValue jsValue = JSValue(JSValue::EncodeAsDouble, value);
1082
1083 if (index >= 0) {
1084 object->putByIndexInline(globalObject, index, jsValue, false);
1085 return;
1086 }
1087
1088 PutPropertySlot slot(object, false);
1089 object->methodTable(vm)->put(
1090 object, globalObject, Identifier::from(vm, index), jsValue, slot);
1091}
1092
1093void JIT_OPERATION operationPutDoubleByValDirectBeyondArrayBoundsStrict(JSGlobalObject* globalObject, JSObject* object, int32_t index, double value)
1094{
1095 VM& vm = globalObject->vm();
1096 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1097 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1098
1099 JSValue jsValue = JSValue(JSValue::EncodeAsDouble, value);
1100
1101 if (index >= 0) {
1102 object->putDirectIndex(globalObject, index, jsValue, 0, PutDirectIndexShouldThrow);
1103 return;
1104 }
1105
1106 PutPropertySlot slot(object, true);
1107 CommonSlowPaths::putDirectWithReify(vm, globalObject, object, Identifier::from(vm, index), jsValue, slot);
1108}
1109
1110void JIT_OPERATION operationPutDoubleByValDirectBeyondArrayBoundsNonStrict(JSGlobalObject* globalObject, JSObject* object, int32_t index, double value)
1111{
1112 VM& vm = globalObject->vm();
1113 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1114 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1115
1116 JSValue jsValue = JSValue(JSValue::EncodeAsDouble, value);
1117
1118 if (index >= 0) {
1119 object->putDirectIndex(globalObject, index, jsValue);
1120 return;
1121 }
1122
1123 PutPropertySlot slot(object, false);
1124 CommonSlowPaths::putDirectWithReify(vm, globalObject, object, Identifier::from(vm, index), jsValue, slot);
1125}
1126
1127void JIT_OPERATION operationPutByValDirectStrict(JSGlobalObject* globalObject, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
1128{
1129 VM& vm = globalObject->vm();
1130 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1131 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1132
1133 putByValInternal<true, true>(globalObject, vm, encodedBase, encodedProperty, encodedValue);
1134}
1135
1136void JIT_OPERATION operationPutByValDirectNonStrict(JSGlobalObject* globalObject, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
1137{
1138 VM& vm = globalObject->vm();
1139 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1140 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1141
1142 putByValInternal<false, true>(globalObject, vm, encodedBase, encodedProperty, encodedValue);
1143}
1144
1145void JIT_OPERATION operationPutByValDirectCellStrict(JSGlobalObject* globalObject, JSCell* cell, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
1146{
1147 VM& vm = globalObject->vm();
1148 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1149 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1150
1151 putByValInternal<true, true>(globalObject, vm, JSValue::encode(cell), encodedProperty, encodedValue);
1152}
1153
1154void JIT_OPERATION operationPutByValDirectCellNonStrict(JSGlobalObject* globalObject, JSCell* cell, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
1155{
1156 VM& vm = globalObject->vm();
1157 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1158 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1159
1160 putByValInternal<false, true>(globalObject, vm, JSValue::encode(cell), encodedProperty, encodedValue);
1161}
1162
1163void JIT_OPERATION operationPutByValDirectCellStringStrict(JSGlobalObject* globalObject, JSCell* cell, JSCell* string, EncodedJSValue encodedValue)
1164{
1165 VM& vm = globalObject->vm();
1166 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1167 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1168
1169 putByValCellStringInternal<true, true>(globalObject, vm, cell, asString(string), JSValue::decode(encodedValue));
1170}
1171
1172void JIT_OPERATION operationPutByValDirectCellStringNonStrict(JSGlobalObject* globalObject, JSCell* cell, JSCell* string, EncodedJSValue encodedValue)
1173{
1174 VM& vm = globalObject->vm();
1175 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1176 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1177
1178 putByValCellStringInternal<false, true>(globalObject, vm, cell, asString(string), JSValue::decode(encodedValue));
1179}
1180
1181void JIT_OPERATION operationPutByValDirectCellSymbolStrict(JSGlobalObject* globalObject, JSCell* cell, JSCell* symbol, EncodedJSValue encodedValue)
1182{
1183 VM& vm = globalObject->vm();
1184 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1185 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1186
1187 auto propertyName = asSymbol(symbol)->privateName();
1188 putByValCellInternal<true, true>(globalObject, vm, cell, propertyName, JSValue::decode(encodedValue));
1189}
1190
1191void JIT_OPERATION operationPutByValDirectCellSymbolNonStrict(JSGlobalObject* globalObject, JSCell* cell, JSCell* symbol, EncodedJSValue encodedValue)
1192{
1193 VM& vm = globalObject->vm();
1194 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1195 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1196
1197 auto propertyName = asSymbol(symbol)->privateName();
1198 putByValCellInternal<false, true>(globalObject, vm, cell, propertyName, JSValue::decode(encodedValue));
1199}
1200
1201void JIT_OPERATION operationPutByValDirectBeyondArrayBoundsStrict(JSGlobalObject* globalObject, JSObject* object, int32_t index, EncodedJSValue encodedValue)
1202{
1203 VM& vm = globalObject->vm();
1204 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1205 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1206 if (index >= 0) {
1207 object->putDirectIndex(globalObject, index, JSValue::decode(encodedValue), 0, PutDirectIndexShouldThrow);
1208 return;
1209 }
1210
1211 PutPropertySlot slot(object, true);
1212 CommonSlowPaths::putDirectWithReify(vm, globalObject, object, Identifier::from(vm, index), JSValue::decode(encodedValue), slot);
1213}
1214
1215void JIT_OPERATION operationPutByValDirectBeyondArrayBoundsNonStrict(JSGlobalObject* globalObject, JSObject* object, int32_t index, EncodedJSValue encodedValue)
1216{
1217 VM& vm = globalObject->vm();
1218 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1219 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1220
1221 if (index >= 0) {
1222 object->putDirectIndex(globalObject, index, JSValue::decode(encodedValue));
1223 return;
1224 }
1225
1226 PutPropertySlot slot(object, false);
1227 CommonSlowPaths::putDirectWithReify(vm, globalObject, object, Identifier::from(vm, index), JSValue::decode(encodedValue), slot);
1228}
1229
1230EncodedJSValue JIT_OPERATION operationArrayPush(JSGlobalObject* globalObject, EncodedJSValue encodedValue, JSArray* array)
1231{
1232 VM& vm = globalObject->vm();
1233 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1234 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1235
1236 array->pushInline(globalObject, JSValue::decode(encodedValue));
1237 return JSValue::encode(jsNumber(array->length()));
1238}
1239
1240EncodedJSValue JIT_OPERATION operationArrayPushDouble(JSGlobalObject* globalObject, double value, JSArray* array)
1241{
1242 VM& vm = globalObject->vm();
1243 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1244 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1245
1246 array->pushInline(globalObject, JSValue(JSValue::EncodeAsDouble, value));
1247 return JSValue::encode(jsNumber(array->length()));
1248}
1249
1250EncodedJSValue JIT_OPERATION operationArrayPushMultiple(JSGlobalObject* globalObject, JSArray* array, void* buffer, int32_t elementCount)
1251{
1252 VM& vm = globalObject->vm();
1253 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1254 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1255 auto scope = DECLARE_THROW_SCOPE(vm);
1256
1257 // We assume that multiple JSArray::push calls with ArrayWithInt32/ArrayWithContiguous do not cause JS traps.
1258 // If it can cause any JS interactions, we can call the caller JS function of this function and overwrite the
1259 // content of ScratchBuffer. If the IndexingType is now ArrayWithInt32/ArrayWithContiguous, we can ensure
1260 // that there is no indexed accessors in this object and its prototype chain.
1261 //
1262 // ArrayWithArrayStorage is also OK. It can have indexed accessors. But if you define an indexed accessor, the array's length
1263 // becomes larger than that index. So Array#push never overlaps with this accessor. So accessors are never called unless
1264 // the IndexingType is ArrayWithSlowPutArrayStorage which could have an indexed accessor in a prototype chain.
1265 RELEASE_ASSERT(!shouldUseSlowPut(array->indexingType()));
1266
1267 EncodedJSValue* values = static_cast<EncodedJSValue*>(buffer);
1268 for (int32_t i = 0; i < elementCount; ++i) {
1269 array->pushInline(globalObject, JSValue::decode(values[i]));
1270 RETURN_IF_EXCEPTION(scope, encodedJSValue());
1271 }
1272 return JSValue::encode(jsNumber(array->length()));
1273}
1274
1275EncodedJSValue JIT_OPERATION operationArrayPushDoubleMultiple(JSGlobalObject* globalObject, JSArray* array, void* buffer, int32_t elementCount)
1276{
1277 VM& vm = globalObject->vm();
1278 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1279 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1280 auto scope = DECLARE_THROW_SCOPE(vm);
1281
1282 // We assume that multiple JSArray::push calls with ArrayWithDouble do not cause JS traps.
1283 // If it can cause any JS interactions, we can call the caller JS function of this function and overwrite the
1284 // content of ScratchBuffer. If the IndexingType is now ArrayWithDouble, we can ensure
1285 // that there is no indexed accessors in this object and its prototype chain.
1286 ASSERT(array->indexingMode() == ArrayWithDouble);
1287
1288 double* values = static_cast<double*>(buffer);
1289 for (int32_t i = 0; i < elementCount; ++i) {
1290 array->pushInline(globalObject, JSValue(JSValue::EncodeAsDouble, values[i]));
1291 RETURN_IF_EXCEPTION(scope, encodedJSValue());
1292 }
1293 return JSValue::encode(jsNumber(array->length()));
1294}
1295
1296EncodedJSValue JIT_OPERATION operationArrayPop(JSGlobalObject* globalObject, JSArray* array)
1297{
1298 VM& vm = globalObject->vm();
1299 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1300 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1301
1302 return JSValue::encode(array->pop(globalObject));
1303}
1304
1305EncodedJSValue JIT_OPERATION operationArrayPopAndRecoverLength(JSGlobalObject* globalObject, JSArray* array)
1306{
1307 VM& vm = globalObject->vm();
1308 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1309 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1310
1311 array->butterfly()->setPublicLength(array->butterfly()->publicLength() + 1);
1312
1313 return JSValue::encode(array->pop(globalObject));
1314}
1315
1316EncodedJSValue JIT_OPERATION operationRegExpExecString(JSGlobalObject* globalObject, RegExpObject* regExpObject, JSString* argument)
1317{
1318 SuperSamplerScope superSamplerScope(false);
1319
1320 VM& vm = globalObject->vm();
1321 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1322 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1323
1324 return JSValue::encode(regExpObject->execInline(globalObject, argument));
1325}
1326
1327EncodedJSValue JIT_OPERATION operationRegExpExec(JSGlobalObject* globalObject, RegExpObject* regExpObject, EncodedJSValue encodedArgument)
1328{
1329 SuperSamplerScope superSamplerScope(false);
1330
1331 VM& vm = globalObject->vm();
1332 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1333 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1334 auto scope = DECLARE_THROW_SCOPE(vm);
1335
1336 JSValue argument = JSValue::decode(encodedArgument);
1337
1338 JSString* input = argument.toStringOrNull(globalObject);
1339 EXCEPTION_ASSERT(!!scope.exception() == !input);
1340 if (!input)
1341 return encodedJSValue();
1342 RELEASE_AND_RETURN(scope, JSValue::encode(regExpObject->execInline(globalObject, input)));
1343}
1344
1345EncodedJSValue JIT_OPERATION operationRegExpExecGeneric(JSGlobalObject* globalObject, EncodedJSValue encodedBase, EncodedJSValue encodedArgument)
1346{
1347 SuperSamplerScope superSamplerScope(false);
1348
1349 VM& vm = globalObject->vm();
1350 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1351 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1352 auto scope = DECLARE_THROW_SCOPE(vm);
1353
1354 JSValue base = JSValue::decode(encodedBase);
1355 JSValue argument = JSValue::decode(encodedArgument);
1356
1357 auto* regexp = jsDynamicCast<RegExpObject*>(vm, base);
1358 if (UNLIKELY(!regexp))
1359 return throwVMTypeError(globalObject, scope);
1360
1361 JSString* input = argument.toStringOrNull(globalObject);
1362 EXCEPTION_ASSERT(!!scope.exception() == !input);
1363 if (!input)
1364 return JSValue::encode(jsUndefined());
1365 RELEASE_AND_RETURN(scope, JSValue::encode(regexp->exec(globalObject, input)));
1366}
1367
1368EncodedJSValue JIT_OPERATION operationRegExpExecNonGlobalOrSticky(JSGlobalObject* globalObject, RegExp* regExp, JSString* string)
1369{
1370 SuperSamplerScope superSamplerScope(false);
1371
1372 VM& vm = globalObject->vm();
1373 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1374 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1375
1376 auto scope = DECLARE_THROW_SCOPE(vm);
1377
1378 String input = string->value(globalObject);
1379 RETURN_IF_EXCEPTION(scope, { });
1380
1381 unsigned lastIndex = 0;
1382 MatchResult result;
1383 JSArray* array = createRegExpMatchesArray(vm, globalObject, string, input, regExp, lastIndex, result);
1384 RETURN_IF_EXCEPTION(scope, { });
1385 if (!array)
1386 return JSValue::encode(jsNull());
1387
1388 globalObject->regExpGlobalData().recordMatch(vm, globalObject, regExp, string, result);
1389 return JSValue::encode(array);
1390}
1391
1392EncodedJSValue JIT_OPERATION operationRegExpMatchFastString(JSGlobalObject* globalObject, RegExpObject* regExpObject, JSString* argument)
1393{
1394 SuperSamplerScope superSamplerScope(false);
1395
1396 VM& vm = globalObject->vm();
1397 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1398 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1399
1400 if (!regExpObject->regExp()->global())
1401 return JSValue::encode(regExpObject->execInline(globalObject, argument));
1402 return JSValue::encode(regExpObject->matchGlobal(globalObject, argument));
1403}
1404
1405EncodedJSValue JIT_OPERATION operationRegExpMatchFastGlobalString(JSGlobalObject* globalObject, RegExp* regExp, JSString* string)
1406{
1407 SuperSamplerScope superSamplerScope(false);
1408
1409 VM& vm = globalObject->vm();
1410 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1411 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1412
1413 auto scope = DECLARE_THROW_SCOPE(vm);
1414
1415 ASSERT(regExp->global());
1416
1417 String s = string->value(globalObject);
1418 RETURN_IF_EXCEPTION(scope, { });
1419
1420 if (regExp->unicode()) {
1421 unsigned stringLength = s.length();
1422 RELEASE_AND_RETURN(scope, JSValue::encode(collectMatches(
1423 vm, globalObject, string, s, regExp,
1424 [&] (size_t end) -> size_t {
1425 return advanceStringUnicode(s, stringLength, end);
1426 })));
1427 }
1428
1429 RELEASE_AND_RETURN(scope, JSValue::encode(collectMatches(
1430 vm, globalObject, string, s, regExp,
1431 [&] (size_t end) -> size_t {
1432 return end + 1;
1433 })));
1434}
1435
1436EncodedJSValue JIT_OPERATION operationParseIntNoRadixGeneric(JSGlobalObject* globalObject, EncodedJSValue value)
1437{
1438 VM& vm = globalObject->vm();
1439 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1440 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1441
1442 return toStringView(globalObject, JSValue::decode(value), [&] (StringView view) {
1443 // This version is as if radix was undefined. Hence, undefined.toNumber() === 0.
1444 return parseIntResult(parseInt(view, 0));
1445 });
1446}
1447
1448EncodedJSValue JIT_OPERATION operationParseIntStringNoRadix(JSGlobalObject* globalObject, JSString* string)
1449{
1450 VM& vm = globalObject->vm();
1451 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1452 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1453 auto scope = DECLARE_THROW_SCOPE(vm);
1454
1455 auto viewWithString = string->viewWithUnderlyingString(globalObject);
1456 RETURN_IF_EXCEPTION(scope, { });
1457
1458 // This version is as if radix was undefined. Hence, undefined.toNumber() === 0.
1459 return parseIntResult(parseInt(viewWithString.view, 0));
1460}
1461
1462EncodedJSValue JIT_OPERATION operationParseIntString(JSGlobalObject* globalObject, JSString* string, int32_t radix)
1463{
1464 VM& vm = globalObject->vm();
1465 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1466 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1467 auto scope = DECLARE_THROW_SCOPE(vm);
1468
1469 auto viewWithString = string->viewWithUnderlyingString(globalObject);
1470 RETURN_IF_EXCEPTION(scope, { });
1471
1472 return parseIntResult(parseInt(viewWithString.view, radix));
1473}
1474
1475EncodedJSValue JIT_OPERATION operationParseIntGeneric(JSGlobalObject* globalObject, EncodedJSValue value, int32_t radix)
1476{
1477 VM& vm = globalObject->vm();
1478 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1479 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1480
1481 return toStringView(globalObject, JSValue::decode(value), [&] (StringView view) {
1482 return parseIntResult(parseInt(view, radix));
1483 });
1484}
1485
1486size_t JIT_OPERATION operationRegExpTestString(JSGlobalObject* globalObject, RegExpObject* regExpObject, JSString* input)
1487{
1488 SuperSamplerScope superSamplerScope(false);
1489
1490 VM& vm = globalObject->vm();
1491 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1492 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1493
1494 return regExpObject->testInline(globalObject, input);
1495}
1496
1497size_t JIT_OPERATION operationRegExpTest(JSGlobalObject* globalObject, RegExpObject* regExpObject, EncodedJSValue encodedArgument)
1498{
1499 SuperSamplerScope superSamplerScope(false);
1500
1501 VM& vm = globalObject->vm();
1502 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1503 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1504
1505 JSValue argument = JSValue::decode(encodedArgument);
1506
1507 JSString* input = argument.toStringOrNull(globalObject);
1508 if (!input)
1509 return false;
1510 return regExpObject->testInline(globalObject, input);
1511}
1512
1513size_t JIT_OPERATION operationRegExpTestGeneric(JSGlobalObject* globalObject, EncodedJSValue encodedBase, EncodedJSValue encodedArgument)
1514{
1515 SuperSamplerScope superSamplerScope(false);
1516
1517 VM& vm = globalObject->vm();
1518 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1519 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1520 auto scope = DECLARE_THROW_SCOPE(vm);
1521
1522 JSValue base = JSValue::decode(encodedBase);
1523 JSValue argument = JSValue::decode(encodedArgument);
1524
1525 auto* regexp = jsDynamicCast<RegExpObject*>(vm, base);
1526 if (UNLIKELY(!regexp)) {
1527 throwTypeError(globalObject, scope);
1528 return false;
1529 }
1530
1531 JSString* input = argument.toStringOrNull(globalObject);
1532 EXCEPTION_ASSERT(!!scope.exception() == !input);
1533 if (!input)
1534 return false;
1535 RELEASE_AND_RETURN(scope, regexp->test(globalObject, input));
1536}
1537
1538JSCell* JIT_OPERATION operationSubBigInt(JSGlobalObject* globalObject, JSCell* op1, JSCell* op2)
1539{
1540 VM& vm = globalObject->vm();
1541 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1542 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1543
1544 JSBigInt* leftOperand = jsCast<JSBigInt*>(op1);
1545 JSBigInt* rightOperand = jsCast<JSBigInt*>(op2);
1546
1547 return JSBigInt::sub(globalObject, leftOperand, rightOperand);
1548}
1549
1550JSCell* JIT_OPERATION operationBitNotBigInt(JSGlobalObject* globalObject, JSCell* op1)
1551{
1552 VM& vm = globalObject->vm();
1553 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1554 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1555
1556 JSBigInt* operand = jsCast<JSBigInt*>(op1);
1557
1558 return JSBigInt::bitwiseNot(globalObject, operand);
1559}
1560
1561JSCell* JIT_OPERATION operationMulBigInt(JSGlobalObject* globalObject, JSCell* op1, JSCell* op2)
1562{
1563 VM& vm = globalObject->vm();
1564 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1565 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1566
1567 JSBigInt* leftOperand = jsCast<JSBigInt*>(op1);
1568 JSBigInt* rightOperand = jsCast<JSBigInt*>(op2);
1569
1570 return JSBigInt::multiply(globalObject, leftOperand, rightOperand);
1571}
1572
1573JSCell* JIT_OPERATION operationModBigInt(JSGlobalObject* globalObject, JSCell* op1, JSCell* op2)
1574{
1575 VM& vm = globalObject->vm();
1576 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1577 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1578
1579 JSBigInt* leftOperand = jsCast<JSBigInt*>(op1);
1580 JSBigInt* rightOperand = jsCast<JSBigInt*>(op2);
1581
1582 return JSBigInt::remainder(globalObject, leftOperand, rightOperand);
1583}
1584
1585JSCell* JIT_OPERATION operationDivBigInt(JSGlobalObject* globalObject, JSCell* op1, JSCell* op2)
1586{
1587 VM& vm = globalObject->vm();
1588 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1589 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1590
1591 JSBigInt* leftOperand = jsCast<JSBigInt*>(op1);
1592 JSBigInt* rightOperand = jsCast<JSBigInt*>(op2);
1593
1594 return JSBigInt::divide(globalObject, leftOperand, rightOperand);
1595}
1596
1597JSCell* JIT_OPERATION operationPowBigInt(JSGlobalObject* globalObject, JSCell* op1, JSCell* op2)
1598{
1599 VM& vm = globalObject->vm();
1600 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1601 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1602
1603 JSBigInt* leftOperand = jsCast<JSBigInt*>(op1);
1604 JSBigInt* rightOperand = jsCast<JSBigInt*>(op2);
1605
1606 return JSBigInt::exponentiate(globalObject, leftOperand, rightOperand);
1607}
1608
1609JSCell* JIT_OPERATION operationBitAndBigInt(JSGlobalObject* globalObject, JSCell* op1, JSCell* op2)
1610{
1611 VM& vm = globalObject->vm();
1612 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1613 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1614
1615 JSBigInt* leftOperand = jsCast<JSBigInt*>(op1);
1616 JSBigInt* rightOperand = jsCast<JSBigInt*>(op2);
1617
1618 return JSBigInt::bitwiseAnd(globalObject, leftOperand, rightOperand);
1619}
1620
1621JSCell* JIT_OPERATION operationBitLShiftBigInt(JSGlobalObject* globalObject, JSCell* op1, JSCell* op2)
1622{
1623 VM& vm = globalObject->vm();
1624 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1625 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1626
1627 JSBigInt* leftOperand = jsCast<JSBigInt*>(op1);
1628 JSBigInt* rightOperand = jsCast<JSBigInt*>(op2);
1629
1630 return JSBigInt::leftShift(globalObject, leftOperand, rightOperand);
1631}
1632
1633JSCell* JIT_OPERATION operationAddBigInt(JSGlobalObject* globalObject, JSCell* op1, JSCell* op2)
1634{
1635 VM& vm = globalObject->vm();
1636 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1637 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1638
1639 JSBigInt* leftOperand = jsCast<JSBigInt*>(op1);
1640 JSBigInt* rightOperand = jsCast<JSBigInt*>(op2);
1641
1642 return JSBigInt::add(globalObject, leftOperand, rightOperand);
1643}
1644
1645JSCell* JIT_OPERATION operationBitRShiftBigInt(JSGlobalObject* globalObject, JSCell* op1, JSCell* op2)
1646{
1647 VM& vm = globalObject->vm();
1648 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1649 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1650
1651 JSBigInt* leftOperand = jsCast<JSBigInt*>(op1);
1652 JSBigInt* rightOperand = jsCast<JSBigInt*>(op2);
1653
1654 return JSBigInt::signedRightShift(globalObject, leftOperand, rightOperand);
1655}
1656
1657JSCell* JIT_OPERATION operationBitOrBigInt(JSGlobalObject* globalObject, JSCell* op1, JSCell* op2)
1658{
1659 VM& vm = globalObject->vm();
1660 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1661 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1662
1663 JSBigInt* leftOperand = jsCast<JSBigInt*>(op1);
1664 JSBigInt* rightOperand = jsCast<JSBigInt*>(op2);
1665
1666 return JSBigInt::bitwiseOr(globalObject, leftOperand, rightOperand);
1667}
1668
1669JSCell* JIT_OPERATION operationBitXorBigInt(JSGlobalObject* globalObject, JSCell* op1, JSCell* op2)
1670{
1671 VM& vm = globalObject->vm();
1672 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1673 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1674
1675 JSBigInt* leftOperand = jsCast<JSBigInt*>(op1);
1676 JSBigInt* rightOperand = jsCast<JSBigInt*>(op2);
1677
1678 return JSBigInt::bitwiseXor(globalObject, leftOperand, rightOperand);
1679}
1680
1681size_t JIT_OPERATION operationCompareStrictEqCell(JSGlobalObject* globalObject, JSCell* op1, JSCell* op2)
1682{
1683 VM& vm = globalObject->vm();
1684 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1685 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1686
1687 return JSValue::strictEqualSlowCaseInline(globalObject, op1, op2);
1688}
1689
1690size_t JIT_OPERATION operationSameValue(JSGlobalObject* globalObject, EncodedJSValue arg1, EncodedJSValue arg2)
1691{
1692 VM& vm = globalObject->vm();
1693 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1694 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1695
1696 return sameValue(globalObject, JSValue::decode(arg1), JSValue::decode(arg2));
1697}
1698
1699EncodedJSValue JIT_OPERATION operationToPrimitive(JSGlobalObject* globalObject, EncodedJSValue value)
1700{
1701 VM& vm = globalObject->vm();
1702 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1703 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1704
1705 return JSValue::encode(JSValue::decode(value).toPrimitive(globalObject));
1706}
1707
1708EncodedJSValue JIT_OPERATION operationToNumber(JSGlobalObject* globalObject, EncodedJSValue value)
1709{
1710 VM& vm = globalObject->vm();
1711 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1712 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1713
1714 return JSValue::encode(jsNumber(JSValue::decode(value).toNumber(globalObject)));
1715}
1716
1717EncodedJSValue JIT_OPERATION operationToNumeric(JSGlobalObject* globalObject, EncodedJSValue value)
1718{
1719 VM& vm = globalObject->vm();
1720 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1721 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1722
1723 auto variant = JSValue::decode(value).toNumeric(globalObject);
1724 if (WTF::holds_alternative<JSBigInt*>(variant))
1725 return JSValue::encode(WTF::get<JSBigInt*>(variant));
1726 return JSValue::encode(jsNumber(WTF::get<double>(variant)));
1727}
1728
1729EncodedJSValue JIT_OPERATION operationGetByValWithThis(JSGlobalObject* globalObject, EncodedJSValue encodedBase, EncodedJSValue encodedThis, EncodedJSValue encodedSubscript)
1730{
1731 VM& vm = globalObject->vm();
1732 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1733 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1734 auto scope = DECLARE_THROW_SCOPE(vm);
1735
1736 JSValue baseValue = JSValue::decode(encodedBase);
1737 JSValue thisVal = JSValue::decode(encodedThis);
1738 JSValue subscript = JSValue::decode(encodedSubscript);
1739
1740 if (LIKELY(baseValue.isCell() && subscript.isString())) {
1741 Structure& structure = *baseValue.asCell()->structure(vm);
1742 if (JSCell::canUseFastGetOwnProperty(structure)) {
1743 RefPtr<AtomStringImpl> existingAtomString = asString(subscript)->toExistingAtomString(globalObject);
1744 RETURN_IF_EXCEPTION(scope, encodedJSValue());
1745 if (existingAtomString) {
1746 if (JSValue result = baseValue.asCell()->fastGetOwnProperty(vm, structure, existingAtomString.get()))
1747 return JSValue::encode(result);
1748 }
1749 }
1750 }
1751
1752 PropertySlot slot(thisVal, PropertySlot::PropertySlot::InternalMethodType::Get);
1753 if (subscript.isUInt32()) {
1754 uint32_t i = subscript.asUInt32();
1755 if (isJSString(baseValue) && asString(baseValue)->canGetIndex(i))
1756 return JSValue::encode(asString(baseValue)->getIndex(globalObject, i));
1757
1758 RELEASE_AND_RETURN(scope, JSValue::encode(baseValue.get(globalObject, i, slot)));
1759 }
1760
1761 baseValue.requireObjectCoercible(globalObject);
1762 RETURN_IF_EXCEPTION(scope, encodedJSValue());
1763
1764 auto property = subscript.toPropertyKey(globalObject);
1765 RETURN_IF_EXCEPTION(scope, encodedJSValue());
1766 RELEASE_AND_RETURN(scope, JSValue::encode(baseValue.get(globalObject, property, slot)));
1767}
1768
1769void JIT_OPERATION operationPutByIdWithThisStrict(JSGlobalObject* globalObject, EncodedJSValue encodedBase, EncodedJSValue encodedThis, EncodedJSValue encodedValue, UniquedStringImpl* impl)
1770{
1771 VM& vm = globalObject->vm();
1772 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1773 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1774
1775 putWithThis<true>(globalObject, encodedBase, encodedThis, encodedValue, Identifier::fromUid(vm, impl));
1776}
1777
1778void JIT_OPERATION operationPutByIdWithThis(JSGlobalObject* globalObject, EncodedJSValue encodedBase, EncodedJSValue encodedThis, EncodedJSValue encodedValue, UniquedStringImpl* impl)
1779{
1780 VM& vm = globalObject->vm();
1781 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1782 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1783
1784 putWithThis<false>(globalObject, encodedBase, encodedThis, encodedValue, Identifier::fromUid(vm, impl));
1785}
1786
1787void JIT_OPERATION operationPutByValWithThisStrict(JSGlobalObject* globalObject, EncodedJSValue encodedBase, EncodedJSValue encodedThis, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue)
1788{
1789 VM& vm = globalObject->vm();
1790 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1791 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1792 auto scope = DECLARE_THROW_SCOPE(vm);
1793
1794 Identifier property = JSValue::decode(encodedSubscript).toPropertyKey(globalObject);
1795 RETURN_IF_EXCEPTION(scope, void());
1796 scope.release();
1797 putWithThis<true>(globalObject, encodedBase, encodedThis, encodedValue, property);
1798}
1799
1800void JIT_OPERATION operationPutByValWithThis(JSGlobalObject* globalObject, EncodedJSValue encodedBase, EncodedJSValue encodedThis, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue)
1801{
1802 VM& vm = globalObject->vm();
1803 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1804 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1805 auto scope = DECLARE_THROW_SCOPE(vm);
1806
1807 Identifier property = JSValue::decode(encodedSubscript).toPropertyKey(globalObject);
1808 RETURN_IF_EXCEPTION(scope, void());
1809 scope.release();
1810 putWithThis<false>(globalObject, encodedBase, encodedThis, encodedValue, property);
1811}
1812
1813ALWAYS_INLINE static void defineDataProperty(JSGlobalObject* globalObject, VM& vm, JSObject* base, const Identifier& propertyName, JSValue value, int32_t attributes)
1814{
1815 PropertyDescriptor descriptor = toPropertyDescriptor(value, jsUndefined(), jsUndefined(), DefinePropertyAttributes(attributes));
1816 ASSERT((descriptor.attributes() & PropertyAttribute::Accessor) || (!descriptor.isAccessorDescriptor()));
1817 if (base->methodTable(vm)->defineOwnProperty == JSObject::defineOwnProperty)
1818 JSObject::defineOwnProperty(base, globalObject, propertyName, descriptor, true);
1819 else
1820 base->methodTable(vm)->defineOwnProperty(base, globalObject, propertyName, descriptor, true);
1821}
1822
1823void JIT_OPERATION operationDefineDataProperty(JSGlobalObject* globalObject, JSObject* base, EncodedJSValue encodedProperty, EncodedJSValue encodedValue, int32_t attributes)
1824{
1825 VM& vm = globalObject->vm();
1826 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1827 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1828 auto scope = DECLARE_THROW_SCOPE(vm);
1829
1830 Identifier propertyName = JSValue::decode(encodedProperty).toPropertyKey(globalObject);
1831 RETURN_IF_EXCEPTION(scope, void());
1832 scope.release();
1833 defineDataProperty(globalObject, vm, base, propertyName, JSValue::decode(encodedValue), attributes);
1834}
1835
1836void JIT_OPERATION operationDefineDataPropertyString(JSGlobalObject* globalObject, JSObject* base, JSString* property, EncodedJSValue encodedValue, int32_t attributes)
1837{
1838 VM& vm = globalObject->vm();
1839 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1840 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1841 auto scope = DECLARE_THROW_SCOPE(vm);
1842
1843 Identifier propertyName = property->toIdentifier(globalObject);
1844 RETURN_IF_EXCEPTION(scope, void());
1845 scope.release();
1846 defineDataProperty(globalObject, vm, base, propertyName, JSValue::decode(encodedValue), attributes);
1847}
1848
1849void JIT_OPERATION operationDefineDataPropertyStringIdent(JSGlobalObject* globalObject, JSObject* base, UniquedStringImpl* property, EncodedJSValue encodedValue, int32_t attributes)
1850{
1851 VM& vm = globalObject->vm();
1852 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1853 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1854 defineDataProperty(globalObject, vm, base, Identifier::fromUid(vm, property), JSValue::decode(encodedValue), attributes);
1855}
1856
1857void JIT_OPERATION operationDefineDataPropertySymbol(JSGlobalObject* globalObject, JSObject* base, Symbol* property, EncodedJSValue encodedValue, int32_t attributes)
1858{
1859 VM& vm = globalObject->vm();
1860 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1861 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1862 defineDataProperty(globalObject, vm, base, Identifier::fromUid(property->privateName()), JSValue::decode(encodedValue), attributes);
1863}
1864
1865ALWAYS_INLINE static void defineAccessorProperty(JSGlobalObject* globalObject, VM& vm, JSObject* base, const Identifier& propertyName, JSObject* getter, JSObject* setter, int32_t attributes)
1866{
1867 PropertyDescriptor descriptor = toPropertyDescriptor(jsUndefined(), getter, setter, DefinePropertyAttributes(attributes));
1868 ASSERT((descriptor.attributes() & PropertyAttribute::Accessor) || (!descriptor.isAccessorDescriptor()));
1869 if (base->methodTable(vm)->defineOwnProperty == JSObject::defineOwnProperty)
1870 JSObject::defineOwnProperty(base, globalObject, propertyName, descriptor, true);
1871 else
1872 base->methodTable(vm)->defineOwnProperty(base, globalObject, propertyName, descriptor, true);
1873}
1874
1875void JIT_OPERATION operationDefineAccessorProperty(JSGlobalObject* globalObject, JSObject* base, EncodedJSValue encodedProperty, JSObject* getter, JSObject* setter, int32_t attributes)
1876{
1877 VM& vm = globalObject->vm();
1878 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1879 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1880 auto scope = DECLARE_THROW_SCOPE(vm);
1881
1882 Identifier propertyName = JSValue::decode(encodedProperty).toPropertyKey(globalObject);
1883 RETURN_IF_EXCEPTION(scope, void());
1884 defineAccessorProperty(globalObject, vm, base, propertyName, getter, setter, attributes);
1885}
1886
1887void JIT_OPERATION operationDefineAccessorPropertyString(JSGlobalObject* globalObject, JSObject* base, JSString* property, JSObject* getter, JSObject* setter, int32_t attributes)
1888{
1889 VM& vm = globalObject->vm();
1890 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1891 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1892 auto scope = DECLARE_THROW_SCOPE(vm);
1893
1894 Identifier propertyName = property->toIdentifier(globalObject);
1895 RETURN_IF_EXCEPTION(scope, void());
1896 defineAccessorProperty(globalObject, vm, base, propertyName, getter, setter, attributes);
1897}
1898
1899void JIT_OPERATION operationDefineAccessorPropertyStringIdent(JSGlobalObject* globalObject, JSObject* base, UniquedStringImpl* property, JSObject* getter, JSObject* setter, int32_t attributes)
1900{
1901 VM& vm = globalObject->vm();
1902 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1903 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1904 defineAccessorProperty(globalObject, vm, base, Identifier::fromUid(vm, property), getter, setter, attributes);
1905}
1906
1907void JIT_OPERATION operationDefineAccessorPropertySymbol(JSGlobalObject* globalObject, JSObject* base, Symbol* property, JSObject* getter, JSObject* setter, int32_t attributes)
1908{
1909 VM& vm = globalObject->vm();
1910 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1911 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1912 defineAccessorProperty(globalObject, vm, base, Identifier::fromUid(property->privateName()), getter, setter, attributes);
1913}
1914
1915char* JIT_OPERATION operationNewArray(JSGlobalObject* globalObject, Structure* arrayStructure, void* buffer, size_t size)
1916{
1917 VM& vm = globalObject->vm();
1918 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1919 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1920
1921 return bitwise_cast<char*>(constructArray(globalObject, arrayStructure, static_cast<JSValue*>(buffer), size));
1922}
1923
1924char* JIT_OPERATION operationNewEmptyArray(VM* vmPointer, Structure* arrayStructure)
1925{
1926 VM& vm = *vmPointer;
1927 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1928 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1929
1930 return bitwise_cast<char*>(JSArray::create(vm, arrayStructure));
1931}
1932
1933char* JIT_OPERATION operationNewArrayWithSize(JSGlobalObject* globalObject, Structure* arrayStructure, int32_t size, Butterfly* butterfly)
1934{
1935 VM& vm = globalObject->vm();
1936 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1937 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1938 auto scope = DECLARE_THROW_SCOPE(vm);
1939
1940 if (UNLIKELY(size < 0))
1941 return bitwise_cast<char*>(throwException(globalObject, scope, createRangeError(globalObject, "Array size is not a small enough positive integer."_s)));
1942
1943 JSArray* result;
1944 if (butterfly)
1945 result = JSArray::createWithButterfly(vm, nullptr, arrayStructure, butterfly);
1946 else
1947 result = JSArray::create(vm, arrayStructure, size);
1948 return bitwise_cast<char*>(result);
1949}
1950
1951char* JIT_OPERATION operationNewArrayWithSizeAndHint(JSGlobalObject* globalObject, Structure* arrayStructure, int32_t size, int32_t vectorLengthHint, Butterfly* butterfly)
1952{
1953 VM& vm = globalObject->vm();
1954 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1955 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1956 auto scope = DECLARE_THROW_SCOPE(vm);
1957
1958 if (UNLIKELY(size < 0))
1959 return bitwise_cast<char*>(throwException(globalObject, scope, createRangeError(globalObject, "Array size is not a small enough positive integer."_s)));
1960
1961 JSArray* result;
1962 if (butterfly)
1963 result = JSArray::createWithButterfly(vm, nullptr, arrayStructure, butterfly);
1964 else {
1965 result = JSArray::tryCreate(vm, arrayStructure, size, vectorLengthHint);
1966 RELEASE_ASSERT(result);
1967 }
1968 return bitwise_cast<char*>(result);
1969}
1970
1971JSCell* JIT_OPERATION operationNewArrayBuffer(VM* vmPointer, Structure* arrayStructure, JSCell* immutableButterflyCell)
1972{
1973 VM& vm = *vmPointer;
1974 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1975 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1976 ASSERT(!arrayStructure->outOfLineCapacity());
1977 auto* immutableButterfly = jsCast<JSImmutableButterfly*>(immutableButterflyCell);
1978 ASSERT(arrayStructure->indexingMode() == immutableButterfly->indexingMode() || hasAnyArrayStorage(arrayStructure->indexingMode()));
1979 auto* result = CommonSlowPaths::allocateNewArrayBuffer(vm, arrayStructure, immutableButterfly);
1980 ASSERT(result->indexingMode() == result->structure(vm)->indexingMode());
1981 ASSERT(result->structure(vm) == arrayStructure);
1982 return result;
1983}
1984
1985char* JIT_OPERATION operationNewInt8ArrayWithSize(
1986 JSGlobalObject* globalObject, Structure* structure, int32_t length, char* vector)
1987{
1988 VM& vm = globalObject->vm();
1989 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1990 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1991 return newTypedArrayWithSize<JSInt8Array>(globalObject, vm, structure, length, vector);
1992}
1993
1994char* JIT_OPERATION operationNewInt8ArrayWithOneArgument(
1995 JSGlobalObject* globalObject, Structure* structure, EncodedJSValue encodedValue)
1996{
1997 VM& vm = globalObject->vm();
1998 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1999 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2000 return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSInt8Array>(globalObject, structure, encodedValue, 0, WTF::nullopt));
2001}
2002
2003char* JIT_OPERATION operationNewInt16ArrayWithSize(
2004 JSGlobalObject* globalObject, Structure* structure, int32_t length, char* vector)
2005{
2006 VM& vm = globalObject->vm();
2007 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2008 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2009 return newTypedArrayWithSize<JSInt16Array>(globalObject, vm, structure, length, vector);
2010}
2011
2012char* JIT_OPERATION operationNewInt16ArrayWithOneArgument(
2013 JSGlobalObject* globalObject, Structure* structure, EncodedJSValue encodedValue)
2014{
2015 VM& vm = globalObject->vm();
2016 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2017 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2018 return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSInt16Array>(globalObject, structure, encodedValue, 0, WTF::nullopt));
2019}
2020
2021char* JIT_OPERATION operationNewInt32ArrayWithSize(
2022 JSGlobalObject* globalObject, Structure* structure, int32_t length, char* vector)
2023{
2024 VM& vm = globalObject->vm();
2025 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2026 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2027 return newTypedArrayWithSize<JSInt32Array>(globalObject, vm, structure, length, vector);
2028}
2029
2030char* JIT_OPERATION operationNewInt32ArrayWithOneArgument(
2031 JSGlobalObject* globalObject, Structure* structure, EncodedJSValue encodedValue)
2032{
2033 VM& vm = globalObject->vm();
2034 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2035 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2036 return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSInt32Array>(globalObject, structure, encodedValue, 0, WTF::nullopt));
2037}
2038
2039char* JIT_OPERATION operationNewUint8ArrayWithSize(
2040 JSGlobalObject* globalObject, Structure* structure, int32_t length, char* vector)
2041{
2042 VM& vm = globalObject->vm();
2043 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2044 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2045 return newTypedArrayWithSize<JSUint8Array>(globalObject, vm, structure, length, vector);
2046}
2047
2048char* JIT_OPERATION operationNewUint8ArrayWithOneArgument(
2049 JSGlobalObject* globalObject, Structure* structure, EncodedJSValue encodedValue)
2050{
2051 VM& vm = globalObject->vm();
2052 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2053 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2054 return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSUint8Array>(globalObject, structure, encodedValue, 0, WTF::nullopt));
2055}
2056
2057char* JIT_OPERATION operationNewUint8ClampedArrayWithSize(
2058 JSGlobalObject* globalObject, Structure* structure, int32_t length, char* vector)
2059{
2060 VM& vm = globalObject->vm();
2061 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2062 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2063 return newTypedArrayWithSize<JSUint8ClampedArray>(globalObject, vm, structure, length, vector);
2064}
2065
2066char* JIT_OPERATION operationNewUint8ClampedArrayWithOneArgument(
2067 JSGlobalObject* globalObject, Structure* structure, EncodedJSValue encodedValue)
2068{
2069 VM& vm = globalObject->vm();
2070 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2071 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2072 return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSUint8ClampedArray>(globalObject, structure, encodedValue, 0, WTF::nullopt));
2073}
2074
2075char* JIT_OPERATION operationNewUint16ArrayWithSize(
2076 JSGlobalObject* globalObject, Structure* structure, int32_t length, char* vector)
2077{
2078 VM& vm = globalObject->vm();
2079 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2080 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2081 return newTypedArrayWithSize<JSUint16Array>(globalObject, vm, structure, length, vector);
2082}
2083
2084char* JIT_OPERATION operationNewUint16ArrayWithOneArgument(
2085 JSGlobalObject* globalObject, Structure* structure, EncodedJSValue encodedValue)
2086{
2087 VM& vm = globalObject->vm();
2088 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2089 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2090 return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSUint16Array>(globalObject, structure, encodedValue, 0, WTF::nullopt));
2091}
2092
2093char* JIT_OPERATION operationNewUint32ArrayWithSize(
2094 JSGlobalObject* globalObject, Structure* structure, int32_t length, char* vector)
2095{
2096 VM& vm = globalObject->vm();
2097 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2098 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2099 return newTypedArrayWithSize<JSUint32Array>(globalObject, vm, structure, length, vector);
2100}
2101
2102char* JIT_OPERATION operationNewUint32ArrayWithOneArgument(
2103 JSGlobalObject* globalObject, Structure* structure, EncodedJSValue encodedValue)
2104{
2105 VM& vm = globalObject->vm();
2106 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2107 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2108 return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSUint32Array>(globalObject, structure, encodedValue, 0, WTF::nullopt));
2109}
2110
2111char* JIT_OPERATION operationNewFloat32ArrayWithSize(
2112 JSGlobalObject* globalObject, Structure* structure, int32_t length, char* vector)
2113{
2114 VM& vm = globalObject->vm();
2115 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2116 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2117 return newTypedArrayWithSize<JSFloat32Array>(globalObject, vm, structure, length, vector);
2118}
2119
2120char* JIT_OPERATION operationNewFloat32ArrayWithOneArgument(
2121 JSGlobalObject* globalObject, Structure* structure, EncodedJSValue encodedValue)
2122{
2123 VM& vm = globalObject->vm();
2124 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2125 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2126 return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSFloat32Array>(globalObject, structure, encodedValue, 0, WTF::nullopt));
2127}
2128
2129char* JIT_OPERATION operationNewFloat64ArrayWithSize(
2130 JSGlobalObject* globalObject, Structure* structure, int32_t length, char* vector)
2131{
2132 VM& vm = globalObject->vm();
2133 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2134 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2135 return newTypedArrayWithSize<JSFloat64Array>(globalObject, vm, structure, length, vector);
2136}
2137
2138char* JIT_OPERATION operationNewFloat64ArrayWithOneArgument(
2139 JSGlobalObject* globalObject, Structure* structure, EncodedJSValue encodedValue)
2140{
2141 VM& vm = globalObject->vm();
2142 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2143 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2144 return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSFloat64Array>(globalObject, structure, encodedValue, 0, WTF::nullopt));
2145}
2146
2147JSCell* JIT_OPERATION operationCreateActivationDirect(VM* vmPointer, Structure* structure, JSScope* scope, SymbolTable* table, EncodedJSValue initialValueEncoded)
2148{
2149 VM& vm = *vmPointer;
2150 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2151 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2152 JSValue initialValue = JSValue::decode(initialValueEncoded);
2153 ASSERT(initialValue == jsUndefined() || initialValue == jsTDZValue());
2154 return JSLexicalEnvironment::create(vm, structure, scope, table, initialValue);
2155}
2156
2157JSCell* JIT_OPERATION operationCreateDirectArguments(VM* vmPointer, Structure* structure, uint32_t length, uint32_t minCapacity)
2158{
2159 VM& vm = *vmPointer;
2160 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2161 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2162 DirectArguments* result = DirectArguments::create(
2163 vm, structure, length, std::max(length, minCapacity));
2164 // The caller will store to this object without barriers. Most likely, at this point, this is
2165 // still a young object and so no barriers are needed. But it's good to be careful anyway,
2166 // since the GC should be allowed to do crazy (like pretenuring, for example).
2167 vm.heap.writeBarrier(result);
2168 return result;
2169}
2170
2171JSCell* JIT_OPERATION operationCreateScopedArguments(JSGlobalObject* globalObject, Structure* structure, Register* argumentStart, uint32_t length, JSFunction* callee, JSLexicalEnvironment* scope)
2172{
2173 VM& vm = globalObject->vm();
2174 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2175 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2176
2177 // We could pass the ScopedArgumentsTable* as an argument. We currently don't because I
2178 // didn't feel like changing the max number of arguments for a slow path call from 6 to 7.
2179 ScopedArgumentsTable* table = scope->symbolTable()->arguments();
2180
2181 return ScopedArguments::createByCopyingFrom(
2182 vm, structure, argumentStart, length, callee, table, scope);
2183}
2184
2185JSCell* JIT_OPERATION operationCreateClonedArguments(JSGlobalObject* globalObject, Structure* structure, Register* argumentStart, uint32_t length, JSFunction* callee)
2186{
2187 VM& vm = globalObject->vm();
2188 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2189 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2190 return ClonedArguments::createByCopyingFrom(
2191 globalObject, structure, argumentStart, length, callee);
2192}
2193
2194JSCell* JIT_OPERATION operationCreateDirectArgumentsDuringExit(VM* vmPointer, InlineCallFrame* inlineCallFrame, JSFunction* callee, uint32_t argumentCount)
2195{
2196 VM& vm = *vmPointer;
2197 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2198 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2199
2200 DeferGCForAWhile deferGC(vm.heap);
2201
2202 CodeBlock* codeBlock;
2203 if (inlineCallFrame)
2204 codeBlock = baselineCodeBlockForInlineCallFrame(inlineCallFrame);
2205 else
2206 codeBlock = callFrame->codeBlock();
2207
2208 unsigned length = argumentCount - 1;
2209 unsigned capacity = std::max(length, static_cast<unsigned>(codeBlock->numParameters() - 1));
2210 DirectArguments* result = DirectArguments::create(
2211 vm, codeBlock->globalObject()->directArgumentsStructure(), length, capacity);
2212
2213 result->setCallee(vm, callee);
2214
2215 Register* arguments =
2216 callFrame->registers() + (inlineCallFrame ? inlineCallFrame->stackOffset : 0) +
2217 CallFrame::argumentOffset(0);
2218 for (unsigned i = length; i--;)
2219 result->setIndexQuickly(vm, i, arguments[i].jsValue());
2220
2221 return result;
2222}
2223
2224JSCell* JIT_OPERATION operationCreateClonedArgumentsDuringExit(VM* vmPointer, InlineCallFrame* inlineCallFrame, JSFunction* callee, uint32_t argumentCount)
2225{
2226 VM& vm = *vmPointer;
2227 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2228 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2229
2230 DeferGCForAWhile deferGC(vm.heap);
2231
2232 CodeBlock* codeBlock;
2233 if (inlineCallFrame)
2234 codeBlock = baselineCodeBlockForInlineCallFrame(inlineCallFrame);
2235 else
2236 codeBlock = callFrame->codeBlock();
2237
2238 unsigned length = argumentCount - 1;
2239 JSGlobalObject* globalObject = codeBlock->globalObject();
2240 ClonedArguments* result = ClonedArguments::createEmpty(
2241 vm, globalObject->clonedArgumentsStructure(), callee, length);
2242
2243 Register* arguments =
2244 callFrame->registers() + (inlineCallFrame ? inlineCallFrame->stackOffset : 0) +
2245 CallFrame::argumentOffset(0);
2246 for (unsigned i = length; i--;)
2247 result->putDirectIndex(globalObject, i, arguments[i].jsValue());
2248
2249
2250 return result;
2251}
2252
2253JSCell* JIT_OPERATION operationCreateRest(JSGlobalObject* globalObject, Register* argumentStart, unsigned numberOfParamsToSkip, unsigned arraySize)
2254{
2255 VM& vm = globalObject->vm();
2256 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2257 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2258
2259 Structure* structure = globalObject->restParameterStructure();
2260 static_assert(sizeof(Register) == sizeof(JSValue), "This is a strong assumption here.");
2261 JSValue* argumentsToCopyRegion = bitwise_cast<JSValue*>(argumentStart) + numberOfParamsToSkip;
2262 return constructArray(globalObject, structure, argumentsToCopyRegion, arraySize);
2263}
2264
2265size_t JIT_OPERATION operationObjectIsObject(JSGlobalObject* globalObject, JSCell* object)
2266{
2267 VM& vm = globalObject->vm();
2268 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2269 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2270
2271 ASSERT(jsDynamicCast<JSObject*>(vm, object));
2272
2273 if (object->structure(vm)->masqueradesAsUndefined(globalObject))
2274 return false;
2275 if (object->isFunction(vm))
2276 return false;
2277 return true;
2278}
2279
2280size_t JIT_OPERATION operationObjectIsFunction(JSGlobalObject* globalObject, JSCell* object)
2281{
2282 VM& vm = globalObject->vm();
2283 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2284 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2285
2286 ASSERT(jsDynamicCast<JSObject*>(vm, object));
2287
2288 if (object->structure(vm)->masqueradesAsUndefined(globalObject))
2289 return false;
2290 if (object->isFunction(vm))
2291 return true;
2292 return false;
2293}
2294
2295JSCell* JIT_OPERATION operationTypeOfObject(JSGlobalObject* globalObject, JSCell* object)
2296{
2297 VM& vm = globalObject->vm();
2298 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2299 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2300
2301 ASSERT(jsDynamicCast<JSObject*>(vm, object));
2302
2303 if (object->structure(vm)->masqueradesAsUndefined(globalObject))
2304 return vm.smallStrings.undefinedString();
2305 if (object->isFunction(vm))
2306 return vm.smallStrings.functionString();
2307 return vm.smallStrings.objectString();
2308}
2309
2310int32_t JIT_OPERATION operationTypeOfObjectAsTypeofType(JSGlobalObject* globalObject, JSCell* object)
2311{
2312 VM& vm = globalObject->vm();
2313 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2314 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2315
2316 ASSERT(jsDynamicCast<JSObject*>(vm, object));
2317
2318 if (object->structure(vm)->masqueradesAsUndefined(globalObject))
2319 return static_cast<int32_t>(TypeofType::Undefined);
2320 if (object->isFunction(vm))
2321 return static_cast<int32_t>(TypeofType::Function);
2322 return static_cast<int32_t>(TypeofType::Object);
2323}
2324
2325char* JIT_OPERATION operationAllocateSimplePropertyStorageWithInitialCapacity(VM* vmPointer)
2326{
2327 VM& vm = *vmPointer;
2328 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2329 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2330
2331 return reinterpret_cast<char*>(
2332 Butterfly::createUninitialized(vm, 0, 0, initialOutOfLineCapacity, false, 0));
2333}
2334
2335char* JIT_OPERATION operationAllocateSimplePropertyStorage(VM* vmPointer, size_t newSize)
2336{
2337 VM& vm = *vmPointer;
2338 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2339 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2340
2341 return reinterpret_cast<char*>(
2342 Butterfly::createUninitialized(vm, 0, 0, newSize, false, 0));
2343}
2344
2345char* JIT_OPERATION operationAllocateComplexPropertyStorageWithInitialCapacity(VM* vmPointer, JSObject* object)
2346{
2347 VM& vm = *vmPointer;
2348 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2349 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2350
2351 ASSERT(!object->structure(vm)->outOfLineCapacity());
2352 return reinterpret_cast<char*>(
2353 object->allocateMoreOutOfLineStorage(vm, 0, initialOutOfLineCapacity));
2354}
2355
2356char* JIT_OPERATION operationAllocateComplexPropertyStorage(VM* vmPointer, JSObject* object, size_t newSize)
2357{
2358 VM& vm = *vmPointer;
2359 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2360 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2361
2362 return reinterpret_cast<char*>(
2363 object->allocateMoreOutOfLineStorage(vm, object->structure(vm)->outOfLineCapacity(), newSize));
2364}
2365
2366char* JIT_OPERATION operationEnsureInt32(VM* vmPointer, JSCell* cell)
2367{
2368 VM& vm = *vmPointer;
2369 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2370 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2371
2372 if (!cell->isObject())
2373 return 0;
2374
2375 auto* result = reinterpret_cast<char*>(asObject(cell)->tryMakeWritableInt32(vm).data());
2376 ASSERT((!isCopyOnWrite(asObject(cell)->indexingMode()) && hasInt32(cell->indexingMode())) || !result);
2377 return result;
2378}
2379
2380char* JIT_OPERATION operationEnsureDouble(VM* vmPointer, JSCell* cell)
2381{
2382 VM& vm = *vmPointer;
2383 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2384 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2385
2386 if (!cell->isObject())
2387 return 0;
2388
2389 auto* result = reinterpret_cast<char*>(asObject(cell)->tryMakeWritableDouble(vm).data());
2390 ASSERT((!isCopyOnWrite(asObject(cell)->indexingMode()) && hasDouble(cell->indexingMode())) || !result);
2391 return result;
2392}
2393
2394char* JIT_OPERATION operationEnsureContiguous(VM* vmPointer, JSCell* cell)
2395{
2396 VM& vm = *vmPointer;
2397 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2398 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2399
2400 if (!cell->isObject())
2401 return 0;
2402
2403 auto* result = reinterpret_cast<char*>(asObject(cell)->tryMakeWritableContiguous(vm).data());
2404 ASSERT((!isCopyOnWrite(asObject(cell)->indexingMode()) && hasContiguous(cell->indexingMode())) || !result);
2405 return result;
2406}
2407
2408char* JIT_OPERATION operationEnsureArrayStorage(VM* vmPointer, JSCell* cell)
2409{
2410 VM& vm = *vmPointer;
2411 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2412 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2413
2414 if (!cell->isObject())
2415 return 0;
2416
2417 auto* result = reinterpret_cast<char*>(asObject(cell)->ensureArrayStorage(vm));
2418 ASSERT((!isCopyOnWrite(asObject(cell)->indexingMode()) && hasAnyArrayStorage(cell->indexingMode())) || !result);
2419 return result;
2420}
2421
2422EncodedJSValue JIT_OPERATION operationHasGenericProperty(JSGlobalObject* globalObject, EncodedJSValue encodedBaseValue, JSCell* property)
2423{
2424 VM& vm = globalObject->vm();
2425 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2426 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2427 auto scope = DECLARE_THROW_SCOPE(vm);
2428
2429 JSValue baseValue = JSValue::decode(encodedBaseValue);
2430 if (baseValue.isUndefinedOrNull())
2431 return JSValue::encode(jsBoolean(false));
2432
2433 JSObject* base = baseValue.toObject(globalObject);
2434 ASSERT(!scope.exception() || !base);
2435 if (!base)
2436 return JSValue::encode(JSValue());
2437 auto propertyName = asString(property)->toIdentifier(globalObject);
2438 RETURN_IF_EXCEPTION(scope, { });
2439 RELEASE_AND_RETURN(scope, JSValue::encode(jsBoolean(base->hasPropertyGeneric(globalObject, propertyName, PropertySlot::InternalMethodType::GetOwnProperty))));
2440}
2441
2442size_t JIT_OPERATION operationHasIndexedPropertyByInt(JSGlobalObject* globalObject, JSCell* baseCell, int32_t subscript, int32_t internalMethodType)
2443{
2444 VM& vm = globalObject->vm();
2445 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2446 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2447 JSObject* object = baseCell->toObject(globalObject);
2448 if (UNLIKELY(subscript < 0)) {
2449 // Go the slowest way possible because negative indices don't use indexed storage.
2450 return object->hasPropertyGeneric(globalObject, Identifier::from(vm, subscript), static_cast<PropertySlot::InternalMethodType>(internalMethodType));
2451 }
2452 return object->hasPropertyGeneric(globalObject, subscript, static_cast<PropertySlot::InternalMethodType>(internalMethodType));
2453}
2454
2455JSCell* JIT_OPERATION operationGetPropertyEnumerator(JSGlobalObject* globalObject, EncodedJSValue encodedBase)
2456{
2457 VM& vm = globalObject->vm();
2458 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2459 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2460 auto scope = DECLARE_THROW_SCOPE(vm);
2461
2462 JSValue base = JSValue::decode(encodedBase);
2463 if (base.isUndefinedOrNull())
2464 return vm.emptyPropertyNameEnumerator();
2465
2466 JSObject* baseObject = base.toObject(globalObject);
2467 RETURN_IF_EXCEPTION(scope, { });
2468
2469 RELEASE_AND_RETURN(scope, propertyNameEnumerator(globalObject, baseObject));
2470}
2471
2472JSCell* JIT_OPERATION operationGetPropertyEnumeratorCell(JSGlobalObject* globalObject, JSCell* cell)
2473{
2474 VM& vm = globalObject->vm();
2475 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2476 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2477 auto scope = DECLARE_THROW_SCOPE(vm);
2478
2479 JSObject* base = cell->toObject(globalObject);
2480 RETURN_IF_EXCEPTION(scope, { });
2481
2482 RELEASE_AND_RETURN(scope, propertyNameEnumerator(globalObject, base));
2483}
2484
2485JSCell* JIT_OPERATION operationToIndexString(JSGlobalObject* globalObject, int32_t index)
2486{
2487 VM& vm = globalObject->vm();
2488 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2489 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2490 return jsString(vm, Identifier::from(vm, index).string());
2491}
2492
2493JSCell* JIT_OPERATION operationNewRegexpWithLastIndex(JSGlobalObject* globalObject, JSCell* regexpPtr, EncodedJSValue encodedLastIndex)
2494{
2495 VM& vm = globalObject->vm();
2496 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2497 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2498
2499 RegExp* regexp = static_cast<RegExp*>(regexpPtr);
2500 ASSERT(regexp->isValid());
2501 return RegExpObject::create(vm, globalObject->regExpStructure(), regexp, JSValue::decode(encodedLastIndex));
2502}
2503
2504StringImpl* JIT_OPERATION operationResolveRope(JSGlobalObject* globalObject, JSString* string)
2505{
2506 VM& vm = globalObject->vm();
2507 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2508 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2509
2510 return string->value(globalObject).impl();
2511}
2512
2513JSString* JIT_OPERATION operationStringValueOf(JSGlobalObject* globalObject, EncodedJSValue encodedArgument)
2514{
2515 VM& vm = globalObject->vm();
2516 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2517 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2518 auto scope = DECLARE_THROW_SCOPE(vm);
2519
2520 JSValue argument = JSValue::decode(encodedArgument);
2521
2522 if (argument.isString())
2523 return asString(argument);
2524
2525 if (auto* stringObject = jsDynamicCast<StringObject*>(vm, argument))
2526 return stringObject->internalValue();
2527
2528 throwVMTypeError(globalObject, scope);
2529 return nullptr;
2530}
2531
2532JSCell* JIT_OPERATION operationStringSubstr(JSGlobalObject* globalObject, JSCell* cell, int32_t from, int32_t span)
2533{
2534 VM& vm = globalObject->vm();
2535 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2536 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2537
2538 return jsSubstring(vm, globalObject, jsCast<JSString*>(cell), from, span);
2539}
2540
2541JSCell* JIT_OPERATION operationStringSlice(JSGlobalObject* globalObject, JSCell* cell, int32_t start, int32_t end)
2542{
2543 VM& vm = globalObject->vm();
2544 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2545 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2546
2547 JSString* string = asString(cell);
2548 static_assert(static_cast<uint64_t>(JSString::MaxLength) <= static_cast<uint64_t>(std::numeric_limits<int32_t>::max()), "");
2549 return stringSlice(globalObject, vm, string, string->length(), start, end);
2550}
2551
2552JSString* JIT_OPERATION operationToLowerCase(JSGlobalObject* globalObject, JSString* string, uint32_t failingIndex)
2553{
2554 VM& vm = globalObject->vm();
2555 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2556 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2557
2558 auto scope = DECLARE_THROW_SCOPE(vm);
2559
2560 String inputString = string->value(globalObject);
2561 RETURN_IF_EXCEPTION(scope, nullptr);
2562 if (!inputString.length())
2563 return vm.smallStrings.emptyString();
2564
2565 String lowercasedString = inputString.is8Bit() ? inputString.convertToLowercaseWithoutLocaleStartingAtFailingIndex8Bit(failingIndex) : inputString.convertToLowercaseWithoutLocale();
2566 if (lowercasedString.impl() == inputString.impl())
2567 return string;
2568 RELEASE_AND_RETURN(scope, jsString(vm, lowercasedString));
2569}
2570
2571char* JIT_OPERATION operationInt32ToString(JSGlobalObject* globalObject, int32_t value, int32_t radix)
2572{
2573 VM& vm = globalObject->vm();
2574 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2575 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2576
2577 auto scope = DECLARE_THROW_SCOPE(vm);
2578
2579 if (radix < 2 || radix > 36) {
2580 throwVMError(globalObject, scope, createRangeError(globalObject, "toString() radix argument must be between 2 and 36"_s));
2581 return nullptr;
2582 }
2583
2584 return reinterpret_cast<char*>(int32ToString(vm, value, radix));
2585}
2586
2587char* JIT_OPERATION operationInt52ToString(JSGlobalObject* globalObject, int64_t value, int32_t radix)
2588{
2589 VM& vm = globalObject->vm();
2590 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2591 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2592
2593 auto scope = DECLARE_THROW_SCOPE(vm);
2594
2595 if (radix < 2 || radix > 36) {
2596 throwVMError(globalObject, scope, createRangeError(globalObject, "toString() radix argument must be between 2 and 36"_s));
2597 return nullptr;
2598 }
2599
2600 return reinterpret_cast<char*>(int52ToString(vm, value, radix));
2601}
2602
2603char* JIT_OPERATION operationDoubleToString(JSGlobalObject* globalObject, double value, int32_t radix)
2604{
2605 VM& vm = globalObject->vm();
2606 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2607 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2608
2609 auto scope = DECLARE_THROW_SCOPE(vm);
2610
2611 if (radix < 2 || radix > 36) {
2612 throwVMError(globalObject, scope, createRangeError(globalObject, "toString() radix argument must be between 2 and 36"_s));
2613 return nullptr;
2614 }
2615
2616 return reinterpret_cast<char*>(numberToString(vm, value, radix));
2617}
2618
2619char* JIT_OPERATION operationInt32ToStringWithValidRadix(JSGlobalObject* globalObject, int32_t value, int32_t radix)
2620{
2621 VM& vm = globalObject->vm();
2622 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2623 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2624
2625 return reinterpret_cast<char*>(int32ToString(vm, value, radix));
2626}
2627
2628char* JIT_OPERATION operationInt52ToStringWithValidRadix(JSGlobalObject* globalObject, int64_t value, int32_t radix)
2629{
2630 VM& vm = globalObject->vm();
2631 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2632 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2633
2634 return reinterpret_cast<char*>(int52ToString(vm, value, radix));
2635}
2636
2637char* JIT_OPERATION operationDoubleToStringWithValidRadix(JSGlobalObject* globalObject, double value, int32_t radix)
2638{
2639 VM& vm = globalObject->vm();
2640 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2641 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2642
2643 return reinterpret_cast<char*>(numberToString(vm, value, radix));
2644}
2645
2646JSString* JIT_OPERATION operationSingleCharacterString(VM* vmPointer, int32_t character)
2647{
2648 VM& vm = *vmPointer;
2649 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2650 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2651
2652 return jsSingleCharacterString(vm, static_cast<UChar>(character));
2653}
2654
2655Symbol* JIT_OPERATION operationNewSymbol(VM* vmPointer)
2656{
2657 VM& vm = *vmPointer;
2658 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2659 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2660
2661 return Symbol::create(vm);
2662}
2663
2664Symbol* JIT_OPERATION operationNewSymbolWithDescription(JSGlobalObject* globalObject, JSString* description)
2665{
2666 VM& vm = globalObject->vm();
2667 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2668 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2669 auto scope = DECLARE_THROW_SCOPE(vm);
2670
2671 String string = description->value(globalObject);
2672 RETURN_IF_EXCEPTION(scope, nullptr);
2673
2674 return Symbol::createWithDescription(vm, string);
2675}
2676
2677JSCell* JIT_OPERATION operationNewStringObject(VM* vmPointer, JSString* string, Structure* structure)
2678{
2679 VM& vm = *vmPointer;
2680 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2681 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2682
2683 return StringObject::create(vm, structure, string);
2684}
2685
2686JSString* JIT_OPERATION operationToStringOnCell(JSGlobalObject* globalObject, JSCell* cell)
2687{
2688 VM& vm = globalObject->vm();
2689 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2690 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2691
2692 return JSValue(cell).toString(globalObject);
2693}
2694
2695JSString* JIT_OPERATION operationToString(JSGlobalObject* globalObject, EncodedJSValue value)
2696{
2697 VM& vm = globalObject->vm();
2698 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2699 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2700
2701 return JSValue::decode(value).toString(globalObject);
2702}
2703
2704JSString* JIT_OPERATION operationCallStringConstructorOnCell(JSGlobalObject* globalObject, JSCell* cell)
2705{
2706 VM& vm = globalObject->vm();
2707 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2708 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2709
2710 return stringConstructor(globalObject, cell);
2711}
2712
2713JSString* JIT_OPERATION operationCallStringConstructor(JSGlobalObject* globalObject, EncodedJSValue value)
2714{
2715 VM& vm = globalObject->vm();
2716 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2717 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2718
2719 return stringConstructor(globalObject, JSValue::decode(value));
2720}
2721
2722JSString* JIT_OPERATION operationMakeRope2(JSGlobalObject* globalObject, JSString* left, JSString* right)
2723{
2724 VM& vm = globalObject->vm();
2725 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2726 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2727
2728 return jsString(globalObject, left, right);
2729}
2730
2731JSString* JIT_OPERATION operationMakeRope3(JSGlobalObject* globalObject, JSString* a, JSString* b, JSString* c)
2732{
2733 VM& vm = globalObject->vm();
2734 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2735 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2736
2737 return jsString(globalObject, a, b, c);
2738}
2739
2740JSString* JIT_OPERATION operationStrCat2(JSGlobalObject* globalObject, EncodedJSValue a, EncodedJSValue b)
2741{
2742 VM& vm = globalObject->vm();
2743 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2744 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2745 auto scope = DECLARE_THROW_SCOPE(vm);
2746
2747 ASSERT(!JSValue::decode(a).isSymbol());
2748 ASSERT(!JSValue::decode(b).isSymbol());
2749 JSString* str1 = JSValue::decode(a).toString(globalObject);
2750 scope.assertNoException(); // Impossible, since we must have been given non-Symbol primitives.
2751 JSString* str2 = JSValue::decode(b).toString(globalObject);
2752 scope.assertNoException();
2753
2754 RELEASE_AND_RETURN(scope, jsString(globalObject, str1, str2));
2755}
2756
2757JSString* JIT_OPERATION operationStrCat3(JSGlobalObject* globalObject, EncodedJSValue a, EncodedJSValue b, EncodedJSValue c)
2758{
2759 VM& vm = globalObject->vm();
2760 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2761 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2762 auto scope = DECLARE_THROW_SCOPE(vm);
2763
2764 ASSERT(!JSValue::decode(a).isSymbol());
2765 ASSERT(!JSValue::decode(b).isSymbol());
2766 ASSERT(!JSValue::decode(c).isSymbol());
2767 JSString* str1 = JSValue::decode(a).toString(globalObject);
2768 scope.assertNoException(); // Impossible, since we must have been given non-Symbol primitives.
2769 JSString* str2 = JSValue::decode(b).toString(globalObject);
2770 scope.assertNoException();
2771 JSString* str3 = JSValue::decode(c).toString(globalObject);
2772 scope.assertNoException();
2773
2774 RELEASE_AND_RETURN(scope, jsString(globalObject, str1, str2, str3));
2775}
2776
2777char* JIT_OPERATION operationFindSwitchImmTargetForDouble(VM* vmPointer, EncodedJSValue encodedValue, size_t tableIndex)
2778{
2779 VM& vm = *vmPointer;
2780 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2781 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2782 CodeBlock* codeBlock = callFrame->codeBlock();
2783 SimpleJumpTable& table = codeBlock->switchJumpTable(tableIndex);
2784 JSValue value = JSValue::decode(encodedValue);
2785 ASSERT(value.isDouble());
2786 double asDouble = value.asDouble();
2787 int32_t asInt32 = static_cast<int32_t>(asDouble);
2788 if (asDouble == asInt32)
2789 return table.ctiForValue(asInt32).executableAddress<char*>();
2790 return table.ctiDefault.executableAddress<char*>();
2791}
2792
2793char* JIT_OPERATION operationSwitchString(JSGlobalObject* globalObject, size_t tableIndex, JSString* string)
2794{
2795 VM& vm = globalObject->vm();
2796 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2797 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2798 auto throwScope = DECLARE_THROW_SCOPE(vm);
2799
2800 StringImpl* strImpl = string->value(globalObject).impl();
2801
2802 RETURN_IF_EXCEPTION(throwScope, nullptr);
2803
2804 return callFrame->codeBlock()->stringSwitchJumpTable(tableIndex).ctiForValue(strImpl).executableAddress<char*>();
2805}
2806
2807int32_t JIT_OPERATION operationSwitchStringAndGetBranchOffset(JSGlobalObject* globalObject, size_t tableIndex, JSString* string)
2808{
2809 VM& vm = globalObject->vm();
2810 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2811 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2812 auto throwScope = DECLARE_THROW_SCOPE(vm);
2813
2814 StringImpl* strImpl = string->value(globalObject).impl();
2815
2816 RETURN_IF_EXCEPTION(throwScope, 0);
2817
2818 return callFrame->codeBlock()->stringSwitchJumpTable(tableIndex).offsetForValue(strImpl, std::numeric_limits<int32_t>::min());
2819}
2820
2821uintptr_t JIT_OPERATION operationCompareStringImplLess(StringImpl* a, StringImpl* b)
2822{
2823 return codePointCompare(a, b) < 0;
2824}
2825
2826uintptr_t JIT_OPERATION operationCompareStringImplLessEq(StringImpl* a, StringImpl* b)
2827{
2828 return codePointCompare(a, b) <= 0;
2829}
2830
2831uintptr_t JIT_OPERATION operationCompareStringImplGreater(StringImpl* a, StringImpl* b)
2832{
2833 return codePointCompare(a, b) > 0;
2834}
2835
2836uintptr_t JIT_OPERATION operationCompareStringImplGreaterEq(StringImpl* a, StringImpl* b)
2837{
2838 return codePointCompare(a, b) >= 0;
2839}
2840
2841uintptr_t JIT_OPERATION operationCompareStringLess(JSGlobalObject* globalObject, JSString* a, JSString* b)
2842{
2843 VM& vm = globalObject->vm();
2844 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2845 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2846
2847 return codePointCompareLessThan(asString(a)->value(globalObject), asString(b)->value(globalObject));
2848}
2849
2850uintptr_t JIT_OPERATION operationCompareStringLessEq(JSGlobalObject* globalObject, JSString* a, JSString* b)
2851{
2852 VM& vm = globalObject->vm();
2853 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2854 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2855
2856 return !codePointCompareLessThan(asString(b)->value(globalObject), asString(a)->value(globalObject));
2857}
2858
2859uintptr_t JIT_OPERATION operationCompareStringGreater(JSGlobalObject* globalObject, JSString* a, JSString* b)
2860{
2861 VM& vm = globalObject->vm();
2862 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2863 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2864
2865 return codePointCompareLessThan(asString(b)->value(globalObject), asString(a)->value(globalObject));
2866}
2867
2868uintptr_t JIT_OPERATION operationCompareStringGreaterEq(JSGlobalObject* globalObject, JSString* a, JSString* b)
2869{
2870 VM& vm = globalObject->vm();
2871 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2872 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2873
2874 return !codePointCompareLessThan(asString(a)->value(globalObject), asString(b)->value(globalObject));
2875}
2876
2877void JIT_OPERATION operationNotifyWrite(VM* vmPointer, WatchpointSet* set)
2878{
2879 VM& vm = *vmPointer;
2880 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2881 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2882
2883 set->touch(vm, "Executed NotifyWrite");
2884}
2885
2886void JIT_OPERATION operationThrowStackOverflowForVarargs(JSGlobalObject* globalObject)
2887{
2888 VM& vm = globalObject->vm();
2889 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2890 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2891 auto scope = DECLARE_THROW_SCOPE(vm);
2892 throwStackOverflowError(globalObject, scope);
2893}
2894
2895int32_t JIT_OPERATION operationSizeOfVarargs(JSGlobalObject* globalObject, EncodedJSValue encodedArguments, uint32_t firstVarArgOffset)
2896{
2897 VM& vm = globalObject->vm();
2898 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2899 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2900 JSValue arguments = JSValue::decode(encodedArguments);
2901
2902 return sizeOfVarargs(globalObject, arguments, firstVarArgOffset);
2903}
2904
2905int32_t JIT_OPERATION operationHasOwnProperty(JSGlobalObject* globalObject, JSObject* thisObject, EncodedJSValue encodedKey)
2906{
2907 VM& vm = globalObject->vm();
2908 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2909 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2910 auto scope = DECLARE_THROW_SCOPE(vm);
2911
2912 JSValue key = JSValue::decode(encodedKey);
2913 Identifier propertyName = key.toPropertyKey(globalObject);
2914 RETURN_IF_EXCEPTION(scope, false);
2915
2916 PropertySlot slot(thisObject, PropertySlot::InternalMethodType::GetOwnProperty);
2917 bool result = thisObject->hasOwnProperty(globalObject, propertyName.impl(), slot);
2918 RETURN_IF_EXCEPTION(scope, false);
2919
2920 HasOwnPropertyCache* hasOwnPropertyCache = vm.hasOwnPropertyCache();
2921 ASSERT(hasOwnPropertyCache);
2922 hasOwnPropertyCache->tryAdd(vm, slot, thisObject, propertyName.impl(), result);
2923 return result;
2924}
2925
2926int32_t JIT_OPERATION operationNumberIsInteger(JSGlobalObject* globalObject, EncodedJSValue value)
2927{
2928 VM& vm = globalObject->vm();
2929 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2930 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2931 return NumberConstructor::isIntegerImpl(JSValue::decode(value));
2932}
2933
2934int32_t JIT_OPERATION operationArrayIndexOfString(JSGlobalObject* globalObject, Butterfly* butterfly, JSString* searchElement, int32_t index)
2935{
2936 VM& vm = globalObject->vm();
2937 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2938 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2939 auto scope = DECLARE_THROW_SCOPE(vm);
2940
2941 int32_t length = butterfly->publicLength();
2942 auto data = butterfly->contiguous().data();
2943 for (; index < length; ++index) {
2944 JSValue value = data[index].get();
2945 if (!value || !value.isString())
2946 continue;
2947 auto* string = asString(value);
2948 if (string == searchElement)
2949 return index;
2950 if (string->equal(globalObject, searchElement)) {
2951 scope.assertNoException();
2952 return index;
2953 }
2954 RETURN_IF_EXCEPTION(scope, { });
2955 }
2956 return -1;
2957}
2958
2959int32_t JIT_OPERATION operationArrayIndexOfValueInt32OrContiguous(JSGlobalObject* globalObject, Butterfly* butterfly, EncodedJSValue encodedValue, int32_t index)
2960{
2961 VM& vm = globalObject->vm();
2962 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2963 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2964 auto scope = DECLARE_THROW_SCOPE(vm);
2965
2966 JSValue searchElement = JSValue::decode(encodedValue);
2967
2968 int32_t length = butterfly->publicLength();
2969 auto data = butterfly->contiguous().data();
2970 for (; index < length; ++index) {
2971 JSValue value = data[index].get();
2972 if (!value)
2973 continue;
2974 bool isEqual = JSValue::strictEqual(globalObject, searchElement, value);
2975 RETURN_IF_EXCEPTION(scope, { });
2976 if (isEqual)
2977 return index;
2978 }
2979 return -1;
2980}
2981
2982int32_t JIT_OPERATION operationArrayIndexOfValueDouble(JSGlobalObject* globalObject, Butterfly* butterfly, EncodedJSValue encodedValue, int32_t index)
2983{
2984 VM& vm = globalObject->vm();
2985 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2986 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2987
2988 JSValue searchElement = JSValue::decode(encodedValue);
2989
2990 if (!searchElement.isNumber())
2991 return -1;
2992 double number = searchElement.asNumber();
2993
2994 int32_t length = butterfly->publicLength();
2995 const double* data = butterfly->contiguousDouble().data();
2996 for (; index < length; ++index) {
2997 // This comparison ignores NaN.
2998 if (data[index] == number)
2999 return index;
3000 }
3001 return -1;
3002}
3003
3004void JIT_OPERATION operationLoadVarargs(JSGlobalObject* globalObject, int32_t firstElementDest, EncodedJSValue encodedArguments, uint32_t offset, uint32_t length, uint32_t mandatoryMinimum)
3005{
3006 VM& vm = globalObject->vm();
3007 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
3008 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
3009 JSValue arguments = JSValue::decode(encodedArguments);
3010
3011 loadVarargs(globalObject, callFrame, VirtualRegister(firstElementDest), arguments, offset, length);
3012
3013 for (uint32_t i = length; i < mandatoryMinimum; ++i)
3014 callFrame->r(firstElementDest + i) = jsUndefined();
3015}
3016
3017double JIT_OPERATION operationFModOnInts(int32_t a, int32_t b)
3018{
3019 return fmod(a, b);
3020}
3021
3022#if USE(JSVALUE32_64)
3023double JIT_OPERATION operationRandom(JSGlobalObject* globalObject)
3024{
3025 return globalObject->weakRandomNumber();
3026}
3027#endif
3028
3029JSCell* JIT_OPERATION operationStringFromCharCode(JSGlobalObject* globalObject, int32_t op1)
3030{
3031 VM& vm = globalObject->vm();
3032 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
3033 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
3034 return JSC::stringFromCharCode(globalObject, op1);
3035}
3036
3037EncodedJSValue JIT_OPERATION operationStringFromCharCodeUntyped(JSGlobalObject* globalObject, EncodedJSValue encodedValue)
3038{
3039 VM& vm = globalObject->vm();
3040 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
3041 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
3042 JSValue charValue = JSValue::decode(encodedValue);
3043 int32_t chInt = charValue.toUInt32(globalObject);
3044 return JSValue::encode(JSC::stringFromCharCode(globalObject, chInt));
3045}
3046
3047int64_t JIT_OPERATION operationConvertBoxedDoubleToInt52(EncodedJSValue encodedValue)
3048{
3049 JSValue value = JSValue::decode(encodedValue);
3050 if (!value.isDouble())
3051 return JSValue::notInt52;
3052 return tryConvertToInt52(value.asDouble());
3053}
3054
3055int64_t JIT_OPERATION operationConvertDoubleToInt52(double value)
3056{
3057 return tryConvertToInt52(value);
3058}
3059
3060char* JIT_OPERATION operationNewRawObject(VM* vmPointer, Structure* structure, int32_t length, Butterfly* butterfly)
3061{
3062 VM& vm = *vmPointer;
3063 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
3064 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
3065
3066 if (!butterfly
3067 && (structure->outOfLineCapacity() || hasIndexedProperties(structure->indexingType()))) {
3068 IndexingHeader header;
3069 header.setVectorLength(length);
3070 header.setPublicLength(0);
3071
3072 butterfly = Butterfly::create(
3073 vm, nullptr, 0, structure->outOfLineCapacity(),
3074 hasIndexedProperties(structure->indexingType()), header,
3075 length * sizeof(EncodedJSValue));
3076 }
3077
3078 JSObject* result = JSObject::createRawObject(vm, structure, butterfly);
3079 return bitwise_cast<char*>(result);
3080}
3081
3082JSCell* JIT_OPERATION operationNewObjectWithButterfly(VM* vmPointer, Structure* structure, Butterfly* butterfly)
3083{
3084 VM& vm = *vmPointer;
3085 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
3086 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
3087
3088 if (!butterfly) {
3089 butterfly = Butterfly::create(
3090 vm, nullptr, 0, structure->outOfLineCapacity(), false, IndexingHeader(), 0);
3091 }
3092
3093 JSObject* result = JSObject::createRawObject(vm, structure, butterfly);
3094 return result;
3095}
3096
3097JSCell* JIT_OPERATION operationNewObjectWithButterflyWithIndexingHeaderAndVectorLength(VM* vmPointer, Structure* structure, unsigned length, Butterfly* butterfly)
3098{
3099 VM& vm = *vmPointer;
3100 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
3101 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
3102
3103 IndexingHeader header;
3104 header.setVectorLength(length);
3105 header.setPublicLength(0);
3106 if (butterfly)
3107 *butterfly->indexingHeader() = header;
3108 else {
3109 butterfly = Butterfly::create(
3110 vm, nullptr, 0, structure->outOfLineCapacity(), true, header,
3111 sizeof(EncodedJSValue) * length);
3112 }
3113
3114 // Paradoxically this may allocate a JSArray. That's totally cool.
3115 JSObject* result = JSObject::createRawObject(vm, structure, butterfly);
3116 return result;
3117}
3118
3119JSCell* JIT_OPERATION operationNewArrayWithSpreadSlow(JSGlobalObject* globalObject, void* buffer, uint32_t numItems)
3120{
3121 VM& vm = globalObject->vm();
3122 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
3123 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
3124 auto scope = DECLARE_THROW_SCOPE(vm);
3125
3126 EncodedJSValue* values = static_cast<EncodedJSValue*>(buffer);
3127 Checked<unsigned, RecordOverflow> checkedLength = 0;
3128 for (unsigned i = 0; i < numItems; i++) {
3129 JSValue value = JSValue::decode(values[i]);
3130 if (JSFixedArray* array = jsDynamicCast<JSFixedArray*>(vm, value))
3131 checkedLength += array->size();
3132 else
3133 ++checkedLength;
3134 }
3135
3136 if (UNLIKELY(checkedLength.hasOverflowed())) {
3137 throwOutOfMemoryError(globalObject, scope);
3138 return nullptr;
3139 }
3140
3141 unsigned length = checkedLength.unsafeGet();
3142 if (UNLIKELY(length >= MIN_ARRAY_STORAGE_CONSTRUCTION_LENGTH)) {
3143 throwOutOfMemoryError(globalObject, scope);
3144 return nullptr;
3145 }
3146
3147 Structure* structure = globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithContiguous);
3148
3149 JSArray* result = JSArray::tryCreate(vm, structure, length);
3150 if (UNLIKELY(!result)) {
3151 throwOutOfMemoryError(globalObject, scope);
3152 return nullptr;
3153 }
3154 RETURN_IF_EXCEPTION(scope, nullptr);
3155
3156 unsigned index = 0;
3157 for (unsigned i = 0; i < numItems; i++) {
3158 JSValue value = JSValue::decode(values[i]);
3159 if (JSFixedArray* array = jsDynamicCast<JSFixedArray*>(vm, value)) {
3160 // We are spreading.
3161 for (unsigned i = 0; i < array->size(); i++) {
3162 result->putDirectIndex(globalObject, index, array->get(i));
3163 RETURN_IF_EXCEPTION(scope, nullptr);
3164 ++index;
3165 }
3166 } else {
3167 // We are not spreading.
3168 result->putDirectIndex(globalObject, index, value);
3169 RETURN_IF_EXCEPTION(scope, nullptr);
3170 ++index;
3171 }
3172 }
3173
3174 return result;
3175}
3176
3177JSCell* operationCreateFixedArray(JSGlobalObject* globalObject, unsigned length)
3178{
3179 VM& vm = globalObject->vm();
3180 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
3181 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
3182 auto scope = DECLARE_THROW_SCOPE(vm);
3183
3184 if (JSFixedArray* result = JSFixedArray::tryCreate(vm, vm.fixedArrayStructure.get(), length))
3185 return result;
3186
3187 throwOutOfMemoryError(globalObject, scope);
3188 return nullptr;
3189}
3190
3191JSCell* JIT_OPERATION operationSpreadGeneric(JSGlobalObject* globalObject, JSCell* iterable)
3192{
3193 VM& vm = globalObject->vm();
3194 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
3195 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
3196
3197 auto throwScope = DECLARE_THROW_SCOPE(vm);
3198
3199 if (isJSArray(iterable)) {
3200 JSArray* array = jsCast<JSArray*>(iterable);
3201 if (array->isIteratorProtocolFastAndNonObservable())
3202 RELEASE_AND_RETURN(throwScope, JSFixedArray::createFromArray(globalObject, vm, array));
3203 }
3204
3205 // FIXME: we can probably make this path faster by having our caller JS code call directly into
3206 // the iteration protocol builtin: https://bugs.webkit.org/show_bug.cgi?id=164520
3207
3208 JSArray* array;
3209 {
3210 JSFunction* iterationFunction = globalObject->iteratorProtocolFunction();
3211 CallData callData;
3212 CallType callType = JSC::getCallData(vm, iterationFunction, callData);
3213 ASSERT(callType != CallType::None);
3214
3215 MarkedArgumentBuffer arguments;
3216 arguments.append(iterable);
3217 ASSERT(!arguments.hasOverflowed());
3218 JSValue arrayResult = call(globalObject, iterationFunction, callType, callData, jsNull(), arguments);
3219 RETURN_IF_EXCEPTION(throwScope, nullptr);
3220 array = jsCast<JSArray*>(arrayResult);
3221 }
3222
3223 RELEASE_AND_RETURN(throwScope, JSFixedArray::createFromArray(globalObject, vm, array));
3224}
3225
3226JSCell* JIT_OPERATION operationSpreadFastArray(JSGlobalObject* globalObject, JSCell* cell)
3227{
3228 VM& vm = globalObject->vm();
3229 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
3230 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
3231
3232 ASSERT(isJSArray(cell));
3233 JSArray* array = jsCast<JSArray*>(cell);
3234 ASSERT(array->isIteratorProtocolFastAndNonObservable());
3235
3236 return JSFixedArray::createFromArray(globalObject, vm, array);
3237}
3238
3239void JIT_OPERATION operationProcessTypeProfilerLogDFG(VM* vmPointer)
3240{
3241 VM& vm = *vmPointer;
3242 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
3243 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
3244
3245 vm.typeProfilerLog()->processLogEntries(vm, "Log Full, called from inside DFG."_s);
3246}
3247
3248EncodedJSValue JIT_OPERATION operationResolveScopeForHoistingFuncDeclInEval(JSGlobalObject* globalObject, JSScope* scope, UniquedStringImpl* impl)
3249{
3250 VM& vm = globalObject->vm();
3251 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
3252 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
3253
3254 JSValue resolvedScope = JSScope::resolveScopeForHoistingFuncDeclInEval(globalObject, scope, Identifier::fromUid(vm, impl));
3255 return JSValue::encode(resolvedScope);
3256}
3257
3258JSCell* JIT_OPERATION operationResolveScope(JSGlobalObject* globalObject, JSScope* scope, UniquedStringImpl* impl)
3259{
3260 VM& vm = globalObject->vm();
3261 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
3262 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
3263
3264 JSObject* resolvedScope = JSScope::resolve(globalObject, scope, Identifier::fromUid(vm, impl));
3265 return resolvedScope;
3266}
3267
3268EncodedJSValue JIT_OPERATION operationGetDynamicVar(JSGlobalObject* globalObject, JSObject* scope, UniquedStringImpl* impl, unsigned getPutInfoBits)
3269{
3270 VM& vm = globalObject->vm();
3271 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
3272 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
3273 auto throwScope = DECLARE_THROW_SCOPE(vm);
3274
3275 Identifier ident = Identifier::fromUid(vm, impl);
3276 RELEASE_AND_RETURN(throwScope, JSValue::encode(scope->getPropertySlot(globalObject, ident, [&] (bool found, PropertySlot& slot) -> JSValue {
3277 if (!found) {
3278 GetPutInfo getPutInfo(getPutInfoBits);
3279 if (getPutInfo.resolveMode() == ThrowIfNotFound)
3280 throwException(globalObject, throwScope, createUndefinedVariableError(globalObject, ident));
3281 return jsUndefined();
3282 }
3283
3284 if (scope->isGlobalLexicalEnvironment()) {
3285 // When we can't statically prove we need a TDZ check, we must perform the check on the slow path.
3286 JSValue result = slot.getValue(globalObject, ident);
3287 if (result == jsTDZValue()) {
3288 throwException(globalObject, throwScope, createTDZError(globalObject));
3289 return jsUndefined();
3290 }
3291 return result;
3292 }
3293
3294 return slot.getValue(globalObject, ident);
3295 })));
3296}
3297
3298ALWAYS_INLINE static void putDynamicVar(JSGlobalObject* globalObject, VM& vm, JSObject* scope, EncodedJSValue value, UniquedStringImpl* impl, unsigned getPutInfoBits, bool isStrictMode)
3299{
3300 auto throwScope = DECLARE_THROW_SCOPE(vm);
3301
3302 const Identifier& ident = Identifier::fromUid(vm, impl);
3303 GetPutInfo getPutInfo(getPutInfoBits);
3304 bool hasProperty = scope->hasProperty(globalObject, ident);
3305 RETURN_IF_EXCEPTION(throwScope, void());
3306 if (hasProperty
3307 && scope->isGlobalLexicalEnvironment()
3308 && !isInitialization(getPutInfo.initializationMode())) {
3309 // When we can't statically prove we need a TDZ check, we must perform the check on the slow path.
3310 PropertySlot slot(scope, PropertySlot::InternalMethodType::Get);
3311 JSGlobalLexicalEnvironment::getOwnPropertySlot(scope, globalObject, ident, slot);
3312 if (slot.getValue(globalObject, ident) == jsTDZValue()) {
3313 throwException(globalObject, throwScope, createTDZError(globalObject));
3314 return;
3315 }
3316 }
3317
3318 if (getPutInfo.resolveMode() == ThrowIfNotFound && !hasProperty) {
3319 throwException(globalObject, throwScope, createUndefinedVariableError(globalObject, ident));
3320 return;
3321 }
3322
3323 PutPropertySlot slot(scope, isStrictMode, PutPropertySlot::UnknownContext, isInitialization(getPutInfo.initializationMode()));
3324 throwScope.release();
3325 scope->methodTable(vm)->put(scope, globalObject, ident, JSValue::decode(value), slot);
3326}
3327
3328void JIT_OPERATION operationPutDynamicVarStrict(JSGlobalObject* globalObject, JSObject* scope, EncodedJSValue value, UniquedStringImpl* impl, unsigned getPutInfoBits)
3329{
3330 VM& vm = globalObject->vm();
3331 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
3332 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
3333 constexpr bool isStrictMode = true;
3334 return putDynamicVar(globalObject, vm, scope, value, impl, getPutInfoBits, isStrictMode);
3335}
3336
3337void JIT_OPERATION operationPutDynamicVarNonStrict(JSGlobalObject* globalObject, JSObject* scope, EncodedJSValue value, UniquedStringImpl* impl, unsigned getPutInfoBits)
3338{
3339 VM& vm = globalObject->vm();
3340 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
3341 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
3342 constexpr bool isStrictMode = false;
3343 return putDynamicVar(globalObject, vm, scope, value, impl, getPutInfoBits, isStrictMode);
3344}
3345
3346int32_t JIT_OPERATION operationMapHash(JSGlobalObject* globalObject, EncodedJSValue input)
3347{
3348 VM& vm = globalObject->vm();
3349 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
3350 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
3351
3352 return jsMapHash(globalObject, vm, JSValue::decode(input));
3353}
3354
3355JSCell* JIT_OPERATION operationJSMapFindBucket(JSGlobalObject* globalObject, JSCell* map, EncodedJSValue key, int32_t hash)
3356{
3357 VM& vm = globalObject->vm();
3358 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
3359 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
3360 JSMap::BucketType** bucket = jsCast<JSMap*>(map)->findBucket(globalObject, JSValue::decode(key), hash);
3361 if (!bucket)
3362 return vm.sentinelMapBucket();
3363 return *bucket;
3364}
3365
3366JSCell* JIT_OPERATION operationJSSetFindBucket(JSGlobalObject* globalObject, JSCell* map, EncodedJSValue key, int32_t hash)
3367{
3368 VM& vm = globalObject->vm();
3369 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
3370 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
3371 JSSet::BucketType** bucket = jsCast<JSSet*>(map)->findBucket(globalObject, JSValue::decode(key), hash);
3372 if (!bucket)
3373 return vm.sentinelSetBucket();
3374 return *bucket;
3375}
3376
3377JSCell* JIT_OPERATION operationSetAdd(JSGlobalObject* globalObject, JSCell* set, EncodedJSValue key, int32_t hash)
3378{
3379 VM& vm = globalObject->vm();
3380 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
3381 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
3382 auto* bucket = jsCast<JSSet*>(set)->addNormalized(globalObject, JSValue::decode(key), JSValue(), hash);
3383 if (!bucket)
3384 return vm.sentinelSetBucket();
3385 return bucket;
3386}
3387
3388JSCell* JIT_OPERATION operationMapSet(JSGlobalObject* globalObject, JSCell* map, EncodedJSValue key, EncodedJSValue value, int32_t hash)
3389{
3390 VM& vm = globalObject->vm();
3391 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
3392 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
3393 auto* bucket = jsCast<JSMap*>(map)->addNormalized(globalObject, JSValue::decode(key), JSValue::decode(value), hash);
3394 if (!bucket)
3395 return vm.sentinelMapBucket();
3396 return bucket;
3397}
3398
3399void JIT_OPERATION operationWeakSetAdd(VM* vmPointer, JSCell* set, JSCell* key, int32_t hash)
3400{
3401 VM& vm = *vmPointer;
3402 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
3403 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
3404 jsCast<JSWeakSet*>(set)->add(vm, asObject(key), JSValue(), hash);
3405}
3406
3407void JIT_OPERATION operationWeakMapSet(VM* vmPointer, JSCell* map, JSCell* key, EncodedJSValue value, int32_t hash)
3408{
3409 VM& vm = *vmPointer;
3410 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
3411 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
3412 jsCast<JSWeakMap*>(map)->add(vm, asObject(key), JSValue::decode(value), hash);
3413}
3414
3415EncodedJSValue JIT_OPERATION operationGetPrototypeOfObject(JSGlobalObject* globalObject, JSObject* thisObject)
3416{
3417 VM& vm = globalObject->vm();
3418 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
3419 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
3420 return JSValue::encode(thisObject->getPrototype(vm, globalObject));
3421}
3422
3423EncodedJSValue JIT_OPERATION operationGetPrototypeOf(JSGlobalObject* globalObject, EncodedJSValue encodedValue)
3424{
3425 VM& vm = globalObject->vm();
3426 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
3427 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
3428 auto scope = DECLARE_THROW_SCOPE(vm);
3429
3430 JSValue thisValue = JSValue::decode(encodedValue).toThis(globalObject, StrictMode);
3431 if (thisValue.isUndefinedOrNull())
3432 return throwVMError(globalObject, scope, createNotAnObjectError(globalObject, thisValue));
3433
3434 JSObject* thisObject = jsDynamicCast<JSObject*>(vm, thisValue);
3435 if (!thisObject) {
3436 JSObject* prototype = thisValue.synthesizePrototype(globalObject);
3437 EXCEPTION_ASSERT(!!scope.exception() == !prototype);
3438 if (UNLIKELY(!prototype))
3439 return JSValue::encode(JSValue());
3440 return JSValue::encode(prototype);
3441 }
3442
3443 RELEASE_AND_RETURN(scope, JSValue::encode(thisObject->getPrototype(vm, globalObject)));
3444}
3445
3446EncodedJSValue JIT_OPERATION operationDateGetFullYear(VM* vmPointer, DateInstance* date)
3447{
3448 VM& vm = *vmPointer;
3449 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
3450 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
3451
3452 const GregorianDateTime* gregorianDateTime = date->gregorianDateTime(vm);
3453 if (!gregorianDateTime)
3454 return JSValue::encode(jsNaN());
3455 return JSValue::encode(jsNumber(gregorianDateTime->year()));
3456}
3457
3458EncodedJSValue JIT_OPERATION operationDateGetUTCFullYear(VM* vmPointer, DateInstance* date)
3459{
3460 VM& vm = *vmPointer;
3461 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
3462 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
3463
3464 const GregorianDateTime* gregorianDateTime = date->gregorianDateTimeUTC(vm);
3465 if (!gregorianDateTime)
3466 return JSValue::encode(jsNaN());
3467 return JSValue::encode(jsNumber(gregorianDateTime->year()));
3468}
3469
3470EncodedJSValue JIT_OPERATION operationDateGetMonth(VM* vmPointer, DateInstance* date)
3471{
3472 VM& vm = *vmPointer;
3473 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
3474 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
3475
3476 const GregorianDateTime* gregorianDateTime = date->gregorianDateTime(vm);
3477 if (!gregorianDateTime)
3478 return JSValue::encode(jsNaN());
3479 return JSValue::encode(jsNumber(gregorianDateTime->month()));
3480}
3481
3482EncodedJSValue JIT_OPERATION operationDateGetUTCMonth(VM* vmPointer, DateInstance* date)
3483{
3484 VM& vm = *vmPointer;
3485 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
3486 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
3487
3488 const GregorianDateTime* gregorianDateTime = date->gregorianDateTimeUTC(vm);
3489 if (!gregorianDateTime)
3490 return JSValue::encode(jsNaN());
3491 return JSValue::encode(jsNumber(gregorianDateTime->month()));
3492}
3493
3494EncodedJSValue JIT_OPERATION operationDateGetDate(VM* vmPointer, DateInstance* date)
3495{
3496 VM& vm = *vmPointer;
3497 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
3498 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
3499
3500 const GregorianDateTime* gregorianDateTime = date->gregorianDateTime(vm);
3501 if (!gregorianDateTime)
3502 return JSValue::encode(jsNaN());
3503 return JSValue::encode(jsNumber(gregorianDateTime->monthDay()));
3504}
3505
3506EncodedJSValue JIT_OPERATION operationDateGetUTCDate(VM* vmPointer, DateInstance* date)
3507{
3508 VM& vm = *vmPointer;
3509 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
3510 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
3511
3512 const GregorianDateTime* gregorianDateTime = date->gregorianDateTimeUTC(vm);
3513 if (!gregorianDateTime)
3514 return JSValue::encode(jsNaN());
3515 return JSValue::encode(jsNumber(gregorianDateTime->monthDay()));
3516}
3517
3518EncodedJSValue JIT_OPERATION operationDateGetDay(VM* vmPointer, DateInstance* date)
3519{
3520 VM& vm = *vmPointer;
3521 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
3522 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
3523
3524 const GregorianDateTime* gregorianDateTime = date->gregorianDateTime(vm);
3525 if (!gregorianDateTime)
3526 return JSValue::encode(jsNaN());
3527 return JSValue::encode(jsNumber(gregorianDateTime->weekDay()));
3528}
3529
3530EncodedJSValue JIT_OPERATION operationDateGetUTCDay(VM* vmPointer, DateInstance* date)
3531{
3532 VM& vm = *vmPointer;
3533 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
3534 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
3535
3536 const GregorianDateTime* gregorianDateTime = date->gregorianDateTimeUTC(vm);
3537 if (!gregorianDateTime)
3538 return JSValue::encode(jsNaN());
3539 return JSValue::encode(jsNumber(gregorianDateTime->weekDay()));
3540}
3541
3542EncodedJSValue JIT_OPERATION operationDateGetHours(VM* vmPointer, DateInstance* date)
3543{
3544 VM& vm = *vmPointer;
3545 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
3546 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
3547
3548 const GregorianDateTime* gregorianDateTime = date->gregorianDateTime(vm);
3549 if (!gregorianDateTime)
3550 return JSValue::encode(jsNaN());
3551 return JSValue::encode(jsNumber(gregorianDateTime->hour()));
3552}
3553
3554EncodedJSValue JIT_OPERATION operationDateGetUTCHours(VM* vmPointer, DateInstance* date)
3555{
3556 VM& vm = *vmPointer;
3557 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
3558 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
3559
3560 const GregorianDateTime* gregorianDateTime = date->gregorianDateTimeUTC(vm);
3561 if (!gregorianDateTime)
3562 return JSValue::encode(jsNaN());
3563 return JSValue::encode(jsNumber(gregorianDateTime->hour()));
3564}
3565
3566EncodedJSValue JIT_OPERATION operationDateGetMinutes(VM* vmPointer, DateInstance* date)
3567{
3568 VM& vm = *vmPointer;
3569 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
3570 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
3571
3572 const GregorianDateTime* gregorianDateTime = date->gregorianDateTime(vm);
3573 if (!gregorianDateTime)
3574 return JSValue::encode(jsNaN());
3575 return JSValue::encode(jsNumber(gregorianDateTime->minute()));
3576}
3577
3578EncodedJSValue JIT_OPERATION operationDateGetUTCMinutes(VM* vmPointer, DateInstance* date)
3579{
3580 VM& vm = *vmPointer;
3581 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
3582 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
3583
3584 const GregorianDateTime* gregorianDateTime = date->gregorianDateTimeUTC(vm);
3585 if (!gregorianDateTime)
3586 return JSValue::encode(jsNaN());
3587 return JSValue::encode(jsNumber(gregorianDateTime->minute()));
3588}
3589
3590EncodedJSValue JIT_OPERATION operationDateGetSeconds(VM* vmPointer, DateInstance* date)
3591{
3592 VM& vm = *vmPointer;
3593 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
3594 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
3595
3596 const GregorianDateTime* gregorianDateTime = date->gregorianDateTime(vm);
3597 if (!gregorianDateTime)
3598 return JSValue::encode(jsNaN());
3599 return JSValue::encode(jsNumber(gregorianDateTime->second()));
3600}
3601
3602EncodedJSValue JIT_OPERATION operationDateGetUTCSeconds(VM* vmPointer, DateInstance* date)
3603{
3604 VM& vm = *vmPointer;
3605 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
3606 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
3607
3608 const GregorianDateTime* gregorianDateTime = date->gregorianDateTimeUTC(vm);
3609 if (!gregorianDateTime)
3610 return JSValue::encode(jsNaN());
3611 return JSValue::encode(jsNumber(gregorianDateTime->second()));
3612}
3613
3614EncodedJSValue JIT_OPERATION operationDateGetTimezoneOffset(VM* vmPointer, DateInstance* date)
3615{
3616 VM& vm = *vmPointer;
3617 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
3618 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
3619
3620 const GregorianDateTime* gregorianDateTime = date->gregorianDateTime(vm);
3621 if (!gregorianDateTime)
3622 return JSValue::encode(jsNaN());
3623 return JSValue::encode(jsNumber(-gregorianDateTime->utcOffsetInMinute()));
3624}
3625
3626EncodedJSValue JIT_OPERATION operationDateGetYear(VM* vmPointer, DateInstance* date)
3627{
3628 VM& vm = *vmPointer;
3629 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
3630 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
3631
3632 const GregorianDateTime* gregorianDateTime = date->gregorianDateTime(vm);
3633 if (!gregorianDateTime)
3634 return JSValue::encode(jsNaN());
3635 return JSValue::encode(jsNumber(gregorianDateTime->year() - 1900));
3636}
3637
3638void JIT_OPERATION operationThrowDFG(JSGlobalObject* globalObject, EncodedJSValue valueToThrow)
3639{
3640 VM& vm = globalObject->vm();
3641 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
3642 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
3643 auto scope = DECLARE_THROW_SCOPE(vm);
3644 scope.throwException(globalObject, JSValue::decode(valueToThrow));
3645}
3646
3647void JIT_OPERATION operationThrowStaticError(JSGlobalObject* globalObject, JSString* message, uint32_t errorType)
3648{
3649 VM& vm = globalObject->vm();
3650 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
3651 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
3652 auto scope = DECLARE_THROW_SCOPE(vm);
3653 String errorMessage = message->value(globalObject);
3654 scope.throwException(globalObject, createError(globalObject, static_cast<ErrorType>(errorType), errorMessage));
3655}
3656
3657void JIT_OPERATION operationLinkDirectCall(CallLinkInfo* callLinkInfo, JSFunction* callee)
3658{
3659 JSGlobalObject* globalObject = callee->globalObject();
3660 VM& vm = globalObject->vm();
3661 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
3662 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
3663 auto throwScope = DECLARE_THROW_SCOPE(vm);
3664
3665 CodeSpecializationKind kind = callLinkInfo->specializationKind();
3666
3667 RELEASE_ASSERT(callLinkInfo->isDirect());
3668
3669 // This would happen if the executable died during GC but the CodeBlock did not die. That should
3670 // not happen because the CodeBlock should have a weak reference to any executable it uses for
3671 // this purpose.
3672 RELEASE_ASSERT(callLinkInfo->executable());
3673
3674 // Having a CodeBlock indicates that this is linked. We shouldn't be taking this path if it's
3675 // linked.
3676 RELEASE_ASSERT(!callLinkInfo->codeBlock());
3677
3678 // We just don't support this yet.
3679 RELEASE_ASSERT(!callLinkInfo->isVarargs());
3680
3681 ExecutableBase* executable = callLinkInfo->executable();
3682 RELEASE_ASSERT(callee->executable() == callLinkInfo->executable());
3683
3684 JSScope* scope = callee->scopeUnchecked();
3685
3686 MacroAssemblerCodePtr<JSEntryPtrTag> codePtr;
3687 CodeBlock* codeBlock = nullptr;
3688 if (executable->isHostFunction())
3689 codePtr = executable->entrypointFor(kind, MustCheckArity);
3690 else {
3691 FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable);
3692
3693 RELEASE_ASSERT(isCall(kind) || functionExecutable->constructAbility() != ConstructAbility::CannotConstruct);
3694
3695 Exception* error = functionExecutable->prepareForExecution<FunctionExecutable>(vm, callee, scope, kind, codeBlock);
3696 EXCEPTION_ASSERT_UNUSED(throwScope, throwScope.exception() == error);
3697 if (UNLIKELY(error))
3698 return;
3699 unsigned argumentStackSlots = callLinkInfo->maxArgumentCountIncludingThis();
3700 if (argumentStackSlots < static_cast<size_t>(codeBlock->numParameters()))
3701 codePtr = functionExecutable->entrypointFor(kind, MustCheckArity);
3702 else
3703 codePtr = functionExecutable->entrypointFor(kind, ArityCheckNotRequired);
3704 }
3705
3706 linkDirectFor(callFrame, *callLinkInfo, codeBlock, codePtr);
3707}
3708
3709void triggerReoptimizationNow(CodeBlock* codeBlock, CodeBlock* optimizedCodeBlock, OSRExitBase* exit)
3710{
3711 // It's sort of preferable that we don't GC while in here. Anyways, doing so wouldn't
3712 // really be profitable.
3713 DeferGCForAWhile deferGC(codeBlock->vm().heap);
3714
3715 sanitizeStackForVM(codeBlock->vm());
3716
3717 if (Options::verboseOSR())
3718 dataLog(*codeBlock, ": Entered reoptimize\n");
3719 // We must be called with the baseline code block.
3720 ASSERT(JITCode::isBaselineCode(codeBlock->jitType()));
3721
3722 // If I am my own replacement, then reoptimization has already been triggered.
3723 // This can happen in recursive functions.
3724 //
3725 // Note that even if optimizedCodeBlock is an FTLForOSREntry style CodeBlock, this condition is a
3726 // sure bet that we don't have anything else left to do.
3727 CodeBlock* replacement = codeBlock->replacement();
3728 if (!replacement || replacement == codeBlock) {
3729 if (Options::verboseOSR())
3730 dataLog(*codeBlock, ": Not reoptimizing because we've already been jettisoned.\n");
3731 return;
3732 }
3733
3734 // Otherwise, the replacement must be optimized code. Use this as an opportunity
3735 // to check our logic.
3736 ASSERT(codeBlock->hasOptimizedReplacement());
3737 ASSERT(JITCode::isOptimizingJIT(optimizedCodeBlock->jitType()));
3738
3739 bool didTryToEnterIntoInlinedLoops = false;
3740 for (InlineCallFrame* inlineCallFrame = exit->m_codeOrigin.inlineCallFrame(); inlineCallFrame; inlineCallFrame = inlineCallFrame->directCaller.inlineCallFrame()) {
3741 if (inlineCallFrame->baselineCodeBlock->ownerExecutable()->didTryToEnterInLoop()) {
3742 didTryToEnterIntoInlinedLoops = true;
3743 break;
3744 }
3745 }
3746
3747 // In order to trigger reoptimization, one of two things must have happened:
3748 // 1) We exited more than some number of times.
3749 // 2) We exited and got stuck in a loop, and now we're exiting again.
3750 bool didExitABunch = optimizedCodeBlock->shouldReoptimizeNow();
3751 bool didGetStuckInLoop =
3752 (codeBlock->checkIfOptimizationThresholdReached() || didTryToEnterIntoInlinedLoops)
3753 && optimizedCodeBlock->shouldReoptimizeFromLoopNow();
3754
3755 if (!didExitABunch && !didGetStuckInLoop) {
3756 if (Options::verboseOSR())
3757 dataLog(*codeBlock, ": Not reoptimizing ", *optimizedCodeBlock, " because it either didn't exit enough or didn't loop enough after exit.\n");
3758 codeBlock->optimizeAfterLongWarmUp();
3759 return;
3760 }
3761
3762 optimizedCodeBlock->jettison(Profiler::JettisonDueToOSRExit, CountReoptimization);
3763}
3764
3765void JIT_OPERATION operationTriggerReoptimizationNow(CodeBlock* codeBlock, CodeBlock* optimizedCodeBlock, OSRExitBase* exit)
3766{
3767 triggerReoptimizationNow(codeBlock, optimizedCodeBlock, exit);
3768}
3769
3770#if ENABLE(FTL_JIT)
3771static bool shouldTriggerFTLCompile(CodeBlock* codeBlock, JITCode* jitCode)
3772{
3773 if (codeBlock->baselineVersion()->m_didFailFTLCompilation) {
3774 CODEBLOCK_LOG_EVENT(codeBlock, "abortFTLCompile", ());
3775 if (Options::verboseOSR())
3776 dataLog("Deferring FTL-optimization of ", *codeBlock, " indefinitely because there was an FTL failure.\n");
3777 jitCode->dontOptimizeAnytimeSoon(codeBlock);
3778 return false;
3779 }
3780
3781 if (!codeBlock->hasOptimizedReplacement()
3782 && !jitCode->checkIfOptimizationThresholdReached(codeBlock)) {
3783 CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("counter = ", jitCode->tierUpCounter));
3784 if (Options::verboseOSR())
3785 dataLog("Choosing not to FTL-optimize ", *codeBlock, " yet.\n");
3786 return false;
3787 }
3788 return true;
3789}
3790
3791static void triggerFTLReplacementCompile(VM& vm, CodeBlock* codeBlock, JITCode* jitCode)
3792{
3793 if (codeBlock->codeType() == GlobalCode) {
3794 // Global code runs once, so we don't want to do anything. We don't want to defer indefinitely,
3795 // since this may have been spuriously called from tier-up initiated in a loop, and that loop may
3796 // later want to run faster code. Deferring for warm-up seems safest.
3797 jitCode->optimizeAfterWarmUp(codeBlock);
3798 return;
3799 }
3800
3801 Worklist::State worklistState;
3802 if (Worklist* worklist = existingGlobalFTLWorklistOrNull()) {
3803 worklistState = worklist->completeAllReadyPlansForVM(
3804 vm, CompilationKey(codeBlock->baselineVersion(), FTLMode));
3805 } else
3806 worklistState = Worklist::NotKnown;
3807
3808 if (worklistState == Worklist::Compiling) {
3809 CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("still compiling"));
3810 jitCode->setOptimizationThresholdBasedOnCompilationResult(
3811 codeBlock, CompilationDeferred);
3812 return;
3813 }
3814
3815 if (codeBlock->hasOptimizedReplacement()) {
3816 CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("has replacement"));
3817 // That's great, we've compiled the code - next time we call this function,
3818 // we'll enter that replacement.
3819 jitCode->optimizeSoon(codeBlock);
3820 return;
3821 }
3822
3823 if (worklistState == Worklist::Compiled) {
3824 CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("compiled and failed"));
3825 // This means that we finished compiling, but failed somehow; in that case the
3826 // thresholds will be set appropriately.
3827 if (Options::verboseOSR())
3828 dataLog("Code block ", *codeBlock, " was compiled but it doesn't have an optimized replacement.\n");
3829 return;
3830 }
3831
3832 CODEBLOCK_LOG_EVENT(codeBlock, "triggerFTLReplacement", ());
3833 // We need to compile the code.
3834 compile(
3835 vm, codeBlock->newReplacement(), codeBlock, FTLMode, BytecodeIndex(),
3836 Operands<Optional<JSValue>>(), ToFTLDeferredCompilationCallback::create());
3837
3838 // If we reached here, the counter has not be reset. Do that now.
3839 jitCode->setOptimizationThresholdBasedOnCompilationResult(
3840 codeBlock, CompilationDeferred);
3841}
3842
3843void JIT_OPERATION operationTriggerTierUpNow(VM* vmPointer)
3844{
3845 VM& vm = *vmPointer;
3846 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
3847 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
3848 DeferGCForAWhile deferGC(vm.heap);
3849 CodeBlock* codeBlock = callFrame->codeBlock();
3850
3851 sanitizeStackForVM(vm);
3852
3853 if (codeBlock->jitType() != JITType::DFGJIT) {
3854 dataLog("Unexpected code block in DFG->FTL tier-up: ", *codeBlock, "\n");
3855 RELEASE_ASSERT_NOT_REACHED();
3856 }
3857
3858 JITCode* jitCode = codeBlock->jitCode()->dfg();
3859
3860 if (Options::verboseOSR()) {
3861 dataLog(
3862 *codeBlock, ": Entered triggerTierUpNow with executeCounter = ",
3863 jitCode->tierUpCounter, "\n");
3864 }
3865
3866 if (shouldTriggerFTLCompile(codeBlock, jitCode))
3867 triggerFTLReplacementCompile(vm, codeBlock, jitCode);
3868
3869 if (codeBlock->hasOptimizedReplacement()) {
3870 if (jitCode->tierUpEntryTriggers.isEmpty()) {
3871 CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("replacement in place, delaying indefinitely"));
3872 // There is nothing more we can do, the only way this will be entered
3873 // is through the function entry point.
3874 jitCode->dontOptimizeAnytimeSoon(codeBlock);
3875 return;
3876 }
3877 if (jitCode->osrEntryBlock() && jitCode->tierUpEntryTriggers.size() == 1) {
3878 CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("trigger in place, delaying indefinitely"));
3879 // There is only one outer loop and its trigger must have been set
3880 // when the plan completed.
3881 // Exiting the inner loop is useless, we can ignore the counter and leave
3882 // the trigger do its job.
3883 jitCode->dontOptimizeAnytimeSoon(codeBlock);
3884 return;
3885 }
3886 }
3887}
3888
3889static char* tierUpCommon(VM& vm, CallFrame* callFrame, BytecodeIndex originBytecodeIndex, bool canOSREnterHere)
3890{
3891 CodeBlock* codeBlock = callFrame->codeBlock();
3892
3893 // Resolve any pending plan for OSR Enter on this function.
3894 Worklist::State worklistState;
3895 if (Worklist* worklist = existingGlobalFTLWorklistOrNull()) {
3896 worklistState = worklist->completeAllReadyPlansForVM(
3897 vm, CompilationKey(codeBlock->baselineVersion(), FTLForOSREntryMode));
3898 } else
3899 worklistState = Worklist::NotKnown;
3900
3901 JITCode* jitCode = codeBlock->jitCode()->dfg();
3902
3903 bool triggeredSlowPathToStartCompilation = false;
3904 auto tierUpEntryTriggers = jitCode->tierUpEntryTriggers.find(originBytecodeIndex);
3905 if (tierUpEntryTriggers != jitCode->tierUpEntryTriggers.end()) {
3906 switch (tierUpEntryTriggers->value) {
3907 case JITCode::TriggerReason::DontTrigger:
3908 // The trigger isn't set, we entered because the counter reached its
3909 // threshold.
3910 break;
3911
3912 case JITCode::TriggerReason::CompilationDone:
3913 // The trigger was set because compilation completed. Don't unset it
3914 // so that further DFG executions OSR enter as well.
3915 break;
3916
3917 case JITCode::TriggerReason::StartCompilation:
3918 // We were asked to enter as soon as possible and start compiling an
3919 // entry for the current bytecode location. Unset this trigger so we
3920 // don't continually enter.
3921 tierUpEntryTriggers->value = JITCode::TriggerReason::DontTrigger;
3922 triggeredSlowPathToStartCompilation = true;
3923 break;
3924 }
3925 }
3926
3927 if (worklistState == Worklist::Compiling) {
3928 CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("still compiling"));
3929 jitCode->setOptimizationThresholdBasedOnCompilationResult(codeBlock, CompilationDeferred);
3930 return nullptr;
3931 }
3932
3933 // If we can OSR Enter, do it right away.
3934 if (canOSREnterHere) {
3935 auto iter = jitCode->bytecodeIndexToStreamIndex.find(originBytecodeIndex);
3936 if (iter != jitCode->bytecodeIndexToStreamIndex.end()) {
3937 unsigned streamIndex = iter->value;
3938 if (CodeBlock* entryBlock = jitCode->osrEntryBlock()) {
3939 if (Options::verboseOSR())
3940 dataLog("OSR entry: From ", RawPointer(jitCode), " got entry block ", RawPointer(entryBlock), "\n");
3941 if (void* address = FTL::prepareOSREntry(vm, callFrame, codeBlock, entryBlock, originBytecodeIndex, streamIndex)) {
3942 CODEBLOCK_LOG_EVENT(entryBlock, "osrEntry", ("at ", originBytecodeIndex));
3943 return retagCodePtr<char*>(address, JSEntryPtrTag, bitwise_cast<PtrTag>(callFrame));
3944 }
3945 }
3946 }
3947 }
3948
3949 if (worklistState == Worklist::Compiled) {
3950 CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("compiled and failed"));
3951 // This means that compilation failed and we already set the thresholds.
3952 if (Options::verboseOSR())
3953 dataLog("Code block ", *codeBlock, " was compiled but it doesn't have an optimized replacement.\n");
3954 return nullptr;
3955 }
3956
3957 // - If we don't have an FTL code block, then try to compile one.
3958 // - If we do have an FTL code block, then try to enter for a while.
3959 // - If we couldn't enter for a while, then trigger OSR entry.
3960
3961 if (!shouldTriggerFTLCompile(codeBlock, jitCode) && !triggeredSlowPathToStartCompilation)
3962 return nullptr;
3963
3964 if (!jitCode->neverExecutedEntry && !triggeredSlowPathToStartCompilation) {
3965 triggerFTLReplacementCompile(vm, codeBlock, jitCode);
3966
3967 if (!codeBlock->hasOptimizedReplacement())
3968 return nullptr;
3969
3970 if (jitCode->osrEntryRetry < Options::ftlOSREntryRetryThreshold()) {
3971 CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("avoiding OSR entry compile"));
3972 jitCode->osrEntryRetry++;
3973 return nullptr;
3974 }
3975 } else
3976 CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("avoiding replacement compile"));
3977
3978 if (CodeBlock* entryBlock = jitCode->osrEntryBlock()) {
3979 if (jitCode->osrEntryRetry < Options::ftlOSREntryRetryThreshold()) {
3980 CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("OSR entry failed, OSR entry threshold not met"));
3981 jitCode->osrEntryRetry++;
3982 jitCode->setOptimizationThresholdBasedOnCompilationResult(
3983 codeBlock, CompilationDeferred);
3984 return nullptr;
3985 }
3986
3987 FTL::ForOSREntryJITCode* entryCode = entryBlock->jitCode()->ftlForOSREntry();
3988 entryCode->countEntryFailure();
3989 if (entryCode->entryFailureCount() <
3990 Options::ftlOSREntryFailureCountForReoptimization()) {
3991 CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("OSR entry failed"));
3992 jitCode->setOptimizationThresholdBasedOnCompilationResult(
3993 codeBlock, CompilationDeferred);
3994 return nullptr;
3995 }
3996
3997 // OSR entry failed. Oh no! This implies that we need to retry. We retry
3998 // without exponential backoff and we only do this for the entry code block.
3999 CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("OSR entry failed too many times"));
4000 jitCode->clearOSREntryBlockAndResetThresholds(codeBlock);
4001 return nullptr;
4002 }
4003
4004 // It's time to try to compile code for OSR entry.
4005
4006 if (!triggeredSlowPathToStartCompilation) {
4007
4008 // An inner loop didn't specifically ask for us to kick off a compilation. This means the counter
4009 // crossed its threshold. We either fall through and kick off a compile for originBytecodeIndex,
4010 // or we flag an outer loop to immediately try to compile itself. If there are outer loops,
4011 // we first try to make them compile themselves. But we will eventually fall back to compiling
4012 // a progressively inner loop if it takes too long for control to reach an outer loop.
4013
4014 auto tryTriggerOuterLoopToCompile = [&] {
4015 auto tierUpHierarchyEntry = jitCode->tierUpInLoopHierarchy.find(originBytecodeIndex);
4016 if (tierUpHierarchyEntry == jitCode->tierUpInLoopHierarchy.end())
4017 return false;
4018
4019 // This vector is ordered from innermost to outermost loop. Every bytecode entry in this vector is
4020 // allowed to do OSR entry. We start with the outermost loop and make our way inwards (hence why we
4021 // iterate the vector in reverse). Our policy is that we will trigger an outer loop to compile
4022 // immediately when program control reaches it. If program control is taking too long to reach that
4023 // outer loop, we progressively move inwards, meaning, we'll eventually trigger some loop that is
4024 // executing to compile. We start with trying to compile outer loops since we believe outer loop
4025 // compilations reveal the best opportunities for optimizing code.
4026 for (auto iter = tierUpHierarchyEntry->value.rbegin(), end = tierUpHierarchyEntry->value.rend(); iter != end; ++iter) {
4027 BytecodeIndex osrEntryCandidate = *iter;
4028
4029 if (jitCode->tierUpEntryTriggers.get(osrEntryCandidate) == JITCode::TriggerReason::StartCompilation) {
4030 // This means that we already asked this loop to compile. If we've reached here, it
4031 // means program control has not yet reached that loop. So it's taking too long to compile.
4032 // So we move on to asking the inner loop of this loop to compile itself.
4033 continue;
4034 }
4035
4036 // This is where we ask the outer to loop to immediately compile itself if program
4037 // control reaches it.
4038 if (Options::verboseOSR())
4039 dataLog("Inner-loop ", originBytecodeIndex, " in ", *codeBlock, " setting parent loop ", osrEntryCandidate, "'s trigger and backing off.\n");
4040 jitCode->tierUpEntryTriggers.set(osrEntryCandidate, JITCode::TriggerReason::StartCompilation);
4041 return true;
4042 }
4043
4044 return false;
4045 };
4046
4047 if (tryTriggerOuterLoopToCompile()) {
4048 jitCode->setOptimizationThresholdBasedOnCompilationResult(codeBlock, CompilationDeferred);
4049 return nullptr;
4050 }
4051 }
4052
4053 if (!canOSREnterHere) {
4054 jitCode->setOptimizationThresholdBasedOnCompilationResult(codeBlock, CompilationDeferred);
4055 return nullptr;
4056 }
4057
4058 // We aren't compiling and haven't compiled anything for OSR entry. So, try to compile
4059 // something.
4060
4061 auto triggerIterator = jitCode->tierUpEntryTriggers.find(originBytecodeIndex);
4062 if (triggerIterator == jitCode->tierUpEntryTriggers.end()) {
4063 jitCode->setOptimizationThresholdBasedOnCompilationResult(codeBlock, CompilationDeferred);
4064 return nullptr;
4065 }
4066
4067 JITCode::TriggerReason* triggerAddress = &(triggerIterator->value);
4068
4069 Operands<Optional<JSValue>> mustHandleValues;
4070 unsigned streamIndex = jitCode->bytecodeIndexToStreamIndex.get(originBytecodeIndex);
4071 jitCode->reconstruct(callFrame, codeBlock, CodeOrigin(originBytecodeIndex), streamIndex, mustHandleValues);
4072 CodeBlock* replacementCodeBlock = codeBlock->newReplacement();
4073
4074 CODEBLOCK_LOG_EVENT(codeBlock, "triggerFTLOSR", ());
4075 CompilationResult forEntryResult = compile(
4076 vm, replacementCodeBlock, codeBlock, FTLForOSREntryMode, originBytecodeIndex,
4077 mustHandleValues, ToFTLForOSREntryDeferredCompilationCallback::create(triggerAddress));
4078
4079 if (jitCode->neverExecutedEntry)
4080 triggerFTLReplacementCompile(vm, codeBlock, jitCode);
4081
4082 if (forEntryResult != CompilationSuccessful) {
4083 CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("OSR ecompilation not successful"));
4084 jitCode->setOptimizationThresholdBasedOnCompilationResult(
4085 codeBlock, CompilationDeferred);
4086 return nullptr;
4087 }
4088
4089 CODEBLOCK_LOG_EVENT(jitCode->osrEntryBlock(), "osrEntry", ("at ", originBytecodeIndex));
4090 // It's possible that the for-entry compile already succeeded. In that case OSR
4091 // entry will succeed unless we ran out of stack. It's not clear what we should do.
4092 // We signal to try again after a while if that happens.
4093 if (Options::verboseOSR())
4094 dataLog("Immediate OSR entry: From ", RawPointer(jitCode), " got entry block ", RawPointer(jitCode->osrEntryBlock()), "\n");
4095
4096 void* address = FTL::prepareOSREntry(vm, callFrame, codeBlock, jitCode->osrEntryBlock(), originBytecodeIndex, streamIndex);
4097 if (!address)
4098 return nullptr;
4099 return retagCodePtr<char*>(address, JSEntryPtrTag, bitwise_cast<PtrTag>(callFrame));
4100}
4101
4102void JIT_OPERATION operationTriggerTierUpNowInLoop(VM* vmPointer, unsigned bytecodeIndexBits)
4103{
4104 VM& vm = *vmPointer;
4105 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
4106 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
4107 DeferGCForAWhile deferGC(vm.heap);
4108 CodeBlock* codeBlock = callFrame->codeBlock();
4109 BytecodeIndex bytecodeIndex = BytecodeIndex::fromBits(bytecodeIndexBits);
4110
4111 sanitizeStackForVM(vm);
4112
4113 if (codeBlock->jitType() != JITType::DFGJIT) {
4114 dataLog("Unexpected code block in DFG->FTL trigger tier up now in loop: ", *codeBlock, "\n");
4115 RELEASE_ASSERT_NOT_REACHED();
4116 }
4117
4118 JITCode* jitCode = codeBlock->jitCode()->dfg();
4119
4120 if (Options::verboseOSR()) {
4121 dataLog(
4122 *codeBlock, ": Entered triggerTierUpNowInLoop with executeCounter = ",
4123 jitCode->tierUpCounter, "\n");
4124 }
4125
4126 if (jitCode->tierUpInLoopHierarchy.contains(bytecodeIndex))
4127 tierUpCommon(vm, callFrame, bytecodeIndex, false);
4128 else if (shouldTriggerFTLCompile(codeBlock, jitCode))
4129 triggerFTLReplacementCompile(vm, codeBlock, jitCode);
4130
4131 // Since we cannot OSR Enter here, the default "optimizeSoon()" is not useful.
4132 if (codeBlock->hasOptimizedReplacement()) {
4133 CODEBLOCK_LOG_EVENT(codeBlock, "delayFTLCompile", ("OSR in loop failed, deferring"));
4134 jitCode->setOptimizationThresholdBasedOnCompilationResult(codeBlock, CompilationDeferred);
4135 }
4136}
4137
4138char* JIT_OPERATION operationTriggerOSREntryNow(VM* vmPointer, unsigned bytecodeIndexBits)
4139{
4140 VM& vm = *vmPointer;
4141 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
4142 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
4143 DeferGCForAWhile deferGC(vm.heap);
4144 CodeBlock* codeBlock = callFrame->codeBlock();
4145 BytecodeIndex bytecodeIndex = BytecodeIndex::fromBits(bytecodeIndexBits);
4146
4147 sanitizeStackForVM(vm);
4148
4149 if (codeBlock->jitType() != JITType::DFGJIT) {
4150 dataLog("Unexpected code block in DFG->FTL tier-up: ", *codeBlock, "\n");
4151 RELEASE_ASSERT_NOT_REACHED();
4152 }
4153
4154 JITCode* jitCode = codeBlock->jitCode()->dfg();
4155
4156 if (Options::verboseOSR()) {
4157 dataLog(
4158 *codeBlock, ": Entered triggerOSREntryNow with executeCounter = ",
4159 jitCode->tierUpCounter, "\n");
4160 }
4161
4162 return tierUpCommon(vm, callFrame, bytecodeIndex, true);
4163}
4164
4165#endif // ENABLE(FTL_JIT)
4166
4167} // extern "C"
4168} } // namespace JSC::DFG
4169
4170IGNORE_WARNINGS_END
4171
4172#endif // ENABLE(DFG_JIT)
4173
4174#endif // ENABLE(JIT)
4175