Skip to content

Commit

Permalink
[JSC] Make megamorphic IC stateless
Browse files Browse the repository at this point in the history
https://bugs.webkit.org/show_bug.cgi?id=274316
rdar://128277946

Reviewed by NOBODY (OOPS!).

We store expected UniquedStringImpl into InlineCacheHandler (must not keep it as Ref! lifetime is managed by StructureStubInfo) in megamorphic IC
when Handler IC is enabled. And we retrieve it from GPRInfo::handlerGPR. So we can share one code for all of megamorphic IC, thus it becomes stateless.

* Source/JavaScriptCore/bytecode/InlineCacheCompiler.cpp:
(JSC::isStateless):
(JSC::InlineCacheHandler::InlineCacheHandler):
(JSC::InlineCacheCompiler::generateWithGuard):
(JSC::InlineCacheCompiler::regenerate):
* Source/JavaScriptCore/bytecode/InlineCacheCompiler.h:
  • Loading branch information
Constellation committed May 18, 2024
1 parent b6af5ac commit a231c2e
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 14 deletions.
44 changes: 33 additions & 11 deletions Source/JavaScriptCore/bytecode/InlineCacheCompiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -442,8 +442,6 @@ static bool isStateless(AccessCase::AccessType type)
{
switch (type) {
case AccessCase::Load:
case AccessCase::LoadMegamorphic:
case AccessCase::StoreMegamorphic:
case AccessCase::Transition:
case AccessCase::Delete:
case AccessCase::DeleteNonConfigurable:
Expand All @@ -470,10 +468,12 @@ static bool isStateless(AccessCase::AccessType type)
case AccessCase::InstanceOfMiss:
case AccessCase::InHit:
case AccessCase::InMiss:
case AccessCase::InMegamorphic:
case AccessCase::IndexedNoIndexingInMiss:
return false;

case AccessCase::InMegamorphic:
case AccessCase::LoadMegamorphic:
case AccessCase::StoreMegamorphic:
case AccessCase::ArrayLength:
case AccessCase::StringLength:
case AccessCase::DirectArgumentsLength:
Expand Down Expand Up @@ -1361,9 +1361,10 @@ MacroAssemblerCodeRef<JITThunkPtrTag> InlineCacheCompiler::generateSlowPathCode(
return { };
}

InlineCacheHandler::InlineCacheHandler(Ref<PolymorphicAccessJITStubRoutine>&& stubRoutine, std::unique_ptr<StructureStubInfoClearingWatchpoint>&& watchpoint)
InlineCacheHandler::InlineCacheHandler(StructureStubInfo& stubInfo, Ref<PolymorphicAccessJITStubRoutine>&& stubRoutine, std::unique_ptr<StructureStubInfoClearingWatchpoint>&& watchpoint)
: m_callTarget(stubRoutine->code().code().template retagged<JITStubRoutinePtrTag>())
, m_jumpTarget(CodePtr<NoPtrTag> { m_callTarget.retagged<NoPtrTag>().dataLocation<uint8_t*>() + prologueSizeInBytesDataIC }.template retagged<JITStubRoutinePtrTag>())
, m_uid(stubInfo.identifier().uid())
, m_stubRoutine(WTFMove(stubRoutine))
, m_watchpoint(WTFMove(watchpoint))
{
Expand Down Expand Up @@ -2408,10 +2409,16 @@ void InlineCacheCompiler::generateWithGuard(unsigned index, AccessCase& accessCa
auto allocator = makeDefaultScratchAllocator(scratchGPR);
GPRReg scratch2GPR = allocator.allocateScratchGPR();
GPRReg scratch3GPR = allocator.allocateScratchGPR();
GPRReg scratch4GPR = allocator.allocateScratchGPR();

ScratchRegisterAllocator::PreservedState preservedState = allocator.preserveReusedRegistersByPushing(jit, ScratchRegisterAllocator::ExtraStackSpace::NoExtraSpace);

auto slowCases = jit.loadMegamorphicProperty(vm, baseGPR, InvalidGPRReg, uid, valueRegs.payloadGPR(), scratchGPR, scratch2GPR, scratch3GPR);
CCallHelpers::JumpList slowCases;
if (useHandlerIC()) {
jit.loadPtr(CCallHelpers::Address(GPRInfo::handlerGPR, InlineCacheHandler::offsetOfUid()), scratch4GPR);
slowCases.append(jit.loadMegamorphicProperty(vm, baseGPR, scratch4GPR, nullptr, valueRegs.payloadGPR(), scratchGPR, scratch2GPR, scratch3GPR));
} else
slowCases.append(jit.loadMegamorphicProperty(vm, baseGPR, InvalidGPRReg, uid, valueRegs.payloadGPR(), scratchGPR, scratch2GPR, scratch3GPR));

allocator.restoreReusedRegistersByPopping(jit, preservedState);
succeed();
Expand All @@ -2435,10 +2442,18 @@ void InlineCacheCompiler::generateWithGuard(unsigned index, AccessCase& accessCa
auto allocator = makeDefaultScratchAllocator(scratchGPR);
GPRReg scratch2GPR = allocator.allocateScratchGPR();
GPRReg scratch3GPR = allocator.allocateScratchGPR();
GPRReg scratch4GPR = allocator.allocateScratchGPR();

ScratchRegisterAllocator::PreservedState preservedState = allocator.preserveReusedRegistersByPushing(jit, ScratchRegisterAllocator::ExtraStackSpace::SpaceForCCall);

auto [slow, reallocating] = jit.storeMegamorphicProperty(vm, baseGPR, InvalidGPRReg, uid, valueRegs.payloadGPR(), scratchGPR, scratch2GPR, scratch3GPR);
CCallHelpers::JumpList slow;
CCallHelpers::JumpList reallocating;

if (useHandlerIC()) {
jit.loadPtr(CCallHelpers::Address(GPRInfo::handlerGPR, InlineCacheHandler::offsetOfUid()), scratch4GPR);
std::tie(slow, reallocating) = jit.storeMegamorphicProperty(vm, baseGPR, scratch4GPR, nullptr, valueRegs.payloadGPR(), scratchGPR, scratch2GPR, scratch3GPR);
} else
std::tie(slow, reallocating) = jit.storeMegamorphicProperty(vm, baseGPR, InvalidGPRReg, uid, valueRegs.payloadGPR(), scratchGPR, scratch2GPR, scratch3GPR);

CCallHelpers::Label doneLabel = jit.label();
allocator.restoreReusedRegistersByPopping(jit, preservedState);
Expand Down Expand Up @@ -2476,10 +2491,16 @@ void InlineCacheCompiler::generateWithGuard(unsigned index, AccessCase& accessCa
auto allocator = makeDefaultScratchAllocator(scratchGPR);
GPRReg scratch2GPR = allocator.allocateScratchGPR();
GPRReg scratch3GPR = allocator.allocateScratchGPR();
GPRReg scratch4GPR = allocator.allocateScratchGPR();

ScratchRegisterAllocator::PreservedState preservedState = allocator.preserveReusedRegistersByPushing(jit, ScratchRegisterAllocator::ExtraStackSpace::NoExtraSpace);

auto slowCases = jit.hasMegamorphicProperty(vm, baseGPR, InvalidGPRReg, uid, valueRegs.payloadGPR(), scratchGPR, scratch2GPR, scratch3GPR);
CCallHelpers::JumpList slowCases;
if (useHandlerIC()) {
jit.loadPtr(CCallHelpers::Address(GPRInfo::handlerGPR, InlineCacheHandler::offsetOfUid()), scratch4GPR);
slowCases.append(jit.hasMegamorphicProperty(vm, baseGPR, scratch4GPR, nullptr, valueRegs.payloadGPR(), scratchGPR, scratch2GPR, scratch3GPR));
} else
slowCases.append(jit.hasMegamorphicProperty(vm, baseGPR, InvalidGPRReg, uid, valueRegs.payloadGPR(), scratchGPR, scratch2GPR, scratch3GPR));

allocator.restoreReusedRegistersByPopping(jit, preservedState);
succeed();
Expand Down Expand Up @@ -4040,7 +4061,7 @@ AccessGenerationResult InlineCacheCompiler::regenerate(const GCSafeConcurrentJSL
if (allAreSimpleLoadOrMiss) {
cases.shrink(0);
additionalWatchpointSets.clear();
cases.append(AccessCase::create(vm(), codeBlock, AccessCase::LoadMegamorphic, identifier));
cases.append(AccessCase::create(vm(), codeBlock, AccessCase::LoadMegamorphic, useHandlerIC() ? nullptr : identifier));
generatedMegamorphicCode = true;
}
break;
Expand Down Expand Up @@ -4111,7 +4132,7 @@ AccessGenerationResult InlineCacheCompiler::regenerate(const GCSafeConcurrentJSL
if (allAreSimpleReplaceOrTransition) {
cases.shrink(0);
additionalWatchpointSets.clear();
cases.append(AccessCase::create(vm(), codeBlock, AccessCase::StoreMegamorphic, identifier));
cases.append(AccessCase::create(vm(), codeBlock, AccessCase::StoreMegamorphic, useHandlerIC() ? nullptr : identifier));
generatedMegamorphicCode = true;
}
break;
Expand Down Expand Up @@ -4179,7 +4200,7 @@ AccessGenerationResult InlineCacheCompiler::regenerate(const GCSafeConcurrentJSL
if (allAreSimpleHitOrMiss) {
cases.shrink(0);
additionalWatchpointSets.clear();
cases.append(AccessCase::create(vm(), codeBlock, AccessCase::InMegamorphic, identifier));
cases.append(AccessCase::create(vm(), codeBlock, AccessCase::InMegamorphic, useHandlerIC() ? nullptr : identifier));
generatedMegamorphicCode = true;
}
break;
Expand Down Expand Up @@ -4229,7 +4250,8 @@ AccessGenerationResult InlineCacheCompiler::regenerate(const GCSafeConcurrentJSL

poly.m_list.shrink(0);
poly.m_list.append(stub->cases().span());
auto handler = InlineCacheHandler::create(WTFMove(stub), WTFMove(watchpoint));

auto handler = InlineCacheHandler::create(*m_stubInfo, WTFMove(stub), WTFMove(watchpoint));
dataLogLnIf(InlineCacheCompilerInternal::verbose, "Returning: ", handler->callTarget());

AccessGenerationResult::Kind resultKind;
Expand Down
9 changes: 6 additions & 3 deletions Source/JavaScriptCore/bytecode/InlineCacheCompiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -166,9 +166,9 @@ class InlineCacheHandler final : public RefCounted<InlineCacheHandler> {
static ptrdiff_t offsetOfJumpTarget() { return OBJECT_OFFSETOF(InlineCacheHandler, m_jumpTarget); }
static ptrdiff_t offsetOfNext() { return OBJECT_OFFSETOF(InlineCacheHandler, m_next); }

static Ref<InlineCacheHandler> create(Ref<PolymorphicAccessJITStubRoutine>&& stubRoutine, std::unique_ptr<StructureStubInfoClearingWatchpoint>&& watchpoint)
static Ref<InlineCacheHandler> create(StructureStubInfo& stubInfo, Ref<PolymorphicAccessJITStubRoutine>&& stubRoutine, std::unique_ptr<StructureStubInfoClearingWatchpoint>&& watchpoint)
{
return adoptRef(*new InlineCacheHandler(WTFMove(stubRoutine), WTFMove(watchpoint)));
return adoptRef(*new InlineCacheHandler(stubInfo, WTFMove(stubRoutine), WTFMove(watchpoint)));
}

CodePtr<JITStubRoutinePtrTag> callTarget() const { return m_callTarget; }
Expand Down Expand Up @@ -196,14 +196,17 @@ class InlineCacheHandler final : public RefCounted<InlineCacheHandler> {
void addOwner(CodeBlock*);
void removeOwner(CodeBlock*);

static ptrdiff_t offsetOfUid() { return OBJECT_OFFSETOF(InlineCacheHandler, m_uid); }

private:
InlineCacheHandler() = default;
InlineCacheHandler(Ref<PolymorphicAccessJITStubRoutine>&&, std::unique_ptr<StructureStubInfoClearingWatchpoint>&&);
InlineCacheHandler(StructureStubInfo&, Ref<PolymorphicAccessJITStubRoutine>&&, std::unique_ptr<StructureStubInfoClearingWatchpoint>&&);

static Ref<InlineCacheHandler> createSlowPath(VM&, AccessType);

CodePtr<JITStubRoutinePtrTag> m_callTarget;
CodePtr<JITStubRoutinePtrTag> m_jumpTarget;
UniquedStringImpl* m_uid { nullptr };
RefPtr<PolymorphicAccessJITStubRoutine> m_stubRoutine;
std::unique_ptr<StructureStubInfoClearingWatchpoint> m_watchpoint;
RefPtr<InlineCacheHandler> m_next;
Expand Down

0 comments on commit a231c2e

Please sign in to comment.