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_MEM_REFERENCE_H 16 #define PANDA_RUNTIME_MEM_REFERENCE_H 17 18 #include "libpandabase/macros.h" 19 #include "libpandabase/mem/mem.h" 20 21 namespace panda::mem { 22 class ReferenceStorage; 23 class RefBlock; 24 namespace test { 25 class ReferenceStorageTest; 26 } // namespace test 27 } // namespace panda::mem 28 29 namespace panda::mem { 30 31 class GlobalObjectStorage; 32 33 class Reference { 34 public: 35 enum class ObjectType : uint8_t { 36 /** 37 * Used for objects on stack (arguments for methods) 38 */ 39 STACK = 0, 40 /** 41 * Local references which can be used inside Frame. If Frame was removed all references inside this Frame can't 42 * be used anymore 43 */ 44 LOCAL = 1, 45 /** 46 * Global references which can be used without Frames 47 */ 48 GLOBAL = 2, 49 /** 50 * Weak references which work as Global references, but will be nullified when GC clears the object when the 51 * object becomes unreachable (no guarantees when it will happen) 52 */ 53 WEAK = 3, 54 ENUM_SIZE 55 }; 56 57 DEFAULT_COPY_SEMANTIC(Reference); 58 DEFAULT_MOVE_SEMANTIC(Reference); 59 ~Reference() = delete; 60 Reference() = delete; 61 IsStack()62 bool IsStack() const 63 { 64 return GetType() == ObjectType::STACK; 65 } 66 IsLocal()67 bool IsLocal() const 68 { 69 ObjectType type = GetType(); 70 return type == ObjectType::STACK || type == ObjectType::LOCAL; 71 } 72 IsGlobal()73 bool IsGlobal() const 74 { 75 return GetType() == ObjectType::GLOBAL; 76 } 77 IsWeak()78 bool IsWeak() const 79 { 80 return GetType() == ObjectType::WEAK; 81 } 82 83 private: 84 static constexpr auto MASK_TYPE = 3U; 85 static constexpr auto MASK_WITHOUT_TYPE = sizeof(uintptr_t) == sizeof(uint64_t) 86 ? std::numeric_limits<uint64_t>::max() - MASK_TYPE 87 : std::numeric_limits<uint32_t>::max() - MASK_TYPE; 88 CreateWithoutType(uintptr_t addr)89 static Reference *CreateWithoutType(uintptr_t addr) 90 { 91 ASSERT((addr & MASK_TYPE) == 0); 92 return reinterpret_cast<Reference *>(addr); 93 } 94 Create(uintptr_t addr,ObjectType type)95 static Reference *Create(uintptr_t addr, ObjectType type) 96 { 97 ASSERT((addr & MASK_TYPE) == 0); 98 return SetType(addr, type); 99 } 100 GetType(const Reference * ref)101 static ObjectType GetType(const Reference *ref) 102 { 103 auto addr = ToUintPtr(ref); 104 return static_cast<ObjectType>(addr & MASK_TYPE); 105 } 106 SetType(Reference * ref,ObjectType type)107 static Reference *SetType(Reference *ref, ObjectType type) 108 { 109 auto addr = ToUintPtr(ref); 110 return SetType(addr, type); 111 } 112 SetType(uintptr_t addr,ObjectType type)113 static Reference *SetType(uintptr_t addr, ObjectType type) 114 { 115 ASSERT((addr & MASK_TYPE) == 0); 116 return reinterpret_cast<Reference *>(addr | static_cast<uintptr_t>(type)); 117 } 118 GetType()119 ObjectType GetType() const 120 { 121 return Reference::GetType(this); 122 } 123 GetRefWithoutType(const Reference * ref)124 static Reference *GetRefWithoutType(const Reference *ref) 125 { 126 auto addr = ToUintPtr(ref); 127 return reinterpret_cast<Reference *>(addr & MASK_WITHOUT_TYPE); 128 } 129 130 friend class panda::mem::ReferenceStorage; 131 friend class panda::mem::GlobalObjectStorage; 132 friend class panda::mem::RefBlock; 133 friend class panda::mem::test::ReferenceStorageTest; 134 }; 135 } // namespace panda::mem 136 #endif // PANDA_RUNTIME_MEM_REFERENCE_H 137