source: webkit/trunk/Source/JavaScriptCore/jit/JITOperations.cpp

Last change on this file was 295066, checked in by [email protected], 3 years ago

ASSERTION FAILED: regExp->isValid() LLIntSlowPaths.cpp(625)
https://bugs.webkit.org/show_bug.cgi?id=241107
<rdar://93369481>

Reviewed by Mark Lam.

We can remove this ASSERT(regExp->isValid()) and others like it that are used for NewRegExp
bytecode processing because subsequent code already must handle the invalid case. These code
paths may create a new RegExp or retrieve a cached RegExp. For the case where a RegExp is
created for the first time it is valid or we wouldn't have generated the NewRegExp bytecode.
This valid RegExp can subsequently be marked with an error if it fails YARR RegExp engine JIT
code or interpreter bytecode generation. Matching with a RegExp with one of these generation
errors properly throws a Syntax error. These ASSERTs fail when the NewRegExp processing
retrieves an already cached RegExp, with a generation error. The matching code will still
throw a Syntax Error.

  • JSTests/stress/regexp-late-compilation-error.js: Added.

(testRegExp1):
(testRegExp2):
(test):

  • Source/JavaScriptCore/dfg/DFGOperations.cpp:

(JSC::DFG::JSC_DEFINE_JIT_OPERATION):

  • Source/JavaScriptCore/jit/JITOperations.cpp:

(JSC::JSC_DEFINE_JIT_OPERATION):

  • Source/JavaScriptCore/llint/LLIntSlowPaths.cpp:

(JSC::LLInt::LLINT_SLOW_PATH_DECL):

Canonical link: https://commits.webkit.org/251161@main

