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 (kUseReadBarrier) {
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