1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef ART_RUNTIME_READ_BARRIER_H_ 18 #define ART_RUNTIME_READ_BARRIER_H_ 19 20 #include "base/mutex.h" 21 #include "base/macros.h" 22 #include "gc_root.h" 23 #include "jni.h" 24 #include "mirror/object_reference.h" 25 #include "offsets.h" 26 #include "read_barrier_c.h" 27 28 // This is a C++ (not C) header file, separate from read_barrier_c.h 29 // which needs to be a C header file for asm_support.h. 30 31 namespace art { 32 namespace mirror { 33 class Object; 34 template<typename MirrorType> class HeapReference; 35 } // namespace mirror 36 class ArtMethod; 37 38 class ReadBarrier { 39 public: 40 // Enable the to-space invariant checks. 41 static constexpr bool kEnableToSpaceInvariantChecks = kIsDebugBuild; 42 // Enable the read barrier checks. 43 static constexpr bool kEnableReadBarrierInvariantChecks = kIsDebugBuild; 44 45 // It's up to the implementation whether the given field gets updated whereas the return value 46 // must be an updated reference unless kAlwaysUpdateField is true. 47 template <typename MirrorType, ReadBarrierOption kReadBarrierOption = kWithReadBarrier, 48 bool kAlwaysUpdateField = false> 49 ALWAYS_INLINE static MirrorType* Barrier( 50 mirror::Object* obj, MemberOffset offset, mirror::HeapReference<MirrorType>* ref_addr) 51 REQUIRES_SHARED(Locks::mutator_lock_); 52 53 // It's up to the implementation whether the given root gets updated 54 // whereas the return value must be an updated reference. 55 template <typename MirrorType, ReadBarrierOption kReadBarrierOption = kWithReadBarrier> 56 ALWAYS_INLINE static MirrorType* BarrierForRoot(MirrorType** root, 57 GcRootSource* gc_root_source = nullptr) 58 REQUIRES_SHARED(Locks::mutator_lock_); 59 60 // It's up to the implementation whether the given root gets updated 61 // whereas the return value must be an updated reference. 62 template <typename MirrorType, ReadBarrierOption kReadBarrierOption = kWithReadBarrier> 63 ALWAYS_INLINE static MirrorType* BarrierForRoot(mirror::CompressedReference<MirrorType>* root, 64 GcRootSource* gc_root_source = nullptr) 65 REQUIRES_SHARED(Locks::mutator_lock_); 66 67 // Return the mirror Object if it is marked, or null if not. 68 template <typename MirrorType> 69 ALWAYS_INLINE static MirrorType* IsMarked(MirrorType* ref) 70 REQUIRES_SHARED(Locks::mutator_lock_); 71 72 static bool IsDuringStartup(); 73 74 // Without the holder object. AssertToSpaceInvariant(mirror::Object * ref)75 static void AssertToSpaceInvariant(mirror::Object* ref) 76 REQUIRES_SHARED(Locks::mutator_lock_) { 77 AssertToSpaceInvariant(nullptr, MemberOffset(0), ref); 78 } 79 // With the holder object. 80 static void AssertToSpaceInvariant(mirror::Object* obj, MemberOffset offset, 81 mirror::Object* ref) 82 REQUIRES_SHARED(Locks::mutator_lock_); 83 // With GcRootSource. 84 static void AssertToSpaceInvariant(GcRootSource* gc_root_source, mirror::Object* ref) 85 REQUIRES_SHARED(Locks::mutator_lock_); 86 87 // ALWAYS_INLINE on this caused a performance regression b/26744236. 88 static mirror::Object* Mark(mirror::Object* obj) REQUIRES_SHARED(Locks::mutator_lock_); 89 WhiteState()90 static constexpr uint32_t WhiteState() { 91 return white_state_; 92 } GrayState()93 static constexpr uint32_t GrayState() { 94 return gray_state_; 95 } 96 97 // fake_address_dependency will be zero which should be bitwise-or'ed with the address of the 98 // subsequent load to prevent the reordering of the read barrier bit load and the subsequent 99 // object reference load (from one of `obj`'s fields). 100 // *fake_address_dependency will be set to 0. 101 ALWAYS_INLINE static bool IsGray(mirror::Object* obj, uintptr_t* fake_address_dependency) 102 REQUIRES_SHARED(Locks::mutator_lock_); 103 104 // This uses a load-acquire to load the read barrier bit internally to prevent the reordering of 105 // the read barrier bit load and the subsequent load. 106 ALWAYS_INLINE static bool IsGray(mirror::Object* obj) 107 REQUIRES_SHARED(Locks::mutator_lock_); 108 IsValidReadBarrierState(uint32_t rb_state)109 static bool IsValidReadBarrierState(uint32_t rb_state) { 110 return rb_state == white_state_ || rb_state == gray_state_; 111 } 112 113 static constexpr uint32_t white_state_ = 0x0; // Not marked. 114 static constexpr uint32_t gray_state_ = 0x1; // Marked, but not marked through. On mark stack. 115 static constexpr uint32_t rb_state_mask_ = 0x1; // The low bits for white|gray. 116 }; 117 118 } // namespace art 119 120 #endif // ART_RUNTIME_READ_BARRIER_H_ 121