14514f5e3Sopenharmony_ci/* 24514f5e3Sopenharmony_ci * Copyright (c) 2022 Huawei Device Co., Ltd. 34514f5e3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 44514f5e3Sopenharmony_ci * you may not use this file except in compliance with the License. 54514f5e3Sopenharmony_ci * You may obtain a copy of the License at 64514f5e3Sopenharmony_ci * 74514f5e3Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 84514f5e3Sopenharmony_ci * 94514f5e3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 104514f5e3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 114514f5e3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 124514f5e3Sopenharmony_ci * See the License for the specific language governing permissions and 134514f5e3Sopenharmony_ci * limitations under the License. 144514f5e3Sopenharmony_ci */ 154514f5e3Sopenharmony_ci 164514f5e3Sopenharmony_ci#ifndef ECMASCRIPT_MEM_VISITOR_H 174514f5e3Sopenharmony_ci#define ECMASCRIPT_MEM_VISITOR_H 184514f5e3Sopenharmony_ci 194514f5e3Sopenharmony_ci#include <functional> 204514f5e3Sopenharmony_ci 214514f5e3Sopenharmony_ci#include <ecmascript/mem/slots.h> 224514f5e3Sopenharmony_ci#include <ecmascript/mem/tagged_object.h> 234514f5e3Sopenharmony_ci 244514f5e3Sopenharmony_cinamespace panda::ecmascript { 254514f5e3Sopenharmony_cienum class Root { 264514f5e3Sopenharmony_ci ROOT_FRAME, 274514f5e3Sopenharmony_ci ROOT_HANDLE, 284514f5e3Sopenharmony_ci ROOT_VM, 294514f5e3Sopenharmony_ci ROOT_STRING, 304514f5e3Sopenharmony_ci ROOT_INTERNAL_CALL_PARAMS, 314514f5e3Sopenharmony_ci}; 324514f5e3Sopenharmony_ci 334514f5e3Sopenharmony_cienum class VisitObjectArea { 344514f5e3Sopenharmony_ci NORMAL, 354514f5e3Sopenharmony_ci NATIVE_POINTER, 364514f5e3Sopenharmony_ci IN_OBJECT, 374514f5e3Sopenharmony_ci RAW_DATA 384514f5e3Sopenharmony_ci}; 394514f5e3Sopenharmony_ci 404514f5e3Sopenharmony_cienum class VisitType : size_t { SEMI_GC_VISIT, OLD_GC_VISIT, SNAPSHOT_VISIT, ALL_VISIT }; 414514f5e3Sopenharmony_cienum class VMRootVisitType : uint8_t { MARK, UPDATE_ROOT, VERIFY, HEAP_SNAPSHOT }; 424514f5e3Sopenharmony_ci 434514f5e3Sopenharmony_ciusing RootVisitor = std::function<void(Root type, ObjectSlot p)>; 444514f5e3Sopenharmony_ciusing RootRangeVisitor = std::function<void(Root type, ObjectSlot start, ObjectSlot end)>; 454514f5e3Sopenharmony_ciusing RootBaseAndDerivedVisitor = 464514f5e3Sopenharmony_ci std::function<void(Root type, ObjectSlot base, ObjectSlot derived, uintptr_t baseOldObject)>; 474514f5e3Sopenharmony_ciusing EcmaObjectRangeVisitor = std::function<void(TaggedObject *root, ObjectSlot start, ObjectSlot end, 484514f5e3Sopenharmony_ci VisitObjectArea area)>; 494514f5e3Sopenharmony_ciusing WeakRootVisitor = std::function<TaggedObject *(TaggedObject *p)>; 504514f5e3Sopenharmony_ci 514514f5e3Sopenharmony_citemplate <VisitType visitType, size_t size> 524514f5e3Sopenharmony_ciclass PrimitiveObjectBodyIterator { 534514f5e3Sopenharmony_cipublic: 544514f5e3Sopenharmony_ci static inline void IterateBody(TaggedObject *root, const EcmaObjectRangeVisitor& visitor) 554514f5e3Sopenharmony_ci { 564514f5e3Sopenharmony_ci if constexpr (visitType == VisitType::ALL_VISIT) { 574514f5e3Sopenharmony_ci constexpr size_t hclassEnd = sizeof(JSTaggedType); 584514f5e3Sopenharmony_ci visitor(root, ObjectSlot(ToUintPtr(root)), 594514f5e3Sopenharmony_ci ObjectSlot(ToUintPtr(root) + hclassEnd), VisitObjectArea::NORMAL); 604514f5e3Sopenharmony_ci if constexpr (size > hclassEnd) { 614514f5e3Sopenharmony_ci visitor(root, ObjectSlot(ToUintPtr(root) + hclassEnd), 624514f5e3Sopenharmony_ci ObjectSlot(ToUintPtr(root) + size), VisitObjectArea::RAW_DATA); 634514f5e3Sopenharmony_ci } 644514f5e3Sopenharmony_ci } 654514f5e3Sopenharmony_ci } 664514f5e3Sopenharmony_ci}; 674514f5e3Sopenharmony_ci 684514f5e3Sopenharmony_citemplate <VisitType visitType, size_t startOffset, size_t endOffset, 694514f5e3Sopenharmony_ci size_t size, size_t startSize = sizeof(JSTaggedType)> 704514f5e3Sopenharmony_ciclass ObjectBodyIterator { 714514f5e3Sopenharmony_cipublic: 724514f5e3Sopenharmony_ci template <VisitObjectArea area, bool visitHClass> 734514f5e3Sopenharmony_ci static inline void IterateBody(TaggedObject *root, const EcmaObjectRangeVisitor& visitor) 744514f5e3Sopenharmony_ci { 754514f5e3Sopenharmony_ci if constexpr (visitType == VisitType::ALL_VISIT) { 764514f5e3Sopenharmony_ci if constexpr (visitHClass) { 774514f5e3Sopenharmony_ci IterateHClass(root, visitor); 784514f5e3Sopenharmony_ci } 794514f5e3Sopenharmony_ci IterateBefore(root, visitor); 804514f5e3Sopenharmony_ci } 814514f5e3Sopenharmony_ci if constexpr (startOffset < endOffset) { 824514f5e3Sopenharmony_ci visitor(root, ObjectSlot(ToUintPtr(root) + startOffset), 834514f5e3Sopenharmony_ci ObjectSlot(ToUintPtr(root) + endOffset), area); 844514f5e3Sopenharmony_ci } 854514f5e3Sopenharmony_ci 864514f5e3Sopenharmony_ci if constexpr (visitType == VisitType::ALL_VISIT) { 874514f5e3Sopenharmony_ci IterateAfter(root, visitor); 884514f5e3Sopenharmony_ci } 894514f5e3Sopenharmony_ci } 904514f5e3Sopenharmony_ci 914514f5e3Sopenharmony_ci static inline void IterateRefBody(TaggedObject *root, const EcmaObjectRangeVisitor& visitor) 924514f5e3Sopenharmony_ci { 934514f5e3Sopenharmony_ci IterateBody<VisitObjectArea::NORMAL, true>(root, visitor); 944514f5e3Sopenharmony_ci } 954514f5e3Sopenharmony_ci 964514f5e3Sopenharmony_ci static inline void IterateNativeBody(TaggedObject *root, const EcmaObjectRangeVisitor& visitor) 974514f5e3Sopenharmony_ci { 984514f5e3Sopenharmony_ci IterateBody<VisitObjectArea::NATIVE_POINTER, true>(root, visitor); 994514f5e3Sopenharmony_ci } 1004514f5e3Sopenharmony_ci 1014514f5e3Sopenharmony_ci static inline void IterateDerivedRefBody(TaggedObject *root, const EcmaObjectRangeVisitor& visitor) 1024514f5e3Sopenharmony_ci { 1034514f5e3Sopenharmony_ci IterateBody<VisitObjectArea::NORMAL, false>(root, visitor); 1044514f5e3Sopenharmony_ci } 1054514f5e3Sopenharmony_ci 1064514f5e3Sopenharmony_ci static inline void IterateHClass(TaggedObject *root, const EcmaObjectRangeVisitor& visitor) 1074514f5e3Sopenharmony_ci { 1084514f5e3Sopenharmony_ci size_t hclassEnd = sizeof(JSTaggedType); 1094514f5e3Sopenharmony_ci visitor(root, ObjectSlot(ToUintPtr(root)), 1104514f5e3Sopenharmony_ci ObjectSlot(ToUintPtr(root) + hclassEnd), VisitObjectArea::NORMAL); 1114514f5e3Sopenharmony_ci } 1124514f5e3Sopenharmony_ci 1134514f5e3Sopenharmony_ci static inline void IterateBefore(TaggedObject *root, const EcmaObjectRangeVisitor& visitor) 1144514f5e3Sopenharmony_ci { 1154514f5e3Sopenharmony_ci if constexpr (startOffset > startSize) { 1164514f5e3Sopenharmony_ci ASSERT(startOffset != endOffset); 1174514f5e3Sopenharmony_ci IteratorRange(root, visitor, startSize, startOffset); 1184514f5e3Sopenharmony_ci } 1194514f5e3Sopenharmony_ci } 1204514f5e3Sopenharmony_ci 1214514f5e3Sopenharmony_ci static inline void IterateAfter(TaggedObject *root, const EcmaObjectRangeVisitor& visitor) 1224514f5e3Sopenharmony_ci { 1234514f5e3Sopenharmony_ci if constexpr (size > endOffset) { 1244514f5e3Sopenharmony_ci IteratorRange(root, visitor, endOffset, size); 1254514f5e3Sopenharmony_ci } 1264514f5e3Sopenharmony_ci } 1274514f5e3Sopenharmony_ci 1284514f5e3Sopenharmony_ci static inline void IteratorRange(TaggedObject *root, const EcmaObjectRangeVisitor& visitor, 1294514f5e3Sopenharmony_ci size_t start, size_t end) 1304514f5e3Sopenharmony_ci { 1314514f5e3Sopenharmony_ci visitor(root, ObjectSlot(ToUintPtr(root) + start), 1324514f5e3Sopenharmony_ci ObjectSlot(ToUintPtr(root) + end), VisitObjectArea::RAW_DATA); 1334514f5e3Sopenharmony_ci } 1344514f5e3Sopenharmony_ci}; 1354514f5e3Sopenharmony_ci 1364514f5e3Sopenharmony_citemplate <VisitType visitType, size_t startOffset> 1374514f5e3Sopenharmony_ciclass ArrayBodyIterator { 1384514f5e3Sopenharmony_cipublic: 1394514f5e3Sopenharmony_ci static inline void IterateBody(TaggedObject *root, const EcmaObjectRangeVisitor& visitor, 1404514f5e3Sopenharmony_ci size_t refLength, size_t length) 1414514f5e3Sopenharmony_ci { 1424514f5e3Sopenharmony_ci if constexpr (visitType == VisitType::ALL_VISIT) { 1434514f5e3Sopenharmony_ci IterateBefore(root, visitor); 1444514f5e3Sopenharmony_ci } 1454514f5e3Sopenharmony_ci if (LIKELY(refLength != 0)) { 1464514f5e3Sopenharmony_ci size_t endOffset = startOffset + refLength * JSTaggedValue::TaggedTypeSize(); 1474514f5e3Sopenharmony_ci visitor(root, ObjectSlot(ToUintPtr(root) + startOffset), 1484514f5e3Sopenharmony_ci ObjectSlot(ToUintPtr(root) + endOffset), VisitObjectArea::NORMAL); 1494514f5e3Sopenharmony_ci } 1504514f5e3Sopenharmony_ci if constexpr (visitType == VisitType::ALL_VISIT) { 1514514f5e3Sopenharmony_ci IterateAfter(root, visitor, refLength, length); 1524514f5e3Sopenharmony_ci } 1534514f5e3Sopenharmony_ci } 1544514f5e3Sopenharmony_ci 1554514f5e3Sopenharmony_ci static inline void IterateBefore(TaggedObject *root, const EcmaObjectRangeVisitor& visitor) 1564514f5e3Sopenharmony_ci { 1574514f5e3Sopenharmony_ci size_t hclassEnd = sizeof(JSTaggedType); 1584514f5e3Sopenharmony_ci ASSERT(startOffset > hclassEnd); 1594514f5e3Sopenharmony_ci visitor(root, ObjectSlot(ToUintPtr(root)), ObjectSlot(ToUintPtr(root) + hclassEnd), VisitObjectArea::NORMAL); 1604514f5e3Sopenharmony_ci IteratorRange(root, visitor, hclassEnd, startOffset); 1614514f5e3Sopenharmony_ci } 1624514f5e3Sopenharmony_ci 1634514f5e3Sopenharmony_ci static inline void IterateAfter(TaggedObject *root, const EcmaObjectRangeVisitor& visitor, 1644514f5e3Sopenharmony_ci size_t refLength, size_t length) 1654514f5e3Sopenharmony_ci { 1664514f5e3Sopenharmony_ci if (length > refLength) { 1674514f5e3Sopenharmony_ci size_t endOffset = startOffset + refLength * JSTaggedValue::TaggedTypeSize(); 1684514f5e3Sopenharmony_ci size_t size = startOffset + length * JSTaggedValue::TaggedTypeSize(); 1694514f5e3Sopenharmony_ci IteratorRange(root, visitor, endOffset, size); 1704514f5e3Sopenharmony_ci } 1714514f5e3Sopenharmony_ci } 1724514f5e3Sopenharmony_ci 1734514f5e3Sopenharmony_ci static inline void IteratorRange(TaggedObject *root, const EcmaObjectRangeVisitor& visitor, 1744514f5e3Sopenharmony_ci size_t start, size_t end) 1754514f5e3Sopenharmony_ci { 1764514f5e3Sopenharmony_ci visitor(root, ObjectSlot(ToUintPtr(root) + start), 1774514f5e3Sopenharmony_ci ObjectSlot(ToUintPtr(root) + end), VisitObjectArea::RAW_DATA); 1784514f5e3Sopenharmony_ci } 1794514f5e3Sopenharmony_ci}; 1804514f5e3Sopenharmony_ci} // namespace panda::ecmascript 1814514f5e3Sopenharmony_ci#endif // ECMASCRIPT_MEM_VISITOR_H 182