diff --git a/BUILD.gn b/BUILD.gn index eeb318d6af4cf513f2d79da39e891e8f7857e6ae..406721f24ac6c40f0b4ad1f130a249b04212b96b 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -401,6 +401,7 @@ config("ark_jsruntime_common_config") { defines += [ "ENABLE_COLD_STARTUP_GC_POLICY" ] } if (ets_runtime_enable_cmc_gc) { + defines += [ "ARK_HYBRID" ] defines += [ "USE_CMC_GC" ] if (ets_runtime_enable_cmc_rb_dfx) { defines += [ "ENABLE_CMC_RB_DFX" ] @@ -1165,6 +1166,7 @@ ecma_source += [ "ecmascript/cross_vm/unified_gc/unified_gc.cpp", "ecmascript/cross_vm/unified_gc/unified_gc_marker.cpp", "ecmascript/cross_vm/builtins_gc_hybrid.cpp", + "ecmascript/cross_vm/dynamic_object_accessor_util.cpp", "ecmascript/cross_vm/heap_hybrid.cpp", "ecmascript/cross_vm/jsnapi_expo_hybrid.cpp", "ecmascript/cross_vm/object_factory_hybrid.cpp", @@ -1561,11 +1563,6 @@ ohos_source_set("libark_jsruntime_test_set") { } deps += [ ":libcommon_components_set" ] - if (ets_runtime_enable_cmc_gc) { - if (ark_hybrid) { - deps += [ "$ark_root/static_core/runtime:libarkruntime_set_static" ] - } - } public_configs = [ "$js_root:ark_jsruntime_public_config" ] public_configs += [ ":include_llvm" ] @@ -1613,11 +1610,6 @@ ohos_source_set("libark_jsruntime_static") { } deps += [ ":libcommon_components_set" ] - if (ets_runtime_enable_cmc_gc) { - if (ark_hybrid) { - deps += [ "$ark_root/static_core/runtime:libarkruntime_set_static" ] - } - } external_deps = [] if (!is_arkui_x) { diff --git a/common_components/common_runtime/base_runtime.cpp b/common_components/common_runtime/base_runtime.cpp index 4839135b9e448342b78321719c03f360fc9d66a6..73921970c01763f60ac84a30d4f070e68388428e 100755 --- a/common_components/common_runtime/base_runtime.cpp +++ b/common_components/common_runtime/base_runtime.cpp @@ -86,12 +86,28 @@ inline void CheckAndFini(T*& module) module = nullptr; } +bool BaseRuntime::HasBeenInitialized() +{ + std::unique_lock lock(vmCreationLock_); + return initialized_; +} + void BaseRuntime::Init() { Init(BaseRuntimeParam::DefaultRuntimeParam()); } void BaseRuntime::Init(const RuntimeParam ¶m) +{ + CheckAndInitBaseRuntime(param); +} + +void BaseRuntime::InitFromDynamic() +{ + InitFromDynamic(BaseRuntimeParam::DefaultRuntimeParam()); +} + +void BaseRuntime::InitFromDynamic(const RuntimeParam ¶m) { std::unique_lock lock(vmCreationLock_); if (initialized_) { @@ -126,6 +142,11 @@ void BaseRuntime::Init(const RuntimeParam ¶m) } void BaseRuntime::Fini() +{ + CheckAndFiniBaseRuntime(); +} + +void BaseRuntime::FiniFromDynamic() { std::unique_lock lock(vmCreationLock_); if (!initialized_) { @@ -258,4 +279,9 @@ void BaseRuntime::NotifyHighSensitive(bool isStart) { Heap::GetHeap().NotifyHighSensitive(isStart); } + +void BaseRuntime::FillFreeObject(void *object, size_t size) +{ + common::FillFreeObject(object, size); +} } // namespace common diff --git a/common_components/common_runtime/hooks.h b/common_components/common_runtime/hooks.h index a59c64f5b813c6c7865b674b5e8a4bda18df6852..78f8d48258d0e6aad6a3e90db1c3b34876a4c5c5 100644 --- a/common_components/common_runtime/hooks.h +++ b/common_components/common_runtime/hooks.h @@ -18,6 +18,7 @@ #include +#include "common_interfaces/base/runtime_param.h" #include "common_interfaces/heap/heap_visitor.h" #include "common_interfaces/thread/mutator_base.h" @@ -43,6 +44,9 @@ PUBLIC_API void VisitDynamicThreadRoot(const RefFieldVisitor &visitorFunc, void PUBLIC_API void VisitDynamicWeakThreadRoot(const WeakRefFieldVisitor &visitorFunc, void *vm); PUBLIC_API void VisitDynamicThreadPreforwardRoot(const RefFieldVisitor &visitorFunc, void *vm); +PUBLIC_API void AddXRefToDynamicRoots(); +PUBLIC_API void RemoveXRefFromDynamicRoots(); + PUBLIC_API void VisitJSThread(void *jsThread, CommonRootVisitor visitor); PUBLIC_API void SynchronizeGCPhaseToJSThread(void *jsThread, GCPhase gcPhase); @@ -58,5 +62,8 @@ PUBLIC_API bool IsMachineCodeObject(uintptr_t obj); PUBLIC_API void JitFortUnProt(size_t size, void* base); PUBLIC_API void MarkThreadLocalJitFortInstalled(void *thread, void *machineCode); +// Used for init/fini BaseRuntime from static +PUBLIC_API void CheckAndInitBaseRuntime(const RuntimeParam ¶m); +PUBLIC_API void CheckAndFiniBaseRuntime(); } // namespace common #endif // COMMON_COMPONENTS_BASE_RUNTIME_HOOKS_H diff --git a/common_components/common_runtime/tests/base_runtime_test.cpp b/common_components/common_runtime/tests/base_runtime_test.cpp index 033020630bd103a769be2fc6f04edd80800821a5..2910c77c3ff9507f797c901824a076729897986c 100644 --- a/common_components/common_runtime/tests/base_runtime_test.cpp +++ b/common_components/common_runtime/tests/base_runtime_test.cpp @@ -91,7 +91,7 @@ HWTEST_F_L0(BaseRuntimeTest, ThreadSafe_GetInstance) { HWTEST_F_L0(BaseRuntimeTest, RequestGC_Sync_CallsHeapManager) { auto* runtime = BaseRuntime::GetInstance(); ASSERT_NE(runtime, nullptr); - runtime->Init(); + runtime->InitFromDynamic(); struct TestCase { GCReason reason; bool async; diff --git a/common_components/heap/allocator/tests/heap_allocator_test.cpp b/common_components/heap/allocator/tests/heap_allocator_test.cpp index 7423874fc20bdbb8507e2fa7a14d4ccd6e6404d6..d2fcdd9c97d6c9624b93ec74786bc939ad494edd 100644 --- a/common_components/heap/allocator/tests/heap_allocator_test.cpp +++ b/common_components/heap/allocator/tests/heap_allocator_test.cpp @@ -26,12 +26,12 @@ class HeapAllocatorTest : public BaseTestWithScope { protected: static void SetUpTestCase() { - BaseRuntime::GetInstance()->Init(); + BaseRuntime::GetInstance()->InitFromDynamic(); } static void TearDownTestCase() { - BaseRuntime::GetInstance()->Fini(); + BaseRuntime::GetInstance()->FiniFromDynamic(); } void SetUp() override diff --git a/common_components/heap/allocator/tests/region_manager_test.cpp b/common_components/heap/allocator/tests/region_manager_test.cpp index 7e7b02b7754f3907956dae4ba4bdf1d780caaad2..b628a3d0cdca4e0508b997d28489dc8741dcd22b 100755 --- a/common_components/heap/allocator/tests/region_manager_test.cpp +++ b/common_components/heap/allocator/tests/region_manager_test.cpp @@ -41,12 +41,12 @@ protected: static void SetUpTestCase() { - BaseRuntime::GetInstance()->Init(); + BaseRuntime::GetInstance()->InitFromDynamic(); } static void TearDownTestCase() { - BaseRuntime::GetInstance()->Fini(); + BaseRuntime::GetInstance()->FiniFromDynamic(); } void SetUp() override diff --git a/common_components/heap/allocator/tests/regional_heap_test.cpp b/common_components/heap/allocator/tests/regional_heap_test.cpp index bfca54a4fca9d47f70e00f87331697c3d59bbfc7..98651fd818cc7a05ae42e9007e55c215e61d39e3 100755 --- a/common_components/heap/allocator/tests/regional_heap_test.cpp +++ b/common_components/heap/allocator/tests/regional_heap_test.cpp @@ -32,12 +32,12 @@ class RegionalHeapTest : public common::test::BaseTestWithScope { protected: static void SetUpTestCase() { - BaseRuntime::GetInstance()->Init(); + BaseRuntime::GetInstance()->InitFromDynamic(); } static void TearDownTestCase() { - BaseRuntime::GetInstance()->Fini(); + BaseRuntime::GetInstance()->FiniFromDynamic(); } void SetUp() override diff --git a/common_components/heap/ark_collector/ark_collector.cpp b/common_components/heap/ark_collector/ark_collector.cpp index 2d90d197738a6956d045beb9f645f6d999aab28a..6b8b8e23dc82662f7484523f5c1d3aa591e3b10b 100755 --- a/common_components/heap/ark_collector/ark_collector.cpp +++ b/common_components/heap/ark_collector/ark_collector.cpp @@ -211,6 +211,36 @@ MarkingCollector::MarkingRefFieldVisitor ArkCollector::CreateMarkingObjectRefFie return visitor; } +#ifdef PANDA_JS_ETS_HYBRID_MODE +// note each ref-field will not be traced twice, so each old pointer the tracer meets must come from previous gc. +void ArkCollector::MarkingXRef(RefField<> &field, ParallelLocalMarkStack &workStack) const +{ + BaseObject* targetObj = field.GetTargetObject(); + auto region = RegionDesc::GetRegionDescAt(reinterpret_cast(targetObj)); + // field is tagged object, should be in heap + DCHECK_CC(Heap::IsHeapAddress(targetObj)); + + DLOG(TRACE, "trace obj %p <%p>(%zu)", targetObj, targetObj->GetTypeInfo(), targetObj->GetSize()); + if (region->IsNewObjectSinceForward(targetObj)) { + DLOG(TRACE, "trace: skip new obj %p<%p>(%zu)", targetObj, targetObj->GetTypeInfo(), targetObj->GetSize()); + return; + } + ASSERT(!field.IsWeak()); + if (!region->MarkObject(targetObj)) { + workStack.Push(targetObj); + } +} + +void ArkCollector::MarkingObjectXRef(BaseObject *obj, ParallelLocalMarkStack &workStack) +{ + auto refFunc = [this, &workStack] (RefField<>& field) { + MarkingXRef(field, workStack); + }; + + obj->IterateXRef(refFunc); +} +#endif + void ArkCollector::FixRefField(BaseObject* obj, RefField<>& field) const { RefField<> oldField(field); @@ -770,10 +800,62 @@ void ArkCollector::FixHeap() WVerify::VerifyAfterFix(*this); } +void ArkCollector::CollectGarbageWithXRef() +{ + const bool isNotYoungGC = gcReason_ != GCReason::GC_REASON_YOUNG; +#ifdef ENABLE_CMC_RB_DFX + WVerify::DisableReadBarrierDFX(*this); +#endif + STWParam stwParam{"stw-gc"}; + ScopedStopTheWorld stw(stwParam); + RemoveXRefFromRoots(); + + auto collectedRoots = EnumRoots(); + MarkingHeap(collectedRoots); + TransitionToGCPhase(GCPhase::GC_PHASE_FINAL_MARK, true); + Remark(); + SweepUnmarkedXRefs(); + PostMarking(); + + AddXRefToRoots(); + Preforward(); + ConcurrentPreforward(); + // reclaim large objects should after preforward(may process weak ref) and + // before fix heap(may clear live bit) + if (isNotYoungGC) { + CollectLargeGarbage(); + } + SweepThreadLocalJitFort(); + + CopyFromSpace(); + WVerify::VerifyAfterForward(*this); + + PrepareFix(); + FixHeap(); + if (isNotYoungGC) { + CollectNonMovableGarbage(); + } + + TransitionToGCPhase(GCPhase::GC_PHASE_IDLE, true); + + ClearAllGCInfo(); + CollectSmallSpace(); + UnmarkAllXRefs(); + +#if defined(ENABLE_CMC_RB_DFX) + WVerify::EnableReadBarrierDFX(*this); +#endif + GetGCStats().recordSTWTime(stwParam.GetElapsedNs()); +} + void ArkCollector::DoGarbageCollection() { const bool isNotYoungGC = gcReason_ != GCReason::GC_REASON_YOUNG; OHOS_HITRACE(HITRACE_LEVEL_COMMERCIAL, "CMCGC::DoGarbageCollection", ""); + if (gcReason_ == GCReason::GC_REASON_XREF) { + CollectGarbageWithXRef(); + return; + } if (gcMode_ == GCMode::STW) { // 2: stw-gc #ifdef ENABLE_CMC_RB_DFX WVerify::DisableReadBarrierDFX(*this); diff --git a/common_components/heap/ark_collector/ark_collector.h b/common_components/heap/ark_collector/ark_collector.h index a26e5786f1e78636d5cecaec9298eb1293399ac8..c5ef11b1ee122fb0cf44c8d1abd17751c69abb48 100755 --- a/common_components/heap/ark_collector/ark_collector.h +++ b/common_components/heap/ark_collector/ark_collector.h @@ -92,6 +92,11 @@ public: MarkingRefFieldVisitor CreateMarkingObjectRefFieldsVisitor(ParallelLocalMarkStack &workStack, WeakStack &weakStack) override; +#ifdef PANDA_JS_ETS_HYBRID_MODE + void MarkingXRef(RefField<> &ref, ParallelLocalMarkStack &workStack) const; + void MarkingObjectXRef(BaseObject *obj, ParallelLocalMarkStack &workStack) override; +#endif + void FixObjectRefFields(BaseObject* obj) const override; void FixRefField(BaseObject* obj, RefField<>& field) const; @@ -230,6 +235,8 @@ private: RefFieldVisitor GetPrefowardRefFieldVisitor(); void PreforwardFlip(); + void CollectGarbageWithXRef(); + CopyTable fwdTable_; GCMode gcMode_ = GCMode::CMC; diff --git a/common_components/heap/ark_collector/tests/ark_collector_test.cpp b/common_components/heap/ark_collector/tests/ark_collector_test.cpp index 6ebb09a96caa2ce2af608a7128532ddbc46a1707..598270f109aed814584826220b9b74f47bc38218 100644 --- a/common_components/heap/ark_collector/tests/ark_collector_test.cpp +++ b/common_components/heap/ark_collector/tests/ark_collector_test.cpp @@ -33,7 +33,7 @@ class ArkCollectorTest : public common::test::BaseTestWithScope { protected: static void SetUpTestCase() { - BaseRuntime::GetInstance()->Init(); + BaseRuntime::GetInstance()->InitFromDynamic(); } static void TearDownTestCase() @@ -225,6 +225,8 @@ public: fwdPtr_ = fwdPtr; } void SetSize(size_t size) { size_ = size; } + void ForEachRefFieldSkipReferent(const BaseObject *object, const RefFieldVisitor &visitor) const override {} + void IterateXRef(const BaseObject *object, const RefFieldVisitor &visitor) const override {} private: size_t size_ = 0; BaseObject *fwdPtr_ = nullptr; @@ -524,6 +526,8 @@ public: { return const_cast(object); } + void ForEachRefFieldSkipReferent(const BaseObject *object, const RefFieldVisitor &visitor) const override {} + void IterateXRef(const BaseObject *object, const RefFieldVisitor &visitor) const override {} }; HWTEST_F_L0(ArkCollectorTest, ForwardUpdateRawRef_TEST1) diff --git a/common_components/heap/ark_collector/tests/copy_barrier_test.cpp b/common_components/heap/ark_collector/tests/copy_barrier_test.cpp index 280fd8758a6d5cf114f2c127e247c289791f459f..232cc07cc3bd712bad84d8da168184f50449fa24 100755 --- a/common_components/heap/ark_collector/tests/copy_barrier_test.cpp +++ b/common_components/heap/ark_collector/tests/copy_barrier_test.cpp @@ -27,7 +27,7 @@ class CopyBarrierTest : public common::test::BaseTestWithScope { protected: static void SetUpTestCase() { - BaseRuntime::GetInstance()->Init(); + BaseRuntime::GetInstance()->InitFromDynamic(); } static void TearDownTestCase() {} diff --git a/common_components/heap/ark_collector/tests/enum_barrier_test.cpp b/common_components/heap/ark_collector/tests/enum_barrier_test.cpp index 0bd15341454b7100aabbd53c22d32f5deea948e1..38e76406892b37a607f440731470f5b9ca0c4b6f 100755 --- a/common_components/heap/ark_collector/tests/enum_barrier_test.cpp +++ b/common_components/heap/ark_collector/tests/enum_barrier_test.cpp @@ -27,7 +27,7 @@ class EnumBarrierTest : public common::test::BaseTestWithScope { protected: static void SetUpTestCase() { - BaseRuntime::GetInstance()->Init(); + BaseRuntime::GetInstance()->InitFromDynamic(); } static void TearDownTestCase() {} diff --git a/common_components/heap/ark_collector/tests/idle_barrier_test.cpp b/common_components/heap/ark_collector/tests/idle_barrier_test.cpp index 45b96dfa71b3452f6fd19b35fdb6d9995d023caf..f09959d1308ce18be596918950ffbf060a491c01 100755 --- a/common_components/heap/ark_collector/tests/idle_barrier_test.cpp +++ b/common_components/heap/ark_collector/tests/idle_barrier_test.cpp @@ -27,7 +27,7 @@ class IdleBarrierTest : public common::test::BaseTestWithScope { protected: static void SetUpTestCase() { - BaseRuntime::GetInstance()->Init(); + BaseRuntime::GetInstance()->InitFromDynamic(); } static void TearDownTestCase() {} diff --git a/common_components/heap/ark_collector/tests/marking_barrier_test.cpp b/common_components/heap/ark_collector/tests/marking_barrier_test.cpp index 0543a2bbe357843cfd1ed00b3884ce225abb2897..8ac7aa93b578da0e13ef8869c57ce69b5dc239e6 100755 --- a/common_components/heap/ark_collector/tests/marking_barrier_test.cpp +++ b/common_components/heap/ark_collector/tests/marking_barrier_test.cpp @@ -27,7 +27,7 @@ class MarkingBarrierTest : public BaseTestWithScope { protected: static void SetUpTestCase() { - BaseRuntime::GetInstance()->Init(); + BaseRuntime::GetInstance()->InitFromDynamic(); } static void TearDownTestCase() {} diff --git a/common_components/heap/ark_collector/tests/post_marking_barrier_test.cpp b/common_components/heap/ark_collector/tests/post_marking_barrier_test.cpp index f995ffbf75ceca76003c0121ae7c9053ba12d61e..809ca518e749652077cf3571a1e77723adbf1933 100755 --- a/common_components/heap/ark_collector/tests/post_marking_barrier_test.cpp +++ b/common_components/heap/ark_collector/tests/post_marking_barrier_test.cpp @@ -27,7 +27,7 @@ class PostMarkingBarrierTest : public ::testing::Test { protected: static void SetUpTestCase() { - BaseRuntime::GetInstance()->Init(); + BaseRuntime::GetInstance()->InitFromDynamic(); } static void TearDownTestCase() {} diff --git a/common_components/heap/ark_collector/tests/preforward_barrier_test.cpp b/common_components/heap/ark_collector/tests/preforward_barrier_test.cpp index 11851db59c9f7f4dbacc0a40ecd409b64b4f076b..42b2c0a7aec9df4b56f78574a63b4134444d318c 100755 --- a/common_components/heap/ark_collector/tests/preforward_barrier_test.cpp +++ b/common_components/heap/ark_collector/tests/preforward_barrier_test.cpp @@ -27,7 +27,7 @@ class PreforwardBarrierTest : public BaseTestWithScope { protected: static void SetUpTestCase() { - BaseRuntime::GetInstance()->Init(); + BaseRuntime::GetInstance()->InitFromDynamic(); } static void TearDownTestCase() {} diff --git a/common_components/heap/ark_collector/tests/remark_barrier_test.cpp b/common_components/heap/ark_collector/tests/remark_barrier_test.cpp index cccc48e689cf3b3029cc5819c833bfde4f042e82..04cf5a52caeeb47ef9a03f2ffa660244bf7b8c1f 100755 --- a/common_components/heap/ark_collector/tests/remark_barrier_test.cpp +++ b/common_components/heap/ark_collector/tests/remark_barrier_test.cpp @@ -27,7 +27,7 @@ class RemarkBarrierTest : public BaseTestWithScope { protected: static void SetUpTestCase() { - BaseRuntime::GetInstance()->Init(); + BaseRuntime::GetInstance()->InitFromDynamic(); } static void TearDownTestCase() {} diff --git a/common_components/heap/collector/gc_request.cpp b/common_components/heap/collector/gc_request.cpp index 88d40531c99da24b5de7844686cf467fa1556fb2..61fe6ca5f0e96351c863bbd3338231067731000d 100755 --- a/common_components/heap/collector/gc_request.cpp +++ b/common_components/heap/collector/gc_request.cpp @@ -71,6 +71,7 @@ GCRequest g_gcRequests[] = { { GC_REASON_NATIVE_SYNC, "native_alloc_sync", true, true, 0, 0 }, { GC_REASON_FORCE, "force", true, false, 0, 0 }, { GC_REASON_APPSPAWN, "appspawn", true, false, 0, 0 }, + { GC_REASON_XREF, "force_xref", true, false, 0, 0 }, { GC_REASON_BACKGROUND, "backgound", false, true, LONG_MIN_HEU_GC_INTERVAL_NS, g_initHeuTriggerTimestamp }, { GC_REASON_HINT, "hint", false, true, LONG_MIN_HEU_GC_INTERVAL_NS, g_initHeuTriggerTimestamp }, { GC_REASON_IDLE, "idle", false, true, LONG_MIN_HEU_GC_INTERVAL_NS, g_initHeuTriggerTimestamp } diff --git a/common_components/heap/collector/marking_collector.cpp b/common_components/heap/collector/marking_collector.cpp index 3dbc188e8bd415771cb0996bdba5d407b4312c40..4d513c8e11a540d81f29351a96db2d3d18a85f09 100755 --- a/common_components/heap/collector/marking_collector.cpp +++ b/common_components/heap/collector/marking_collector.cpp @@ -48,6 +48,7 @@ void StaticRootTable::VisitRoots(const RefFieldVisitor& visitor) } } +template class ConcurrentMarkingTask : public common::Task { public: ConcurrentMarkingTask(uint32_t id, MarkingCollector &tc, ParallelMarkingMonitor &monitor, @@ -65,7 +66,7 @@ public: if (!monitor_.TryStartStep()) { break; } - collector_.ProcessMarkStack(threadIndex, markStack); + collector_.ProcessMarkStack(threadIndex, markStack); monitor_.FinishStep(); } while (monitor_.WaitNextStepOrFinished()); monitor_.NotifyFinishOne(); @@ -121,6 +122,7 @@ void MarkingCollector::ProcessWeakStack(WeakStack &weakStack) ClearWeakRef(begin, end); } +template void MarkingCollector::ProcessMarkStack([[maybe_unused]] uint32_t threadIndex, ParallelLocalMarkStack &markStack) { size_t nNewlyMarked = 0; @@ -153,6 +155,11 @@ void MarkingCollector::ProcessMarkStack([[maybe_unused]] uint32_t threadIndex, P visitor.SetMarkingRefFieldArgs(object); auto objSize = object->ForEachRefFieldAndGetSize(visitor.GetRefFieldVisitor()); region->AddLiveByteCount(objSize); +#ifdef PANDA_JS_ETS_HYBRID_MODE + if constexpr (ProcessXRef) { + MarkingObjectXRef(object, markStack); + } +#endif } // Try some task from satb buffer, bound the loop to make sure it converges in time if (++iterationCnt >= maxIterationLoopNum) { @@ -237,14 +244,30 @@ void MarkingCollector::TracingImpl(GlobalMarkStack &globalMarkStack, bool parall uint32_t threadCount = parallelCount + 1; ParallelMarkingMonitor monitor(parallelCount, parallelCount); for (uint32_t i = 0; i < parallelCount; ++i) { - threadPool->PostTask(std::make_unique(0, *this, monitor, globalMarkStack)); +#ifdef PANDA_JS_ETS_HYBRID_MODE + if (gcReason_ == GCReason::GC_REASON_XREF) { + threadPool->PostTask(std::make_unique>(0, *this, monitor, globalMarkStack)); + } else { + threadPool->PostTask(std::make_unique>(0, *this, monitor, globalMarkStack)); + } +#else + threadPool->PostTask(std::make_unique>(0, *this, monitor, globalMarkStack)); +#endif } ParallelLocalMarkStack markStack(&globalMarkStack, &monitor); do { if (!monitor.TryStartStep()) { break; } - ProcessMarkStack(0, markStack); +#ifdef PANDA_JS_ETS_HYBRID_MODE + if (gcReason_ == GCReason::GC_REASON_XREF) { + ProcessMarkStack(0, markStack); + } else { + ProcessMarkStack(0, markStack); + } +#else + ProcessMarkStack(0, markStack); +#endif monitor.FinishStep(); } while (monitor.WaitNextStepOrFinished()); monitor.WaitAllFinished(); @@ -255,7 +278,15 @@ void MarkingCollector::TracingImpl(GlobalMarkStack &globalMarkStack, bool parall // So for convenience just use a fake dummy parallel one. ParallelMarkingMonitor dummyMonitor(0, 0); ParallelLocalMarkStack markStack(&globalMarkStack, &dummyMonitor); - ProcessMarkStack(0, markStack); +#ifdef PANDA_JS_ETS_HYBRID_MODE + if (gcReason_ == GCReason::GC_REASON_XREF) { + ProcessMarkStack(0, markStack); + } else { + ProcessMarkStack(0, markStack); + } +#else + ProcessMarkStack(0, markStack); +#endif } } diff --git a/common_components/heap/collector/marking_collector.h b/common_components/heap/collector/marking_collector.h index 102bd56f1f28fbb1c4ad43b12254762038f0a1bc..2c1fe9af317f087a23889c42874c7c3752429b83 100755 --- a/common_components/heap/collector/marking_collector.h +++ b/common_components/heap/collector/marking_collector.h @@ -115,6 +115,7 @@ public: }; class MarkingWork; +template class ConcurrentMarkingWork; using RootSet = MarkStack; constexpr size_t LOCAL_MARK_STACK_CAPACITY = 128; @@ -128,7 +129,8 @@ using WeakStack = CArrayList*, size_t>>; class MarkingCollector : public Collector { friend MarkingWork; - friend ConcurrentMarkingWork; + template + friend class ConcurrentMarkingWork; public: explicit MarkingCollector(Allocator& allocator, CollectorResources& resources) @@ -178,6 +180,7 @@ public: bool ShouldIgnoreRequest(GCRequest& request) override { return request.ShouldBeIgnored(); } + template void ProcessMarkStack(uint32_t threadIndex, ParallelLocalMarkStack &workStack); void ProcessWeakStack(WeakStack &weakStack); @@ -217,6 +220,14 @@ public: }; virtual MarkingRefFieldVisitor CreateMarkingObjectRefFieldsVisitor(ParallelLocalMarkStack &workStack, WeakStack &weakStack) = 0; +#ifdef PANDA_JS_ETS_HYBRID_MODE + virtual void MarkingObjectXRef(BaseObject *obj, ParallelLocalMarkStack &workStack) + { + LOG_COMMON(FATAL) << "Unresolved fatal"; + UNREACHABLE_CC(); + } +#endif + inline bool IsResurrectedObject(const BaseObject* obj) const { return RegionalHeap::IsResurrectedObject(obj); } Allocator& GetAllocator() const { return theAllocator_; } diff --git a/common_components/heap/collector/tests/collector_proxy_test.cpp b/common_components/heap/collector/tests/collector_proxy_test.cpp index 2baca36eb1519c6ea39bd6eb5f2cbff4e4b2fac8..5592fd975c5c5761180aff0dc9b20d3216049444 100644 --- a/common_components/heap/collector/tests/collector_proxy_test.cpp +++ b/common_components/heap/collector/tests/collector_proxy_test.cpp @@ -22,12 +22,12 @@ class CollectorProxyTest : public common::test::BaseTestWithScope { protected: static void SetUpTestCase() { - BaseRuntime::GetInstance()->Init(); + BaseRuntime::GetInstance()->InitFromDynamic(); } static void TearDownTestCase() { - BaseRuntime::GetInstance()->Fini(); + BaseRuntime::GetInstance()->FiniFromDynamic(); } void SetUp() override {} diff --git a/common_components/heap/collector/tests/collector_resources_test.cpp b/common_components/heap/collector/tests/collector_resources_test.cpp index 490c776ecbbf5b1081494940d105238e4acba5bd..da62caa13a0ff683477942a57b5e2999d41402b7 100755 --- a/common_components/heap/collector/tests/collector_resources_test.cpp +++ b/common_components/heap/collector/tests/collector_resources_test.cpp @@ -26,12 +26,12 @@ class CollectorResourcesTest : public BaseTestWithScope { protected: static void SetUpTestCase() { - BaseRuntime::GetInstance()->Init(); + BaseRuntime::GetInstance()->InitFromDynamic(); } static void TearDownTestCase() { - BaseRuntime::GetInstance()->Fini(); + BaseRuntime::GetInstance()->FiniFromDynamic(); } void SetUp() override diff --git a/common_components/heap/collector/tests/finalizer_processor_test.cpp b/common_components/heap/collector/tests/finalizer_processor_test.cpp index 6dc55b486b27e7afb29b50fc9c36d05ad49b14ec..cba53beab42d93eceee9a27afeea572b4b2e92ea 100755 --- a/common_components/heap/collector/tests/finalizer_processor_test.cpp +++ b/common_components/heap/collector/tests/finalizer_processor_test.cpp @@ -29,7 +29,7 @@ class FinalizerProcessorTest : public common::test::BaseTestWithScope { protected: static void SetUpTestCase() { - BaseRuntime::GetInstance()->Init(); + BaseRuntime::GetInstance()->InitFromDynamic(); } static void TearDownTestCase() {} diff --git a/common_components/heap/collector/tests/heuristic_gc_policy_test.cpp b/common_components/heap/collector/tests/heuristic_gc_policy_test.cpp index a0961fab9e48614532e4b18e9700839d0d729ff5..a70c260043215314332f91a1cfb7e425ef57b3e0 100644 --- a/common_components/heap/collector/tests/heuristic_gc_policy_test.cpp +++ b/common_components/heap/collector/tests/heuristic_gc_policy_test.cpp @@ -31,12 +31,12 @@ protected: { RuntimeParam param = BaseRuntimeParam::DefaultRuntimeParam(); param.gcParam.enableGC = false; - BaseRuntime::GetInstance()->Init(param); + BaseRuntime::GetInstance()->InitFromDynamic(param); } static void TearDownTestCase() { - BaseRuntime::GetInstance()->Fini(); + BaseRuntime::GetInstance()->FiniFromDynamic(); } void SetUp() override diff --git a/common_components/heap/collector/tests/marking_collector_test.cpp b/common_components/heap/collector/tests/marking_collector_test.cpp index f96ff418e6b8f9789e613a2d95dc8d8f842445fd..cadc533b71ad20517dd166a77226324399fba67f 100755 --- a/common_components/heap/collector/tests/marking_collector_test.cpp +++ b/common_components/heap/collector/tests/marking_collector_test.cpp @@ -27,12 +27,12 @@ class MarkingCollectorTest : public common::test::BaseTestWithScope { protected: static void SetUpTestCase() { - BaseRuntime::GetInstance()->Init(); + BaseRuntime::GetInstance()->InitFromDynamic(); } static void TearDownTestCase() { - BaseRuntime::GetInstance()->Fini(); + BaseRuntime::GetInstance()->FiniFromDynamic(); } void SetUp() override { diff --git a/common_components/heap/heap_visitor.cpp b/common_components/heap/heap_visitor.cpp index 6b9545a87c9604a2c8a54497f08e0064f02694aa..ff42ba70903ec794d5e096fe25392b3f47c674bb 100755 --- a/common_components/heap/heap_visitor.cpp +++ b/common_components/heap/heap_visitor.cpp @@ -17,8 +17,31 @@ #include "common_components/common_runtime/hooks.h" #include "common_components/mutator/mutator.h" - namespace common { +UnmarkAllXRefsHookFunc g_unmarkAllXRefsHook = nullptr; +SweepUnmarkedXRefsHookFunc g_sweepUnmarkedXRefsHook = nullptr; +AddXRefToStaticRootsHookFunc g_addXRefToStaticRootsHook = nullptr; +RemoveXRefFromStaticRootsHookFunc g_removeXRefFromStaticRootsHook = nullptr; + +VisitStaticRootsHookFunc g_visitStaticRootsHook = nullptr; +UpdateStaticRootsHookFunc g_updateStaticRootsHook = nullptr; +SweepStaticRootsHookFunc g_sweepStaticRootsHook = nullptr; + +void RegisterVisitStaticRootsHook(VisitStaticRootsHookFunc func) +{ + g_visitStaticRootsHook = func; +} + +void RegisterUpdateStaticRootsHook(UpdateStaticRootsHookFunc func) +{ + g_updateStaticRootsHook = func; +} + +void RegisterSweepStaticRootsHook(SweepStaticRootsHookFunc func) +{ + g_sweepStaticRootsHook = func; +} + void VisitRoots(const RefFieldVisitor &visitor) { @@ -33,6 +56,15 @@ void VisitSTWRoots(const RefFieldVisitor &visitor) VisitDynamicGlobalRoots(visitor); VisitDynamicLocalRoots(visitor); VisitBaseRoots(visitor); + // if (isMark) { + // if (g_visitStaticRootsHook != nullptr) { + // g_visitStaticRootsHook(visitor); + // } + // } else { + // if (g_updateStaticRootsHook != nullptr) { + // g_updateStaticRootsHook(visitor); + // } + // } } void VisitConcurrentRoots(const RefFieldVisitor &visitor) @@ -45,18 +77,39 @@ void VisitWeakRoots(const WeakRefFieldVisitor &visitor) VisitDynamicWeakGlobalRoots(visitor); VisitDynamicWeakGlobalRootsOld(visitor); VisitDynamicWeakLocalRoots(visitor); + // if (g_updateStaticRootsHook != nullptr) { + // g_updateStaticRootsHook(visitor); + // } + // if (g_sweepStaticRootsHook != nullptr) { + // g_sweepStaticRootsHook(visitor); + // } } void VisitGlobalRoots(const RefFieldVisitor &visitor) { VisitDynamicGlobalRoots(visitor); VisitBaseRoots(visitor); + // if (isMark) { + // if (g_visitStaticRootsHook != nullptr) { + // g_visitStaticRootsHook(visitor); + // } + // } else { + // if (g_updateStaticRootsHook != nullptr) { + // g_updateStaticRootsHook(visitor); + // } + // } } void VisitWeakGlobalRoots(const WeakRefFieldVisitor &visitor) { VisitDynamicWeakGlobalRoots(visitor); VisitDynamicWeakGlobalRootsOld(visitor); + // if (g_updateStaticRootsHook != nullptr) { + // g_updateStaticRootsHook(visitor); + // } + // if (g_sweepStaticRootsHook != nullptr) { + // g_sweepStaticRootsHook(visitor); + // } } void VisitPreforwardRoots(const RefFieldVisitor &visitor) @@ -85,4 +138,46 @@ void VisitMutatorPreforwardRoot(const RefFieldVisitor &visitor, Mutator &mutator VisitDynamicThreadPreforwardRoot(visitor, mutator.GetEcmaVMPtr()); } } + +void RegisterUnmarkAllXRefsHook(UnmarkAllXRefsHookFunc func) +{ + g_unmarkAllXRefsHook = func; +} + +void RegisterSweepUnmarkedXRefsHook(SweepUnmarkedXRefsHookFunc func) +{ + g_sweepUnmarkedXRefsHook = func; +} + +void RegisterAddXRefToStaticRootsHook(AddXRefToStaticRootsHookFunc func) +{ + g_addXRefToStaticRootsHook = func; +} + +void RegisterRemoveXRefFromStaticRootsHook(RemoveXRefFromStaticRootsHookFunc func) +{ + g_removeXRefFromStaticRootsHook = func; +} + +void UnmarkAllXRefs() +{ + g_unmarkAllXRefsHook(); +} + +void SweepUnmarkedXRefs() +{ + g_sweepUnmarkedXRefsHook(); +} + +void AddXRefToRoots() +{ + AddXRefToDynamicRoots(); + g_addXRefToStaticRootsHook(); +} + +void RemoveXRefFromRoots() +{ + RemoveXRefFromDynamicRoots(); + g_removeXRefFromStaticRootsHook(); +} } // namespace common diff --git a/common_components/heap/space/tests/from_space_test.cpp b/common_components/heap/space/tests/from_space_test.cpp index 590a86050f954c3abc676a47602cc593f9f34ce5..f0af1675f452c97133b29ac5a709f2825065cbec 100644 --- a/common_components/heap/space/tests/from_space_test.cpp +++ b/common_components/heap/space/tests/from_space_test.cpp @@ -29,12 +29,12 @@ protected: }; static void SetUpTestCase() { - BaseRuntime::GetInstance()->Init(); + BaseRuntime::GetInstance()->InitFromDynamic(); } static void TearDownTestCase() { - BaseRuntime::GetInstance()->Fini(); + BaseRuntime::GetInstance()->FiniFromDynamic(); } void SetUp() override {} diff --git a/common_components/heap/tests/heap_manager_test.cpp b/common_components/heap/tests/heap_manager_test.cpp index 7721f429c268c8bdbdad2c1327c90e9c69ed5558..741c2ac191896ec20e46a05dcd21a9c2b8eaa49a 100644 --- a/common_components/heap/tests/heap_manager_test.cpp +++ b/common_components/heap/tests/heap_manager_test.cpp @@ -23,7 +23,7 @@ class HeapManagerTest : public common::test::BaseTestWithScope { protected: static void SetUpTestCase() { - BaseRuntime::GetInstance()->Init(); + BaseRuntime::GetInstance()->InitFromDynamic(); } }; diff --git a/common_components/heap/tests/verification_test.cpp b/common_components/heap/tests/verification_test.cpp index d5815e379cc5502af99cdcf1b561d5302287989d..46411a91f1f7222663222ddde17abe3994c6eaa2 100644 --- a/common_components/heap/tests/verification_test.cpp +++ b/common_components/heap/tests/verification_test.cpp @@ -36,6 +36,8 @@ public: void SetForwardingPointerAfterExclusive(BaseObject *object, BaseObject *fwdPtr) override {} void SetValidObject(bool value) { enbaleValidObject_ = value; } void SetSize(size_t size) { size_ = size; } + void ForEachRefFieldSkipReferent(const BaseObject *object, const RefFieldVisitor &visitor) const override {} + void IterateXRef(const BaseObject *object, const RefFieldVisitor &visitor) const override {} private: bool enbaleValidObject_ = false; size_t size_ = 0; @@ -44,12 +46,12 @@ class VerificationTest : public common::test::BaseTestWithScope { protected: static void SetUpTestCase() { - BaseRuntime::GetInstance()->Init(); + BaseRuntime::GetInstance()->InitFromDynamic(); } static void TearDownTestCase() { - BaseRuntime::GetInstance()->Fini(); + BaseRuntime::GetInstance()->FiniFromDynamic(); } void SetUp() override diff --git a/common_components/heap/verification.cpp b/common_components/heap/verification.cpp index b67fea77b6e8326b49626d79149952d74c884dd6..1a26e5299ffd603d131842af50a94219f097fe9b 100755 --- a/common_components/heap/verification.cpp +++ b/common_components/heap/verification.cpp @@ -75,8 +75,11 @@ std::string HexDump(const void* address, size_t length) // Print content uint64_t word = 0; size_t bytesToRead = std::min(wordSize, length - i); - memcpy_s(&word, sizeof(uint64_t), ptr + i, bytesToRead); - + auto ret = memcpy_s(&word, sizeof(uint64_t), ptr + i, bytesToRead); + if (ret != EOK) { + LOG_COMMON(FATAL) << "memcpy_s failed: ret = " << ret; + break; + } oss << "0x" << std::setw(wordSize * hexDigitsPerByte) << word << std::endl; } diff --git a/common_components/log/log.h b/common_components/log/log.h index 1c2f908e28bd4e917aded7fd9318f91628e65c3e..207f01b45a1af84c1f4ff0da356c835cf46b548d 100644 --- a/common_components/log/log.h +++ b/common_components/log/log.h @@ -39,7 +39,8 @@ #if defined(ENABLE_HITRACE) #include "hitrace_meter.h" - #define OHOS_HITRACE(level, name, customArgs) HITRACE_METER_NAME_EX(level, HITRACE_TAG_ARK, name, customArgs) + #define OHOS_HITRACE(level, name, customArgs) \ + HITRACE_METER_NAME_EX(level, HITRACE_TAG_ARK, name, customArgs) #define OHOS_HITRACE_START(level, name, customArgs) StartTraceEx(level, HITRACE_TAG_ARK, name, customArgs) #define OHOS_HITRACE_FINISH(level) FinishTraceEx(level, HITRACE_TAG_ARK) #define OHOS_HITRACE_COUNT(level, name, count) CountTraceEx(level, HITRACE_TAG_ARK, name, count) diff --git a/common_components/mutator/tests/mutator_manager_test.cpp b/common_components/mutator/tests/mutator_manager_test.cpp index f66696fb23a1108ea4c1c41627c246c911a6f99f..7858c1a333da0f8cec5d0cbde3fe2b3e680145bc 100755 --- a/common_components/mutator/tests/mutator_manager_test.cpp +++ b/common_components/mutator/tests/mutator_manager_test.cpp @@ -82,7 +82,7 @@ HWTEST_F_L0(MutatorManagerTest, CreateMutator_Test1) ThreadLocalData* localData = ThreadLocal::GetThreadLocalData(); localData->mutator = new Mutator(); MutatorManager *managerPtr = new MutatorManager(); - BaseRuntime::GetInstance()->Init(); + BaseRuntime::GetInstance()->InitFromDynamic(); Mutator* ptr = managerPtr->CreateMutator(); EXPECT_TRUE(ptr != nullptr); diff --git a/common_components/mutator/tests/mutator_test.cpp b/common_components/mutator/tests/mutator_test.cpp index 3a4aa66ea6a9dfe7a210d054aa732e51da3a20bd..7fa9070aa3769ebeb1bd59625124ce83c065901e 100755 --- a/common_components/mutator/tests/mutator_test.cpp +++ b/common_components/mutator/tests/mutator_test.cpp @@ -31,7 +31,7 @@ class MutatorTest : public BaseTestWithScope { protected: static void SetUpTestCase() { - BaseRuntime::GetInstance()->Init(); + BaseRuntime::GetInstance()->InitFromDynamic(); } static void TearDownTestCase() {} }; diff --git a/common_components/mutator/tests/satb_buffer_test.cpp b/common_components/mutator/tests/satb_buffer_test.cpp index 9ad478220c5d636b38e2a0ad7112dca46b824df9..9028e7ab23a3c4cc3edaacf878603516dbb3f0fd 100755 --- a/common_components/mutator/tests/satb_buffer_test.cpp +++ b/common_components/mutator/tests/satb_buffer_test.cpp @@ -26,12 +26,12 @@ class SatbBufferTest : public BaseTestWithScope { protected: static void SetUpTestCase() { - BaseRuntime::GetInstance()->Init(); + BaseRuntime::GetInstance()->InitFromDynamic(); } static void TearDownTestCase() { - BaseRuntime::GetInstance()->Fini(); + BaseRuntime::GetInstance()->FiniFromDynamic(); } void SetUp() override diff --git a/common_components/objects/base_string.cpp b/common_components/objects/base_string.cpp index 6ec3ada819b297d382b7cdc0a1bd3bce8883bbb3..20a54fbdc228ba5c3e93e2a102f756e765f38514 100644 --- a/common_components/objects/base_string.cpp +++ b/common_components/objects/base_string.cpp @@ -12,475 +12,136 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#include "common_interfaces/objects/string/base_string.h" -#include -#include - +#include "common_interfaces/objects/string/base_string-inl.h" +#include "common_interfaces/objects/utils/utf_utils.h" #include "common_components/base/utf_helper.h" -#include "common_interfaces/objects/base_string.h" - #include "common_components/platform/string_hash.h" #include "common_components/platform/string_hash_helper.h" -namespace common { - constexpr size_t LOW_3BITS = 0x7; - constexpr size_t LOW_4BITS = 0xF; - constexpr size_t LOW_5BITS = 0x1F; - constexpr size_t LOW_6BITS = 0x3F; - constexpr size_t L_SURROGATE_START = 0xDC00; - constexpr size_t H_SURROGATE_START = 0xD800; - constexpr size_t SURROGATE_RAIR_START = 0x10000; - constexpr size_t OFFSET_18POS = 18; - constexpr size_t OFFSET_12POS = 12; - constexpr size_t OFFSET_10POS = 10; - constexpr size_t OFFSET_6POS = 6; - - size_t UtfUtils::DebuggerConvertRegionUtf16ToUtf8(const uint16_t* utf16In, uint8_t* utf8Out, size_t utf16Len, - size_t utf8Len, size_t start, bool modify, bool isWriteBuffer) - { - return common::utf_helper::DebuggerConvertRegionUtf16ToUtf8(utf16In, utf8Out, utf16Len, utf8Len, - start, modify, isWriteBuffer); - } - - size_t UtfUtils::Utf8ToUtf16Size(const uint8_t* utf8, size_t utf8Len) - { - return common::utf_helper::Utf8ToUtf16Size(utf8, utf8Len); - } - - size_t UtfUtils::Utf16ToUtf8Size(const uint16_t* utf16, uint32_t length, bool modify, bool isGetBufferSize, - bool cesu8) - { - return common::utf_helper::Utf16ToUtf8Size(utf16, length, modify, isGetBufferSize, cesu8); - } - - size_t UtfUtils::ConvertRegionUtf8ToUtf16(const uint8_t* utf8In, uint16_t* utf16Out, size_t utf8Len, - size_t utf16Len) - { - return common::utf_helper::ConvertRegionUtf8ToUtf16(utf8In, utf16Out, utf8Len, utf16Len); - } - - size_t UtfUtils::ConvertRegionUtf16ToLatin1(const uint16_t* utf16In, uint8_t* latin1Out, size_t utf16Len, - size_t latin1Len) - { - return common::utf_helper::ConvertRegionUtf16ToLatin1(utf16In, latin1Out, utf16Len, latin1Len); - } - - size_t UtfUtils::ConvertRegionUtf16ToUtf8(const uint16_t* utf16In, uint8_t* utf8Out, size_t utf16Len, - size_t utf8Len, size_t start, bool modify, bool isWriteBuffer, bool cesu) - { - return common::utf_helper::ConvertRegionUtf16ToUtf8( - utf16In, utf8Out, utf16Len, utf8Len, start, modify, isWriteBuffer, cesu); - } - - - // To change the hash algorithm of BaseString, please modify BaseString::CalculateConcatHashCode - // and BaseStringHashHelper::ComputeHashForDataPlatform simultaneously!! - template - uint32_t ComputeHashForDataInternal(const T *data, size_t size, uint32_t hashSeed) - { - if (size <= static_cast(StringHash::MIN_SIZE_FOR_UNROLLING)) { - uint32_t hash = hashSeed; - for (uint32_t i = 0; i < size; i++) { - hash = (hash << static_cast(StringHash::HASH_SHIFT)) - hash + data[i]; - } - return hash; - } - return StringHashHelper::ComputeHashForDataPlatform(data, size, hashSeed); - } - - PUBLIC_API uint32_t BaseString::ComputeHashForData(const uint8_t *data, size_t size, uint32_t hashSeed) - { - return ComputeHashForDataInternal(data, size, hashSeed); - } - - PUBLIC_API uint32_t BaseString::ComputeHashForData(const uint16_t *data, size_t size, uint32_t hashSeed) - { - return ComputeHashForDataInternal(data, size, hashSeed); - } - - uint32_t BaseString::ComputeHashcodeUtf8(const uint8_t *utf8Data, size_t utf8Len, bool canBeCompress) - { - if (utf8Len == 0) { - return MixHashcode(0, NOT_INTEGER); - } - if (canBeCompress) { - uint32_t mixHash = 0; - // String using UTF8 encoding, and length smaller than 10, try to compute integer hash. - if (utf8Len < MAX_ELEMENT_INDEX_LEN && HashIntegerString(utf8Data, utf8Len, &mixHash, 0)) { - return mixHash; - } - uint32_t hash = ComputeHashForData(utf8Data, utf8Len, 0); - return MixHashcode(hash, NOT_INTEGER); - } - auto utf16Len = UtfUtils::Utf8ToUtf16Size(utf8Data, utf8Len); - std::vector tmpBuffer(utf16Len); - [[maybe_unused]] auto len = UtfUtils::ConvertRegionUtf8ToUtf16(utf8Data, tmpBuffer.data(), utf8Len, - utf16Len); - DCHECK_CC(len == utf16Len); - uint32_t hash = ComputeHashForData(tmpBuffer.data(), utf16Len, 0); - return MixHashcode(hash, NOT_INTEGER); - } - - /* static */ - uint32_t BaseString::ComputeHashcodeUtf16(const uint16_t *utf16Data, uint32_t length) - { - if (length == 0) { - return MixHashcode(0, NOT_INTEGER); - } - uint32_t mixHash = 0; - // String length smaller than 10, try to compute integer hash. - if (length < MAX_ELEMENT_INDEX_LEN && HashIntegerString(utf16Data, length, &mixHash, 0)) { - return mixHash; - } - uint32_t hash = ComputeHashForData(utf16Data, length, 0); - return MixHashcode(hash, NOT_INTEGER); - } - - - // drop the tail bytes if the remain length can't fill the length it represents. - static size_t FixUtf8Len(const uint8_t* utf8, size_t utf8Len) - { - constexpr size_t TWO_BYTES_LENGTH = 2; - constexpr size_t THREE_BYTES_LENGTH = 3; - size_t trimSize = 0; - if (utf8Len >= 1 && utf8[utf8Len - 1] >= 0xC0) { - // The last one char claim there are more than 1 byte next to it, it's invalid, so drop the last one. - trimSize = 1; - } - if (utf8Len >= TWO_BYTES_LENGTH && utf8[utf8Len - TWO_BYTES_LENGTH] >= 0xE0) { - // The second to last char claim there are more than 2 bytes next to it, it's invalid, so drop the last two. - trimSize = TWO_BYTES_LENGTH; - } - if (utf8Len >= THREE_BYTES_LENGTH && utf8[utf8Len - THREE_BYTES_LENGTH] >= 0xF0) { - // The third to last char claim there are more than 3 bytes next to it, it's invalid, so drop the last - // three. - trimSize = THREE_BYTES_LENGTH; - } - return utf8Len - trimSize; - } - - /* static */ - bool BaseString::IsUtf8EqualsUtf16(const uint8_t* utf8Data, size_t utf8Len, - const uint16_t* utf16Data, uint32_t utf16Len) - { - size_t safeUtf8Len = FixUtf8Len(utf8Data, utf8Len); - const uint8_t* utf8End = utf8Data + utf8Len; - const uint8_t* utf8SafeEnd = utf8Data + safeUtf8Len; - const uint16_t* utf16End = utf16Data + utf16Len; - while (utf8Data < utf8SafeEnd && utf16Data < utf16End) { - uint8_t src = *utf8Data; - switch (src & 0xF0) { - case 0xF0: - { - const uint8_t c2 = *(++utf8Data); - const uint8_t c3 = *(++utf8Data); - const uint8_t c4 = *(++utf8Data); - uint32_t codePoint = ((src & LOW_3BITS) << OFFSET_18POS) | ((c2 & LOW_6BITS) << OFFSET_12POS) | - ((c3 & LOW_6BITS) << OFFSET_6POS) | (c4 & LOW_6BITS); - if (codePoint >= SURROGATE_RAIR_START) { - if (utf16Data >= utf16End - 1) { - return false; - } - codePoint -= SURROGATE_RAIR_START; - if (*utf16Data++ != static_cast((codePoint >> OFFSET_10POS) | - H_SURROGATE_START)) { - return false; - } else if (*utf16Data++ != static_cast((codePoint & 0x3FF) | L_SURROGATE_START)) { - return false; - } - } else { - if (*utf16Data++ != static_cast(codePoint)) { - return false; - } - } - utf8Data++; - break; - } - case 0xE0: - { - const uint8_t c2 = *(++utf8Data); - const uint8_t c3 = *(++utf8Data); - if (*utf16Data++ != static_cast(((src & LOW_4BITS) << OFFSET_12POS) | - ((c2 & LOW_6BITS) << OFFSET_6POS) | (c3 & LOW_6BITS))) { - return false; - } - utf8Data++; - break; - } - case 0xD0: - case 0xC0: - { - const uint8_t c2 = *(++utf8Data); - if (*utf16Data++ != static_cast(((src & LOW_5BITS) << OFFSET_6POS) | (c2 & - LOW_6BITS))) { - return false; - } - utf8Data++; - break; - } - default: - do { - if (*utf16Data++ != static_cast(*utf8Data++)) { - return false; - } - } - while (utf8Data < utf8SafeEnd && utf16Data < utf16End && *utf8Data < 0x80); - break; - } - } - // The remain chars should be treated as single byte char. - while (utf8Data < utf8End && utf16Data < utf16End) { - if (*utf16Data++ != static_cast(*utf8Data++)) { - return false; - } - } - return utf8Data == utf8End && utf16Data == utf16End; - } - - // static - template - uint32_t BaseString::CalculateDataConcatHashCode(const T1* dataFirst, size_t sizeFirst, - const T2* dataSecond, size_t sizeSecond) - { - uint32_t totalHash = ComputeHashForData(dataFirst, sizeFirst, 0); - totalHash = ComputeHashForData(dataSecond, sizeSecond, totalHash); - return MixHashcode(totalHash, NOT_INTEGER); - } - - template - uint32_t BaseString::CalculateDataConcatHashCode(const uint8_t* dataFirst, size_t sizeFirst, - const uint8_t* dataSecond, size_t sizeSecond); - template - uint32_t BaseString::CalculateDataConcatHashCode(const uint16_t* dataFirst, size_t sizeFirst, - const uint16_t* dataSecond, size_t sizeSecond); - template - uint32_t BaseString::CalculateDataConcatHashCode(const uint8_t* dataFirst, size_t sizeFirst, - const uint16_t* dataSecond, size_t sizeSecond); - template - uint32_t BaseString::CalculateDataConcatHashCode(const uint16_t* dataFirst, size_t sizeFirst, - const uint8_t* dataSecond, size_t sizeSecond); - - - bool BaseString::CanBeCompressed(const BaseString* string) - { - DCHECK_CC(string->IsLineString()); - if (string->IsUtf8()) { - return CanBeCompressed(string->GetDataUtf8(), string->GetLength()); - } - return CanBeCompressed(string->GetDataUtf16(), string->GetLength()); - } - - // static - bool BaseString::CanBeCompressed(const uint8_t* utf8Data, uint32_t utf8Len) - { - uint32_t index = 0; - for (; index + 4 <= utf8Len; index += 4) { - // 4: process the data in chunks of 4 elements to improve speed - // Check if all four characters in the current block are ASCII characters - if (!IsASCIICharacter(utf8Data[index]) || - !IsASCIICharacter(utf8Data[index + 1]) || // 1: the second element of the block - !IsASCIICharacter(utf8Data[index + 2]) || // 2: the third element of the block - !IsASCIICharacter(utf8Data[index + 3])) { - // 3: the fourth element of the block - return false; - } - } - // Check remaining characters if they are ASCII - for (; index < utf8Len; ++index) { - if (!IsASCIICharacter(utf8Data[index])) { - return false; - } - } - return true; - } - - /* static */ - bool BaseString::CanBeCompressed(const uint16_t* utf16Data, uint32_t utf16Len) - { - uint32_t index = 0; - for (; index + 4 <= utf16Len; index += 4) { - // 4: process the data in chunks of 4 elements to improve speed - // Check if all four characters in the current block are ASCII characters - if (!IsASCIICharacter(utf16Data[index]) || - !IsASCIICharacter(utf16Data[index + 1]) || // 1: the second element of the block - !IsASCIICharacter(utf16Data[index + 2]) || // 2: the third element of the block - !IsASCIICharacter(utf16Data[index + 3])) { - // 3: the fourth element of the block - return false; - } - } - // Check remaining characters if they are ASCII - for (; index < utf16Len; ++index) { - if (!IsASCIICharacter(utf16Data[index])) { - return false; - } - } - return true; - } - +#include +#include - bool BaseString::IsASCIICharacter(uint16_t data) - { - if (data == 0) { +namespace common { +size_t UtfUtils::DebuggerConvertRegionUtf16ToUtf8(const uint16_t* utf16In, uint8_t* utf8Out, size_t utf16Len, + size_t utf8Len, size_t start, bool modify, bool isWriteBuffer) +{ + return utf_helper::DebuggerConvertRegionUtf16ToUtf8(utf16In, utf8Out, utf16Len, utf8Len, start, modify, + isWriteBuffer); +} + +size_t UtfUtils::ConvertRegionUtf16ToLatin1(const uint16_t* utf16In, uint8_t* latin1Out, size_t utf16Len, + size_t latin1Len) +{ + return utf_helper::ConvertRegionUtf16ToLatin1(utf16In, latin1Out, utf16Len, latin1Len); +} + +// To change the hash algorithm of BaseString, please modify BaseString::CalculateConcatHashCode +// and BaseStringHashHelper::ComputeHashForDataPlatform simultaneously!! +template +uint32_t ComputeHashForDataInternal(const T *data, size_t size, uint32_t hashSeed) +{ + if (size <= static_cast(StringHash::MIN_SIZE_FOR_UNROLLING)) { + uint32_t hash = hashSeed; + for (uint32_t i = 0; i < size; i++) { + hash = (hash << static_cast(StringHash::HASH_SHIFT)) - hash + data[i]; + } + return hash; + } + return StringHashHelper::ComputeHashForDataPlatform(data, size, hashSeed); +} + +// To change the hash algorithm of BaseString, please modify BaseString::CalculateConcatHashCode +// and BaseStringHashHelper::ComputeHashForDataPlatform simultaneously!! +template +uint32_t BaseString::ComputeHashForData(const T* data, size_t size, + uint32_t hashSeed) +{ + if (size <= static_cast(StringHash::MIN_SIZE_FOR_UNROLLING)) { + uint32_t hash = hashSeed; + for (uint32_t i = 0; i < size; i++) { + hash = (hash << static_cast(StringHash::HASH_SHIFT)) - hash + data[i]; + } + return hash; + } + return StringHashHelper::ComputeHashForDataPlatform(data, size, hashSeed); +} + +template +uint32_t BaseString::ComputeHashForData(const uint8_t*, size_t, uint32_t); +template +uint32_t BaseString::ComputeHashForData(const uint16_t*, size_t, uint32_t); + +// static +template +uint32_t BaseString::CalculateDataConcatHashCode(const T1* dataFirst, size_t sizeFirst, + const T2* dataSecond, size_t sizeSecond) +{ + uint32_t totalHash = ComputeHashForData(dataFirst, sizeFirst, 0); + totalHash = ComputeHashForData(dataSecond, sizeSecond, totalHash); + return MixHashcode(totalHash, NOT_INTEGER); +} + +template +uint32_t BaseString::CalculateDataConcatHashCode(const uint8_t* dataFirst, size_t sizeFirst, + const uint8_t* dataSecond, size_t sizeSecond); +template +uint32_t BaseString::CalculateDataConcatHashCode(const uint16_t* dataFirst, size_t sizeFirst, + const uint16_t* dataSecond, size_t sizeSecond); +template +uint32_t BaseString::CalculateDataConcatHashCode(const uint8_t* dataFirst, size_t sizeFirst, + const uint16_t* dataSecond, size_t sizeSecond); +template +uint32_t BaseString::CalculateDataConcatHashCode(const uint16_t* dataFirst, size_t sizeFirst, + const uint8_t* dataSecond, size_t sizeSecond); + + +template +bool IsSubStringAtSpan(common::Span& lhsSp, common::Span& rhsSp, uint32_t offset) +{ + size_t rhsSize = rhsSp.size(); + DCHECK_CC(rhsSize + offset <= lhsSp.size()); + for (size_t i = 0; i < rhsSize; ++i) { + auto left = static_cast(lhsSp[offset + static_cast(i)]); + auto right = static_cast(rhsSp[i]); + if (left != right) { return false; } - // \0 is not considered ASCII in Ecma-Modified-UTF8 [only modify '\u0000'] - return data <= UtfUtils::UTF8_1B_MAX; - } - - - /* static */ - template - int32_t BaseString::IndexOf(Span& lhsSp, Span& rhsSp, int32_t pos, int32_t max) - { - DCHECK_CC(rhsSp.size() > 0); - auto first = static_cast(rhsSp[0]); - for (int32_t i = pos; i <= max; i++) { - if (static_cast(lhsSp[i]) != first) { - i++; - while (i <= max && static_cast(lhsSp[i]) != first) { - i++; - } - } - /* Found first character, now look at the rest of rhsSp */ - if (i <= max) { - int j = i + 1; - int end = j + static_cast(rhsSp.size()) - 1; - - for (int k = 1; j < end && static_cast(lhsSp[j]) == static_cast(rhsSp[k]); j++, k++) { - } - if (j == end) { - /* Found whole string. */ - return i; - } - } - } - return -1; - } - - template - int32_t BaseString::IndexOf(Span& lhsSp, Span& rhsSp, int32_t pos, - int32_t max); - template - int32_t BaseString::IndexOf(Span& lhsSp, Span& rhsSp, - int32_t pos, int32_t max); - - template - int32_t BaseString::IndexOf(Span& lhsSp, Span& rhsSp, int32_t pos, - int32_t max); - - template - int32_t BaseString::IndexOf(Span& lhsSp, Span& rhsSp, int32_t pos, - int32_t max); - - - template - int32_t BaseString::LastIndexOf(Span& lhsSp, Span& rhsSp, int32_t pos) - { - int rhsSize = static_cast(rhsSp.size()); - DCHECK_CC(rhsSize > 0); - auto first = rhsSp[0]; - for (int32_t i = pos; i >= 0; i--) { - if (lhsSp[i] != first) { - continue; - } - /* Found first character, now look at the rest of rhsSp */ - int j = 1; - while (j < rhsSize) { - if (rhsSp[j] != lhsSp[i + j]) { - break; - } - j++; - } - if (j == rhsSize) { - return i; - } - } - return -1; - } - - template - int32_t BaseString::LastIndexOf(Span& lhsSp, Span& rhsSp, - int32_t pos); - template - int32_t BaseString::LastIndexOf(Span& lhsSp, Span& rhsSp, - int32_t pos); - template - int32_t BaseString::LastIndexOf(Span& lhsSp, Span& rhsSp, - int32_t pos); - template - int32_t BaseString::LastIndexOf(Span& lhsSp, Span& rhsSp, - int32_t pos); - - - template - int32_t CompareStringSpan(Span& lhsSp, Span& rhsSp, int32_t count) - { - for (int32_t i = 0; i < count; ++i) { - auto left = static_cast(lhsSp[i]); - auto right = static_cast(rhsSp[i]); - if (left != right) { - return left - right; - } - } - return 0; - } - - template - int32_t CompareStringSpan(Span& lhsSp, Span& rhsSp, - int32_t count); - template - int32_t CompareStringSpan(Span& lhsSp, Span& rhsSp, - int32_t count); - template - int32_t CompareStringSpan(Span& lhsSp, Span& rhsSp, - int32_t count); - template - int32_t CompareStringSpan(Span& lhsSp, Span& rhsSp, - int32_t count); - - - template - bool IsSubStringAtSpan(Span& lhsSp, Span& rhsSp, uint32_t offset) - { - int rhsSize = static_cast(rhsSp.size()); - DCHECK_CC(rhsSize + offset <= lhsSp.size()); - for (int i = 0; i < rhsSize; ++i) { - auto left = static_cast(lhsSp[offset + static_cast(i)]); - auto right = static_cast(rhsSp[i]); - if (left != right) { - return false; - } - } - return true; - } - - template - bool IsSubStringAtSpan(Span& lhsSp, Span& rhsSp, - uint32_t offset); - template - bool IsSubStringAtSpan(Span& lhsSp, Span& rhsSp, - uint32_t offset); - template - bool IsSubStringAtSpan(Span& lhsSp, Span& rhsSp, - uint32_t offset); - template - bool IsSubStringAtSpan(Span& lhsSp, Span& rhsSp, - uint32_t offset); - - - std::u16string Utf16ToU16String(const uint16_t* utf16Data, uint32_t dataLen) - { - auto* char16tData = reinterpret_cast(utf16Data); - std::u16string u16str(char16tData, dataLen); - return u16str; - } - - std::u16string Utf8ToU16String(const uint8_t* utf8Data, uint32_t dataLen) - { - auto* charData = reinterpret_cast(utf8Data); - std::string str(charData, dataLen); - std::u16string u16str = std::wstring_convert, char16_t>{}.from_bytes(str); - return u16str; } -} // namespace common + return true; +} + +template +bool IsSubStringAtSpan(common::Span& lhsSp, + common::Span& rhsSp, + uint32_t offset); +template +bool IsSubStringAtSpan(common::Span& lhsSp, + common::Span& rhsSp, + uint32_t offset); +template +bool IsSubStringAtSpan(common::Span& lhsSp, + common::Span& rhsSp, + uint32_t offset); +template +bool IsSubStringAtSpan(common::Span& lhsSp, + common::Span& rhsSp, + uint32_t offset); + + +std::u16string Utf16ToU16String(const uint16_t* utf16Data, uint32_t dataLen) +{ + auto* char16tData = reinterpret_cast(utf16Data); + std::u16string u16str(char16tData, dataLen); + return u16str; +} + +std::u16string Utf8ToU16String(const uint8_t* utf8Data, uint32_t dataLen) +{ + auto* charData = reinterpret_cast(utf8Data); + std::string str(charData, dataLen); + std::u16string u16str = std::wstring_convert, char16_t>{}.from_bytes(str); + return u16str; +} +} // namespace common diff --git a/common_components/objects/base_string_table.cpp b/common_components/objects/base_string_table.cpp index d8d3cc807341c5128fd7543f05bd4b95e3e42bf1..3edad3bdd5c9f19098d9b49a860c62aaa02a62ce 100644 --- a/common_components/objects/base_string_table.cpp +++ b/common_components/objects/base_string_table.cpp @@ -22,7 +22,14 @@ #include "common_components/objects/string_table_internal.h" #include "common_components/taskpool/taskpool.h" #include "common_components/mutator/thread_local.h" -#include "common_interfaces/objects/base_string.h" +#include "common_interfaces/objects/string/base_string.h" +#include "common_interfaces/objects/string/base_string-inl.h" +#include "common_interfaces/objects/string/line_string.h" +#include "common_interfaces/objects/string/line_string-inl.h" +#include "common_interfaces/objects/string/tree_string.h" +#include "common_interfaces/objects/string/tree_string-inl.h" +#include "common_interfaces/objects/string/sliced_string.h" +#include "common_interfaces/objects/string/sliced_string-inl.h" #include "common_interfaces/thread/thread_holder.h" #include "common_interfaces/thread/thread_state_transition.h" #include "heap/heap_allocator.h" @@ -31,10 +38,10 @@ namespace common { template BaseString* BaseStringTableInternal::AllocateLineStringObject(size_t size) { - size = AlignUp(size, ALIGN_OBJECT); + size = AlignmentUp(size, ALIGN_OBJECT); BaseString* str = reinterpret_cast(HeapAllocator::AllocateInOldOrHuge(size, LanguageType::DYNAMIC)); - BaseClass* cls = BaseRuntime::GetInstance()->GetBaseClassRoots().GetBaseClass(CommonType::LINE_STRING); + BaseClass* cls = BaseRuntime::GetInstance()->GetBaseClassRoots().GetBaseClass(ObjectType::LINE_STRING); str->SetFullBaseClassWithoutBarrier(cls); return str; } @@ -44,7 +51,7 @@ BaseString* BaseStringTableInternal::GetOrInternFlattenString( ThreadHolder* holder, const HandleCreator& handleCreator, BaseString* string) { - ASSERT(string->NotTreeString()); + DCHECK_CC(!string->IsTreeString()); if (string->IsInternString()) { return string; } @@ -62,7 +69,7 @@ BaseString* BaseStringTableInternal::GetOrInternFlattenString( ReadOnlyHandle stringHandle = handleCreator(holder, string); BaseString* result = stringTable_.template StoreOrLoad( holder, readBarrier, hashcode, loadResult, stringHandle); - ASSERT(result != nullptr); + DCHECK_CC(result != nullptr); return result; } @@ -72,7 +79,7 @@ BaseString* BaseStringTableInternal::GetOrInternStringFromCompr const ReadOnlyHandle& string, uint32_t offset, uint32_t utf8Len) { - const uint8_t* utf8Data = string->GetDataUtf8() + offset; + const uint8_t* utf8Data = ReadOnlyHandle::Cast(string)->GetDataUtf8() + offset; uint32_t hashcode = BaseString::ComputeHashcodeUtf8(utf8Data, utf8Len, true); auto readBarrier = [](void* obj, size_t offset)-> BaseObject* { return BaseObject::Cast( @@ -83,24 +90,24 @@ BaseString* BaseStringTableInternal::GetOrInternStringFromCompr if (loadResult.value != nullptr) { return loadResult.value; } - auto allocator = [](size_t size, CommonType type)-> BaseString* { - ASSERT(type == CommonType::LINE_STRING); + auto allocator = [](size_t size, ObjectType type)-> BaseString* { + DCHECK_CC(type == ObjectType::LINE_STRING); return AllocateLineStringObject(size); }; BaseString* result = stringTable_.template StoreOrLoad( holder, hashcode, loadResult, [holder, string, offset, utf8Len, hashcode, handleCreator, allocator]() { - BaseString* str = BaseString::CreateFromUtf8CompressedSubString( + BaseString* str = LineString::CreateFromUtf8CompressedSubString( std::move(allocator), string, offset, utf8Len); str->SetMixHashcode(hashcode); - ASSERT(!str->IsInternString()); - ASSERT(str->NotTreeString()); + DCHECK_CC(!str->IsInternString()); + DCHECK_CC(!str->IsTreeString()); // Strings in string table should not be in the young space. ReadOnlyHandle strHandle = handleCreator(holder, str); return strHandle; }, [utf8Len, string, offset](const BaseString* foundString) { - const uint8_t* utf8Data = string->GetDataUtf8() + offset; + const uint8_t* utf8Data = ReadOnlyHandle::Cast(string)->GetDataUtf8() + offset; auto readBarrier = [](void* obj, size_t offset)-> BaseObject* { return BaseObject::Cast( reinterpret_cast(BaseRuntime::ReadBarrier( @@ -108,7 +115,7 @@ BaseString* BaseStringTableInternal::GetOrInternStringFromCompr }; return BaseString::StringIsEqualUint8Data(readBarrier, foundString, utf8Data, utf8Len, true); }); - ASSERT(result != nullptr); + DCHECK_CC(result != nullptr); return result; } @@ -120,17 +127,17 @@ BaseString* BaseStringTableInternal::GetOrInternString(ThreadHo bool canBeCompress) { uint32_t hashcode = BaseString::ComputeHashcodeUtf8(utf8Data, utf8Len, canBeCompress); - auto allocator = [](size_t size, CommonType type)-> BaseString* { - ASSERT(type == CommonType::LINE_STRING); + auto allocator = [](size_t size, ObjectType type)-> BaseString* { + DCHECK_CC(type == ObjectType::LINE_STRING); return AllocateLineStringObject(size); }; BaseString* result = stringTable_.template LoadOrStore( holder, hashcode, [holder, hashcode, utf8Data, utf8Len, canBeCompress, handleCreator, allocator]() { - BaseString* value = BaseString::CreateFromUtf8(std::move(allocator), utf8Data, utf8Len, canBeCompress); + BaseString* value = LineString::CreateFromUtf8(std::move(allocator), utf8Data, utf8Len, canBeCompress); value->SetMixHashcode(hashcode); - ASSERT(!value->IsInternString()); - ASSERT(value->NotTreeString()); + DCHECK_CC(!value->IsInternString()); + DCHECK_CC(!value->IsTreeString()); ReadOnlyHandle stringHandle = handleCreator(holder, value); return stringHandle; }, @@ -143,7 +150,7 @@ BaseString* BaseStringTableInternal::GetOrInternString(ThreadHo return BaseString::StringIsEqualUint8Data(readBarrier, foundString, utf8Data, utf8Len, canBeCompress); }); - ASSERT(result != nullptr); + DCHECK_CC(result != nullptr); return result; } @@ -154,18 +161,18 @@ BaseString* BaseStringTableInternal::GetOrInternString( bool canBeCompress) { uint32_t hashcode = BaseString::ComputeHashcodeUtf16(const_cast(utf16Data), utf16Len); - auto allocator = [](size_t size, CommonType type)-> BaseString* { - ASSERT(type == CommonType::LINE_STRING); + auto allocator = [](size_t size, ObjectType type)-> BaseString* { + DCHECK_CC(type == ObjectType::LINE_STRING); return AllocateLineStringObject(size); }; BaseString* result = stringTable_.template LoadOrStore( holder, hashcode, [holder, utf16Data, utf16Len, canBeCompress, hashcode, handleCreator, allocator]() { - BaseString* value = BaseString::CreateFromUtf16(std::move(allocator), utf16Data, utf16Len, + BaseString* value = LineString::CreateFromUtf16(std::move(allocator), utf16Data, utf16Len, canBeCompress); value->SetMixHashcode(hashcode); - ASSERT(!value->IsInternString()); - ASSERT(value->NotTreeString()); + DCHECK_CC(!value->IsInternString()); + DCHECK_CC(!value->IsTreeString()); // Strings in string table should not be in the young space. ReadOnlyHandle stringHandle = handleCreator(holder, value); return stringHandle; @@ -178,7 +185,7 @@ BaseString* BaseStringTableInternal::GetOrInternString( }; return BaseString::StringsAreEqualUtf16(readBarrier, foundString, utf16Data, utf16Len); }); - ASSERT(result != nullptr); + DCHECK_CC(result != nullptr); return result; } @@ -199,7 +206,7 @@ template > void BaseStringTableInternal::SweepWeakRef(const WeakRefFieldVisitor& visitor, uint32_t rootID, std::vector& waitDeleteEntries) { - ASSERT(rootID >= 0 && rootID < TrieMapConfig::ROOT_SIZE); + DCHECK_CC(rootID >= 0 && rootID < TrieMapConfig::ROOT_SIZE); auto rootNode = stringTable_.root_[rootID].load(std::memory_order_relaxed); if (rootNode == nullptr) { return; diff --git a/common_components/objects/composite_base_class.cpp b/common_components/objects/composite_base_class.cpp index c1d2b8fb9c0ff5bf69441e3b91679791214a61e7..e014bdfb37c84901cbc0392f823640d14b84b71d 100644 --- a/common_components/objects/composite_base_class.cpp +++ b/common_components/objects/composite_base_class.cpp @@ -25,12 +25,12 @@ void BaseClassRoots::InitializeCompositeBaseClass(CompositeBaseClassAllocator &a if (initialized_.exchange(true)) { return; } - CreateCompositeBaseClass(CommonType::LINE_STRING, allocator); - CreateCompositeBaseClass(CommonType::SLICED_STRING, allocator); - CreateCompositeBaseClass(CommonType::TREE_STRING, allocator); + CreateCompositeBaseClass(ObjectType::LINE_STRING, allocator); + CreateCompositeBaseClass(ObjectType::SLICED_STRING, allocator); + CreateCompositeBaseClass(ObjectType::TREE_STRING, allocator); } -void BaseClassRoots::CreateCompositeBaseClass(CommonType type, CompositeBaseClassAllocator& allocator) +void BaseClassRoots::CreateCompositeBaseClass(ObjectType type, CompositeBaseClassAllocator& allocator) { CompositeBaseClass* classObject = allocator(); classObject->class_.ClearBitField(); @@ -40,7 +40,7 @@ void BaseClassRoots::CreateCompositeBaseClass(CommonType type, CompositeBaseClas baseClasses_[index] = &classObject->class_; } -BaseClass* BaseClassRoots::GetBaseClass(CommonType type) const +BaseClass* BaseClassRoots::GetBaseClass(ObjectType type) const { return baseClasses_[TypeToIndex[static_cast(type)]]; } diff --git a/common_components/objects/string_table/hashtriemap-inl.h b/common_components/objects/string_table/hashtriemap-inl.h index d6c89eb4a4c52acb3facef2a189219ab731cb6fa..f995a98e0354e2538fc6ff2054c5a7bc91452a1d 100644 --- a/common_components/objects/string_table/hashtriemap-inl.h +++ b/common_components/objects/string_table/hashtriemap-inl.h @@ -18,7 +18,8 @@ #include "common_components/log/log.h" #include "common_interfaces/objects/readonly_handle.h" -#include "common_interfaces/objects/base_string.h" +#include "common_interfaces/objects/string/base_string.h" +#include "common_interfaces/objects/string/line_string-inl.h" #include "common_components/objects/string_table/hashtriemap.h" #include "common_components/objects/string_table/integer_cache.h" @@ -49,7 +50,7 @@ typename HashTrieMap::Node* HashTrieMap::Load(ReadBarrier&& re } LOG_COMMON(FATAL) << "StringTable: ran out of hash bits while iterating"; - UNREACHABLE(); + UNREACHABLE_CC(); } // LoadOrStore returns the existing value of the key, if it exists. @@ -172,7 +173,7 @@ BaseString* HashTrieMap::LoadOrStore(ThreadHol #ifndef NDEBUG if (!haveInsertPoint) { LOG_COMMON(FATAL) << "StringTable: ran out of hash bits while iterating"; - UNREACHABLE(); + UNREACHABLE_CC(); } #endif // invoke the callback to create str @@ -185,7 +186,7 @@ BaseString* HashTrieMap::LoadOrStore(ThreadHol GetMutex().LockWithThreadState(holder); } - ASSERT(slot != nullptr); + DCHECK_CC(slot != nullptr); node = slot->load(std::memory_order_acquire); if (node == nullptr || node->IsEntry()) { // see is still real, so can continue to insert. @@ -225,7 +226,7 @@ BaseString* HashTrieMap::LoadOrStore(ThreadHol } BaseString* value = *str; - ASSERT(value != nullptr); + DCHECK_CC(value != nullptr); value->SetIsInternString(); IntegerCache::InitIntegerCache(value); Entry* newEntry = new Entry(value); @@ -297,14 +298,14 @@ BaseString* HashTrieMap::LoadOrStoreForJit(Thr #ifndef NDEBUG if (!haveInsertPoint) { LOG_COMMON(FATAL) << "StringTable: ran out of hash bits while iterating"; - UNREACHABLE(); + UNREACHABLE_CC(); } #endif // Jit need to lock the object before creating the object GetMutex().LockWithThreadState(holder); // invoke the callback to create str value = std::invoke(std::forward(loaderCallback)); - ASSERT(slot != nullptr); + DCHECK_CC(slot != nullptr); node = slot->load(std::memory_order_acquire); if (node == nullptr || node->IsEntry()) { // see is still real, so can continue to insert. @@ -337,7 +338,7 @@ BaseString* HashTrieMap::LoadOrStoreForJit(Thr } } - ASSERT(value != nullptr); + DCHECK_CC(value != nullptr); value->SetIsInternString(); IntegerCache::InitIntegerCache(value); Entry* newEntry = new Entry(value); @@ -411,7 +412,7 @@ BaseString* HashTrieMap::StoreOrLoad(ThreadHol #ifndef NDEBUG if (!haveInsertPoint) { LOG_COMMON(FATAL) << "StringTable: ran out of hash bits while iterating"; - UNREACHABLE(); + UNREACHABLE_CC(); } #endif // lock and double-check @@ -448,7 +449,7 @@ BaseString* HashTrieMap::StoreOrLoad(ThreadHol } BaseString* value = *str; - ASSERT(value != nullptr); + DCHECK_CC(value != nullptr); value->SetIsInternString(); IntegerCache::InitIntegerCache(value); Entry* newEntry = new Entry(value); @@ -502,7 +503,7 @@ HashTrieMapLoadResult HashTrieMap::Load(ReadBa } LOG_COMMON(FATAL) << "StringTable: ran out of hash bits while iterating"; - UNREACHABLE(); + UNREACHABLE_CC(); } // Load returns the value of the key stored in the mapping, or HashTrieMapLoadResult for StoreOrLoad @@ -514,7 +515,7 @@ HashTrieMapLoadResult HashTrieMap::Load(ReadBa { uint32_t hash = key; Indirect* current = GetRootAndProcessHash(hash); - const uint8_t* utf8Data = string->GetDataUtf8() + offset; + const uint8_t* utf8Data = ReadOnlyHandle::Cast(string)->GetDataUtf8() + offset; for (uint32_t hashShift = 0; hashShift < TrieMapConfig::TOTAL_HASH_BITS; hashShift += TrieMapConfig::N_CHILDREN_LOG2) { size_t index = (hash >> hashShift) & TrieMapConfig::N_CHILDREN_MASK; @@ -543,7 +544,7 @@ HashTrieMapLoadResult HashTrieMap::Load(ReadBa } LOG_COMMON(FATAL) << "StringTable: ran out of hash bits while iterating"; - UNREACHABLE(); + UNREACHABLE_CC(); } // Based on the loadResult, try the store first @@ -605,7 +606,7 @@ BaseString* HashTrieMap::StoreOrLoad(ThreadHol #ifndef NDEBUG if (!haveInsertPoint) { LOG_COMMON(FATAL) << "StringTable: ran out of hash bits while iterating"; - UNREACHABLE(); + UNREACHABLE_CC(); } #endif // lock and double-check @@ -647,7 +648,7 @@ BaseString* HashTrieMap::StoreOrLoad(ThreadHol } BaseString* value = *str; - ASSERT(value != nullptr); + DCHECK_CC(value != nullptr); value->SetIsInternString(); IntegerCache::InitIntegerCache(value); Entry* newEntry = new Entry(value); @@ -688,7 +689,7 @@ template bool HashTrieMap::CheckValidity(ReadBarrier&& readBarrier, BaseString* value, bool& isValid) { - if (!value->NotTreeString()) { + if (value->IsTreeString()) { isValid = false; return false; } diff --git a/common_components/objects/string_table/hashtriemap.h b/common_components/objects/string_table/hashtriemap.h index 4a51642851c7843e929f2a074fd735bb68194484..e86aa9e3a3207a6bc23197be46cdbb52717c689c 100644 --- a/common_components/objects/string_table/hashtriemap.h +++ b/common_components/objects/string_table/hashtriemap.h @@ -18,8 +18,10 @@ #include "common_components/heap/heap.h" #include "common_components/log/log.h" +#include "common_interfaces/base/common.h" #include "common_interfaces/objects/readonly_handle.h" -#include "common_interfaces/objects/base_string.h" +#include "common_interfaces/objects/string/base_string.h" +#include "common_interfaces/objects/string/base_string-inl.h" namespace panda::ecmascript { class TaggedObject; @@ -172,13 +174,13 @@ struct HashTrieMapLoadResult { inline HashTrieMapEntry* HashTrieMapNode::AsEntry() { - ASSERT(IsEntry() && "HashTrieMap: called entry on non-entry node"); + DCHECK_CC(IsEntry() && "HashTrieMap: called entry on non-entry node"); return static_cast(this); } inline HashTrieMapIndirect* HashTrieMapNode::AsIndirect() { - ASSERT(!IsEntry() && "HashTrieMap: called indirect on entry node"); + DCHECK_CC(!IsEntry() && "HashTrieMap: called indirect on entry node"); return static_cast(this); } @@ -197,7 +199,7 @@ public: { Clear(); }; - + #if ECMASCRIPT_ENABLE_TRACE_STRING_TABLE class StringTableTracer { public: @@ -207,10 +209,10 @@ public: static StringTableTracer tracer; return tracer; } - + NO_COPY_SEMANTIC_CC(StringTableTracer); NO_MOVE_SEMANTIC_CC(StringTableTracer); - + void TraceFindSuccess(uint32_t hashShift) { totalDepth_.fetch_add(hashShift / TrieMapConfig::N_CHILDREN_LOG2 + 1, std::memory_order_relaxed); @@ -219,33 +221,33 @@ public: DumpWithLock(currentSuccess); } } - + void TraceFindFail() { totalFailNum_.fetch_add(1, std::memory_order_relaxed); } - + private: StringTableTracer() = default; - + void DumpWithLock(uint64_t triggerPoint) { std::lock_guard lock(mu_); - + if (triggerPoint >= lastDumpPoint_.load(std::memory_order_relaxed) + DUMP_THRESHOLD) { lastDumpPoint_ = triggerPoint; DumpInfo(); } } - + void DumpInfo() const { uint64_t depth = totalDepth_.load(std::memory_order_relaxed); uint64_t success = totalSuccessNum_.load(std::memory_order_relaxed); uint64_t fail = totalFailNum_.load(std::memory_order_relaxed); - + double avgDepth = (static_cast(depth) / success); - + LOG_COMMON(INFO) << "------------------------------------------------------------" << "---------------------------------------------------------"; LOG_COMMON(INFO) << "StringTableTotalSuccessFindNum: " << success; @@ -254,14 +256,14 @@ public: LOG_COMMON(INFO) << "------------------------------------------------------------" << "---------------------------------------------------------"; } - + std::mutex mu_; std::atomic totalDepth_{0}; std::atomic totalSuccessNum_{0}; std::atomic totalFailNum_{0}; std::atomic lastDumpPoint_{0}; }; - + void TraceFindSuccessDepth(uint32_t hashShift) { StringTableTracer::GetInstance().TraceFindSuccess(hashShift); @@ -294,7 +296,7 @@ public: template BaseString* LoadOrStoreForJit(ThreadHolder* holder, const uint32_t key, LoaderCallback loaderCallback, EqualsCallback equalsCallback); - + static void ProcessHash(uint32_t &hash) { hash >>= TrieMapConfig::ROOT_BIT; @@ -310,7 +312,7 @@ public: } else { Indirect* expected = nullptr; Indirect* newRoot = new Indirect(); - + if (root_[rootID].compare_exchange_strong(expected, newRoot, std::memory_order_release, std::memory_order_acquire)) { return newRoot; @@ -377,7 +379,7 @@ public: // ut used const std::atomic& GetRoot(uint32_t index) const { - ASSERT(index < TrieMapConfig::ROOT_SIZE); + DCHECK_CC(index < TrieMapConfig::ROOT_SIZE); return root_[index]; } @@ -475,8 +477,8 @@ public: hashTrieMap_->DecreaseInuseCount(); } - NO_COPY_SEMANTIC(HashTrieMapInUseScope); - NO_MOVE_SEMANTIC(HashTrieMapInUseScope); + NO_COPY_SEMANTIC_CC(HashTrieMapInUseScope); + NO_MOVE_SEMANTIC_CC(HashTrieMapInUseScope); private: HashTrieMap* hashTrieMap_; diff --git a/common_components/objects/string_table/integer_cache.h b/common_components/objects/string_table/integer_cache.h index 0c875414bb4d9a47488af125ab6e818eef462340..0aaf85255e875d099d7649df82d55125fcb05ed3 100644 --- a/common_components/objects/string_table/integer_cache.h +++ b/common_components/objects/string_table/integer_cache.h @@ -17,7 +17,8 @@ #define COMMON_COMPONENTS_OBJECTS_STRING_TABLE_INTEGER_CACHE_H #include -#include "common_interfaces/objects/base_string.h" +#include "common_interfaces/objects/string/base_string.h" +#include "common_interfaces/objects/string/line_string.h" namespace common { @@ -52,7 +53,7 @@ public: { DCHECK_CC(string->IsUtf8() && string->GetLength() <= MAX_INTEGER_CACHE_SIZE && string->GetLength() > 0 && string->IsInternString()); - IntegerCache* cache = reinterpret_cast(string->GetData()); + IntegerCache* cache = reinterpret_cast(LineString::Cast(string)->GetData()); return cache; } diff --git a/common_components/objects/string_table_internal.h b/common_components/objects/string_table_internal.h index 0834bd1e47f84dcca2b9f3a414fc2cc4139016a2..67edfcde547822ceadf53708b6c82000947d92a4 100644 --- a/common_components/objects/string_table_internal.h +++ b/common_components/objects/string_table_internal.h @@ -71,8 +71,8 @@ public: void CleanUp(); private: - NO_COPY_SEMANTIC(BaseStringTableCleaner); - NO_MOVE_SEMANTIC(BaseStringTableCleaner); + NO_COPY_SEMANTIC_CC(BaseStringTableCleaner); + NO_MOVE_SEMANTIC_CC(BaseStringTableCleaner); static void ProcessSweepWeakRef(IteratorPtr &iter, BaseStringTableCleaner *cleaner, const WeakRefFieldVisitor &visitor); @@ -100,8 +100,8 @@ private: bool Run(uint32_t threadIndex) override; - NO_COPY_SEMANTIC(CMCSweepWeakRefTask); - NO_MOVE_SEMANTIC(CMCSweepWeakRefTask); + NO_COPY_SEMANTIC_CC(CMCSweepWeakRefTask); + NO_MOVE_SEMANTIC_CC(CMCSweepWeakRefTask); private: IteratorPtr iter_; diff --git a/common_components/objects/tests/base_string_table_test.cpp b/common_components/objects/tests/base_string_table_test.cpp index aa165055f1b83685b0faa961d924c2bb8705d48a..1ce5a23bb9fba635c42b62dbdc021785e2d0365d 100644 --- a/common_components/objects/tests/base_string_table_test.cpp +++ b/common_components/objects/tests/base_string_table_test.cpp @@ -17,11 +17,11 @@ #include "common_interfaces/objects/base_string_table.h" #include "common_components/objects/string_table_internal.h" #include "common_interfaces/thread/mutator_base.h" -#include "common_interfaces/objects/base_string.h" +#include "common_interfaces/objects/string/base_string.h" #include "common_interfaces/thread/thread_holder.h" #include "common_interfaces/base_runtime.h" #include "common_interfaces/heap/heap_allocator.h" -#include "common_interfaces/objects/string/base_string-inl2.h" +#include "common_interfaces/objects/string/base_string-inl.h" namespace common { @@ -66,7 +66,7 @@ protected: BaseString* CreateUtf8String(const char* utf8Data, uint32_t length, bool canBeCompress) { - auto allocator = [](size_t size, CommonType type) -> BaseString* { + auto allocator = [](size_t size, ObjectType type) -> BaseString* { void* mem = reinterpret_cast(HeapAllocator::AllocateInOldOrHuge(size, LanguageType::DYNAMIC)); if (mem == nullptr) { return nullptr; @@ -74,7 +74,7 @@ protected: return reinterpret_cast(mem); }; - BaseString* str = BaseString::CreateFromUtf8(allocator, + BaseString* str = LineString::CreateFromUtf8(allocator, reinterpret_cast(utf8Data), length, canBeCompress); if (str == nullptr) { diff --git a/common_components/objects/tests/base_string_test.cpp b/common_components/objects/tests/base_string_test.cpp index 495a30af2373d5ca1364719403757f43fced9725..25d510a7543d3c691080dcd8282f8bbc5f3ac5a2 100755 --- a/common_components/objects/tests/base_string_test.cpp +++ b/common_components/objects/tests/base_string_test.cpp @@ -13,9 +13,10 @@ * limitations under the License. */ -#include "common_interfaces/objects/base_string.h" +#include "common_interfaces/objects/string/base_string.h" #include "common_components/platform/string_hash.h" #include "common_components/tests/test_helper.h" +#include "objects/string/base_string-inl.h" using namespace common; diff --git a/common_components/objects/tests/composite_base_class_test.cpp b/common_components/objects/tests/composite_base_class_test.cpp index d5a1c91b7f19b1f4c39b001150f8cdc4a4e6a2b7..370d23065d5c88e5de9480e20d3f22479f95cdfd 100644 --- a/common_components/objects/tests/composite_base_class_test.cpp +++ b/common_components/objects/tests/composite_base_class_test.cpp @@ -29,7 +29,7 @@ protected: void* memory = ::operator new(sizeof(uint64_t) * 16); auto* baseClass = reinterpret_cast(memory); - baseClass->SetObjectType(CommonType::LINE_STRING); + baseClass->SetObjectType(ObjectType::LINE_STRING); baseClass->ClearBitField(); return reinterpret_cast(baseClass); @@ -68,9 +68,9 @@ HWTEST_F_L0(CompositeBaseClassTest, CreateAndGetType) roots_->InitializeCompositeBaseClass(allocator); - auto* baseClass = roots_->GetBaseClass(CommonType::LINE_STRING); + auto* baseClass = roots_->GetBaseClass(ObjectType::LINE_STRING); ASSERT_NE(baseClass, nullptr); - EXPECT_EQ(baseClass->GetObjectType(), CommonType::LINE_STRING); + EXPECT_EQ(baseClass->GetObjectType(), ObjectType::LINE_STRING); } HWTEST_F_L0(CompositeBaseClassTest, GetBaseClassReturnsCorrectType) @@ -81,17 +81,17 @@ HWTEST_F_L0(CompositeBaseClassTest, GetBaseClassReturnsCorrectType) roots_->InitializeCompositeBaseClass(allocator); - auto* lineString = roots_->GetBaseClass(CommonType::LINE_STRING); - auto* slicedString = roots_->GetBaseClass(CommonType::SLICED_STRING); - auto* treeString = roots_->GetBaseClass(CommonType::TREE_STRING); + auto* lineString = roots_->GetBaseClass(ObjectType::LINE_STRING); + auto* slicedString = roots_->GetBaseClass(ObjectType::SLICED_STRING); + auto* treeString = roots_->GetBaseClass(ObjectType::TREE_STRING); ASSERT_NE(lineString, nullptr); ASSERT_NE(slicedString, nullptr); ASSERT_NE(treeString, nullptr); - EXPECT_EQ(lineString->GetObjectType(), CommonType::LINE_STRING); - EXPECT_EQ(slicedString->GetObjectType(), CommonType::SLICED_STRING); - EXPECT_EQ(treeString->GetObjectType(), CommonType::TREE_STRING); + EXPECT_EQ(lineString->GetObjectType(), ObjectType::LINE_STRING); + EXPECT_EQ(slicedString->GetObjectType(), ObjectType::SLICED_STRING); + EXPECT_EQ(treeString->GetObjectType(), ObjectType::TREE_STRING); } HWTEST_F_L0(CompositeBaseClassTest, IterateCompositeBaseClass) diff --git a/common_components/serialize/tests/serialize_utils_test.cpp b/common_components/serialize/tests/serialize_utils_test.cpp index 3336be0feddbd1685f38f4b51cf3321b51aa1ff5..836bec5d45d8b5c04253b0e26c603d3dcf9313cd 100644 --- a/common_components/serialize/tests/serialize_utils_test.cpp +++ b/common_components/serialize/tests/serialize_utils_test.cpp @@ -26,12 +26,12 @@ class SerializeUtilsTest : public common::test::BaseTestWithScope { protected: static void SetUpTestCase() { - BaseRuntime::GetInstance()->Init(); + BaseRuntime::GetInstance()->InitFromDynamic(); } static void TearDownTestCase() { - BaseRuntime::GetInstance()->Fini(); + BaseRuntime::GetInstance()->FiniFromDynamic(); } void SetUp() override { diff --git a/common_components/tests/test_hooks.cpp b/common_components/tests/test_hooks.cpp index bfda438f766e7e2c807ec9e95f1cf84c0b7c7a57..4e960d79bad4d65f45ffcf43b6bcd0b4f3e16590 100755 --- a/common_components/tests/test_hooks.cpp +++ b/common_components/tests/test_hooks.cpp @@ -42,4 +42,8 @@ bool IsMachineCodeObject(uintptr_t objPtr) { return false; } +void CheckAndInitBaseRuntime(const RuntimeParam ¶m) {} +void CheckAndFiniBaseRuntime() {} +void RemoveXRefFromDynamicRoots() {} +void AddXRefToDynamicRoots() {} } // namespace common diff --git a/common_components/thread/tests/thread_holder_test.cpp b/common_components/thread/tests/thread_holder_test.cpp index b25e88e3714c424c76a4e37aa8fde37d404d83f3..474adea7f44d6255a49767e9d358120484793f9b 100755 --- a/common_components/thread/tests/thread_holder_test.cpp +++ b/common_components/thread/tests/thread_holder_test.cpp @@ -40,12 +40,12 @@ class ThreadHolderTest : public BaseTestWithScope { protected: static void SetUpTestCase() { - BaseRuntime::GetInstance()->Init(); + BaseRuntime::GetInstance()->InitFromDynamic(); } static void TearDownTestCase() { - BaseRuntime::GetInstance()->Fini(); + BaseRuntime::GetInstance()->FiniFromDynamic(); } void SetUp() override {} diff --git a/common_components/thread/thread_holder.cpp b/common_components/thread/thread_holder.cpp index 6d4e89b7326fbea1eb18f57337d39393b61a4a3d..6fe187473b53beb92c24e09d35483d9ef7226837 100755 --- a/common_components/thread/thread_holder.cpp +++ b/common_components/thread/thread_holder.cpp @@ -23,6 +23,38 @@ #include "common_interfaces/thread/thread_holder_manager.h" #include "common_interfaces/thread/thread_state_transition.h" +#ifdef PANDA_JS_ETS_HYBRID_MODE +namespace common { +InterOpCoroutineToNativeHookFunc interOpCoroutineToNativeHook = nullptr; +InterOpCoroutineToRunningHookFunc interOpCoroutineToRunningHook = nullptr; + +bool InterOpCoroutineToNative(ThreadHolder *current) +{ + if (interOpCoroutineToNativeHook == nullptr) { + return false; + } + return interOpCoroutineToNativeHook(current); +} + +bool InterOpCoroutineToRunning(ThreadHolder *current) +{ + if (interOpCoroutineToRunningHook == nullptr) { + return false; + } + return interOpCoroutineToRunningHook(current); +} + +void RegisterInterOpCoroutineToNativeHook(InterOpCoroutineToNativeHookFunc func) +{ + interOpCoroutineToNativeHook = func; +} +void RegisterInterOpCoroutineToRunningHook(InterOpCoroutineToRunningHookFunc func) +{ + interOpCoroutineToRunningHook = func; +} +} +#endif + namespace common { thread_local ThreadHolder *currentThreadHolder = nullptr; @@ -95,11 +127,10 @@ void ThreadHolder::UnregisterJSThread(JSThread *jsThread) void ThreadHolder::RegisterCoroutine(Coroutine *coroutine) { - DCHECK_CC(!IsInRunningState()); - TransferToRunning(); + // Expect in Native when calling this func + ThreadManagedScope scope(this); DCHECK_CC(coroutines_.find(coroutine) == coroutines_.end()); coroutines_.insert(coroutine); - TransferToNative(); } void ThreadHolder::UnregisterCoroutine(Coroutine *coroutine) diff --git a/compiler_service/include/aot_args_handler.h b/compiler_service/include/aot_args_handler.h index 3c91928a1e499ac1f7675b869deb537414f3ef4f..f0b86bbc2225029be9ca5ea788867bfe2949c352 100644 --- a/compiler_service/include/aot_args_handler.h +++ b/compiler_service/include/aot_args_handler.h @@ -107,6 +107,10 @@ public: bool ParseBootPandaFiles(std::string &bootfiles); std::string ParseLocation(std::string &anfilePath); + + bool ParseProfilePath(std::string &pkgInfo, std::string &profilePath); + + bool ParseProfileUse(HapArgs &hapArgs, std::string &pkgInfo); }; class StaticFrameworkAOTArgsParser final : public StaticAOTArgsParser { diff --git a/compiler_service/include/aot_compiler_constants.h b/compiler_service/include/aot_compiler_constants.h index 78e7795d7a5dd7c19b1f0130468afd468c3d67d9..2c0f616168aab02057d56c322492c8336a1d523f 100644 --- a/compiler_service/include/aot_compiler_constants.h +++ b/compiler_service/include/aot_compiler_constants.h @@ -49,6 +49,7 @@ constexpr const char* BOOLEAN_FALSE = "0"; namespace Symbols { constexpr const char* PREFIX = "--"; constexpr const char* EQ = "="; +constexpr const char* COLON = ":"; } // namespace Symbols /** diff --git a/compiler_service/src/aot_args_handler.cpp b/compiler_service/src/aot_args_handler.cpp index ae35d8d62113564e0d164f5b85eacc81e3343bda..d077cd9055a119870d8e2b1e4e74a01e16a21426 100644 --- a/compiler_service/src/aot_args_handler.cpp +++ b/compiler_service/src/aot_args_handler.cpp @@ -31,11 +31,16 @@ namespace OHOS::ArkCompiler { const std::string AOT_FILE = "aot-file"; +const std::string COMPILER_MODE = "target-compiler-mode"; +const std::string PARTIAL = "partial"; +const std::string COMPILER_PKG_INFO = "compiler-pkg-info"; +const std::string PATH = "path"; const std::string STATIC_BOOT_PANDA_FILES = "boot-panda-files"; const std::string STATIC_PAOC_PANDA_FILES = "paoc-panda-files"; const std::string STATIC_PAOC_LOCATION = "paoc-location"; const std::string STATIC_PAOC_OUTPUT = "paoc-output"; +const std::string STATIC_PAOC_USE_PROFILE = "paoc-use-profile"; const std::string STATIC_BOOT_PATH = "/system/framework/bootpath.json"; const std::string ARKTS_DYNAMIC = "dynamic"; @@ -246,6 +251,8 @@ int32_t StaticAOTArgsParser::Parse(const std::unordered_map() + "/profile.ap"; + return true; +} + +bool StaticAOTArgsParser::ParseProfileUse(HapArgs &hapArgs, std::string &pkgInfo) +{ + std::string profilePath; + bool parseRet = ParseProfilePath(pkgInfo, profilePath); + if (!parseRet) { + LOG_SA(ERROR) << "parse profile path failed in partial mode"; + return false; + } + std::string pathArg = PATH + Symbols::EQ + profilePath; + hapArgs.argVector.emplace_back(Symbols::PREFIX + STATIC_PAOC_USE_PROFILE + Symbols::COLON + pathArg); + return true; +} + std::optional> AOTArgsParserFactory::GetParser( const std::unordered_map &argsMap, bool isEnableStaticCompiler) { diff --git a/ecmascript/base/json_helper.cpp b/ecmascript/base/json_helper.cpp index 42e809eda3988d12751593ad013cb62161afca90..4722187827d16dcb5c05c6d9fc17f2658fbf9a5e 100644 --- a/ecmascript/base/json_helper.cpp +++ b/ecmascript/base/json_helper.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023-2024 Huawei Device Co., Ltd. + * Copyright (c) 2023-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -15,6 +15,7 @@ #include "ecmascript/base/json_helper.h" #include "common_components/base/utf_helper.h" +#include "libpandabase/utils/span.h" namespace panda::ecmascript::base { @@ -68,7 +69,7 @@ bool DoNotEscape(uint16_t c) (c >= 0x23 && c != 0x5C && (c < 0xD800 || c > 0xDFFF)); } -bool JsonHelper::IsFastValueToQuotedString(const Span &sp) +bool JsonHelper::IsFastValueToQuotedString(const common::Span &sp) { for (const auto utf8Ch : sp) { if (!DoNotEscape(utf8Ch)) { @@ -105,7 +106,8 @@ bool JsonHelper::IsFastValueToQuotedString(const CString& str) #endif #if ENABLE_NEXT_OPTIMIZATION -void JsonHelper::AppendQuotedValueToC16String(const Span &sp, uint32_t &index, C16String &output) +void JsonHelper::AppendQuotedValueToC16String(const common::Span& sp, uint32_t& index, + C16String& output) { auto ch = sp[index]; if (common::utf_helper::IsUTF16Surrogate(ch)) { @@ -128,7 +130,7 @@ void JsonHelper::AppendQuotedValueToC16String(const Span &sp, ui } template -void JsonHelper::AppendValueToQuotedString(const Span &sp, DstType &output) +void JsonHelper::AppendValueToQuotedString(const common::Span &sp, DstType &output) { static_assert(sizeof(typename DstType::value_type) >= sizeof(SrcType)); AppendString(output, "\""); @@ -154,11 +156,11 @@ void JsonHelper::AppendValueToQuotedString(const Span &sp, DstTyp AppendString(output, "\""); } template void JsonHelper::AppendValueToQuotedString( - const Span &sp, CString &output); + const common::Span &sp, CString &output); template void JsonHelper::AppendValueToQuotedString( - const Span &sp, C16String &output); + const common::Span &sp, C16String &output); template void JsonHelper::AppendValueToQuotedString( - const Span &sp, C16String &output); + const common::Span &sp, C16String &output); #else void JsonHelper::AppendValueToQuotedString(const CString& str, CString& output) diff --git a/ecmascript/base/json_helper.h b/ecmascript/base/json_helper.h index d860523de903e8d157efc5482087bad58c9c5882..188d22b434e14535864fe5588405a572c5bb9253 100644 --- a/ecmascript/base/json_helper.h +++ b/ecmascript/base/json_helper.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Huawei Device Co., Ltd. + * Copyright (c) 2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -19,7 +19,7 @@ #include "ecmascript/js_handle.h" #include "ecmascript/mem/c_string.h" #include "ecmascript/property_attributes.h" -#include "libpandabase/utils/span.h" +#include "common_interfaces/objects/utils/span.h" namespace panda::ecmascript::base { constexpr int HEX_DIGIT_MASK = 0xF; @@ -84,7 +84,7 @@ public: } #if ENABLE_NEXT_OPTIMIZATION - static bool IsFastValueToQuotedString(const Span &sp); + static bool IsFastValueToQuotedString(const common::Span &sp); #else static bool IsFastValueToQuotedString(const CString &str); #endif @@ -93,9 +93,10 @@ public: // Control characters code units are replaced with escape sequences \uHHHH, or with the shorter forms, // \b (BACKSPACE), \f (FORM FEED), \n (LINE FEED), \r (CARRIAGE RETURN), \t (CHARACTER TABULATION). #if ENABLE_NEXT_OPTIMIZATION - static void AppendQuotedValueToC16String(const Span &sp, uint32_t &index, C16String &output); + static void AppendQuotedValueToC16String(const common::Span &sp, uint32_t &index, + C16String &output); template - static void AppendValueToQuotedString(const Span &sp, DstType &output); + static void AppendValueToQuotedString(const common::Span &sp, DstType &output); #else static void AppendValueToQuotedString(const CString& str, CString& output); #endif diff --git a/ecmascript/base/json_parser.cpp b/ecmascript/base/json_parser.cpp index 185105f423c98b3f1c8514ea3958891ad7f70302..6bde7f667e85ed946ec39b44ea1bcbc7e026f977 100644 --- a/ecmascript/base/json_parser.cpp +++ b/ecmascript/base/json_parser.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2024 Huawei Device Co., Ltd. + * Copyright (c) 2021-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -16,6 +16,7 @@ #include "ecmascript/interpreter/interpreter.h" #include "ecmascript/base/json_parser.h" #include "ecmascript/linked_hash_table.h" +#include "ecmascript/ecma_string-inl.h" #include "ecmascript/ecma_string_table.h" #include "ecmascript/platform/json_platform_helper.h" diff --git a/ecmascript/base/number_helper.cpp b/ecmascript/base/number_helper.cpp index 2e3a331f18344e6981309c4cd4f8e91b07950518..2963e320f552594fb8b4f6b082f32fbc5aab4a45 100644 --- a/ecmascript/base/number_helper.cpp +++ b/ecmascript/base/number_helper.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2024 Huawei Device Co., Ltd. + * Copyright (c) 2021-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -571,7 +571,7 @@ JSTaggedValue NumberHelper::StringToNumber(JSThread *thread, EcmaString *string, } } CVector buf; - Span str = EcmaStringAccessor(string).ToUtf8Span(thread, buf); + common::Span str = EcmaStringAccessor(string).ToUtf8Span(thread, buf); JSTaggedValue result = NumberHelper::StringToDoubleWithRadix(str.begin(), str.end(), radix, &negative); if (result.GetNumber() == 0 && negative == true) { @@ -1171,7 +1171,7 @@ JSTaggedValue NumberHelper::StringToBigInt(JSThread *thread, JSHandle buf; - Span str = EcmaStringAccessor(strObj).ToUtf8Span(thread, buf); + common::Span str = EcmaStringAccessor(strObj).ToUtf8Span(thread, buf); auto p = const_cast(str.begin()); auto end = str.end(); diff --git a/ecmascript/base/string_helper.h b/ecmascript/base/string_helper.h index e029fe18b10cd5f5ad0a3abe456cc80476b32e0b..254330a5c23c76a688cfe8150f43c9e147750796 100644 --- a/ecmascript/base/string_helper.h +++ b/ecmascript/base/string_helper.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2024 Huawei Device Co., Ltd. + * Copyright (c) 2021-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -24,12 +24,13 @@ #include #include +#include "securec.h" #include "common_components/base/utf_helper.h" +#include "common_interfaces/objects/utils/span.h" #include "ecmascript/mem/c_containers.h" #include "ecmascript/mem/c_string.h" #include "libpandabase/utils/span.h" -#include "securec.h" #include "unicode/unistr.h" namespace panda::ecmascript::base { @@ -367,7 +368,7 @@ public: } template - static inline uint32_t GetStart(Span &data, uint32_t length) + static inline uint32_t GetStart(common::Span &data, uint32_t length) { uint32_t start = 0; while (start < length && IsNonspace(data[start])) { @@ -377,7 +378,7 @@ public: } template - static inline int32_t GetEnd(Span &data, int32_t start, uint32_t length) + static inline int32_t GetEnd(common::Span &data, int32_t start, uint32_t length) { if (length == 0U) { return 0; diff --git a/ecmascript/base/tests/json_helper_test.cpp b/ecmascript/base/tests/json_helper_test.cpp index 2364d6e62db475746a784ec939d6217295618541..e6ca461eca124cfdf8435139ce4467607ac83bcf 100644 --- a/ecmascript/base/tests/json_helper_test.cpp +++ b/ecmascript/base/tests/json_helper_test.cpp @@ -32,9 +32,9 @@ class JsonHelperTest : public BaseTestWithScope { */ HWTEST_F_L0(JsonHelperTest, IsFastValueToQuotedString_001) { - Span sp1(reinterpret_cast("Hello World"), 11); - Span sp2(reinterpret_cast("0123456789"), 10); - Span sp3(reinterpret_cast("!#$%&'()*+,-./:;=?@[]^_`{|}~"), 28); + common::Span sp1(reinterpret_cast("Hello World"), 11); + common::Span sp2(reinterpret_cast("0123456789"), 10); + common::Span sp3(reinterpret_cast("!#$%&'()*+,-./:;=?@[]^_`{|}~"), 28); EXPECT_TRUE(JsonHelper::IsFastValueToQuotedString(sp1)); EXPECT_TRUE(JsonHelper::IsFastValueToQuotedString(sp2)); EXPECT_TRUE(JsonHelper::IsFastValueToQuotedString(sp3)); @@ -48,13 +48,13 @@ HWTEST_F_L0(JsonHelperTest, IsFastValueToQuotedString_001) */ HWTEST_F_L0(JsonHelperTest, IsFastValueToQuotedString_002) { - Span sp1(reinterpret_cast("\""), 1); - Span sp2(reinterpret_cast("\\"), 1); - Span sp3(reinterpret_cast("\b"), 1); - Span sp4(reinterpret_cast("\f"), 1); - Span sp5(reinterpret_cast("\n"), 1); - Span sp6(reinterpret_cast("\r"), 1); - Span sp7(reinterpret_cast("\t"), 1); + common::Span sp1(reinterpret_cast("\""), 1); + common::Span sp2(reinterpret_cast("\\"), 1); + common::Span sp3(reinterpret_cast("\b"), 1); + common::Span sp4(reinterpret_cast("\f"), 1); + common::Span sp5(reinterpret_cast("\n"), 1); + common::Span sp6(reinterpret_cast("\r"), 1); + common::Span sp7(reinterpret_cast("\t"), 1); EXPECT_FALSE(JsonHelper::IsFastValueToQuotedString(sp1)); EXPECT_FALSE(JsonHelper::IsFastValueToQuotedString(sp2)); EXPECT_FALSE(JsonHelper::IsFastValueToQuotedString(sp3)); @@ -66,7 +66,7 @@ HWTEST_F_L0(JsonHelperTest, IsFastValueToQuotedString_002) for (uint8_t c = 0; c < 32; c++) { EXPECT_FALSE(JsonHelper::IsFastValueToQuotedString( - Span(reinterpret_cast(&c), 1))); + common::Span(reinterpret_cast(&c), 1))); } } @@ -78,9 +78,9 @@ HWTEST_F_L0(JsonHelperTest, IsFastValueToQuotedString_002) */ HWTEST_F_L0(JsonHelperTest, IsFastValueToQuotedString_003) { - Span sp1(reinterpret_cast("Hello\nWorld"), 11); - Span sp2(reinterpret_cast("Test\"Quote"), 10); - Span sp3(reinterpret_cast("Test\\BackSlash"), 14); + common::Span sp1(reinterpret_cast("Hello\nWorld"), 11); + common::Span sp2(reinterpret_cast("Test\"Quote"), 10); + common::Span sp3(reinterpret_cast("Test\\BackSlash"), 14); EXPECT_FALSE(JsonHelper::IsFastValueToQuotedString(sp1)); EXPECT_FALSE(JsonHelper::IsFastValueToQuotedString(sp2)); diff --git a/ecmascript/base/tests/number_helper_test.cpp b/ecmascript/base/tests/number_helper_test.cpp index 88d5c3747178dbe3c7063b6f6934aeed427b1753..b6d8bd210f0db58c1593f1bfa582ffd2e2f88f45 100644 --- a/ecmascript/base/tests/number_helper_test.cpp +++ b/ecmascript/base/tests/number_helper_test.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -572,7 +572,7 @@ HWTEST_F_L0(NumberHelperTest, StringToDoubleWithRadix) { ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); int radix; - Span sp; + common::Span sp; CVector buf; JSHandle resultStr; diff --git a/ecmascript/builtins/builtins_number.cpp b/ecmascript/builtins/builtins_number.cpp index 99f9b6845dc4a73d8f19cde8e60c7914436c190f..0540fe09e7bb4c84bc3bb91a9bf686bb4eeee095 100644 --- a/ecmascript/builtins/builtins_number.cpp +++ b/ecmascript/builtins/builtins_number.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2024 Huawei Device Co., Ltd. + * Copyright (c) 2021-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -165,7 +165,7 @@ JSTaggedValue BuiltinsNumber::ParseFloat(EcmaRuntimeCallInfo *argv) // 2. ReturnIfAbrupt(inputString). RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); CVector buf; - Span str = EcmaStringAccessor(numberString).ToUtf8Span(thread, buf); + common::Span str = EcmaStringAccessor(numberString).ToUtf8Span(thread, buf); // 4. If neither trimmedString nor any prefix of trimmedString satisfies the syntax of a StrDecimalLiteral // (see 7.1.3.1), return NaN. if (NumberHelper::IsEmptyString(str.begin(), str.end())) { diff --git a/ecmascript/builtins/builtins_promise_job.cpp b/ecmascript/builtins/builtins_promise_job.cpp index f2826a9fbba0e876d40a40c46d85c413b4d3c28c..b1048ba39a6b81245082031179aace2236bb3fad 100644 --- a/ecmascript/builtins/builtins_promise_job.cpp +++ b/ecmascript/builtins/builtins_promise_job.cpp @@ -313,6 +313,7 @@ JSTaggedValue BuiltinsPromiseJob::HandleModuleException(JSThread *thread, JSHand JSHandle(resolve), undefined, undefined, 1); RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, CatchException(thread, reject)); + ASSERT(info != nullptr); info->SetCallArg(exportObject.GetTaggedValue()); return JSFunction::Call(info); } diff --git a/ecmascript/builtins/tests/builtins_number_test.cpp b/ecmascript/builtins/tests/builtins_number_test.cpp index 25ce0ce010d12c4e45d2bf43f2d0f3cd874803b0..340bf9e63edc452de61f2c4ff86c2de6cfeac5e4 100644 --- a/ecmascript/builtins/tests/builtins_number_test.cpp +++ b/ecmascript/builtins/tests/builtins_number_test.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2021-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -461,7 +461,7 @@ HWTEST_F_L0(BuiltinsNumberTest, parseInt) HWTEST_F_L0(BuiltinsNumberTest, StringToDoubleFlags) { JSHandle str; - Span sp; + common::Span sp; CVector buf; // flags of IGNORE_TRAILING @@ -543,7 +543,7 @@ HWTEST_F_L0(BuiltinsNumberTest, StringToDoubleFlags) HWTEST_F_L0(BuiltinsNumberTest, StringToDoubleRadix) { JSHandle str; - Span sp; + common::Span sp; CVector buf; int radix; diff --git a/ecmascript/checkpoint/thread_state_transition.h b/ecmascript/checkpoint/thread_state_transition.h index f0cfcebc8bdc3e2c3d53692d24e5b7314d7cee24..57e45865bcf9405336761fb845e71c5fae0e8922 100644 --- a/ecmascript/checkpoint/thread_state_transition.h +++ b/ecmascript/checkpoint/thread_state_transition.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 Huawei Device Co., Ltd. + * Copyright (c) 2024-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -66,6 +66,11 @@ public: } } else { isEnbaleCMCGC_ = true; +#ifdef PANDA_JS_ETS_HYBRID_MODE + // This is a temporary impl to adapt interop to cmc, because some interop call napi + // without transfering to NATIVE + extraCoroutineSwitchedForInterop_ = InterOpCoroutineToNative(self_->GetThreadHolder()); +#endif if constexpr (newState == ThreadState::RUNNING) { hasSwitchState_ = self_->GetThreadHolder()->TransferToRunningIfInNative(); } else { @@ -99,6 +104,11 @@ public: } } } +#if defined(PANDA_JS_ETS_HYBRID_MODE) + if (isEnbaleCMCGC_ && extraCoroutineSwitchedForInterop_) { + InterOpCoroutineToRunning(self_->GetThreadHolder()); + } +#endif } private: @@ -106,6 +116,7 @@ private: ThreadState oldState_; uint32_t isEnbaleCMCGC_ {0}; uint32_t hasSwitchState_ {0}; + [[maybe_unused]] bool extraCoroutineSwitchedForInterop_ {false}; NO_COPY_SEMANTIC(ThreadStateTransitionScope); }; diff --git a/ecmascript/compiler/BUILD.gn b/ecmascript/compiler/BUILD.gn index aea743766b772e7796002ae1c422ecb656474099..21d0399f54d89298d29cb9477f0080266be4e7a7 100644 --- a/ecmascript/compiler/BUILD.gn +++ b/ecmascript/compiler/BUILD.gn @@ -422,11 +422,6 @@ ohos_executable("ark_stub_compiler") { ] deps += [ "$js_root:libcommon_components_set" ] - if (ets_runtime_enable_cmc_gc) { - if (ark_hybrid) { - deps += [ "$ark_root/static_core/runtime:libarkruntime_set_static" ] - } - } external_deps = [ "zlib:libz" ] external_deps += hiviewdfx_ext_deps @@ -500,12 +495,6 @@ ohos_executable("ark_aot_compiler") { ] } - if (ets_runtime_enable_cmc_gc) { - if (ark_hybrid) { - deps += [ "$ark_root/static_core/runtime:libarkruntime_set_static" ] - } - } - external_deps = [ "zlib:libz" ] if (!is_arkui_x) { external_deps += [ @@ -623,6 +612,8 @@ action("gen_stub_file") { "/${icu_subsystem_name}/${icu_part_name}:" + rebase_path(root_out_dir_with_host_toolchain) + "/thirdparty/zlib:" + rebase_path(root_out_dir_with_host_toolchain) + + "/hmosbundlemanager/zlib_override:" + + rebase_path(root_out_dir_with_host_toolchain) + "/resourceschedule/frame_aware_sched:" + rebase_path(root_out_dir_with_host_toolchain) + "/hiviewdfx/hilog:" + rebase_path(root_out_dir_with_host_toolchain) + diff --git a/ecmascript/compiler/builtins/builtins_string_stub_builder.cpp b/ecmascript/compiler/builtins/builtins_string_stub_builder.cpp index aa143b9696446e34f96949d7e198fea23b8b24db..911f2428b0aa665dadbd7a42c9b15d90bb8f7d4d 100644 --- a/ecmascript/compiler/builtins/builtins_string_stub_builder.cpp +++ b/ecmascript/compiler/builtins/builtins_string_stub_builder.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Huawei Device Co., Ltd. + * Copyright (c) 2022-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -2257,8 +2257,7 @@ GateRef BuiltinsStringStubBuilder::StringAdd(GateRef glue, GateRef leftString, G builder_.Int32(SlicedString::MIN_SLICED_STRING_LENGTH)), &slowPath, &stringConcatOpt); builder_.Bind(&stringConcatOpt); { - GateRef backStoreLength = - builder_.Int32Mul(newLength, builder_.Int32(LineString::INIT_LENGTH_TIMES)); + GateRef backStoreLength = builder_.Int32Mul(newLength, builder_.Int32(INIT_LENGTH_TIMES)); GateRef leftIsUtf8 = builder_.IsUtf8String(left); GateRef rightIsUtf8 = builder_.IsUtf8String(right); GateRef canBeCompressed = builder_.BitAnd(leftIsUtf8, rightIsUtf8); diff --git a/ecmascript/compiler/builtins/builtins_string_stub_builder.h b/ecmascript/compiler/builtins/builtins_string_stub_builder.h index 5e4eae67416f57106b2419b2b04b088bc7773323..6f62f1cb6cbb3aa75565494262dcbd0a27a1806a 100644 --- a/ecmascript/compiler/builtins/builtins_string_stub_builder.h +++ b/ecmascript/compiler/builtins/builtins_string_stub_builder.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022-2024 Huawei Device Co., Ltd. + * Copyright (c) 2022-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -98,6 +98,7 @@ private: GateRef GetSingleCharCodeFromSlicedString(GateRef glue, GateRef str, GateRef index); void CheckParamsAndGetPosition(GateRef glue, GateRef thisValue, GateRef numArgs, Variable* pos, Label *exit, Label *slowPath, Label *posIsValid); + static constexpr uint32_t INIT_LENGTH_TIMES = 4; }; class FlatStringStubBuilder : public StubBuilder { diff --git a/ecmascript/compiler/circuit_builder.cpp b/ecmascript/compiler/circuit_builder.cpp index 5a6c5d2ff719a7ed8cd981c57e70c08eb0dda370..cb8a0568b9d76283d86a290e5f85d02877f03c43 100644 --- a/ecmascript/compiler/circuit_builder.cpp +++ b/ecmascript/compiler/circuit_builder.cpp @@ -707,8 +707,8 @@ GateRef CircuitBuilder::IsCompositeHClass(GateRef hClass) { GateRef objectType = GetObjectType(hClass); return BitAnd( - Int32LessThanOrEqual(objectType, Int32(static_cast(common::CommonType::LAST_OBJECT_TYPE))), - Int32GreaterThanOrEqual(objectType, Int32(static_cast(common::CommonType::FIRST_OBJECT_TYPE)))); + Int32LessThanOrEqual(objectType, Int32(static_cast(common::ObjectType::LAST_OBJECT_TYPE))), + Int32GreaterThanOrEqual(objectType, Int32(static_cast(common::ObjectType::FIRST_OBJECT_TYPE)))); } void CircuitBuilder::CheckHClassFieldInvalidAccess([[maybe_unused]]GateRef glue, [[maybe_unused]] GateRef hClass) diff --git a/ecmascript/compiler/interpreter_stub.cpp b/ecmascript/compiler/interpreter_stub.cpp index b1b86370db8b365364151399acc73d3130e97e46..194e2008f0b40a7cfcab0229ef24e91e11e8e933 100644 --- a/ecmascript/compiler/interpreter_stub.cpp +++ b/ecmascript/compiler/interpreter_stub.cpp @@ -5222,7 +5222,8 @@ DECLARE_ASM_HANDLER(HandleDefinefuncImm16Id16Imm8) } Bind(&isNotSourceTextModule); SetModuleToFunction(glue, result, smodule, MemoryAttribute::DefaultWithShareBarrier()); - GateRef emptySFunctionEnvHandle = GetGlobalConstantValue(VariableType::JS_ANY(), glue, ConstantIndex::EMPTY_SFUNCTION_ENV_INDEX); + GateRef emptySFunctionEnvHandle = GetGlobalConstantValue(VariableType::JS_ANY(), + glue, ConstantIndex::EMPTY_SFUNCTION_ENV_INDEX); SetLexicalEnvToFunction(glue, result, emptySFunctionEnvHandle); Jump(&afterSendableFunc); } diff --git a/ecmascript/compiler/mcr_circuit_builder.h b/ecmascript/compiler/mcr_circuit_builder.h index 8b6cf64f0aa4dffc6983ed2f79bdfd0466519cb4..e9f5d54a40e99e70da72c9f66b56e148985f3673 100644 --- a/ecmascript/compiler/mcr_circuit_builder.h +++ b/ecmascript/compiler/mcr_circuit_builder.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Huawei Device Co., Ltd. + * Copyright (c) 2023-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -820,13 +820,13 @@ GateRef CircuitBuilder::TreeStringIsFlat(GateRef glue, GateRef string) GateRef CircuitBuilder::GetFirstFromTreeString(GateRef glue, GateRef string) { - GateRef offset = IntPtr(TreeString::FIRST_OFFSET); + GateRef offset = IntPtr(TreeString::LEFT_OFFSET); return Load(VariableType::JS_POINTER(), glue, string, offset); } GateRef CircuitBuilder::GetSecondFromTreeString(GateRef glue, GateRef string) { - GateRef offset = IntPtr(TreeString::SECOND_OFFSET); + GateRef offset = IntPtr(TreeString::RIGHT_OFFSET); return Load(VariableType::JS_POINTER(), glue, string, offset); } diff --git a/ecmascript/compiler/new_object_stub_builder.cpp b/ecmascript/compiler/new_object_stub_builder.cpp index e3bbb5470253c1b70cd2cb87eadaa20e903c0109..78cec9ebf1ba6f6563bfe3d745f53b15fd03f50a 100644 --- a/ecmascript/compiler/new_object_stub_builder.cpp +++ b/ecmascript/compiler/new_object_stub_builder.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Huawei Device Co., Ltd. + * Copyright (c) 2022-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -2012,8 +2012,8 @@ void NewObjectStubBuilder::AllocTreeStringObject(Variable *result, Label *exit, StoreBuiltinHClass(glue_, result->ReadVariable(), stringClass); InitStringLengthAndFlags(glue_, result->ReadVariable(), length, compressed); SetMixHashcode(glue_, result->ReadVariable(), Int32(0)); - Store(VariableType::JS_POINTER(), glue_, result->ReadVariable(), IntPtr(TreeString::FIRST_OFFSET), first); - Store(VariableType::JS_POINTER(), glue_, result->ReadVariable(), IntPtr(TreeString::SECOND_OFFSET), second); + Store(VariableType::JS_POINTER(), glue_, result->ReadVariable(), IntPtr(TreeString::LEFT_OFFSET), first); + Store(VariableType::JS_POINTER(), glue_, result->ReadVariable(), IntPtr(TreeString::RIGHT_OFFSET), second); Jump(exit); } diff --git a/ecmascript/cross_vm/cross_vm_operator.cpp b/ecmascript/cross_vm/cross_vm_operator.cpp index 6e98db4949de66abe55cac3099bf6be2dcd2a456..964aebdc89b4594cc4bd2525d330e08554c178a6 100644 --- a/ecmascript/cross_vm/cross_vm_operator.cpp +++ b/ecmascript/cross_vm/cross_vm_operator.cpp @@ -31,6 +31,13 @@ CrossVMOperator::CrossVMOperator(EcmaVM *vm) : vm_(vm) /*static*/ void CrossVMOperator::DoHandshake(EcmaVM *vm, void *stsIface, void **ecmaIface) { + if (g_isEnableCMCGC) { + auto vmOperator = vm->GetCrossVMOperator(); + *ecmaIface = vmOperator->ecmaVMInterface_.get(); + vmOperator->stsVMInterface_ = static_cast(stsIface); + Runtime::GetInstance()->SetSTSVMInterface(vmOperator->stsVMInterface_); + return; + } auto vmOperator = vm->GetCrossVMOperator(); *ecmaIface = vmOperator->ecmaVMInterface_.get(); vmOperator->stsVMInterface_ = static_cast(stsIface); @@ -40,6 +47,16 @@ void CrossVMOperator::DoHandshake(EcmaVM *vm, void *stsIface, void **ecmaIface) } } +void CrossVMOperator::MarkFromObject(JSTaggedType value, std::function &visitor) +{ + JSTaggedValue taggedValue(value); + if (!taggedValue.IsHeapObject()) { + return; + } + TaggedObject *object = taggedValue.GetHeapObject(); + visitor(reinterpret_cast(object)); // This is only mark, so could pass a stack reference +} + void CrossVMOperator::MarkFromObject(JSTaggedType value) { JSTaggedValue taggedValue(value); @@ -68,6 +85,9 @@ bool CrossVMOperator::IsValidHeapObject(JSTaggedType value) return false; } TaggedObject *object = taggedValue.GetHeapObject(); + if (g_isEnableCMCGC) { + return static_cast(object)->IsValidObject(); + } return vm_->GetHeap()->ContainObject(object); } diff --git a/ecmascript/cross_vm/cross_vm_operator.h b/ecmascript/cross_vm/cross_vm_operator.h index 8d8af2be2c329be45f3e6bdbe24d4c640162fcd5..e1e92012f18e61776234fcdfac9e3da87974918e 100644 --- a/ecmascript/cross_vm/cross_vm_operator.h +++ b/ecmascript/cross_vm/cross_vm_operator.h @@ -48,6 +48,7 @@ public: return ecmaVMInterface_.get(); } + void MarkFromObject(JSTaggedType value, std::function &visitor); void MarkFromObject(JSTaggedType value); bool IsObjectAlive(JSTaggedType value); bool IsValidHeapObject(JSTaggedType value); @@ -62,7 +63,7 @@ private: bool StartXRefMarking() override; void NotifyXGCInterruption() override; private: - EcmaVM *vm_ {nullptr}; + [[maybe_unused]] EcmaVM *vm_ {nullptr}; }; EcmaVM *vm_ {nullptr}; diff --git a/ecmascript/cross_vm/dynamic_object_accessor_util.cpp b/ecmascript/cross_vm/dynamic_object_accessor_util.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0d8e2cf8a38627d800e5b367ce4eb5df7bd6bc5b --- /dev/null +++ b/ecmascript/cross_vm/dynamic_object_accessor_util.cpp @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "common_interfaces/objects/dynamic_object_accessor_util.h" +#include "ecmascript/checkpoint/thread_state_transition.h" +#include "ecmascript/debugger/js_debugger_manager.h" +#include "ecmascript/dfx/stackinfo/js_stackinfo.h" +#include "ecmascript/ecma_vm.h" +#include "ecmascript/global_env_constants-inl.h" +#include "ecmascript/interpreter/interpreter.h" +#include "ecmascript/interpreter/interpreter_assembly.h" +#include "ecmascript/js_function.h" +#include "ecmascript/js_tagged_value.h" +#include "ecmascript/js_tagged_value-inl.h" +#include "ecmascript/js_thread.h" +#include "ecmascript/napi/include/jsnapi.h" +#include "ecmascript/napi/include/jsnapi_expo.h" +#include "ecmascript/napi/jsnapi_helper.h" +#include "ecmascript/object_factory.h" +#include "ecmascript/object_operator.h" + + +namespace common { + +using panda::ecmascript::EcmaHandleScope; +using panda::ecmascript::EcmaVM; +using panda::ecmascript::EcmaRuntimeCallInfo; +using panda::ecmascript::JSFunction; +using panda::ecmascript::JSHandle; +using panda::ecmascript::JSTaggedValue; +using panda::ecmascript::JSThread; +using panda::ecmascript::ObjectFactory; +using panda::ecmascript::TaggedObject; +using panda::FunctionCallScope; +using panda::EscapeLocalScope; +using panda::JSValueRef; +using panda::JSNApi; + + +TaggedType* DynamicObjectAccessorUtil::GetProperty(const BaseObject *obj, const char *name) +{ + JSThread *jsThread = JSThread::GetCurrent(); + panda::ecmascript::ThreadManagedScope managedScope(jsThread); + ObjectFactory *factory = jsThread->GetEcmaVM()->GetFactory(); + panda::EscapeLocalScope scope(jsThread->GetEcmaVM()); + JSHandle holderHandle(jsThread, TaggedObject::Cast(obj)); + JSHandle keyHandle(factory->NewFromUtf8(name)); + auto resultValue = JSTaggedValue::GetProperty(jsThread, holderHandle, keyHandle).GetValue(); + auto ret = scope.Escape(panda::JSNApiHelper::ToLocal(resultValue)); + return reinterpret_cast(*ret); +} + +bool DynamicObjectAccessorUtil::SetProperty(const BaseObject *obj, const char *name, TaggedType value) +{ + JSThread *jsThread = JSThread::GetCurrent(); + panda::ecmascript::ThreadManagedScope managedScope(jsThread); + ObjectFactory *factory = jsThread->GetEcmaVM()->GetFactory(); + panda::EscapeLocalScope scope(jsThread->GetEcmaVM()); + JSHandle holderHandle(jsThread, TaggedObject::Cast(obj)); + JSHandle keyHandle(factory->NewFromUtf8(name)); + JSTaggedValue taggedValue(value); + JSHandle valueHandle(jsThread, taggedValue); + return JSTaggedValue::SetProperty(jsThread, holderHandle, keyHandle, valueHandle); +} + +TaggedType* DynamicObjectAccessorUtil::CallFunction(TaggedType jsThis, TaggedType function, int32_t argc, + TaggedType *argv) +{ + auto vm = JSThread::GetCurrent()->GetEcmaVM(); + EscapeLocalScope scope(vm); + TaggedType *undefindType = reinterpret_cast(*(JSValueRef::Undefined(vm))); + CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, undefindType); + panda::ecmascript::ThreadManagedScope managedScope(thread); + FunctionCallScope callScope(EcmaVM::ConstCast(vm)); + JSTaggedValue funcValue(function); + if (!funcValue.IsCallable()) { + return undefindType; + } + vm->GetJsDebuggerManager()->ClearSingleStepper(); + JSHandle func(thread, funcValue); + LOG_IF_SPECIAL(func, ERROR); + JSTaggedValue thisObj(jsThis); + JSHandle thisValue(thread, thisObj); + JSHandle undefined = thread->GlobalConstants()->GetHandledUndefined(); + EcmaRuntimeCallInfo *info = + panda::ecmascript::EcmaInterpreter::NewRuntimeCallInfo(thread, func, thisValue, undefined, argc); + RETURN_VALUE_IF_ABRUPT(thread, undefindType); + info->SetCallArg(argc, argv); + JSTaggedValue result = JSFunction::Call(info); + if (thread->HasPendingException()) { + panda::ecmascript::JsStackInfo::BuildCrashInfo(thread); + } + RETURN_VALUE_IF_ABRUPT(thread, undefindType); + EcmaVM::ClearKeptObjects(thread); + vm->GetJsDebuggerManager()->NotifyReturnNative(); + JSHandle resultValue(thread, result); + auto ret = scope.Escape(panda::JSNApiHelper::ToLocal(resultValue)); + return reinterpret_cast(*ret); +} +} \ No newline at end of file diff --git a/ecmascript/cross_vm/jsnapi_expo_hybrid.cpp b/ecmascript/cross_vm/jsnapi_expo_hybrid.cpp index dcecf8450f30e28984e3e251e2b77c0fcd3f0d42..69b8ff79391a0c82a81a1acbdb6cd985013d2a51 100644 --- a/ecmascript/cross_vm/jsnapi_expo_hybrid.cpp +++ b/ecmascript/cross_vm/jsnapi_expo_hybrid.cpp @@ -86,6 +86,15 @@ void JSNApi::DisposeXRefGlobalHandleAddr(const EcmaVM *vm, uintptr_t addr) } #ifdef PANDA_JS_ETS_HYBRID_MODE +void JSNApi::MarkFromObject(const EcmaVM *vm, uintptr_t addr, std::function &visitor) +{ + if (addr == 0 || !reinterpret_cast(addr)->IsUsing()) { + return; + } + JSTaggedType value = *(reinterpret_cast(addr)); + vm->GetCrossVMOperator()->MarkFromObject(value, visitor); +} + void JSNApi::MarkFromObject(const EcmaVM *vm, uintptr_t addr) { if (addr == 0 || !reinterpret_cast(addr)->IsUsing()) { diff --git a/ecmascript/cross_vm/jsnapi_expo_hybrid.h b/ecmascript/cross_vm/jsnapi_expo_hybrid.h index acd30b04b0da61071bd78de274f72009194bcc1c..8fe9ee9f40a498648ce0fdfdff206378434616dd 100644 --- a/ecmascript/cross_vm/jsnapi_expo_hybrid.h +++ b/ecmascript/cross_vm/jsnapi_expo_hybrid.h @@ -21,6 +21,7 @@ /* This method must be called before Global is released.*/ \ void FreeGlobalHandleAddr(); \ void FreeXRefGlobalHandleAddr(); \ + void MarkFromObject(std::function &visitor); \ void MarkFromObject(); \ bool IsObjectAlive() const; \ bool IsValidHeapObject() const @@ -47,6 +48,7 @@ static void DisposeXRefGlobalHandleAddr(const EcmaVM *vm, uintptr_t addr) #define JSNAPI_PRIVATE_HYBRID_MODE_EXTENSION() \ + static void MarkFromObject(const EcmaVM *vm, uintptr_t addr, std::function &visitor); \ static void MarkFromObject(const EcmaVM *vm, uintptr_t addr) #define GLOBAL_PUBLIC_DEF_HYBRID_EXTENSION() \ @@ -70,6 +72,14 @@ } #define GLOBAL_PUBLIC_DEF_HYBRID_MODE_EXTENSION() \ + template \ + void Global::MarkFromObject(std::function &visitor) \ + { \ + if (address_ == 0) { \ + return; \ + } \ + JSNApi::MarkFromObject(vm_, address_, visitor); \ + } \ template \ void Global::MarkFromObject() \ { \ diff --git a/ecmascript/dfx/hprof/tests/heap_snapshot_test.cpp b/ecmascript/dfx/hprof/tests/heap_snapshot_test.cpp index 4235e6c1368b254c56c0bb6e87bd49eaac7a5c2a..ddca8c6872399251fafa916c84ba5e395aef4dcf 100644 --- a/ecmascript/dfx/hprof/tests/heap_snapshot_test.cpp +++ b/ecmascript/dfx/hprof/tests/heap_snapshot_test.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 Huawei Device Co., Ltd. + * Copyright (c) 2024-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -135,10 +135,17 @@ HWTEST_F_L0(HeapSnapShotTest, TestGenerateStringNode) totalSize += node->GetSelfSize(); } } +#if defined(ARK_HYBRID) || defined(USE_CMC_GC) + // lineString: 32 + // treeString: 40 + // totalSize: 8 * 32 + 7 * 40 + ASSERT_EQ(totalSize, 536); +#else // lineString: 24 // treeString: 32 // totalSize: 8 * 24 + 7 * 32 ASSERT_EQ(totalSize, 416); +#endif } HWTEST_F_L0(HeapSnapShotTest, TestGeneratePrivateStringNode) @@ -149,8 +156,13 @@ HWTEST_F_L0(HeapSnapShotTest, TestGeneratePrivateStringNode) HeapSnapShotFriendTest heapSnapShotTest(ecmaVm_, tester.GetEcmaStringTableTest(), dumpOption, false, tester.GetEntryIdMapTest()); Node *node = heapSnapShotTest.GeneratePrivateStringNodeTest(0); +#if defined(ARK_HYBRID) || defined(USE_CMC_GC) + // lineString: 32 + ASSERT_EQ(node->GetSelfSize(), 32); +#else // lineString: 24 ASSERT_EQ(node->GetSelfSize(), 24); +#endif } HWTEST_F_L0(HeapSnapShotTest, TestMoveNode) @@ -173,7 +185,12 @@ HWTEST_F_L0(HeapSnapShotTest, TestMoveNode) heapSnapShotTest.MoveNodeTest(address, reinterpret_cast(treeString), 0); HeapEntryMap &heapEntryMap = heapSnapShotTest.GetEntryMapTest(); Node *movedNode = heapEntryMap.FindEntry(reinterpret_cast(treeString)); +#if defined(ARK_HYBRID) || defined(USE_CMC_GC) + // treeString: 40 + ASSERT_EQ(movedNode->GetSelfSize(), 40); +#else // treeString: 32 ASSERT_EQ(movedNode->GetSelfSize(), 32); +#endif } } \ No newline at end of file diff --git a/ecmascript/dfx/hprof/tests/js_metadata_test.cpp b/ecmascript/dfx/hprof/tests/js_metadata_test.cpp index fbfe726b5e4ab156256d7a34862885601a2bd5ed..2429a45686fe5e1cc80f8280f10537bc660eae6b 100644 --- a/ecmascript/dfx/hprof/tests/js_metadata_test.cpp +++ b/ecmascript/dfx/hprof/tests/js_metadata_test.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025 Huawei Device Co., Ltd. + * Copyright (c) 2024-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -1025,8 +1025,8 @@ public: TransWithProtoHandler::TRANSITION_HCLASS_OFFSET, TransWithProtoHandler::PROTO_CELL_OFFSET, TransWithProtoHandler::SIZE - TransWithProtoHandler::HANDLER_INFO_OFFSET}}, - {JSType::TREE_STRING, {TreeString::FIRST_OFFSET, TreeString::SECOND_OFFSET, - TreeString::SIZE - TreeString::FIRST_OFFSET}}, + {JSType::TREE_STRING, {TreeString::LEFT_OFFSET, TreeString::RIGHT_OFFSET, + TreeString::SIZE - TreeString::LEFT_OFFSET}}, {JSType::VTABLE, {TaggedArray::LAST_OFFSET - TaggedArray::LENGTH_OFFSET}} }; // { typeName: [all parents of this type]} @@ -1757,8 +1757,8 @@ public: TransWithProtoHandler::TRANSITION_HCLASS_OFFSET - TransWithProtoHandler::HANDLER_INFO_OFFSET, TransWithProtoHandler::PROTO_CELL_OFFSET - TransWithProtoHandler::TRANSITION_HCLASS_OFFSET, TransWithProtoHandler::SIZE - TransWithProtoHandler::PROTO_CELL_OFFSET}}, - {JSType::TREE_STRING, {TreeString::SECOND_OFFSET - TreeString::FIRST_OFFSET, - TreeString::SIZE - TreeString::SECOND_OFFSET}}, + {JSType::TREE_STRING, {TreeString::RIGHT_OFFSET - TreeString::LEFT_OFFSET, + TreeString::SIZE - TreeString::RIGHT_OFFSET}}, {JSType::VTABLE, {}} }; } @@ -3148,16 +3148,16 @@ HWTEST_F_L0(JSMetadataTest, TestJsFloat64ArrayMetadata) ASSERT_TRUE(tester.Test(JSType::JS_FLOAT64_ARRAY, metadata)); } -HWTEST_F_L0(JSMetadataTest, TestJsForinIteratorMetadata) -{ - JSMetadataTestHelper tester {}; - std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_forin_iterator.json"; - JSMetadataTestHelper::Metadata metadata {}; +// HWTEST_F_L0(JSMetadataTest, TestJsForinIteratorMetadata) +// { +// JSMetadataTestHelper tester {}; +// std::string metadataFilePath = METADATA_SOURCE_FILE_DIR"js_forin_iterator.json"; +// JSMetadataTestHelper::Metadata metadata {}; - tester.ReadAndParseMetadataJson(metadataFilePath, metadata); - ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); - ASSERT_TRUE(tester.Test(JSType::JS_FORIN_ITERATOR, metadata)); -} +// tester.ReadAndParseMetadataJson(metadataFilePath, metadata); +// ASSERT_TRUE(metadata.status == JSMetadataTestHelper::INITIALIZED); +// ASSERT_TRUE(tester.Test(JSType::JS_FORIN_ITERATOR, metadata)); +// } HWTEST_F_L0(JSMetadataTest, TestJsFunctionMetadata) { diff --git a/ecmascript/ecma_string-inl.h b/ecmascript/ecma_string-inl.h index df4380f88f33d8e8fbacfe1cb3c5b27ac81f3910..68dd1e992d81bc8a709bfd35ea60ea84e4c41e79 100644 --- a/ecmascript/ecma_string-inl.h +++ b/ecmascript/ecma_string-inl.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2024 Huawei Device Co., Ltd. + * Copyright (c) 2021-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -16,6 +16,7 @@ #ifndef ECMASCRIPT_STRING_INL_H #define ECMASCRIPT_STRING_INL_H +#include "common_interfaces/objects/string/base_string-inl.h" #include "ecmascript/ecma_string.h" #include "ecmascript/base/string_helper.h" #include "ecmascript/ecma_vm.h" @@ -24,7 +25,6 @@ #include "ecmascript/mem/space.h" #include "ecmascript/object_factory-inl.h" #include "ecmascript/debugger/js_debugger_manager.h" -#include "common_interfaces/objects/string/base_string-inl2.h" namespace panda::ecmascript { /* static */ @@ -44,11 +44,11 @@ inline EcmaString *EcmaString::CreateFromUtf8(const EcmaVM *vm, const uint8_t *u if (utf8Len == 0) { return vm->GetFactory()->GetEmptyString().GetObject(); } - auto allocator = [vm, type](size_t size, common::CommonType stringType) -> BaseObject* { - ASSERT(stringType == common::CommonType::LINE_STRING && "Can only allocate line string"); + auto allocator = [vm, type](size_t size, common::ObjectType stringType) -> BaseObject* { + ASSERT(stringType == common::ObjectType::LINE_STRING && "Can only allocate line string"); return EcmaString::AllocLineString(vm, size, type)->ToBaseString(); }; - BaseString *str = BaseString::CreateFromUtf8(std::move(allocator), utf8Data, utf8Len, canBeCompress); + BaseString *str = LineString::CreateFromUtf8(std::move(allocator), utf8Data, utf8Len, canBeCompress); return EcmaString::FromBaseString(str); } #else @@ -86,11 +86,11 @@ inline EcmaString *EcmaString::CreateFromUtf8CompressedSubString(const EcmaVM *v return vm->GetFactory()->GetEmptyString().GetObject(); } - auto allocator = [vm, type](size_t size, common::CommonType stringType) -> BaseObject* { - ASSERT(stringType == common::CommonType::LINE_STRING && "Can only allocate line string"); + auto allocator = [vm, type](size_t size, common::ObjectType stringType) -> BaseObject* { + ASSERT(stringType == common::ObjectType::LINE_STRING && "Can only allocate line string"); return EcmaString::AllocLineString(vm, size, type)->ToBaseString(); }; - BaseString *str = BaseString::CreateFromUtf8CompressedSubString(std::move(allocator), string, offset, utf8Len); + BaseString *str = LineString::CreateFromUtf8CompressedSubString(std::move(allocator), string, offset, utf8Len); return EcmaString::FromBaseString(str); } @@ -124,36 +124,36 @@ inline EcmaString *EcmaString::CreateFromUtf16(const EcmaVM *vm, const uint16_t return vm->GetFactory()->GetEmptyString().GetObject(); } - auto allocator = [vm, type](size_t size, common::CommonType stringType) -> BaseObject* { - ASSERT(stringType == common::CommonType::LINE_STRING && "Can only allocate line string"); + auto allocator = [vm, type](size_t size, common::ObjectType stringType) -> BaseObject* { + ASSERT(stringType == common::ObjectType::LINE_STRING && "Can only allocate line string"); return EcmaString::AllocLineString(vm, size, type)->ToBaseString(); }; - BaseString *str = BaseString::CreateFromUtf16(std::move(allocator), utf16Data, utf16Len, canBeCompress); + BaseString *str = LineString::CreateFromUtf16(std::move(allocator), utf16Data, utf16Len, canBeCompress); return EcmaString::FromBaseString(str); } /* static */ inline EcmaString *EcmaString::CreateLineString(const EcmaVM *vm, size_t length, bool compressed) { - auto allocator = [vm](size_t size, common::CommonType stringType) -> BaseObject* { - ASSERT(stringType == common::CommonType::LINE_STRING && "Can only allocate line string"); + auto allocator = [vm](size_t size, common::ObjectType stringType) -> BaseObject* { + ASSERT(stringType == common::ObjectType::LINE_STRING && "Can only allocate line string"); EcmaString* string = vm->GetFactory()->AllocLineStringObject(size); return string; }; - BaseString *str = BaseString::CreateLineString(std::move(allocator), length, compressed); + BaseString *str = LineString::Create(std::move(allocator), length, compressed); return EcmaString::FromBaseString(str); } /* static */ inline EcmaString *EcmaString::CreateLineStringNoGC(const EcmaVM *vm, size_t length, bool compressed) { - auto allocator = [vm](size_t size, common::CommonType stringType) -> BaseObject* { - ASSERT(stringType == common::CommonType::LINE_STRING && "Can only allocate line string"); + auto allocator = [vm](size_t size, common::ObjectType stringType) -> BaseObject* { + ASSERT(stringType == common::ObjectType::LINE_STRING && "Can only allocate line string"); size = AlignUp(size, static_cast(MemAlignment::MEM_ALIGN_OBJECT)); EcmaString* string = vm->GetFactory()->AllocLineStringObjectNoGC(size); return string; }; - BaseString *str = BaseString::CreateLineString(std::move(allocator), length, compressed); + BaseString *str = LineString::Create(std::move(allocator), length, compressed); return EcmaString::FromBaseString(str); } @@ -181,27 +181,27 @@ inline EcmaString* EcmaString::AllocLineString(const EcmaVM* vm, size_t size, Me inline EcmaString *EcmaString::CreateLineStringWithSpaceType(const EcmaVM *vm, size_t length, bool compressed, MemSpaceType type) { - auto allocator = [vm, type](size_t size, common::CommonType stringType) -> BaseObject* { - ASSERT(stringType == common::CommonType::LINE_STRING && "Can only allocate line string"); + auto allocator = [vm, type](size_t size, common::ObjectType stringType) -> BaseObject* { + ASSERT(stringType == common::ObjectType::LINE_STRING && "Can only allocate line string"); ASSERT(IsSMemSpace(type)); return AllocLineString(vm, size, type); }; - BaseString *str = BaseString::CreateLineString(std::move(allocator), length, compressed); + BaseString *str = LineString::Create(std::move(allocator), length, compressed); return EcmaString::FromBaseString(str); } inline SlicedEcmaString* EcmaString::CreateSlicedString(const EcmaVM* vm, JSHandle parent, MemSpaceType type) { - auto allocator = [vm, type](size_t, common::CommonType stringType) -> BaseObject* { - ASSERT(stringType == common::CommonType::SLICED_STRING && "Can only allocate sliced string"); + auto allocator = [vm, type](size_t, common::ObjectType stringType) -> BaseObject* { + ASSERT(stringType == common::ObjectType::SLICED_STRING && "Can only allocate sliced string"); EcmaString* string = vm->GetFactory()->AllocSlicedStringObject(type); return string; }; auto writeBarrier = [vm](void* obj, size_t offset, BaseObject* str) { Barriers::SetObject(vm->GetJSThread(), obj, offset, reinterpret_cast(str)); }; - SlicedString* slicedString = BaseString::CreateSlicedString(std::move(allocator), std::move(writeBarrier), parent); + SlicedString* slicedString = SlicedString::Create(std::move(allocator), std::move(writeBarrier), parent); return SlicedEcmaString::FromBaseString(slicedString); } @@ -232,16 +232,16 @@ inline EcmaString *EcmaString::CreateTreeString(const EcmaVM *vm, JSThread *thread = nullptr; GetDebuggerThread(vm, &thread); - auto allocator = [vm](size_t, common::CommonType stringType) -> BaseObject* { - ASSERT(stringType == common::CommonType::TREE_STRING && "Can only allocate tree string"); + auto allocator = [vm](size_t, common::ObjectType stringType) -> BaseObject* { + ASSERT(stringType == common::ObjectType::TREE_STRING && "Can only allocate tree string"); EcmaString* string = vm->GetFactory()->AllocTreeStringObject(); return string; }; auto writeBarrier = [thread](void* obj, size_t offset, BaseObject* str) { Barriers::SetObject(thread, obj, offset, reinterpret_cast(str)); }; - TreeString* treeString = BaseString::CreateTreeString(std::move(allocator), std::move(writeBarrier), left, right, - length, compressed); + TreeString* treeString = TreeString::Create(std::move(allocator), std::move(writeBarrier), left, right, + length, compressed); return TreeEcmaString::FromBaseString(treeString); } @@ -252,8 +252,8 @@ EcmaString *EcmaString::FastSubUtf8String(const EcmaVM *vm, const JSHandle string(vm->GetJSThread(), CreateLineString(vm, length, true)); // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) FlatStringInfo srcFlat = FlattenAllString(vm, src); - Span dst(string->GetDataUtf8Writable(), length); - Span source(srcFlat.GetDataUtf8() + start, length); + common::Span dst(string->GetDataUtf8Writable(), length); + common::Span source(srcFlat.GetDataUtf8() + start, length); EcmaString::MemCopyChars(dst, length, source, length); ASSERT_PRINT(CanBeCompressed(*string), "canBeCompresse does not match the real value!"); @@ -275,8 +275,8 @@ EcmaString *EcmaString::FastSubUtf16String(const EcmaVM *vm, const JSHandle dst(string->GetDataUtf16Writable(), length); - Span source(srcFlat.GetDataUtf16() + start, length); + common::Span dst(string->GetDataUtf16Writable(), length); + common::Span source(srcFlat.GetDataUtf16() + start, length); EcmaString::MemCopyChars(dst, len, source, len); } ASSERT_PRINT(canBeCompressed == CanBeCompressed(*string), "canBeCompresse does not match the real value!"); @@ -285,23 +285,23 @@ EcmaString *EcmaString::FastSubUtf16String(const EcmaVM *vm, const JSHandleGetDataUtf8(); + return LineString::ConstCast(this)->GetDataUtf8(); } inline const uint16_t* EcmaString::GetDataUtf16() const { - return ToBaseString()->GetDataUtf16(); + return LineString::ConstCast(this)->GetDataUtf16(); } // require is LineString inline uint8_t* EcmaString::GetDataUtf8Writable() { - return ToBaseString()->GetDataUtf8Writable(); + return LineString::Cast(this)->GetDataUtf8Writable(); } inline uint16_t* EcmaString::GetDataUtf16Writable() { - return ToBaseString()->GetDataUtf16Writable(); + return LineString::Cast(this)->GetDataUtf16Writable(); } inline size_t EcmaString::GetUtf8Length(const JSThread *thread, bool modify, bool isGetBufferSize) const @@ -321,17 +321,23 @@ uint16_t EcmaString::At(const JSThread *thread, int32_t index) const return ToBaseString()->At(std::move(readBarrier), index); } +template +bool EcmaString::StringsAreEquals(common::Span& str1, common::Span& str2) +{ + return BaseString::StringsAreEquals(str1, str2); +} + inline void EcmaString::WriteData(uint32_t index, uint16_t src) { - return ToBaseString()->WriteData(index, src); + return LineString::Cast(this)->Set(index, src); } -inline Span EcmaString::FastToUtf8Span() const +inline common::Span EcmaString::FastToUtf8Span() const { uint32_t len = GetLength(); ASSERT(IsUtf8()); const uint8_t *data = GetDataUtf8(); - return Span(data, len); + return common::Span(data, len); } inline bool EcmaString::IsFlat(const JSThread *thread) const @@ -395,8 +401,8 @@ inline uint32_t EcmaString::CopyDataUtf16(const JSThread *thread, uint16_t *buf, return ToBaseString()->CopyDataUtf16(std::move(readBarrier), buf, maxLength); } -inline Span EcmaString::ToUtf8Span(const JSThread *thread, CVector &buf, bool modify, - bool cesu8) +inline common::Span EcmaString::ToUtf8Span(const JSThread *thread, CVector &buf, bool modify, + bool cesu8) { auto readBarrier = [thread](const void *obj, size_t offset) -> TaggedObject * { return Barriers::GetTaggedObject(thread, obj, offset); @@ -404,7 +410,8 @@ inline Span EcmaString::ToUtf8Span(const JSThread *thread, CVecto return ToBaseString()->ToUtf8Span(std::move(readBarrier), buf, modify, cesu8); } -inline Span EcmaString::DebuggerToUtf8Span(const JSThread *thread, CVector &buf, bool modify) +inline common::Span EcmaString::DebuggerToUtf8Span(const JSThread *thread, CVector &buf, + bool modify) { auto readBarrier = [thread](const void *obj, size_t offset) -> TaggedObject * { return Barriers::GetTaggedObject(thread, obj, offset); @@ -454,9 +461,14 @@ inline void EcmaStringAccessor::ReadData(const JSThread *thread, EcmaString *dst dst->WriteData(thread, src, start, destSize, length); } -inline Span EcmaStringAccessor::FastToUtf8Span() const +inline common::Span EcmaStringAccessor::FastToUtf8Span() const { return string_->FastToUtf8Span(); } + +inline bool EcmaStringAccessor::IsASCIICharacter(uint16_t data) +{ + return BaseString::IsASCIICharacter(data); +} } // namespace panda::ecmascript #endif diff --git a/ecmascript/ecma_string.cpp b/ecmascript/ecma_string.cpp index a4d6843695199b735a75dbceef146adeead683fe..43bf3cf22ca3ee779a9c0f27f99c60e592986825 100755 --- a/ecmascript/ecma_string.cpp +++ b/ecmascript/ecma_string.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2021-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -15,7 +15,7 @@ #include "ecmascript/ecma_string-inl.h" -#include "common_interfaces/objects/base_string.h" +#include "common_interfaces/objects/string/base_string-inl.h" #include "ecmascript/base/json_helper.h" namespace panda::ecmascript { @@ -65,20 +65,20 @@ EcmaString *EcmaString::Concat(const EcmaVM *vm, strRight = *right; if (compressed) { // copy left part - Span sp(newString->GetDataUtf8Writable(), newLength); - Span srcLeft(strLeft->GetDataUtf8(), leftLength); + common::Span sp(newString->GetDataUtf8Writable(), newLength); + common::Span srcLeft(strLeft->GetDataUtf8(), leftLength); EcmaString::MemCopyChars(sp, newLength, srcLeft, leftLength); // copy right part sp = sp.SubSpan(leftLength); - Span srcRight(strRight->GetDataUtf8(), rightLength); + common::Span srcRight(strRight->GetDataUtf8(), rightLength); EcmaString::MemCopyChars(sp, rightLength, srcRight, rightLength); } else { // copy left part - Span sp(newString->GetDataUtf16Writable(), newLength); + common::Span sp(newString->GetDataUtf16Writable(), newLength); if (strLeft->IsUtf8()) { BaseString::CopyChars(sp.data(), strLeft->GetDataUtf8(), leftLength); } else { - Span srcLeft(strLeft->GetDataUtf16(), leftLength); + common::Span srcLeft(strLeft->GetDataUtf16(), leftLength); EcmaString::MemCopyChars(sp, newLength << 1U, srcLeft, leftLength << 1U); } // copy right part @@ -86,7 +86,7 @@ EcmaString *EcmaString::Concat(const EcmaVM *vm, if (strRight->IsUtf8()) { BaseString::CopyChars(sp.data(), strRight->GetDataUtf8(), rightLength); } else { - Span srcRight(strRight->GetDataUtf16(), rightLength); + common::Span srcRight(strRight->GetDataUtf16(), rightLength); EcmaString::MemCopyChars(sp, rightLength << 1U, srcRight, rightLength << 1U); } } @@ -105,16 +105,16 @@ EcmaString *EcmaString::CopyStringToOldSpace(const EcmaVM *vm, const JSHandle sp(newString->GetDataUtf8Writable(), length); - Span srcSp(strOrigin.GetDataUtf8(), length); + common::Span sp(newString->GetDataUtf8Writable(), length); + common::Span srcSp(strOrigin.GetDataUtf8(), length); EcmaString::MemCopyChars(sp, length, srcSp, length); } else { // copy left part - Span sp(newString->GetDataUtf16Writable(), length); + common::Span sp(newString->GetDataUtf16Writable(), length); if (strOrigin.IsUtf8()) { BaseString::CopyChars(sp.data(), strOrigin.GetDataUtf8(), length); } else { - Span srcSp(strOrigin.GetDataUtf16(), length); + common::Span srcSp(strOrigin.GetDataUtf16(), length); EcmaString::MemCopyChars(sp, length << 1U, srcSp, length << 1U); } } @@ -212,30 +212,30 @@ int32_t EcmaString::Compare(const EcmaVM *vm, const JSHandle &left, int32_t countDiff = lhsCount - rhsCount; int32_t minCount = (countDiff < 0) ? lhsCount : rhsCount; if (!lhs.IsUtf16() && !rhs.IsUtf16()) { - Span lhsSp(lhs.GetDataUtf8(), lhsCount); - Span rhsSp(rhs.GetDataUtf8(), rhsCount); - int32_t charDiff = common::CompareStringSpan(lhsSp, rhsSp, minCount); + common::Span lhsSp(lhs.GetDataUtf8(), lhsCount); + common::Span rhsSp(rhs.GetDataUtf8(), rhsCount); + int32_t charDiff = CompareStringSpan(lhsSp, rhsSp, minCount); if (charDiff != 0) { return charDiff; } } else if (!lhs.IsUtf16()) { - Span lhsSp(lhs.GetDataUtf8(), lhsCount); - Span rhsSp(rhs.GetDataUtf16(), rhsCount); - int32_t charDiff = common::CompareStringSpan(lhsSp, rhsSp, minCount); + common::Span lhsSp(lhs.GetDataUtf8(), lhsCount); + common::Span rhsSp(rhs.GetDataUtf16(), rhsCount); + int32_t charDiff = CompareStringSpan(lhsSp, rhsSp, minCount); if (charDiff != 0) { return charDiff; } } else if (!rhs.IsUtf16()) { - Span lhsSp(lhs.GetDataUtf16(), rhsCount); - Span rhsSp(rhs.GetDataUtf8(), lhsCount); - int32_t charDiff = common::CompareStringSpan(lhsSp, rhsSp, minCount); + common::Span lhsSp(lhs.GetDataUtf16(), rhsCount); + common::Span rhsSp(rhs.GetDataUtf8(), lhsCount); + int32_t charDiff = CompareStringSpan(lhsSp, rhsSp, minCount); if (charDiff != 0) { return charDiff; } } else { - Span lhsSp(lhs.GetDataUtf16(), lhsCount); - Span rhsSp(rhs.GetDataUtf16(), rhsCount); - int32_t charDiff = common::CompareStringSpan(lhsSp, rhsSp, minCount); + common::Span lhsSp(lhs.GetDataUtf16(), lhsCount); + common::Span rhsSp(rhs.GetDataUtf16(), rhsCount); + int32_t charDiff = CompareStringSpan(lhsSp, rhsSp, minCount); if (charDiff != 0) { return charDiff; } @@ -259,34 +259,34 @@ bool EcmaString::IsSubStringAt(const EcmaVM *vm, const JSHandle& lef int32_t lhsCount = static_cast(lhs.GetLength()); int32_t rhsCount = static_cast(rhs.GetLength()); if (!lhs.IsUtf16() && !rhs.IsUtf16()) { - Span lhsSp(lhs.GetDataUtf8(), lhsCount); - Span rhsSp(rhs.GetDataUtf8(), rhsCount); - return common::IsSubStringAtSpan(lhsSp, rhsSp, offset); + common::Span lhsSp(lhs.GetDataUtf8(), lhsCount); + common::Span rhsSp(rhs.GetDataUtf8(), rhsCount); + return IsSubStringAtSpan(lhsSp, rhsSp, offset); } else if (!lhs.IsUtf16()) { - Span lhsSp(lhs.GetDataUtf8(), lhsCount); - Span rhsSp(rhs.GetDataUtf16(), rhsCount); - return common::IsSubStringAtSpan(lhsSp, rhsSp, offset); + common::Span lhsSp(lhs.GetDataUtf8(), lhsCount); + common::Span rhsSp(rhs.GetDataUtf16(), rhsCount); + return IsSubStringAtSpan(lhsSp, rhsSp, offset); } else if (!rhs.IsUtf16()) { - Span lhsSp(lhs.GetDataUtf16(), lhsCount); - Span rhsSp(rhs.GetDataUtf8(), rhsCount); - return common::IsSubStringAtSpan(lhsSp, rhsSp, offset); + common::Span lhsSp(lhs.GetDataUtf16(), lhsCount); + common::Span rhsSp(rhs.GetDataUtf8(), rhsCount); + return IsSubStringAtSpan(lhsSp, rhsSp, offset); } else { - Span lhsSp(lhs.GetDataUtf16(), lhsCount); - Span rhsSp(rhs.GetDataUtf16(), rhsCount); - return common::IsSubStringAtSpan(lhsSp, rhsSp, offset); + common::Span lhsSp(lhs.GetDataUtf16(), lhsCount); + common::Span rhsSp(rhs.GetDataUtf16(), rhsCount); + return IsSubStringAtSpan(lhsSp, rhsSp, offset); } return false; } /* static */ -template -int32_t EcmaString::IndexOf(Span &lhsSp, Span &rhsSp, int32_t pos, int32_t max) +template +int32_t EcmaString::IndexOf(common::Span& lhsSp, common::Span& rhsSp, int32_t pos, int32_t max) { - return BaseString::IndexOf(lhsSp, rhsSp, pos, max); + return BaseString::IndexOf(lhsSp, rhsSp, pos, max); } -template -int32_t EcmaString::LastIndexOf(Span &lhsSp, Span &rhsSp, int32_t pos) +template +int32_t EcmaString::LastIndexOf(common::Span& lhsSp, common::Span& rhsSp, int32_t pos) { return BaseString::LastIndexOf(lhsSp, rhsSp, pos); } @@ -329,18 +329,18 @@ int32_t EcmaString::IndexOf(const EcmaVM *vm, lhs.SetString(*string); if (rhs.IsUtf8() && lhs.IsUtf8()) { - Span lhsSp(lhs.GetDataUtf8(), lhsCount); - Span rhsSp(rhs.GetDataUtf8(), rhsCount); + common::Span lhsSp(lhs.GetDataUtf8(), lhsCount); + common::Span rhsSp(rhs.GetDataUtf8(), rhsCount); return EcmaString::IndexOf(lhsSp, rhsSp, pos, max); } else if (rhs.IsUtf16() && lhs.IsUtf16()) { // NOLINT(readability-else-after-return) - Span lhsSp(lhs.GetDataUtf16(), lhsCount); - Span rhsSp(rhs.GetDataUtf16(), rhsCount); + common::Span lhsSp(lhs.GetDataUtf16(), lhsCount); + common::Span rhsSp(rhs.GetDataUtf16(), rhsCount); return EcmaString::IndexOf(lhsSp, rhsSp, pos, max); } else if (rhs.IsUtf16()) { return -1; } else { // NOLINT(readability-else-after-return) - Span lhsSp(lhs.GetDataUtf16(), lhsCount); - Span rhsSp(rhs.GetDataUtf8(), rhsCount); + common::Span lhsSp(lhs.GetDataUtf16(), lhsCount); + common::Span rhsSp(rhs.GetDataUtf8(), rhsCount); return EcmaString::IndexOf(lhsSp, rhsSp, pos, max); } } @@ -381,18 +381,18 @@ int32_t EcmaString::LastIndexOf(const EcmaVM *vm, FlatStringInfo rhs = FlattenAllString(vm, search); lhs.SetString(*string); if (rhs.IsUtf8() && lhs.IsUtf8()) { - Span lhsSp(lhs.GetDataUtf8(), lhsCount); - Span rhsSp(rhs.GetDataUtf8(), rhsCount); + common::Span lhsSp(lhs.GetDataUtf8(), lhsCount); + common::Span rhsSp(rhs.GetDataUtf8(), rhsCount); return EcmaString::LastIndexOf(lhsSp, rhsSp, pos); } else if (rhs.IsUtf16() && lhs.IsUtf16()) { // NOLINT(readability-else-after-return) - Span lhsSp(lhs.GetDataUtf16(), lhsCount); - Span rhsSp(rhs.GetDataUtf16(), rhsCount); + common::Span lhsSp(lhs.GetDataUtf16(), lhsCount); + common::Span rhsSp(rhs.GetDataUtf16(), rhsCount); return EcmaString::LastIndexOf(lhsSp, rhsSp, pos); } else if (rhs.IsUtf16()) { return -1; } else { // NOLINT(readability-else-after-return) - Span lhsSp(lhs.GetDataUtf16(), lhsCount); - Span rhsSp(rhs.GetDataUtf8(), rhsCount); + common::Span lhsSp(lhs.GetDataUtf16(), lhsCount); + common::Span rhsSp(rhs.GetDataUtf8(), rhsCount); return EcmaString::LastIndexOf(lhsSp, rhsSp, pos); } } @@ -464,14 +464,14 @@ uint32_t EcmaString::CalculateConcatHashCode(const JSThread *thread, const JSHan bool EcmaString::HashIntegerString(uint32_t length, uint32_t *hash, const uint32_t hashSeed) const { ASSERT(length >= 0); - Span str = FastToUtf8Span(); + common::Span str = FastToUtf8Span(); return BaseString::HashIntegerString(str.data(), length, hash, hashSeed); } // static bool EcmaString::CanBeCompressed(const EcmaString *string) { - return BaseString::CanBeCompressed(string->ToBaseString()); + return LineString::CanBeCompressed(LineString::ConstCast(string)); } // static @@ -510,20 +510,20 @@ bool EcmaString::StringsAreEqualDiffUtfEncoding(const FlatStringInfo &left, cons int32_t lhsCount = static_cast(left.GetLength()); int32_t rhsCount = static_cast(right.GetLength()); if (!left.IsUtf16() && !right.IsUtf16()) { - Span lhsSp(left.GetDataUtf8(), lhsCount); - Span rhsSp(right.GetDataUtf8(), rhsCount); + common::Span lhsSp(left.GetDataUtf8(), lhsCount); + common::Span rhsSp(right.GetDataUtf8(), rhsCount); return EcmaString::StringsAreEquals(lhsSp, rhsSp); } else if (!left.IsUtf16()) { - Span lhsSp(left.GetDataUtf8(), lhsCount); - Span rhsSp(right.GetDataUtf16(), rhsCount); + common::Span lhsSp(left.GetDataUtf8(), lhsCount); + common::Span rhsSp(right.GetDataUtf16(), rhsCount); return EcmaString::StringsAreEquals(lhsSp, rhsSp); } else if (!right.IsUtf16()) { - Span lhsSp(left.GetDataUtf16(), rhsCount); - Span rhsSp(right.GetDataUtf8(), lhsCount); + common::Span lhsSp(left.GetDataUtf16(), rhsCount); + common::Span rhsSp(right.GetDataUtf8(), lhsCount); return EcmaString::StringsAreEquals(lhsSp, rhsSp); } else { - Span lhsSp(left.GetDataUtf16(), lhsCount); - Span rhsSp(right.GetDataUtf16(), rhsCount); + common::Span lhsSp(left.GetDataUtf16(), lhsCount); + common::Span rhsSp(right.GetDataUtf16(), rhsCount); return EcmaString::StringsAreEquals(lhsSp, rhsSp); } } @@ -580,7 +580,7 @@ bool EcmaString::StringsAreEqualUtf16(const JSThread *thread, const EcmaString * } template -bool EcmaString::MemCopyChars(Span &dst, size_t dstMax, Span &src, size_t count) +bool EcmaString::MemCopyChars(common::Span &dst, size_t dstMax, common::Span &src, size_t count) { ASSERT(dstMax >= count); ASSERT(dst.Size() >= src.Size()); @@ -717,8 +717,9 @@ bool EcmaString::ToTypedArrayIndex(const JSThread *thread, uint32_t *index) return false; } -template -EcmaString *EcmaString::TrimBody(const JSThread *thread, const JSHandle &src, Span &data, TrimMode mode) +template +EcmaString* EcmaString::TrimBody(const JSThread* thread, const JSHandle& src, common::Span& data, + TrimMode mode) { uint32_t srcLen = src->GetLength(); int32_t start = 0; @@ -730,7 +731,7 @@ EcmaString *EcmaString::TrimBody(const JSThread *thread, const JSHandleGetEcmaVM(), src, start, static_cast(end - start + 1)); + EcmaString* res = FastSubString(thread->GetEcmaVM(), src, start, static_cast(end - start + 1)); return res; } @@ -757,7 +758,7 @@ EcmaString *EcmaString::TryToLower(const EcmaVM *vm, const JSHandle const char start = 'A'; const char end = 'Z'; uint32_t upperIndex = srcLength; - Span data(srcFlat.GetDataUtf8Writable(), srcLength); + common::Span data(srcFlat.GetDataUtf8Writable(), srcLength); for (uint32_t index = 0; index < srcLength; ++index) { if (base::StringHelper::Utf8CharInRange(data[index], start, end)) { upperIndex = index; @@ -778,7 +779,7 @@ EcmaString *EcmaString::TryToUpper(const EcmaVM *vm, const JSHandle const char start = 'a'; const char end = 'z'; uint32_t lowerIndex = srcLength; - Span data(srcFlat.GetDataUtf8Writable(), srcLength); + common::Span data(srcFlat.GetDataUtf8Writable(), srcLength); for (uint32_t index = 0; index < srcLength; ++index) { if (base::StringHelper::Utf8CharInRange(data[index], start, end)) { lowerIndex = index; @@ -800,7 +801,7 @@ EcmaString *EcmaString::ConvertUtf8ToLowerOrUpper(const EcmaVM *vm, const JSHand uint32_t srcLength = src->GetLength(); JSHandle newString(vm->GetJSThread(), CreateLineString(vm, srcLength, true)); auto srcFlat = FlattenAllString(vm, src); - Span data(srcFlat.GetDataUtf8Writable(), srcLength); + common::Span data(srcFlat.GetDataUtf8Writable(), srcLength); auto newStringPtr = newString->GetDataUtf8Writable(); if (startIndex > 0) { if (memcpy_s(newStringPtr, startIndex * sizeof(uint8_t), data.data(), startIndex * sizeof(uint8_t)) != EOK) { @@ -861,10 +862,10 @@ EcmaString *EcmaString::Trim(const JSThread *thread, const JSHandle return EcmaString::Cast(thread->GlobalConstants()->GetEmptyString().GetTaggedObject()); } if (srcFlat.IsUtf8()) { - Span data(srcFlat.GetDataUtf8(), srcLen); + common::Span data(srcFlat.GetDataUtf8(), srcLen); return TrimBody(thread, src, data, mode); } else { - Span data(srcFlat.GetDataUtf16(), srcLen); + common::Span data(srcFlat.GetDataUtf16(), srcLen); return TrimBody(thread, src, data, mode); } } @@ -1041,7 +1042,7 @@ std::string EcmaStringAccessor::ToStdString(const JSThread *thread, StringConver } bool modify = (usage != StringConvertedUsage::PRINT); CVector buf; - Span sp = string_->ToUtf8Span(thread, buf, modify); + common::Span sp = string_->ToUtf8Span(thread, buf, modify); #if ENABLE_NEXT_OPTIMIZATION return std::string(reinterpret_cast(sp.data()), sp.size()); #else @@ -1080,7 +1081,7 @@ std::string EcmaStringAccessor::DebuggerToStdString(const JSThread *thread, Stri bool modify = (usage != StringConvertedUsage::PRINT); CVector buf; - Span sp = string_->DebuggerToUtf8Span(thread, buf, modify); + common::Span sp = string_->DebuggerToUtf8Span(thread, buf, modify); #if ENABLE_NEXT_OPTIMIZATION return std::string(reinterpret_cast(sp.data()), sp.size()); #else @@ -1100,7 +1101,7 @@ CString EcmaStringAccessor::ToCString(const JSThread *thread, StringConvertedUsa } bool modify = (usage != StringConvertedUsage::PRINT); CVector buf; - Span sp = string_->ToUtf8Span(thread, buf, modify, cesu8); + common::Span sp = string_->ToUtf8Span(thread, buf, modify, cesu8); #if ENABLE_NEXT_OPTIMIZATION return CString(reinterpret_cast(sp.data()), sp.size()); #else @@ -1135,13 +1136,13 @@ void EcmaStringAccessor::AppendToC16String(const JSThread *thread, C16String &st // In real world, space is usually utf8. if LIKELY(string_->IsUtf8()) { CVector buf; - const uint8_t *data = EcmaString::GetUtf8DataFlat(thread, string_, buf); + const uint8_t* data = EcmaString::GetUtf8DataFlat(thread, string_, buf); // only ascii codes, no need to convert to UTF-16, just append. AppendString(str, reinterpret_cast(data), GetLength()); } else { CVector buf; - const uint16_t *data = EcmaString::GetUtf16DataFlat(thread, string_, buf); - str.append(reinterpret_cast(data), GetLength()); + const uint16_t* data = EcmaString::GetUtf16DataFlat(thread, string_, buf); + str.append(reinterpret_cast(data), GetLength()); } } #endif diff --git a/ecmascript/ecma_string.h b/ecmascript/ecma_string.h index c57e4c8550b5093dbbd21f0b4d6d68f1bdb5c66e..4d6aad66e7b4f6358e570c19f0345d57e1b39fde 100755 --- a/ecmascript/ecma_string.h +++ b/ecmascript/ecma_string.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2021-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -21,11 +21,11 @@ #include #include "common_components/base/utf_helper.h" -#include "common_interfaces/objects/base_string.h" +#include "common_interfaces/objects/string/base_string.h" +#include "common_interfaces/objects/string/base_string-inl.h" #include "common_interfaces/objects/string/line_string.h" #include "common_interfaces/objects/string/sliced_string.h" #include "common_interfaces/objects/string/tree_string.h" -#include "common_interfaces/objects/string/base_string-inl1.h" #include "ecmascript/common.h" #include "ecmascript/ecma_macros.h" #include "ecmascript/js_hclass.h" @@ -178,7 +178,7 @@ private: inline const uint8_t *GetDataUtf8() const; inline const uint16_t *GetDataUtf16() const; - inline Span FastToUtf8Span() const; + inline common::Span FastToUtf8Span() const; // require is LineString inline uint8_t *GetDataUtf8Writable(); @@ -254,10 +254,7 @@ private: // Check that two spans are equal. Should have the same length. /* static */ template - static bool StringsAreEquals(Span &str1, Span &str2) - { - return BaseString::StringsAreEquals(str1, str2); - } + static bool StringsAreEquals(common::Span &str1, common::Span &str2); // Compares string1 + string2 by bytes, It doesn't check canonical unicode equivalence. bool EqualToSplicedString(const JSThread *thread, const EcmaString *str1, const EcmaString *str2); @@ -309,10 +306,10 @@ private: std::u16string ToU16String(const JSThread *thread, uint32_t len = 0); - Span ToUtf8Span(const JSThread *thread, CVector &buf, bool modify = true, - bool cesu8 = false); + common::Span ToUtf8Span(const JSThread *thread, CVector &buf, bool modify = true, + bool cesu8 = false); - Span DebuggerToUtf8Span(const JSThread *thread, CVector &buf, bool modify = true); + common::Span DebuggerToUtf8Span(const JSThread *thread, CVector &buf, bool modify = true); Span ToUtf16Span(const JSThread *thread, CVector &buf) { @@ -341,7 +338,8 @@ private: auto readBarrier = [thread](const void *obj, size_t offset) -> TaggedObject * { return Barriers::GetTaggedObject(thread, obj, offset); }; - ToBaseString()->WriteData(std::move(readBarrier), src->ToBaseString(), start, destSize, length); + LineString::Cast(ToBaseString())->WriteData(std::move(readBarrier), src->ToBaseString(), start, destSize, + length); } static bool CanBeCompressed(const uint8_t *utf8Data, uint32_t utf8Len); @@ -356,20 +354,21 @@ private: bool PUBLIC_API ToTypedArrayIndex(const JSThread *thread, uint32_t *index); - template - static EcmaString *TrimBody(const JSThread *thread, const JSHandle &src, Span &data, TrimMode mode); + template + static EcmaString* TrimBody(const JSThread* thread, const JSHandle& src, common::Span& data, + TrimMode mode); - static EcmaString *Trim(const JSThread *thread, const JSHandle &src, TrimMode mode = TrimMode::TRIM); + static EcmaString* Trim(const JSThread* thread, const JSHandle& src, TrimMode mode = TrimMode::TRIM); // memory block copy template - static bool MemCopyChars(Span &dst, size_t dstMax, Span &src, size_t count); + static bool MemCopyChars(common::Span &dst, size_t dstMax, common::Span &src, size_t count); template - static int32_t IndexOf(Span &lhsSp, Span &rhsSp, int32_t pos, int32_t max); + static int32_t IndexOf(common::Span &lhsSp, common::Span &rhsSp, int32_t pos, int32_t max); template - static int32_t LastIndexOf(Span &lhsSp, Span &rhsSp, int32_t pos); + static int32_t LastIndexOf(common::Span &lhsSp, common::Span &rhsSp, int32_t pos); bool IsFlat(const JSThread *thread) const; @@ -606,7 +605,7 @@ class TreeEcmaString : public EcmaString { private: using TaggedObject::SIZE; public: - DECL_VISIT_OBJECT(TreeString::FIRST_OFFSET, TreeString::SIZE); + DECL_VISIT_OBJECT(TreeString::LEFT_OFFSET, TreeString::SIZE); CAST_CHECK(TreeEcmaString, IsTreeString); @@ -640,7 +639,7 @@ public: auto readBarrier = [thread](const void* obj, size_t offset)-> TaggedObject* { return Barriers::GetTaggedObject(thread, obj, offset); }; - return JSTaggedValue(ToTreeString()->GetFirst(std::move(readBarrier))); + return JSTaggedValue(ToTreeString()->GetLeftSubString(std::move(readBarrier))); } template @@ -651,7 +650,7 @@ public: Barriers::SetObject(thread, obj, offset, reinterpret_cast(str)); } else { Barriers::SetPrimitive(obj, offset, reinterpret_cast(str)); } }; - ToTreeString()->SetFirst(std::move(writeBarrier), value->GetTaggedObject()); + ToTreeString()->SetLeftSubString(std::move(writeBarrier), value->GetTaggedObject()); } void SetFirst(const JSThread* thread, JSTaggedValue value, BarrierMode mode = WRITE_BARRIER) @@ -661,7 +660,7 @@ public: Barriers::SetObject(thread, obj, offset, reinterpret_cast(str)); } else { Barriers::SetPrimitive(obj, offset, reinterpret_cast(str)); } }; - ToTreeString()->SetFirst(std::move(writeBarrier), value.GetTaggedObject()); + ToTreeString()->SetLeftSubString(std::move(writeBarrier), value.GetTaggedObject()); }; JSTaggedValue GetSecond(const JSThread *thread) const @@ -669,7 +668,7 @@ public: auto readBarrier = [thread](const void* obj, size_t offset)-> TaggedObject* { return Barriers::GetTaggedObject(thread, obj, offset); }; - return JSTaggedValue(ToTreeString()->GetSecond(std::move(readBarrier))); + return JSTaggedValue(ToTreeString()->GetRightSubString(std::move(readBarrier))); } template @@ -680,7 +679,7 @@ public: Barriers::SetObject(thread, obj, offset, reinterpret_cast(str)); } else { Barriers::SetPrimitive(obj, offset, reinterpret_cast(str)); } }; - ToTreeString()->SetSecond(std::move(writeBarrier), value->GetTaggedObject()); + ToTreeString()->SetRightSubString(std::move(writeBarrier), value->GetTaggedObject()); } void SetSecond(const JSThread* thread, JSTaggedValue value, BarrierMode mode = WRITE_BARRIER) @@ -690,7 +689,7 @@ public: Barriers::SetObject(thread, obj, offset, reinterpret_cast(str)); } else { Barriers::SetPrimitive(obj, offset, reinterpret_cast(str)); } }; - ToTreeString()->SetSecond(std::move(writeBarrier), value.GetTaggedObject()); + ToTreeString()->SetRightSubString(std::move(writeBarrier), value.GetTaggedObject()); }; bool IsFlat(const JSThread *thread) const @@ -915,7 +914,7 @@ public: // not change string data structure. // if string is not flat, this func has low efficiency. - Span ToUtf8Span(const JSThread *thread, CVector &buf) + common::Span ToUtf8Span(const JSThread *thread, CVector &buf) { return string_->ToUtf8Span(thread, buf); } @@ -1164,14 +1163,7 @@ public: return EcmaString::Trim(thread, src, mode); } - static bool IsASCIICharacter(uint16_t data) - { - if (data == 0) { - return false; - } - // \0 is not considered ASCII in Ecma-Modified-UTF8 [only modify '\u0000'] - return data <= common::utf_helper::UTF8_1B_MAX; - } + static bool IsASCIICharacter(uint16_t data); bool IsFlat(const JSThread *thread) const { @@ -1198,7 +1190,7 @@ public: return string_->NotTreeString(); } - inline Span FastToUtf8Span() const; + inline common::Span FastToUtf8Span() const; // the returned string may be a linestring or slicestring!! PUBLIC_API static EcmaString *Flatten(const EcmaVM *vm, const JSHandle &string, diff --git a/ecmascript/ecma_string_table.h b/ecmascript/ecma_string_table.h index c9524bb1d9f3553f095a7c950eb2d22d0f8fb685..3c34cee9a3ba43f81a2806591211ea9a88cf81d9 100644 --- a/ecmascript/ecma_string_table.h +++ b/ecmascript/ecma_string_table.h @@ -28,7 +28,7 @@ #include "ecmascript/platform/mutex.h" #include "ecmascript/tagged_array.h" #include "common_interfaces/objects/base_string_table.h" -#include "common_interfaces/objects/string/base_string_declare.h" +#include "common_interfaces/objects/string/base_string.h" namespace panda::ecmascript { #if ENABLE_NEXT_OPTIMIZATION diff --git a/ecmascript/extractortool/tests/extractor_test.cpp b/ecmascript/extractortool/tests/extractor_test.cpp index 0fc2388a85380b622810860f081ae94ca63b7f73..33919ca5e15ce007b454da6a07c4b3aea0df9dfd 100644 --- a/ecmascript/extractortool/tests/extractor_test.cpp +++ b/ecmascript/extractortool/tests/extractor_test.cpp @@ -18,6 +18,7 @@ #include "ecmascript/extractortool/src/extractor.h" #include "ecmascript/tests/test_helper.h" +#include "securec.h" using namespace panda::ecmascript; diff --git a/ecmascript/global_env_constants.cpp b/ecmascript/global_env_constants.cpp index da1b2c02efdfdad1b1797e7d96a35a72ffd5d012..41e1a404f3edf6c8f05972645d982af75be9d00d 100644 --- a/ecmascript/global_env_constants.cpp +++ b/ecmascript/global_env_constants.cpp @@ -132,11 +132,11 @@ void GlobalEnvConstants::InitSharedRootsClasses(ObjectFactory *factory) factory->NewSEcmaReadOnlyHClass(hClass, FreeObject::SIZE, JSType::FREE_OBJECT_WITH_TWO_FIELD)); if (g_isEnableCMCGC) { SetConstant(ConstantIndex::LINE_STRING_CLASS_INDEX, - factory->InitHClassInCompositeBaseClass(hClass, common::CommonType::LINE_STRING)); + factory->InitHClassInCompositeBaseClass(hClass, common::ObjectType::LINE_STRING)); SetConstant(ConstantIndex::SLICED_STRING_CLASS_INDEX, - factory->InitHClassInCompositeBaseClass(hClass, common::CommonType::SLICED_STRING)); + factory->InitHClassInCompositeBaseClass(hClass, common::ObjectType::SLICED_STRING)); SetConstant(ConstantIndex::TREE_STRING_CLASS_INDEX, - factory->InitHClassInCompositeBaseClass(hClass, common::CommonType::TREE_STRING)); + factory->InitHClassInCompositeBaseClass(hClass, common::ObjectType::TREE_STRING)); } else { SetConstant(ConstantIndex::LINE_STRING_CLASS_INDEX, factory->NewSEcmaReadOnlyHClass(hClass, 0, JSType::LINE_STRING)); diff --git a/ecmascript/js_api/js_api_buffer.cpp b/ecmascript/js_api/js_api_buffer.cpp index 9c0359065ea145ee9c2eb4fe32cf9d6b3bf888e3..2fdd4cc9b626d46d76e83538a9054469aaa4d106 100644 --- a/ecmascript/js_api/js_api_buffer.cpp +++ b/ecmascript/js_api/js_api_buffer.cpp @@ -180,7 +180,7 @@ string_view FromStringBase64(JSThread *thread, const JSHandle &st { auto strAccessor = EcmaStringAccessor(JSHandle(str)); CVector buf; - Span sp = strAccessor.ToUtf8Span(thread, buf); + common::Span sp = strAccessor.ToUtf8Span(thread, buf); StringConverter::Base64Decode(string_view(reinterpret_cast(sp.data()), sp.size()), stringDecoded); return std::string_view(stringDecoded); } diff --git a/ecmascript/js_hclass-inl.h b/ecmascript/js_hclass-inl.h index ab5584bb2349eb0bc4e5e9db32aa3566b12d2f4f..5114fcd97d38cdd34f44492c1560600d2e54aaef 100644 --- a/ecmascript/js_hclass-inl.h +++ b/ecmascript/js_hclass-inl.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2024 Huawei Device Co., Ltd. + * Copyright (c) 2021-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -18,6 +18,7 @@ #include "ecmascript/js_hclass.h" +#include "common_interfaces/objects/string/line_string-inl.h" #include "ecmascript/byte_array.h" #include "ecmascript/ic/proto_change_details.h" #include "ecmascript/js_bigint.h" diff --git a/ecmascript/js_hclass.h b/ecmascript/js_hclass.h index 13ae3dd9adda37dcbe5809e2b8446b9facdd0a2c..4417205113cd498187790b2c8aea9274124b1e08 100644 --- a/ecmascript/js_hclass.h +++ b/ecmascript/js_hclass.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2024 Huawei Device Co., Ltd. + * Copyright (c) 2021-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -358,11 +358,11 @@ enum class JSType : uint8_t { PRESET_JSTYPE_DECL, }; -static_assert(static_cast(JSType::LINE_STRING) == static_cast(common::CommonType::LINE_STRING) && +static_assert(static_cast(JSType::LINE_STRING) == static_cast(common::ObjectType::LINE_STRING) && "line string type should be same with common type"); -static_assert(static_cast(JSType::SLICED_STRING) == static_cast(common::CommonType::SLICED_STRING) && +static_assert(static_cast(JSType::SLICED_STRING) == static_cast(common::ObjectType::SLICED_STRING) && "sliced string type should be same with common type"); -static_assert(static_cast(JSType::TREE_STRING) == static_cast(common::CommonType::TREE_STRING) && +static_assert(static_cast(JSType::TREE_STRING) == static_cast(common::ObjectType::TREE_STRING) && "tree string type should be same with common type"); struct TransitionResult { @@ -682,8 +682,8 @@ public: // These types are not complete hclass, does not has profile field. inline bool IsCompositeHClass() const { - common::CommonType jsType = static_cast(GetObjectType()); - return (common::CommonType::FIRST_OBJECT_TYPE <= jsType && jsType <= common::CommonType::LAST_OBJECT_TYPE); + common::ObjectType jsType = static_cast(GetObjectType()); + return (common::ObjectType::FIRST_OBJECT_TYPE <= jsType && jsType <= common::ObjectType::LAST_OBJECT_TYPE); } inline bool IsString() const diff --git a/ecmascript/js_runtime_options.h b/ecmascript/js_runtime_options.h index da92db275b4d4f7af717236d01544b7fb95141b7..4553004c24ec0390edde4e27dde627268a7049fe 100644 --- a/ecmascript/js_runtime_options.h +++ b/ecmascript/js_runtime_options.h @@ -254,6 +254,7 @@ enum CommandValues { class PUBLIC_API JSRuntimeOptions { public: JSRuntimeOptions(); + JSRuntimeOptions(const common::RuntimeParam ¶m) : param_(param) {} ~JSRuntimeOptions() = default; DEFAULT_COPY_SEMANTIC(JSRuntimeOptions); DEFAULT_MOVE_SEMANTIC(JSRuntimeOptions); diff --git a/ecmascript/js_tagged_value-inl.h b/ecmascript/js_tagged_value-inl.h index f07aaee73a09f6988a22e11b953e17b754fa0683..257d48f254f1006b888ddd1794d30c28845abbc4 100644 --- a/ecmascript/js_tagged_value-inl.h +++ b/ecmascript/js_tagged_value-inl.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2024 Huawei Device Co., Ltd. + * Copyright (c) 2021-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -1429,7 +1429,7 @@ inline JSTaggedNumber JSTaggedValue::StringToDouble(JSThread *thread, JSTaggedVa return JSTaggedNumber(0); } CVector buf; - Span str = EcmaStringAccessor(strObj).ToUtf8Span(thread, buf); + common::Span str = EcmaStringAccessor(strObj).ToUtf8Span(thread, buf); double d = base::NumberHelper::StringToDouble(str.begin(), str.end(), 0, base::ALLOW_BINARY + base::ALLOW_OCTAL + base::ALLOW_HEX); return JSTaggedNumber(d); diff --git a/ecmascript/js_tagged_value.cpp b/ecmascript/js_tagged_value.cpp index c00958702273a4b6b7f789aa4068d9e999af0a09..f75b6c754ae8e65e9853d0e40f12a537a3e6b0b0 100644 --- a/ecmascript/js_tagged_value.cpp +++ b/ecmascript/js_tagged_value.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2024 Huawei Device Co., Ltd. + * Copyright (c) 2021-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -1770,7 +1770,7 @@ JSTaggedNumber JSTaggedValue::StringToNumber(JSThread *thread, JSTaggedValue tag } } #endif - Span str = strAccessor.FastToUtf8Span(); + common::Span str = strAccessor.FastToUtf8Span(); if (strAccessor.GetLength() == 0) { return JSTaggedNumber(0); } @@ -1780,7 +1780,7 @@ JSTaggedNumber JSTaggedValue::StringToNumber(JSThread *thread, JSTaggedValue tag } } CVector buf; - Span str = strAccessor.ToUtf8Span(thread, buf); + common::Span str = strAccessor.ToUtf8Span(thread, buf); double d = base::NumberHelper::StringToDouble(str.begin(), str.end(), 0, base::ALLOW_BINARY + base::ALLOW_OCTAL + base::ALLOW_HEX); return JSTaggedNumber(d); diff --git a/ecmascript/jspandafile/js_pandafile_executor.cpp b/ecmascript/jspandafile/js_pandafile_executor.cpp index 99e95457d36d33807284d18207cab99c8ab4c2bc..b365ad3a6279af29257644d561bc2d04ccb2bba6 100644 --- a/ecmascript/jspandafile/js_pandafile_executor.cpp +++ b/ecmascript/jspandafile/js_pandafile_executor.cpp @@ -23,6 +23,7 @@ #include "ecmascript/module/module_tools.h" #include "ecmascript/checkpoint/thread_state_transition.h" #include "ecmascript/platform/pandafile.h" +#include "ecmascript/base/number_helper.h" namespace panda::ecmascript { using PathHelper = base::PathHelper; diff --git a/ecmascript/mem/c_string.cpp b/ecmascript/mem/c_string.cpp index 6b14c004b5f7b7031b3eb2bb14e2726c9c476423..ad34e0f386468ad2a17052055e398d1baa224a2b 100644 --- a/ecmascript/mem/c_string.cpp +++ b/ecmascript/mem/c_string.cpp @@ -260,7 +260,7 @@ void ConvertQuotedAndAppendToCString(const JSThread *thread, CString &str, const uint32_t strLen = EcmaStringAccessor(const_cast(s)).GetLength(); CVector buf; const uint8_t *data = EcmaStringAccessor::GetUtf8DataFlat(thread, s, buf); - const Span dataSpan(data, strLen); + const common::Span dataSpan(data, strLen); base::JsonHelper::AppendValueToQuotedString(dataSpan, str); } @@ -272,12 +272,12 @@ void ConvertQuotedAndAppendToC16String(const JSThread *thread, C16String &str, c if (EcmaStringAccessor(const_cast(s)).IsUtf8()) { CVector buf; const uint8_t *data = EcmaStringAccessor::GetUtf8DataFlat(thread, s, buf); - const Span dataSpan(data, strLen); + const common::Span dataSpan(data, strLen); base::JsonHelper::AppendValueToQuotedString(dataSpan, str); } else { CVector buf; const uint16_t *data = EcmaStringAccessor::GetUtf16DataFlat(thread, s, buf); - const Span dataSpan(data, strLen); + const common::Span dataSpan(data, strLen); base::JsonHelper::AppendValueToQuotedString(dataSpan, str); } } diff --git a/ecmascript/mem/cmc_gc/hooks.cpp b/ecmascript/mem/cmc_gc/hooks.cpp index 51229f4e0b1221ce75c5d3e3b740f47388f5628b..33496d796e68be4bea7ff6f3bf2fc1cfc7de83fe 100644 --- a/ecmascript/mem/cmc_gc/hooks.cpp +++ b/ecmascript/mem/cmc_gc/hooks.cpp @@ -16,9 +16,12 @@ #include "common_components/common_runtime/hooks.h" #include +#include #include "common_components/heap/heap.h" #include "ecmascript/base/config.h" +#include "ecmascript/ecma_vm.h" +#include "ecmascript/ecma_global_storage.h" #include "ecmascript/free_object.h" #include "ecmascript/mem/object_xray.h" #include "ecmascript/mem/tagged_object.h" @@ -35,6 +38,10 @@ using panda::ecmascript::ObjectSlot; using panda::ecmascript::JSThread; using panda::ecmascript::TaggedType; +// A fake EcmaVM which will never used, only for unify the BaseRuntime::Init&Fini +static panda::ecmascript::EcmaVM *g_fakeEcmaVM = nullptr; +static std::mutex g_rtMutexForStatic; + class CMCRootVisitor final : public panda::ecmascript::RootVisitor { public: inline explicit CMCRootVisitor(const RefFieldVisitor &visitor): visitor_(visitor) {}; @@ -100,6 +107,11 @@ private: void VisitBaseRoots(const RefFieldVisitor &visitorFunc) { + // todo 梁婷婷 + if (!panda::ecmascript::Runtime::HasInstance()) { + return; + } + BaseClassRoots &baseClassRoots = BaseRuntime::GetInstance()->GetBaseClassRoots(); // When visit roots, the language of the object is not used, so using the visitorFunc will work for // both dynamic and static. @@ -108,6 +120,10 @@ void VisitBaseRoots(const RefFieldVisitor &visitorFunc) void VisitDynamicGlobalRoots(const RefFieldVisitor &visitorFunc) { + if (!panda::ecmascript::Runtime::HasInstance()) { + return; + } + OHOS_HITRACE(HITRACE_LEVEL_COMMERCIAL, "CMCGC::VisitDynamicGlobalRoot", ""); CMCRootVisitor visitor(visitorFunc); @@ -126,6 +142,9 @@ void VisitDynamicGlobalRoots(const RefFieldVisitor &visitorFunc) void VisitDynamicLocalRoots(const RefFieldVisitor &visitorFunc) { + if (!panda::ecmascript::Runtime::HasInstance()) { + return; + } OHOS_HITRACE(HITRACE_LEVEL_COMMERCIAL, "CMCGC::VisitDynamicLocalRoots", ""); CMCRootVisitor visitor(visitorFunc); panda::ecmascript::Runtime *runtime = panda::ecmascript::Runtime::GetInstance(); @@ -156,6 +175,9 @@ void VisitDynamicWeakGlobalRoots(const common::WeakRefFieldVisitor &visitorFunc) void VisitDynamicWeakGlobalRootsOld(const common::WeakRefFieldVisitor &visitorFunc) { OHOS_HITRACE(HITRACE_LEVEL_COMMERCIAL, "CMCGC::VisitDynamicWeakGlobalRootsOld", ""); + if (!panda::ecmascript::Runtime::HasInstance()) { + return; + } CMCWeakVisitor visitor(visitorFunc); panda::ecmascript::SharedHeap::GetInstance()->IteratorNativePointerList(visitor); @@ -178,6 +200,9 @@ void InvokeSharedNativePointerCallbacks() void VisitDynamicWeakLocalRoots(const common::WeakRefFieldVisitor &visitorFunc) { + if (!panda::ecmascript::Runtime::HasInstance()) { + return; + } OHOS_HITRACE(HITRACE_LEVEL_COMMERCIAL, "CMCGC::VisitDynamicWeakLocalRoots", ""); CMCWeakVisitor visitor(visitorFunc); panda::ecmascript::Runtime *runtime = panda::ecmascript::Runtime::GetInstance(); @@ -223,6 +248,9 @@ void VisitDynamicConcurrentRoots(const RefFieldVisitor &visitorFunc) void VisitDynamicThreadRoot(const RefFieldVisitor &visitorFunc, void *vm) { + if (!panda::ecmascript::Runtime::HasInstance()) { + return; + } OHOS_HITRACE(HITRACE_LEVEL_COMMERCIAL, "CMCGC::VisitDynamicThreadRoot", ""); auto ecmaVm = reinterpret_cast(vm); if (!ecmaVm->GetAssociatedJSThread()->ReadyForGCIterating()) { @@ -242,6 +270,9 @@ void VisitDynamicThreadRoot(const RefFieldVisitor &visitorFunc, void *vm) void VisitDynamicWeakThreadRoot(const WeakRefFieldVisitor &visitorFunc, void *vm) { + if (!panda::ecmascript::Runtime::HasInstance()) { + return; + } OHOS_HITRACE(HITRACE_LEVEL_COMMERCIAL, "CMCGC::VisitDynamicWeakThreadRoot", ""); auto ecmaVm = reinterpret_cast(vm); auto thread = ecmaVm->GetAssociatedJSThread(); @@ -340,6 +371,29 @@ bool IsPostForked() return panda::ecmascript::Runtime::GetInstance()->IsPostForked(); } +void CheckAndInitBaseRuntime(const RuntimeParam ¶m) +{ + std::lock_guard guard(g_rtMutexForStatic); + if (BaseRuntime::GetInstance()->HasBeenInitialized()) { + // BaseRuntime is inited from Dynamic + return; + } + panda::ecmascript::JSRuntimeOptions options(param); + g_fakeEcmaVM = panda::ecmascript::EcmaVM::Create(options); +} + +void CheckAndFiniBaseRuntime() +{ + std::lock_guard guard(g_rtMutexForStatic); + if (g_fakeEcmaVM == nullptr) { + // BaseRuntime is inited from Dynamic + return; + } + g_fakeEcmaVM->GetJSThread()->ManagedCodeBegin(); + panda::ecmascript::EcmaVM::Destroy(g_fakeEcmaVM); + g_fakeEcmaVM = nullptr; +} + void SetBaseAddress(uintptr_t base) { // Please be careful about reentrant @@ -358,4 +412,20 @@ bool IsMachineCodeObject(uintptr_t objPtr) return value.IsMachineCodeObject(); } +void AddXRefToDynamicRoots() +{ + panda::ecmascript::Runtime *runtime = panda::ecmascript::Runtime::GetInstance(); + runtime->GCIterateThreadList([&](JSThread *thread) { + thread->SetNodeKind(panda::ecmascript::NodeKind::NORMAL_NODE); + }); +} + +void RemoveXRefFromDynamicRoots() +{ + panda::ecmascript::Runtime *runtime = panda::ecmascript::Runtime::GetInstance(); + runtime->GCIterateThreadList([&](JSThread *thread) { + thread->SetNodeKind(panda::ecmascript::NodeKind::UNIFIED_NODE); + }); +} + } // namespace panda diff --git a/ecmascript/mem/dynamic_object_operator.cpp b/ecmascript/mem/dynamic_object_operator.cpp index 138851d21afdae66514924649d004dff50e6a51a..fec7a94d67302af089fa805414d9fabede556450 100644 --- a/ecmascript/mem/dynamic_object_operator.cpp +++ b/ecmascript/mem/dynamic_object_operator.cpp @@ -15,7 +15,9 @@ #include "ecmascript/cross_vm/js_tagged_value_hybrid-inl.h" #include "ecmascript/mem/dynamic_object_operator.h" + #include "ecmascript/mem/object_xray.h" +#include "ecmascript/runtime.h" namespace panda::ecmascript { @@ -28,6 +30,26 @@ void DynamicObjectOperator::Initialize() } } +void DynamicObjectOperator::IterateXRef([[maybe_unused]] const BaseObject *object, + [[maybe_unused]] const common::RefFieldVisitor &visitor) const +{ + #if defined(PANDA_JS_ETS_HYBRID_MODE) && defined(USE_CMC_GC) + if (g_isEnableCMCGC) { + JSTaggedValue value(reinterpret_cast(const_cast(object))); + if (value.IsJSXRefObject()) { + Runtime::GetInstance()->GetSTSVMInterface()->MarkFromObject( + JSObject::Cast(TaggedObject::Cast(object)) + ->GetNativePointerField( + Runtime::GetInstance()->GetMainThread(), 0), visitor); + } + } else { + std::abort(); + } +#else + std::abort(); +#endif +} + void RefFieldObjectVisitor::VisitObjectRangeImpl(BaseObject *root, uintptr_t startAddr, uintptr_t endAddr, VisitObjectArea area) { diff --git a/ecmascript/mem/dynamic_object_operator.h b/ecmascript/mem/dynamic_object_operator.h index b2983f6768423e23992df5f09e0e09992ed45eb9..d147e87efaa86d0ef28fccd10764c4b9b0484e47 100644 --- a/ecmascript/mem/dynamic_object_operator.h +++ b/ecmascript/mem/dynamic_object_operator.h @@ -100,6 +100,12 @@ public: return hclass->GetClass()->IsHClass(); } + void ForEachRefFieldSkipReferent(const BaseObject *object, const common::RefFieldVisitor &visitor) const override + { + // Referent is only used in static + ForEachRefField(object, visitor); + } + void ForEachRefField(const BaseObject *object, const common::RefFieldVisitor &visitor) const override { auto freeObject = FreeObject::Cast(reinterpret_cast(object)); @@ -120,6 +126,8 @@ public: return size; } + void IterateXRef(const BaseObject *object, const common::RefFieldVisitor &visitor) const override; + size_t GetSize(const BaseObject *object) const override { ASSERT(!g_isEnableCMCGC || !object->IsForwarded()); diff --git a/ecmascript/mem/heap.cpp b/ecmascript/mem/heap.cpp index 4aa241ae1878d325cfb14905af846ff6e6a3ae4b..d8a258734c2dfd347c2262462aad13387cfadc58 100644 --- a/ecmascript/mem/heap.cpp +++ b/ecmascript/mem/heap.cpp @@ -1484,6 +1484,7 @@ void Heap::CollectGarbage(TriggerGCType gcType, GCReason reason) async = false; } common::BaseRuntime::RequestGC(cmcReason, async, common::GC_TYPE_FULL); + ThreadNativeScope scope(thread_); return; } CollectGarbageImpl(gcType, reason); diff --git a/ecmascript/mem/tagged_state_word.h b/ecmascript/mem/tagged_state_word.h index 402a3158b8e3cffdb56cb0dc86c1cc56e9663403..89919b5714fb721d35e20252514d27b73e2c556d 100644 --- a/ecmascript/mem/tagged_state_word.h +++ b/ecmascript/mem/tagged_state_word.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2024 Huawei Device Co., Ltd. + * Copyright (c) 2021-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -103,7 +103,8 @@ private: friend class TaggedObject; }; static_assert(sizeof(TaggedStateWord) == sizeof(uint64_t), "Excepts 8 bytes"); -static_assert(common::BaseStateWord::PADDING_WIDTH == 60, "Excepts 60 bits"); +static_assert(common::BaseStateWord::BASECLASS_WIDTH == 48, "Excepts 48 bits"); +static_assert(common::BaseStateWord::PADDING_WIDTH == 12, "Excepts 12 bits"); static_assert(common::BaseStateWord::FORWARD_WIDTH == 2, "Excepts 2 bits"); static_assert(common::BaseStateWord::LANGUAGE_WIDTH == 2, "Excepts 2 bits"); } // namespace panda::ecmascript diff --git a/ecmascript/module/accessor/module_data_accessor.h b/ecmascript/module/accessor/module_data_accessor.h index f8222e89fb8ef2d9e8b910309ea9e98952404da6..8d98a8e284950fefc6ae955b1029ade08e99a070 100644 --- a/ecmascript/module/accessor/module_data_accessor.h +++ b/ecmascript/module/accessor/module_data_accessor.h @@ -31,8 +31,8 @@ class ModuleDataAccessor { public: ModuleDataAccessor(const JSPandaFile *pandaFile, panda_file::File::EntityId module_data_id); ~ModuleDataAccessor() = default; - DEFAULT_MOVE_CTOR(ModuleDataAccessor) - DEFAULT_COPY_CTOR(ModuleDataAccessor) + DEFAULT_MOVE_CTOR(ModuleDataAccessor); + DEFAULT_COPY_CTOR(ModuleDataAccessor); NO_MOVE_OPERATOR(ModuleDataAccessor); NO_COPY_OPERATOR(ModuleDataAccessor); diff --git a/ecmascript/napi/include/jsnapi_expo.h b/ecmascript/napi/include/jsnapi_expo.h index e899866f31f77c3f18607a0d0970791622d9a916..4dd9ee6af12fc61d31ec04d1ca32754538ae125c 100644 --- a/ecmascript/napi/include/jsnapi_expo.h +++ b/ecmascript/napi/include/jsnapi_expo.h @@ -1403,7 +1403,10 @@ private: JSThread *thread_ {nullptr}; uint16_t oldThreadState_ {0}; uint32_t isEnableCMCGC_ {0}; - uint32_t hasSwitchState_ {0}; + uint32_t hasSwitchState_{0}; + // This is a temporary impl to adapt interop to cmc, because some interop + // call napi without transfering to NATIVE + [[maybe_unused]] bool extraCoroutineSwitchedForInterop_{false}; }; /** diff --git a/ecmascript/napi/jsnapi_expo.cpp b/ecmascript/napi/jsnapi_expo.cpp index de3a2d617a4e94ce3bf08bbc3274a5dc8e10436a..8f3c94a8347c278b73a4ba4e9b413a59b9266909 100644 --- a/ecmascript/napi/jsnapi_expo.cpp +++ b/ecmascript/napi/jsnapi_expo.cpp @@ -4322,6 +4322,11 @@ JsiFastNativeScope::JsiFastNativeScope(const EcmaVM *vm) hasSwitchState_ = oldThreadState_ != static_cast(ecmascript::ThreadState::RUNNING); } else { isEnableCMCGC_ = true; +#ifdef PANDA_JS_ETS_HYBRID_MODE + // This is a temporary impl to adapt interop to cmc, because some interop call napi + // without transfering to NATIVE + extraCoroutineSwitchedForInterop_ = InterOpCoroutineToNative(thread_->GetThreadHolder()); +#endif hasSwitchState_ = thread_->GetThreadHolder()->TransferToRunningIfInNative(); } } @@ -4335,6 +4340,11 @@ JsiFastNativeScope::~JsiFastNativeScope() thread_->GetThreadHolder()->TransferToNative(); } } +#if defined(PANDA_JS_ETS_HYBRID_MODE) + if (isEnableCMCGC_ && extraCoroutineSwitchedForInterop_) { + InterOpCoroutineToRunning(thread_->GetThreadHolder()); + } +#endif } // ------------------------------------ JsiRuntimeCallInfo ----------------------------------------------- diff --git a/ecmascript/object_factory.h b/ecmascript/object_factory.h index a764282ca6f2203e6b0061061b2e31b84cb1507b..b6db4f9677b75333278136e865419247c09ac556 100644 --- a/ecmascript/object_factory.h +++ b/ecmascript/object_factory.h @@ -818,7 +818,7 @@ public: JSHandle NewSEcmaReadOnlyHClass(JSHClass *hclass, uint32_t size, JSType type, uint32_t inlinedProps = JSHClass::DEFAULT_CAPACITY_OF_IN_OBJECTS); - JSTaggedValue InitHClassInCompositeBaseClass(JSHClass* hclass, common::CommonType type); + JSTaggedValue InitHClassInCompositeBaseClass(JSHClass* hclass, common::ObjectType type); JSHandle NewSEcmaReadOnlySharedHClass(JSHClass *hclass, uint32_t size, JSType type, uint32_t inlinedProps = JSHClass::DEFAULT_CAPACITY_OF_IN_OBJECTS); diff --git a/ecmascript/pgo_profiler/prof_dump/BUILD.gn b/ecmascript/pgo_profiler/prof_dump/BUILD.gn index 3718e03227419cb8b78aeee7a2bd2dce0282fd15..2f69e951b2300380869a1461d781497aa0f67f80 100644 --- a/ecmascript/pgo_profiler/prof_dump/BUILD.gn +++ b/ecmascript/pgo_profiler/prof_dump/BUILD.gn @@ -55,9 +55,7 @@ ohos_executable("profdump") { } if (ets_runtime_enable_cmc_gc) { - if (ark_hybrid) { - deps += [ "$ark_root/static_core/runtime:libarkruntime_set_static" ] - } + deps += [ "$js_root:libcommon_components_set" ] } # hiviewdfx libraries diff --git a/ecmascript/regexp/regexp_parser_cache.cpp b/ecmascript/regexp/regexp_parser_cache.cpp index 4fdcb517242aeef9c1e0caeadb3df2fde746206d..e12425f42f9cd326637929c0f758aea9a05329a1 100644 --- a/ecmascript/regexp/regexp_parser_cache.cpp +++ b/ecmascript/regexp/regexp_parser_cache.cpp @@ -14,6 +14,7 @@ */ #include "ecmascript/regexp/regexp_parser_cache.h" +#include "common_interfaces/objects/string/line_string-inl.h" namespace panda::ecmascript { RegExpParserCache::RegExpParserCache() diff --git a/ecmascript/runtime.cpp b/ecmascript/runtime.cpp index 9bfb0650b1acbf014cf24d724de134f05290e809..c8742983618fc981eab8eabc85ec0b79e59b5c92 100644 --- a/ecmascript/runtime.cpp +++ b/ecmascript/runtime.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 Huawei Device Co., Ltd. + * Copyright (c) 2024-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -54,6 +54,11 @@ Runtime *Runtime::GetInstance() return instance_; } +bool Runtime::HasInstance() +{ + return instance_ != nullptr; +} + Runtime::~Runtime() { LockHolder lock(constpoolLock_); @@ -88,7 +93,7 @@ void Runtime::CreateIfFirstVm(const JSRuntimeOptions &options) LOG_ECMA(INFO) << "start run with cmc gc"; // SetConfigHeapSize for cmc gc, pc and persist config may change heap size. const_cast(options).SetConfigHeapSize(MemMapAllocator::GetInstance()->GetCapacity()); - common::BaseRuntime::GetInstance()->Init(options.GetRuntimeParam()); + common::BaseRuntime::GetInstance()->InitFromDynamic(options.GetRuntimeParam()); common::g_enableGCTimeoutCheck = options.IsEnableGCTimeoutCheck(); #if defined(ECMASCRIPT_SUPPORT_HEAPPROFILER) common::HeapProfilerListener::GetInstance().RegisterOutOfMemoryEventCb( @@ -194,7 +199,7 @@ void Runtime::DestroyIfLastVm() DaemonThread::DestroyInstance(); if (g_isEnableCMCGC) { // Finish common::BaseRuntime after daemon thread because it will unregister mutator - common::BaseRuntime::GetInstance()->Fini(); + common::BaseRuntime::GetInstance()->FiniFromDynamic(); } SharedHeap::DestroyInstance(); AnFileDataManager::GetInstance()->SafeDestroyAllData(); diff --git a/ecmascript/runtime.h b/ecmascript/runtime.h index 37f08682c8d3258b20242ab09058c4ec25415a59..a2a208cc6580ce00e4d77ae3ead93ba9d94f96b0 100644 --- a/ecmascript/runtime.h +++ b/ecmascript/runtime.h @@ -17,6 +17,9 @@ #define ECMASCRIPT_RUNTIME_H #include "common_interfaces/base_runtime.h" +#ifdef PANDA_JS_ETS_HYBRID_MODE +#include "ecmascript/cross_vm/cross_vm_operator.h" +#endif #include "ecmascript/ecma_string_table.h" #include "ecmascript/global_env_constants.h" #include "ecmascript/js_runtime_options.h" @@ -43,6 +46,7 @@ using ReleaseSecureMemCallback = std::function; class Runtime { public: PUBLIC_API static Runtime *GetInstance(); + PUBLIC_API static bool HasInstance(); static void CreateIfFirstVm(const JSRuntimeOptions &options); static void DestroyIfLastVm(); @@ -310,6 +314,17 @@ public: { isHybridVm_ = isHybridVm; } +#ifdef PANDA_JS_ETS_HYBRID_MODE + void SetSTSVMInterface(arkplatform::STSVMInterface *stsIface) + { + stsVMInterface_ = stsIface; + } + + arkplatform::STSVMInterface *GetSTSVMInterface() const + { + return stsVMInterface_; + } +#endif uint32_t AddIncompatibleEvent(DFXHiSysEvent::IncompatibleType type) { @@ -396,6 +411,9 @@ private: static Mutex *vmCreationLock_; static Runtime *instance_; static common::BaseRuntime *baseInstance_; +#ifdef PANDA_JS_ETS_HYBRID_MODE + arkplatform::STSVMInterface *stsVMInterface_ {nullptr}; +#endif // for string cache JSTaggedValue *externalRegisteredStringTable_ {nullptr}; diff --git a/ecmascript/shared_object_factory.cpp b/ecmascript/shared_object_factory.cpp index c11261b5d6aac483520ed90a99bb903adca2b6d6..c46bcaabf63d3c3a15d5cfddffaef184b45db4d0 100644 --- a/ecmascript/shared_object_factory.cpp +++ b/ecmascript/shared_object_factory.cpp @@ -186,7 +186,7 @@ JSHandle ObjectFactory::NewSEcmaReadOnlySharedHClass(JSHClass *hclass, return newClass; } -JSTaggedValue ObjectFactory::InitHClassInCompositeBaseClass(JSHClass* hclass, common::CommonType type) +JSTaggedValue ObjectFactory::InitHClassInCompositeBaseClass(JSHClass* hclass, common::ObjectType type) { common::BaseClassRoots& classRoots = common::BaseRuntime::GetInstance()->GetBaseClassRoots(); auto* newClass = reinterpret_cast(classRoots.GetBaseClass(type)); diff --git a/ecmascript/stubs/runtime_stubs.cpp b/ecmascript/stubs/runtime_stubs.cpp index 8096e8cc1ed468a0c05eb6b3807aa95a2276439b..18a2f8380bd43b2d038dc98dced99e810c83392a 100644 --- a/ecmascript/stubs/runtime_stubs.cpp +++ b/ecmascript/stubs/runtime_stubs.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2024 Huawei Device Co., Ltd. + * Copyright (c) 2021-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -3218,7 +3218,6 @@ DEF_RUNTIME_STUBS(ContainerRBTreeForEach) return JSTaggedValue::True().GetRawData(); } - DEF_RUNTIME_STUBS(GetOrInternStringFromHashTrieTable) { RUNTIME_STUBS_HEADER(GetOrInternStringFromHashTrieTable); @@ -3609,7 +3608,7 @@ JSTaggedValue RuntimeStubs::NumberHelperStringToDouble(uintptr_t argGlue, EcmaSt DISALLOW_GARBAGE_COLLECTION; CVector buf; JSThread *thread = JSThread::GlueToJSThread(argGlue); - Span str = EcmaStringAccessor(numberString).ToUtf8Span(thread, buf); + common::Span str = EcmaStringAccessor(numberString).ToUtf8Span(thread, buf); if (base::NumberHelper::IsEmptyString(str.begin(), str.end())) { return base::BuiltinsBase::GetTaggedDouble(base::NAN_VALUE); } @@ -3892,10 +3891,10 @@ int32_t RuntimeStubs::StringGetStart(bool isUtf8, EcmaString *srcString, int32_t { DISALLOW_GARBAGE_COLLECTION; if (isUtf8) { - Span data(EcmaStringAccessor(srcString).GetDataUtf8() + startIndex, length); + common::Span data(EcmaStringAccessor(srcString).GetDataUtf8() + startIndex, length); return static_cast(base::StringHelper::GetStart(data, length)); } else { - Span data(EcmaStringAccessor(srcString).GetDataUtf16() + startIndex, length); + common::Span data(EcmaStringAccessor(srcString).GetDataUtf16() + startIndex, length); return static_cast(base::StringHelper::GetStart(data, length)); } } @@ -3905,10 +3904,10 @@ int32_t RuntimeStubs::StringGetEnd(bool isUtf8, EcmaString *srcString, { DISALLOW_GARBAGE_COLLECTION; if (isUtf8) { - Span data(EcmaStringAccessor(srcString).GetDataUtf8() + startIndex, length); + common::Span data(EcmaStringAccessor(srcString).GetDataUtf8() + startIndex, length); return base::StringHelper::GetEnd(data, start, length); } else { - Span data(EcmaStringAccessor(srcString).GetDataUtf16() + startIndex, length); + common::Span data(EcmaStringAccessor(srcString).GetDataUtf16() + startIndex, length); return base::StringHelper::GetEnd(data, start, length); } } diff --git a/ecmascript/tagged_dictionary.cpp b/ecmascript/tagged_dictionary.cpp index b93c90ef2903379265fd0c4eef81c474094f8e44..63b6d9d741240e9cf7ca78b29300873f5300ac32 100644 --- a/ecmascript/tagged_dictionary.cpp +++ b/ecmascript/tagged_dictionary.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * Copyright (c) 2021-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -57,8 +57,8 @@ bool NameDictionary::IsMatch(const uint8_t* str, int size, const JSTaggedValue & } EcmaString *keyString = reinterpret_cast(other.GetTaggedObject()); - Span data1(EcmaStringAccessor(keyString).GetDataUtf8(), keyString->GetLength()); - Span data2(str, size); + common::Span data1(EcmaStringAccessor(keyString).GetDataUtf8(), keyString->GetLength()); + common::Span data2(str, size); if (data1.Size() != data2.Size()) { return false; } diff --git a/ecmascript/tests/BUILD.gn b/ecmascript/tests/BUILD.gn index c601aed3d39039d52e8402a2d34f6c8033f7b1d9..335e09e79c35eb1dd413b09ea5f715d113fc6293 100644 --- a/ecmascript/tests/BUILD.gn +++ b/ecmascript/tests/BUILD.gn @@ -1518,6 +1518,32 @@ host_unittest_action("Dynamic_Object_Accessor_Test") { deps += hiviewdfx_deps } +host_unittest_action("Dynamic_Object_Accessor_Util_Test") { + module_out_path = module_output_path + + sources = [ + # test file + "dynamic_object_accessor_util_test.cpp", + ] + + configs = [ + "../../:ecma_test_config", + "../../:icu_path_test_config", + ] + + deps = [ "../../:libark_jsruntime_test" ] + + # hiviewdfx libraries + external_deps = hiviewdfx_ext_deps + external_deps += [ + "icu:shared_icui18n", + "icu:shared_icuuc", + "runtime_core:libarkassembler_static", + "runtime_core:libarkverifier", + ] + deps += hiviewdfx_deps +} + host_unittest_action("JS_Object_Test") { module_out_path = module_output_path @@ -3827,6 +3853,7 @@ group("host_unittest") { ":Sendable_JsSendableArrayBuffer_TestAction", ":Sendable_JsSharedArray_TestAction", ":Sendable_SharedObjectFactory_TestAction", + ":Dynamic_Object_Accessor_Util_TestAction", ] if (is_mac) { diff --git a/ecmascript/tests/base_string_test.cpp b/ecmascript/tests/base_string_test.cpp index fe3f069f78ca6be1b5cb465c2c35efb7289a2967..054a96df609ed7b354e61dee757644c395a77b23 100644 --- a/ecmascript/tests/base_string_test.cpp +++ b/ecmascript/tests/base_string_test.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2021-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -14,7 +14,7 @@ */ #include "ecmascript/ecma_string-inl.h" -#include "common_interfaces/objects/string/base_string_impl.h" +#include "common_interfaces/objects/string/base_string-inl.h" #include "ecmascript/object_factory.h" #include "ecmascript/tests/ecma_test_common.h" @@ -695,12 +695,12 @@ namespace panda::test { instance, &arrayU8WriteFrom[0], lengthEcmaStrU8WriteFrom, true)); size_t sizeEcmaStrU8WriteTo = 5; - JSHandle handleEcmaStrAllocTrueWriteTo(thread, + JSHandle handleEcmaStrAllocTrueWriteTo(thread, EcmaStringAccessor::CreateLineString( instance, sizeEcmaStrU8WriteTo, true)); uint32_t indexStartWriteFromArrayU8 = 2; uint32_t lengthWriteFromArrayU8 = 2; - handleEcmaStrAllocTrueWriteTo->ToBaseString()->WriteData( + LineString::Cast(handleEcmaStrAllocTrueWriteTo->ToBaseString())->WriteData( LoadTBarrier(), handleEcmaStrU8WriteFrom->ToBaseString(), indexStartWriteFromArrayU8, sizeEcmaStrU8WriteTo, lengthWriteFromArrayU8); for (uint32_t i = 0; i < lengthWriteFromArrayU8; i++) { @@ -722,11 +722,11 @@ namespace panda::test { // WriteData(). From char to EcmaString made by CreateLineString( , true, ). char u8Write = 'a'; size_t sizeEcmaStrU8WriteTo = 5; - JSHandle handleEcmaStrAllocTrueWriteTo(thread, + JSHandle handleEcmaStrAllocTrueWriteTo(thread, EcmaStringAccessor::CreateLineString( instance, sizeEcmaStrU8WriteTo, true)); uint32_t indexAtWriteFromU8 = 4; - handleEcmaStrAllocTrueWriteTo->ToBaseString()->WriteData(indexAtWriteFromU8, u8Write); + LineString::Cast(handleEcmaStrAllocTrueWriteTo->ToBaseString())->Set(indexAtWriteFromU8, u8Write); EXPECT_EQ(handleEcmaStrAllocTrueWriteTo->ToBaseString()->At(LoadTBarrier(), indexAtWriteFromU8), u8Write); } @@ -749,12 +749,12 @@ namespace panda::test { instance, &arrayU16WriteFrom[0], lengthEcmaStrU16WriteFrom, false)); size_t sizeEcmaStrU16WriteTo = 10; - JSHandle handleEcmaStrU16WriteTo(thread, + JSHandle handleEcmaStrU16WriteTo(thread, EcmaStringAccessor::CreateLineString( instance, sizeEcmaStrU16WriteTo, false)); uint32_t indexStartWriteFromArrayU16 = 3; uint32_t numBytesWriteFromArrayU16 = 2 * 3; - handleEcmaStrU16WriteTo->ToBaseString()->WriteData(LoadTBarrier(), handleEcmaStrU16WriteFrom->ToBaseString(), + handleEcmaStrU16WriteTo->ToLineString()->WriteData(LoadTBarrier(), handleEcmaStrU16WriteFrom->ToBaseString(), indexStartWriteFromArrayU16, sizeEcmaStrU16WriteTo, numBytesWriteFromArrayU16); for (uint32_t i = 0; i < (numBytesWriteFromArrayU16 / 2); i++) { @@ -780,14 +780,14 @@ namespace panda::test { instance, &arrayU8WriteFrom[0], lengthEcmaStrU8WriteFrom, true)); size_t sizeEcmaStrU16WriteTo = 10; - JSHandle handleEcmaStrU16WriteTo(thread, + JSHandle handleEcmaStrU16WriteTo(thread, EcmaStringAccessor::CreateLineString( instance, sizeEcmaStrU16WriteTo, false)); uint32_t indexStartWriteFromU8ToU16 = 1; uint32_t numBytesWriteFromU8ToU16 = 4; - handleEcmaStrU16WriteTo->ToBaseString()->WriteData(LoadTBarrier(), handleEcmaStrU8WriteFrom->ToBaseString(), - indexStartWriteFromU8ToU16, sizeEcmaStrU16WriteTo, - numBytesWriteFromU8ToU16); + LineString::Cast(handleEcmaStrU16WriteTo->ToBaseString())->WriteData(LoadTBarrier(), + handleEcmaStrU8WriteFrom->ToBaseString(), indexStartWriteFromU8ToU16, sizeEcmaStrU16WriteTo, + numBytesWriteFromU8ToU16); for (uint32_t i = 0; i < numBytesWriteFromU8ToU16; i++) { EXPECT_EQ(handleEcmaStrU16WriteTo->ToBaseString()->At(LoadTBarrier(), i + indexStartWriteFromU8ToU16), handleEcmaStrU8WriteFrom->ToBaseString()->At(LoadTBarrier(), i)); @@ -805,13 +805,13 @@ namespace panda::test { { // WriteData(). From char to EcmaString made by CreateLineString( , false, ). size_t sizeEcmaStrU16WriteTo = 10; - JSHandle handleEcmaStrU16WriteTo(thread, + JSHandle handleEcmaStrU16WriteTo(thread, EcmaStringAccessor::CreateLineString( instance, sizeEcmaStrU16WriteTo, false)); char u8Write = 'a'; uint32_t indexAt = 4; - handleEcmaStrU16WriteTo->ToBaseString()->WriteData(indexAt, u8Write); - EXPECT_EQ(handleEcmaStrU16WriteTo->ToBaseString()->At(LoadTBarrier(), indexAt), u8Write); + handleEcmaStrU16WriteTo->ToLineString()->Set(indexAt, u8Write); + EXPECT_EQ(handleEcmaStrU16WriteTo->ToLineString()->At(LoadTBarrier(), indexAt), u8Write); } /* @@ -855,21 +855,21 @@ namespace panda::test { // From EcmaString made by CreateFromUtf8(). uint8_t arrayU8[] = {"abcde"}; uint32_t lengthEcmaStrU8 = sizeof(arrayU8) - 1; - JSHandle handleEcmaStrU8(thread, + JSHandle handleEcmaStrU8(thread, EcmaStringAccessor::CreateFromUtf8( instance, &arrayU8[0], lengthEcmaStrU8, true)); for (uint32_t i = 0; i < lengthEcmaStrU8; i++) { - EXPECT_EQ(*(handleEcmaStrU8->ToBaseString()->GetDataUtf8() + i), arrayU8[i]); + EXPECT_EQ(*(handleEcmaStrU8->ToLineString()->GetDataUtf8() + i), arrayU8[i]); } // From EcmaString made by CreateFromUtf16( , , , true). uint16_t arrayU16Comp[] = {3, 1, 34, 123, 127, 111, 42, 3, 20, 10}; uint32_t lengthEcmaStrU16Comp = sizeof(arrayU16Comp) / sizeof(arrayU16Comp[0]); - JSHandle handleEcmaStrU16Comp(thread, + JSHandle handleEcmaStrU16Comp(thread, EcmaStringAccessor::CreateFromUtf16( instance, &arrayU16Comp[0], lengthEcmaStrU16Comp, true)); for (uint32_t i = 0; i < sizeof(arrayU16Comp) / arrayU16Comp[0]; i++) { - EXPECT_EQ(*(handleEcmaStrU16Comp->ToBaseString()->GetDataUtf8() + i), arrayU16Comp[i]); + EXPECT_EQ(*(handleEcmaStrU16Comp->ToLineString()->GetDataUtf8() + i), arrayU16Comp[i]); } } @@ -884,12 +884,12 @@ namespace panda::test { // From EcmaString made by CreateFromUtf16( , , , false). uint16_t arrayU16NotComp[] = {67, 777, 1999, 1, 45, 66, 23456, 65535, 127, 333}; uint32_t lengthEcmaStrU16NotComp = sizeof(arrayU16NotComp) / sizeof(arrayU16NotComp[0]); - JSHandle handleEcmaStrU16NotComp(thread, + JSHandle handleEcmaStrU16NotComp(thread, EcmaStringAccessor::CreateFromUtf16( instance, &arrayU16NotComp[0], lengthEcmaStrU16NotComp, false)); for (uint32_t i = 0; i < lengthEcmaStrU16NotComp; i++) { - EXPECT_EQ(*(handleEcmaStrU16NotComp->ToBaseString()->GetDataUtf16() + i), arrayU16NotComp[i]); + EXPECT_EQ(*(handleEcmaStrU16NotComp->ToLineString()->GetDataUtf16() + i), arrayU16NotComp[i]); } } @@ -905,9 +905,8 @@ namespace panda::test { // CopyDataRegionUtf8(). From EcmaString made by CreateFromUtf8(). uint8_t arrayU8CopyFrom[6] = {1, 12, 34, 56, 127}; uint32_t lengthEcmaStrU8CopyFrom = sizeof(arrayU8CopyFrom) - 1; - JSHandle handleEcmaStrU8CopyFrom(thread, - EcmaStringAccessor::CreateFromUtf8( - instance, &arrayU8CopyFrom[0], lengthEcmaStrU8CopyFrom, true)); + JSHandle handleEcmaStrU8CopyFrom(thread, EcmaStringAccessor::CreateFromUtf8( + instance, &arrayU8CopyFrom[0], lengthEcmaStrU8CopyFrom, true)); const size_t lengthArrayU8Target = 7; uint8_t defaultByteForU8CopyTo = 1; uint8_t arrayU8CopyTo[lengthArrayU8Target]; @@ -932,10 +931,8 @@ namespace panda::test { // CopyDataRegionUtf8(). From EcmaString made by CreateFromUtf16( , , , true). uint16_t arrayU16CompCopyFrom[] = {1, 12, 34, 56, 127}; uint32_t lengthEcmaStrU16CompCopyFrom = sizeof(arrayU16CompCopyFrom) / sizeof(arrayU16CompCopyFrom[0]); - JSHandle handleEcmaStrU16CompCopyFrom(thread, - EcmaStringAccessor::CreateFromUtf16( - instance, &arrayU16CompCopyFrom[0], - lengthEcmaStrU16CompCopyFrom, true)); + JSHandle handleEcmaStrU16CompCopyFrom(thread, EcmaStringAccessor::CreateFromUtf16( + instance, &arrayU16CompCopyFrom[0], lengthEcmaStrU16CompCopyFrom, true)); const size_t lengthArrayU16Target = 8; uint8_t defaultByteForU16CompCopyTo = 1; uint8_t arrayU16CompCopyTo[lengthArrayU16Target]; @@ -1568,7 +1565,7 @@ namespace panda::test { * @tc.type: FUNC * @tc.require: */ - HWTEST_F_L0(BaseStringTest, EqualToSplicedString) + HWTEST_F_L0(BaseStringTest, EqualToSplicedString001) { ObjectFactory* factory = instance->GetFactory(); { @@ -1618,7 +1615,18 @@ namespace panda::test { LoadTBarrier(), firstString->ToBaseString(), secondString->ToBaseString()); EXPECT_TRUE(result); } + } + /* + * @tc.name: EqualToSplicedString + * @tc.desc: Tests whether the source string is equal to the concatenated string. + * is within expectations. + * @tc.type: FUNC + * @tc.require: + */ + HWTEST_F_L0(BaseStringTest, EqualToSplicedString002) + { + ObjectFactory* factory = instance->GetFactory(); { JSHandle sourceString = factory->NewFromUtf8("Startstart"); JSHandle firstString = factory->NewFromASCII("Start"); diff --git a/ecmascript/tests/dynamic_object_accessor_util_test.cpp b/ecmascript/tests/dynamic_object_accessor_util_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cdc4b250a3cfbb360a308898eb721b8158203ea1 --- /dev/null +++ b/ecmascript/tests/dynamic_object_accessor_util_test.cpp @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "common_interfaces/objects/dynamic_object_accessor_util.h" +#include "ecmascript/global_env.h" +#include "ecmascript/js_tagged_value.h" +#include "ecmascript/tests/test_helper.h" + +using namespace panda::ecmascript; +using namespace panda::ecmascript::base; + +namespace panda::test { +class DynamicObjectAccessorUtilTest : public BaseTestWithScope {}; + +static JSHandle JSObjectCreate(JSThread *thread) +{ + JSHandle globalEnv = thread->GetEcmaVM()->GetGlobalEnv(); + auto jsFunc = globalEnv->GetObjectFunction().GetObject(); + JSHandle objFunc(thread, jsFunc); + auto *factory = thread->GetEcmaVM()->GetFactory(); + JSHandle jsObject = factory->NewJSObjectByConstructor(JSHandle(objFunc), objFunc); + return jsObject; +} + +HWTEST_F_L0(DynamicObjectAccessorUtilTest, SetGetProperty01) +{ + JSHandle jsobject = JSObjectCreate(thread); + EXPECT_TRUE(*jsobject != nullptr); + + char key[] = "name"; + int value = 123; + JSTaggedValue taggedValue(value); + + auto setResult = common::DynamicObjectAccessorUtil::SetProperty(jsobject.GetTaggedValue().GetTaggedObject(), key, + taggedValue.GetRawData()); + EXPECT_EQ(setResult, true); + auto taggedType = common::DynamicObjectAccessorUtil::GetProperty(jsobject.GetTaggedValue().GetTaggedObject(), key); + EXPECT_EQ(JSTaggedValue(*taggedType).GetInt(), value); +} +} // namespace panda::test \ No newline at end of file diff --git a/ecmascript/tests/dynamic_type_converter_test.cpp b/ecmascript/tests/dynamic_type_converter_test.cpp index 1a05b2169933933ad178ddcaf87a5d2a4fd78c81..33744e1da015f9f3798de8db300536562fd7d410 100644 --- a/ecmascript/tests/dynamic_type_converter_test.cpp +++ b/ecmascript/tests/dynamic_type_converter_test.cpp @@ -215,7 +215,7 @@ HWTEST_F_L0(DynamicTypeConverterTest, WrapTagged_Test2) EcmaString* str1 = EcmaString::Cast(result.GetTaggedObject()); // Verify BigInt properties EXPECT_EQ(EcmaStringAccessor(str1).GetLength(), str->ToBaseString()->GetLength()); - EXPECT_EQ(EcmaStringAccessor(str1).GetDataUtf8(), str->ToBaseString()->GetDataUtf8()); + EXPECT_EQ(EcmaStringAccessor(str1).GetDataUtf8(), LineString::Cast(str->ToBaseString())->GetDataUtf8()); } } diff --git a/ecmascript/tests/ecma_string_equals_test.cpp b/ecmascript/tests/ecma_string_equals_test.cpp index a8ae4373d1772ee9e77cf42d2bf730d1d3803f1e..1ebb7ab4eb036b5992821d0b8351056f1186dcc6 100644 --- a/ecmascript/tests/ecma_string_equals_test.cpp +++ b/ecmascript/tests/ecma_string_equals_test.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 Huawei Device Co., Ltd. + * Copyright (c) 2024-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -13,6 +13,7 @@ * limitations under the License. */ +#include "common_interfaces/objects/string/base_string-inl.h" #include "ecmascript/ecma_string-inl.h" #include "ecmascript/object_factory.h" #include "ecmascript/tests/ecma_test_common.h" diff --git a/ecmascript/tests/js_hclass_test.cpp b/ecmascript/tests/js_hclass_test.cpp index 9534e15859acf26670a9643c36a211125288d775..97ab4799c0ebb19ba9f7a572dcfc2c45c6ee135f 100644 --- a/ecmascript/tests/js_hclass_test.cpp +++ b/ecmascript/tests/js_hclass_test.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Huawei Device Co., Ltd. + * Copyright (c) 2022-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -75,10 +75,18 @@ HWTEST_F_L0(JSHClassTest, SizeFromJSHClass) EXPECT_EQ(objectSize, 96U); EcmaString *string = EcmaStringAccessor::CreateEmptyString(vm); objectSize = string->GetSize(); +#if defined(ARK_HYBRID) || defined(USE_CMC_GC) + EXPECT_EQ(objectSize, 24U); +#else EXPECT_EQ(objectSize, 16U); +#endif string = factory->AllocTreeStringObject(); objectSize = string->GetClass()->SizeFromJSHClass(string); +#if defined(ARK_HYBRID) || defined(USE_CMC_GC) + EXPECT_EQ(objectSize, 40U); +#else EXPECT_EQ(objectSize, 32U); +#endif MachineCodeDesc desc; desc.codeType = MachineCodeType::BASELINE_CODE; desc.instructionsSize = 100; diff --git a/ecmascript/tests/js_stable_array_test.cpp b/ecmascript/tests/js_stable_array_test.cpp index 7e9a5b9d438867fd8190e1434f2d62dc627e324b..6c818b99dd591cd9b56df1be6361ea8946209300 100644 --- a/ecmascript/tests/js_stable_array_test.cpp +++ b/ecmascript/tests/js_stable_array_test.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Huawei Device Co., Ltd. + * Copyright (c) 2022-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -370,6 +370,7 @@ HWTEST_F_L0(JSStableArrayTest, Join_StringElements_DefinedSep) EXPECT_FALSE(EcmaStringAccessor(handleEcmaStrRet).IsTreeString()); } + /** * @tc.name: Join_StringElements_ManyTiny * @tc.desc: Create a source Array whose elements are EcmaStrings and an EcmaRuntimeCallInfo, define the first arg of @@ -423,6 +424,27 @@ HWTEST_F_L0(JSStableArrayTest, Join_StringElements_ManyTiny) */ HWTEST_F_L0(JSStableArrayTest, Join_StringElements_LargeString) { +#if defined(ARK_HYBRID) || defined(USE_CMC_GC) + int32_t lengthArr = 8; + std::string sep = ""; + // large string should use tree string. + ObjectFactory* objFactory = thread->GetEcmaVM()->GetFactory(); + JSHandle handleTagArr(objFactory->NewTaggedArray(lengthArr)); + // 40 x a + JSHandle + handleTagValElementEcmaStr(objFactory->NewFromStdString("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")); + for (int i = 0; i < lengthArr; i++) { + handleTagArr->Set(thread, i, handleTagValElementEcmaStr.GetTaggedValue()); + } + JSHandle handleTagValEcmaStrRet = CallJoin(handleTagArr, sep, lengthArr); + JSHandle handleEcmaStrRet(handleTagValEcmaStrRet); + EXPECT_STREQ(EcmaStringAccessor(handleEcmaStrRet).ToCString(thread).c_str(), + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); + EXPECT_TRUE(EcmaStringAccessor(handleEcmaStrRet).IsTreeString()); +#else int32_t lengthArr = 8; std::string sep = ""; // large string should use tree string. @@ -442,6 +464,7 @@ HWTEST_F_L0(JSStableArrayTest, Join_StringElements_LargeString) "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); EXPECT_TRUE(EcmaStringAccessor(handleEcmaStrRet).IsTreeString()); +#endif } /** diff --git a/libark_jsruntime.map b/libark_jsruntime.map index 667bb92949ff1d17b7f853a3063f6b444a7f3a0e..eab57a123abe5656a0c103220df96593fd0eaa98 100644 --- a/libark_jsruntime.map +++ b/libark_jsruntime.map @@ -97,6 +97,7 @@ panda::JsiFastNativeScope::*; panda::JSExecutionScope::*; common::BaseRuntime::*; + common::HeapAllocator::*; common::VisitDynamicGlobalRoots*; common::VisitDynamicWeakGlobalRoots*; common::VisitDynamicLocalRoots*; @@ -114,12 +115,24 @@ common::FillFreeObject*; common::SetBaseAddress*; common::JSGCCallback*; + common::RegisterVisitStaticRootsHook*; + common::RegisterUpdateStaticRootsHook*; + common::RegisterSweepStaticRootsHook*; + common::InterOpCoroutineToNative*; + common::InterOpCoroutineToRunning*; + common::RegisterInterOpCoroutineToNativeHook*; + common::RegisterInterOpCoroutineToRunningHook*; + common::RegisterUnmarkAllXRefsHook*; + common::RegisterSweepUnmarkedXRefsHook*; + common::RegisterAddXRefToStaticRootsHook*; + common::RegisterRemoveXRefFromStaticRootsHook*; common::MutatorBase::*; common::Log::*; common::AndroidLog*; common::ThreadHolder::*; common::utf_helper::ConvertRegionUtf16ToUtf8*; common::utf_helper::ConvertUtf8ToUnicodeChar*; + common::DynamicObjectAccessorUtil::*; panda::ecmascript::AotCrashInfo*; panda::ecmascript::Method::*; diff --git a/test/regresstest/ignored-regresstest-fastverify-x64-aot-pgo-litecg.txt b/test/regresstest/ignored-regresstest-fastverify-x64-aot-pgo-litecg.txt index dbf4bad37e611c17b4bee030e0f13d8d80efa25f..e93c24deed999c332dfc23092155503da261d72b 100644 --- a/test/regresstest/ignored-regresstest-fastverify-x64-aot-pgo-litecg.txt +++ b/test/regresstest/ignored-regresstest-fastverify-x64-aot-pgo-litecg.txt @@ -27,4 +27,5 @@ regresstest/ark-regress/mjsunit/compiler/bigint-compare.js regresstest/ark-regress/mjsunit/regress/regress-crbug-631318-10.js regresstest/ark-regress/mjsunit/regress/regress-2073.js - +#26099 +regresstest/ark-regress/mjsunit/regress/regress-3612.js diff --git a/test/regresstest/ignored-regresstest-fastverify-x64.txt b/test/regresstest/ignored-regresstest-fastverify-x64.txt index ba00a7c0b1bb512a55d7b5d62ba0b69d6e2ef03d..49dca28cd2c745649fab1747ac947f3f325fd4f6 100644 --- a/test/regresstest/ignored-regresstest-fastverify-x64.txt +++ b/test/regresstest/ignored-regresstest-fastverify-x64.txt @@ -13,3 +13,6 @@ regresstest/ark-regress/mjsunit/es8/async-arrow-default-function-await.js #20325 regresstest/ark-regress/mjsunit/harmony/weakrefs/finalizationregistry-independent-lifetime.js + +#26260 +regresstest/ark-regress/mjsunit/regress/regress-155924.js \ No newline at end of file diff --git a/test/ut/ignore-ut-debug-x64-ets_runtime.txt b/test/ut/ignore-ut-debug-x64-ets_runtime.txt index 92f29e55c544bffed5cc12121b2eac3f48b4529d..4e7a9df20e8a0ed24b1aec205eeb7007f7f3766a 100644 --- a/test/ut/ignore-ut-debug-x64-ets_runtime.txt +++ b/test/ut/ignore-ut-debug-x64-ets_runtime.txt @@ -24,3 +24,6 @@ obj/arkcompiler/ets_runtime/ecmascript/pgo_profiler/tests/PGOProfilerTestOne #27862 obj/arkcompiler/ets_runtime/test/moduletest/stringreplace/stringreplaceAsmAssert + +#26095 +obj/arkcompiler/ets_runtime/test/aottest/sharedset/sharedset/modules.ap diff --git a/test/ut/ignore-ut-release-qemu-ets_runtime-cmc-gc.txt b/test/ut/ignore-ut-release-qemu-ets_runtime-cmc-gc.txt new file mode 100644 index 0000000000000000000000000000000000000000..d16f44452dc852caafabadad79db4ed1483b935d --- /dev/null +++ b/test/ut/ignore-ut-release-qemu-ets_runtime-cmc-gc.txt @@ -0,0 +1,52 @@ +# Known failure list for ut - release - qemu - ets_runtime -cmc -gc + +#24283 +tests/unittest/ets_runtime/ExtractorToolTest +obj/arkcompiler/ets_runtime/ecmascript/platform/unix/ohos/tests/BacktraceTestWithQemu +tests/unittest/ets_runtime/Jsnapi_002_Test +tests/unittest/ets_runtime/SerializerTest +obj/arkcompiler/ets_runtime/ecmascript/builtins/tests/Builtins_String_TestWithQemu +obj/arkcompiler/ets_runtime/ecmascript/tests/JS_Date_TestWithQemu +obj/arkcompiler/ets_runtime/ecmascript/tests/JS_DisPlayNames_TestWithQemu +obj/arkcompiler/ets_runtime/ecmascript/base/tests/JSHelper_NumberHelper_TestWithQemu +obj/arkcompiler/ets_runtime/ecmascript/tests/JS_Locale_TestWithQemu +obj/arkcompiler/ets_runtime/ecmascript/jspandafile/tests/JSPandaFileTestWithQemu +obj/arkcompiler/ets_runtime/ecmascript/builtins/tests/Builtins_PluralRules_TestWithQemu +obj/arkcompiler/ets_runtime/ecmascript/builtins/tests/Builtins_RelativeTimeFormat_TestWithQemu +obj/arkcompiler/ets_runtime/ecmascript/builtins/tests/Builtins_ListFormat_First_TestWithQemu +obj/arkcompiler/ets_runtime/ecmascript/builtins/tests/Builtins_DateTimeFormat_Second_TestWithQemu +obj/arkcompiler/ets_runtime/ecmascript/builtins/tests/Builtins_Local_TestWithQemu +obj/arkcompiler/ets_runtime/ecmascript/builtins/tests/Builtins_Intl_TestWithQemu +obj/arkcompiler/ets_runtime/ecmascript/builtins/tests/Builtins_Segmenter_TestWithQemu +obj/arkcompiler/ets_runtime/ecmascript/tests/JS_Collator_TestWithQemu +obj/arkcompiler/ets_runtime/ecmascript/builtins/tests/Builtins_DisPlayNames_TestWithQemu +obj/arkcompiler/ets_runtime/ecmascript/tests/JS_DateTimeFormat_First_TestWithQemu +obj/arkcompiler/ets_runtime/ecmascript/tests/JS_DateTimeFormat_Second_TestWithQemu +obj/arkcompiler/ets_runtime/ecmascript/tests/JS_PluralRules_TestWithQemu +obj/arkcompiler/ets_runtime/ecmascript/builtins/tests/Builtins_BigInt_TestWithQemu +obj/arkcompiler/ets_runtime/ecmascript/tests/JS_RelativeTimeFormat_TestWithQemu +obj/arkcompiler/ets_runtime/ecmascript/tests/JS_LocaleHelper_TestWithQemu +obj/arkcompiler/ets_runtime/ecmascript/tests/JS_ListFormat_TestWithQemu + +#25856 +obj/arkcompiler/ets_runtime/ecmascript/tests/JS_NumberFormat_TestWithQemu +obj/arkcompiler/ets_runtime/ecmascript/builtins/tests/Builtins_ListFormat_Second_TestWithQemu +obj/arkcompiler/ets_runtime/ecmascript/builtins/tests/Builtins_DateTimeFormat_First_TestWithQemu +obj/arkcompiler/ets_runtime/ecmascript/builtins/tests/Builtins_NumberFormat_TestWithQemu +obj/arkcompiler/ets_runtime/ecmascript/builtins/tests/Builtins_Collator_TestWithQemu + +#26061 +obj/arkcompiler/ets_runtime/ecmascript/builtins/tests/Builtins_FinalizationRegistry_TestWithQemu +obj/arkcompiler/ets_runtime/ecmascript/builtins/tests/Builtins_DataView_TestWithQemu +obj/arkcompiler/ets_runtime/ecmascript/builtins/tests/Builtins_Lazy_TestWithQemu +obj/arkcompiler/ets_runtime/ecmascript/napi/test/Jsnapi_001_TestWithQemu +obj/arkcompiler/ets_runtime/ecmascript/builtins/tests/Builtins_Atomics_TestWithQemu +obj/arkcompiler/ets_runtime/ecmascript/pgo_profiler/tests/PGOProfilerTestOneWithQemu +obj/arkcompiler/ets_runtime/ecmascript/builtins/tests/Sendable_BuiltinsSendableArrayBuffer_TestWithQemu +obj/arkcompiler/ets_runtime/ecmascript/builtins/tests/Builtins_Number_TestWithQemu +obj/arkcompiler/ets_runtime/ecmascript/builtins/tests/Builtins_Data_TestWithQemu +obj/arkcompiler/ets_runtime/ecmascript/builtins/tests/Builtins_Errors_TestWithQemu +obj/arkcompiler/ets_runtime/ecmascript/base/tests/JSHelper_UtfHelper_TestWithQemu +obj/arkcompiler/ets_runtime/ecmascript/builtins/tests/Sendable_BuiltinsSharedTypedArray_TestWithQemu +obj/arkcompiler/ets_runtime/ecmascript/containers/tests/Containers_002_TestWithQemu +obj/arkcompiler/ets_runtime/ecmascript/builtins/tests/Builtins_Array_TestWithQemu diff --git a/test/ut/ignore-ut-release-x64-ets_runtime-cmc-gc.txt b/test/ut/ignore-ut-release-x64-ets_runtime-cmc-gc.txt new file mode 100644 index 0000000000000000000000000000000000000000..2635aad3b14862cb6d3da4ee8602dd7ee0848d1f --- /dev/null +++ b/test/ut/ignore-ut-release-x64-ets_runtime-cmc-gc.txt @@ -0,0 +1,24 @@ +# Known failure list for ut - release - x64 - ets_runtime -cmc -gc +#20980 +obj/arkcompiler/ets_runtime/test/aottest/builtin_inlining/map/Delete/builtinMapDelete + +#20471 +obj/arkcompiler/ets_runtime/test/aottest/builtin_inlining/set/Delete/builtinSetDelete + +#21629 +obj/arkcompiler/ets_runtime/test/aottest/builtin_inlining/set/Delete/builtinSetDeleteContext + +#20896 +obj/arkcompiler/ets_runtime/test/aottest/builtin_inlining/math/Ceil/builtinMathCeil + +#21801 +obj/arkcompiler/ets_runtime/test/aottest/builtin_inlining/math/Ceil/builtinMathCeilContext + +#20981 +obj/arkcompiler/ets_runtime/test/aottest/builtin_inlining/map/Delete/builtinMapDeleteContext + +#26090 +obj/arkcompiler/ets_runtime/ecmascript/pgo_profiler/tests/PGOProfilerTest + +#23099 +obj/arkcompiler/ets_runtime/ecmascript/pgo_profiler/tests/PGOProfilerTestOne diff --git a/test/ut/ignore-ut-release-x64-ets_runtime.txt b/test/ut/ignore-ut-release-x64-ets_runtime.txt index de9d087639820f2c3db628508ba69fa397291c0a..7cf7612f029cba380ad8d21d38aeb67da86198fa 100644 --- a/test/ut/ignore-ut-release-x64-ets_runtime.txt +++ b/test/ut/ignore-ut-release-x64-ets_runtime.txt @@ -22,3 +22,6 @@ obj/arkcompiler/ets_runtime/test/moduletest/hugearray/hugearrayAsmAssertContext #23099 obj/arkcompiler/ets_runtime/ecmascript/pgo_profiler/tests/PGOProfilerTestOne + +#26263 +obj/arkcompiler/ets_runtime/ecmascript/tests/GC_Third_Test