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