diff --git a/BUILD.gn b/BUILD.gn index c98841b5221472308bdbfb217e8f754a758ce55a..3c61ad3a13576d50a5d2c4160a22f4ef0b6e2e71 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -1050,6 +1050,7 @@ ecma_source += [ "common_components/log/log.cpp", "common_components/objects/base_object.cpp", "common_components/objects/base_string.cpp", + "common_components/objects/composite_base_class.cpp", "common_components/taskpool/taskpool.cpp", "common_components/taskpool/runner.cpp", "common_components/taskpool/task_queue.cpp", diff --git a/common_components/base_runtime/base_runtime.cpp b/common_components/base_runtime/base_runtime.cpp index 5cc388293d7020637961c8dad78e9e0b51948800..f295fbb115e7d86427263b332e5ffa6345cf6eb2 100755 --- a/common_components/base_runtime/base_runtime.cpp +++ b/common_components/base_runtime/base_runtime.cpp @@ -23,6 +23,7 @@ #include "common_components/common_runtime/src/heap_manager.h" #include "common_components/common_runtime/src/log_manager.h" #include "common_components/common_runtime/src/mutator/mutator_manager.h" +#include "common_interfaces/objects/composite_base_class.h" #include "common_interfaces/thread/thread_state_transition.h" namespace panda { @@ -113,7 +114,7 @@ void BaseRuntime::InitFromDynamic(const RuntimeParam ¶m) logManager_ = NewAndInit(); mutatorManager_ = NewAndInit(); heapManager_ = NewAndInit(param_); - + baseClassRoots_ = NewAndInit(); LOG_COMMON(INFO) << "Arkcommon runtime started."; // Record runtime parameter to report. heap growth value needs to plus 1. VLOG(REPORT, "Runtime parameter:\n\tHeap size: %zu(KB)\n\tRegion size: %zu(KB)\n\tExemption threshold: %.2f\n\t" @@ -149,6 +150,7 @@ void BaseRuntime::FiniFromDynamic() CheckAndFini(heapManager_); CheckAndFini(mutatorManager_); CheckAndFini(logManager_); + CheckAndFini(baseClassRoots_); PagePool::Instance().Fini(); } diff --git a/common_components/base_runtime/hooks.h b/common_components/base_runtime/hooks.h index f13d2d12080a2a1c6456390b612a6d94022bd30f..7196196be4b57a7ba550b00f1d9b5bee51141e45 100644 --- a/common_components/base_runtime/hooks.h +++ b/common_components/base_runtime/hooks.h @@ -25,6 +25,8 @@ // Visitor that iterate all `RefField`s in a TaggedObject and add them to // `WorkStack` Should be moved to BaseRT and panda namespace later namespace panda { +// Roots in BaseRuntime +PUBLIC_API void VisitBaseRoots(const RefFieldVisitor &visitor); // Dynamic VM Roots scanning PUBLIC_API void VisitDynamicRoots(const RefFieldVisitor &visitor, bool isMark); PUBLIC_API void VisitDynamicWeakRoots(const WeakRefFieldVisitor &visitorFunc); diff --git a/common_components/heap/heap_visitor.cpp b/common_components/heap/heap_visitor.cpp index 0deef6d2973ceabc26c622b4f4671eaa6ad762bd..f87331676532c04463dbc76718b4393be7fcbe2a 100755 --- a/common_components/heap/heap_visitor.cpp +++ b/common_components/heap/heap_visitor.cpp @@ -60,6 +60,7 @@ void RegisterRemoveXRefFromStaticRootsHook(RemoveXRefFromStaticRootsHookFunc fun void VisitRoots(const RefFieldVisitor &visitor, bool isMark) { VisitDynamicRoots(visitor, isMark); + VisitBaseRoots(visitor); if (isMark) { if (g_visitStaticRootsHook != nullptr) { g_visitStaticRootsHook(visitor); diff --git a/common_components/objects/composite_base_class.cpp b/common_components/objects/composite_base_class.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c1d2b8fb9c0ff5bf69441e3b91679791214a61e7 --- /dev/null +++ b/common_components/objects/composite_base_class.cpp @@ -0,0 +1,58 @@ +/* +* 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 +#include + +#include "objects/composite_base_class.h" +#include "objects/base_object.h" + +namespace common { +void BaseClassRoots::InitializeCompositeBaseClass(CompositeBaseClassAllocator &allocator) +{ + if (initialized_.exchange(true)) { + return; + } + CreateCompositeBaseClass(CommonType::LINE_STRING, allocator); + CreateCompositeBaseClass(CommonType::SLICED_STRING, allocator); + CreateCompositeBaseClass(CommonType::TREE_STRING, allocator); +} + +void BaseClassRoots::CreateCompositeBaseClass(CommonType type, CompositeBaseClassAllocator& allocator) +{ + CompositeBaseClass* classObject = allocator(); + classObject->class_.ClearBitField(); + classObject->class_.SetObjectType(type); + size_t index = TypeToIndex[static_cast(type)]; + compositeBaseClasses_[index] = classObject; + baseClasses_[index] = &classObject->class_; +} + +BaseClass* BaseClassRoots::GetBaseClass(CommonType type) const +{ + return baseClasses_[TypeToIndex[static_cast(type)]]; +} + +void BaseClassRoots::IterateCompositeBaseClass(const RefFieldVisitor& visitorFunc) +{ + if (!initialized_) { + return; + } + for (auto& it : compositeBaseClasses_) { + visitorFunc(reinterpret_cast&>(it)); + } +} + +} // namespace panda diff --git a/ecmascript/ecma_macros.h b/ecmascript/ecma_macros.h index 6ba423ffbcb30e553f6fa2ce5a4f1c715bc26c95..bd03f3ab03fb0f18050bee6c14096b993d2c8355 100644 --- a/ecmascript/ecma_macros.h +++ b/ecmascript/ecma_macros.h @@ -68,11 +68,26 @@ #define SET_VALUE_PRIMITIVE(addr, offset, value) \ Barriers::SetPrimitive(this, offset, (value).GetRawData()) +#if !defined(NDEBUG) && USE_CMC_GC +#define FIELD_ACCESS_CHECK(needCheck, name, check) \ + if constexpr (needCheck) { \ + if (check()) { \ + LOG_FULL(FATAL) << #name" field can't be used under check: "#check; \ + UNREACHABLE(); \ + }; \ + } +#else + #define FIELD_ACCESS_CHECK(needCheck, name, check) +#endif + +#define DUMMY_FUNC() false + // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) -#define ACCESSORS(name, offset, endOffset) \ +#define ACCESSORS_WITH_DCHECK_BASE(name, offset, endOffset, needCheck, check) \ static constexpr size_t endOffset = (offset) + JSTaggedValue::TaggedTypeSize(); \ JSTaggedValue Get##name() const \ { \ + FIELD_ACCESS_CHECK(needCheck, name, check); \ /* Note: We can't statically decide the element type is a primitive or heap object, especially for */ \ /* dynamically-typed languages like JavaScript. So we simply skip the read-barrier. */ \ return JSTaggedValue(Barriers::GetTaggedValue(this, offset)); \ @@ -103,6 +118,12 @@ } \ } +#define ACCESSORS(name, offset, endOffset) \ + ACCESSORS_WITH_DCHECK_BASE(name, offset, endOffset, false, DUMMY_FUNC) + +#define ACCESSORS_DCHECK(name, offset, endOffset, check) \ + ACCESSORS_WITH_DCHECK_BASE(name, offset, endOffset, true, check) + // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) #define ACCESSORS_SYNCHRONIZED_PRIMITIVE_FIELD(name, type, offset, endOffset) \ static constexpr size_t endOffset = (offset) + sizeof(type); \ @@ -118,10 +139,11 @@ } // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) -#define ACCESSORS_SYNCHRONIZED(name, offset, endOffset) \ +#define ACCESSORS_SYNCHRONIZED_WITH_DCHECK_BASE(name, offset, endOffset, needCheck, check) \ static constexpr size_t endOffset = (offset) + JSTaggedValue::TaggedTypeSize(); \ JSTaggedValue Get##name() const \ { \ + FIELD_ACCESS_CHECK(needCheck, name, check); \ /* Note: We can't statically decide the element type is a primitive or heap object, especially for */ \ /* dynamically-typed languages like JavaScript. So we simply skip the read-barrier. */ \ /* Synchronized means it will restrain the store and load in atomic. */ \ @@ -130,32 +152,45 @@ template \ void Set##name(const JSThread *thread, JSHandle value) \ { \ + FIELD_ACCESS_CHECK(needCheck, name, check); \ bool isPrimitive = !value.GetTaggedValue().IsHeapObject(); \ Barriers::SynchronizedSetObject(thread, this, offset, value.GetTaggedValue().GetRawData(), isPrimitive); \ } \ void Set##name(const JSThread *thread, JSTaggedValue value) \ { \ + FIELD_ACCESS_CHECK(needCheck, name, check); \ bool isPrimitive = !value.IsHeapObject(); \ Barriers::SynchronizedSetObject(thread, this, offset, value.GetRawData(), isPrimitive); \ } +#define ACCESSORS_SYNCHRONIZED(name, offset, endOffset) \ + ACCESSORS_SYNCHRONIZED_WITH_DCHECK_BASE(name, offset, endOffset, false, DUMMY_FUNC) + +#define ACCESSORS_SYNCHRONIZED_DCHECK(name, offset, endOffset, check) \ + ACCESSORS_SYNCHRONIZED_WITH_DCHECK_BASE(name, offset, endOffset, true, check) + // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) #define DEFINE_ALIGN_SIZE(offset) \ static constexpr size_t SIZE = ((offset) + sizeof(JSTaggedType) - 1U) & (~(sizeof(JSTaggedType) - 1U)) // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) -#define ACCESSORS_FIXED_SIZE_FIELD(name, type, sizeType, offset, endOffset) \ - static_assert(sizeof(type) <= sizeof(sizeType)); \ - static constexpr size_t endOffset = (offset) + sizeof(sizeType); \ - inline void Set##name(type value) \ - { \ - Barriers::SetPrimitive(this, offset, value); \ - } \ - inline type Get##name() const \ - { \ - return Barriers::GetValue(this, offset); \ +#define ACCESSORS_FIXED_SIZE_FIELD_DCHECK_BASE(name, type, sizeType, offset, endOffset, needCheck, check) \ + static_assert(sizeof(type) <= sizeof(sizeType)); \ + static constexpr size_t endOffset = (offset) + sizeof(sizeType); \ + inline void Set##name(type value) \ + { \ + FIELD_ACCESS_CHECK(needCheck, name, check); \ + Barriers::SetPrimitive(this, offset, value); \ + } \ + inline type Get##name() const \ + { \ + FIELD_ACCESS_CHECK(needCheck, name, check); \ + return Barriers::GetValue(this, offset); \ } +#define ACCESSORS_FIXED_SIZE_FIELD(name, type, sizeType, offset, endOffset) \ + ACCESSORS_FIXED_SIZE_FIELD_DCHECK_BASE(name, type, sizeType, offset, endOffset, false, DUMMY_FUNC) + // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) #define ACCESSORS_NATIVE_FIELD(name, type, offset, endOffset) \ ACCESSORS_FIXED_SIZE_FIELD(name, type *, type *, offset, endOffset) @@ -164,6 +199,10 @@ #define ACCESSORS_PRIMITIVE_FIELD(name, type, offset, endOffset) \ ACCESSORS_FIXED_SIZE_FIELD(name, type, type, offset, endOffset) +// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) +#define ACCESSORS_PRIMITIVE_FIELD_DCHECK(name, type, offset, endOffset, check) \ + ACCESSORS_FIXED_SIZE_FIELD_DCHECK_BASE(name, type, type, offset, endOffset, true, check) + // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) #define ACCESSORS_BIT_FIELD(name, offset, endOffset) \ ACCESSORS_FIXED_SIZE_FIELD(name, uint32_t, uint32_t, offset, endOffset) \ diff --git a/ecmascript/global_env_constants.cpp b/ecmascript/global_env_constants.cpp index acc9572b1841a0e7e66ab06d9010aa138e30dcf3..c3bd9177e34ef328619f35773382393a775b4174 100644 --- a/ecmascript/global_env_constants.cpp +++ b/ecmascript/global_env_constants.cpp @@ -51,6 +51,7 @@ #include "ecmascript/shared_objects/js_shared_map_iterator.h" #include "ecmascript/shared_objects/js_shared_set_iterator.h" #include "ecmascript/vtable.h" +#include "common_interfaces/objects/composite_base_class.h" namespace panda::ecmascript { void GlobalEnvConstants::Init(JSThread *thread) @@ -96,11 +97,31 @@ void GlobalEnvConstants::InitSharedStrings(ObjectFactory *factory) #undef INIT_GLOBAL_ENV_CONSTANT_STRING } +#ifdef USE_CMC_GC +void GlobalEnvConstants::InitCompositeBaseClasses(ObjectFactory* factory, JSHClass* hClass) +{ + auto compositeBaseClassClass = factory-> + NewSEcmaReadOnlyHClass(hClass, common::CompositeBaseClass::SIZE, JSType::COMPOSITE_BASE_CLASS); + SetConstant(ConstantIndex::COMPOSITE_BASE_CLASS_CLASS_INDEX, compositeBaseClassClass); + common::BaseClassRoots& classRoots = common::BaseRuntime::GetInstance()->GetBaseClassRoots(); + classRoots.InitializeCompositeBaseClass( + [compositeBaseClassClass, factory]()-> common::CompositeBaseClass* { + TaggedObject* compositeBaseClass = factory->NewNonMovableObject(compositeBaseClassClass, 0); + compositeBaseClass->SetFullBaseClassWithoutBarrier( + reinterpret_cast(*compositeBaseClassClass)); + factory->InitObjectFields(compositeBaseClass, JSTaggedValue(reinterpret_cast(nullptr))); + return reinterpret_cast(compositeBaseClass); + }); +} +#endif + void GlobalEnvConstants::InitSharedRootsClasses(ObjectFactory *factory) { // Global constants are readonly. JSHClass *hClass = *factory->InitSClassClass(); - +#ifdef USE_CMC_GC + InitCompositeBaseClasses(factory, hClass); +#endif SetConstant(ConstantIndex::HCLASS_CLASS_INDEX, JSTaggedValue(hClass)); // To reverse the order, the hclass of string needs to load default supers SetConstant(ConstantIndex::TAGGED_ARRAY_CLASS_INDEX, @@ -111,12 +132,21 @@ void GlobalEnvConstants::InitSharedRootsClasses(ObjectFactory *factory) factory->NewSEcmaReadOnlyHClass(hClass, FreeObject::SIZE_OFFSET, JSType::FREE_OBJECT_WITH_ONE_FIELD)); SetConstant(ConstantIndex::FREE_OBJECT_WITH_TWO_FIELD_CLASS_INDEX, factory->NewSEcmaReadOnlyHClass(hClass, FreeObject::SIZE, JSType::FREE_OBJECT_WITH_TWO_FIELD)); +#ifdef USE_CMC_GC + SetConstant(ConstantIndex::LINE_STRING_CLASS_INDEX, + factory->InitHClassInCompositeBaseClass(hClass, common::CommonType::LINE_STRING)); + SetConstant(ConstantIndex::SLICED_STRING_CLASS_INDEX, + factory->InitHClassInCompositeBaseClass(hClass, common::CommonType::SLICED_STRING)); + SetConstant(ConstantIndex::TREE_STRING_CLASS_INDEX, + factory->InitHClassInCompositeBaseClass(hClass, common::CommonType::TREE_STRING)); +#else SetConstant(ConstantIndex::LINE_STRING_CLASS_INDEX, factory->NewSEcmaReadOnlyHClass(hClass, 0, JSType::LINE_STRING)); SetConstant(ConstantIndex::SLICED_STRING_CLASS_INDEX, factory->NewSEcmaReadOnlyHClass(hClass, 0, JSType::SLICED_STRING)); SetConstant(ConstantIndex::TREE_STRING_CLASS_INDEX, factory->NewSEcmaReadOnlyHClass(hClass, 0, JSType::TREE_STRING)); +#endif SetConstant(ConstantIndex::BYTE_ARRAY_CLASS_INDEX, factory->NewSEcmaReadOnlyHClass(hClass, 0, JSType::BYTE_ARRAY)); SetConstant(ConstantIndex::CONSTANT_POOL_CLASS_INDEX, diff --git a/ecmascript/global_env_constants.h b/ecmascript/global_env_constants.h index d88730392e373501f814796667ab40c0e679cc47..014f900f32a9537c36b4a6b80e23518e0b694ecb 100644 --- a/ecmascript/global_env_constants.h +++ b/ecmascript/global_env_constants.h @@ -111,7 +111,8 @@ class ObjectFactory; V(JSTaggedValue, SharedMutantTaggedArrayClass, SHARED_MUTANT_TAGGED_ARRAY_CLASS_INDEX, ecma_roots_class) \ /* COWMutantTaggedArray only in local now */ \ V(JSTaggedValue, SharedAOTLiteralInfoClass, SHARED_AOT_LITERAL_INFO_CLASS_INDEX, ecma_roots_class) \ - /* VTable only in local now */ + /* VTable only in local now */ \ + V(JSTaggedValue, CompositeBaseClassClass, COMPOSITE_BASE_CLASS_CLASS_INDEX, ecma_roots_class) #endif #define GLOBAL_ENV_CONSTANT_CLASS(V) \ @@ -837,6 +838,9 @@ public: private: void InitSharedStrings(ObjectFactory *factory); +#ifdef USE_CMC_GC + void InitCompositeBaseClasses(ObjectFactory* factory, JSHClass* hClass); +#endif void InitSharedRootsClasses(ObjectFactory *factory); void InitSharedMiscellanious(JSThread *thread, ObjectFactory *factory); void InitRootsClasses(ObjectFactory *factory); diff --git a/ecmascript/js_hclass.h b/ecmascript/js_hclass.h index f93f536d1364b5e16b315089f730ed00c179ac92..4ae6cc15e263f39b0c11da0661e010a665808399 100644 --- a/ecmascript/js_hclass.h +++ b/ecmascript/js_hclass.h @@ -24,6 +24,7 @@ #include "ecmascript/mem/slots.h" #include "ecmascript/mem/visitor.h" #include "ecmascript/property_attributes.h" +#include "common_interfaces/objects/composite_base_class.h" #include "libpandabase/utils/bit_field.h" @@ -84,6 +85,7 @@ struct Reference; LINE_STRING, /* /////////////////////////////////////////////////////////////////////////////////-PADDING */ \ SLICED_STRING, /* ////////////////////////////////////////////////////////////////////////////////-PADDING */ \ TREE_STRING, /* //////////////////////////////////////////////////////////////////////////////////-PADDING */ \ + COMPOSITE_BASE_CLASS, /* /////////////////////////////////////////////////////////////////////////-PADDING */ \ \ JS_OBJECT, /* JS_OBJECT_FIRST ////////////////////////////////////////////////////////////////////// */ \ JS_XREF_OBJECT, /* //////////////////////////////////////////////////////////////////////////////-PADDING */ \ @@ -667,6 +669,13 @@ public: return GetObjectType() == JSType::HCLASS; } + // These types are not complete hclass, does not has profile field. + inline bool HasProfileType() const + { + common::CommonType jsType = static_cast(GetObjectType()); + return !(common::CommonType::FIRST_OBJECT_TYPE <= jsType && jsType <= common::CommonType::LAST_OBJECT_TYPE); + } + inline bool IsString() const { JSType jsType = GetObjectType(); @@ -2062,15 +2071,17 @@ public: static constexpr size_t BIT_FIELD_OFFSET = TaggedObjectSize(); ACCESSORS_PRIMITIVE_FIELD(BitField, uint32_t, BIT_FIELD_OFFSET, BIT_FIELD1_OFFSET); ACCESSORS_PRIMITIVE_FIELD(BitField1, uint32_t, BIT_FIELD1_OFFSET, PROTOTYPE_OFFSET); - ACCESSORS(Proto, PROTOTYPE_OFFSET, LAYOUT_OFFSET); - ACCESSORS_SYNCHRONIZED(Layout, LAYOUT_OFFSET, TRANSTIONS_OFFSET); - ACCESSORS(Transitions, TRANSTIONS_OFFSET, PARENT_OFFSET); - ACCESSORS(Parent, PARENT_OFFSET, PROTO_CHANGE_MARKER_OFFSET); - ACCESSORS(ProtoChangeMarker, PROTO_CHANGE_MARKER_OFFSET, PROTO_CHANGE_DETAILS_OFFSET); - ACCESSORS(ProtoChangeDetails, PROTO_CHANGE_DETAILS_OFFSET, ENUM_CACHE_OFFSET); - ACCESSORS(EnumCache, ENUM_CACHE_OFFSET, PROFILE_TYPE); - ACCESSORS_PRIMITIVE_FIELD(ProfileType, uint64_t, PROFILE_TYPE, LAST_OFFSET); + ACCESSORS_DCHECK(Proto, PROTOTYPE_OFFSET, LAYOUT_OFFSET, IsString); + ACCESSORS_SYNCHRONIZED_DCHECK(Layout, LAYOUT_OFFSET, TRANSTIONS_OFFSET, IsString); + ACCESSORS_DCHECK(Transitions, TRANSTIONS_OFFSET, PARENT_OFFSET, IsString); + ACCESSORS_DCHECK(Parent, PARENT_OFFSET, PROTO_CHANGE_MARKER_OFFSET, IsString); + ACCESSORS_DCHECK(ProtoChangeMarker, PROTO_CHANGE_MARKER_OFFSET, PROTO_CHANGE_DETAILS_OFFSET, IsString); + ACCESSORS_DCHECK(ProtoChangeDetails, PROTO_CHANGE_DETAILS_OFFSET, ENUM_CACHE_OFFSET, IsString); + ACCESSORS_DCHECK(EnumCache, ENUM_CACHE_OFFSET, PROFILE_TYPE_OFFSET, IsString); + ACCESSORS_PRIMITIVE_FIELD_DCHECK(ProfileType, uint64_t, PROFILE_TYPE_OFFSET, LAST_OFFSET, IsString); DEFINE_ALIGN_SIZE(LAST_OFFSET); + static_assert(panda::CompositeBaseClass::SIZE >= SIZE, + "CompositeBaseClass::SIZE should be larger than JSHClass::SIZE"); static JSHandle SetPrototypeWithNotification(const JSThread *thread, const JSHandle &hclass, diff --git a/ecmascript/mem/cmc_gc/hooks.cpp b/ecmascript/mem/cmc_gc/hooks.cpp index 2b2fd64b436620a98cabaa59a976e3f8ba1245a6..0029ef620caef2dc92dd9446aceb3b12baa55cfb 100644 --- a/ecmascript/mem/cmc_gc/hooks.cpp +++ b/ecmascript/mem/cmc_gc/hooks.cpp @@ -27,6 +27,7 @@ #include "ecmascript/mem/visitor.h" #include "ecmascript/runtime.h" #include "objects/base_type.h" +#include "objects/composite_base_class.h" namespace panda { using ecmascript::ObjectXRay; @@ -100,6 +101,14 @@ private: const WeakRefFieldVisitor &visitor_; }; +void VisitBaseRoots(const RefFieldVisitor &visitorFunc) +{ + 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. + baseClassRoots.IterateCompositeBaseClass(visitorFunc); +} + void VisitDynamicRoots(const RefFieldVisitor &visitorFunc, bool isMark) { if (!ecmascript::Runtime::HasInstance()) { diff --git a/ecmascript/mem/object_xray.h b/ecmascript/mem/object_xray.h index fa675d8b35185526a097d3bba3596313f2994eb5..23695aa9a0f99e908467af419c51441b546cc463 100644 --- a/ecmascript/mem/object_xray.h +++ b/ecmascript/mem/object_xray.h @@ -18,6 +18,7 @@ #include +#include "common_interfaces/objects/composite_base_class.h" #include "ecmascript/byte_array.h" #include "ecmascript/ecma_vm.h" #include "ecmascript/js_async_from_sync_iterator.h" @@ -414,6 +415,16 @@ public: JSHClass::Cast(object)->VisitRangeSlot(visitor); } break; + case JSType::COMPOSITE_BASE_CLASS: + // semi gc is not needed to visit hclass + if constexpr (visitType != VisitType::SEMI_GC_VISIT) { + // reference to the comments in composite_base_class.h, only step 1 and step 2, it maybe enter here. + // When the CompostBaseClass is changed to 1.2 Class, it will be visited from 1.2 class linker. + ObjectBodyIterator::IterateRefBody(object, visitor); + } + break; case JSType::LINE_STRING: if constexpr (visitType == VisitType::ALL_VISIT) { LineEcmaString::Cast(object)->VisitRangeSlot(visitor); diff --git a/ecmascript/object_factory.cpp b/ecmascript/object_factory.cpp index fb084f0b6bdb82dcbde05157fc96f2c8d1ad0047..3727c5c8a0e0700155b26f81d6dfee5db92ce7e0 100644 --- a/ecmascript/object_factory.cpp +++ b/ecmascript/object_factory.cpp @@ -198,7 +198,7 @@ JSHandle ObjectFactory::NewEcmaHClass(uint32_t size, JSType type, uint size, type, inlinedProps); } -void ObjectFactory::InitObjectFields(const TaggedObject *object) +void ObjectFactory::InitObjectFields(const TaggedObject *object, JSTaggedValue initValue) { auto *klass = object->GetClass(); auto objBodySize = klass->GetObjectSize() - TaggedObject::TaggedObjectSize(); diff --git a/ecmascript/object_factory.h b/ecmascript/object_factory.h index 270fd3684566554410a56daffa7b88afd735817a..6439ec05b7f7ea3ccb5eeed794548993bc21ced0 100644 --- a/ecmascript/object_factory.h +++ b/ecmascript/object_factory.h @@ -16,6 +16,7 @@ #ifndef ECMASCRIPT_OBJECT_FACTORY_H #define ECMASCRIPT_OBJECT_FACTORY_H +#include "common_interfaces/objects/base_class.h" #include "ecmascript/base/error_type.h" #include "ecmascript/base/number_helper.h" #include "ecmascript/compiler/builtins/builtins_call_signature.h" @@ -770,8 +771,8 @@ public: JSHandle NewSEcmaReadOnlyHClass(JSHClass *hclass, uint32_t size, JSType type, uint32_t inlinedProps = JSHClass::DEFAULT_CAPACITY_OF_IN_OBJECTS); - #ifdef USE_CMC_GC + JSTaggedValue InitHClassInCompositeBaseClass(JSHClass* hclass, common::CommonType type); JSHandle NewSEcmaReadOnlySharedHClass(JSHClass *hclass, uint32_t size, JSType type, uint32_t inlinedProps = JSHClass::DEFAULT_CAPACITY_OF_IN_OBJECTS); #endif @@ -928,7 +929,7 @@ private: friend class EcmaString; friend class SnapshotProcessor; friend class SingleCharTable; - void InitObjectFields(const TaggedObject *object); + void InitObjectFields(const TaggedObject *object, JSTaggedValue initValue = JSTaggedValue::Undefined()); JSThread *thread_ {nullptr}; bool isTriggerGc_ {false}; diff --git a/ecmascript/pgo_profiler/pgo_profiler.cpp b/ecmascript/pgo_profiler/pgo_profiler.cpp index 20b1aff27c3e4a817127753839583b820691b3fb..2f7a32bfbaf6eeceb4f1938ae0073d008376f4e9 100644 --- a/ecmascript/pgo_profiler/pgo_profiler.cpp +++ b/ecmascript/pgo_profiler/pgo_profiler.cpp @@ -1213,6 +1213,9 @@ void PGOProfiler::DumpICByValueWithHandler(ApEntityId abcId, const CString &reco void PGOProfiler::TryDumpProtoTransitionType(JSHClass *hclass) { + if (!hclass->HasProfileType()) { + return; + } JSHClass *ihc1 = JSHClass::FindRootHClass(hclass); auto transitionType = GetProfileType(ihc1, true); if (!transitionType.IsRootType() || !transitionType.IsTransitionClassType()) { @@ -1570,6 +1573,9 @@ bool PGOProfiler::AddTransitionObjectInfo(ProfileType recordType, JSHClass* holdTra, PGOSampleType accessorMethod) { + if (!receiver->HasProfileType()) { + return false; + } auto receiverRootType = FindRootProfileType(receiver); if (!receiverRootType.IsRootType()) { return false; diff --git a/ecmascript/shared_object_factory.cpp b/ecmascript/shared_object_factory.cpp index 637901e7b537859466757d8ec0657b1d1c3faaef..76a1cca2d12ecf90699adbb177cbc1d8bacc9a6f 100644 --- a/ecmascript/shared_object_factory.cpp +++ b/ecmascript/shared_object_factory.cpp @@ -13,6 +13,8 @@ * limitations under the License. */ +#include "common_interfaces/objects/base_class.h" +#include "common_interfaces/objects/composite_base_class.h" #include "ecmascript/jspandafile/program_object.h" #include "ecmascript/layout_info-inl.h" #include "ecmascript/mem/heap-inl.h" @@ -176,6 +178,22 @@ JSHandle ObjectFactory::NewSEcmaReadOnlySharedHClass(JSHClass *hclass, ASSERT(newClass->IsInSharedHeap()); return newClass; } + +JSTaggedValue ObjectFactory::InitHClassInCompositeBaseClass(JSHClass* hclass, common::CommonType type) +{ + common::BaseClassRoots& classRoots = common::BaseRuntime::GetInstance()->GetBaseClassRoots(); + auto* newClass = reinterpret_cast(classRoots.GetBaseClass(type)); + newClass->SetClassWithoutBarrier(hclass); + newClass->SetObjectSize(0); + newClass->SetExtensible(true); + newClass->SetIsPrototype(false); + newClass->SetHasDeleteProperty(false); + newClass->SetIsAllTaggedProp(true); + newClass->SetElementsKind(ElementsKind::GENERIC); + newClass->SetConstructionCounter(0); + newClass->SetIsJSShared(true); + return JSTaggedValue(newClass); +} #endif JSHandle ObjectFactory::InitSClassClass() diff --git a/ecmascript/tests/js_hclass_test.cpp b/ecmascript/tests/js_hclass_test.cpp index 444dc3dc9f58d6bcea7bd0be41aa324a0658f03e..93b70ca5fd8540a546f9e234b7c7121d45c8b3ab 100644 --- a/ecmascript/tests/js_hclass_test.cpp +++ b/ecmascript/tests/js_hclass_test.cpp @@ -96,12 +96,12 @@ HWTEST_F_L0(JSHClassTest, HasReferenceField) ObjectFactory *factory = vm->GetFactory(); JSHandle nullHandle(thread, JSTaggedValue::Null()); - JSHandle obj1Class = factory->NewEcmaHClass(TaggedArray::SIZE, JSType::LINE_STRING, nullHandle); - JSHandle obj2Class = factory->NewEcmaHClass(TaggedArray::SIZE, JSType::TREE_STRING, nullHandle); + JSHandle obj1Class = JSHandle::Cast(thread->GlobalConstants()->GetHandledLineStringClass()); + JSHandle obj2Class = JSHandle::Cast(thread->GlobalConstants()->GetHandledTreeStringClass()); JSHandle obj3Class = factory->NewEcmaHClass(TaggedArray::SIZE, JSType::JS_NATIVE_POINTER, nullHandle); JSHandle obj4Class = factory->NewEcmaHClass(TaggedArray::SIZE, JSType::JS_OBJECT, nullHandle); - JSHandle obj5Class = factory->NewEcmaHClass(TaggedArray::SIZE, JSType::SLICED_STRING, nullHandle); + JSHandle obj5Class = JSHandle::Cast(thread->GlobalConstants()->GetHandledSlicedStringClass()); EXPECT_FALSE(obj1Class->HasReferenceField()); EXPECT_TRUE(obj2Class->HasReferenceField()); EXPECT_FALSE(obj3Class->HasReferenceField());