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