File size: 157.0 KB
Line 
1/*
2 * Copyright (C) 2013-2022 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 "JITOperations.h"
28
29#if ENABLE(JIT)
30
31#include "ArithProfile.h"
32#include "ArrayConstructor.h"
33#include "CacheableIdentifierInlines.h"
34#include "CodeBlockInlines.h"
35#include "CommonSlowPathsInlines.h"
36#include "DFGDriver.h"
37#include "DFGOSREntry.h"
38#include "DFGThunks.h"
39#include "Debugger.h"
40#include "ExceptionFuzz.h"
41#include "FrameTracers.h"
42#include "GetterSetter.h"
43#include "ICStats.h"
44#include "Interpreter.h"
45#include "JIT.h"
46#include "JITExceptions.h"
47#include "JITToDFGDeferredCompilationCallback.h"
48#include "JITWorklist.h"
49#include "JSAsyncFunction.h"
50#include "JSAsyncGenerator.h"
51#include "JSAsyncGeneratorFunction.h"
52#include "JSCInlines.h"
53#include "JSCPtrTag.h"
54#include "JSGeneratorFunction.h"
55#include "JSGlobalObjectFunctions.h"
56#include "JSInternalPromise.h"
57#include "JSLexicalEnvironment.h"
58#include "JSRemoteFunction.h"
59#include "JSWithScope.h"
60#include "LLIntEntrypoint.h"
61#include "ObjectConstructor.h"
62#include "PropertyName.h"
63#include "RegExpObject.h"
64#include "RepatchInlines.h"
65#include "ShadowChicken.h"
66#include "StructureStubInfo.h"
67#include "SuperSampler.h"
68#include "ThunkGenerators.h"
69#include "TypeProfilerLog.h"
70#include "VMInlines.h"
71#include "VMTrapsInlines.h"
72
73IGNORE_WARNINGS_BEGIN("frame-address")
74
75namespace JSC {
76
77ALWAYS_INLINE JSValue profiledAdd(JSGlobalObject* globalObject, JSValue op1, JSValue op2, BinaryArithProfile& arithProfile)
78{
79 arithProfile.observeLHSAndRHS(op1, op2);
80 JSValue result = jsAdd(globalObject, op1, op2);
81 arithProfile.observeResult(result);
82 return result;
83}
84
85#if COMPILER(MSVC)
86extern "C" void * _ReturnAddress(void);
87#pragma intrinsic(_ReturnAddress)
88
89#define OUR_RETURN_ADDRESS _ReturnAddress()
90#else
91// FIXME (see rdar://72897291): Work around a Clang bug where __builtin_return_address()
92// sometimes gives us a signed pointer, and sometimes does not.
93#define OUR_RETURN_ADDRESS removeCodePtrTag(__builtin_return_address(0))
94#endif
95
96
97JSC_DEFINE_JIT_OPERATION(operationThrowStackOverflowError, void, (CodeBlock* codeBlock))
98{
99 // We pass in our own code block, because the callframe hasn't been populated.
100 VM& vm = codeBlock->vm();
101 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
102 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
103 auto scope = DECLARE_THROW_SCOPE(vm);
104 callFrame->convertToStackOverflowFrame(vm, codeBlock);
105 throwStackOverflowError(codeBlock->globalObject(), scope);
106}
107
108JSC_DEFINE_JIT_OPERATION(operationThrowStackOverflowErrorFromThunk, void, (JSGlobalObject* globalObject))
109{
110 VM& vm = globalObject->vm();
111 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
112 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
113 auto scope = DECLARE_THROW_SCOPE(vm);
114 throwStackOverflowError(globalObject, scope);
115 genericUnwind(vm, callFrame);
116 ASSERT(vm.targetMachinePCForThrow);
117}
118
119static JSValue getWrappedValue(JSGlobalObject* globalObject, JSGlobalObject* targetGlobalObject, JSValue value)
120{
121 VM& vm = globalObject->vm();
122 auto scope = DECLARE_THROW_SCOPE(vm);
123
124 if (!value.isObject())
125 RELEASE_AND_RETURN(scope, value);
126
127 if (value.isCallable())
128 RELEASE_AND_RETURN(scope, JSRemoteFunction::tryCreate(targetGlobalObject, vm, static_cast<JSObject*>(value.asCell())));
129
130 throwTypeError(globalObject, scope, "value passing between realms must be callable or primitive"_s);
131 return jsUndefined();
132}
133
134JSC_DEFINE_JIT_OPERATION(operationGetWrappedValueForTarget, EncodedJSValue, (JSRemoteFunction* callee, EncodedJSValue encodedValue))
135{
136 JSGlobalObject* globalObject = callee->globalObject();
137 VM& vm = globalObject->vm();
138
139 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
140 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
141 ASSERT(isRemoteFunction(callee));
142
143 JSGlobalObject* targetGlobalObject = callee->targetFunction()->globalObject();
144 return JSValue::encode(getWrappedValue(globalObject, targetGlobalObject, JSValue::decode(encodedValue)));
145}
146
147JSC_DEFINE_JIT_OPERATION(operationGetWrappedValueForCaller, EncodedJSValue, (JSRemoteFunction* callee, EncodedJSValue encodedValue))
148{
149 JSGlobalObject* globalObject = callee->globalObject();
150 VM& vm = globalObject->vm();
151
152 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
153 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
154 ASSERT(isRemoteFunction(callee));
155
156 auto scope = DECLARE_THROW_SCOPE(vm);
157
158 RELEASE_AND_RETURN(scope, JSValue::encode(getWrappedValue(globalObject, globalObject, JSValue::decode(encodedValue))));
159}
160
161JSC_DEFINE_JIT_OPERATION(operationMaterializeRemoteFunctionTargetCode, SlowPathReturnType, (JSRemoteFunction* callee))
162{
163 JSGlobalObject* globalObject = callee->globalObject();
164 VM& vm = globalObject->vm();
165
166 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
167 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
168 auto throwScope = DECLARE_THROW_SCOPE(vm);
169
170 ASSERT(isRemoteFunction(callee));
171
172 auto* targetFunction = jsCast<JSFunction*>(callee->targetFunction()); // We call this function only when JSRemoteFunction's target is JSFunction.
173 ExecutableBase* executable = targetFunction->executable();
174
175 // Force the executable to cache its arity entrypoint.
176 {
177 DeferTraps deferTraps(vm); // We can't jettison any code until after we link the call.
178 CodeBlock* codeBlockSlot = nullptr;
179 if (!executable->isHostFunction()) {
180 JSScope* scope = targetFunction->scopeUnchecked();
181 FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable);
182 functionExecutable->prepareForExecution<FunctionExecutable>(vm, targetFunction, scope, CodeForCall, codeBlockSlot);
183 RETURN_IF_EXCEPTION(throwScope, encodeResult(nullptr, nullptr));
184 }
185 return encodeResult(executable->entrypointFor(CodeForCall, MustCheckArity).executableAddress(), codeBlockSlot);
186 }
187}
188
189JSC_DEFINE_JIT_OPERATION(operationThrowRemoteFunctionException, EncodedJSValue, (JSRemoteFunction* callee))
190{
191 JSGlobalObject* globalObject = callee->globalObject();
192 VM& vm = globalObject->vm();
193
194 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
195 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
196 ASSERT(isRemoteFunction(callee));
197
198 auto scope = DECLARE_THROW_SCOPE(vm);
199 Exception* exception = scope.exception();
200
201 // We should only be here when "rethrowing" an exception
202 RELEASE_ASSERT(exception);
203
204 if (UNLIKELY(vm.isTerminationException(exception))) {
205 scope.release();
206 return { };
207 }
208
209 JSValue exceptionValue = exception->value();
210 scope.clearException();
211
212 String exceptionString = exceptionValue.toWTFString(globalObject);
213 Exception* toStringException = scope.exception();
214 if (UNLIKELY(toStringException && vm.isTerminationException(toStringException))) {
215 scope.release();
216 return { };
217 }
218 scope.clearException();
219
220 if (exceptionString.length())
221 return throwVMTypeError(globalObject, scope, exceptionString);
222
223 return throwVMTypeError(globalObject, scope);
224}
225
226JSC_DEFINE_JIT_OPERATION(operationThrowIteratorResultIsNotObject, void, (JSGlobalObject* globalObject))
227{
228 VM& vm = globalObject->vm();
229 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
230 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
231 auto scope = DECLARE_THROW_SCOPE(vm);
232
233 throwTypeError(globalObject, scope, "Iterator result interface is not an object."_s);
234}
235
236JSC_DEFINE_JIT_OPERATION(operationCallArityCheck, int32_t, (JSGlobalObject* globalObject))
237{
238 VM& vm = globalObject->vm();
239 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
240 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
241 auto scope = DECLARE_THROW_SCOPE(vm);
242
243 int32_t missingArgCount = CommonSlowPaths::arityCheckFor(vm, callFrame, CodeForCall);
244 if (UNLIKELY(missingArgCount < 0)) {
245 CodeBlock* codeBlock = CommonSlowPaths::codeBlockFromCallFrameCallee(callFrame, CodeForCall);
246 callFrame->convertToStackOverflowFrame(vm, codeBlock);
247 throwStackOverflowError(globalObject, scope);
248 }
249
250 return missingArgCount;
251}
252
253JSC_DEFINE_JIT_OPERATION(operationConstructArityCheck, int32_t, (JSGlobalObject* globalObject))
254{
255 VM& vm = globalObject->vm();
256 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
257 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
258 auto scope = DECLARE_THROW_SCOPE(vm);
259
260 int32_t missingArgCount = CommonSlowPaths::arityCheckFor(vm, callFrame, CodeForConstruct);
261 if (UNLIKELY(missingArgCount < 0)) {
262 CodeBlock* codeBlock = CommonSlowPaths::codeBlockFromCallFrameCallee(callFrame, CodeForConstruct);
263 callFrame->convertToStackOverflowFrame(vm, codeBlock);
264 throwStackOverflowError(globalObject, scope);
265 }
266
267 return missingArgCount;
268}
269
270JSC_DEFINE_JIT_OPERATION(operationTryGetById, EncodedJSValue, (JSGlobalObject* globalObject, StructureStubInfo* stubInfo, EncodedJSValue base, uintptr_t rawCacheableIdentifier))
271{
272 VM& vm = globalObject->vm();
273 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
274 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
275 CacheableIdentifier identifier = CacheableIdentifier::createFromRawBits(rawCacheableIdentifier);
276 Identifier ident = Identifier::fromUid(vm, identifier.uid());
277 stubInfo->tookSlowPath = true;
278
279 JSValue baseValue = JSValue::decode(base);
280 PropertySlot slot(baseValue, PropertySlot::InternalMethodType::VMInquiry, &vm);
281 baseValue.getPropertySlot(globalObject, ident, slot);
282
283 return JSValue::encode(slot.getPureResult());
284}
285
286
287JSC_DEFINE_JIT_OPERATION(operationTryGetByIdGeneric, EncodedJSValue, (JSGlobalObject* globalObject, EncodedJSValue base, uintptr_t rawCacheableIdentifier))
288{
289 VM& vm = globalObject->vm();
290 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
291 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
292 CacheableIdentifier identifier = CacheableIdentifier::createFromRawBits(rawCacheableIdentifier);
293 Identifier ident = Identifier::fromUid(vm, identifier.uid());
294
295 JSValue baseValue = JSValue::decode(base);
296 PropertySlot slot(baseValue, PropertySlot::InternalMethodType::VMInquiry, &vm);
297 baseValue.getPropertySlot(globalObject, ident, slot);
298
299 return JSValue::encode(slot.getPureResult());
300}
301
302JSC_DEFINE_JIT_OPERATION(operationTryGetByIdOptimize, EncodedJSValue, (JSGlobalObject* globalObject, StructureStubInfo* stubInfo, EncodedJSValue base, uintptr_t rawCacheableIdentifier))
303{
304 VM& vm = globalObject->vm();
305 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
306 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
307 auto scope = DECLARE_THROW_SCOPE(vm);
308 CacheableIdentifier identifier = CacheableIdentifier::createFromRawBits(rawCacheableIdentifier);
309 Identifier ident = Identifier::fromUid(vm, identifier.uid());
310
311 JSValue baseValue = JSValue::decode(base);
312 PropertySlot slot(baseValue, PropertySlot::InternalMethodType::VMInquiry, &vm);
313
314 baseValue.getPropertySlot(globalObject, ident, slot);
315 RETURN_IF_EXCEPTION(scope, encodedJSValue());
316
317 CodeBlock* codeBlock = callFrame->codeBlock();
318 if (stubInfo->considerCachingBy(vm, codeBlock, baseValue.structureOrNull(), identifier) && !slot.isTaintedByOpaqueObject() && (slot.isCacheableValue() || slot.isCacheableGetter() || slot.isUnset()))
319 repatchGetBy(globalObject, codeBlock, baseValue, identifier, slot, *stubInfo, GetByKind::TryById);
320
321 return JSValue::encode(slot.getPureResult());
322}
323
324JSC_DEFINE_JIT_OPERATION(operationGetByIdDirect, EncodedJSValue, (JSGlobalObject* globalObject, StructureStubInfo* stubInfo, EncodedJSValue base, uintptr_t rawCacheableIdentifier))
325{
326 VM& vm = globalObject->vm();
327 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
328 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
329 auto scope = DECLARE_THROW_SCOPE(vm);
330 CacheableIdentifier identifier = CacheableIdentifier::createFromRawBits(rawCacheableIdentifier);
331 Identifier ident = Identifier::fromUid(vm, identifier.uid());
332 stubInfo->tookSlowPath = true;
333
334 JSValue baseValue = JSValue::decode(base);
335 PropertySlot slot(baseValue, PropertySlot::InternalMethodType::GetOwnProperty);
336
337 bool found = baseValue.getOwnPropertySlot(globalObject, ident, slot);
338 RETURN_IF_EXCEPTION(scope, encodedJSValue());
339
340 RELEASE_AND_RETURN(scope, JSValue::encode(found ? slot.getValue(globalObject, ident) : jsUndefined()));
341}
342
343JSC_DEFINE_JIT_OPERATION(operationGetByIdDirectGeneric, EncodedJSValue, (JSGlobalObject* globalObject, EncodedJSValue base, uintptr_t rawCacheableIdentifier))
344{
345 VM& vm = globalObject->vm();
346 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
347 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
348 auto scope = DECLARE_THROW_SCOPE(vm);
349 CacheableIdentifier identifier = CacheableIdentifier::createFromRawBits(rawCacheableIdentifier);
350 Identifier ident = Identifier::fromUid(vm, identifier.uid());
351
352 JSValue baseValue = JSValue::decode(base);
353 PropertySlot slot(baseValue, PropertySlot::InternalMethodType::GetOwnProperty);
354
355 bool found = baseValue.getOwnPropertySlot(globalObject, ident, slot);
356 RETURN_IF_EXCEPTION(scope, encodedJSValue());
357
358 RELEASE_AND_RETURN(scope, JSValue::encode(found ? slot.getValue(globalObject, ident) : jsUndefined()));
359}
360
361JSC_DEFINE_JIT_OPERATION(operationGetByIdDirectOptimize, EncodedJSValue, (JSGlobalObject* globalObject, StructureStubInfo* stubInfo, EncodedJSValue base, uintptr_t rawCacheableIdentifier))
362{
363 VM& vm = globalObject->vm();
364 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
365 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
366 auto scope = DECLARE_THROW_SCOPE(vm);
367 CacheableIdentifier identifier = CacheableIdentifier::createFromRawBits(rawCacheableIdentifier);
368 Identifier ident = Identifier::fromUid(vm, identifier.uid());
369
370 JSValue baseValue = JSValue::decode(base);
371 PropertySlot slot(baseValue, PropertySlot::InternalMethodType::GetOwnProperty);
372
373 bool found = baseValue.getOwnPropertySlot(globalObject, ident, slot);
374 RETURN_IF_EXCEPTION(scope, encodedJSValue());
375
376 CodeBlock* codeBlock = callFrame->codeBlock();
377 if (stubInfo->considerCachingBy(vm, codeBlock, baseValue.structureOrNull(), identifier))
378 repatchGetBy(globalObject, codeBlock, baseValue, identifier, slot, *stubInfo, GetByKind::ByIdDirect);
379
380 RELEASE_AND_RETURN(scope, JSValue::encode(found ? slot.getValue(globalObject, ident) : jsUndefined()));
381}
382
383JSC_DEFINE_JIT_OPERATION(operationGetById, EncodedJSValue, (JSGlobalObject* globalObject, StructureStubInfo* stubInfo, EncodedJSValue base, uintptr_t rawCacheableIdentifier))
384{
385 SuperSamplerScope superSamplerScope(false);
386
387 VM& vm = globalObject->vm();
388 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
389 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
390
391 stubInfo->tookSlowPath = true;
392
393 JSValue baseValue = JSValue::decode(base);
394 PropertySlot slot(baseValue, PropertySlot::InternalMethodType::Get);
395 CacheableIdentifier identifier = CacheableIdentifier::createFromRawBits(rawCacheableIdentifier);
396 Identifier ident = Identifier::fromUid(vm, identifier.uid());
397 JSValue result = baseValue.get(globalObject, ident, slot);
398
399 LOG_IC((ICEvent::OperationGetById, baseValue.classInfoOrNull(), ident, baseValue == slot.slotBase()));
400
401 return JSValue::encode(result);
402}
403
404JSC_DEFINE_JIT_OPERATION(operationGetByIdGeneric, EncodedJSValue, (JSGlobalObject* globalObject, EncodedJSValue base, uintptr_t rawCacheableIdentifier))
405{
406 SuperSamplerScope superSamplerScope(false);
407
408 VM& vm = globalObject->vm();
409 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
410 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
411
412 JSValue baseValue = JSValue::decode(base);
413 PropertySlot slot(baseValue, PropertySlot::InternalMethodType::Get);
414 CacheableIdentifier identifier = CacheableIdentifier::createFromRawBits(rawCacheableIdentifier);
415 Identifier ident = Identifier::fromUid(vm, identifier.uid());
416 JSValue result = baseValue.get(globalObject, ident, slot);
417
418 LOG_IC((ICEvent::OperationGetByIdGeneric, baseValue.classInfoOrNull(), ident, baseValue == slot.slotBase()));
419
420 return JSValue::encode(result);
421}
422
423JSC_DEFINE_JIT_OPERATION(operationGetByIdOptimize, EncodedJSValue, (JSGlobalObject* globalObject, StructureStubInfo* stubInfo, EncodedJSValue base, uintptr_t rawCacheableIdentifier))
424{
425 SuperSamplerScope superSamplerScope(false);
426
427 VM& vm = globalObject->vm();
428 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
429 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
430 CacheableIdentifier identifier = CacheableIdentifier::createFromRawBits(rawCacheableIdentifier);
431 Identifier ident = Identifier::fromUid(vm, identifier.uid());
432
433 JSValue baseValue = JSValue::decode(base);
434
435 return JSValue::encode(baseValue.getPropertySlot(globalObject, ident, [&] (bool found, PropertySlot& slot) -> JSValue {
436
437 LOG_IC((ICEvent::OperationGetByIdOptimize, baseValue.classInfoOrNull(), ident, baseValue == slot.slotBase()));
438
439 CodeBlock* codeBlock = callFrame->codeBlock();
440 if (stubInfo->considerCachingBy(vm, codeBlock, baseValue.structureOrNull(), identifier))
441 repatchGetBy(globalObject, codeBlock, baseValue, identifier, slot, *stubInfo, GetByKind::ById);
442 return found ? slot.getValue(globalObject, ident) : jsUndefined();
443 }));
444}
445
446JSC_DEFINE_JIT_OPERATION(operationGetByIdWithThis, EncodedJSValue, (JSGlobalObject* globalObject, StructureStubInfo* stubInfo, EncodedJSValue base, EncodedJSValue thisEncoded, uintptr_t rawCacheableIdentifier))
447{
448 SuperSamplerScope superSamplerScope(false);
449
450 VM& vm = globalObject->vm();
451 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
452 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
453 CacheableIdentifier identifier = CacheableIdentifier::createFromRawBits(rawCacheableIdentifier);
454 Identifier ident = Identifier::fromUid(vm, identifier.uid());
455
456 stubInfo->tookSlowPath = true;
457
458 JSValue baseValue = JSValue::decode(base);
459 JSValue thisValue = JSValue::decode(thisEncoded);
460 PropertySlot slot(thisValue, PropertySlot::InternalMethodType::Get);
461
462 return JSValue::encode(baseValue.get(globalObject, ident, slot));
463}
464
465JSC_DEFINE_JIT_OPERATION(operationGetByIdWithThisGeneric, EncodedJSValue, (JSGlobalObject* globalObject, EncodedJSValue base, EncodedJSValue thisEncoded, uintptr_t rawCacheableIdentifier))
466{
467 SuperSamplerScope superSamplerScope(false);
468
469 VM& vm = globalObject->vm();
470 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
471 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
472 CacheableIdentifier identifier = CacheableIdentifier::createFromRawBits(rawCacheableIdentifier);
473 Identifier ident = Identifier::fromUid(vm, identifier.uid());
474
475 JSValue baseValue = JSValue::decode(base);
476 JSValue thisValue = JSValue::decode(thisEncoded);
477 PropertySlot slot(thisValue, PropertySlot::InternalMethodType::Get);
478
479 return JSValue::encode(baseValue.get(globalObject, ident, slot));
480}
481
482JSC_DEFINE_JIT_OPERATION(operationGetByIdWithThisOptimize, EncodedJSValue, (JSGlobalObject* globalObject, StructureStubInfo* stubInfo, EncodedJSValue base, EncodedJSValue thisEncoded, uintptr_t rawCacheableIdentifier))
483{
484 SuperSamplerScope superSamplerScope(false);
485
486 VM& vm = globalObject->vm();
487 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
488 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
489 CacheableIdentifier identifier = CacheableIdentifier::createFromRawBits(rawCacheableIdentifier);
490 Identifier ident = Identifier::fromUid(vm, identifier.uid());
491
492 JSValue baseValue = JSValue::decode(base);
493 JSValue thisValue = JSValue::decode(thisEncoded);
494
495 PropertySlot slot(thisValue, PropertySlot::InternalMethodType::Get);
496 return JSValue::encode(baseValue.getPropertySlot(globalObject, ident, slot, [&] (bool found, PropertySlot& slot) -> JSValue {
497 LOG_IC((ICEvent::OperationGetByIdWithThisOptimize, baseValue.classInfoOrNull(), ident, baseValue == slot.slotBase()));
498
499 CodeBlock* codeBlock = callFrame->codeBlock();
500 if (stubInfo->considerCachingBy(vm, codeBlock, baseValue.structureOrNull(), identifier))
501 repatchGetBy(globalObject, codeBlock, baseValue, identifier, slot, *stubInfo, GetByKind::ByIdWithThis);
502 return found ? slot.getValue(globalObject, ident) : jsUndefined();
503 }));
504}
505
506JSC_DEFINE_JIT_OPERATION(operationInByIdGeneric, EncodedJSValue, (JSGlobalObject* globalObject, StructureStubInfo* stubInfo, EncodedJSValue base, uintptr_t rawCacheableIdentifier))
507{
508 SuperSamplerScope superSamplerScope(false);
509
510 VM& vm = globalObject->vm();
511 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
512 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
513 auto scope = DECLARE_THROW_SCOPE(vm);
514
515 stubInfo->tookSlowPath = true;
516
517 CacheableIdentifier identifier = CacheableIdentifier::createFromRawBits(rawCacheableIdentifier);
518 Identifier ident = Identifier::fromUid(vm, identifier.uid());
519
520 JSValue baseValue = JSValue::decode(base);
521 if (!baseValue.isObject()) {
522 throwException(globalObject, scope, createInvalidInParameterError(globalObject, baseValue));
523 return JSValue::encode(jsUndefined());
524 }
525 JSObject* baseObject = asObject(baseValue);
526
527 LOG_IC((ICEvent::OperationInByIdGeneric, baseObject->classInfo(), ident));
528
529 scope.release();
530 PropertySlot slot(baseObject, PropertySlot::InternalMethodType::HasProperty);
531 return JSValue::encode(jsBoolean(baseObject->getPropertySlot(globalObject, ident, slot)));
532}
533
534JSC_DEFINE_JIT_OPERATION(operationInByIdOptimize, EncodedJSValue, (JSGlobalObject* globalObject, StructureStubInfo* stubInfo, EncodedJSValue base, uintptr_t rawCacheableIdentifier))
535{
536 SuperSamplerScope superSamplerScope(false);
537
538 VM& vm = globalObject->vm();
539 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
540 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
541 auto scope = DECLARE_THROW_SCOPE(vm);
542
543 CacheableIdentifier identifier = CacheableIdentifier::createFromRawBits(rawCacheableIdentifier);
544 Identifier ident = Identifier::fromUid(vm, identifier.uid());
545
546 JSValue baseValue = JSValue::decode(base);
547 if (!baseValue.isObject()) {
548 throwException(globalObject, scope, createInvalidInParameterError(globalObject, baseValue));
549 return JSValue::encode(jsUndefined());
550 }
551 JSObject* baseObject = asObject(baseValue);
552
553 LOG_IC((ICEvent::OperationInByIdOptimize, baseObject->classInfo(), ident));
554
555 scope.release();
556 PropertySlot slot(baseObject, PropertySlot::InternalMethodType::HasProperty);
557 bool found = baseObject->getPropertySlot(globalObject, ident, slot);
558 CodeBlock* codeBlock = callFrame->codeBlock();
559 if (stubInfo->considerCachingBy(vm, codeBlock, baseObject->structure(), identifier))
560 repatchInBy(globalObject, codeBlock, baseObject, identifier, found, slot, *stubInfo, InByKind::ById);
561 return JSValue::encode(jsBoolean(found));
562}
563
564JSC_DEFINE_JIT_OPERATION(operationInByValOptimize, EncodedJSValue, (JSGlobalObject* globalObject, StructureStubInfo* stubInfo, ArrayProfile* arrayProfile, EncodedJSValue encodedBase, EncodedJSValue encodedKey))
565{
566 SuperSamplerScope superSamplerScope(false);
567
568 VM& vm = globalObject->vm();
569 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
570 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
571 auto scope = DECLARE_THROW_SCOPE(vm);
572
573 JSValue baseValue = JSValue::decode(encodedBase);
574 if (!baseValue.isObject()) {
575 throwException(globalObject, scope, createInvalidInParameterError(globalObject, baseValue));
576 return encodedJSValue();
577 }
578 JSObject* baseObject = asObject(baseValue);
579 if (arrayProfile)
580 arrayProfile->observeStructure(baseObject->structure());
581
582 JSValue key = JSValue::decode(encodedKey);
583 uint32_t i;
584 if (key.getUInt32(i)) {
585 // FIXME: InByVal should have inline caching for integer indices too, as GetByVal does.
586 // https://bugs.webkit.org/show_bug.cgi?id=226619
587 if (arrayProfile)
588 arrayProfile->observeIndexedRead(baseObject, i);
589 RELEASE_AND_RETURN(scope, JSValue::encode(jsBoolean(baseObject->hasProperty(globalObject, i))));
590 }
591
592 const Identifier propertyName = key.toPropertyKey(globalObject);
593 RETURN_IF_EXCEPTION(scope, encodedJSValue());
594 PropertySlot slot(baseObject, PropertySlot::InternalMethodType::HasProperty);
595 bool found = baseObject->getPropertySlot(globalObject, propertyName, slot);
596 RETURN_IF_EXCEPTION(scope, encodedJSValue());
597
598 if (CacheableIdentifier::isCacheableIdentifierCell(key) && (key.isSymbol() || !parseIndex(propertyName))) {
599 CodeBlock* codeBlock = callFrame->codeBlock();
600 CacheableIdentifier identifier = CacheableIdentifier::createFromCell(key.asCell());
601 if (stubInfo->considerCachingBy(vm, codeBlock, baseObject->structure(), identifier))
602 repatchInBy(globalObject, codeBlock, baseObject, identifier, found, slot, *stubInfo, InByKind::ByVal);
603 }
604
605 return JSValue::encode(jsBoolean(found));
606}
607
608JSC_DEFINE_JIT_OPERATION(operationInByValGeneric, EncodedJSValue, (JSGlobalObject* globalObject, StructureStubInfo* stubInfo, ArrayProfile* arrayProfile, EncodedJSValue base, EncodedJSValue key))
609{
610 SuperSamplerScope superSamplerScope(false);
611
612 VM& vm = globalObject->vm();
613 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
614 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
615
616 stubInfo->tookSlowPath = true;
617 return JSValue::encode(jsBoolean(CommonSlowPaths::opInByVal(globalObject, JSValue::decode(base), JSValue::decode(key), arrayProfile)));
618}
619
620JSC_DEFINE_JIT_OPERATION(operationHasPrivateNameOptimize, EncodedJSValue, (JSGlobalObject* globalObject, StructureStubInfo* stubInfo, EncodedJSValue encodedBase, EncodedJSValue encodedProperty))
621{
622 SuperSamplerScope superSamplerScope(false);
623
624 VM& vm = globalObject->vm();
625 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
626 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
627 auto scope = DECLARE_THROW_SCOPE(vm);
628
629 JSValue baseValue = JSValue::decode(encodedBase);
630 if (!baseValue.isObject()) {
631 throwException(globalObject, scope, createInvalidInParameterError(globalObject, baseValue));
632 return encodedJSValue();
633 }
634 JSObject* baseObject = asObject(baseValue);
635
636 JSValue propertyValue = JSValue::decode(encodedProperty);
637 ASSERT(propertyValue.isSymbol());
638 auto property = propertyValue.toPropertyKey(globalObject);
639 RETURN_IF_EXCEPTION(scope, { });
640
641 PropertySlot slot(baseObject, PropertySlot::InternalMethodType::HasProperty);
642 bool found = JSObject::getPrivateFieldSlot(baseObject, globalObject, property, slot);
643
644 ASSERT(CacheableIdentifier::isCacheableIdentifierCell(propertyValue));
645 CodeBlock* codeBlock = callFrame->codeBlock();
646 CacheableIdentifier identifier = CacheableIdentifier::createFromCell(propertyValue.asCell());
647 if (stubInfo->considerCachingBy(vm, codeBlock, baseObject->structure(), identifier))
648 repatchInBy(globalObject, codeBlock, baseObject, identifier, found, slot, *stubInfo, InByKind::PrivateName);
649
650 return JSValue::encode(jsBoolean(found));
651}
652
653JSC_DEFINE_JIT_OPERATION(operationHasPrivateNameGeneric, EncodedJSValue, (JSGlobalObject* globalObject, StructureStubInfo* stubInfo, EncodedJSValue encodedBase, EncodedJSValue encodedProperty))
654{
655 SuperSamplerScope superSamplerScope(false);
656
657 VM& vm = globalObject->vm();
658 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
659 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
660 auto scope = DECLARE_THROW_SCOPE(vm);
661
662 stubInfo->tookSlowPath = true;
663
664 JSValue baseValue = JSValue::decode(encodedBase);
665 if (!baseValue.isObject()) {
666 throwException(globalObject, scope, createInvalidInParameterError(globalObject, baseValue));
667 return encodedJSValue();
668 }
669
670 JSValue propertyValue = JSValue::decode(encodedProperty);
671 ASSERT(propertyValue.isSymbol());
672 auto property = propertyValue.toPropertyKey(globalObject);
673 RETURN_IF_EXCEPTION(scope, { });
674
675 return JSValue::encode(jsBoolean(asObject(baseValue)->hasPrivateField(globalObject, property)));
676}
677
678JSC_DEFINE_JIT_OPERATION(operationHasPrivateBrandOptimize, EncodedJSValue, (JSGlobalObject* globalObject, StructureStubInfo* stubInfo, EncodedJSValue encodedBase, EncodedJSValue encodedBrand))
679{
680 SuperSamplerScope superSamplerScope(false);
681
682 VM& vm = globalObject->vm();
683 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
684 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
685 auto scope = DECLARE_THROW_SCOPE(vm);
686
687 JSValue baseValue = JSValue::decode(encodedBase);
688 if (!baseValue.isObject()) {
689 throwException(globalObject, scope, createInvalidInParameterError(globalObject, baseValue));
690 return encodedJSValue();
691 }
692 JSObject* baseObject = asObject(baseValue);
693
694 JSValue brand = JSValue::decode(encodedBrand);
695 bool found = asObject(baseValue)->hasPrivateBrand(globalObject, brand);
696
697 ASSERT(CacheableIdentifier::isCacheableIdentifierCell(brand));
698 CodeBlock* codeBlock = callFrame->codeBlock();
699 CacheableIdentifier identifier = CacheableIdentifier::createFromCell(brand.asCell());
700 if (stubInfo->considerCachingBy(vm, codeBlock, baseObject->structure(), identifier))
701 repatchHasPrivateBrand(globalObject, codeBlock, baseObject, identifier, found, *stubInfo);
702
703 return JSValue::encode(jsBoolean(found));
704}
705
706JSC_DEFINE_JIT_OPERATION(operationHasPrivateBrandGeneric, EncodedJSValue, (JSGlobalObject* globalObject, StructureStubInfo* stubInfo, EncodedJSValue encodedBase, EncodedJSValue encodedBrand))
707{
708 SuperSamplerScope superSamplerScope(false);
709
710 VM& vm = globalObject->vm();
711 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
712 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
713 auto scope = DECLARE_THROW_SCOPE(vm);
714
715 stubInfo->tookSlowPath = true;
716
717 JSValue baseValue = JSValue::decode(encodedBase);
718 if (!baseValue.isObject()) {
719 throwException(globalObject, scope, createInvalidInParameterError(globalObject, baseValue));
720 return encodedJSValue();
721 }
722
723 return JSValue::encode(jsBoolean(asObject(baseValue)->hasPrivateBrand(globalObject, JSValue::decode(encodedBrand))));
724}
725
726JSC_DEFINE_JIT_OPERATION(operationPutByIdStrict, void, (JSGlobalObject* globalObject, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, uintptr_t rawCacheableIdentifier))
727{
728 SuperSamplerScope superSamplerScope(false);
729
730 VM& vm = globalObject->vm();
731 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
732 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
733
734 stubInfo->tookSlowPath = true;
735
736 JSValue baseValue = JSValue::decode(encodedBase);
737 CacheableIdentifier identifier = CacheableIdentifier::createFromRawBits(rawCacheableIdentifier);
738 Identifier ident = Identifier::fromUid(vm, identifier.uid());
739 PutPropertySlot slot(baseValue, true, callFrame->codeBlock()->putByIdContext());
740 baseValue.putInline(globalObject, ident, JSValue::decode(encodedValue), slot);
741
742 LOG_IC((ICEvent::OperationPutByIdStrict, baseValue.classInfoOrNull(), ident, slot.base() == baseValue));
743}
744
745JSC_DEFINE_JIT_OPERATION(operationPutByIdNonStrict, void, (JSGlobalObject* globalObject, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, uintptr_t rawCacheableIdentifier))
746{
747 SuperSamplerScope superSamplerScope(false);
748
749 VM& vm = globalObject->vm();
750 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
751 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
752
753 stubInfo->tookSlowPath = true;
754
755 JSValue baseValue = JSValue::decode(encodedBase);
756 CacheableIdentifier identifier = CacheableIdentifier::createFromRawBits(rawCacheableIdentifier);
757 Identifier ident = Identifier::fromUid(vm, identifier.uid());
758 PutPropertySlot slot(baseValue, false, callFrame->codeBlock()->putByIdContext());
759 baseValue.putInline(globalObject, ident, JSValue::decode(encodedValue), slot);
760
761 LOG_IC((ICEvent::OperationPutByIdNonStrict, baseValue.classInfoOrNull(), ident, slot.base() == baseValue));
762}
763
764JSC_DEFINE_JIT_OPERATION(operationPutByIdDirectStrict, void, (JSGlobalObject* globalObject, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, uintptr_t rawCacheableIdentifier))
765{
766 SuperSamplerScope superSamplerScope(false);
767
768 VM& vm = globalObject->vm();
769 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
770 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
771
772 stubInfo->tookSlowPath = true;
773
774 JSValue baseValue = JSValue::decode(encodedBase);
775 CacheableIdentifier identifier = CacheableIdentifier::createFromRawBits(rawCacheableIdentifier);
776 Identifier ident = Identifier::fromUid(vm, identifier.uid());
777 PutPropertySlot slot(baseValue, true, callFrame->codeBlock()->putByIdContext());
778 CommonSlowPaths::putDirectWithReify(vm, globalObject, asObject(baseValue), ident, JSValue::decode(encodedValue), slot);
779
780 LOG_IC((ICEvent::OperationPutByIdDirectStrict, baseValue.classInfoOrNull(), ident, slot.base() == baseValue));
781}
782
783JSC_DEFINE_JIT_OPERATION(operationPutByIdDirectNonStrict, void, (JSGlobalObject* globalObject, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, uintptr_t rawCacheableIdentifier))
784{
785 SuperSamplerScope superSamplerScope(false);
786
787 VM& vm = globalObject->vm();
788 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
789 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
790
791 stubInfo->tookSlowPath = true;
792
793 JSValue baseValue = JSValue::decode(encodedBase);
794 CacheableIdentifier identifier = CacheableIdentifier::createFromRawBits(rawCacheableIdentifier);
795 Identifier ident = Identifier::fromUid(vm, identifier.uid());
796 PutPropertySlot slot(baseValue, false, callFrame->codeBlock()->putByIdContext());
797 CommonSlowPaths::putDirectWithReify(vm, globalObject, asObject(baseValue), ident, JSValue::decode(encodedValue), slot);
798
799 LOG_IC((ICEvent::OperationPutByIdDirectNonStrict, baseValue.classInfoOrNull(), ident, slot.base() == baseValue));
800}
801
802JSC_DEFINE_JIT_OPERATION(operationPutByIdStrictOptimize, void, (JSGlobalObject* globalObject, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, uintptr_t rawCacheableIdentifier))
803{
804 SuperSamplerScope superSamplerScope(false);
805
806 VM& vm = globalObject->vm();
807 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
808 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
809 auto scope = DECLARE_THROW_SCOPE(vm);
810
811 CacheableIdentifier identifier = CacheableIdentifier::createFromRawBits(rawCacheableIdentifier);
812 Identifier ident = Identifier::fromUid(vm, identifier.uid());
813 AccessType accessType = static_cast<AccessType>(stubInfo->accessType);
814
815 JSValue value = JSValue::decode(encodedValue);
816 JSValue baseValue = JSValue::decode(encodedBase);
817 CodeBlock* codeBlock = callFrame->codeBlock();
818 PutPropertySlot slot(baseValue, true, codeBlock->putByIdContext());
819
820 Structure* structure = CommonSlowPaths::originalStructureBeforePut(baseValue);
821 baseValue.putInline(globalObject, ident, value, slot);
822
823 LOG_IC((ICEvent::OperationPutByIdStrictOptimize, baseValue.classInfoOrNull(), ident, slot.base() == baseValue));
824
825 RETURN_IF_EXCEPTION(scope, void());
826
827 if (accessType != static_cast<AccessType>(stubInfo->accessType))
828 return;
829
830 if (stubInfo->considerCachingBy(vm, codeBlock, structure, identifier))
831 repatchPutBy(globalObject, codeBlock, baseValue, structure, identifier, slot, *stubInfo, PutByKind::ById, PutKind::NotDirect);
832}
833
834JSC_DEFINE_JIT_OPERATION(operationPutByIdNonStrictOptimize, void, (JSGlobalObject* globalObject, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, uintptr_t rawCacheableIdentifier))
835{
836 SuperSamplerScope superSamplerScope(false);
837
838 VM& vm = globalObject->vm();
839 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
840 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
841 auto scope = DECLARE_THROW_SCOPE(vm);
842
843 CacheableIdentifier identifier = CacheableIdentifier::createFromRawBits(rawCacheableIdentifier);
844 Identifier ident = Identifier::fromUid(vm, identifier.uid());
845 AccessType accessType = static_cast<AccessType>(stubInfo->accessType);
846
847 JSValue value = JSValue::decode(encodedValue);
848 JSValue baseValue = JSValue::decode(encodedBase);
849 CodeBlock* codeBlock = callFrame->codeBlock();
850 PutPropertySlot slot(baseValue, false, codeBlock->putByIdContext());
851
852 Structure* structure = CommonSlowPaths::originalStructureBeforePut(baseValue);
853 baseValue.putInline(globalObject, ident, value, slot);
854
855 LOG_IC((ICEvent::OperationPutByIdNonStrictOptimize, baseValue.classInfoOrNull(), ident, slot.base() == baseValue));
856
857 RETURN_IF_EXCEPTION(scope, void());
858
859 if (accessType != static_cast<AccessType>(stubInfo->accessType))
860 return;
861
862 if (stubInfo->considerCachingBy(vm, codeBlock, structure, identifier))
863 repatchPutBy(globalObject, codeBlock, baseValue, structure, identifier, slot, *stubInfo, PutByKind::ById, PutKind::NotDirect);
864}
865
866JSC_DEFINE_JIT_OPERATION(operationPutByIdDirectStrictOptimize, void, (JSGlobalObject* globalObject, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, uintptr_t rawCacheableIdentifier))
867{
868 SuperSamplerScope superSamplerScope(false);
869
870 VM& vm = globalObject->vm();
871 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
872 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
873 auto scope = DECLARE_THROW_SCOPE(vm);
874
875 CacheableIdentifier identifier = CacheableIdentifier::createFromRawBits(rawCacheableIdentifier);
876 Identifier ident = Identifier::fromUid(vm, identifier.uid());
877 AccessType accessType = static_cast<AccessType>(stubInfo->accessType);
878
879 JSValue value = JSValue::decode(encodedValue);
880 JSObject* baseObject = asObject(JSValue::decode(encodedBase));
881 CodeBlock* codeBlock = callFrame->codeBlock();
882 PutPropertySlot slot(baseObject, true, codeBlock->putByIdContext());
883 Structure* structure = nullptr;
884 CommonSlowPaths::putDirectWithReify(vm, globalObject, baseObject, ident, value, slot, &structure);
885
886 LOG_IC((ICEvent::OperationPutByIdDirectStrictOptimize, baseObject->classInfo(), ident, slot.base() == baseObject));
887
888 RETURN_IF_EXCEPTION(scope, void());
889
890 if (accessType != static_cast<AccessType>(stubInfo->accessType))
891 return;
892
893 if (stubInfo->considerCachingBy(vm, codeBlock, structure, identifier))
894 repatchPutBy(globalObject, codeBlock, baseObject, structure, identifier, slot, *stubInfo, PutByKind::ById, PutKind::Direct);
895}
896
897JSC_DEFINE_JIT_OPERATION(operationPutByIdDirectNonStrictOptimize, void, (JSGlobalObject* globalObject, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, uintptr_t rawCacheableIdentifier))
898{
899 SuperSamplerScope superSamplerScope(false);
900
901 VM& vm = globalObject->vm();
902 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
903 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
904 auto scope = DECLARE_THROW_SCOPE(vm);
905
906 CacheableIdentifier identifier = CacheableIdentifier::createFromRawBits(rawCacheableIdentifier);
907 Identifier ident = Identifier::fromUid(vm, identifier.uid());
908 AccessType accessType = static_cast<AccessType>(stubInfo->accessType);
909
910 JSValue value = JSValue::decode(encodedValue);
911 JSObject* baseObject = asObject(JSValue::decode(encodedBase));
912 CodeBlock* codeBlock = callFrame->codeBlock();
913 PutPropertySlot slot(baseObject, false, codeBlock->putByIdContext());
914 Structure* structure = nullptr;
915 CommonSlowPaths::putDirectWithReify(vm, globalObject, baseObject, ident, value, slot, &structure);
916
917 LOG_IC((ICEvent::OperationPutByIdDirectNonStrictOptimize, baseObject->classInfo(), ident, slot.base() == baseObject));
918
919 RETURN_IF_EXCEPTION(scope, void());
920
921 if (accessType != static_cast<AccessType>(stubInfo->accessType))
922 return;
923
924 if (stubInfo->considerCachingBy(vm, codeBlock, structure, identifier))
925 repatchPutBy(globalObject, codeBlock, baseObject, structure, identifier, slot, *stubInfo, PutByKind::ById, PutKind::Direct);
926}
927
928template<typename PutPrivateFieldCallback>
929ALWAYS_INLINE static void setPrivateField(VM& vm, JSGlobalObject* globalObject, CallFrame* callFrame, JSValue baseValue, CacheableIdentifier identifier, JSValue value, PutPrivateFieldCallback callback)
930{
931 auto scope = DECLARE_THROW_SCOPE(vm);
932
933 Identifier ident = Identifier::fromUid(vm, identifier.uid());
934 ASSERT(ident.isPrivateName());
935
936 JSObject* baseObject = baseValue.toObject(globalObject);
937 RETURN_IF_EXCEPTION(scope, void());
938 CodeBlock* codeBlock = callFrame->codeBlock();
939 Structure* oldStructure = baseObject->structure();
940
941 PutPropertySlot putSlot(baseObject, true, codeBlock->putByIdContext());
942 baseObject->setPrivateField(globalObject, ident, value, putSlot);
943 RETURN_IF_EXCEPTION(scope, void());
944
945 callback(vm, codeBlock, oldStructure, putSlot, ident);
946}
947
948template<typename PutPrivateFieldCallback>
949ALWAYS_INLINE static void definePrivateField(VM& vm, JSGlobalObject* globalObject, CallFrame* callFrame, JSValue baseValue, CacheableIdentifier identifier, JSValue value, PutPrivateFieldCallback callback)
950{
951 auto scope = DECLARE_THROW_SCOPE(vm);
952
953 Identifier ident = Identifier::fromUid(vm, identifier.uid());
954 ASSERT(ident.isPrivateName());
955
956 JSObject* baseObject = baseValue.toObject(globalObject);
957 RETURN_IF_EXCEPTION(scope, void());
958 CodeBlock* codeBlock = callFrame->codeBlock();
959 Structure* oldStructure = baseObject->structure();
960
961 PutPropertySlot putSlot(baseObject, true, codeBlock->putByIdContext());
962 baseObject->definePrivateField(globalObject, ident, value, putSlot);
963 RETURN_IF_EXCEPTION(scope, void());
964
965 callback(vm, codeBlock, oldStructure, putSlot, ident);
966}
967
968JSC_DEFINE_JIT_OPERATION(operationPutByIdDefinePrivateFieldStrict, void, (JSGlobalObject* globalObject, StructureStubInfo*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, uintptr_t rawCacheableIdentifier))
969{
970 VM& vm = globalObject->vm();
971 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
972 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
973
974 CacheableIdentifier identifier = CacheableIdentifier::createFromRawBits(rawCacheableIdentifier);
975 JSValue value = JSValue::decode(encodedValue);
976 JSValue baseValue = JSValue::decode(encodedBase);
977
978 definePrivateField(vm, globalObject, callFrame, baseValue, identifier, value, [](VM&, CodeBlock*, Structure*, PutPropertySlot&, const Identifier&) { });
979}
980
981JSC_DEFINE_JIT_OPERATION(operationPutByIdDefinePrivateFieldStrictOptimize, void, (JSGlobalObject* globalObject, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, uintptr_t rawCacheableIdentifier))
982{
983 SuperSamplerScope superSamplerScope(false);
984 VM& vm = globalObject->vm();
985 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
986 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
987
988 CacheableIdentifier identifier = CacheableIdentifier::createFromRawBits(rawCacheableIdentifier);
989 AccessType accessType = static_cast<AccessType>(stubInfo->accessType);
990 JSValue value = JSValue::decode(encodedValue);
991 JSValue baseValue = JSValue::decode(encodedBase);
992
993 definePrivateField(vm, globalObject, callFrame, baseValue, identifier, value, [=](VM& vm, CodeBlock* codeBlock, Structure* oldStructure, PutPropertySlot& putSlot, const Identifier& ident) {
994 JSObject* baseObject = asObject(baseValue);
995 LOG_IC((ICEvent::OperationPutByIdDefinePrivateFieldFieldStrictOptimize, baseObject->classInfo(), ident, putSlot.base() == baseObject));
996
997 ASSERT_UNUSED(accessType, accessType == static_cast<AccessType>(stubInfo->accessType));
998
999 if (stubInfo->considerCachingBy(vm, codeBlock, oldStructure, identifier))
1000 repatchPutBy(globalObject, codeBlock, baseObject, oldStructure, identifier, putSlot, *stubInfo, PutByKind::ById, PutKind::DirectPrivateFieldDefine);
1001 });
1002}
1003
1004JSC_DEFINE_JIT_OPERATION(operationPutByIdSetPrivateFieldStrict, void, (JSGlobalObject* globalObject, StructureStubInfo*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, uintptr_t rawCacheableIdentifier))
1005{
1006 VM& vm = globalObject->vm();
1007 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1008 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1009
1010 CacheableIdentifier identifier = CacheableIdentifier::createFromRawBits(rawCacheableIdentifier);
1011 JSValue value = JSValue::decode(encodedValue);
1012 JSValue baseValue = JSValue::decode(encodedBase);
1013
1014 setPrivateField(vm, globalObject, callFrame, baseValue, identifier, value, [](VM&, CodeBlock*, Structure*, PutPropertySlot&, const Identifier&) { });
1015}
1016
1017JSC_DEFINE_JIT_OPERATION(operationPutByIdSetPrivateFieldStrictOptimize, void, (JSGlobalObject* globalObject, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, uintptr_t rawCacheableIdentifier))
1018{
1019 SuperSamplerScope superSamplerScope(false);
1020 VM& vm = globalObject->vm();
1021 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1022 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1023
1024 CacheableIdentifier identifier = CacheableIdentifier::createFromRawBits(rawCacheableIdentifier);
1025 AccessType accessType = static_cast<AccessType>(stubInfo->accessType);
1026 JSValue value = JSValue::decode(encodedValue);
1027 JSValue baseValue = JSValue::decode(encodedBase);
1028
1029 setPrivateField(vm, globalObject, callFrame, baseValue, identifier, value, [&](VM& vm, CodeBlock* codeBlock, Structure* oldStructure, PutPropertySlot& putSlot, const Identifier& ident) {
1030 JSObject* baseObject = asObject(baseValue);
1031 LOG_IC((ICEvent::OperationPutByIdPutPrivateFieldFieldStrictOptimize, baseObject->classInfo(), ident, putSlot.base() == baseObject));
1032
1033 ASSERT_UNUSED(accessType, accessType == static_cast<AccessType>(stubInfo->accessType));
1034
1035 if (stubInfo->considerCachingBy(vm, codeBlock, oldStructure, identifier))
1036 repatchPutBy(globalObject, codeBlock, baseObject, oldStructure, identifier, putSlot, *stubInfo, PutByKind::ById, PutKind::DirectPrivateFieldSet);
1037 });
1038}
1039
1040static void putByVal(JSGlobalObject* globalObject, JSValue baseValue, JSValue subscript, JSValue value, ArrayProfile* arrayProfile, ECMAMode ecmaMode)
1041{
1042 VM& vm = globalObject->vm();
1043 auto scope = DECLARE_THROW_SCOPE(vm);
1044 if (std::optional<uint32_t> index = subscript.tryGetAsUint32Index()) {
1045 uint32_t i = *index;
1046 if (baseValue.isObject()) {
1047 JSObject* object = asObject(baseValue);
1048 if (object->trySetIndexQuickly(vm, i, value, arrayProfile))
1049 return;
1050
1051 if (arrayProfile)
1052 arrayProfile->setOutOfBounds();
1053 scope.release();
1054 object->methodTable()->putByIndex(object, globalObject, i, value, ecmaMode.isStrict());
1055 return;
1056 }
1057
1058 scope.release();
1059 baseValue.putByIndex(globalObject, i, value, ecmaMode.isStrict());
1060 return;
1061 }
1062
1063 if (subscript.isNumber()) {
1064 if (baseValue.isObject()) {
1065 if (arrayProfile)
1066 arrayProfile->setOutOfBounds();
1067 }
1068 }
1069
1070 auto property = subscript.toPropertyKey(globalObject);
1071 // Don't put to an object if toString threw an exception.
1072 RETURN_IF_EXCEPTION(scope, void());
1073
1074 scope.release();
1075 PutPropertySlot slot(baseValue, ecmaMode.isStrict());
1076 baseValue.putInline(globalObject, property, value, slot);
1077}
1078
1079static void directPutByVal(JSGlobalObject* globalObject, JSObject* baseObject, JSValue subscript, JSValue value, ArrayProfile* arrayProfile, ECMAMode ecmaMode)
1080{
1081 VM& vm = globalObject->vm();
1082 auto scope = DECLARE_THROW_SCOPE(vm);
1083
1084 if (std::optional<uint32_t> maybeIndex = subscript.tryGetAsUint32Index()) {
1085 uint32_t index = *maybeIndex;
1086
1087 switch (baseObject->indexingType()) {
1088 case ALL_INT32_INDEXING_TYPES:
1089 case ALL_DOUBLE_INDEXING_TYPES:
1090 case ALL_CONTIGUOUS_INDEXING_TYPES:
1091 case ALL_ARRAY_STORAGE_INDEXING_TYPES:
1092 if (index < baseObject->butterfly()->vectorLength())
1093 break;
1094 FALLTHROUGH;
1095 default:
1096 if (arrayProfile)
1097 arrayProfile->setOutOfBounds();
1098 break;
1099 }
1100
1101 scope.release();
1102 baseObject->putDirectIndex(globalObject, index, value, 0, ecmaMode.isStrict() ? PutDirectIndexShouldThrow : PutDirectIndexShouldNotThrow);
1103 return;
1104 }
1105
1106 // Don't put to an object if toString threw an exception.
1107 auto property = subscript.toPropertyKey(globalObject);
1108 RETURN_IF_EXCEPTION(scope, void());
1109
1110 if (std::optional<uint32_t> index = parseIndex(property)) {
1111 scope.release();
1112 baseObject->putDirectIndex(globalObject, index.value(), value, 0, ecmaMode.isStrict() ? PutDirectIndexShouldThrow : PutDirectIndexShouldNotThrow);
1113 return;
1114 }
1115
1116 scope.release();
1117 PutPropertySlot slot(baseObject, ecmaMode.isStrict());
1118 CommonSlowPaths::putDirectWithReify(vm, globalObject, baseObject, property, value, slot);
1119}
1120
1121enum class OptimizationResult {
1122 NotOptimized,
1123 SeenOnce,
1124 Optimized,
1125 GiveUp,
1126};
1127
1128static ALWAYS_INLINE void putByValOptimize(JSGlobalObject* globalObject, CodeBlock* codeBlock, JSValue baseValue, JSValue subscript, JSValue value, StructureStubInfo* stubInfo, ArrayProfile* profile, ECMAMode ecmaMode)
1129{
1130 VM& vm = globalObject->vm();
1131 auto scope = DECLARE_THROW_SCOPE(vm);
1132
1133 if (baseValue.isObject()) {
1134 JSObject* baseObject = asObject(baseValue);
1135 if (!isCopyOnWrite(baseObject->indexingMode()) && subscript.isInt32()) {
1136 Structure* structure = baseObject->structure();
1137 if (stubInfo->considerCachingGeneric(vm, codeBlock, structure)) {
1138 if (profile) {
1139 ConcurrentJSLocker locker(codeBlock->m_lock);
1140 profile->computeUpdatedPrediction(locker, codeBlock, structure);
1141 }
1142 repatchArrayPutByVal(globalObject, codeBlock, baseValue, subscript, *stubInfo, PutKind::NotDirect, ecmaMode);
1143 }
1144 }
1145
1146 if (CacheableIdentifier::isCacheableIdentifierCell(subscript)) {
1147 const Identifier propertyName = subscript.toPropertyKey(globalObject);
1148 RETURN_IF_EXCEPTION(scope, void());
1149 if (subscript.isSymbol() || !parseIndex(propertyName)) {
1150 AccessType accessType = static_cast<AccessType>(stubInfo->accessType);
1151 PutPropertySlot slot(baseValue, ecmaMode.isStrict(), codeBlock->putByIdContext());
1152
1153 Structure* structure = CommonSlowPaths::originalStructureBeforePut(baseValue);
1154 baseObject->putInline(globalObject, propertyName, value, slot);
1155 RETURN_IF_EXCEPTION(scope, void());
1156
1157 if (accessType != static_cast<AccessType>(stubInfo->accessType))
1158 return;
1159
1160 CacheableIdentifier identifier = CacheableIdentifier::createFromCell(subscript.asCell());
1161 if (stubInfo->considerCachingBy(vm, codeBlock, structure, identifier))
1162 repatchPutBy(globalObject, codeBlock, baseValue, structure, identifier, slot, *stubInfo, PutByKind::ByVal, PutKind::NotDirect);
1163 return;
1164 }
1165 }
1166 }
1167
1168 RELEASE_AND_RETURN(scope, putByVal(globalObject, baseValue, subscript, value, profile, ecmaMode));
1169}
1170
1171JSC_DEFINE_JIT_OPERATION(operationPutByValStrictOptimize, void, (JSGlobalObject* globalObject, EncodedJSValue encodedBaseValue, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue, StructureStubInfo* stubInfo, ArrayProfile* profile))
1172{
1173 VM& vm = globalObject->vm();
1174 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1175 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1176
1177 JSValue baseValue = JSValue::decode(encodedBaseValue);
1178 JSValue subscript = JSValue::decode(encodedSubscript);
1179 JSValue value = JSValue::decode(encodedValue);
1180
1181 putByValOptimize(globalObject, callFrame->codeBlock(), baseValue, subscript, value, stubInfo, profile, ECMAMode::strict());
1182}
1183
1184JSC_DEFINE_JIT_OPERATION(operationPutByValNonStrictOptimize, void, (JSGlobalObject* globalObject, EncodedJSValue encodedBaseValue, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue, StructureStubInfo* stubInfo, ArrayProfile* profile))
1185{
1186 VM& vm = globalObject->vm();
1187 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1188 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1189
1190 JSValue baseValue = JSValue::decode(encodedBaseValue);
1191 JSValue subscript = JSValue::decode(encodedSubscript);
1192 JSValue value = JSValue::decode(encodedValue);
1193
1194 putByValOptimize(globalObject, callFrame->codeBlock(), baseValue, subscript, value, stubInfo, profile, ECMAMode::sloppy());
1195}
1196
1197static ALWAYS_INLINE void directPutByValOptimize(JSGlobalObject* globalObject, CodeBlock* codeBlock, JSValue baseValue, JSValue subscript, JSValue value, StructureStubInfo* stubInfo, ArrayProfile* profile, ECMAMode ecmaMode)
1198{
1199 VM& vm = globalObject->vm();
1200 auto scope = DECLARE_THROW_SCOPE(vm);
1201
1202 RELEASE_ASSERT(baseValue.isObject());
1203 JSObject* baseObject = asObject(baseValue);
1204
1205 if (!isCopyOnWrite(baseObject->indexingMode()) && subscript.isInt32()) {
1206 Structure* structure = baseObject->structure();
1207 if (stubInfo->considerCachingGeneric(vm, codeBlock, structure)) {
1208 if (profile) {
1209 ConcurrentJSLocker locker(codeBlock->m_lock);
1210 profile->computeUpdatedPrediction(locker, codeBlock, structure);
1211 }
1212 repatchArrayPutByVal(globalObject, codeBlock, baseValue, subscript, *stubInfo, PutKind::Direct, ecmaMode);
1213 }
1214 }
1215
1216 if (CacheableIdentifier::isCacheableIdentifierCell(subscript)) {
1217 const Identifier propertyName = subscript.toPropertyKey(globalObject);
1218 RETURN_IF_EXCEPTION(scope, void());
1219 if (subscript.isSymbol() || !parseIndex(propertyName)) {
1220 AccessType accessType = static_cast<AccessType>(stubInfo->accessType);
1221 PutPropertySlot slot(baseValue, ecmaMode.isStrict(), codeBlock->putByIdContext());
1222
1223 Structure* structure = CommonSlowPaths::originalStructureBeforePut(baseValue);
1224 CommonSlowPaths::putDirectWithReify(vm, globalObject, baseObject, propertyName, value, slot);
1225
1226 RETURN_IF_EXCEPTION(scope, void());
1227
1228 if (accessType != static_cast<AccessType>(stubInfo->accessType))
1229 return;
1230
1231 CacheableIdentifier identifier = CacheableIdentifier::createFromCell(subscript.asCell());
1232 if (stubInfo->considerCachingBy(vm, codeBlock, structure, identifier))
1233 repatchPutBy(globalObject, codeBlock, baseValue, structure, identifier, slot, *stubInfo, PutByKind::ByVal, PutKind::Direct);
1234 return;
1235 }
1236 }
1237
1238 RELEASE_AND_RETURN(scope, directPutByVal(globalObject, baseObject, subscript, value, profile, ecmaMode));
1239
1240}
1241
1242JSC_DEFINE_JIT_OPERATION(operationDirectPutByValStrictOptimize, void, (JSGlobalObject* globalObject, EncodedJSValue encodedBaseValue, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue, StructureStubInfo* stubInfo, ArrayProfile* profile))
1243{
1244 VM& vm = globalObject->vm();
1245 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1246 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1247
1248 JSValue baseValue = JSValue::decode(encodedBaseValue);
1249 JSValue subscript = JSValue::decode(encodedSubscript);
1250 JSValue value = JSValue::decode(encodedValue);
1251
1252 directPutByValOptimize(globalObject, callFrame->codeBlock(), baseValue, subscript, value, stubInfo, profile, ECMAMode::strict());
1253}
1254
1255JSC_DEFINE_JIT_OPERATION(operationDirectPutByValNonStrictOptimize, void, (JSGlobalObject* globalObject, EncodedJSValue encodedBaseValue, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue, StructureStubInfo* stubInfo, ArrayProfile* profile))
1256{
1257 VM& vm = globalObject->vm();
1258 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1259 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1260
1261 JSValue baseValue = JSValue::decode(encodedBaseValue);
1262 JSValue subscript = JSValue::decode(encodedSubscript);
1263 JSValue value = JSValue::decode(encodedValue);
1264
1265 directPutByValOptimize(globalObject, callFrame->codeBlock(), baseValue, subscript, value, stubInfo, profile, ECMAMode::sloppy());
1266}
1267
1268JSC_DEFINE_JIT_OPERATION(operationPutByValStrictGeneric, void, (JSGlobalObject* globalObject, EncodedJSValue encodedBaseValue, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue, StructureStubInfo* stubInfo, ArrayProfile* profile))
1269{
1270 VM& vm = globalObject->vm();
1271 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1272 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1273
1274 JSValue baseValue = JSValue::decode(encodedBaseValue);
1275 JSValue subscript = JSValue::decode(encodedSubscript);
1276 JSValue value = JSValue::decode(encodedValue);
1277
1278 stubInfo->tookSlowPath = true;
1279
1280 putByVal(globalObject, baseValue, subscript, value, profile, ECMAMode::strict());
1281}
1282
1283JSC_DEFINE_JIT_OPERATION(operationPutByValNonStrictGeneric, void, (JSGlobalObject* globalObject, EncodedJSValue encodedBaseValue, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue, StructureStubInfo* stubInfo, ArrayProfile* profile))
1284{
1285 VM& vm = globalObject->vm();
1286 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1287 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1288
1289 JSValue baseValue = JSValue::decode(encodedBaseValue);
1290 JSValue subscript = JSValue::decode(encodedSubscript);
1291 JSValue value = JSValue::decode(encodedValue);
1292
1293 stubInfo->tookSlowPath = true;
1294
1295 putByVal(globalObject, baseValue, subscript, value, profile, ECMAMode::sloppy());
1296}
1297
1298JSC_DEFINE_JIT_OPERATION(operationDirectPutByValStrictGeneric, void, (JSGlobalObject* globalObject, EncodedJSValue encodedBaseValue, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue, StructureStubInfo* stubInfo, ArrayProfile* profile))
1299{
1300 VM& vm = globalObject->vm();
1301 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1302 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1303
1304 JSValue baseValue = JSValue::decode(encodedBaseValue);
1305 JSValue subscript = JSValue::decode(encodedSubscript);
1306 JSValue value = JSValue::decode(encodedValue);
1307 RELEASE_ASSERT(baseValue.isObject());
1308
1309 stubInfo->tookSlowPath = true;
1310
1311 directPutByVal(globalObject, asObject(baseValue), subscript, value, profile, ECMAMode::strict());
1312}
1313
1314JSC_DEFINE_JIT_OPERATION(operationDirectPutByValNonStrictGeneric, void, (JSGlobalObject* globalObject, EncodedJSValue encodedBaseValue, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue, StructureStubInfo* stubInfo, ArrayProfile* profile))
1315{
1316 VM& vm = globalObject->vm();
1317 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1318 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1319
1320 JSValue baseValue = JSValue::decode(encodedBaseValue);
1321 JSValue subscript = JSValue::decode(encodedSubscript);
1322 JSValue value = JSValue::decode(encodedValue);
1323 RELEASE_ASSERT(baseValue.isObject());
1324
1325 stubInfo->tookSlowPath = true;
1326
1327 directPutByVal(globalObject, asObject(baseValue), subscript, value, profile, ECMAMode::sloppy());
1328}
1329
1330JSC_DEFINE_JIT_OPERATION(operationSetPrivateBrandOptimize, void, (JSGlobalObject* globalObject, StructureStubInfo* stubInfo, EncodedJSValue encodedBaseValue, EncodedJSValue encodedBrand))
1331{
1332 VM& vm = globalObject->vm();
1333 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1334 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1335 auto scope = DECLARE_THROW_SCOPE(vm);
1336
1337 JSValue baseValue = JSValue::decode(encodedBaseValue);
1338 JSValue brand = JSValue::decode(encodedBrand);
1339
1340 ASSERT(baseValue.isObject());
1341 ASSERT(brand.isSymbol());
1342
1343 JSObject* baseObject = asObject(baseValue);
1344 Structure* oldStructure = baseObject->structure();
1345 baseObject->setPrivateBrand(globalObject, brand);
1346 RETURN_IF_EXCEPTION(scope, void());
1347
1348 CodeBlock* codeBlock = callFrame->codeBlock();
1349 if (CacheableIdentifier::isCacheableIdentifierCell(brand)) {
1350 CacheableIdentifier identifier = CacheableIdentifier::createFromCell(brand.asCell());
1351 if (stubInfo->considerCachingBy(vm, codeBlock, baseObject->structure(), identifier))
1352 repatchSetPrivateBrand(globalObject, codeBlock, baseObject, oldStructure, identifier, *stubInfo);
1353 }
1354
1355}
1356
1357JSC_DEFINE_JIT_OPERATION(operationSetPrivateBrandGeneric, void, (JSGlobalObject* globalObject, StructureStubInfo* stubInfo, EncodedJSValue encodedBaseValue, EncodedJSValue encodedBrand))
1358{
1359 VM& vm = globalObject->vm();
1360 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1361 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1362 auto scope = DECLARE_THROW_SCOPE(vm);
1363
1364 JSValue baseValue = JSValue::decode(encodedBaseValue);
1365 JSValue brand = JSValue::decode(encodedBrand);
1366
1367 if (stubInfo)
1368 stubInfo->tookSlowPath = true;
1369
1370 ASSERT(baseValue.isObject());
1371 ASSERT(brand.isSymbol());
1372
1373 JSObject* baseObject = asObject(baseValue);
1374 baseObject->setPrivateBrand(globalObject, brand);
1375 RETURN_IF_EXCEPTION(scope, void());
1376}
1377
1378JSC_DEFINE_JIT_OPERATION(operationCheckPrivateBrandOptimize, void, (JSGlobalObject* globalObject, StructureStubInfo* stubInfo, EncodedJSValue encodedBaseValue, EncodedJSValue encodedBrand))
1379{
1380 VM& vm = globalObject->vm();
1381 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1382 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1383 auto scope = DECLARE_THROW_SCOPE(vm);
1384
1385 JSValue baseValue = JSValue::decode(encodedBaseValue);
1386 JSValue brand = JSValue::decode(encodedBrand);
1387
1388 JSObject* baseObject = baseValue.toObject(globalObject);
1389 RETURN_IF_EXCEPTION(scope, void());
1390
1391 ASSERT(brand.isSymbol());
1392
1393 baseObject->checkPrivateBrand(globalObject, brand);
1394 RETURN_IF_EXCEPTION(scope, void());
1395
1396 CodeBlock* codeBlock = callFrame->codeBlock();
1397 if (CacheableIdentifier::isCacheableIdentifierCell(brand)) {
1398 CacheableIdentifier identifier = CacheableIdentifier::createFromCell(brand.asCell());
1399 if (stubInfo->considerCachingBy(vm, codeBlock, baseObject->structure(), identifier))
1400 repatchCheckPrivateBrand(globalObject, codeBlock, baseObject, identifier, *stubInfo);
1401 }
1402}
1403
1404JSC_DEFINE_JIT_OPERATION(operationCheckPrivateBrandGeneric, void, (JSGlobalObject* globalObject, StructureStubInfo* stubInfo, EncodedJSValue encodedBaseValue, EncodedJSValue encodedBrand))
1405{
1406 VM& vm = globalObject->vm();
1407 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1408 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1409 auto scope = DECLARE_THROW_SCOPE(vm);
1410
1411 JSValue baseValue = JSValue::decode(encodedBaseValue);
1412 JSValue brand = JSValue::decode(encodedBrand);
1413
1414 stubInfo->tookSlowPath = true;
1415
1416 JSObject* baseObject = baseValue.toObject(globalObject);
1417 RETURN_IF_EXCEPTION(scope, void());
1418
1419 ASSERT(brand.isSymbol());
1420
1421 baseObject->checkPrivateBrand(globalObject, brand);
1422 RETURN_IF_EXCEPTION(scope, void());
1423}
1424
1425template<bool define>
1426static ALWAYS_INLINE void putPrivateNameOptimize(JSGlobalObject* globalObject, CodeBlock* codeBlock, JSValue baseValue, JSValue subscript, JSValue value, StructureStubInfo* stubInfo)
1427{
1428 VM& vm = globalObject->vm();
1429 auto scope = DECLARE_THROW_SCOPE(vm);
1430
1431 auto baseObject = baseValue.toObject(globalObject);
1432 RETURN_IF_EXCEPTION(scope, void());
1433
1434 auto propertyName = subscript.toPropertyKey(globalObject);
1435 RETURN_IF_EXCEPTION(scope, void());
1436
1437 // Private fields can only be accessed within class lexical scope
1438 // and class methods are always in strict mode
1439 AccessType accessType = static_cast<AccessType>(stubInfo->accessType);
1440 Structure* structure = CommonSlowPaths::originalStructureBeforePut(baseValue);
1441 constexpr bool isStrictMode = true;
1442 PutPropertySlot slot(baseObject, isStrictMode);
1443 if constexpr (define)
1444 baseObject->definePrivateField(globalObject, propertyName, value, slot);
1445 else
1446 baseObject->setPrivateField(globalObject, propertyName, value, slot);
1447 RETURN_IF_EXCEPTION(scope, void());
1448
1449 if (accessType != static_cast<AccessType>(stubInfo->accessType))
1450 return;
1451
1452 if (baseValue.isObject() && CacheableIdentifier::isCacheableIdentifierCell(subscript)) {
1453 CacheableIdentifier identifier = CacheableIdentifier::createFromCell(subscript.asCell());
1454 if (stubInfo->considerCachingBy(vm, codeBlock, structure, identifier))
1455 repatchPutBy(globalObject, codeBlock, baseValue, structure, identifier, slot, *stubInfo, PutByKind::ByVal, define ? PutKind::DirectPrivateFieldDefine : PutKind::DirectPrivateFieldSet);
1456 }
1457}
1458
1459template<bool define>
1460static ALWAYS_INLINE void putPrivateName(JSGlobalObject* globalObject, JSValue baseValue, JSValue subscript, JSValue value)
1461{
1462 VM& vm = globalObject->vm();
1463 auto scope = DECLARE_THROW_SCOPE(vm);
1464
1465 auto baseObject = baseValue.toObject(globalObject);
1466 RETURN_IF_EXCEPTION(scope, void());
1467
1468 auto propertyName = subscript.toPropertyKey(globalObject);
1469 RETURN_IF_EXCEPTION(scope, void());
1470
1471 scope.release();
1472
1473 // Private fields can only be accessed within class lexical scope
1474 // and class methods are always in strict mode
1475 constexpr bool isStrictMode = true;
1476 PutPropertySlot slot(baseObject, isStrictMode);
1477 if constexpr (define)
1478 baseObject->definePrivateField(globalObject, propertyName, value, slot);
1479 else
1480 baseObject->setPrivateField(globalObject, propertyName, value, slot);
1481}
1482
1483JSC_DEFINE_JIT_OPERATION(operationPutByValDefinePrivateFieldOptimize, void, (JSGlobalObject* globalObject, EncodedJSValue encodedBaseValue, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue, StructureStubInfo* stubInfo, ArrayProfile*))
1484{
1485 VM& vm = globalObject->vm();
1486 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1487 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1488
1489 CodeBlock* codeBlock = callFrame->codeBlock();
1490 JSValue baseValue = JSValue::decode(encodedBaseValue);
1491 JSValue subscript = JSValue::decode(encodedSubscript);
1492 JSValue value = JSValue::decode(encodedValue);
1493 putPrivateNameOptimize<true>(globalObject, codeBlock, baseValue, subscript, value, stubInfo);
1494}
1495
1496JSC_DEFINE_JIT_OPERATION(operationPutByValSetPrivateFieldOptimize, void, (JSGlobalObject* globalObject, EncodedJSValue encodedBaseValue, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue, StructureStubInfo* stubInfo, ArrayProfile*))
1497{
1498 VM& vm = globalObject->vm();
1499 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1500 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1501
1502 CodeBlock* codeBlock = callFrame->codeBlock();
1503 JSValue baseValue = JSValue::decode(encodedBaseValue);
1504 JSValue subscript = JSValue::decode(encodedSubscript);
1505 JSValue value = JSValue::decode(encodedValue);
1506 putPrivateNameOptimize<false>(globalObject, codeBlock, baseValue, subscript, value, stubInfo);
1507}
1508
1509JSC_DEFINE_JIT_OPERATION(operationPutByValDefinePrivateFieldGeneric, void, (JSGlobalObject* globalObject, EncodedJSValue encodedBaseValue, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue, StructureStubInfo* stubInfo, ArrayProfile*))
1510{
1511 VM& vm = globalObject->vm();
1512 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1513 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1514
1515 JSValue baseValue = JSValue::decode(encodedBaseValue);
1516 JSValue subscript = JSValue::decode(encodedSubscript);
1517 JSValue value = JSValue::decode(encodedValue);
1518
1519 if (stubInfo)
1520 stubInfo->tookSlowPath = true;
1521
1522 putPrivateName<true>(globalObject, baseValue, subscript, value);
1523}
1524
1525JSC_DEFINE_JIT_OPERATION(operationPutByValSetPrivateFieldGeneric, void, (JSGlobalObject* globalObject, EncodedJSValue encodedBaseValue, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue, StructureStubInfo* stubInfo, ArrayProfile*))
1526{
1527 VM& vm = globalObject->vm();
1528 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1529 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1530
1531 JSValue baseValue = JSValue::decode(encodedBaseValue);
1532 JSValue subscript = JSValue::decode(encodedSubscript);
1533 JSValue value = JSValue::decode(encodedValue);
1534
1535 if (stubInfo)
1536 stubInfo->tookSlowPath = true;
1537
1538 putPrivateName<false>(globalObject, baseValue, subscript, value);
1539}
1540
1541JSC_DEFINE_JIT_OPERATION(operationCallEval, EncodedJSValue, (JSGlobalObject* globalObject, CallFrame* calleeFrame, ECMAMode ecmaMode))
1542{
1543 VM& vm = globalObject->vm();
1544 auto scope = DECLARE_THROW_SCOPE(vm);
1545
1546 calleeFrame->setCodeBlock(nullptr);
1547
1548 if (!isHostFunction(calleeFrame->guaranteedJSValueCallee(), globalFuncEval))
1549 return JSValue::encode(JSValue());
1550
1551 JSValue result = eval(globalObject, calleeFrame, ecmaMode);
1552 RETURN_IF_EXCEPTION(scope, encodedJSValue());
1553
1554 return JSValue::encode(result);
1555}
1556
1557JSC_DEFINE_JIT_OPERATION(operationLinkCall, SlowPathReturnType, (CallFrame* calleeFrame, JSGlobalObject* globalObject, CallLinkInfo* callLinkInfo))
1558{
1559 sanitizeStackForVM(globalObject->vm());
1560 return linkFor(calleeFrame, globalObject, callLinkInfo);
1561}
1562
1563JSC_DEFINE_JIT_OPERATION(operationLinkPolymorphicCall, SlowPathReturnType, (CallFrame* calleeFrame, JSGlobalObject* globalObject, CallLinkInfo* callLinkInfo))
1564{
1565 sanitizeStackForVM(globalObject->vm());
1566 ASSERT(callLinkInfo->specializationKind() == CodeForCall);
1567 JSCell* calleeAsFunctionCell;
1568 SlowPathReturnType result = virtualForWithFunction(globalObject, calleeFrame, callLinkInfo, calleeAsFunctionCell);
1569
1570 linkPolymorphicCall(globalObject, calleeFrame, *callLinkInfo, CallVariant(calleeAsFunctionCell));
1571
1572 return result;
1573}
1574
1575JSC_DEFINE_JIT_OPERATION(operationVirtualCall, SlowPathReturnType, (CallFrame* calleeFrame, JSGlobalObject* globalObject, CallLinkInfo* callLinkInfo))
1576{
1577 sanitizeStackForVM(globalObject->vm());
1578 JSCell* calleeAsFunctionCellIgnored;
1579 return virtualForWithFunction(globalObject, calleeFrame, callLinkInfo, calleeAsFunctionCellIgnored);
1580}
1581
1582JSC_DEFINE_JIT_OPERATION(operationCompareLess, size_t, (JSGlobalObject* globalObject, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2))
1583{
1584 VM& vm = globalObject->vm();
1585 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1586 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1587
1588 return jsLess<true>(globalObject, JSValue::decode(encodedOp1), JSValue::decode(encodedOp2));
1589}
1590
1591JSC_DEFINE_JIT_OPERATION(operationCompareLessEq, size_t, (JSGlobalObject* globalObject, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2))
1592{
1593 VM& vm = globalObject->vm();
1594 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1595 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1596
1597 return jsLessEq<true>(globalObject, JSValue::decode(encodedOp1), JSValue::decode(encodedOp2));
1598}
1599
1600JSC_DEFINE_JIT_OPERATION(operationCompareGreater, size_t, (JSGlobalObject* globalObject, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2))
1601{
1602 VM& vm = globalObject->vm();
1603 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1604 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1605
1606 return jsLess<false>(globalObject, JSValue::decode(encodedOp2), JSValue::decode(encodedOp1));
1607}
1608
1609JSC_DEFINE_JIT_OPERATION(operationCompareGreaterEq, size_t, (JSGlobalObject* globalObject, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2))
1610{
1611 VM& vm = globalObject->vm();
1612 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1613 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1614
1615 return jsLessEq<false>(globalObject, JSValue::decode(encodedOp2), JSValue::decode(encodedOp1));
1616}
1617
1618JSC_DEFINE_JIT_OPERATION(operationCompareEq, size_t, (JSGlobalObject* globalObject, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2))
1619{
1620 VM& vm = globalObject->vm();
1621 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1622 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1623
1624 return JSValue::equalSlowCaseInline(globalObject, JSValue::decode(encodedOp1), JSValue::decode(encodedOp2));
1625}
1626
1627#if USE(JSVALUE64)
1628JSC_DEFINE_JIT_OPERATION(operationCompareStringEq, EncodedJSValue, (JSGlobalObject* globalObject, JSCell* left, JSCell* right))
1629#else
1630JSC_DEFINE_JIT_OPERATION(operationCompareStringEq, size_t, (JSGlobalObject* globalObject, JSCell* left, JSCell* right))
1631#endif
1632{
1633 VM& vm = globalObject->vm();
1634 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1635 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1636
1637 bool result = asString(left)->equal(globalObject, asString(right));
1638#if USE(JSVALUE64)
1639 return JSValue::encode(jsBoolean(result));
1640#else
1641 return result;
1642#endif
1643}
1644
1645JSC_DEFINE_JIT_OPERATION(operationCompareStrictEq, size_t, (JSGlobalObject* globalObject, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2))
1646{
1647 VM& vm = globalObject->vm();
1648 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1649 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1650
1651 JSValue src1 = JSValue::decode(encodedOp1);
1652 JSValue src2 = JSValue::decode(encodedOp2);
1653
1654 return JSValue::strictEqual(globalObject, src1, src2);
1655}
1656
1657#if USE(BIGINT32)
1658JSC_DEFINE_JIT_OPERATION(operationCompareEqHeapBigIntToInt32, size_t, (JSGlobalObject* globalObject, JSCell* heapBigInt, int32_t smallInt))
1659{
1660 VM& vm = globalObject->vm();
1661 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1662 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1663
1664 ASSERT(heapBigInt->isHeapBigInt());
1665
1666 return static_cast<JSBigInt*>(heapBigInt)->equalsToInt32(smallInt);
1667}
1668#endif
1669
1670JSC_DEFINE_JIT_OPERATION(operationNewArrayWithProfile, EncodedJSValue, (JSGlobalObject* globalObject, ArrayAllocationProfile* profile, const JSValue* values, int size))
1671{
1672 VM& vm = globalObject->vm();
1673 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1674 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1675 return JSValue::encode(constructArrayNegativeIndexed(globalObject, profile, values, size));
1676}
1677
1678JSC_DEFINE_JIT_OPERATION(operationNewArrayWithSizeAndProfile, EncodedJSValue, (JSGlobalObject* globalObject, ArrayAllocationProfile* profile, EncodedJSValue size))
1679{
1680 VM& vm = globalObject->vm();
1681 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1682 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1683 JSValue sizeValue = JSValue::decode(size);
1684 return JSValue::encode(constructArrayWithSizeQuirk(globalObject, profile, sizeValue));
1685}
1686
1687template<typename FunctionType>
1688static EncodedJSValue newFunctionCommon(VM& vm, JSScope* scope, JSCell* functionExecutable, bool isInvalidated)
1689{
1690 ASSERT(functionExecutable->inherits<FunctionExecutable>());
1691 if (isInvalidated)
1692 return JSValue::encode(FunctionType::createWithInvalidatedReallocationWatchpoint(vm, static_cast<FunctionExecutable*>(functionExecutable), scope));
1693 return JSValue::encode(FunctionType::create(vm, static_cast<FunctionExecutable*>(functionExecutable), scope));
1694}
1695
1696JSC_DEFINE_JIT_OPERATION(operationNewFunction, EncodedJSValue, (VM* vmPointer, JSScope* scope, JSCell* functionExecutable))
1697{
1698 VM& vm = *vmPointer;
1699 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1700 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1701 return newFunctionCommon<JSFunction>(vm, scope, functionExecutable, false);
1702}
1703
1704JSC_DEFINE_JIT_OPERATION(operationNewFunctionWithInvalidatedReallocationWatchpoint, EncodedJSValue, (VM* vmPointer, JSScope* scope, JSCell* functionExecutable))
1705{
1706 VM& vm = *vmPointer;
1707 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1708 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1709 return newFunctionCommon<JSFunction>(vm, scope, functionExecutable, true);
1710}
1711
1712JSC_DEFINE_JIT_OPERATION(operationNewGeneratorFunction, EncodedJSValue, (VM* vmPointer, JSScope* scope, JSCell* functionExecutable))
1713{
1714 VM& vm = *vmPointer;
1715 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1716 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1717 return newFunctionCommon<JSGeneratorFunction>(vm, scope, functionExecutable, false);
1718}
1719
1720JSC_DEFINE_JIT_OPERATION(operationNewGeneratorFunctionWithInvalidatedReallocationWatchpoint, EncodedJSValue, (VM* vmPointer, JSScope* scope, JSCell* functionExecutable))
1721{
1722 VM& vm = *vmPointer;
1723 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1724 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1725 return newFunctionCommon<JSGeneratorFunction>(vm, scope, functionExecutable, true);
1726}
1727
1728JSC_DEFINE_JIT_OPERATION(operationNewAsyncFunction, EncodedJSValue, (VM* vmPointer, JSScope* scope, JSCell* functionExecutable))
1729{
1730 VM& vm = *vmPointer;
1731 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1732 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1733 return newFunctionCommon<JSAsyncFunction>(vm, scope, functionExecutable, false);
1734}
1735
1736JSC_DEFINE_JIT_OPERATION(operationNewAsyncFunctionWithInvalidatedReallocationWatchpoint, EncodedJSValue, (VM* vmPointer, JSScope* scope, JSCell* functionExecutable))
1737{
1738 VM& vm = *vmPointer;
1739 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1740 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1741 return newFunctionCommon<JSAsyncFunction>(vm, scope, functionExecutable, true);
1742}
1743
1744JSC_DEFINE_JIT_OPERATION(operationNewAsyncGeneratorFunction, EncodedJSValue, (VM* vmPointer, JSScope* scope, JSCell* functionExecutable))
1745{
1746 VM& vm = *vmPointer;
1747 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1748 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1749 return newFunctionCommon<JSAsyncGeneratorFunction>(vm, scope, functionExecutable, false);
1750}
1751
1752JSC_DEFINE_JIT_OPERATION(operationNewAsyncGeneratorFunctionWithInvalidatedReallocationWatchpoint, EncodedJSValue, (VM* vmPointer, JSScope* scope, JSCell* functionExecutable))
1753{
1754 VM& vm = *vmPointer;
1755 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1756 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1757 return newFunctionCommon<JSAsyncGeneratorFunction>(vm, scope, functionExecutable, true);
1758}
1759
1760JSC_DEFINE_JIT_OPERATION(operationSetFunctionName, void, (JSGlobalObject* globalObject, JSCell* funcCell, EncodedJSValue encodedName))
1761{
1762 VM& vm = globalObject->vm();
1763 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1764 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1765
1766 JSFunction* func = jsCast<JSFunction*>(funcCell);
1767 JSValue name = JSValue::decode(encodedName);
1768 func->setFunctionName(globalObject, name);
1769}
1770
1771JSC_DEFINE_JIT_OPERATION(operationNewObject, JSCell*, (VM* vmPointer, Structure* structure))
1772{
1773 VM& vm = *vmPointer;
1774 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1775 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1776
1777 return constructEmptyObject(vm, structure);
1778}
1779
1780JSC_DEFINE_JIT_OPERATION(operationNewPromise, JSCell*, (VM* vmPointer, Structure* structure))
1781{
1782 VM& vm = *vmPointer;
1783 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1784 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1785
1786 return JSPromise::create(vm, structure);
1787}
1788
1789JSC_DEFINE_JIT_OPERATION(operationNewInternalPromise, JSCell*, (VM* vmPointer, Structure* structure))
1790{
1791 VM& vm = *vmPointer;
1792 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1793 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1794
1795 return JSInternalPromise::create(vm, structure);
1796}
1797
1798JSC_DEFINE_JIT_OPERATION(operationNewGenerator, JSCell*, (VM* vmPointer, Structure* structure))
1799{
1800 VM& vm = *vmPointer;
1801 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1802 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1803
1804 return JSGenerator::create(vm, structure);
1805}
1806
1807JSC_DEFINE_JIT_OPERATION(operationNewAsyncGenerator, JSCell*, (VM* vmPointer, Structure* structure))
1808{
1809 VM& vm = *vmPointer;
1810 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1811 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1812
1813 return JSAsyncGenerator::create(vm, structure);
1814}
1815
1816JSC_DEFINE_JIT_OPERATION(operationNewRegexp, JSCell*, (JSGlobalObject* globalObject, JSCell* regexpPtr))
1817{
1818 SuperSamplerScope superSamplerScope(false);
1819 VM& vm = globalObject->vm();
1820 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1821 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1822
1823 RegExp* regexp = static_cast<RegExp*>(regexpPtr);
1824 static constexpr bool areLegacyFeaturesEnabled = true;
1825 return RegExpObject::create(vm, globalObject->regExpStructure(), regexp, areLegacyFeaturesEnabled);
1826}
1827
1828// The only reason for returning an UnusedPtr (instead of void) is so that we can reuse the
1829// existing DFG slow path generator machinery when creating the slow path for CheckTraps
1830// in the DFG. If a DFG slow path generator that supports a void return type is added in the
1831// future, we can switch to using that then.
1832JSC_DEFINE_JIT_OPERATION(operationHandleTraps, UnusedPtr, (JSGlobalObject* globalObject))
1833{
1834 VM& vm = globalObject->vm();
1835 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1836 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1837 ASSERT(vm.traps().needHandling(VMTraps::AsyncEvents));
1838 vm.traps().handleTraps(VMTraps::AsyncEvents);
1839 return nullptr;
1840}
1841
1842JSC_DEFINE_JIT_OPERATION(operationDebug, void, (VM* vmPointer, int32_t debugHookType))
1843{
1844 VM& vm = *vmPointer;
1845 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1846 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1847
1848 vm.interpreter->debug(callFrame, static_cast<DebugHookType>(debugHookType));
1849}
1850
1851#if ENABLE(DFG_JIT)
1852static void updateAllPredictionsAndOptimizeAfterWarmUp(CodeBlock* codeBlock)
1853{
1854 codeBlock->updateAllPredictions();
1855 codeBlock->optimizeAfterWarmUp();
1856}
1857
1858JSC_DEFINE_JIT_OPERATION(operationOptimize, SlowPathReturnType, (VM* vmPointer, uint32_t bytecodeIndexBits))
1859{
1860 VM& vm = *vmPointer;
1861 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
1862 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
1863 BytecodeIndex bytecodeIndex = BytecodeIndex::fromBits(bytecodeIndexBits);
1864
1865 // Defer GC for a while so that it doesn't run between when we enter into this
1866 // slow path and when we figure out the state of our code block. This prevents
1867 // a number of awkward reentrancy scenarios, including:
1868 //
1869 // - The optimized version of our code block being jettisoned by GC right after
1870 // we concluded that we wanted to use it, but have not planted it into the JS
1871 // stack yet.
1872 //
1873 // - An optimized version of our code block being installed just as we decided
1874 // that it wasn't ready yet.
1875 //
1876 // Note that jettisoning won't happen if we already initiated OSR, because in
1877 // that case we would have already planted the optimized code block into the JS
1878 // stack.
1879 DeferGCForAWhile deferGC(vm);
1880
1881 CodeBlock* codeBlock = callFrame->codeBlock();
1882 if (UNLIKELY(codeBlock->jitType() != JITType::BaselineJIT)) {
1883 dataLog("Unexpected code block in Baseline->DFG tier-up: ", *codeBlock, "\n");
1884 RELEASE_ASSERT_NOT_REACHED();
1885 }
1886
1887 if (bytecodeIndex) {
1888 // If we're attempting to OSR from a loop, assume that this should be
1889 // separately optimized.
1890 codeBlock->m_shouldAlwaysBeInlined = false;
1891 }
1892
1893 if (UNLIKELY(Options::verboseOSR())) {
1894 dataLog(
1895 *codeBlock, ": Entered optimize with bytecodeIndex = ", bytecodeIndex,
1896 ", executeCounter = ", codeBlock->jitExecuteCounter(),
1897 ", optimizationDelayCounter = ", codeBlock->reoptimizationRetryCounter(),
1898 ", exitCounter = ");
1899 if (codeBlock->hasOptimizedReplacement())
1900 dataLog(codeBlock->replacement()->osrExitCounter());
1901 else
1902 dataLog("N/A");
1903 dataLog("\n");
1904 }
1905
1906 if (!codeBlock->checkIfOptimizationThresholdReached()) {
1907 CODEBLOCK_LOG_EVENT(codeBlock, "delayOptimizeToDFG", ("counter = ", codeBlock->jitExecuteCounter()));
1908 codeBlock->updateAllPredictions();
1909 dataLogLnIf(Options::verboseOSR(), "Choosing not to optimize ", *codeBlock, " yet, because the threshold hasn't been reached.");
1910 return encodeResult(nullptr, nullptr);
1911 }
1912
1913 if (UNLIKELY(vm.terminationInProgress())) {
1914 // If termination of the current stack of execution is in progress,
1915 // then we need to hold off on optimized compiles so that termination
1916 // checks will be called, and we can unwind out of the current stack.
1917 CODEBLOCK_LOG_EVENT(codeBlock, "delayOptimizeToDFG", ("Terminating current execution"));
1918 updateAllPredictionsAndOptimizeAfterWarmUp(codeBlock);
1919 return encodeResult(nullptr, nullptr);
1920 }
1921
1922 Debugger* debugger = codeBlock->globalObject()->debugger();
1923 if (UNLIKELY(debugger && (debugger->isStepping() || codeBlock->baselineAlternative()->hasDebuggerRequests()))) {
1924 CODEBLOCK_LOG_EVENT(codeBlock, "delayOptimizeToDFG", ("debugger is stepping or has requests"));
1925 updateAllPredictionsAndOptimizeAfterWarmUp(codeBlock);
1926 return encodeResult(nullptr, nullptr);
1927 }
1928
1929 if (codeBlock->m_shouldAlwaysBeInlined) {
1930 CODEBLOCK_LOG_EVENT(codeBlock, "delayOptimizeToDFG", ("should always be inlined"));
1931 updateAllPredictionsAndOptimizeAfterWarmUp(codeBlock);
1932 dataLogLnIf(Options::verboseOSR(), "Choosing not to optimize ", *codeBlock, " yet, because m_shouldAlwaysBeInlined == true.");
1933 return encodeResult(nullptr, nullptr);
1934 }
1935
1936 // The call to JITWorklist::completeAllReadyPlansForVM() will complete all ready
1937 // (i.e. compiled) code blocks. But if it completes ours, we also need to know
1938 // what the result was so that we don't plow ahead and attempt OSR or immediate
1939 // reoptimization. This will have already also set the appropriate JIT execution
1940 // count threshold depending on what happened, so if the compilation was anything
1941 // but successful we just want to return early. See the case for worklistState ==
1942 // JITWorklist::Compiled, below.
1943
1944 // Note that we could have alternatively just called Worklist::compilationState()
1945 // here, and if it returned Compiled, we could have then called
1946 // completeAndScheduleOSR() below. But that would have meant that it could take
1947 // longer for code blocks to be completed: they would only complete when *their*
1948 // execution count trigger fired; but that could take a while since the firing is
1949 // racy. It could also mean that code blocks that never run again after being
1950 // compiled would sit on the worklist until next GC. That's fine, but it's
1951 // probably a waste of memory. Our goal here is to complete code blocks as soon as
1952 // possible in order to minimize the chances of us executing baseline code after
1953 // optimized code is already available.
1954 JITWorklist::State worklistState = JITWorklist::ensureGlobalWorklist().completeAllReadyPlansForVM(
1955 vm, JITCompilationKey(codeBlock, Options::forceUnlinkedDFG() ? JITCompilationMode::UnlinkedDFG : JITCompilationMode::DFG));
1956
1957 if (worklistState == JITWorklist::Compiling) {
1958 CODEBLOCK_LOG_EVENT(codeBlock, "delayOptimizeToDFG", ("compiling"));
1959 // We cannot be in the process of asynchronous compilation and also have an optimized
1960 // replacement.
1961 RELEASE_ASSERT(!codeBlock->hasOptimizedReplacement());
1962 codeBlock->setOptimizationThresholdBasedOnCompilationResult(CompilationDeferred);
1963 return encodeResult(nullptr, nullptr);
1964 }
1965
1966 if (worklistState == JITWorklist::Compiled) {
1967 // If we don't have an optimized replacement but we did just get compiled, then
1968 // the compilation failed or was invalidated, in which case the execution count
1969 // thresholds have already been set appropriately by
1970 // CodeBlock::setOptimizationThresholdBasedOnCompilationResult() and we have
1971 // nothing left to do.
1972 if (!codeBlock->hasOptimizedReplacement()) {
1973 CODEBLOCK_LOG_EVENT(codeBlock, "delayOptimizeToDFG", ("compiled and failed"));
1974 codeBlock->updateAllPredictions();
1975 dataLogLnIf(Options::verboseOSR(), "Code block ", *codeBlock, " was compiled but it doesn't have an optimized replacement.");
1976 return encodeResult(nullptr, nullptr);
1977 }
1978 } else if (codeBlock->hasOptimizedReplacement()) {
1979 CodeBlock* replacement = codeBlock->replacement();
1980 dataLogLnIf(Options::verboseOSR(), "Considering OSR ", codeBlock, " -> ", replacement, ".");
1981 // If we have an optimized replacement, then it must be the case that we entered
1982 // cti_optimize from a loop. That's because if there's an optimized replacement,
1983 // then all calls to this function will be relinked to the replacement and so
1984 // the prologue OSR will never fire.
1985
1986 // This is an interesting threshold check. Consider that a function OSR exits
1987 // in the middle of a loop, while having a relatively low exit count. The exit
1988 // will reset the execution counter to some target threshold, meaning that this
1989 // code won't be reached until that loop heats up for >=1000 executions. But then
1990 // we do a second check here, to see if we should either reoptimize, or just
1991 // attempt OSR entry. Hence it might even be correct for
1992 // shouldReoptimizeFromLoopNow() to always return true. But we make it do some
1993 // additional checking anyway, to reduce the amount of recompilation thrashing.
1994 if (replacement->shouldReoptimizeFromLoopNow()) {
1995 CODEBLOCK_LOG_EVENT(codeBlock, "delayOptimizeToDFG", ("should reoptimize from loop now"));
1996 dataLogLnIf(Options::verboseOSR(),
1997 "Triggering reoptimization of ", codeBlock,
1998 "(", replacement, ") (in loop).");
1999 replacement->jettison(Profiler::JettisonDueToBaselineLoopReoptimizationTrigger, CountReoptimization);
2000 return encodeResult(nullptr, nullptr);
2001 }
2002 } else {
2003 if (!codeBlock->shouldOptimizeNow()) {
2004 CODEBLOCK_LOG_EVENT(codeBlock, "delayOptimizeToDFG", ("insufficient profiling"));
2005 dataLogLnIf(Options::verboseOSR(),
2006 "Delaying optimization for ", *codeBlock,
2007 " because of insufficient profiling.");
2008 return encodeResult(nullptr, nullptr);
2009 }
2010
2011 dataLogLnIf(Options::verboseOSR(), "Triggering optimized compilation of ", *codeBlock);
2012
2013 unsigned numVarsWithValues = 0;
2014 if (bytecodeIndex)
2015 numVarsWithValues = codeBlock->numCalleeLocals();
2016
2017 Operands<std::optional<JSValue>> mustHandleValues(codeBlock->numParameters(), numVarsWithValues, 0);
2018 int localsUsedForCalleeSaves = static_cast<int>(CodeBlock::llintBaselineCalleeSaveSpaceAsVirtualRegisters());
2019 for (size_t i = 0; i < mustHandleValues.size(); ++i) {
2020 Operand operand = mustHandleValues.operandForIndex(i);
2021
2022 if (operand.isLocal() && operand.toLocal() < localsUsedForCalleeSaves)
2023 continue;
2024 mustHandleValues[i] = callFrame->uncheckedR(operand.virtualRegister()).jsValue();
2025 }
2026
2027 CodeBlock* replacementCodeBlock = codeBlock->newReplacement();
2028 CompilationResult result = DFG::compile(
2029 vm, replacementCodeBlock, nullptr, Options::forceUnlinkedDFG() ? JITCompilationMode::UnlinkedDFG : JITCompilationMode::DFG, bytecodeIndex,
2030 mustHandleValues, JITToDFGDeferredCompilationCallback::create());
2031
2032 if (result != CompilationSuccessful) {
2033 CODEBLOCK_LOG_EVENT(codeBlock, "delayOptimizeToDFG", ("compilation failed"));
2034 return encodeResult(nullptr, nullptr);
2035 }
2036 }
2037
2038 CodeBlock* optimizedCodeBlock = codeBlock->replacement();
2039 ASSERT(optimizedCodeBlock && JITCode::isOptimizingJIT(optimizedCodeBlock->jitType()));
2040
2041 if (void* dataBuffer = DFG::prepareOSREntry(vm, callFrame, optimizedCodeBlock, bytecodeIndex)) {
2042 CODEBLOCK_LOG_EVENT(optimizedCodeBlock, "osrEntry", ("at bc#", bytecodeIndex));
2043 dataLogLnIf(Options::verboseOSR(), "Performing OSR ", codeBlock, " -> ", optimizedCodeBlock);
2044
2045 codeBlock->optimizeSoon();
2046 codeBlock->unlinkedCodeBlock()->setDidOptimize(TriState::True);
2047 void* targetPC = untagCodePtr<JITThunkPtrTag>(vm.getCTIStub(DFG::osrEntryThunkGenerator).code().executableAddress());
2048 targetPC = tagCodePtrWithStackPointerForJITCall(targetPC, callFrame);
2049 return encodeResult(targetPC, dataBuffer);
2050 }
2051
2052 dataLogLnIf(Options::verboseOSR(),
2053 "Optimizing ", codeBlock, " -> ", codeBlock->replacement(),
2054 " succeeded, OSR failed, after a delay of ",
2055 codeBlock->optimizationDelayCounter());
2056
2057 // Count the OSR failure as a speculation failure. If this happens a lot, then
2058 // reoptimize.
2059 optimizedCodeBlock->countOSRExit();
2060
2061 // We are a lot more conservative about triggering reoptimization after OSR failure than
2062 // before it. If we enter the optimize_from_loop trigger with a bucket full of fail
2063 // already, then we really would like to reoptimize immediately. But this case covers
2064 // something else: there weren't many (or any) speculation failures before, but we just
2065 // failed to enter the speculative code because some variable had the wrong value or
2066 // because the OSR code decided for any spurious reason that it did not want to OSR
2067 // right now. So, we only trigger reoptimization only upon the more conservative (non-loop)
2068 // reoptimization trigger.
2069 if (optimizedCodeBlock->shouldReoptimizeNow()) {
2070 CODEBLOCK_LOG_EVENT(codeBlock, "delayOptimizeToDFG", ("should reoptimize now"));
2071 dataLogLnIf(Options::verboseOSR(),
2072 "Triggering reoptimization of ", codeBlock, " -> ",
2073 codeBlock->replacement(), " (after OSR fail).");
2074 optimizedCodeBlock->jettison(Profiler::JettisonDueToBaselineLoopReoptimizationTriggerOnOSREntryFail, CountReoptimization);
2075 return encodeResult(nullptr, nullptr);
2076 }
2077
2078 // OSR failed this time, but it might succeed next time! Let the code run a bit
2079 // longer and then try again.
2080 codeBlock->optimizeAfterWarmUp();
2081
2082 CODEBLOCK_LOG_EVENT(codeBlock, "delayOptimizeToDFG", ("OSR failed"));
2083 return encodeResult(nullptr, nullptr);
2084}
2085
2086JSC_DEFINE_JIT_OPERATION(operationTryOSREnterAtCatchAndValueProfile, SlowPathReturnType, (VM* vmPointer, uint32_t bytecodeIndexBits))
2087{
2088 VM& vm = *vmPointer;
2089 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2090 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2091 BytecodeIndex bytecodeIndex = BytecodeIndex::fromBits(bytecodeIndexBits);
2092
2093 CodeBlock* codeBlock = callFrame->codeBlock();
2094 CodeBlock* optimizedReplacement = codeBlock->replacement();
2095 if (UNLIKELY(!optimizedReplacement))
2096 return encodeResult(nullptr, nullptr);
2097
2098 switch (optimizedReplacement->jitType()) {
2099 case JITType::DFGJIT:
2100 case JITType::FTLJIT: {
2101 MacroAssemblerCodePtr<ExceptionHandlerPtrTag> entry = DFG::prepareCatchOSREntry(vm, callFrame, codeBlock, optimizedReplacement, bytecodeIndex);
2102 return encodeResult(entry.executableAddress<char*>(), optimizedReplacement);
2103 }
2104 default:
2105 break;
2106 }
2107
2108 codeBlock->ensureCatchLivenessIsComputedForBytecodeIndex(bytecodeIndex);
2109 auto bytecode = codeBlock->instructions().at(bytecodeIndex)->as<OpCatch>();
2110 auto& metadata = bytecode.metadata(codeBlock);
2111 metadata.m_buffer->forEach([&] (ValueProfileAndVirtualRegister& profile) {
2112 profile.m_buckets[0] = JSValue::encode(callFrame->uncheckedR(profile.m_operand).jsValue());
2113 });
2114
2115 return encodeResult(nullptr, nullptr);
2116}
2117
2118#endif
2119
2120enum class AccessorType {
2121 Getter,
2122 Setter
2123};
2124
2125static void putAccessorByVal(JSGlobalObject* globalObject, JSObject* base, JSValue subscript, int32_t attribute, JSObject* accessor, AccessorType accessorType)
2126{
2127 VM& vm = globalObject->vm();
2128 auto scope = DECLARE_THROW_SCOPE(vm);
2129 auto propertyKey = subscript.toPropertyKey(globalObject);
2130 RETURN_IF_EXCEPTION(scope, void());
2131
2132 scope.release();
2133 if (accessorType == AccessorType::Getter)
2134 base->putGetter(globalObject, propertyKey, accessor, attribute);
2135 else
2136 base->putSetter(globalObject, propertyKey, accessor, attribute);
2137}
2138
2139JSC_DEFINE_JIT_OPERATION(operationPutGetterById, void, (JSGlobalObject* globalObject, JSCell* object, UniquedStringImpl* uid, int32_t options, JSCell* getter))
2140{
2141 VM& vm = globalObject->vm();
2142 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2143 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2144
2145 ASSERT(object && object->isObject());
2146 JSObject* baseObj = object->getObject();
2147
2148 ASSERT(getter->isObject());
2149 baseObj->putGetter(globalObject, uid, getter, options);
2150}
2151
2152JSC_DEFINE_JIT_OPERATION(operationPutSetterById, void, (JSGlobalObject* globalObject, JSCell* object, UniquedStringImpl* uid, int32_t options, JSCell* setter))
2153{
2154 VM& vm = globalObject->vm();
2155 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2156 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2157
2158 ASSERT(object && object->isObject());
2159 JSObject* baseObj = object->getObject();
2160
2161 ASSERT(setter->isObject());
2162 baseObj->putSetter(globalObject, uid, setter, options);
2163}
2164
2165JSC_DEFINE_JIT_OPERATION(operationPutGetterByVal, void, (JSGlobalObject* globalObject, JSCell* base, EncodedJSValue encodedSubscript, int32_t attribute, JSCell* getter))
2166{
2167 VM& vm = globalObject->vm();
2168 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2169 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2170
2171 putAccessorByVal(globalObject, asObject(base), JSValue::decode(encodedSubscript), attribute, asObject(getter), AccessorType::Getter);
2172}
2173
2174JSC_DEFINE_JIT_OPERATION(operationPutSetterByVal, void, (JSGlobalObject* globalObject, JSCell* base, EncodedJSValue encodedSubscript, int32_t attribute, JSCell* setter))
2175{
2176 VM& vm = globalObject->vm();
2177 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2178 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2179
2180 putAccessorByVal(globalObject, asObject(base), JSValue::decode(encodedSubscript), attribute, asObject(setter), AccessorType::Setter);
2181}
2182
2183#if USE(JSVALUE64)
2184JSC_DEFINE_JIT_OPERATION(operationPutGetterSetter, void, (JSGlobalObject* globalObject, JSCell* object, UniquedStringImpl* uid, int32_t attribute, EncodedJSValue encodedGetterValue, EncodedJSValue encodedSetterValue))
2185{
2186 VM& vm = globalObject->vm();
2187 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2188 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2189
2190 ASSERT(object && object->isObject());
2191 JSObject* baseObject = asObject(object);
2192
2193 JSValue getter = JSValue::decode(encodedGetterValue);
2194 JSValue setter = JSValue::decode(encodedSetterValue);
2195 ASSERT(getter.isObject() || setter.isObject());
2196 GetterSetter* accessor = GetterSetter::create(vm, globalObject, getter, setter);
2197 CommonSlowPaths::putDirectAccessorWithReify(vm, globalObject, baseObject, uid, accessor, attribute);
2198}
2199
2200#else
2201JSC_DEFINE_JIT_OPERATION(operationPutGetterSetter, void, (JSGlobalObject* globalObject, JSCell* object, UniquedStringImpl* uid, int32_t attribute, JSCell* getterCell, JSCell* setterCell))
2202{
2203 VM& vm = globalObject->vm();
2204 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2205 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2206
2207 ASSERT(object && object->isObject());
2208 JSObject* baseObject = asObject(object);
2209
2210 ASSERT(getterCell || setterCell);
2211 JSObject* getter = getterCell ? getterCell->getObject() : nullptr;
2212 JSObject* setter = setterCell ? setterCell->getObject() : nullptr;
2213 GetterSetter* accessor = GetterSetter::create(vm, globalObject, getter, setter);
2214 CommonSlowPaths::putDirectAccessorWithReify(vm, globalObject, baseObject, uid, accessor, attribute);
2215}
2216#endif
2217
2218JSC_DEFINE_JIT_OPERATION(operationInstanceOfCustom, size_t, (JSGlobalObject* globalObject, EncodedJSValue encodedValue, JSObject* constructor, EncodedJSValue encodedHasInstance))
2219{
2220 VM& vm = globalObject->vm();
2221 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2222 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2223
2224 JSValue value = JSValue::decode(encodedValue);
2225 JSValue hasInstanceValue = JSValue::decode(encodedHasInstance);
2226
2227 if (constructor->hasInstance(globalObject, value, hasInstanceValue))
2228 return 1;
2229 return 0;
2230}
2231
2232ALWAYS_INLINE static JSValue getByVal(JSGlobalObject* globalObject, CallFrame* callFrame, ArrayProfile* arrayProfile, JSValue baseValue, JSValue subscript)
2233{
2234 UNUSED_PARAM(callFrame);
2235 VM& vm = globalObject->vm();
2236 auto scope = DECLARE_THROW_SCOPE(vm);
2237
2238 if (LIKELY(baseValue.isCell() && subscript.isString())) {
2239 Structure& structure = *baseValue.asCell()->structure();
2240 if (JSCell::canUseFastGetOwnProperty(structure)) {
2241 auto existingAtomString = asString(subscript)->toExistingAtomString(globalObject);
2242 RETURN_IF_EXCEPTION(scope, JSValue());
2243 if (!existingAtomString.isNull()) {
2244 if (JSValue result = baseValue.asCell()->fastGetOwnProperty(vm, structure, existingAtomString.impl())) {
2245 ASSERT(callFrame->bytecodeIndex() != BytecodeIndex(0));
2246 return result;
2247 }
2248 }
2249 }
2250 }
2251
2252 if (std::optional<uint32_t> index = subscript.tryGetAsUint32Index()) {
2253 uint32_t i = *index;
2254 if (isJSString(baseValue)) {
2255 if (asString(baseValue)->canGetIndex(i))
2256 RELEASE_AND_RETURN(scope, asString(baseValue)->getIndex(globalObject, i));
2257 if (arrayProfile)
2258 arrayProfile->setOutOfBounds();
2259 } else if (baseValue.isObject()) {
2260 JSObject* object = asObject(baseValue);
2261 if (JSValue result = object->tryGetIndexQuickly(i, arrayProfile))
2262 return result;
2263
2264 bool skipMarkingOutOfBounds = false;
2265
2266 if (object->indexingType() == ArrayWithContiguous
2267 && static_cast<uint32_t>(i) < object->butterfly()->publicLength()) {
2268 // FIXME: expand this to ArrayStorage, Int32, and maybe Double:
2269 // https://bugs.webkit.org/show_bug.cgi?id=182940
2270 auto* globalObject = object->globalObject();
2271 skipMarkingOutOfBounds = globalObject->isOriginalArrayStructure(object->structure()) && globalObject->arrayPrototypeChainIsSane();
2272 }
2273
2274 if (!skipMarkingOutOfBounds && !CommonSlowPaths::canAccessArgumentIndexQuickly(*object, i)) {
2275 // FIXME: This will make us think that in-bounds typed array accesses are actually
2276 // out-of-bounds.
2277 // https://bugs.webkit.org/show_bug.cgi?id=149886
2278 if (arrayProfile)
2279 arrayProfile->setOutOfBounds();
2280 }
2281 }
2282
2283 RELEASE_AND_RETURN(scope, baseValue.get(globalObject, i));
2284 } else if (subscript.isNumber() && baseValue.isCell() && arrayProfile)
2285 arrayProfile->setOutOfBounds();
2286
2287 baseValue.requireObjectCoercible(globalObject);
2288 RETURN_IF_EXCEPTION(scope, JSValue());
2289 auto property = subscript.toPropertyKey(globalObject);
2290 RETURN_IF_EXCEPTION(scope, JSValue());
2291
2292 ASSERT(callFrame->bytecodeIndex() != BytecodeIndex(0));
2293 RELEASE_AND_RETURN(scope, baseValue.get(globalObject, property));
2294}
2295
2296JSC_DEFINE_JIT_OPERATION(operationGetByValGeneric, EncodedJSValue, (JSGlobalObject* globalObject, StructureStubInfo* stubInfo, ArrayProfile* profile, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript))
2297{
2298 VM& vm = globalObject->vm();
2299 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2300 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2301 JSValue baseValue = JSValue::decode(encodedBase);
2302 JSValue subscript = JSValue::decode(encodedSubscript);
2303
2304 stubInfo->tookSlowPath = true;
2305
2306 return JSValue::encode(getByVal(globalObject, callFrame, profile, baseValue, subscript));
2307}
2308
2309JSC_DEFINE_JIT_OPERATION(operationGetByValOptimize, EncodedJSValue, (JSGlobalObject* globalObject, StructureStubInfo* stubInfo, ArrayProfile* profile, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript))
2310{
2311 VM& vm = globalObject->vm();
2312 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2313 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2314 auto scope = DECLARE_THROW_SCOPE(vm);
2315
2316 JSValue baseValue = JSValue::decode(encodedBase);
2317 JSValue subscript = JSValue::decode(encodedSubscript);
2318
2319 CodeBlock* codeBlock = callFrame->codeBlock();
2320
2321 if (baseValue.isCell() && subscript.isInt32()) {
2322 Structure* structure = baseValue.asCell()->structure();
2323 if (stubInfo->considerCachingGeneric(vm, codeBlock, structure)) {
2324 if (profile) {
2325 ConcurrentJSLocker locker(codeBlock->m_lock);
2326 profile->computeUpdatedPrediction(locker, codeBlock, structure);
2327 }
2328 repatchArrayGetByVal(globalObject, codeBlock, baseValue, subscript, *stubInfo);
2329 }
2330 }
2331
2332 if (baseValue.isCell() && CacheableIdentifier::isCacheableIdentifierCell(subscript)) {
2333 const Identifier propertyName = subscript.toPropertyKey(globalObject);
2334 RETURN_IF_EXCEPTION(scope, encodedJSValue());
2335 if (subscript.isSymbol() || !parseIndex(propertyName)) {
2336 scope.release();
2337 return JSValue::encode(baseValue.getPropertySlot(globalObject, propertyName, [&] (bool found, PropertySlot& slot) -> JSValue {
2338 LOG_IC((ICEvent::OperationGetByValOptimize, baseValue.classInfoOrNull(), propertyName, baseValue == slot.slotBase()));
2339
2340 CacheableIdentifier identifier = CacheableIdentifier::createFromCell(subscript.asCell());
2341 if (stubInfo->considerCachingBy(vm, codeBlock, baseValue.structureOrNull(), identifier))
2342 repatchGetBy(globalObject, codeBlock, baseValue, identifier, slot, *stubInfo, GetByKind::ByVal);
2343 return found ? slot.getValue(globalObject, propertyName) : jsUndefined();
2344 }));
2345 }
2346 }
2347
2348 RELEASE_AND_RETURN(scope, JSValue::encode(getByVal(globalObject, callFrame, profile, baseValue, subscript)));
2349}
2350
2351JSC_DEFINE_JIT_OPERATION(operationGetByVal, EncodedJSValue, (JSGlobalObject* globalObject, EncodedJSValue encodedBase, EncodedJSValue encodedProperty))
2352{
2353 VM& vm = globalObject->vm();
2354 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2355 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2356 auto scope = DECLARE_THROW_SCOPE(vm);
2357
2358 JSValue baseValue = JSValue::decode(encodedBase);
2359 JSValue property = JSValue::decode(encodedProperty);
2360
2361 if (LIKELY(baseValue.isCell())) {
2362 JSCell* base = baseValue.asCell();
2363
2364 if (std::optional<uint32_t> index = property.tryGetAsUint32Index())
2365 RELEASE_AND_RETURN(scope, getByValWithIndex(globalObject, base, *index));
2366
2367 if (property.isString()) {
2368 Structure& structure = *base->structure();
2369 if (JSCell::canUseFastGetOwnProperty(structure)) {
2370 auto existingAtomString = asString(property)->toExistingAtomString(globalObject);
2371 RETURN_IF_EXCEPTION(scope, encodedJSValue());
2372 if (!existingAtomString.isNull()) {
2373 if (JSValue result = base->fastGetOwnProperty(vm, structure, existingAtomString.impl()))
2374 return JSValue::encode(result);
2375 }
2376 }
2377 }
2378 }
2379
2380 baseValue.requireObjectCoercible(globalObject);
2381 RETURN_IF_EXCEPTION(scope, encodedJSValue());
2382 auto propertyName = property.toPropertyKey(globalObject);
2383 RETURN_IF_EXCEPTION(scope, encodedJSValue());
2384 RELEASE_AND_RETURN(scope, JSValue::encode(baseValue.get(globalObject, propertyName)));
2385}
2386
2387ALWAYS_INLINE static JSValue getPrivateName(JSGlobalObject* globalObject, CallFrame* callFrame, JSValue baseValue, JSValue fieldNameValue)
2388{
2389 UNUSED_PARAM(callFrame);
2390 VM& vm = globalObject->vm();
2391 auto scope = DECLARE_THROW_SCOPE(vm);
2392
2393 JSObject* base = baseValue.toObject(globalObject);
2394 RETURN_IF_EXCEPTION(scope, JSValue());
2395 auto fieldName = fieldNameValue.toPropertyKey(globalObject);
2396 RETURN_IF_EXCEPTION(scope, JSValue());
2397
2398 PropertySlot slot(base, PropertySlot::InternalMethodType::GetOwnProperty);
2399 base->getPrivateField(globalObject, fieldName, slot);
2400 RETURN_IF_EXCEPTION(scope, JSValue());
2401
2402 return slot.getValue(globalObject, fieldName);
2403}
2404
2405ALWAYS_INLINE static JSValue getPrivateName(JSGlobalObject* globalObject, CallFrame* callFrame, JSValue baseValue, Identifier fieldName)
2406{
2407 ASSERT(fieldName.isPrivateName());
2408 UNUSED_PARAM(callFrame);
2409 VM& vm = globalObject->vm();
2410 auto scope = DECLARE_THROW_SCOPE(vm);
2411
2412 baseValue.requireObjectCoercible(globalObject);
2413 RETURN_IF_EXCEPTION(scope, JSValue());
2414
2415 JSObject* base = baseValue.toObject(globalObject);
2416 RETURN_IF_EXCEPTION(scope, JSValue());
2417
2418 PropertySlot slot(base, PropertySlot::InternalMethodType::GetOwnProperty);
2419 base->getPrivateField(globalObject, fieldName, slot);
2420 RETURN_IF_EXCEPTION(scope, JSValue());
2421
2422 return slot.getValue(globalObject, fieldName);
2423}
2424
2425JSC_DEFINE_JIT_OPERATION(operationGetPrivateNameOptimize, EncodedJSValue, (JSGlobalObject* globalObject, StructureStubInfo* stubInfo, EncodedJSValue encodedBase, EncodedJSValue encodedFieldName))
2426{
2427 VM& vm = globalObject->vm();
2428 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2429 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2430 auto scope = DECLARE_THROW_SCOPE(vm);
2431
2432 JSValue baseValue = JSValue::decode(encodedBase);
2433 JSValue fieldNameValue = JSValue::decode(encodedFieldName);
2434 ASSERT(CacheableIdentifier::isCacheableIdentifierCell(fieldNameValue));
2435
2436 CodeBlock* codeBlock = callFrame->codeBlock();
2437
2438 if (baseValue.isObject()) {
2439 const Identifier fieldName = fieldNameValue.toPropertyKey(globalObject);
2440 EXCEPTION_ASSERT(!scope.exception() || vm.hasPendingTerminationException());
2441 RETURN_IF_EXCEPTION(scope, encodedJSValue());
2442 ASSERT(fieldName.isSymbol());
2443
2444 JSObject* base = jsCast<JSObject*>(baseValue.asCell());
2445
2446 PropertySlot slot(base, PropertySlot::InternalMethodType::GetOwnProperty);
2447 base->getPrivateField(globalObject, fieldName, slot);
2448 RETURN_IF_EXCEPTION(scope, encodedJSValue());
2449
2450 LOG_IC((ICEvent::OperationGetPrivateNameOptimize, baseValue.classInfoOrNull(), fieldName, true));
2451
2452 CacheableIdentifier identifier = CacheableIdentifier::createFromCell(fieldNameValue.asCell());
2453 if (stubInfo->considerCachingBy(vm, codeBlock, baseValue.structureOrNull(), identifier))
2454 repatchGetBy(globalObject, codeBlock, baseValue, identifier, slot, *stubInfo, GetByKind::PrivateName);
2455 return JSValue::encode(slot.getValue(globalObject, fieldName));
2456 }
2457
2458 RELEASE_AND_RETURN(scope, JSValue::encode(getPrivateName(globalObject, callFrame, baseValue, fieldNameValue)));
2459}
2460
2461JSC_DEFINE_JIT_OPERATION(operationGetPrivateName, EncodedJSValue, (JSGlobalObject* globalObject, StructureStubInfo* stubInfo, EncodedJSValue encodedBase, EncodedJSValue encodedFieldName))
2462{
2463 VM& vm = globalObject->vm();
2464 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2465 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2466
2467 JSValue baseValue = JSValue::decode(encodedBase);
2468 JSValue fieldNameValue = JSValue::decode(encodedFieldName);
2469
2470 if (stubInfo)
2471 stubInfo->tookSlowPath = true;
2472
2473 return JSValue::encode(getPrivateName(globalObject, callFrame, baseValue, fieldNameValue));
2474}
2475
2476JSC_DEFINE_JIT_OPERATION(operationGetPrivateNameById, EncodedJSValue, (JSGlobalObject* globalObject, StructureStubInfo* stubInfo, EncodedJSValue base, uintptr_t rawCacheableIdentifier))
2477{
2478 SuperSamplerScope superSamplerScope(false);
2479
2480 VM& vm = globalObject->vm();
2481 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2482 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2483
2484 stubInfo->tookSlowPath = true;
2485
2486 JSValue baseValue = JSValue::decode(base);
2487 CacheableIdentifier identifier = CacheableIdentifier::createFromRawBits(rawCacheableIdentifier);
2488 Identifier fieldName = Identifier::fromUid(vm, identifier.uid());
2489
2490 JSValue result = getPrivateName(globalObject, callFrame, baseValue, fieldName);
2491
2492 LOG_IC((ICEvent::OperationGetPrivateNameById, baseValue.classInfoOrNull(), fieldName, true));
2493
2494 return JSValue::encode(result);
2495}
2496
2497JSC_DEFINE_JIT_OPERATION(operationGetPrivateNameByIdOptimize, EncodedJSValue, (JSGlobalObject* globalObject, StructureStubInfo* stubInfo, EncodedJSValue base, uintptr_t rawCacheableIdentifier))
2498{
2499 SuperSamplerScope superSamplerScope(false);
2500
2501 VM& vm = globalObject->vm();
2502 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2503 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2504 CacheableIdentifier identifier = CacheableIdentifier::createFromRawBits(rawCacheableIdentifier);
2505 auto scope = DECLARE_THROW_SCOPE(vm);
2506
2507 JSValue baseValue = JSValue::decode(base);
2508 auto fieldName = Identifier::fromUid(vm, identifier.uid());
2509
2510 if (baseValue.isObject()) {
2511 JSObject* base = jsCast<JSObject*>(baseValue.asCell());
2512
2513 PropertySlot slot(base, PropertySlot::InternalMethodType::GetOwnProperty);
2514 base->getPrivateField(globalObject, fieldName, slot);
2515 RETURN_IF_EXCEPTION(scope, encodedJSValue());
2516
2517 LOG_IC((ICEvent::OperationGetPrivateNameOptimize, baseValue.classInfoOrNull(), fieldName, true));
2518
2519 CodeBlock* codeBlock = callFrame->codeBlock();
2520 if (stubInfo->considerCachingBy(vm, codeBlock, baseValue.structureOrNull(), identifier))
2521 repatchGetBy(globalObject, codeBlock, baseValue, identifier, slot, *stubInfo, GetByKind::PrivateNameById);
2522 return JSValue::encode(slot.getValue(globalObject, fieldName));
2523 }
2524
2525 RELEASE_AND_RETURN(scope, JSValue::encode(getPrivateName(globalObject, callFrame, baseValue, fieldName)));
2526}
2527
2528JSC_DEFINE_JIT_OPERATION(operationGetPrivateNameByIdGeneric, EncodedJSValue, (JSGlobalObject* globalObject, EncodedJSValue base, uintptr_t rawCacheableIdentifier))
2529{
2530 SuperSamplerScope superSamplerScope(false);
2531
2532 VM& vm = globalObject->vm();
2533 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2534 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2535
2536 JSValue baseValue = JSValue::decode(base);
2537 CacheableIdentifier identifier = CacheableIdentifier::createFromRawBits(rawCacheableIdentifier);
2538 Identifier fieldName = Identifier::fromUid(vm, identifier.uid());
2539
2540 JSValue result = getPrivateName(globalObject, callFrame, baseValue, fieldName);
2541
2542 LOG_IC((ICEvent::OperationGetPrivateNameByIdGeneric, baseValue.classInfoOrNull(), fieldName, true));
2543
2544 return JSValue::encode(result);
2545}
2546
2547static bool deleteById(JSGlobalObject* globalObject, VM& vm, DeletePropertySlot& slot, JSValue base, const Identifier& ident, ECMAMode ecmaMode)
2548{
2549 auto scope = DECLARE_THROW_SCOPE(vm);
2550
2551 JSObject* baseObj = base.toObject(globalObject);
2552 RETURN_IF_EXCEPTION(scope, false);
2553 if (!baseObj)
2554 return false;
2555 bool couldDelete = baseObj->methodTable()->deleteProperty(baseObj, globalObject, ident, slot);
2556 RETURN_IF_EXCEPTION(scope, false);
2557 if (!couldDelete && ecmaMode.isStrict())
2558 throwTypeError(globalObject, scope, UnableToDeletePropertyError);
2559 return couldDelete;
2560}
2561
2562JSC_DEFINE_JIT_OPERATION(operationDeleteByIdOptimize, size_t, (JSGlobalObject* globalObject, StructureStubInfo* stubInfo, EncodedJSValue encodedBase, uintptr_t rawCacheableIdentifier, ECMAMode ecmaMode))
2563{
2564 VM& vm = globalObject->vm();
2565 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2566 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2567 auto scope = DECLARE_THROW_SCOPE(vm);
2568 JSValue baseValue = JSValue::decode(encodedBase);
2569
2570 DeletePropertySlot slot;
2571 Structure* oldStructure = baseValue.structureOrNull();
2572
2573 CacheableIdentifier identifier = CacheableIdentifier::createFromRawBits(rawCacheableIdentifier);
2574 Identifier ident = Identifier::fromUid(vm, identifier.uid());
2575
2576 bool result = deleteById(globalObject, vm, slot, baseValue, ident, ecmaMode);
2577 RETURN_IF_EXCEPTION(scope, encodedJSValue());
2578
2579 if (baseValue.isObject()) {
2580 if (!parseIndex(ident)) {
2581 CodeBlock* codeBlock = callFrame->codeBlock();
2582 if (stubInfo->considerCachingBy(vm, codeBlock, baseValue.structureOrNull(), identifier))
2583 repatchDeleteBy(globalObject, codeBlock, slot, baseValue, oldStructure, identifier, *stubInfo, DelByKind::ById, ecmaMode);
2584 }
2585 }
2586
2587 return result;
2588}
2589
2590JSC_DEFINE_JIT_OPERATION(operationDeleteByIdGeneric, size_t, (JSGlobalObject* globalObject, StructureStubInfo*, EncodedJSValue encodedBase, uintptr_t rawCacheableIdentifier, ECMAMode ecmaMode))
2591{
2592 VM& vm = globalObject->vm();
2593 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2594 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2595 CacheableIdentifier identifier = CacheableIdentifier::createFromRawBits(rawCacheableIdentifier);
2596 Identifier ident = Identifier::fromUid(vm, identifier.uid());
2597 DeletePropertySlot slot;
2598 return deleteById(globalObject, vm, slot, JSValue::decode(encodedBase), ident, ecmaMode);
2599}
2600
2601static bool deleteByVal(JSGlobalObject* globalObject, VM& vm, DeletePropertySlot& slot, JSValue base, JSValue key, ECMAMode ecmaMode)
2602{
2603 auto scope = DECLARE_THROW_SCOPE(vm);
2604
2605 JSObject* baseObj = base.toObject(globalObject);
2606 RETURN_IF_EXCEPTION(scope, false);
2607 if (!baseObj)
2608 return false;
2609
2610 bool couldDelete;
2611 uint32_t index;
2612 if (key.getUInt32(index))
2613 couldDelete = baseObj->methodTable()->deletePropertyByIndex(baseObj, globalObject, index);
2614 else {
2615 Identifier property = key.toPropertyKey(globalObject);
2616 RETURN_IF_EXCEPTION(scope, false);
2617 couldDelete = baseObj->methodTable()->deleteProperty(baseObj, globalObject, property, slot);
2618 }
2619 RETURN_IF_EXCEPTION(scope, false);
2620 if (!couldDelete && ecmaMode.isStrict())
2621 throwTypeError(globalObject, scope, UnableToDeletePropertyError);
2622 return couldDelete;
2623}
2624
2625JSC_DEFINE_JIT_OPERATION(operationDeleteByValOptimize, size_t, (JSGlobalObject* globalObject, StructureStubInfo* stubInfo, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript, ECMAMode ecmaMode))
2626{
2627 VM& vm = globalObject->vm();
2628 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2629 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2630 auto scope = DECLARE_THROW_SCOPE(vm);
2631 JSValue baseValue = JSValue::decode(encodedBase);
2632 JSValue subscript = JSValue::decode(encodedSubscript);
2633
2634 DeletePropertySlot slot;
2635 Structure* oldStructure = baseValue.structureOrNull();
2636
2637 bool result = deleteByVal(globalObject, vm, slot, baseValue, subscript, ecmaMode);
2638 RETURN_IF_EXCEPTION(scope, encodedJSValue());
2639
2640 if (baseValue.isObject() && CacheableIdentifier::isCacheableIdentifierCell(subscript)) {
2641 const Identifier propertyName = subscript.toPropertyKey(globalObject);
2642 RETURN_IF_EXCEPTION(scope, encodedJSValue());
2643
2644 if (subscript.isSymbol() || !parseIndex(propertyName)) {
2645 CodeBlock* codeBlock = callFrame->codeBlock();
2646 CacheableIdentifier identifier = CacheableIdentifier::createFromCell(subscript.asCell());
2647 if (stubInfo->considerCachingBy(vm, codeBlock, baseValue.structureOrNull(), identifier))
2648 repatchDeleteBy(globalObject, codeBlock, slot, baseValue, oldStructure, identifier, *stubInfo, DelByKind::ByVal, ecmaMode);
2649 }
2650 }
2651
2652 return result;
2653}
2654
2655JSC_DEFINE_JIT_OPERATION(operationDeleteByValGeneric, size_t, (JSGlobalObject* globalObject, StructureStubInfo*, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript, ECMAMode ecmaMode))
2656{
2657 VM& vm = globalObject->vm();
2658 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2659 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2660 DeletePropertySlot slot;
2661 return deleteByVal(globalObject, vm, slot, JSValue::decode(encodedBase), JSValue::decode(encodedSubscript), ecmaMode);
2662}
2663
2664JSC_DEFINE_JIT_OPERATION(operationPushWithScope, JSCell*, (JSGlobalObject* globalObject, JSCell* currentScopeCell, EncodedJSValue objectValue))
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 JSObject* object = JSValue::decode(objectValue).toObject(globalObject);
2672 RETURN_IF_EXCEPTION(scope, nullptr);
2673
2674 JSScope* currentScope = jsCast<JSScope*>(currentScopeCell);
2675
2676 return JSWithScope::create(vm, globalObject, currentScope, object);
2677}
2678
2679JSC_DEFINE_JIT_OPERATION(operationPushWithScopeObject, JSCell*, (JSGlobalObject* globalObject, JSCell* currentScopeCell, JSObject* object))
2680{
2681 VM& vm = globalObject->vm();
2682 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2683 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2684 JSScope* currentScope = jsCast<JSScope*>(currentScopeCell);
2685 return JSWithScope::create(vm, globalObject, currentScope, object);
2686}
2687
2688JSC_DEFINE_JIT_OPERATION(operationInstanceOfGeneric, EncodedJSValue, (JSGlobalObject* globalObject, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedProto))
2689{
2690 VM& vm = globalObject->vm();
2691 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2692 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2693 JSValue value = JSValue::decode(encodedValue);
2694 JSValue proto = JSValue::decode(encodedProto);
2695
2696 stubInfo->tookSlowPath = true;
2697
2698 bool result = JSObject::defaultHasInstance(globalObject, value, proto);
2699 return JSValue::encode(jsBoolean(result));
2700}
2701
2702JSC_DEFINE_JIT_OPERATION(operationInstanceOfOptimize, EncodedJSValue, (JSGlobalObject* globalObject, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedProto))
2703{
2704 VM& vm = globalObject->vm();
2705 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2706 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2707 auto scope = DECLARE_THROW_SCOPE(vm);
2708 JSValue value = JSValue::decode(encodedValue);
2709 JSValue proto = JSValue::decode(encodedProto);
2710
2711 bool result = JSObject::defaultHasInstance(globalObject, value, proto);
2712 RETURN_IF_EXCEPTION(scope, JSValue::encode(jsUndefined()));
2713
2714 CodeBlock* codeBlock = callFrame->codeBlock();
2715 if (stubInfo->considerCachingGeneric(vm, codeBlock, value.structureOrNull()))
2716 repatchInstanceOf(globalObject, codeBlock, value, proto, *stubInfo, result);
2717
2718 return JSValue::encode(jsBoolean(result));
2719}
2720
2721JSC_DEFINE_JIT_OPERATION(operationSizeFrameForForwardArguments, int32_t, (JSGlobalObject* globalObject, EncodedJSValue, int32_t numUsedStackSlots, int32_t))
2722{
2723 VM& vm = globalObject->vm();
2724 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2725 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2726 return sizeFrameForForwardArguments(globalObject, callFrame, vm, numUsedStackSlots);
2727}
2728
2729JSC_DEFINE_JIT_OPERATION(operationSizeFrameForVarargs, int32_t, (JSGlobalObject* globalObject, EncodedJSValue encodedArguments, int32_t numUsedStackSlots, int32_t firstVarArgOffset))
2730{
2731 VM& vm = globalObject->vm();
2732 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2733 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2734 JSValue arguments = JSValue::decode(encodedArguments);
2735 return sizeFrameForVarargs(globalObject, callFrame, vm, arguments, numUsedStackSlots, firstVarArgOffset);
2736}
2737
2738JSC_DEFINE_JIT_OPERATION(operationSetupForwardArgumentsFrame, CallFrame*, (JSGlobalObject* globalObject, CallFrame* newCallFrame, EncodedJSValue, int32_t, int32_t length))
2739{
2740 VM& vm = globalObject->vm();
2741 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2742 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2743 setupForwardArgumentsFrame(globalObject, callFrame, newCallFrame, length);
2744 return newCallFrame;
2745}
2746
2747JSC_DEFINE_JIT_OPERATION(operationSetupVarargsFrame, CallFrame*, (JSGlobalObject* globalObject, CallFrame* newCallFrame, EncodedJSValue encodedArguments, int32_t firstVarArgOffset, int32_t length))
2748{
2749 VM& vm = globalObject->vm();
2750 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2751 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2752 JSValue arguments = JSValue::decode(encodedArguments);
2753 setupVarargsFrame(globalObject, callFrame, newCallFrame, arguments, firstVarArgOffset, length);
2754 return newCallFrame;
2755}
2756
2757JSC_DEFINE_JIT_OPERATION(operationSwitchCharWithUnknownKeyType, char*, (JSGlobalObject* globalObject, EncodedJSValue encodedKey, size_t tableIndex, int32_t min))
2758{
2759 VM& vm = globalObject->vm();
2760 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2761 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2762 auto throwScope = DECLARE_THROW_SCOPE(vm);
2763
2764 JSValue key = JSValue::decode(encodedKey);
2765 CodeBlock* codeBlock = callFrame->codeBlock();
2766
2767 const SimpleJumpTable& linkedTable = codeBlock->baselineSwitchJumpTable(tableIndex);
2768 ASSERT(codeBlock->unlinkedSwitchJumpTable(tableIndex).m_min == min);
2769 void* result = linkedTable.m_ctiDefault.executableAddress();
2770
2771 if (key.isString()) {
2772 JSString* string = asString(key);
2773 if (string->length() == 1) {
2774 String value = string->value(globalObject);
2775 RETURN_IF_EXCEPTION(throwScope, nullptr);
2776 result = linkedTable.ctiForValue(min, value[0]).executableAddress();
2777 }
2778 }
2779
2780 assertIsTaggedWith<JSSwitchPtrTag>(result);
2781 return reinterpret_cast<char*>(result);
2782}
2783
2784JSC_DEFINE_JIT_OPERATION(operationSwitchImmWithUnknownKeyType, char*, (VM* vmPointer, EncodedJSValue encodedKey, size_t tableIndex, int32_t min))
2785{
2786 VM& vm = *vmPointer;
2787 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2788 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2789 JSValue key = JSValue::decode(encodedKey);
2790 CodeBlock* codeBlock = callFrame->codeBlock();
2791
2792 const SimpleJumpTable& linkedTable = codeBlock->baselineSwitchJumpTable(tableIndex);
2793 ASSERT(codeBlock->unlinkedSwitchJumpTable(tableIndex).m_min == min);
2794 void* result;
2795 if (key.isInt32())
2796 result = linkedTable.ctiForValue(min, key.asInt32()).executableAddress();
2797 else if (key.isDouble() && key.asDouble() == static_cast<int32_t>(key.asDouble()))
2798 result = linkedTable.ctiForValue(min, static_cast<int32_t>(key.asDouble())).executableAddress();
2799 else
2800 result = linkedTable.m_ctiDefault.executableAddress();
2801 assertIsTaggedWith<JSSwitchPtrTag>(result);
2802 return reinterpret_cast<char*>(result);
2803}
2804
2805JSC_DEFINE_JIT_OPERATION(operationSwitchStringWithUnknownKeyType, char*, (JSGlobalObject* globalObject, EncodedJSValue encodedKey, size_t tableIndex))
2806{
2807 VM& vm = globalObject->vm();
2808 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2809 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2810 JSValue key = JSValue::decode(encodedKey);
2811 CodeBlock* codeBlock = callFrame->codeBlock();
2812 auto throwScope = DECLARE_THROW_SCOPE(vm);
2813
2814 void* result;
2815 const StringJumpTable& linkedTable = codeBlock->baselineStringSwitchJumpTable(tableIndex);
2816
2817 if (key.isString()) {
2818 StringImpl* value = asString(key)->value(globalObject).impl();
2819
2820 RETURN_IF_EXCEPTION(throwScope, nullptr);
2821
2822 const UnlinkedStringJumpTable& unlinkedTable = codeBlock->unlinkedStringSwitchJumpTable(tableIndex);
2823 result = linkedTable.ctiForValue(unlinkedTable, value).executableAddress();
2824 } else
2825 result = linkedTable.ctiDefault().executableAddress();
2826
2827 assertIsTaggedWith<JSSwitchPtrTag>(result);
2828 return reinterpret_cast<char*>(result);
2829}
2830
2831JSC_DEFINE_JIT_OPERATION(operationResolveScopeForBaseline, EncodedJSValue, (JSGlobalObject* globalObject, const JSInstruction* pc))
2832{
2833 VM& vm = globalObject->vm();
2834 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2835 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2836 auto throwScope = DECLARE_THROW_SCOPE(vm);
2837
2838 CodeBlock* codeBlock = callFrame->codeBlock();
2839
2840 auto bytecode = pc->as<OpResolveScope>();
2841 const Identifier& ident = codeBlock->identifier(bytecode.m_var);
2842 JSScope* scope = callFrame->uncheckedR(bytecode.m_scope).Register::scope();
2843 JSObject* resolvedScope = JSScope::resolve(globalObject, scope, ident);
2844 // Proxy can throw an error here, e.g. Proxy in with statement's @unscopables.
2845 RETURN_IF_EXCEPTION(throwScope, { });
2846
2847 auto& metadata = bytecode.metadata(codeBlock);
2848 ResolveType resolveType = metadata.m_resolveType;
2849
2850 // ModuleVar does not keep the scope register value alive in DFG.
2851 ASSERT(resolveType != ModuleVar);
2852
2853 switch (resolveType) {
2854 case GlobalProperty:
2855 case GlobalPropertyWithVarInjectionChecks:
2856 case UnresolvedProperty:
2857 case UnresolvedPropertyWithVarInjectionChecks: {
2858 if (resolvedScope->isGlobalObject()) {
2859 JSGlobalObject* globalObject = jsCast<JSGlobalObject*>(resolvedScope);
2860 bool hasProperty = globalObject->hasProperty(globalObject, ident);
2861 RETURN_IF_EXCEPTION(throwScope, { });
2862 if (hasProperty) {
2863 ConcurrentJSLocker locker(codeBlock->m_lock);
2864 metadata.m_resolveType = needsVarInjectionChecks(resolveType) ? GlobalPropertyWithVarInjectionChecks : GlobalProperty;
2865 metadata.m_globalObject.set(vm, codeBlock, globalObject);
2866 metadata.m_globalLexicalBindingEpoch = globalObject->globalLexicalBindingEpoch();
2867 }
2868 } else if (resolvedScope->isGlobalLexicalEnvironment()) {
2869 JSGlobalLexicalEnvironment* globalLexicalEnvironment = jsCast<JSGlobalLexicalEnvironment*>(resolvedScope);
2870 ConcurrentJSLocker locker(codeBlock->m_lock);
2871 metadata.m_resolveType = needsVarInjectionChecks(resolveType) ? GlobalLexicalVarWithVarInjectionChecks : GlobalLexicalVar;
2872 metadata.m_globalLexicalEnvironment.set(vm, codeBlock, globalLexicalEnvironment);
2873 }
2874 break;
2875 }
2876 default:
2877 break;
2878 }
2879
2880 return JSValue::encode(resolvedScope);
2881}
2882
2883JSC_DEFINE_JIT_OPERATION(operationGetFromScope, EncodedJSValue, (JSGlobalObject* globalObject, const JSInstruction* pc))
2884{
2885 VM& vm = globalObject->vm();
2886 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2887 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2888 auto throwScope = DECLARE_THROW_SCOPE(vm);
2889
2890 CodeBlock* codeBlock = callFrame->codeBlock();
2891
2892 auto bytecode = pc->as<OpGetFromScope>();
2893 const Identifier& ident = codeBlock->identifier(bytecode.m_var);
2894 JSObject* scope = jsCast<JSObject*>(callFrame->uncheckedR(bytecode.m_scope).jsValue());
2895 GetPutInfo& getPutInfo = bytecode.metadata(codeBlock).m_getPutInfo;
2896
2897 // ModuleVar is always converted to ClosureVar for get_from_scope.
2898 ASSERT(getPutInfo.resolveType() != ModuleVar);
2899
2900 RELEASE_AND_RETURN(throwScope, JSValue::encode(scope->getPropertySlot(globalObject, ident, [&] (bool found, PropertySlot& slot) -> JSValue {
2901 if (!found) {
2902 if (getPutInfo.resolveMode() == ThrowIfNotFound)
2903 throwException(globalObject, throwScope, createUndefinedVariableError(globalObject, ident));
2904 return jsUndefined();
2905 }
2906
2907 JSValue result = JSValue();
2908 if (scope->isGlobalLexicalEnvironment()) {
2909 // When we can't statically prove we need a TDZ check, we must perform the check on the slow path.
2910 result = slot.getValue(globalObject, ident);
2911 if (result == jsTDZValue()) {
2912 throwException(globalObject, throwScope, createTDZError(globalObject));
2913 return jsUndefined();
2914 }
2915 }
2916
2917 CommonSlowPaths::tryCacheGetFromScopeGlobal(globalObject, codeBlock, vm, bytecode, scope, slot, ident);
2918
2919 if (!result)
2920 return slot.getValue(globalObject, ident);
2921 return result;
2922 })));
2923}
2924
2925JSC_DEFINE_JIT_OPERATION(operationPutToScope, void, (JSGlobalObject* globalObject, const JSInstruction* pc))
2926{
2927 VM& vm = globalObject->vm();
2928 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2929 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2930 auto throwScope = DECLARE_THROW_SCOPE(vm);
2931
2932 CodeBlock* codeBlock = callFrame->codeBlock();
2933 auto bytecode = pc->as<OpPutToScope>();
2934 auto& metadata = bytecode.metadata(codeBlock);
2935
2936 const Identifier& ident = codeBlock->identifier(bytecode.m_var);
2937 JSObject* scope = jsCast<JSObject*>(callFrame->uncheckedR(bytecode.m_scope).jsValue());
2938 JSValue value = callFrame->r(bytecode.m_value).jsValue();
2939 GetPutInfo& getPutInfo = metadata.m_getPutInfo;
2940
2941 // ModuleVar does not keep the scope register value alive in DFG.
2942 ASSERT(getPutInfo.resolveType() != ModuleVar);
2943
2944 if (getPutInfo.resolveType() == ResolvedClosureVar) {
2945 JSLexicalEnvironment* environment = jsCast<JSLexicalEnvironment*>(scope);
2946 environment->variableAt(ScopeOffset(metadata.m_operand)).set(vm, environment, value);
2947 if (WatchpointSet* set = metadata.m_watchpointSet)
2948 set->touch(vm, "Executed op_put_scope<ResolvedClosureVar>");
2949 return;
2950 }
2951
2952 bool hasProperty = scope->hasProperty(globalObject, ident);
2953 RETURN_IF_EXCEPTION(throwScope, void());
2954 if (hasProperty
2955 && scope->isGlobalLexicalEnvironment()
2956 && !isInitialization(getPutInfo.initializationMode())) {
2957 // When we can't statically prove we need a TDZ check, we must perform the check on the slow path.
2958 PropertySlot slot(scope, PropertySlot::InternalMethodType::Get);
2959 JSGlobalLexicalEnvironment::getOwnPropertySlot(scope, globalObject, ident, slot);
2960 if (slot.getValue(globalObject, ident) == jsTDZValue()) {
2961 throwException(globalObject, throwScope, createTDZError(globalObject));
2962 return;
2963 }
2964 }
2965
2966 if (getPutInfo.resolveMode() == ThrowIfNotFound && !hasProperty) {
2967 throwException(globalObject, throwScope, createUndefinedVariableError(globalObject, ident));
2968 return;
2969 }
2970
2971 PutPropertySlot slot(scope, getPutInfo.ecmaMode().isStrict(), PutPropertySlot::UnknownContext, isInitialization(getPutInfo.initializationMode()));
2972 scope->methodTable()->put(scope, globalObject, ident, value, slot);
2973
2974 RETURN_IF_EXCEPTION(throwScope, void());
2975
2976 CommonSlowPaths::tryCachePutToScopeGlobal(globalObject, codeBlock, bytecode, scope, slot, ident);
2977}
2978
2979JSC_DEFINE_JIT_OPERATION(operationThrow, void, (JSGlobalObject* globalObject, EncodedJSValue encodedExceptionValue))
2980{
2981 VM& vm = globalObject->vm();
2982 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2983 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2984 auto scope = DECLARE_THROW_SCOPE(vm);
2985
2986 JSValue exceptionValue = JSValue::decode(encodedExceptionValue);
2987 throwException(globalObject, scope, exceptionValue);
2988
2989 // Results stored out-of-band in vm.targetMachinePCForThrow & vm.callFrameForCatch
2990 genericUnwind(vm, callFrame);
2991}
2992
2993JSC_DEFINE_JIT_OPERATION(operationReallocateButterflyToHavePropertyStorageWithInitialCapacity, char*, (VM* vmPointer, JSObject* object))
2994{
2995 VM& vm = *vmPointer;
2996 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
2997 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
2998
2999 ASSERT(!object->structure()->outOfLineCapacity());
3000 Butterfly* result = object->allocateMoreOutOfLineStorage(vm, 0, initialOutOfLineCapacity);
3001 object->nukeStructureAndSetButterfly(vm, object->structureID(), result);
3002 return reinterpret_cast<char*>(result);
3003}
3004
3005JSC_DEFINE_JIT_OPERATION(operationReallocateButterflyToGrowPropertyStorage, char*, (VM* vmPointer, JSObject* object, size_t newSize))
3006{
3007 VM& vm = *vmPointer;
3008 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
3009 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
3010
3011 Butterfly* result = object->allocateMoreOutOfLineStorage(vm, object->structure()->outOfLineCapacity(), newSize);
3012 object->nukeStructureAndSetButterfly(vm, object->structureID(), result);
3013 return reinterpret_cast<char*>(result);
3014}
3015
3016JSC_DEFINE_JIT_OPERATION(operationOSRWriteBarrier, void, (VM* vmPointer, JSCell* cell))
3017{
3018 VM& vm = *vmPointer;
3019 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
3020 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
3021 vm.writeBarrier(cell);
3022}
3023
3024JSC_DEFINE_JIT_OPERATION(operationWriteBarrierSlowPath, void, (VM* vmPointer, JSCell* cell))
3025{
3026 VM& vm = *vmPointer;
3027 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
3028 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
3029 vm.writeBarrierSlowPath(cell);
3030}
3031
3032JSC_DEFINE_JIT_OPERATION(operationLookupExceptionHandler, void, (VM* vmPointer))
3033{
3034 VM& vm = *vmPointer;
3035 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
3036 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
3037 genericUnwind(vm, callFrame);
3038 ASSERT(vm.targetMachinePCForThrow);
3039}
3040
3041JSC_DEFINE_JIT_OPERATION(operationLookupExceptionHandlerFromCallerFrame, void, (VM* vmPointer))
3042{
3043 VM& vm = *vmPointer;
3044 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
3045 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
3046 ASSERT(callFrame->isStackOverflowFrame());
3047 ASSERT(jsCast<ErrorInstance*>(vm.exceptionForInspection()->value().asCell())->isStackOverflowError());
3048 genericUnwind(vm, callFrame);
3049 ASSERT(vm.targetMachinePCForThrow);
3050}
3051
3052JSC_DEFINE_JIT_OPERATION(operationVMHandleException, void, (VM* vmPointer))
3053{
3054 VM& vm = *vmPointer;
3055 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
3056 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
3057 genericUnwind(vm, callFrame);
3058}
3059
3060// This function "should" just take the JSGlobalObject*, but doing so would make it more difficult
3061// to call from exception check sites. So, unlike all of our other functions, we allow
3062// ourselves to play some gnarly ABI tricks just to simplify the calling convention. This is
3063// particularly safe here since this is never called on the critical path - it's only for
3064// testing.
3065JSC_DEFINE_JIT_OPERATION(operationExceptionFuzz, void, (JSGlobalObject* globalObject))
3066{
3067 VM& vm = globalObject->vm();
3068 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
3069 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
3070 auto scope = DECLARE_THROW_SCOPE(vm);
3071 UNUSED_PARAM(scope);
3072#if COMPILER(GCC_COMPATIBLE)
3073 void* returnPC = __builtin_return_address(0);
3074 // FIXME (see rdar://72897291): Work around a Clang bug where __builtin_return_address()
3075 // sometimes gives us a signed pointer, and sometimes does not.
3076 returnPC = removeCodePtrTag(returnPC);
3077 doExceptionFuzzing(globalObject, scope, "JITOperations", returnPC);
3078#endif // COMPILER(GCC_COMPATIBLE)
3079}
3080
3081JSC_DEFINE_JIT_OPERATION(operationExceptionFuzzWithCallFrame, void, (VM* vmPointer))
3082{
3083 VM& vm = *vmPointer;
3084 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
3085 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
3086 auto scope = DECLARE_THROW_SCOPE(vm);
3087 UNUSED_PARAM(scope);
3088#if COMPILER(GCC_COMPATIBLE)
3089 void* returnPC = __builtin_return_address(0);
3090 // FIXME (see rdar://72897291): Work around a Clang bug where __builtin_return_address()
3091 // sometimes gives us a signed pointer, and sometimes does not.
3092 returnPC = removeCodePtrTag(returnPC);
3093 doExceptionFuzzing(callFrame->lexicalGlobalObject(vm), scope, "JITOperations", returnPC);
3094#endif // COMPILER(GCC_COMPATIBLE)
3095}
3096
3097JSC_DEFINE_JIT_OPERATION(operationValueAdd, EncodedJSValue, (JSGlobalObject* globalObject, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2))
3098{
3099 VM& vm = globalObject->vm();
3100 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
3101 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
3102 return JSValue::encode(jsAdd(globalObject, JSValue::decode(encodedOp1), JSValue::decode(encodedOp2)));
3103}
3104
3105JSC_DEFINE_JIT_OPERATION(operationValueAddProfiled, EncodedJSValue, (JSGlobalObject* globalObject, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, BinaryArithProfile* arithProfile))
3106{
3107 ASSERT(arithProfile);
3108 VM& vm = globalObject->vm();
3109 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
3110 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
3111 return JSValue::encode(profiledAdd(globalObject, JSValue::decode(encodedOp1), JSValue::decode(encodedOp2), *arithProfile));
3112}
3113
3114JSC_DEFINE_JIT_OPERATION(operationValueAddProfiledOptimize, EncodedJSValue, (JSGlobalObject* globalObject, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, JITAddIC* addIC))
3115{
3116 VM& vm = globalObject->vm();
3117 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
3118 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
3119
3120 JSValue op1 = JSValue::decode(encodedOp1);
3121 JSValue op2 = JSValue::decode(encodedOp2);
3122
3123 BinaryArithProfile* arithProfile = addIC->arithProfile();
3124 ASSERT(arithProfile);
3125 arithProfile->observeLHSAndRHS(op1, op2);
3126 auto nonOptimizeVariant = operationValueAddProfiledNoOptimize;
3127 addIC->generateOutOfLine(callFrame->codeBlock(), nonOptimizeVariant);
3128
3129#if ENABLE(MATH_IC_STATS)
3130 callFrame->codeBlock()->dumpMathICStats();
3131#endif
3132
3133 JSValue result = jsAdd(globalObject, op1, op2);
3134 arithProfile->observeResult(result);
3135
3136 return JSValue::encode(result);
3137}
3138
3139JSC_DEFINE_JIT_OPERATION(operationValueAddProfiledNoOptimize, EncodedJSValue, (JSGlobalObject* globalObject, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, JITAddIC* addIC))
3140{
3141 VM& vm = globalObject->vm();
3142 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
3143 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
3144
3145 BinaryArithProfile* arithProfile = addIC->arithProfile();
3146 ASSERT(arithProfile);
3147 return JSValue::encode(profiledAdd(globalObject, JSValue::decode(encodedOp1), JSValue::decode(encodedOp2), *arithProfile));
3148}
3149
3150JSC_DEFINE_JIT_OPERATION(operationValueAddOptimize, EncodedJSValue, (JSGlobalObject* globalObject, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, JITAddIC* addIC))
3151{
3152 VM& vm = globalObject->vm();
3153 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
3154 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
3155
3156 JSValue op1 = JSValue::decode(encodedOp1);
3157 JSValue op2 = JSValue::decode(encodedOp2);
3158
3159 auto nonOptimizeVariant = operationValueAddNoOptimize;
3160 if (BinaryArithProfile* arithProfile = addIC->arithProfile())
3161 arithProfile->observeLHSAndRHS(op1, op2);
3162 addIC->generateOutOfLine(callFrame->codeBlock(), nonOptimizeVariant);
3163
3164#if ENABLE(MATH_IC_STATS)
3165 callFrame->codeBlock()->dumpMathICStats();
3166#endif
3167
3168 return JSValue::encode(jsAdd(globalObject, op1, op2));
3169}
3170
3171JSC_DEFINE_JIT_OPERATION(operationValueAddNoOptimize, EncodedJSValue, (JSGlobalObject* globalObject, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, JITAddIC*))
3172{
3173 VM& vm = globalObject->vm();
3174 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
3175 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
3176
3177 JSValue op1 = JSValue::decode(encodedOp1);
3178 JSValue op2 = JSValue::decode(encodedOp2);
3179
3180 JSValue result = jsAdd(globalObject, op1, op2);
3181
3182 return JSValue::encode(result);
3183}
3184
3185ALWAYS_INLINE static EncodedJSValue unprofiledMul(JSGlobalObject* globalObject, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
3186{
3187 JSValue op1 = JSValue::decode(encodedOp1);
3188 JSValue op2 = JSValue::decode(encodedOp2);
3189
3190 return JSValue::encode(jsMul(globalObject, op1, op2));
3191}
3192
3193ALWAYS_INLINE static EncodedJSValue profiledMul(JSGlobalObject* globalObject, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, BinaryArithProfile& arithProfile, bool shouldObserveLHSAndRHSTypes = true)
3194{
3195 VM& vm = globalObject->vm();
3196 auto scope = DECLARE_THROW_SCOPE(vm);
3197 JSValue op1 = JSValue::decode(encodedOp1);
3198 JSValue op2 = JSValue::decode(encodedOp2);
3199
3200 if (shouldObserveLHSAndRHSTypes)
3201 arithProfile.observeLHSAndRHS(op1, op2);
3202
3203 JSValue result = jsMul(globalObject, op1, op2);
3204 RETURN_IF_EXCEPTION(scope, encodedJSValue());
3205 arithProfile.observeResult(result);
3206 return JSValue::encode(result);
3207}
3208
3209JSC_DEFINE_JIT_OPERATION(operationValueMul, EncodedJSValue, (JSGlobalObject* globalObject, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2))
3210{
3211 VM& vm = globalObject->vm();
3212 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
3213 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
3214
3215 return unprofiledMul(globalObject, encodedOp1, encodedOp2);
3216}
3217
3218JSC_DEFINE_JIT_OPERATION(operationValueMulNoOptimize, EncodedJSValue, (JSGlobalObject* globalObject, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, JITMulIC*))
3219{
3220 VM& vm = globalObject->vm();
3221 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
3222 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
3223
3224 return unprofiledMul(globalObject, encodedOp1, encodedOp2);
3225}
3226
3227JSC_DEFINE_JIT_OPERATION(operationValueMulOptimize, EncodedJSValue, (JSGlobalObject* globalObject, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, JITMulIC* mulIC))
3228{
3229 VM& vm = globalObject->vm();
3230 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
3231 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
3232
3233 auto nonOptimizeVariant = operationValueMulNoOptimize;
3234 if (BinaryArithProfile* arithProfile = mulIC->arithProfile())
3235 arithProfile->observeLHSAndRHS(JSValue::decode(encodedOp1), JSValue::decode(encodedOp2));
3236 mulIC->generateOutOfLine(callFrame->codeBlock(), nonOptimizeVariant);
3237
3238#if ENABLE(MATH_IC_STATS)
3239 callFrame->codeBlock()->dumpMathICStats();
3240#endif
3241
3242 return unprofiledMul(globalObject, encodedOp1, encodedOp2);
3243}
3244
3245JSC_DEFINE_JIT_OPERATION(operationValueMulProfiled, EncodedJSValue, (JSGlobalObject* globalObject, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, BinaryArithProfile* arithProfile))
3246{
3247 VM& vm = globalObject->vm();
3248 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
3249 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
3250
3251 ASSERT(arithProfile);
3252 return profiledMul(globalObject, encodedOp1, encodedOp2, *arithProfile);
3253}
3254
3255JSC_DEFINE_JIT_OPERATION(operationValueMulProfiledOptimize, EncodedJSValue, (JSGlobalObject* globalObject, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, JITMulIC* mulIC))
3256{
3257 VM& vm = globalObject->vm();
3258 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
3259 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
3260
3261 BinaryArithProfile* arithProfile = mulIC->arithProfile();
3262 ASSERT(arithProfile);
3263 arithProfile->observeLHSAndRHS(JSValue::decode(encodedOp1), JSValue::decode(encodedOp2));
3264 auto nonOptimizeVariant = operationValueMulProfiledNoOptimize;
3265 mulIC->generateOutOfLine(callFrame->codeBlock(), nonOptimizeVariant);
3266
3267#if ENABLE(MATH_IC_STATS)
3268 callFrame->codeBlock()->dumpMathICStats();
3269#endif
3270
3271 return profiledMul(globalObject, encodedOp1, encodedOp2, *arithProfile, false);
3272}
3273
3274JSC_DEFINE_JIT_OPERATION(operationValueMulProfiledNoOptimize, EncodedJSValue, (JSGlobalObject* globalObject, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, JITMulIC* mulIC))
3275{
3276 VM& vm = globalObject->vm();
3277 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
3278 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
3279
3280 BinaryArithProfile* arithProfile = mulIC->arithProfile();
3281 ASSERT(arithProfile);
3282 return profiledMul(globalObject, encodedOp1, encodedOp2, *arithProfile);
3283}
3284
3285// FIXME: it would be better to call those operationValueNegate, since the operand can be a BigInt
3286JSC_DEFINE_JIT_OPERATION(operationArithNegate, EncodedJSValue, (JSGlobalObject* globalObject, EncodedJSValue encodedOperand))
3287{
3288 VM& vm = globalObject->vm();
3289 auto scope = DECLARE_THROW_SCOPE(vm);
3290 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
3291 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
3292
3293 JSValue operand = JSValue::decode(encodedOperand);
3294
3295 JSValue primValue = operand.toPrimitive(globalObject, PreferNumber);
3296 RETURN_IF_EXCEPTION(scope, encodedJSValue());
3297
3298#if USE(BIGINT32)
3299 if (primValue.isBigInt32())
3300 RELEASE_AND_RETURN(scope, JSValue::encode(JSBigInt::unaryMinus(globalObject, primValue.bigInt32AsInt32())));
3301#endif
3302 if (primValue.isHeapBigInt())
3303 RELEASE_AND_RETURN(scope, JSValue::encode(JSBigInt::unaryMinus(globalObject, primValue.asHeapBigInt())));
3304
3305 double number = primValue.toNumber(globalObject);
3306 RETURN_IF_EXCEPTION(scope, encodedJSValue());
3307 return JSValue::encode(jsNumber(-number));
3308
3309}
3310
3311// FIXME: it would be better to call those operationValueNegate, since the operand can be a BigInt
3312JSC_DEFINE_JIT_OPERATION(operationArithNegateProfiled, EncodedJSValue, (JSGlobalObject* globalObject, EncodedJSValue encodedOperand, UnaryArithProfile* arithProfile))
3313{
3314 ASSERT(arithProfile);
3315 VM& vm = globalObject->vm();
3316 auto scope = DECLARE_THROW_SCOPE(vm);
3317 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
3318 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
3319
3320 JSValue operand = JSValue::decode(encodedOperand);
3321 arithProfile->observeArg(operand);
3322
3323 JSValue primValue = operand.toPrimitive(globalObject, PreferNumber);
3324 RETURN_IF_EXCEPTION(scope, encodedJSValue());
3325
3326#if USE(BIGINT32)
3327 if (primValue.isBigInt32()) {
3328 JSValue result = JSBigInt::unaryMinus(globalObject, primValue.bigInt32AsInt32());
3329 RETURN_IF_EXCEPTION(scope, { });
3330 arithProfile->observeResult(result);
3331 return JSValue::encode(result);
3332 }
3333#endif
3334 if (primValue.isHeapBigInt()) {
3335 JSValue result = JSBigInt::unaryMinus(globalObject, primValue.asHeapBigInt());
3336 RETURN_IF_EXCEPTION(scope, { });
3337 arithProfile->observeResult(result);
3338 return JSValue::encode(result);
3339 }
3340
3341 double number = primValue.toNumber(globalObject);
3342 RETURN_IF_EXCEPTION(scope, encodedJSValue());
3343 JSValue result = jsNumber(-number);
3344 arithProfile->observeResult(result);
3345 return JSValue::encode(result);
3346}
3347
3348// FIXME: it would be better to call those operationValueNegate, since the operand can be a BigInt
3349JSC_DEFINE_JIT_OPERATION(operationArithNegateProfiledOptimize, EncodedJSValue, (JSGlobalObject* globalObject, EncodedJSValue encodedOperand, JITNegIC* negIC))
3350{
3351 VM& vm = globalObject->vm();
3352 auto scope = DECLARE_THROW_SCOPE(vm);
3353 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
3354 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
3355
3356 JSValue operand = JSValue::decode(encodedOperand);
3357
3358 UnaryArithProfile* arithProfile = negIC->arithProfile();
3359 ASSERT(arithProfile);
3360 arithProfile->observeArg(operand);
3361 negIC->generateOutOfLine(callFrame->codeBlock(), operationArithNegateProfiled);
3362
3363#if ENABLE(MATH_IC_STATS)
3364 callFrame->codeBlock()->dumpMathICStats();
3365#endif
3366
3367 JSValue primValue = operand.toPrimitive(globalObject, PreferNumber);
3368 RETURN_IF_EXCEPTION(scope, encodedJSValue());
3369
3370#if USE(BIGINT32)
3371 if (primValue.isBigInt32()) {
3372 JSValue result = JSBigInt::unaryMinus(globalObject, primValue.bigInt32AsInt32());
3373 RETURN_IF_EXCEPTION(scope, { });
3374 arithProfile->observeResult(result);
3375 return JSValue::encode(result);
3376 }
3377#endif
3378 if (primValue.isHeapBigInt()) {
3379 JSValue result = JSBigInt::unaryMinus(globalObject, primValue.asHeapBigInt());
3380 RETURN_IF_EXCEPTION(scope, { });
3381 arithProfile->observeResult(result);
3382 return JSValue::encode(result);
3383 }
3384
3385 double number = primValue.toNumber(globalObject);
3386 RETURN_IF_EXCEPTION(scope, encodedJSValue());
3387 JSValue result = jsNumber(-number);
3388 arithProfile->observeResult(result);
3389 return JSValue::encode(result);
3390}
3391
3392// FIXME: it would be better to call those operationValueNegate, since the operand can be a BigInt
3393JSC_DEFINE_JIT_OPERATION(operationArithNegateOptimize, EncodedJSValue, (JSGlobalObject* globalObject, EncodedJSValue encodedOperand, JITNegIC* negIC))
3394{
3395 VM& vm = globalObject->vm();
3396 auto scope = DECLARE_THROW_SCOPE(vm);
3397 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
3398 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
3399
3400 JSValue operand = JSValue::decode(encodedOperand);
3401
3402 if (UnaryArithProfile* arithProfile = negIC->arithProfile())
3403 arithProfile->observeArg(operand);
3404 negIC->generateOutOfLine(callFrame->codeBlock(), operationArithNegate);
3405
3406#if ENABLE(MATH_IC_STATS)
3407 callFrame->codeBlock()->dumpMathICStats();
3408#endif
3409
3410 JSValue primValue = operand.toPrimitive(globalObject, PreferNumber);
3411 RETURN_IF_EXCEPTION(scope, encodedJSValue());
3412
3413#if USE(BIGINT32)
3414 // FIXME: why does this function profile the argument but not the result?
3415 if (primValue.isBigInt32())
3416 RELEASE_AND_RETURN(scope, JSValue::encode(JSBigInt::unaryMinus(globalObject, primValue.bigInt32AsInt32())));
3417#endif
3418 if (primValue.isHeapBigInt())
3419 RELEASE_AND_RETURN(scope, JSValue::encode(JSBigInt::unaryMinus(globalObject, primValue.asHeapBigInt())));
3420
3421 double number = primValue.toNumber(globalObject);
3422 RETURN_IF_EXCEPTION(scope, encodedJSValue());
3423 return JSValue::encode(jsNumber(-number));
3424}
3425
3426ALWAYS_INLINE static EncodedJSValue unprofiledSub(JSGlobalObject* globalObject, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
3427{
3428 JSValue op1 = JSValue::decode(encodedOp1);
3429 JSValue op2 = JSValue::decode(encodedOp2);
3430
3431 return JSValue::encode(jsSub(globalObject, op1, op2));
3432}
3433
3434ALWAYS_INLINE static EncodedJSValue profiledSub(VM& vm, JSGlobalObject* globalObject, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, BinaryArithProfile& arithProfile, bool shouldObserveLHSAndRHSTypes = true)
3435{
3436 auto scope = DECLARE_THROW_SCOPE(vm);
3437
3438 JSValue op1 = JSValue::decode(encodedOp1);
3439 JSValue op2 = JSValue::decode(encodedOp2);
3440
3441 if (shouldObserveLHSAndRHSTypes)
3442 arithProfile.observeLHSAndRHS(op1, op2);
3443
3444 JSValue result = jsSub(globalObject, op1, op2);
3445 RETURN_IF_EXCEPTION(scope, encodedJSValue());
3446 arithProfile.observeResult(result);
3447 return JSValue::encode(result);
3448}
3449
3450JSC_DEFINE_JIT_OPERATION(operationValueSub, EncodedJSValue, (JSGlobalObject* globalObject, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2))
3451{
3452 VM& vm = globalObject->vm();
3453 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
3454 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
3455 return unprofiledSub(globalObject, encodedOp1, encodedOp2);
3456}
3457
3458JSC_DEFINE_JIT_OPERATION(operationValueSubProfiled, EncodedJSValue, (JSGlobalObject* globalObject, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, BinaryArithProfile* arithProfile))
3459{
3460 ASSERT(arithProfile);
3461
3462 VM& vm = globalObject->vm();
3463 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
3464 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
3465
3466 return profiledSub(vm, globalObject, encodedOp1, encodedOp2, *arithProfile);
3467}
3468
3469JSC_DEFINE_JIT_OPERATION(operationValueSubOptimize, EncodedJSValue, (JSGlobalObject* globalObject, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, JITSubIC* subIC))
3470{
3471 VM& vm = globalObject->vm();
3472 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
3473 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
3474
3475 auto nonOptimizeVariant = operationValueSubNoOptimize;
3476 if (BinaryArithProfile* arithProfile = subIC->arithProfile())
3477 arithProfile->observeLHSAndRHS(JSValue::decode(encodedOp1), JSValue::decode(encodedOp2));
3478 subIC->generateOutOfLine(callFrame->codeBlock(), nonOptimizeVariant);
3479
3480#if ENABLE(MATH_IC_STATS)
3481 callFrame->codeBlock()->dumpMathICStats();
3482#endif
3483
3484 return unprofiledSub(globalObject, encodedOp1, encodedOp2);
3485}
3486
3487JSC_DEFINE_JIT_OPERATION(operationValueSubNoOptimize, EncodedJSValue, (JSGlobalObject* globalObject, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, JITSubIC*))
3488{
3489 VM& vm = globalObject->vm();
3490 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
3491 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
3492
3493 return unprofiledSub(globalObject, encodedOp1, encodedOp2);
3494}
3495
3496JSC_DEFINE_JIT_OPERATION(operationValueSubProfiledOptimize, EncodedJSValue, (JSGlobalObject* globalObject, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, JITSubIC* subIC))
3497{
3498 VM& vm = globalObject->vm();
3499 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
3500 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
3501
3502 BinaryArithProfile* arithProfile = subIC->arithProfile();
3503 ASSERT(arithProfile);
3504 arithProfile->observeLHSAndRHS(JSValue::decode(encodedOp1), JSValue::decode(encodedOp2));
3505 auto nonOptimizeVariant = operationValueSubProfiledNoOptimize;
3506 subIC->generateOutOfLine(callFrame->codeBlock(), nonOptimizeVariant);
3507
3508#if ENABLE(MATH_IC_STATS)
3509 callFrame->codeBlock()->dumpMathICStats();
3510#endif
3511
3512 return profiledSub(vm, globalObject, encodedOp1, encodedOp2, *arithProfile, false);
3513}
3514
3515JSC_DEFINE_JIT_OPERATION(operationValueSubProfiledNoOptimize, EncodedJSValue, (JSGlobalObject* globalObject, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, JITSubIC* subIC))
3516{
3517 VM& vm = globalObject->vm();
3518 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
3519 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
3520
3521 BinaryArithProfile* arithProfile = subIC->arithProfile();
3522 ASSERT(arithProfile);
3523 return profiledSub(vm, globalObject, encodedOp1, encodedOp2, *arithProfile);
3524}
3525
3526JSC_DEFINE_JIT_OPERATION(operationProcessTypeProfilerLog, void, (VM* vmPointer))
3527{
3528 VM& vm = *vmPointer;
3529 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
3530 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
3531 vm.typeProfilerLog()->processLogEntries(vm, "Log Full, called from inside baseline JIT"_s);
3532}
3533
3534JSC_DEFINE_JIT_OPERATION(operationProcessShadowChickenLog, void, (VM* vmPointer))
3535{
3536 VM& vm = *vmPointer;
3537 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
3538 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
3539 RELEASE_ASSERT(vm.shadowChicken());
3540 vm.shadowChicken()->update(vm, callFrame);
3541}
3542
3543JSC_DEFINE_JIT_OPERATION(operationRetrieveAndClearExceptionIfCatchable, JSCell*, (VM* vmPointer))
3544{
3545 VM& vm = *vmPointer;
3546 CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
3547 JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
3548 auto scope = DECLARE_THROW_SCOPE(vm);
3549 RELEASE_ASSERT(!!scope.exception());
3550
3551 Exception* exception = scope.exception();
3552 if (UNLIKELY(vm.isTerminationException(exception))) {
3553 genericUnwind(vm, callFrame);
3554 return nullptr;
3555 }
3556
3557 // We want to clear the exception here rather than in the catch prologue
3558 // JIT code because clearing it also entails clearing a bit in an Atomic
3559 // bit field in VMTraps.
3560 scope.clearException();
3561 return exception;
3562}
3563
3564} // namespace JSC
3565
3566IGNORE_WARNINGS_END
3567
3568#endif // ENABLE(JIT)
Note: See TracBrowser for help on using the repository browser.