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 ECMASCRIPT_MEM_BARRIERS_H 17 #define ECMASCRIPT_MEM_BARRIERS_H 18 19 #include "ecmascript/common.h" 20 #include "ecmascript/js_tagged_value.h" 21 #include "ecmascript/mem/mark_word.h" 22 #include "ecmascript/mem/mem_common.h" 23 #include "common_interfaces/base_runtime.h" 24 #include "common_interfaces/thread/mutator_base.h" 25 26 namespace panda::ecmascript { 27 class Region; 28 29 enum class WriteBarrierType : size_t { NORMAL, DESERIALIZE, AOT_DESERIALIZE }; 30 31 class Barriers { 32 public: 33 template<class T> SetPrimitive(void * obj,size_t offset,T value)34 static inline void SetPrimitive(void *obj, size_t offset, T value) 35 { 36 auto *addr = reinterpret_cast<T *>(ToUintPtr(obj) + offset); 37 // NOLINTNEXTLINE(clang-analyzer-core.NullDereference) 38 *addr = value; 39 } 40 41 #ifdef ARK_USE_SATB_BARRIER 42 template<> SetPrimitive(void * obj,size_t offset,JSTaggedType value)43 inline void SetPrimitive(void *obj, size_t offset, JSTaggedType value) 44 { 45 // NOT USE IN Concrruent Enum Barrier 46 CMCWriteBarrier(nullptr, obj, offset, JSTaggedValue::Hole().GetRawData()); 47 auto *addr = reinterpret_cast<JSTaggedType *>(ToUintPtr(obj) + offset); 48 // NOLINTNEXTLINE(clang-analyzer-core.NullDereference) 49 *addr = value; 50 // thread not be used, and satb barrier don't need newvalue. 51 } 52 #endif 53 54 template<class T> AtomicSetPrimitive(volatile void * obj,size_t offset,T oldValue,T value)55 static inline T AtomicSetPrimitive(volatile void *obj, size_t offset, T oldValue, T value) 56 { 57 volatile auto atomicField = reinterpret_cast<volatile std::atomic<T> *>(ToUintPtr(obj) + offset); 58 std::atomic_compare_exchange_strong_explicit(atomicField, &oldValue, value, std::memory_order_release, 59 std::memory_order_relaxed); 60 return oldValue; 61 } 62 63 template<bool needWriteBarrier = true> 64 static void SetObject(const JSThread *thread, void *obj, size_t offset, JSTaggedType value); 65 66 // dstAddr/srcAddr is the address will be copied to/from. 67 // It can be a derived pointer point to the middle of an object. 68 // 69 // Note: dstObj is the object address for dstAddr, it must point to the head of an object. 70 template <bool needWriteBarrier, bool maybeOverlap> 71 static void CopyObject(const JSThread *thread, const TaggedObject *dstObj, JSTaggedValue *dstAddr, 72 const JSTaggedValue *srcAddr, size_t count); 73 74 // dstAddr/srcAddr is the address will be copied to/from. 75 // It can be a derived pointer point to the middle of an object. 76 // 77 // Note: dstObj is the object address for dstAddr, it must point to the head of an object. 78 template<bool needReadBarrier, bool maybeOverlap> 79 static void CopyObjectPrimitive(const JSThread *thread, JSTaggedValue* dst, const JSTaggedValue* src, 80 size_t count); 81 static void SynchronizedSetObject(const JSThread *thread, void *obj, size_t offset, JSTaggedType value, 82 bool isPrimitive = false); 83 84 template<class T> GetPrimitive(const void * obj,size_t offset)85 static inline T GetPrimitive(const void *obj, size_t offset) 86 { 87 auto *addr = reinterpret_cast<T *>(ToUintPtr(obj) + offset); 88 return *addr; 89 } 90 91 static JSTaggedType ReadBarrierForObject(const JSThread *thread, uintptr_t value); 92 93 static TaggedObject* GetTaggedObject(const JSThread *thread, const void* obj, size_t offset); 94 static JSTaggedType GetTaggedValue(const JSThread *thread, const void *obj, size_t offset); 95 static JSTaggedType GetTaggedValue(const JSThread *thread, uintptr_t slotAddress); 96 static JSTaggedType GetTaggedValueAtomic(const JSThread *thread, const void *obj, size_t offset); 97 static JSTaggedType UpdateSlot(const JSThread *thread, void *obj, size_t offset); 98 99 template <RBMode mode = RBMode::DEFAULT_RB> 100 static TaggedObject *GetTaggedObject(const JSThread *thread, const void *obj, size_t offset); 101 102 template <RBMode mode> 103 static JSTaggedType GetTaggedValue(const JSThread *thread, const void *obj, size_t offset); 104 105 template <RBMode mode> 106 static JSTaggedType GetTaggedValue(const JSThread *thread, uintptr_t slotAddress); 107 108 template <RBMode mode> 109 static JSTaggedType GetTaggedValueAtomic(const JSThread *thread, const void *obj, size_t offset); 110 111 static void PUBLIC_API Update(const JSThread *thread, uintptr_t slotAddr, Region *objectRegion, 112 TaggedObject *value, Region *valueRegion, 113 WriteBarrierType writeType = WriteBarrierType::NORMAL); 114 115 static void PUBLIC_API UpdateShared(const JSThread *thread, uintptr_t slotAddr, Region *objectRegion, 116 TaggedObject *value, Region *valueRegion); 117 static void PUBLIC_API CMCWriteBarrier(const JSThread *thread, void *obj, size_t offset, JSTaggedType value); 118 static void PUBLIC_API CMCArrayCopyWriteBarrier(const JSThread *thread, const TaggedObject *dstObj, 119 void* src, void* dst, size_t count); 120 static bool ShouldProcessSATB(common::GCPhase gcPhase); 121 static bool ShouldGetGCReason(common::GCPhase gcPhase); 122 static bool ShouldUpdateRememberSet(common::GCPhase gcPhase); 123 124 static void CMCArrayCopyReadBarrierForward(const JSThread *thread, JSTaggedValue* dst, const JSTaggedValue* src, 125 size_t count); 126 static void CMCArrayCopyReadBarrierBackward(const JSThread *thread, JSTaggedValue* dst, const JSTaggedValue* src, 127 size_t count); 128 }; 129 } // namespace panda::ecmascript 130 131 #endif // ECMASCRIPT_MEM_BARRIERS_H 132