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_OBJECT_ACCESSOR_H 16 #define PANDA_RUNTIME_OBJECT_ACCESSOR_H 17 18 #include <cstddef> 19 20 #include "runtime/mem/gc/gc_barrier_set.h" 21 22 namespace panda { 23 24 class ObjectHeader; 25 class Field; 26 class ManagedThread; 27 28 class ObjectAccessor { 29 public: 30 template <class T, bool IS_VOLATILE = false> GetPrimitive(const void * obj,size_t offset)31 static T GetPrimitive(const void *obj, size_t offset) 32 { 33 return Get<T, IS_VOLATILE>(obj, offset); 34 } 35 36 template <class T, bool IS_VOLATILE = false> SetPrimitive(void * obj,size_t offset,T value)37 static void SetPrimitive(void *obj, size_t offset, T value) 38 { 39 Set<T, IS_VOLATILE>(obj, offset, value); 40 } 41 42 template <bool IS_VOLATILE = false, bool NEED_READ_BARRIER = true, bool IS_DYN = false> 43 static ObjectHeader *GetObject(const void *obj, size_t offset); 44 45 template <bool IS_VOLATILE = false, bool NEED_WRITE_BARRIER = true, bool IS_DYN = false> 46 static void SetObject(void *obj, size_t offset, ObjectHeader *value); 47 48 template <class T> 49 static T GetFieldPrimitive(const void *obj, const Field &field); 50 51 template <class T> 52 static void SetFieldPrimitive(void *obj, const Field &field, T value); 53 54 template <bool NEED_READ_BARRIER = true, bool IS_DYN = false> 55 static ObjectHeader *GetFieldObject(const void *obj, const Field &field); 56 57 template <bool NEED_WRITE_BARRIER = true, bool IS_DYN = false> 58 static void SetFieldObject(void *obj, const Field &field, ObjectHeader *value); 59 60 // Pass thread parameter to speed up interpreter 61 template <bool IS_VOLATILE = false, bool NEED_READ_BARRIER = true, bool IS_DYN = false> 62 static ObjectHeader *GetObject(const ManagedThread *thread, const void *obj, size_t offset); 63 64 template <bool IS_VOLATILE = false, bool NEED_WRITE_BARRIER = true, bool IS_DYN = false> 65 static void SetObject(const ManagedThread *thread, void *obj, size_t offset, ObjectHeader *value); 66 67 template <bool NEED_READ_BARRIER = true, bool IS_DYN = false> 68 static ObjectHeader *GetFieldObject(const ManagedThread *thread, const void *obj, const Field &field); 69 70 template <bool NEED_WRITE_BARRIER = true, bool IS_DYN = false> 71 static void SetFieldObject(const ManagedThread *thread, void *obj, const Field &field, ObjectHeader *value); 72 73 template <class T> 74 static T GetFieldPrimitive(const void *obj, size_t offset, std::memory_order memoryOrder); 75 76 template <class T> 77 static void SetFieldPrimitive(void *obj, size_t offset, T value, std::memory_order memoryOrder); 78 79 template <bool NEED_READ_BARRIER = true, bool IS_DYN = false> 80 static ObjectHeader *GetFieldObject(const void *obj, int offset, std::memory_order memoryOrder); 81 82 template <bool NEED_WRITE_BARRIER = true, bool IS_DYN = false> 83 static void SetFieldObject(void *obj, size_t offset, ObjectHeader *value, std::memory_order memoryOrder); 84 85 template <typename T> 86 static std::pair<bool, T> CompareAndSetFieldPrimitive(void *obj, size_t offset, T oldValue, T newValue, 87 std::memory_order memoryOrder, bool strong); 88 89 template <bool NEED_WRITE_BARRIER = true, bool IS_DYN = false> 90 static std::pair<bool, ObjectHeader *> CompareAndSetFieldObject(void *obj, size_t offset, ObjectHeader *oldValue, 91 ObjectHeader *newValue, 92 std::memory_order memoryOrder, bool strong); 93 94 template <typename T> 95 static T GetAndSetFieldPrimitive(void *obj, size_t offset, T value, std::memory_order memoryOrder); 96 97 template <bool NEED_WRITE_BARRIER = true, bool IS_DYN = false> 98 static ObjectHeader *GetAndSetFieldObject(void *obj, size_t offset, ObjectHeader *value, 99 std::memory_order memoryOrder); 100 101 template <typename T> 102 static T GetAndAddFieldPrimitive(void *obj, size_t offset, T value, std::memory_order memoryOrder); 103 104 template <typename T> 105 static T GetAndBitwiseOrFieldPrimitive(void *obj, size_t offset, T value, std::memory_order memoryOrder); 106 107 template <typename T> 108 static T GetAndBitwiseAndFieldPrimitive(void *obj, size_t offset, T value, std::memory_order memoryOrder); 109 110 template <typename T> 111 static T GetAndBitwiseXorFieldPrimitive(void *obj, size_t offset, T value, std::memory_order memoryOrder); 112 113 static inline void SetDynValueWithoutBarrier(void *obj, size_t offset, coretypes::TaggedType value); 114 115 static inline void SetDynValue(const ManagedThread *thread, void *obj, size_t offset, coretypes::TaggedType value); 116 117 template <typename T> 118 static inline void SetDynPrimitive(const ManagedThread *thread, void *obj, size_t offset, T value); 119 120 template <class T> GetDynValue(const void * obj,size_t offset)121 static inline T GetDynValue(const void *obj, size_t offset) 122 { 123 uintptr_t addr = ToUintPtr(obj) + offset; 124 ASSERT(IsAddressInObjectsHeap(addr)); 125 // Atomic with relaxed order reason: concurrent access from GC 126 return reinterpret_cast<const std::atomic<T> *>(addr)->load(std::memory_order_relaxed); 127 } 128 129 static void SetClass(ObjectHeader *obj, BaseClass *newClass); 130 131 private: 132 template <class T, bool IS_VOLATILE> Get(const void * obj,size_t offset)133 static T Get(const void *obj, size_t offset) 134 { 135 auto *addr = reinterpret_cast<T *>(reinterpret_cast<uintptr_t>(obj) + offset); 136 ASSERT(IsAddressInObjectsHeap(addr)); 137 if (IS_VOLATILE) { 138 // Atomic with seq_cst order reason: required for volatile 139 return reinterpret_cast<const std::atomic<T> *>(addr)->load(std::memory_order_seq_cst); 140 } 141 // Atomic with relaxed order reason: to be compatible with other vms 142 return reinterpret_cast<const std::atomic<T> *>(addr)->load(std::memory_order_relaxed); 143 } 144 145 template <class T, bool IS_VOLATILE> Set(void * obj,size_t offset,T value)146 static void Set(void *obj, size_t offset, T value) 147 { 148 auto *addr = reinterpret_cast<T *>(reinterpret_cast<uintptr_t>(obj) + offset); 149 ASSERT(IsAddressInObjectsHeap(addr)); 150 if (IS_VOLATILE) { 151 // Atomic with seq_cst order reason: required for volatile 152 return reinterpret_cast<std::atomic<T> *>(addr)->store(value, std::memory_order_seq_cst); 153 } 154 // Atomic with relaxed order reason: to be compatible with other vms 155 return reinterpret_cast<std::atomic<T> *>(addr)->store(value, std::memory_order_relaxed); 156 } 157 158 template <class T> Get(const void * obj,size_t offset,std::memory_order memoryOrder)159 static T Get(const void *obj, size_t offset, std::memory_order memoryOrder) 160 { 161 auto *addr = reinterpret_cast<T *>(reinterpret_cast<uintptr_t>(obj) + offset); 162 ASSERT(IsAddressInObjectsHeap(addr)); 163 // Atomic with parameterized order reason: memory order passed as argument 164 return reinterpret_cast<const std::atomic<T> *>(addr)->load(memoryOrder); 165 } 166 167 template <class T> Set(void * obj,size_t offset,T value,std::memory_order memoryOrder)168 static void Set(void *obj, size_t offset, T value, std::memory_order memoryOrder) 169 { 170 auto *addr = reinterpret_cast<T *>(reinterpret_cast<uintptr_t>(obj) + offset); 171 ASSERT(IsAddressInObjectsHeap(addr)); 172 // Atomic with parameterized order reason: memory order passed as argument 173 return reinterpret_cast<std::atomic<T> *>(addr)->store(value, memoryOrder); 174 } 175 176 PANDA_PUBLIC_API static mem::GCBarrierSet *GetBarrierSet(); 177 178 PANDA_PUBLIC_API static mem::GCBarrierSet *GetBarrierSet(const ManagedThread *thread); 179 180 static mem::BarrierType GetPreBarrierType(const ManagedThread *thread); 181 182 PANDA_PUBLIC_API static mem::BarrierType GetPostBarrierType(const ManagedThread *thread); 183 }; 184 185 } // namespace panda 186 187 #endif // PANDA_RUNTIME_OBJECT_ACCESSOR_H 188