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