From 0a86a72a967ac2cbc04bea0cfd2da0a72f42ea64 Mon Sep 17 00:00:00 2001 From: ZhouGuangyuan Date: Fri, 4 Jul 2025 11:14:41 +0800 Subject: [PATCH] Install barrier for gcphase Issue: https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/ICK4QD Signed-off-by: ZhouGuangyuan Change-Id: Ie3f70fcf6cebb992d78ea846ef64344d9238729f --- ecmascript/compiler/call_signature.cpp | 19 ++++- ecmascript/compiler/call_signature.h | 5 +- .../compiler/codegen/llvm/llvm_ir_builder.cpp | 2 +- ecmascript/compiler/common_stub_csigns.h | 19 ++++- ecmascript/compiler/common_stubs.cpp | 34 ++++++++- ecmascript/compiler/stub_builder.cpp | 70 +++++-------------- ecmascript/compiler/stub_builder.h | 6 +- ecmascript/mem/cmc_gc/hooks.cpp | 41 ++++++++++- 8 files changed, 129 insertions(+), 67 deletions(-) diff --git a/ecmascript/compiler/call_signature.cpp b/ecmascript/compiler/call_signature.cpp index 6bf93385a0..88ff969655 100644 --- a/ecmascript/compiler/call_signature.cpp +++ b/ecmascript/compiler/call_signature.cpp @@ -948,9 +948,24 @@ DEF_CALL_SIGNATURE(VerifyBarrier) SETVALUEBARRIER_CALL_ARGS_SIGNATURE_COMMON(VerifyBarrier); } -DEF_CALL_SIGNATURE(CMCSetValueWithBarrier) +DEF_CALL_SIGNATURE(CMCSetValueUpdateRSet) { - SETVALUEBARRIER_CALL_ARGS_SIGNATURE_COMMON(CMCSetValueWithBarrier); + SETVALUEBARRIER_CALL_ARGS_SIGNATURE_COMMON(CMCSetValueUpdateRSet); +} + +DEF_CALL_SIGNATURE(CMCSetValueUpdateRSetAndMarkSatb) +{ + SETVALUEBARRIER_CALL_ARGS_SIGNATURE_COMMON(CMCSetValueUpdateRSetAndMarkSatb); +} + +DEF_CALL_SIGNATURE(CMCSetValueMarkSatb) +{ + SETVALUEBARRIER_CALL_ARGS_SIGNATURE_COMMON(CMCSetValueMarkSatb); +} + +DEF_CALL_SIGNATURE(CMCSetValueDoNothing) +{ + SETVALUEBARRIER_CALL_ARGS_SIGNATURE_COMMON(CMCSetValueDoNothing); } #undef SETVALUEBARRIER_CALL_ARGS_SIGNATURE_COMMON diff --git a/ecmascript/compiler/call_signature.h b/ecmascript/compiler/call_signature.h index 59c932acec..c4babcb806 100644 --- a/ecmascript/compiler/call_signature.h +++ b/ecmascript/compiler/call_signature.h @@ -709,7 +709,10 @@ private: V(CopyArgvArray) \ V(MarkRSetCardTable) \ V(MarkInBuffer) \ - V(CMCSetValueWithBarrier) + V(CMCSetValueUpdateRSet) \ + V(CMCSetValueUpdateRSetAndMarkSatb) \ + V(CMCSetValueMarkSatb) \ + V(CMCSetValueDoNothing) #define DECL_CALL_SIGNATURE(name) \ class name##CallSignature final { \ diff --git a/ecmascript/compiler/codegen/llvm/llvm_ir_builder.cpp b/ecmascript/compiler/codegen/llvm/llvm_ir_builder.cpp index a54e8514f5..304891fefa 100644 --- a/ecmascript/compiler/codegen/llvm/llvm_ir_builder.cpp +++ b/ecmascript/compiler/codegen/llvm/llvm_ir_builder.cpp @@ -1047,7 +1047,7 @@ void LLVMIRBuilder::VisitCall(GateRef gate, const std::vector &inList, if (op == OpCode::CALL) { const size_t index = acc_.GetConstantValue(inList[targetIndex]); calleeDescriptor = CommonStubCSigns::Get(index); - if (enableOptDirectCall_) { + if (enableOptDirectCall_ && !CommonStubCSigns::CanUpdate(index)) { if (isStwCopyStub_) { calleeDescriptor = CommonStubCSigns::Get(index + CommonStubCSigns::NUM_OF_ALL_NORMAL_STUBS); } diff --git a/ecmascript/compiler/common_stub_csigns.h b/ecmascript/compiler/common_stub_csigns.h index e7d40eb11b..30bc62f7fc 100644 --- a/ecmascript/compiler/common_stub_csigns.h +++ b/ecmascript/compiler/common_stub_csigns.h @@ -159,7 +159,10 @@ namespace panda::ecmascript::kungfu { V(DefineNormalFuncForJit) \ V(DefineArrowFuncForJit) \ V(DefineBaseConstructorForJit) \ - V(CMCSetValueWithBarrier) + V(CMCSetValueUpdateRSet) \ + V(CMCSetValueUpdateRSetAndMarkSatb) \ + V(CMCSetValueMarkSatb) \ + V(CMCSetValueDoNothing) #define COMMON_STUB_ID_LIST(V) \ COMMON_STUB_LIST(V) @@ -177,7 +180,7 @@ public: COMMON_STW_COPY_STUB_LIST(DEF_STUB_ID) #undef DEF_STUB_ID NUM_OF_STUBS, - NUM_OF_ALL_NORMAL_STUBS = CMCSetValueWithBarrier + 1, + NUM_OF_ALL_NORMAL_STUBS = CMCSetValueDoNothing + 1, }; #define ASSERT_ID_EQUAL(name) \ static_assert((static_cast(ID::name##StwCopy)) == \ @@ -214,6 +217,18 @@ public: return false; } + static bool CanUpdate(size_t index) + { + ASSERT(index < NUM_OF_STUBS); + switch (index) { + case SetValueWithBarrier: + return true; + default: + return false; + } + return false; + } + static bool IsCold(size_t index) { ASSERT(index < NUM_OF_STUBS); diff --git a/ecmascript/compiler/common_stubs.cpp b/ecmascript/compiler/common_stubs.cpp index 42374a64eb..0433864eab 100644 --- a/ecmascript/compiler/common_stubs.cpp +++ b/ecmascript/compiler/common_stubs.cpp @@ -1272,13 +1272,43 @@ void SetValueWithBarrierStubBuilder::GenerateCircuit() Return(); } -void CMCSetValueWithBarrierStubBuilder::GenerateCircuit() +void CMCSetValueUpdateRSetStubBuilder::GenerateCircuit() { GateRef glue = PtrArgument(0); GateRef obj = TaggedArgument(1); GateRef offset = PtrArgument(2); // 2 : 3rd para GateRef value = TaggedArgument(3); // 3 : 4th para - CMCSetValueWithBarrier(glue, obj, offset, value); + CMCSetValueWithBarrier(glue, obj, offset, value, true, false); + Return(); +} + +void CMCSetValueUpdateRSetAndMarkSatbStubBuilder::GenerateCircuit() +{ + GateRef glue = PtrArgument(0); + GateRef obj = TaggedArgument(1); + GateRef offset = PtrArgument(2); // 2 : 3rd para + GateRef value = TaggedArgument(3); // 3 : 4th para + CMCSetValueWithBarrier(glue, obj, offset, value, true, true); + Return(); +} + +void CMCSetValueMarkSatbStubBuilder::GenerateCircuit() +{ + GateRef glue = PtrArgument(0); + GateRef obj = TaggedArgument(1); + GateRef offset = PtrArgument(2); // 2 : 3rd para + GateRef value = TaggedArgument(3); // 3 : 4th para + CMCSetValueWithBarrier(glue, obj, offset, value, false, true); + Return(); +} + +void CMCSetValueDoNothingStubBuilder::GenerateCircuit() +{ + GateRef glue = PtrArgument(0); + GateRef obj = TaggedArgument(1); + GateRef offset = PtrArgument(2); // 2 : 3rd para + GateRef value = TaggedArgument(3); // 3 : 4th para + CMCSetValueWithBarrier(glue, obj, offset, value, false, false); Return(); } diff --git a/ecmascript/compiler/stub_builder.cpp b/ecmascript/compiler/stub_builder.cpp index 1097851a39..af6ee5d0b0 100644 --- a/ecmascript/compiler/stub_builder.cpp +++ b/ecmascript/compiler/stub_builder.cpp @@ -1934,44 +1934,22 @@ GateRef StubBuilder::IsInYoungSpace(GateRef regionType) return ret; } -void StubBuilder::CMCSetValueWithBarrier(GateRef glue, GateRef obj, [[maybe_unused]]GateRef offset, GateRef value) +void StubBuilder::CMCSetValueWithBarrier(GateRef glue, GateRef obj, [[maybe_unused]] GateRef offset, GateRef value, + bool updateRSet, bool markInSatb) { auto env = GetEnvironment(); Label entry(env); env->SubCfgEntry(&entry); Label exit(env); - - GateRef gcPhase = LoadPrimitive(VariableType::INT8(), glue, - Int64(JSThread::GlueData::GetSharedGCStateBitFieldOffset(false) + - JSThread::CMCGCPhaseBits::START_BIT / BITS_PER_BYTE)); - Label checkOldToYoung(env); - Label markRSet(env); - Label notMarkRSet(env); - Label notIdlePhase(env); - BRANCH(Int8Equal(gcPhase, Int8(common::GCPhase::GC_PHASE_IDLE)), &checkOldToYoung, ¬IdlePhase); - Bind(¬IdlePhase); - GateRef gcReason = LoadPrimitive(VariableType::INT32(), glue, - Int64(JSThread::GlueData::GetSharedGCStateBitFieldOffset(false) + - JSThread::CMCGCReasonBits::START_BIT / BITS_PER_BYTE)); - Label reasonNotYoung(env); - BRANCH(Int32Equal(gcReason, Int32(common::GCReason::GC_REASON_YOUNG)), &checkOldToYoung, &reasonNotYoung); - Bind(&reasonNotYoung); - GateRef needMarkPhase = LogicOrBuilder(env) - .Or(Int8Equal(gcPhase, Int8(common::GCPhase::GC_PHASE_COPY))) - .Or(Int8Equal(gcPhase, Int8(common::GCPhase::GC_PHASE_FIX))) - .Or(Int8Equal(gcPhase, Int8(common::GCPhase::GC_PHASE_PRECOPY))) - .Or(Int8Equal(gcPhase, Int8(common::GCPhase::GC_PHASE_FINAL_MARK))) - .Or(Int8Equal(gcPhase, Int8(common::GCPhase::GC_PHASE_REMARK_SATB))) - .Done(); - BRANCH(needMarkPhase, &checkOldToYoung, ¬MarkRSet); - Bind(&checkOldToYoung); - { + Label next(env); + if (updateRSet) { + Label markRSet(env); GateRef objRegionType = GetCMCRegionType(obj); GateRef valueRegionType = GetCMCRegionType(value); GateRef isOldToYoung = LogicAndBuilder(env) .And(BoolNot(IsInYoungSpace(objRegionType))) .And(IsInYoungSpace(valueRegionType)).Done(); - BRANCH_UNLIKELY(isOldToYoung, &markRSet, ¬MarkRSet); + BRANCH_UNLIKELY(isOldToYoung, &markRSet, &next); Bind(&markRSet); { Label markBit(env); @@ -1984,31 +1962,26 @@ void StubBuilder::CMCSetValueWithBarrier(GateRef glue, GateRef obj, [[maybe_unus GateRef headMaskBitStart = IntPtrMod(IntPtrDiv(objOffset, IntPtr(common::kMarkedBytesPerBit)), IntPtr(common::kBitsPerWord)); GateRef headMaskBits = Int64LSL(Int64(1), headMaskBitStart); - GateRef cardOffset = PtrMul(cardIdx, IntPtr(common::kBytesPerWord)); + GateRef cardOffset = PtrMul(cardIdx, IntPtr(sizeof(uint64_t) / sizeof(uint8_t))); GateRef cardTable = LoadPrimitive(VariableType::NATIVE_POINTER(), rset, - IntPtr(common::RegionRSet::CARD_TABLE_OFFSET_IN_RSET)); + IntPtr(sizeof(uint64_t) / sizeof(uint8_t))); GateRef card = LoadPrimitive(VariableType::INT64(), cardTable, cardOffset); GateRef isMarked = Int64NotEqual(Int64And(card, headMaskBits), Int64(0)); - BRANCH_NO_WEIGHT(isMarked, ¬MarkRSet, &markBit); + BRANCH_NO_WEIGHT(isMarked, &next, &markBit); Bind(&markBit); { Int64FetchOr(PtrAdd(cardTable, cardOffset), headMaskBits); - Jump(¬MarkRSet); + Jump(&next); } } + } else { + Jump(&next); } - Bind(¬MarkRSet); - Label markInBuffer(env); - GateRef needMarkInBuffer = LogicOrBuilder(env) - .Or(Int8Equal(gcPhase, Int8(common::GCPhase::GC_PHASE_ENUM))) - .Or(Int8Equal(gcPhase, Int8(common::GCPhase::GC_PHASE_MARK))) - .Or(Int8Equal(gcPhase, Int8(common::GCPhase::GC_PHASE_FINAL_MARK))) - .Or(Int8Equal(gcPhase, Int8(common::GCPhase::GC_PHASE_REMARK_SATB))) - .Done(); - BRANCH_UNLIKELY(needMarkInBuffer, &markInBuffer, &exit); - Bind(&markInBuffer); + Bind(&next); { - CallNGCRuntime(glue, RTSTUB_ID(MarkInBuffer), {value}); + if (markInSatb) { + CallNGCRuntime(glue, RTSTUB_ID(MarkInBuffer), {value}); + } Jump(&exit); } Bind(&exit); @@ -2022,17 +1995,6 @@ void StubBuilder::SetValueWithBarrier(GateRef glue, GateRef obj, GateRef offset, Label entry(env); env->SubCfgEntry(&entry); Label exit(env); - Label callRuntime(env); - Label checkNext(env); - BRANCH_LIKELY(LoadPrimitive( - VariableType::BOOL(), glue, IntPtr(JSThread::GlueData::GetIsEnableCMCGCOffset(env->Is32Bit()))), - &callRuntime, &checkNext); - Bind(&callRuntime); - { - CMCSetValueWithBarrier(glue, obj, offset, value); - Jump(&exit); - } - Bind(&checkNext); // ObjectAddressToRange function may cause obj is not an object. GC may not mark this obj. GateRef objectRegion = ObjectAddressToRange(obj); GateRef valueRegion = ObjectAddressToRange(value); diff --git a/ecmascript/compiler/stub_builder.h b/ecmascript/compiler/stub_builder.h index 1065dc7836..4b6a3ec0e0 100644 --- a/ecmascript/compiler/stub_builder.h +++ b/ecmascript/compiler/stub_builder.h @@ -188,7 +188,7 @@ public: GateRef CallRuntimeWithGlobalEnv(GateRef glue, GateRef globalEnv, int index, const std::vector& args); GateRef CallRuntimeWithGlobalEnv(GateRef glue, GateRef globalEnv, int index, GateRef argc, GateRef argv); GateRef CallRuntimeWithCurrentEnv(GateRef glue, GateRef currentEnv, int index, const std::vector& args); - + GateRef CallNGCRuntime(GateRef glue, int index, const std::vector& args, GateRef hir = Circuit::NullGate()); GateRef FastCallOptimized(GateRef glue, GateRef code, @@ -823,7 +823,8 @@ public: GateRef GetCMCRegionRSet(GateRef obj); GateRef GetCMCRegionType(GateRef obj); GateRef IsInYoungSpace(GateRef regionType); - void CMCSetValueWithBarrier(GateRef glue, GateRef obj, GateRef offset, GateRef value); + void CMCSetValueWithBarrier(GateRef glue, GateRef obj, GateRef offset, GateRef value, bool updateRSet, + bool markInSatb); void SetValueWithBarrier(GateRef glue, GateRef obj, GateRef offset, GateRef value, MemoryAttribute::ShareFlag share = MemoryAttribute::UNKNOWN); GateRef GetValueWithBarrier(GateRef glue, GateRef addr); @@ -1319,6 +1320,7 @@ private: CallSignature *callSignature_ {nullptr}; Environment *env_; GateRef globalEnv_ {Gate::InvalidGateRef}; + }; } // namespace panda::ecmascript::kungfu #endif // ECMASCRIPT_COMPILER_STUB_BUILDER_H diff --git a/ecmascript/mem/cmc_gc/hooks.cpp b/ecmascript/mem/cmc_gc/hooks.cpp index ac569744a0..7464094533 100644 --- a/ecmascript/mem/cmc_gc/hooks.cpp +++ b/ecmascript/mem/cmc_gc/hooks.cpp @@ -25,6 +25,7 @@ #include "ecmascript/mem/tagged_state_word.h" #include "ecmascript/mem/visitor.h" #include "ecmascript/runtime.h" +#include "ecmascript/interpreter/interpreter-inl.h" #include "objects/base_type.h" #include "objects/composite_base_class.h" @@ -205,10 +206,44 @@ void VisitJSThread(void *jsThread, CommonRootVisitor visitor) reinterpret_cast(jsThread)->Visit(visitor); } -void SynchronizeGCPhaseToJSThread(void *jsThread, GCPhase gcPhase) -{ +void SynchronizeGCPhaseToJSThread(void *jsThread, GCPhase gcPhase) { + using panda::ecmascript::CommonStubCSigns; reinterpret_cast(jsThread)->SetCMCGCPhase(gcPhase); - reinterpret_cast(jsThread)->SetCMCGCReason(Heap::GetHeap().GetGCReason()); + GCReason reason = Heap::GetHeap().GetGCReason(); + reinterpret_cast(jsThread)->SetCMCGCReason(reason); + auto *thread = static_cast(jsThread); + CommonStubCSigns::ID barrierId; + switch (gcPhase) { + case GC_PHASE_ENUM: + case GC_PHASE_MARK: + if (reason == GC_REASON_YOUNG) { + barrierId = CommonStubCSigns::CMCSetValueUpdateRSetAndMarkSatb; + } else { + barrierId = CommonStubCSigns::CMCSetValueMarkSatb; + } + break; + case GC_PHASE_POST_MARK: + if (reason == GC_REASON_YOUNG) { + barrierId = CommonStubCSigns::CMCSetValueUpdateRSet; + } else { + barrierId = CommonStubCSigns::CMCSetValueDoNothing; + } + break; + case GC_PHASE_REMARK_SATB: + case GC_PHASE_FINAL_MARK: + barrierId = CommonStubCSigns::CMCSetValueUpdateRSetAndMarkSatb; + break; + case GC_PHASE_IDLE: + case GC_PHASE_PRECOPY: + case GC_PHASE_COPY: + case GC_PHASE_FIX: + barrierId = CommonStubCSigns::CMCSetValueUpdateRSet; + break; + default: + LOG_ECMA(FATAL) << "Unknown GC phase " << gcPhase; + UNREACHABLE(); + } + thread->SetFastStubEntry(CommonStubCSigns::SetValueWithBarrier, thread->GetFastStubEntry(barrierId)); if (panda::ecmascript::g_isEnableCMCGC) { // forcely enable read barrier for read barrier DFX #ifdef ENABLE_CMC_RB_DFX -- Gitee