• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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_INCLUDE_CLASS_H_
17 #define PANDA_RUNTIME_INCLUDE_CLASS_H_
18 
19 #include <securec.h>
20 #include <atomic>
21 #include <cstdint>
22 #include <iostream>
23 #include <memory>
24 
25 #include "libpandafile/file.h"
26 #include "libpandafile/file_items.h"
27 #include "runtime/include/field.h"
28 #include "runtime/include/itable.h"
29 #include "runtime/include/method.h"
30 #include "runtime/include/object_header.h"
31 #include "libpandabase/macros.h"
32 
33 namespace panda {
34 
35 class ClassLinkerContext;
36 class Field;
37 class ManagedThread;
38 
39 class BaseClass {
40 public:
41     static constexpr uint32_t DYNAMIC_CLASS = 1U;
42 
43 public:
BaseClass(panda_file::SourceLang lang)44     explicit BaseClass(panda_file::SourceLang lang) : lang_(lang) {}
45 
46     ~BaseClass() = default;
47 
48     DEFAULT_COPY_SEMANTIC(BaseClass);
49     DEFAULT_MOVE_SEMANTIC(BaseClass);
50 
GetFlags()51     uint32_t GetFlags() const
52     {
53         return flags_;
54     }
55 
SetFlags(uint32_t flags)56     void SetFlags(uint32_t flags)
57     {
58         flags_ = flags;
59     }
60 
IsDynamicClass()61     bool IsDynamicClass() const
62     {
63         return (flags_ & DYNAMIC_CLASS) != 0;
64     }
65 
GetObjectSize()66     uint32_t GetObjectSize() const
67     {
68         return object_size_;
69     }
70 
SetObjectSize(uint32_t size)71     void SetObjectSize(uint32_t size)
72     {
73         object_size_ = size;
74     }
75 
SetManagedObject(ObjectHeader * obj)76     void SetManagedObject(ObjectHeader *obj)
77     {
78         managed_object_ = obj;
79     }
80 
GetManagedObject()81     ObjectHeader *GetManagedObject() const
82     {
83         return managed_object_;
84     }
85 
GetSourceLang()86     panda_file::SourceLang GetSourceLang() const
87     {
88         return lang_;
89     }
90 
SetSourceLang(panda_file::SourceLang lang)91     void SetSourceLang(panda_file::SourceLang lang)
92     {
93         lang_ = lang;
94     }
95 
OffsetOfManageObject()96     static constexpr size_t OffsetOfManageObject()
97     {
98         return offsetof(BaseClass, managed_object_);
99     }
100 
101 private:
102     uint32_t flags_ {0};
103     // Size of the object of this class. In case of static classes it is 0
104     // for abstract classes, interfaces and classes whose objects
105     // have variable size (for example strings).
106     uint32_t object_size_ {0};
107     ObjectHeader *managed_object_ {nullptr};
108     panda_file::SourceLang lang_;
109 };
110 
111 class Class : public BaseClass {
112 public:
113     using UniqId = uint64_t;
114     static constexpr uint32_t STRING_CLASS = 1U << 1U;
115     static constexpr size_t IMTABLE_SIZE = 32;
116 
117     enum {
118         DUMPCLASSFULLDETAILS = 1,
119         DUMPCLASSCLASSLODER = 2,
120         DUMPCLASSINITIALIZED = 4,
121     };
122 
123     enum class State : uint8_t { INITIAL = 0, LOADED, VERIFIED, INITIALIZING, ERRONEOUS, INITIALIZED };
124 
125     Class(const uint8_t *descriptor, panda_file::SourceLang lang, uint32_t vtable_size, uint32_t imt_size,
126           uint32_t size);
127 
GetBase()128     Class *GetBase() const
129     {
130         return base_;
131     }
132 
SetBase(Class * base)133     void SetBase(Class *base)
134     {
135         base_ = base;
136     }
137 
GetFileId()138     panda_file::File::EntityId GetFileId() const
139     {
140         return file_id_;
141     }
142 
SetFileId(panda_file::File::EntityId file_id)143     void SetFileId(panda_file::File::EntityId file_id)
144     {
145         file_id_ = file_id;
146     }
147 
GetPandaFile()148     const panda_file::File *GetPandaFile() const
149     {
150         return panda_file_;
151     }
152 
SetPandaFile(const panda_file::File * pf)153     void SetPandaFile(const panda_file::File *pf)
154     {
155         panda_file_ = pf;
156     }
157 
GetDescriptor()158     const uint8_t *GetDescriptor() const
159     {
160         return descriptor_;
161     }
162 
SetMethods(Span<Method> methods,uint32_t num_vmethods,uint32_t num_smethods)163     void SetMethods(Span<Method> methods, uint32_t num_vmethods, uint32_t num_smethods)
164     {
165         methods_ = methods.data();
166         num_methods_ = num_vmethods + num_smethods;
167         num_vmethods_ = num_vmethods;
168         num_copied_methods_ = methods.size() - num_methods_;
169     }
170 
GetMethods()171     Span<Method> GetMethods() const
172     {
173         return {methods_, num_methods_};
174     }
175 
GetStaticMethods()176     Span<Method> GetStaticMethods() const
177     {
178         return GetMethods().SubSpan(num_vmethods_);
179     }
180 
GetVirtualMethods()181     Span<Method> GetVirtualMethods() const
182     {
183         return {methods_, num_vmethods_};
184     }
185 
GetCopiedMethods()186     Span<Method> GetCopiedMethods() const
187     {
188         Span<Method> res {methods_, num_methods_ + num_copied_methods_};
189         return res.SubSpan(num_methods_);
190     }
191 
GetFields()192     Span<Field> GetFields() const
193     {
194         return {fields_, num_fields_};
195     }
196 
GetStaticFields()197     Span<Field> GetStaticFields() const
198     {
199         return {fields_, num_sfields_};
200     }
201 
GetInstanceFields()202     Span<Field> GetInstanceFields() const
203     {
204         return GetFields().SubSpan(num_sfields_);
205     }
206 
SetFields(Span<Field> fields,uint32_t num_sfields)207     void SetFields(Span<Field> fields, uint32_t num_sfields)
208     {
209         fields_ = fields.data();
210         num_fields_ = fields.size();
211         num_sfields_ = num_sfields;
212     }
213 
GetVTable()214     Span<Method *> GetVTable()
215     {
216         return GetClassSpan().SubSpan<Method *>(GetVTableOffset(), vtable_size_);
217     }
218 
GetVTable()219     Span<Method *const> GetVTable() const
220     {
221         return GetClassSpan().SubSpan<Method *const>(GetVTableOffset(), vtable_size_);
222     }
223 
GetInterfaces()224     Span<Class *> GetInterfaces() const
225     {
226         return {ifaces_, num_ifaces_};
227     }
228 
SetInterfaces(Span<Class * > ifaces)229     void SetInterfaces(Span<Class *> ifaces)
230     {
231         ifaces_ = ifaces.data();
232         num_ifaces_ = ifaces.size();
233     }
234 
GetIMT()235     Span<Method *> GetIMT()
236     {
237         return GetClassSpan().SubSpan<Method *>(GetIMTOffset(), imt_size_);
238     }
239 
GetIMT()240     Span<Method *const> GetIMT() const
241     {
242         return GetClassSpan().SubSpan<Method *const>(GetIMTOffset(), imt_size_);
243     }
244 
GetIMTableIndex(uint32_t method_offset)245     uint32_t GetIMTableIndex(uint32_t method_offset) const
246     {
247         ASSERT(imt_size_ != 0);
248         return method_offset % imt_size_;
249     }
250 
GetAccessFlags()251     uint32_t GetAccessFlags() const
252     {
253         return access_flags_;
254     }
255 
SetAccessFlags(uint32_t access_flags)256     void SetAccessFlags(uint32_t access_flags)
257     {
258         access_flags_ = access_flags;
259     }
260 
IsPublic()261     bool IsPublic() const
262     {
263         return (access_flags_ & ACC_PUBLIC) != 0;
264     }
265 
IsFinal()266     bool IsFinal() const
267     {
268         return (access_flags_ & ACC_FINAL) != 0;
269     }
270 
IsAnnotation()271     bool IsAnnotation() const
272     {
273         return (access_flags_ & ACC_ANNOTATION) != 0;
274     }
275 
IsEnum()276     bool IsEnum() const
277     {
278         return (access_flags_ & ACC_ENUM) != 0;
279     }
280 
GetVTableSize()281     uint32_t GetVTableSize() const
282     {
283         return vtable_size_;
284     }
285 
GetIMTSize()286     uint32_t GetIMTSize() const
287     {
288         return imt_size_;
289     }
290 
GetClassSize()291     uint32_t GetClassSize() const
292     {
293         return class_size_;
294     }
295 
GetObjectSize()296     uint32_t GetObjectSize() const
297     {
298         ASSERT(!IsVariableSize());
299         return BaseClass::GetObjectSize();
300     }
301 
SetObjectSize(uint32_t size)302     void SetObjectSize(uint32_t size)
303     {
304         ASSERT(!IsVariableSize());
305         BaseClass::SetObjectSize(size);
306     }
307 
308     static uint32_t GetTypeSize(panda_file::Type type);
309     uint32_t GetComponentSize() const;
310 
GetComponentType()311     Class *GetComponentType() const
312     {
313         return component_type_;
314     }
315 
SetComponentType(Class * type)316     void SetComponentType(Class *type)
317     {
318         component_type_ = type;
319     }
320 
IsArrayClass()321     bool IsArrayClass() const
322     {
323         return component_type_ != nullptr;
324     }
325 
IsObjectArrayClass()326     bool IsObjectArrayClass() const
327     {
328         return IsArrayClass() && !component_type_->IsPrimitive();
329     }
330 
IsStringClass()331     bool IsStringClass() const
332     {
333         return (GetFlags() & STRING_CLASS) != 0;
334     }
335 
IsVariableSize()336     bool IsVariableSize() const
337     {
338         return IsArrayClass() || IsStringClass();
339     }
340 
GetStaticFieldsOffset()341     size_t GetStaticFieldsOffset() const
342     {
343         return ClassHelper::ComputeClassSize(vtable_size_, imt_size_, 0, 0, 0, 0, 0, 0);
344     }
345 
GetType()346     panda_file::Type GetType() const
347     {
348         return type_;
349     }
350 
SetType(panda_file::Type type)351     void SetType(panda_file::Type type)
352     {
353         type_ = type;
354     }
355 
IsPrimitive()356     bool IsPrimitive() const
357     {
358         return type_.IsPrimitive();
359     }
360 
IsAbstract()361     bool IsAbstract() const
362     {
363         return (access_flags_ & ACC_ABSTRACT) != 0;
364     }
365 
IsInterface()366     bool IsInterface() const
367     {
368         return (access_flags_ & ACC_INTERFACE) != 0;
369     }
370 
IsInstantiable()371     bool IsInstantiable() const
372     {
373         return (!IsPrimitive() && !IsAbstract() && !IsInterface()) || IsArrayClass();
374     }
375 
IsObjectClass()376     bool IsObjectClass() const
377     {
378         return !IsPrimitive() && GetBase() == nullptr;
379     }
380 
381     /**
382      * Check if the object is Class instance
383      * @return true if the object is Class instance
384      */
IsClassClass()385     bool IsClassClass() const
386     {
387         return GetManagedObject()->ClassAddr<Class>() == this;
388     }
389 
390     bool IsSubClassOf(const Class *klass) const;
391 
392     /**
393      * Check whether an instance of this class can be assigned from an instance of class "klass".
394      * Object of type O is instance of type T if O is the same as T or is subtype of T. For arrays T should be a root
395      * type in type hierarchy or T is such array that O array elements are the same or subtype of T array elements.
396      */
397     bool IsAssignableFrom(const Class *klass) const;
398 
IsProxy()399     bool IsProxy() const
400     {
401         return (GetAccessFlags() & ACC_PROXY) != 0;
402     }
403 
404     bool Implements(const Class *klass) const;
405 
SetITable(ITable itable)406     void SetITable(ITable itable)
407     {
408         itable_ = itable;
409     }
410 
GetITable()411     ITable GetITable() const
412     {
413         return itable_;
414     }
415 
GetState()416     State GetState() const
417     {
418         return state_;
419     }
420 
421     void SetState(State state);
422 
IsVerified()423     bool IsVerified() const
424     {
425         return state_ >= State::VERIFIED;
426     }
427 
IsInitializing()428     bool IsInitializing() const
429     {
430         return state_ == State::INITIALIZING;
431     }
432 
IsInitialized()433     bool IsInitialized() const
434     {
435         return state_ == State::INITIALIZED;
436     }
437 
IsLoaded()438     bool IsLoaded() const
439     {
440         return state_ >= State::LOADED;
441     }
442 
IsErroneous()443     bool IsErroneous() const
444     {
445         return state_ == State::ERRONEOUS;
446     }
447 
GetStateOffset()448     static constexpr uint32_t GetStateOffset()
449     {
450         return MEMBER_OFFSET(Class, state_);
451     }
452 
GetComponentTypeOffset()453     static constexpr uint32_t GetComponentTypeOffset()
454     {
455         return MEMBER_OFFSET(Class, component_type_);
456     }
457 
GetTypeOffset()458     static constexpr uint32_t GetTypeOffset()
459     {
460         return MEMBER_OFFSET(Class, type_);
461     }
462 
GetBaseOffset()463     static constexpr uint32_t GetBaseOffset()
464     {
465         return MEMBER_OFFSET(Class, base_);
466     }
467 
GetInitializedValue()468     uint8_t GetInitializedValue()
469     {
470         return static_cast<uint8_t>(State::INITIALIZED);
471     }
472 
IsVerifiedSuccess()473     bool IsVerifiedSuccess() const
474     {
475         return (IsVerified() && (!IsErroneous()));
476     }
SetInitTid(uint32_t id)477     void SetInitTid(uint32_t id)
478     {
479         init_tid_ = id;
480     }
481 
GetInitTid()482     uint32_t GetInitTid() const
483     {
484         return init_tid_;
485     }
486 
GetVTableOffset()487     static size_t GetVTableOffset()
488     {
489         return ClassHelper::ComputeClassSize(0, 0, 0, 0, 0, 0, 0, 0);
490     }
491 
GetNumVirtualMethods()492     uint32_t GetNumVirtualMethods() const
493     {
494         return num_vmethods_;
495     }
496 
SetNumVirtualMethods(uint32_t n)497     void SetNumVirtualMethods(uint32_t n)
498     {
499         num_vmethods_ = n;
500     }
501 
GetNumCopiedMethods()502     uint32_t GetNumCopiedMethods() const
503     {
504         return num_copied_methods_;
505     }
506 
SetNumCopiedMethods(uint32_t n)507     void SetNumCopiedMethods(uint32_t n)
508     {
509         num_copied_methods_ = n;
510     }
511 
GetNumStaticFields()512     uint32_t GetNumStaticFields() const
513     {
514         return num_sfields_;
515     }
516 
SetNumStaticFields(uint32_t n)517     void SetNumStaticFields(uint32_t n)
518     {
519         num_sfields_ = n;
520     }
521 
SetHasDefaultMethods()522     void SetHasDefaultMethods()
523     {
524         access_flags_ |= ACC_HAS_DEFAULT_METHODS;
525     }
526 
HasDefaultMethods()527     bool HasDefaultMethods() const
528     {
529         return (access_flags_ & ACC_HAS_DEFAULT_METHODS) != 0;
530     }
531 
GetIMTOffset()532     size_t GetIMTOffset()
533     {
534         return GetVTableOffset() + vtable_size_ * sizeof(uintptr_t);
535     }
536 
GetIMTOffset()537     size_t GetIMTOffset() const
538     {
539         return GetVTableOffset() + vtable_size_ * sizeof(uintptr_t);
540     }
541 
542     std::string GetName() const;
543 
GetLoadContext()544     ClassLinkerContext *GetLoadContext() const
545     {
546         ASSERT(load_context_ != nullptr);
547         return load_context_;
548     }
549 
SetLoadContext(ClassLinkerContext * context)550     void SetLoadContext(ClassLinkerContext *context)
551     {
552         ASSERT(context != nullptr);
553         load_context_ = context;
554     }
555 
556     template <class Pred>
557     Field *FindInstanceField(Pred pred) const;
558 
559     template <class Pred>
560     Field *FindStaticField(Pred pred) const;
561 
562     template <class Pred>
563     Field *FindField(Pred pred) const;
564 
565     template <class Pred>
566     Field *FindDeclaredField(Pred pred) const;
567 
568     Field *GetInstanceFieldByName(const uint8_t *mutf8_name) const;
569 
570     Field *GetStaticFieldByName(const uint8_t *mutf8_name) const;
571 
572     Field *GetDeclaredFieldByName(const uint8_t *mutf8_name) const;
573 
574     template <class Pred>
575     Method *FindVirtualClassMethod(Pred pred) const;
576 
577     template <class Pred>
578     Method *FindInterfaceMethod(Pred pred) const;
579 
580     template <class Pred>
581     Method *FindVirtualInterfaceMethod(Pred pred) const;
582 
583     template <class Pred>
584     Method *FindStaticInterfaceMethod(Pred pred) const;
585 
586     template <class Pred>
587     Method *FindStaticClassMethod(Pred pred) const;
588 
589     template <class Pred>
590     Method *FindClassMethod(Pred pred) const;
591 
592     Method *GetDirectMethod(const uint8_t *mutf8_name, const Method::Proto &proto) const;
593 
594     Method *GetClassMethod(const uint8_t *mutf8_name, const Method::Proto &proto) const;
595 
596     Method *GetInterfaceMethod(const uint8_t *mutf8_name, const Method::Proto &proto) const;
597 
598     Method *GetDirectMethod(const uint8_t *mutf8_name) const;
599 
600     Method *GetClassMethod(const uint8_t *mutf8_name) const;
601 
602     Method *ResolveVirtualMethod(const Method *method) const;
603 
604     template <class T, bool is_volatile = false>
605     T GetFieldPrimitive(size_t offset) const;
606 
607     template <class T, bool is_volatile = false>
608     void SetFieldPrimitive(size_t offset, T value);
609 
610     template <bool is_volatile = false, bool need_read_barrier = true>
611     ObjectHeader *GetFieldObject(size_t offset) const;
612 
613     template <bool is_volatile = false, bool need_write_barrier = true>
614     void SetFieldObject(size_t offset, ObjectHeader *value);
615 
616     template <class T>
617     T GetFieldPrimitive(const Field &field) const;
618 
619     template <class T>
620     void SetFieldPrimitive(const Field &field, T value);
621 
622     template <bool need_read_barrier = true>
623     ObjectHeader *GetFieldObject(const Field &field) const;
624 
625     template <bool need_write_barrier = true>
626     void SetFieldObject(const Field &field, ObjectHeader *value);
627 
628     // Pass thread parameter to speed up interpreter
629     template <bool need_read_barrier = true>
630     ObjectHeader *GetFieldObject(ManagedThread *thread, const Field &field) const;
631 
632     template <bool need_write_barrier = true>
633     void SetFieldObject(ManagedThread *thread, const Field &field, ObjectHeader *value);
634 
635     template <class T>
636     T GetFieldPrimitive(size_t offset, std::memory_order memory_order) const;
637 
638     template <class T>
639     void SetFieldPrimitive(size_t offset, T value, std::memory_order memory_order);
640 
641     template <bool need_read_barrier = true>
642     ObjectHeader *GetFieldObject(size_t offset, std::memory_order memory_order) const;
643 
644     template <bool need_write_barrier = true>
645     void SetFieldObject(size_t offset, ObjectHeader *value, std::memory_order memory_order);
646 
647     template <typename T>
648     bool CompareAndSetFieldPrimitive(size_t offset, T old_value, T new_value, std::memory_order memory_order,
649                                      bool strong);
650 
651     template <bool need_write_barrier = true>
652     bool CompareAndSetFieldObject(size_t offset, ObjectHeader *old_value, ObjectHeader *new_value,
653                                   std::memory_order memory_order, bool strong);
654 
655     template <typename T>
656     T CompareAndExchangeFieldPrimitive(size_t offset, T old_value, T new_value, std::memory_order memory_order,
657                                        bool strong);
658 
659     template <bool need_write_barrier = true>
660     ObjectHeader *CompareAndExchangeFieldObject(size_t offset, ObjectHeader *old_value, ObjectHeader *new_value,
661                                                 std::memory_order memory_order, bool strong);
662 
663     template <typename T>
664     T GetAndSetFieldPrimitive(size_t offset, T value, std::memory_order memory_order);
665 
666     template <bool need_write_barrier = true>
667     ObjectHeader *GetAndSetFieldObject(size_t offset, ObjectHeader *value, std::memory_order memory_order);
668 
669     template <typename T>
670     T GetAndAddFieldPrimitive(size_t offset, T value, std::memory_order memory_order);
671 
672     template <typename T>
673     T GetAndBitwiseOrFieldPrimitive(size_t offset, T value, std::memory_order memory_order);
674 
675     template <typename T>
676     T GetAndBitwiseAndFieldPrimitive(size_t offset, T value, std::memory_order memory_order);
677 
678     template <typename T>
679     T GetAndBitwiseXorFieldPrimitive(size_t offset, T value, std::memory_order memory_order);
680 
681     void DumpClass(std::ostream &os, size_t flags);
682 
683     static UniqId CalcUniqId(const panda_file::File *file, panda_file::File::EntityId file_id);
684 
685     // for synthetic classes, like arrays
686     static UniqId CalcUniqId(const uint8_t *descriptor);
687 
GetUniqId()688     UniqId GetUniqId() const
689     {
690         auto id = uniq_id_.load();
691         if (id == 0) {
692             id = CalcUniqId();
693             uniq_id_.store(id);
694         }
695         return id;
696     }
697 
SetRefFieldsNum(uint32_t num,bool is_static)698     void SetRefFieldsNum(uint32_t num, bool is_static)
699     {
700         if (is_static) {
701             num_refsfields_ = num;
702         } else {
703             num_reffields_ = num;
704         }
705     }
706 
SetRefFieldsOffset(uint32_t offset,bool is_static)707     void SetRefFieldsOffset(uint32_t offset, bool is_static)
708     {
709         if (is_static) {
710             offset_refsfields_ = offset;
711         } else {
712             offset_reffields_ = offset;
713         }
714     }
715 
SetVolatileRefFieldsNum(uint32_t num,bool is_static)716     void SetVolatileRefFieldsNum(uint32_t num, bool is_static)
717     {
718         if (is_static) {
719             volatile_refsfields_num_ = num;
720         } else {
721             volatile_reffields_num_ = num;
722         }
723     }
724 
725     template <bool is_static>
GetRefFieldsNum()726     uint32_t GetRefFieldsNum() const
727     {
728         return is_static ? num_refsfields_ : num_reffields_;
729     }
730 
731     template <bool is_static>
GetRefFieldsOffset()732     uint32_t GetRefFieldsOffset() const
733     {
734         return is_static ? offset_refsfields_ : offset_reffields_;
735     }
736 
737     template <bool is_static>
GetVolatileRefFieldsNum()738     uint32_t GetVolatileRefFieldsNum() const
739     {
740         return is_static ? volatile_refsfields_num_ : volatile_reffields_num_;
741     }
742 
ResolveClassIndex(panda_file::File::Index idx)743     panda_file::File::EntityId ResolveClassIndex(panda_file::File::Index idx) const
744     {
745         return class_idx_[idx];
746     }
747 
ResolveMethodIndex(panda_file::File::Index idx)748     panda_file::File::EntityId ResolveMethodIndex(panda_file::File::Index idx) const
749     {
750         return method_idx_[idx];
751     }
752 
ResolveFieldIndex(panda_file::File::Index idx)753     panda_file::File::EntityId ResolveFieldIndex(panda_file::File::Index idx) const
754     {
755         return field_idx_[idx];
756     }
757 
GetClassIndex()758     Span<const panda_file::File::EntityId> GetClassIndex() const
759     {
760         return class_idx_;
761     }
762 
SetClassIndex(Span<const panda_file::File::EntityId> index)763     void SetClassIndex(Span<const panda_file::File::EntityId> index)
764     {
765         class_idx_ = index;
766     }
767 
GetMethodIndex()768     Span<const panda_file::File::EntityId> GetMethodIndex() const
769     {
770         return method_idx_;
771     }
772 
SetMethodIndex(Span<const panda_file::File::EntityId> index)773     void SetMethodIndex(Span<const panda_file::File::EntityId> index)
774     {
775         method_idx_ = index;
776     }
777 
GetFieldIndex()778     Span<const panda_file::File::EntityId> GetFieldIndex() const
779     {
780         return field_idx_;
781     }
782 
SetFieldIndex(Span<const panda_file::File::EntityId> index)783     void SetFieldIndex(Span<const panda_file::File::EntityId> index)
784     {
785         field_idx_ = index;
786     }
787 
788     static Class *FromClassObject(const ObjectHeader *obj);
789 
790     static size_t GetClassObjectSizeFromClass(Class *cls);
791 
792     ~Class() = default;
793 
794     NO_COPY_SEMANTIC(Class);
795     NO_MOVE_SEMANTIC(Class);
796 
797 private:
798     enum class FindFilter { STATIC, INSTANCE, ALL, COPIED };
799 
800     template <FindFilter filter>
801     Span<Field> GetFields() const;
802 
803     template <FindFilter filter, class Pred>
804     Field *FindDeclaredField(Pred pred) const;
805 
806     template <FindFilter filter, class Pred>
807     Field *FindField(Pred pred) const;
808 
809     template <FindFilter filter>
810     Span<Method> GetMethods() const;
811 
812     template <FindFilter filter, class Pred>
813     Method *FindDirectMethod(Pred pred) const;
814 
815     template <FindFilter filter, class Pred>
816     Method *FindClassMethod(Pred pred) const;
817 
818     template <FindFilter filter, class Pred>
819     Method *FindInterfaceMethod(Pred pred) const;
820 
GetClassSpan()821     Span<std::byte> GetClassSpan()
822     {
823         return Span(reinterpret_cast<std::byte *>(this), class_size_);
824     }
825 
GetClassSpan()826     Span<const std::byte> GetClassSpan() const
827     {
828         return Span(reinterpret_cast<const std::byte *>(this), class_size_);
829     }
830 
831     Class *base_ {nullptr};
832     const panda_file::File *panda_file_ {nullptr};
833     // Decscriptor is a valid MUTF8 string. See docs/file_format.md#typedescriptor for more information.
834     const uint8_t *descriptor_;
835     Method *methods_ {nullptr};
836     Field *fields_ {nullptr};
837     Class **ifaces_ {nullptr};
838 
839     panda_file::File::EntityId file_id_ {};
840     uint32_t vtable_size_;
841     uint32_t imt_size_;
842     uint32_t class_size_;
843     uint32_t access_flags_ {0};
844 
845     uint32_t num_methods_ {0};
846     uint32_t num_vmethods_ {0};
847     uint32_t num_copied_methods_ {0};
848     uint32_t num_fields_ {0};
849     uint32_t num_sfields_ {0};
850     uint32_t num_ifaces_ {0};
851     uint32_t init_tid_ {0};
852 
853     ITable itable_;
854 
855     // For array types this field contains array's element size, for non-array type it should be zero.
856     Class *component_type_ {nullptr};
857 
858     ClassLinkerContext *load_context_ {nullptr};
859 
860     panda_file::Type type_ {panda_file::Type::TypeId::REFERENCE};
861     std::atomic<State> state_ {State::INITIAL};
862 
863     UniqId CalcUniqId() const;
864     mutable std::atomic<UniqId> uniq_id_ {0};
865 
866     uint32_t num_reffields_ {0};      // instance reference fields num
867     uint32_t num_refsfields_ {0};     // static reference fields num
868     uint32_t offset_reffields_ {0};   // first instance reference fields offset in object layout
869     uint32_t offset_refsfields_ {0};  // first static reference fields offset in object layout
870     uint32_t volatile_reffields_num_ {0};
871     uint32_t volatile_refsfields_num_ {0};
872 
873     Span<const panda_file::File::EntityId> class_idx_ {nullptr, nullptr};
874     Span<const panda_file::File::EntityId> method_idx_ {nullptr, nullptr};
875     Span<const panda_file::File::EntityId> field_idx_ {nullptr, nullptr};
876 };
877 
878 std::ostream &operator<<(std::ostream &os, const Class::State &state);
879 
880 #ifdef PANDA_TARGET_64
881 
882 constexpr uint32_t CLASS_MANAGE_OBJECT_OFFSET = 8U;
883 static_assert(CLASS_MANAGE_OBJECT_OFFSET == Class::OffsetOfManageObject());
884 
885 constexpr uint32_t CLASS_STATE_OFFSET = 153U;
886 static_assert(CLASS_STATE_OFFSET == panda::Class::GetStateOffset());
887 
888 constexpr uint32_t CLASS_COMPONENT_TYPE_OFFSET = 136U;
889 static_assert(CLASS_COMPONENT_TYPE_OFFSET == panda::Class::GetComponentTypeOffset());
890 
891 constexpr uint32_t CLASS_TYPE_OFFSET = 152U;
892 static_assert(CLASS_TYPE_OFFSET == panda::Class::GetTypeOffset());
893 
894 constexpr uint32_t CLASS_BASE_OFFSET = 24U;
895 static_assert(CLASS_BASE_OFFSET == panda::Class::GetBaseOffset());
896 
897 #endif
898 
899 }  // namespace panda
900 
901 #endif  // PANDA_RUNTIME_INCLUDE_CLASS_H_
902