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 // All common ObjectHeader methods can be found here: 16 // - Get/Set Mark or Class word 17 // - Get size of the object header and an object itself 18 // - Get/Generate an object hash 19 // Methods, specific for Class word: 20 // - Get different object fields 21 // - Return object type 22 // - Verify object 23 // - Is it a subclass of not 24 // - Get field addr 25 // Methods, specific for Mark word: 26 // - Object locked/unlocked 27 // - Marked for GC or not 28 // - Monitor functions (get monitor, notify, notify all, wait) 29 // - Forwarded or not 30 31 #ifndef PANDA_RUNTIME_INCLUDE_OBJECT_HEADER_H_ 32 #define PANDA_RUNTIME_INCLUDE_OBJECT_HEADER_H_ 33 34 #include <atomic> 35 #include <ctime> 36 37 #include "runtime/include/class_helper.h" 38 #include "runtime/mark_word.h" 39 40 namespace panda { 41 42 namespace object_header_traits { 43 44 constexpr const uint32_t LINEAR_X = 1103515245U; 45 constexpr const uint32_t LINEAR_Y = 12345U; 46 constexpr const uint32_t LINEAR_SEED = 987654321U; 47 // NOLINTNEXTLINE(fuchsia-statically-constructed-objects) 48 static auto hash_seed = std::atomic<uint32_t>(LINEAR_SEED + std::time(nullptr)); 49 50 } // namespace object_header_traits 51 52 class BaseClass; 53 class Class; 54 class Field; 55 class ManagedThread; 56 57 class ObjectHeader { 58 public: 59 // Simple getters and setters for Class and Mark words. 60 // Use it only in single thread GetMark()61 inline MarkWord GetMark() const 62 { 63 return *(const_cast<MarkWord *>(reinterpret_cast<const MarkWord *>(&markWord_))); 64 } SetMark(volatile MarkWord mark_word)65 inline void SetMark(volatile MarkWord mark_word) 66 { 67 markWord_ = mark_word.Value(); 68 } 69 AtomicGetMark()70 inline MarkWord AtomicGetMark() const 71 { 72 auto ptr = const_cast<MarkWord *>(reinterpret_cast<const MarkWord *>(&markWord_)); 73 auto atomic_ptr = reinterpret_cast<std::atomic<MarkWord> *>(ptr); 74 return atomic_ptr->load(); 75 } 76 SetClass(BaseClass * klass)77 inline void SetClass(BaseClass *klass) 78 { 79 static_assert(sizeof(ClassHelper::classWordSize) == sizeof(object_pointer_type)); 80 reinterpret_cast<std::atomic<ClassHelper::classWordSize> *>(&classWord_) 81 ->store(static_cast<ClassHelper::classWordSize>(ToObjPtrType(klass)), std::memory_order_release); 82 ASSERT(AtomicClassAddr<BaseClass>() == klass); 83 } 84 85 template <typename T> ClassAddr()86 inline T *ClassAddr() const 87 { 88 return AtomicClassAddr<T>(); 89 } 90 91 template <typename T> AtomicClassAddr()92 inline T *AtomicClassAddr() const 93 { 94 auto ptr = const_cast<ClassHelper::classWordSize *>(&classWord_); 95 return reinterpret_cast<T *>( 96 reinterpret_cast<std::atomic<ClassHelper::classWordSize> *>(ptr)->load(std::memory_order_acquire)); 97 } 98 99 // Generate hash value for an object. GenerateHashCode()100 static inline uint32_t GenerateHashCode() 101 { 102 uint32_t ex_val; 103 uint32_t n_val; 104 do { 105 ex_val = object_header_traits::hash_seed.load(std::memory_order_relaxed); 106 n_val = ex_val * object_header_traits::LINEAR_X + object_header_traits::LINEAR_Y; 107 } while (!object_header_traits::hash_seed.compare_exchange_weak(ex_val, n_val, std::memory_order_relaxed) || 108 (ex_val & MarkWord::HASH_MASK) == 0); 109 return ex_val & MarkWord::HASH_MASK; 110 } 111 112 // Get Hash value for an object. 113 uint32_t GetHashCode(); 114 uint32_t GetHashCodeFromMonitor(Monitor *monitor_p); 115 116 // Size of object header ObjectHeaderSize()117 static constexpr int ObjectHeaderSize() 118 { 119 return sizeof(ObjectHeader); 120 } 121 GetClassOffset()122 static constexpr size_t GetClassOffset() 123 { 124 return MEMBER_OFFSET(ObjectHeader, classWord_); 125 } 126 GetMarkWordOffset()127 static constexpr size_t GetMarkWordOffset() 128 { 129 return MEMBER_OFFSET(ObjectHeader, markWord_); 130 } 131 132 // Garbage collection method 133 template <bool atomic_flag = true> IsMarkedForGC()134 inline bool IsMarkedForGC() const 135 { 136 if constexpr (!atomic_flag) { // NOLINTNEXTLINE(readability-braces-around-statements) 137 return GetMark().IsMarkedForGC(); 138 } 139 return AtomicGetMark().IsMarkedForGC(); 140 } 141 template <bool atomic_flag = true> SetMarkedForGC()142 inline void SetMarkedForGC() 143 { 144 if constexpr (!atomic_flag) { // NOLINTNEXTLINE(readability-braces-around-statements) 145 SetMark(GetMark().SetMarkedForGC()); 146 return; 147 } 148 bool res; 149 do { 150 MarkWord word = AtomicGetMark(); 151 res = AtomicSetMark(word, word.SetMarkedForGC()); 152 } while (!res); 153 } 154 template <bool atomic_flag = true> SetUnMarkedForGC()155 inline void SetUnMarkedForGC() 156 { 157 if constexpr (!atomic_flag) { // NOLINTNEXTLINE(readability-braces-around-statements) 158 SetMark(GetMark().SetUnMarkedForGC()); 159 return; 160 } 161 bool res; 162 do { 163 MarkWord word = AtomicGetMark(); 164 res = AtomicSetMark(word, word.SetUnMarkedForGC()); 165 } while (!res); 166 } IsForwarded()167 inline bool IsForwarded() const 168 { 169 return AtomicGetMark().GetState() == MarkWord::ObjectState::STATE_GC; 170 } 171 172 // Type test methods 173 inline bool IsInstance() const; 174 175 // Get field address in Class 176 inline void *FieldAddr(int offset) const; 177 178 bool AtomicSetMark(MarkWord old_mark_word, MarkWord new_mark_word); 179 180 // Accessors to typical Class types 181 template <class T, bool is_volatile = false> 182 T GetFieldPrimitive(size_t offset) const; 183 184 template <class T, bool is_volatile = false> 185 void SetFieldPrimitive(size_t offset, T value); 186 187 template <bool is_volatile = false, bool need_read_barrier = true, bool is_dyn = false> 188 ObjectHeader *GetFieldObject(int offset) const; 189 190 template <bool is_volatile = false, bool need_write_barrier = true, bool is_dyn = false> 191 void SetFieldObject(size_t offset, ObjectHeader *value); 192 193 template <class T> 194 T GetFieldPrimitive(const Field &field) const; 195 196 template <class T> 197 void SetFieldPrimitive(const Field &field, T value); 198 199 template <bool need_read_barrier = true, bool is_dyn = false> 200 ObjectHeader *GetFieldObject(const Field &field) const; 201 202 template <bool need_write_barrier = true, bool is_dyn = false> 203 void SetFieldObject(const Field &field, ObjectHeader *value); 204 205 // Pass thread parameter to speed up interpreter 206 template <bool need_read_barrier = true, bool is_dyn = false> 207 ObjectHeader *GetFieldObject(ManagedThread *thread, const Field &field); 208 209 template <bool need_write_barrier = true, bool is_dyn = false> 210 void SetFieldObject(ManagedThread *thread, const Field &field, ObjectHeader *value); 211 212 template <bool is_volatile = false, bool need_write_barrier = true, bool is_dyn = false> 213 void SetFieldObject(ManagedThread *thread, size_t offset, ObjectHeader *value); 214 215 template <class T> 216 T GetFieldPrimitive(size_t offset, std::memory_order memory_order) const; 217 218 template <class T> 219 void SetFieldPrimitive(size_t offset, T value, std::memory_order memory_order); 220 221 template <bool need_read_barrier = true, bool is_dyn = false> 222 ObjectHeader *GetFieldObject(size_t offset, std::memory_order memory_order) const; 223 224 template <bool need_write_barrier = true, bool is_dyn = false> 225 void SetFieldObject(size_t offset, ObjectHeader *value, std::memory_order memory_order); 226 227 template <typename T> 228 bool CompareAndSetFieldPrimitive(size_t offset, T old_value, T new_value, std::memory_order memory_order, 229 bool strong); 230 231 template <bool need_write_barrier = true, bool is_dyn = false> 232 bool CompareAndSetFieldObject(size_t offset, ObjectHeader *old_value, ObjectHeader *new_value, 233 std::memory_order memory_order, bool strong); 234 235 template <typename T> 236 T CompareAndExchangeFieldPrimitive(size_t offset, T old_value, T new_value, std::memory_order memory_order, 237 bool strong); 238 239 template <bool need_write_barrier = true, bool is_dyn = false> 240 ObjectHeader *CompareAndExchangeFieldObject(size_t offset, ObjectHeader *old_value, ObjectHeader *new_value, 241 std::memory_order memory_order, bool strong); 242 243 template <typename T> 244 T GetAndSetFieldPrimitive(size_t offset, T value, std::memory_order memory_order); 245 246 template <bool need_write_barrier = true, bool is_dyn = false> 247 ObjectHeader *GetAndSetFieldObject(size_t offset, ObjectHeader *value, std::memory_order memory_order); 248 249 template <typename T> 250 T GetAndAddFieldPrimitive(size_t offset, T value, std::memory_order memory_order); 251 252 template <typename T> 253 T GetAndBitwiseOrFieldPrimitive(size_t offset, T value, std::memory_order memory_order); 254 255 template <typename T> 256 T GetAndBitwiseAndFieldPrimitive(size_t offset, T value, std::memory_order memory_order); 257 258 template <typename T> 259 T GetAndBitwiseXorFieldPrimitive(size_t offset, T value, std::memory_order memory_order); 260 261 /* 262 * Is the object is an instance of specified class. 263 * 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 264 * type in type hierarchy or T is such array that O array elements are the same or subtype of T array elements. 265 */ 266 inline bool IsInstanceOf(Class *klass); 267 268 // Verification methods 269 static void Verify(ObjectHeader *object_header); 270 271 static ObjectHeader *Create(BaseClass *klass); 272 273 static ObjectHeader *CreateNonMovable(BaseClass *klass); 274 275 static ObjectHeader *Clone(ObjectHeader *src); 276 277 static ObjectHeader *ShallowCopy(ObjectHeader *src); 278 279 size_t ObjectSize() const; 280 281 private: 282 MarkWord::markWordSize markWord_; 283 ClassHelper::classWordSize classWord_; 284 285 /** 286 * Allocates memory for the Object. No ctor is called. 287 * @param klass - class of Object 288 * @param non_movable - if true, object will be allocated in non-movable space 289 * @return pointer to the created Object 290 */ 291 static ObjectHeader *CreateObject(BaseClass *klass, bool non_movable); 292 }; 293 294 constexpr uint32_t OBJECT_HEADER_CLASS_OFFSET = 4U; 295 static_assert(OBJECT_HEADER_CLASS_OFFSET == panda::ObjectHeader::GetClassOffset()); 296 297 } // namespace panda 298 299 #endif // PANDA_RUNTIME_INCLUDE_OBJECT_HEADER_H_ 300