/** * Copyright (c) 2021-2022 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef PANDA_RUNTIME_OBJECT_ACCESSOR_H_ #define PANDA_RUNTIME_OBJECT_ACCESSOR_H_ #include #include "runtime/mem/gc/gc_barrier_set.h" namespace panda { class ObjectHeader; class Field; class ManagedThread; class ObjectAccessor { public: template static T GetPrimitive(const void *obj, size_t offset) { return Get(obj, offset); } template static void SetPrimitive(void *obj, size_t offset, T value) { Set(obj, offset, value); } template static ObjectHeader *GetObject(const void *obj, size_t offset); template static void SetObject(void *obj, size_t offset, ObjectHeader *value); template static T GetFieldPrimitive(const void *obj, const Field &field); template static void SetFieldPrimitive(void *obj, const Field &field, T value); template static ObjectHeader *GetFieldObject(const void *obj, const Field &field); template static void SetFieldObject(void *obj, const Field &field, ObjectHeader *value); // Pass thread parameter to speed up interpreter template static ObjectHeader *GetObject(const ManagedThread *thread, const void *obj, size_t offset); template static void SetObject(const ManagedThread *thread, void *obj, size_t offset, ObjectHeader *value); template static ObjectHeader *GetFieldObject(const ManagedThread *thread, const void *obj, const Field &field); template static void SetFieldObject(const ManagedThread *thread, void *obj, const Field &field, ObjectHeader *value); template static T GetFieldPrimitive(const void *obj, size_t offset, std::memory_order memory_order); template static void SetFieldPrimitive(void *obj, size_t offset, T value, std::memory_order memory_order); template static ObjectHeader *GetFieldObject(const void *obj, int offset, std::memory_order memory_order); template static void SetFieldObject(void *obj, size_t offset, ObjectHeader *value, std::memory_order memory_order); template static std::pair CompareAndSetFieldPrimitive(void *obj, size_t offset, T old_value, T new_value, std::memory_order memory_order, bool strong); template static std::pair CompareAndSetFieldObject(void *obj, size_t offset, ObjectHeader *old_value, ObjectHeader *new_value, std::memory_order memory_order, bool strong); template static T GetAndSetFieldPrimitive(void *obj, size_t offset, T value, std::memory_order memory_order); template static ObjectHeader *GetAndSetFieldObject(void *obj, size_t offset, ObjectHeader *value, std::memory_order memory_order); template static T GetAndAddFieldPrimitive(void *obj, size_t offset, T value, std::memory_order memory_order); template static T GetAndBitwiseOrFieldPrimitive(void *obj, size_t offset, T value, std::memory_order memory_order); template static T GetAndBitwiseAndFieldPrimitive(void *obj, size_t offset, T value, std::memory_order memory_order); template static T GetAndBitwiseXorFieldPrimitive(void *obj, size_t offset, T value, std::memory_order memory_order); static inline void SetDynValueWithoutBarrier(void *obj, size_t offset, coretypes::TaggedType value); static inline void SetDynValue(const ManagedThread *thread, void *obj, size_t offset, coretypes::TaggedType value); template static inline void SetDynPrimitive(const ManagedThread *thread, void *obj, size_t offset, T value); template static inline T GetDynValue(const void *obj, size_t offset) { uintptr_t addr = ToUintPtr(obj) + offset; ASSERT(IsInObjectsAddressSpace(addr)); // Atomic with relaxed order reason: concurrent access from GC return reinterpret_cast *>(addr)->load(std::memory_order_relaxed); } private: template static T Get(const void *obj, size_t offset) { auto *addr = reinterpret_cast(reinterpret_cast(obj) + offset); ASSERT(IsInObjectsAddressSpace(ToUintPtr(addr))); if (is_volatile) { // Atomic with seq_cst order reason: required for volatile return reinterpret_cast *>(addr)->load(std::memory_order_seq_cst); } // Atomic with relaxed order reason: to be compatible with other vms return reinterpret_cast *>(addr)->load(std::memory_order_relaxed); } template static void Set(void *obj, size_t offset, T value) { auto *addr = reinterpret_cast(reinterpret_cast(obj) + offset); ASSERT(IsInObjectsAddressSpace(ToUintPtr(addr))); if (is_volatile) { // Atomic with seq_cst order reason: required for volatile return reinterpret_cast *>(addr)->store(value, std::memory_order_seq_cst); } // Atomic with relaxed order reason: to be compatible with other vms return reinterpret_cast *>(addr)->store(value, std::memory_order_relaxed); } template static T Get(const void *obj, size_t offset, std::memory_order memory_order) { auto *addr = reinterpret_cast(reinterpret_cast(obj) + offset); ASSERT(IsInObjectsAddressSpace(ToUintPtr(addr))); // Atomic with parameterized order reason: memory order passed as argument return reinterpret_cast *>(addr)->load(memory_order); } template static void Set(void *obj, size_t offset, T value, std::memory_order memory_order) { auto *addr = reinterpret_cast(reinterpret_cast(obj) + offset); ASSERT(IsInObjectsAddressSpace(ToUintPtr(addr))); // Atomic with parameterized order reason: memory order passed as argument return reinterpret_cast *>(addr)->store(value, memory_order); } static mem::GCBarrierSet *GetBarrierSet(); static mem::GCBarrierSet *GetBarrierSet(const ManagedThread *thread); static mem::BarrierType GetPreBarrierType(const ManagedThread *thread); static mem::BarrierType GetPostBarrierType(const ManagedThread *thread); }; } // namespace panda #endif // PANDA_RUNTIME_OBJECT_ACCESSOR_H_