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