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