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