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 <android-base/logging.h> 21 22 #include "base/locks.h" 23 #include "base/macros.h" 24 #include "base/runtime_debug.h" 25 #include "gc_root.h" 26 #include "jni.h" 27 #include "mirror/object_reference.h" 28 #include "offsets.h" 29 #include "read_barrier_config.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. This is slow and happens very often. Do not enable in 41 // fast-debug environment. 42 DECLARE_RUNTIME_DEBUG_FLAG(kEnableToSpaceInvariantChecks); 43 44 // Enable the read barrier checks. This is slow and happens very often. Do not enable in 45 // fast-debug environment. 46 DECLARE_RUNTIME_DEBUG_FLAG(kEnableReadBarrierInvariantChecks); 47 48 // Return the reference at ref_addr, invoking read barrier as appropriate. 49 // Ref_addr is an address within obj. 50 // It's up to the implementation whether the given field gets updated whereas the return value 51 // must be an updated reference unless kAlwaysUpdateField is true. 52 template <typename MirrorType, 53 bool kIsVolatile, 54 ReadBarrierOption kReadBarrierOption = kWithReadBarrier, 55 bool kAlwaysUpdateField = false> 56 ALWAYS_INLINE static MirrorType* Barrier( 57 mirror::Object* obj, MemberOffset offset, mirror::HeapReference<MirrorType>* ref_addr) 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(MirrorType** root, 64 GcRootSource* gc_root_source = nullptr) 65 REQUIRES_SHARED(Locks::mutator_lock_); 66 67 // It's up to the implementation whether the given root gets updated 68 // whereas the return value must be an updated reference. 69 template <typename MirrorType, ReadBarrierOption kReadBarrierOption = kWithReadBarrier> 70 ALWAYS_INLINE static MirrorType* BarrierForRoot(mirror::CompressedReference<MirrorType>* root, 71 GcRootSource* gc_root_source = nullptr) 72 REQUIRES_SHARED(Locks::mutator_lock_); 73 74 // Return the mirror Object if it is marked, or null if not. 75 template <typename MirrorType> 76 ALWAYS_INLINE static MirrorType* IsMarked(MirrorType* ref) 77 REQUIRES_SHARED(Locks::mutator_lock_); 78 79 static bool IsDuringStartup(); 80 81 // Without the holder object. AssertToSpaceInvariant(mirror::Object * ref)82 static void AssertToSpaceInvariant(mirror::Object* ref) 83 REQUIRES_SHARED(Locks::mutator_lock_) { 84 AssertToSpaceInvariant(nullptr, MemberOffset(0), ref); 85 } 86 // With the holder object. 87 static void AssertToSpaceInvariant(mirror::Object* obj, MemberOffset offset, 88 mirror::Object* ref) 89 REQUIRES_SHARED(Locks::mutator_lock_); 90 // With GcRootSource. 91 static void AssertToSpaceInvariant(GcRootSource* gc_root_source, mirror::Object* ref) 92 REQUIRES_SHARED(Locks::mutator_lock_); 93 94 // Without the holder object, and only with the read barrier configuration (no-op otherwise). MaybeAssertToSpaceInvariant(mirror::Object * ref)95 static void MaybeAssertToSpaceInvariant(mirror::Object* ref) 96 REQUIRES_SHARED(Locks::mutator_lock_) { 97 if (gUseReadBarrier) { 98 AssertToSpaceInvariant(ref); 99 } 100 } 101 102 // ALWAYS_INLINE on this caused a performance regression b/26744236. 103 static mirror::Object* Mark(mirror::Object* obj) REQUIRES_SHARED(Locks::mutator_lock_); 104 NonGrayState()105 static constexpr uint32_t NonGrayState() { 106 return kNonGrayState; 107 } GrayState()108 static constexpr uint32_t GrayState() { 109 return kGrayState; 110 } 111 112 // fake_address_dependency will be zero which should be bitwise-or'ed with the address of the 113 // subsequent load to prevent the reordering of the read barrier bit load and the subsequent 114 // object reference load (from one of `obj`'s fields). 115 // *fake_address_dependency will be set to 0. 116 ALWAYS_INLINE static bool IsGray(mirror::Object* obj, uintptr_t* fake_address_dependency) 117 REQUIRES_SHARED(Locks::mutator_lock_); 118 119 // This uses a load-acquire to load the read barrier bit internally to prevent the reordering of 120 // the read barrier bit load and the subsequent load. 121 ALWAYS_INLINE static bool IsGray(mirror::Object* obj) 122 REQUIRES_SHARED(Locks::mutator_lock_); 123 IsValidReadBarrierState(uint32_t rb_state)124 static bool IsValidReadBarrierState(uint32_t rb_state) { 125 return rb_state == kNonGrayState || rb_state == kGrayState; 126 } 127 128 private: 129 static constexpr uint32_t kNonGrayState = 0x0; // White (not marked) or black (marked through). 130 static constexpr uint32_t kGrayState = 0x1; // Marked, but not marked through. On mark stack. 131 static constexpr uint32_t kRBStateMask = 0x1; // The low bits for non-gray|gray. 132 }; 133 134 } // namespace art 135 136 #endif // ART_RUNTIME_READ_BARRIER_H_ 137