• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef ECMASCRIPT_MEM_DYNAMIC_OBJECT_OPERATOR_H
17 #define ECMASCRIPT_MEM_DYNAMIC_OBJECT_OPERATOR_H
18 
19 #include "common_interfaces/objects/base_object.h"
20 #include "common_interfaces/objects/base_object_operator.h"
21 #include "ecmascript/free_object.h"
22 #include "ecmascript/js_hclass-inl.h"
23 #include "ecmascript/mem/tagged_object.h"
24 #include "libpandabase/macros.h"
25 
26 namespace panda::ecmascript {
27 class RefFieldObjectVisitor final : public BaseObjectVisitor<RefFieldObjectVisitor> {
28    public:
RefFieldObjectVisitor(const common::RefFieldVisitor & visitor)29     inline explicit RefFieldObjectVisitor(const common::RefFieldVisitor &visitor): visitor_(visitor) {};
30     ~RefFieldObjectVisitor() override = default;
31 
32     void VisitObjectRangeImpl(BaseObject *root, uintptr_t start, uintptr_t end,
33                               VisitObjectArea area) override;
34 
35     void VisitObjectHClassImpl(BaseObject *hclass) override;
36 
37     void VisitAllRefFields(TaggedObject *obj);
38 
39    private:
40     void visit(ObjectSlot slot);
41 
42     template <class Callback>
VisitBodyInObj(TaggedObject * root,ObjectSlot start,ObjectSlot end,Callback && cb)43     void VisitBodyInObj(TaggedObject *root, ObjectSlot start, ObjectSlot end, Callback &&cb)
44     {
45         JSHClass *hclass = root->SynchronizedGetClass();
46         ASSERT(!hclass->IsAllTaggedProp());
47         auto thread = JSThread::GetCurrent();
48         LayoutInfo *layout;
49         if (thread == nullptr) {
50             // gc thread
51             if (g_isEnableCMCGC) {
52                 layout = LayoutInfo::UncheckCast(hclass->GetLayout<RBMode::FAST_CMC_RB>(thread).GetTaggedObject());
53             } else {
54                 layout = LayoutInfo::UncheckCast(hclass->GetLayout<RBMode::FAST_NO_RB>(thread).GetTaggedObject());
55             }
56         } else {
57             // serialization
58             layout = LayoutInfo::UncheckCast(hclass->GetLayout(thread).GetTaggedObject());
59         }
60         ObjectSlot realEnd = start;
61         realEnd += layout->GetPropertiesCapacity(); // only += operator is supported
62         end = std::min(end, realEnd);
63 
64         int index = 0;
65         for (ObjectSlot slot = start; slot < end; slot++) {
66             PropertyAttributes attr;
67             if (thread == nullptr) {
68                 if (g_isEnableCMCGC) {
69                     attr = layout->GetAttr<RBMode::FAST_CMC_RB>(thread, index++);
70                 } else {
71                     attr = layout->GetAttr<RBMode::FAST_NO_RB>(thread, index++);
72                 }
73             } else {
74                 attr = layout->GetAttr(thread, index++);
75             }
76             if (attr.IsTaggedRep()) {
77                 cb(slot);
78             }
79         }
80     }
81 
82     const common::RefFieldVisitor &visitor_;
83 };
84 
85 static constexpr uint64_t TAG_MARK_BIT = 0x02ULL;
GetHeader(const BaseObject * obj)86 static uint64_t GetHeader(const BaseObject* obj)
87 {
88     return (*((uint64_t*)obj));
89 }
90 
91 class DynamicObjectOperator : public common::BaseObjectOperatorInterfaces {
92 public:
93     static void Initialize();
94 
IsValidObject(const BaseObject * object)95     bool IsValidObject([[maybe_unused]] const BaseObject *object) const override
96     {
97         auto taggedObject = TaggedObject::Cast(object);
98         auto hclass = taggedObject->GetClass();
99 
100         return hclass->GetClass()->IsHClass();
101     }
102 
ForEachRefField(const BaseObject * object,const common::RefFieldVisitor & visitor)103     void ForEachRefField(const BaseObject *object, const common::RefFieldVisitor &visitor) const override
104     {
105         auto freeObject = FreeObject::Cast(reinterpret_cast<uintptr_t>(object));
106         if (!freeObject->IsFreeObject()) {
107             RefFieldObjectVisitor refFieldObjectVisitor(visitor);
108             refFieldObjectVisitor.VisitAllRefFields(TaggedObject::Cast(object));
109         }
110     }
111 
GetSize(const BaseObject * object)112     size_t GetSize(const BaseObject *object) const override
113     {
114         ASSERT(!g_isEnableCMCGC || !object->IsForwarded());
115         auto freeObject = FreeObject::Cast(reinterpret_cast<uintptr_t>(object));
116         if (freeObject->IsFreeObject()) {
117             return freeObject->Available();
118         }
119         auto taggedObject = TaggedObject::Cast(object);
120         JSHClass *jsHclass = taggedObject->GetClass();
121         size_t size = jsHclass->SizeFromJSHClass(taggedObject);
122         return AlignUp<size_t>(size, 8); // 8 Byte alignment
123     }
124 
GetForwardingPointer(const BaseObject * object)125     BaseObject *GetForwardingPointer(const BaseObject *object) const override
126     {
127         return TaggedObject::Cast(object)->GetForwardingPointer();
128     }
129 
SetForwardingPointerAfterExclusive(BaseObject * object,BaseObject * fwdPtr)130     void SetForwardingPointerAfterExclusive(BaseObject *object, BaseObject *fwdPtr) override
131     {
132         TaggedObject::Cast(object)->SetForwardingPointerAfterExclusive(fwdPtr);
133     }
134 
135 private:
136     static DynamicObjectOperator dynOperator_;
137 };
138 }  // namespace panda::ecmascript
139 #endif  // ECMASCRIPT_MEM_DYNAMIC_OBJECT_OPERATOR_H
140