blob: 997cedb0931da68c69ede231c5a67e57d9b5033d [file] [log] [blame]
Andreas Gampe6dee92e2016-09-12 19:58:13 -07001/*
2 * Copyright (C) 2016 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_OPENJDKJVMTI_OBJECT_TAGGING_H_
18#define ART_RUNTIME_OPENJDKJVMTI_OBJECT_TAGGING_H_
19
Andreas Gampee54eee12016-10-20 19:03:58 -070020#include <unordered_map>
21
Andreas Gampe6dee92e2016-09-12 19:58:13 -070022#include "base/mutex.h"
23#include "gc/system_weak.h"
24#include "gc_root-inl.h"
Andreas Gampee54eee12016-10-20 19:03:58 -070025#include "globals.h"
Andreas Gampe5e6046b2016-10-25 12:05:53 -070026#include "jvmti.h"
Andreas Gampe6dee92e2016-09-12 19:58:13 -070027#include "mirror/object.h"
28#include "thread-inl.h"
29
30namespace openjdkjvmti {
31
Andreas Gampecc13b222016-10-10 19:09:09 -070032class EventHandler;
33
Andreas Gampe6dee92e2016-09-12 19:58:13 -070034class ObjectTagTable : public art::gc::SystemWeakHolder {
35 public:
Andreas Gampecc13b222016-10-10 19:09:09 -070036 explicit ObjectTagTable(EventHandler* event_handler)
37 : art::gc::SystemWeakHolder(art::LockLevel::kAllocTrackerLock),
Andreas Gampe3fe4d5a2016-10-21 12:32:31 -070038 update_since_last_sweep_(false),
Andreas Gampecc13b222016-10-10 19:09:09 -070039 event_handler_(event_handler) {
Andreas Gampe6dee92e2016-09-12 19:58:13 -070040 }
41
42 void Add(art::mirror::Object* obj, jlong tag)
43 REQUIRES_SHARED(art::Locks::mutator_lock_)
Andreas Gampecc13b222016-10-10 19:09:09 -070044 REQUIRES(!allow_disallow_lock_);
Andreas Gampe6dee92e2016-09-12 19:58:13 -070045
Andreas Gampecc13b222016-10-10 19:09:09 -070046 bool Remove(art::mirror::Object* obj, jlong* tag)
47 REQUIRES_SHARED(art::Locks::mutator_lock_)
48 REQUIRES(!allow_disallow_lock_);
Andreas Gampedef4ee62016-11-07 10:10:21 -080049 bool RemoveLocked(art::mirror::Object* obj, jlong* tag)
50 REQUIRES_SHARED(art::Locks::mutator_lock_)
51 REQUIRES(allow_disallow_lock_);
Andreas Gampe6dee92e2016-09-12 19:58:13 -070052
Andreas Gampee54d9922016-10-11 19:55:37 -070053 bool Set(art::mirror::Object* obj, jlong tag)
54 REQUIRES_SHARED(art::Locks::mutator_lock_)
55 REQUIRES(!allow_disallow_lock_);
Andreas Gampedef4ee62016-11-07 10:10:21 -080056 bool SetLocked(art::mirror::Object* obj, jlong tag)
57 REQUIRES_SHARED(art::Locks::mutator_lock_)
58 REQUIRES(allow_disallow_lock_);
Andreas Gampee54d9922016-10-11 19:55:37 -070059
Andreas Gampe6dee92e2016-09-12 19:58:13 -070060 bool GetTag(art::mirror::Object* obj, jlong* result)
61 REQUIRES_SHARED(art::Locks::mutator_lock_)
62 REQUIRES(!allow_disallow_lock_) {
63 art::Thread* self = art::Thread::Current();
64 art::MutexLock mu(self, allow_disallow_lock_);
65 Wait(self);
66
Andreas Gampee54eee12016-10-20 19:03:58 -070067 return GetTagLocked(self, obj, result);
Andreas Gampe6dee92e2016-09-12 19:58:13 -070068 }
Andreas Gampedef4ee62016-11-07 10:10:21 -080069 bool GetTagLocked(art::mirror::Object* obj, jlong* result)
70 REQUIRES_SHARED(art::Locks::mutator_lock_)
71 REQUIRES(allow_disallow_lock_) {
72 art::Thread* self = art::Thread::Current();
73 allow_disallow_lock_.AssertHeld(self);
74 Wait(self);
75
76 return GetTagLocked(self, obj, result);
77 }
78
79 jlong GetTagOrZero(art::mirror::Object* obj)
80 REQUIRES_SHARED(art::Locks::mutator_lock_)
81 REQUIRES(!allow_disallow_lock_) {
82 jlong tmp = 0;
83 GetTag(obj, &tmp);
84 return tmp;
85 }
86 jlong GetTagOrZeroLocked(art::mirror::Object* obj)
87 REQUIRES_SHARED(art::Locks::mutator_lock_)
88 REQUIRES(allow_disallow_lock_) {
89 jlong tmp = 0;
90 GetTagLocked(obj, &tmp);
91 return tmp;
92 }
Andreas Gampe6dee92e2016-09-12 19:58:13 -070093
Andreas Gampe6dee92e2016-09-12 19:58:13 -070094 void Sweep(art::IsMarkedVisitor* visitor)
95 REQUIRES_SHARED(art::Locks::mutator_lock_)
Andreas Gampecc13b222016-10-10 19:09:09 -070096 REQUIRES(!allow_disallow_lock_);
Andreas Gampe6dee92e2016-09-12 19:58:13 -070097
Andreas Gampe5e6046b2016-10-25 12:05:53 -070098 jvmtiError GetTaggedObjects(jvmtiEnv* jvmti_env,
99 jint tag_count,
100 const jlong* tags,
101 jint* count_ptr,
102 jobject** object_result_ptr,
103 jlong** tag_result_ptr)
104 REQUIRES_SHARED(art::Locks::mutator_lock_)
105 REQUIRES(!allow_disallow_lock_);
106
Andreas Gampedef4ee62016-11-07 10:10:21 -0800107 void Lock() ACQUIRE(allow_disallow_lock_);
108 void Unlock() RELEASE(allow_disallow_lock_);
109 void AssertLocked() ASSERT_CAPABILITY(allow_disallow_lock_);
110
Andreas Gampe6dee92e2016-09-12 19:58:13 -0700111 private:
Andreas Gampee54eee12016-10-20 19:03:58 -0700112 bool SetLocked(art::Thread* self, art::mirror::Object* obj, jlong tag)
113 REQUIRES_SHARED(art::Locks::mutator_lock_)
114 REQUIRES(allow_disallow_lock_);
115
116 bool RemoveLocked(art::Thread* self, art::mirror::Object* obj, jlong* tag)
117 REQUIRES_SHARED(art::Locks::mutator_lock_)
118 REQUIRES(allow_disallow_lock_);
119
120 bool GetTagLocked(art::Thread* self, art::mirror::Object* obj, jlong* result)
121 REQUIRES_SHARED(art::Locks::mutator_lock_)
122 REQUIRES(allow_disallow_lock_) {
123 auto it = tagged_objects_.find(art::GcRoot<art::mirror::Object>(obj));
124 if (it != tagged_objects_.end()) {
125 *result = it->second;
126 return true;
127 }
128
129 if (art::kUseReadBarrier &&
130 self != nullptr &&
Andreas Gampe3fe4d5a2016-10-21 12:32:31 -0700131 self->GetIsGcMarking() &&
132 !update_since_last_sweep_) {
Andreas Gampee54eee12016-10-20 19:03:58 -0700133 return GetTagSlowPath(self, obj, result);
134 }
135
136 return false;
137 }
138
139 // Slow-path for GetTag. We didn't find the object, but we might be storing from-pointers and
140 // are asked to retrieve with a to-pointer.
141 bool GetTagSlowPath(art::Thread* self, art::mirror::Object* obj, jlong* result)
142 REQUIRES_SHARED(art::Locks::mutator_lock_)
143 REQUIRES(allow_disallow_lock_);
144
Andreas Gampe3fe4d5a2016-10-21 12:32:31 -0700145 // Update the table by doing read barriers on each element, ensuring that to-space pointers
146 // are stored.
147 void UpdateTableWithReadBarrier()
Andreas Gampee54eee12016-10-20 19:03:58 -0700148 REQUIRES_SHARED(art::Locks::mutator_lock_)
149 REQUIRES(allow_disallow_lock_);
Andreas Gampe6dee92e2016-09-12 19:58:13 -0700150
Andreas Gampecc13b222016-10-10 19:09:09 -0700151 template <bool kHandleNull>
152 void SweepImpl(art::IsMarkedVisitor* visitor)
Andreas Gampee54eee12016-10-20 19:03:58 -0700153 REQUIRES_SHARED(art::Locks::mutator_lock_)
154 REQUIRES(!allow_disallow_lock_);
Andreas Gampecc13b222016-10-10 19:09:09 -0700155 void HandleNullSweep(jlong tag);
Andreas Gampe6dee92e2016-09-12 19:58:13 -0700156
Andreas Gampee54eee12016-10-20 19:03:58 -0700157 enum TableUpdateNullTarget {
158 kIgnoreNull,
159 kRemoveNull,
160 kCallHandleNull
161 };
162
163 template <typename T, TableUpdateNullTarget kTargetNull>
164 void UpdateTableWith(T& updater)
165 REQUIRES_SHARED(art::Locks::mutator_lock_)
166 REQUIRES(allow_disallow_lock_);
167
168 struct HashGcRoot {
169 size_t operator()(const art::GcRoot<art::mirror::Object>& r) const
170 REQUIRES_SHARED(art::Locks::mutator_lock_) {
171 return reinterpret_cast<uintptr_t>(r.Read<art::kWithoutReadBarrier>());
172 }
173 };
174
175 struct EqGcRoot {
176 bool operator()(const art::GcRoot<art::mirror::Object>& r1,
177 const art::GcRoot<art::mirror::Object>& r2) const
178 REQUIRES_SHARED(art::Locks::mutator_lock_) {
179 return r1.Read<art::kWithoutReadBarrier>() == r2.Read<art::kWithoutReadBarrier>();
180 }
181 };
182
183 std::unordered_map<art::GcRoot<art::mirror::Object>,
184 jlong,
185 HashGcRoot,
186 EqGcRoot> tagged_objects_
187 GUARDED_BY(allow_disallow_lock_)
188 GUARDED_BY(art::Locks::mutator_lock_);
Andreas Gampe3fe4d5a2016-10-21 12:32:31 -0700189 // To avoid repeatedly scanning the whole table, remember if we did that since the last sweep.
190 bool update_since_last_sweep_;
Andreas Gampecc13b222016-10-10 19:09:09 -0700191
192 EventHandler* event_handler_;
Andreas Gampe6dee92e2016-09-12 19:58:13 -0700193};
194
195} // namespace openjdkjvmti
196
197#endif // ART_RUNTIME_OPENJDKJVMTI_OBJECT_TAGGING_H_