/* * Copyright (c) 2021 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_INCLUDE_OBJECT_ACCESSOR_H_ #define PANDA_RUNTIME_INCLUDE_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(ManagedThread *thread, const void *obj, const Field &field); template static void SetFieldObject(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); template static inline void SetDynPrimitive(void *obj, size_t offset, T value) { auto *addr = reinterpret_cast(ToUintPtr(obj) + offset); ASSERT(IsInObjectsAddressSpace(ToUintPtr(addr))); *addr = value; } template static inline void SetDynObject(const ManagedThread *thread, void *obj, size_t offset, ObjectHeader *value); template static inline T GetDynValue(const void *obj, size_t offset) { auto *addr = reinterpret_cast(ToUintPtr(obj) + offset); ASSERT(IsInObjectsAddressSpace(ToUintPtr(addr))); return *addr; } 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) { return reinterpret_cast *>(addr)->load(std::memory_order_seq_cst); } 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) { return reinterpret_cast *>(addr)->store(value, std::memory_order_seq_cst); } 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))); 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))); 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_INCLUDE_OBJECT_ACCESSOR_H_