• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2024 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 PANDA_RUNTIME_MEM_NEW_OBJECT_HELPERS_INL_H
17 #define PANDA_RUNTIME_MEM_NEW_OBJECT_HELPERS_INL_H
18 
19 #include "runtime/mem/object-references-iterator.h"
20 #include "runtime/include/coretypes/array-inl.h"
21 #include "runtime/include/class-inl.h"
22 
23 namespace ark::mem {
24 class ObjectArrayIterator {
25 public:
26     template <typename T, bool INTERRUPTIBLE, typename Handler>
27     static bool Iterate(coretypes::Array *array, Handler *handler);
28 
29     template <typename T, bool INTERRUPTIBLE, typename Handler>
30     static bool Iterate(coretypes::Array *array, Handler *handler, void *begin, void *end);
31 };
32 
33 template <typename T, bool INTERRUPTIBLE, typename Handler>
Iterate(coretypes::Array * array,Handler * handler)34 bool ObjectArrayIterator::Iterate(coretypes::Array *array, Handler *handler)
35 {
36     auto *arrayStart = array->GetBase<T *>();
37     // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
38     auto *arrayEnd = arrayStart + array->GetLength();
39 
40     // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
41     for (auto *p = arrayStart; p < arrayEnd; ++p) {
42         [[maybe_unused]] auto cont = handler->ProcessObjectPointer(p);
43         if constexpr (INTERRUPTIBLE) {
44             if (!cont) {
45                 return false;
46             }
47         }
48     }
49 
50     return true;
51 }
52 
53 template <typename T, bool INTERRUPTIBLE, typename Handler>
Iterate(coretypes::Array * array,Handler * handler,void * begin,void * end)54 bool ObjectArrayIterator::Iterate(coretypes::Array *array, Handler *handler, void *begin, void *end)
55 {
56     ASSERT(IsAligned(ToUintPtr(begin), DEFAULT_ALIGNMENT_IN_BYTES));
57 
58     auto *arrayStart = array->GetBase<T *>();
59     // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
60     auto *arrayEnd = arrayStart + array->GetLength();
61     auto *p = begin < arrayStart ? arrayStart : reinterpret_cast<T *>(begin);
62 
63     if (end > arrayEnd) {
64         end = arrayEnd;
65     }
66 
67     // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
68     for (; p < end; ++p) {
69         [[maybe_unused]] auto cont = handler->ProcessObjectPointer(p);
70         if constexpr (INTERRUPTIBLE) {
71             if (!cont) {
72                 return false;
73             }
74         }
75     }
76 
77     return true;
78 }
79 
80 template <bool INTERRUPTIBLE, typename Handler>
Iterate(ObjectHeader * obj,Handler * handler,void * begin,void * end)81 bool ObjectIterator<LANG_TYPE_STATIC>::Iterate(ObjectHeader *obj, Handler *handler, void *begin, void *end)
82 {
83     auto *cls = obj->ClassAddr<Class>();
84     ASSERT(cls != nullptr);
85     return Iterate<INTERRUPTIBLE>(cls, obj, handler, begin, end);
86 }
87 
88 template <typename Handler>
IterateAndDiscoverReferences(GC * gc,ObjectHeader * obj,Handler * handler)89 bool ObjectIterator<LANG_TYPE_STATIC>::IterateAndDiscoverReferences(GC *gc, ObjectHeader *obj, Handler *handler)
90 {
91     auto *cls = obj->ClassAddr<Class>();
92     ASSERT(cls != nullptr);
93 
94     if (gc->IsReference(cls, obj, [gc](auto *o) { return gc->InGCSweepRange(o); })) {
95         gc->ProcessReferenceForSinglePassCompaction(
96             cls, obj, [handler](void *o) { handler->ProcessObjectPointer(reinterpret_cast<ObjectPointerType *>(o)); });
97         return true;
98     }
99 
100     return Iterate<false>(cls, obj, handler);
101 }
102 
103 template <typename Handler>
IterateAndDiscoverReferences(GC * gc,ObjectHeader * obj,Handler * handler,void * begin,void * end)104 bool ObjectIterator<LANG_TYPE_STATIC>::IterateAndDiscoverReferences(GC *gc, ObjectHeader *obj, Handler *handler,
105                                                                     void *begin, void *end)
106 {
107     auto *cls = obj->ClassAddr<Class>();
108     ASSERT(cls != nullptr);
109 
110     if (gc->IsReference(cls, obj, [gc](auto *o) { return gc->InGCSweepRange(o); })) {
111         gc->ProcessReferenceForSinglePassCompaction(
112             cls, obj, [handler](void *o) { handler->ProcessObjectPointer(reinterpret_cast<ObjectPointerType *>(o)); });
113         return true;
114     }
115 
116     return Iterate<false>(cls, obj, handler, begin, end);
117 }
118 
119 template <bool INTERRUPTIBLE, typename Handler>
Iterate(Class * cls,ObjectHeader * obj,Handler * handler)120 bool ObjectIterator<LANG_TYPE_STATIC>::Iterate(Class *cls, ObjectHeader *obj, Handler *handler)
121 {
122     if (cls->IsObjectArrayClass()) {
123         return ObjectArrayIterator::Iterate<ObjectPointerType, INTERRUPTIBLE>(static_cast<coretypes::Array *>(obj),
124                                                                               handler);
125     }
126     if (cls->IsClassClass()) {
127         auto *objectClass = ark::Class::FromClassObject(obj);
128         if (objectClass->IsInitializing() || objectClass->IsInitialized()) {
129             if (!IterateClassReferences<INTERRUPTIBLE>(objectClass, handler)) {
130                 return false;
131             }
132         }
133     }
134 
135     return IterateObjectReferences<INTERRUPTIBLE>(obj, cls, handler);
136 }
137 
138 template <bool INTERRUPTIBLE, typename Handler>
Iterate(Class * cls,ObjectHeader * obj,Handler * handler,void * begin,void * end)139 bool ObjectIterator<LANG_TYPE_STATIC>::Iterate(Class *cls, ObjectHeader *obj, Handler *handler, void *begin, void *end)
140 {
141     if (cls->IsObjectArrayClass()) {
142         return ObjectArrayIterator::Iterate<ObjectPointerType, INTERRUPTIBLE>(static_cast<coretypes::Array *>(obj),
143                                                                               handler, begin, end);
144     }
145     if (cls->IsClassClass()) {
146         auto *objectClass = ark::Class::FromClassObject(obj);
147         if (objectClass->IsInitializing() || objectClass->IsInitialized()) {
148             if (!IterateClassReferences<INTERRUPTIBLE>(objectClass, handler, begin, end)) {
149                 return false;
150             }
151         }
152     }
153 
154     if (obj >= begin && !cls->IsVariableSize() && ToUintPtr(obj) + cls->GetObjectSize() <= ToUintPtr(end)) {
155         return IterateObjectReferences<INTERRUPTIBLE>(obj, cls, handler);
156     }
157 
158     return IterateObjectReferences<INTERRUPTIBLE>(obj, cls, handler, begin, end);
159 }
160 
161 template <bool INTERRUPTIBLE, typename Handler>
IterateClassReferences(Class * cls,Handler * handler)162 bool ObjectIterator<LANG_TYPE_STATIC>::IterateClassReferences(Class *cls, Handler *handler)
163 {
164     auto refNum = cls->GetRefFieldsNum<true>();
165     if (refNum > 0) {
166         auto offset = cls->GetRefFieldsOffset<true>();
167         // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
168         auto *refStart = reinterpret_cast<ObjectPointerType *>(ToUintPtr(cls) + offset);
169         // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
170         auto *refEnd = refStart + refNum;
171         return IterateRange<INTERRUPTIBLE>(refStart, refEnd, handler);
172     }
173     return true;
174 }
175 
176 template <bool INTERRUPTIBLE, typename Handler>
IterateClassReferences(Class * cls,Handler * handler,void * begin,void * end)177 bool ObjectIterator<LANG_TYPE_STATIC>::IterateClassReferences(Class *cls, Handler *handler, void *begin, void *end)
178 {
179     auto refNum = cls->GetRefFieldsNum<true>();
180     if (refNum > 0) {
181         auto offset = cls->GetRefFieldsOffset<true>();
182         // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
183         auto *refStart = reinterpret_cast<ObjectPointerType *>(ToUintPtr(cls) + offset);
184         // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
185         auto *refEnd = refStart + refNum;
186         return IterateRange<INTERRUPTIBLE>(refStart, refEnd, handler, begin, end);
187     }
188     return true;
189 }
190 
191 template <bool INTERRUPTIBLE, typename Handler>
IterateObjectReferences(ObjectHeader * object,Class * objClass,Handler * handler)192 bool ObjectIterator<LANG_TYPE_STATIC>::IterateObjectReferences(ObjectHeader *object, Class *objClass, Handler *handler)
193 {
194     ASSERT(objClass != nullptr);
195     ASSERT(!objClass->IsDynamicClass());
196     auto *cls = objClass;
197     while (cls != nullptr) {
198         auto refNum = cls->GetRefFieldsNum<false>();
199         if (refNum == 0) {
200             cls = cls->GetBase();
201             continue;
202         }
203 
204         auto offset = cls->GetRefFieldsOffset<false>();
205         // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
206         auto *refStart = reinterpret_cast<ObjectPointerType *>(ToUintPtr(object) + offset);
207         // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
208         auto *refEnd = refStart + refNum;
209         ASSERT_PRINT(ToUintPtr(refEnd) <= ToUintPtr(object) + objClass->GetObjectSize(),
210                      "cls " << objClass->GetName() << " obj " << object << " size " << objClass->GetObjectSize()
211                             << " refs " << refStart << ".." << refEnd);
212         [[maybe_unused]] auto cont = IterateRange<INTERRUPTIBLE>(refStart, refEnd, handler);
213         if constexpr (INTERRUPTIBLE) {
214             if (!cont) {
215                 return false;
216             }
217         }
218 
219         cls = cls->GetBase();
220     }
221     return true;
222 }
223 
224 template <bool INTERRUPTIBLE, typename Handler>
IterateObjectReferences(ObjectHeader * object,Class * cls,Handler * handler,void * begin,void * end)225 bool ObjectIterator<LANG_TYPE_STATIC>::IterateObjectReferences(ObjectHeader *object, Class *cls, Handler *handler,
226                                                                void *begin, void *end)
227 {
228     ASSERT(cls != nullptr);
229     ASSERT(!cls->IsDynamicClass());
230     while (cls != nullptr) {
231         auto refNum = cls->GetRefFieldsNum<false>();
232         if (refNum == 0) {
233             cls = cls->GetBase();
234             continue;
235         }
236 
237         auto offset = cls->GetRefFieldsOffset<false>();
238         // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
239         auto *refStart = reinterpret_cast<ObjectPointerType *>(ToUintPtr(object) + offset);
240         // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
241         auto *refEnd = refStart + refNum;
242         [[maybe_unused]] auto cont = IterateRange<INTERRUPTIBLE>(refStart, refEnd, handler, begin, end);
243         if constexpr (INTERRUPTIBLE) {
244             if (!cont) {
245                 return false;
246             }
247         }
248 
249         cls = cls->GetBase();
250     }
251     return true;
252 }
253 
254 template <bool INTERRUPTIBLE, typename Handler>
IterateRange(ObjectPointerType * refStart,const ObjectPointerType * refEnd,Handler * handler)255 bool ObjectIterator<LANG_TYPE_STATIC>::IterateRange(ObjectPointerType *refStart, const ObjectPointerType *refEnd,
256                                                     Handler *handler)
257 {
258     // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
259     for (auto *p = refStart; p < refEnd; p++) {
260         [[maybe_unused]] auto cont = handler->ProcessObjectPointer(p);
261         if constexpr (INTERRUPTIBLE) {
262             if (!cont) {
263                 return false;
264             }
265         }
266     }
267     return true;
268 }
269 
270 template <bool INTERRUPTIBLE, typename Handler>
IterateRange(ObjectPointerType * refStart,ObjectPointerType * refEnd,Handler * handler,void * begin,void * end)271 bool ObjectIterator<LANG_TYPE_STATIC>::IterateRange(ObjectPointerType *refStart, ObjectPointerType *refEnd,
272                                                     Handler *handler, void *begin, void *end)
273 {
274     auto *p = begin < refStart ? refStart : reinterpret_cast<ObjectPointerType *>(begin);
275     if (end > refEnd) {
276         end = refEnd;
277     }
278     // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
279     for (; p < end; p++) {
280         [[maybe_unused]] auto cont = handler->ProcessObjectPointer(p);
281         if constexpr (INTERRUPTIBLE) {
282             if (!cont) {
283                 return false;
284             }
285         }
286     }
287     return true;
288 }
289 
290 template <bool INTERRUPTIBLE, typename Handler>
Iterate(ObjectHeader * obj,Handler * handler,void * begin,void * end)291 bool ObjectIterator<LANG_TYPE_DYNAMIC>::Iterate(ObjectHeader *obj, Handler *handler, void *begin, void *end)
292 {
293     auto *cls = obj->ClassAddr<HClass>();
294     ASSERT(cls != nullptr && cls->IsDynamicClass());
295     return Iterate<INTERRUPTIBLE>(cls, obj, handler, begin, end);
296 }
297 
298 template <typename Handler>
IterateAndDiscoverReferences(GC * gc,ObjectHeader * obj,Handler * handler)299 bool ObjectIterator<LANG_TYPE_DYNAMIC>::IterateAndDiscoverReferences(GC *gc, ObjectHeader *obj, Handler *handler)
300 {
301     auto *cls = obj->ClassAddr<HClass>();
302     ASSERT(cls != nullptr && cls->IsDynamicClass());
303 
304     if (gc->IsReference(cls, obj, [gc](auto *o) { return gc->InGCSweepRange(o); })) {
305         gc->ProcessReferenceForSinglePassCompaction(
306             cls, obj, [handler](void *o) { handler->ProcessObjectPointer(reinterpret_cast<TaggedType *>(o)); });
307         return true;
308     }
309 
310     return Iterate<false>(cls, obj, handler);
311 }
312 
313 template <typename Handler>
IterateAndDiscoverReferences(GC * gc,ObjectHeader * obj,Handler * handler,void * begin,void * end)314 bool ObjectIterator<LANG_TYPE_DYNAMIC>::IterateAndDiscoverReferences(GC *gc, ObjectHeader *obj, Handler *handler,
315                                                                      void *begin, void *end)
316 {
317     auto *cls = obj->ClassAddr<HClass>();
318     ASSERT(cls != nullptr && cls->IsDynamicClass());
319 
320     if (gc->IsReference(cls, obj, [gc](auto *o) { return gc->InGCSweepRange(o); })) {
321         gc->ProcessReferenceForSinglePassCompaction(
322             cls, obj, [handler](void *o) { handler->ProcessObjectPointer(reinterpret_cast<TaggedType *>(o)); });
323         return true;
324     }
325 
326     return Iterate<false>(cls, obj, handler, begin, end);
327 }
328 
329 template <bool INTERRUPTIBLE, typename Handler>
Iterate(HClass * cls,ObjectHeader * obj,Handler * handler)330 bool ObjectIterator<LANG_TYPE_DYNAMIC>::Iterate(HClass *cls, ObjectHeader *obj, Handler *handler)
331 {
332     if (cls->IsString() || cls->IsNativePointer()) {
333         return true;
334     }
335     if (cls->IsArray()) {
336         return ObjectArrayIterator::Iterate<TaggedType, INTERRUPTIBLE>(static_cast<coretypes::Array *>(obj), handler);
337     }
338     if (cls->IsHClass()) {
339         return IterateClassReferences<INTERRUPTIBLE>(coretypes::DynClass::Cast(obj), handler);
340     }
341 
342     return IterateObjectReferences<INTERRUPTIBLE>(obj, cls, handler);
343 }
344 
345 template <bool INTERRUPTIBLE, typename Handler>
Iterate(HClass * cls,ObjectHeader * obj,Handler * handler,void * begin,void * end)346 bool ObjectIterator<LANG_TYPE_DYNAMIC>::Iterate(HClass *cls, ObjectHeader *obj, Handler *handler, void *begin,
347                                                 void *end)
348 {
349     if (cls->IsString() || cls->IsNativePointer()) {
350         return true;
351     }
352     if (cls->IsArray()) {
353         return ObjectArrayIterator::Iterate<TaggedType, INTERRUPTIBLE>(static_cast<coretypes::Array *>(obj), handler,
354                                                                        begin, end);
355     }
356     if (cls->IsHClass()) {
357         return IterateClassReferences<INTERRUPTIBLE>(coretypes::DynClass::Cast(obj), handler, begin, end);
358     }
359 
360     return IterateObjectReferences<INTERRUPTIBLE>(obj, cls, handler, begin, end);
361 }
362 
363 template <bool INTERRUPTIBLE, typename Handler>
IterateClassReferences(coretypes::DynClass * dynClass,Handler * handler)364 bool ObjectIterator<LANG_TYPE_DYNAMIC>::IterateClassReferences(coretypes::DynClass *dynClass, Handler *handler)
365 {
366     auto hklassSize = dynClass->ClassAddr<HClass>()->GetObjectSize() - sizeof(coretypes::DynClass);
367     auto bodySize = hklassSize - sizeof(HClass);
368     auto numOfFields = bodySize / TaggedValue::TaggedTypeSize();
369     auto fieldOffset = sizeof(ObjectHeader) + sizeof(HClass);
370     // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
371     auto *fieldStart = reinterpret_cast<TaggedType *>(ToUintPtr(dynClass) + fieldOffset);
372     // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
373     auto *fieldEnd = fieldStart + numOfFields;
374     // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
375     for (auto *p = fieldStart; p < fieldEnd; p++) {
376         [[maybe_unused]] auto cont = handler->ProcessObjectPointer(p);
377         if constexpr (INTERRUPTIBLE) {
378             if (!cont) {
379                 return false;
380             }
381         }
382     }
383     return true;
384 }
385 
386 template <bool INTERRUPTIBLE, typename Handler>
IterateClassReferences(coretypes::DynClass * dynClass,Handler * handler,void * begin,void * end)387 bool ObjectIterator<LANG_TYPE_DYNAMIC>::IterateClassReferences(coretypes::DynClass *dynClass, Handler *handler,
388                                                                void *begin, void *end)
389 {
390     auto hklassSize = dynClass->ClassAddr<HClass>()->GetObjectSize() - sizeof(coretypes::DynClass);
391     auto bodySize = hklassSize - sizeof(HClass);
392     auto numOfFields = bodySize / TaggedValue::TaggedTypeSize();
393     auto fieldOffset = sizeof(ObjectHeader) + sizeof(HClass);
394     // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
395     auto *fieldStart = reinterpret_cast<TaggedType *>(ToUintPtr(dynClass) + fieldOffset);
396     // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
397     auto *fieldEnd = fieldStart + numOfFields;
398     auto *p = begin < fieldStart ? fieldStart : reinterpret_cast<TaggedType *>(begin);
399     if (end > fieldEnd) {
400         end = fieldEnd;
401     }
402     // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
403     for (; p < end; p++) {
404         [[maybe_unused]] auto cont = handler->ProcessObjectPointer(p);
405         if constexpr (INTERRUPTIBLE) {
406             if (!cont) {
407                 return false;
408             }
409         }
410     }
411     return true;
412 }
413 
414 template <bool INTERRUPTIBLE, typename Handler>
IterateObjectReferences(ObjectHeader * object,HClass * cls,Handler * handler)415 bool ObjectIterator<LANG_TYPE_DYNAMIC>::IterateObjectReferences(ObjectHeader *object, HClass *cls, Handler *handler)
416 {
417     ASSERT(cls->IsDynamicClass());
418     LOG(DEBUG, GC) << "TraverseObject Current object: " << GetDebugInfoAboutObject(object);
419     auto objBodySize = cls->GetObjectSize() - ObjectHeader::ObjectHeaderSize();
420     ASSERT(objBodySize % TaggedValue::TaggedTypeSize() == 0);
421     auto numOfFields = objBodySize / TaggedValue::TaggedTypeSize();
422     auto dataOffset = ObjectHeader::ObjectHeaderSize();
423     // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
424     auto *fieldStart = reinterpret_cast<TaggedType *>(ToUintPtr(object) + dataOffset);
425     // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
426     auto *fieldEnd = fieldStart + numOfFields;
427     // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
428     for (auto *p = fieldStart; p < fieldEnd; p++) {
429         if (cls->IsNativeField(ToUintPtr(p) - ToUintPtr(object))) {
430             continue;
431         }
432         [[maybe_unused]] auto cont = handler->ProcessObjectPointer(p);
433         if constexpr (INTERRUPTIBLE) {
434             if (!cont) {
435                 return false;
436             }
437         }
438     }
439     return true;
440 }
441 
442 template <bool INTERRUPTIBLE, typename Handler>
IterateObjectReferences(ObjectHeader * object,HClass * cls,Handler * handler,void * begin,void * end)443 bool ObjectIterator<LANG_TYPE_DYNAMIC>::IterateObjectReferences(ObjectHeader *object, HClass *cls, Handler *handler,
444                                                                 void *begin, void *end)
445 {
446     ASSERT(cls->IsDynamicClass());
447     LOG(DEBUG, GC) << "TraverseObject Current object: " << GetDebugInfoAboutObject(object);
448     auto objBodySize = cls->GetObjectSize() - ObjectHeader::ObjectHeaderSize();
449     ASSERT(objBodySize % TaggedValue::TaggedTypeSize() == 0);
450     auto numOfFields = objBodySize / TaggedValue::TaggedTypeSize();
451     auto dataOffset = ObjectHeader::ObjectHeaderSize();
452     // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
453     auto *fieldStart = reinterpret_cast<TaggedType *>(ToUintPtr(object) + dataOffset);
454     // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
455     auto *fieldEnd = fieldStart + numOfFields;
456     auto *p = begin < fieldStart ? fieldStart : reinterpret_cast<TaggedType *>(begin);
457     if (end > fieldEnd) {
458         end = fieldEnd;
459     }
460     // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
461     for (; p < end; p++) {
462         if (cls->IsNativeField(ToUintPtr(p) - ToUintPtr(object))) {
463             continue;
464         }
465         [[maybe_unused]] auto cont = handler->ProcessObjectPointer(p);
466         if constexpr (INTERRUPTIBLE) {
467             if (!cont) {
468                 return false;
469             }
470         }
471     }
472     return true;
473 }
474 }  // namespace ark::mem
475 
476 #endif  // PANDA_RUNTIME_MEM_NEW_OBJECT_HELPERS_INL_H
477