blob: 071d139f18589a9da7f5e394a6f15c98575e0610 [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 Gampe6dee92e2016-09-12 19:58:13 -070049
Andreas Gampee54d9922016-10-11 19:55:37 -070050 bool Set(art::mirror::Object* obj, jlong tag)
51 REQUIRES_SHARED(art::Locks::mutator_lock_)
52 REQUIRES(!allow_disallow_lock_);
53
Andreas Gampe6dee92e2016-09-12 19:58:13 -070054 bool GetTag(art::mirror::Object* obj, jlong* result)
55 REQUIRES_SHARED(art::Locks::mutator_lock_)
56 REQUIRES(!allow_disallow_lock_) {
57 art::Thread* self = art::Thread::Current();
58 art::MutexLock mu(self, allow_disallow_lock_);
59 Wait(self);
60
Andreas Gampee54eee12016-10-20 19:03:58 -070061 return GetTagLocked(self, obj, result);
Andreas Gampe6dee92e2016-09-12 19:58:13 -070062 }
63
Andreas Gampe6dee92e2016-09-12 19:58:13 -070064 void Sweep(art::IsMarkedVisitor* visitor)
65 REQUIRES_SHARED(art::Locks::mutator_lock_)
Andreas Gampecc13b222016-10-10 19:09:09 -070066 REQUIRES(!allow_disallow_lock_);
Andreas Gampe6dee92e2016-09-12 19:58:13 -070067
Andreas Gampe5e6046b2016-10-25 12:05:53 -070068 jvmtiError GetTaggedObjects(jvmtiEnv* jvmti_env,
69 jint tag_count,
70 const jlong* tags,
71 jint* count_ptr,
72 jobject** object_result_ptr,
73 jlong** tag_result_ptr)
74 REQUIRES_SHARED(art::Locks::mutator_lock_)
75 REQUIRES(!allow_disallow_lock_);
76
Andreas Gampe6dee92e2016-09-12 19:58:13 -070077 private:
Andreas Gampee54eee12016-10-20 19:03:58 -070078 bool SetLocked(art::Thread* self, art::mirror::Object* obj, jlong tag)
79 REQUIRES_SHARED(art::Locks::mutator_lock_)
80 REQUIRES(allow_disallow_lock_);
81
82 bool RemoveLocked(art::Thread* self, art::mirror::Object* obj, jlong* tag)
83 REQUIRES_SHARED(art::Locks::mutator_lock_)
84 REQUIRES(allow_disallow_lock_);
85
86 bool GetTagLocked(art::Thread* self, art::mirror::Object* obj, jlong* result)
87 REQUIRES_SHARED(art::Locks::mutator_lock_)
88 REQUIRES(allow_disallow_lock_) {
89 auto it = tagged_objects_.find(art::GcRoot<art::mirror::Object>(obj));
90 if (it != tagged_objects_.end()) {
91 *result = it->second;
92 return true;
93 }
94
95 if (art::kUseReadBarrier &&
96 self != nullptr &&
Andreas Gampe3fe4d5a2016-10-21 12:32:31 -070097 self->GetIsGcMarking() &&
98 !update_since_last_sweep_) {
Andreas Gampee54eee12016-10-20 19:03:58 -070099 return GetTagSlowPath(self, obj, result);
100 }
101
102 return false;
103 }
104
105 // Slow-path for GetTag. We didn't find the object, but we might be storing from-pointers and
106 // are asked to retrieve with a to-pointer.
107 bool GetTagSlowPath(art::Thread* self, art::mirror::Object* obj, jlong* result)
108 REQUIRES_SHARED(art::Locks::mutator_lock_)
109 REQUIRES(allow_disallow_lock_);
110
Andreas Gampe3fe4d5a2016-10-21 12:32:31 -0700111 // Update the table by doing read barriers on each element, ensuring that to-space pointers
112 // are stored.
113 void UpdateTableWithReadBarrier()
Andreas Gampee54eee12016-10-20 19:03:58 -0700114 REQUIRES_SHARED(art::Locks::mutator_lock_)
115 REQUIRES(allow_disallow_lock_);
Andreas Gampe6dee92e2016-09-12 19:58:13 -0700116
Andreas Gampecc13b222016-10-10 19:09:09 -0700117 template <bool kHandleNull>
118 void SweepImpl(art::IsMarkedVisitor* visitor)
Andreas Gampee54eee12016-10-20 19:03:58 -0700119 REQUIRES_SHARED(art::Locks::mutator_lock_)
120 REQUIRES(!allow_disallow_lock_);
Andreas Gampecc13b222016-10-10 19:09:09 -0700121 void HandleNullSweep(jlong tag);
Andreas Gampe6dee92e2016-09-12 19:58:13 -0700122
Andreas Gampee54eee12016-10-20 19:03:58 -0700123 enum TableUpdateNullTarget {
124 kIgnoreNull,
125 kRemoveNull,
126 kCallHandleNull
127 };
128
129 template <typename T, TableUpdateNullTarget kTargetNull>
130 void UpdateTableWith(T& updater)
131 REQUIRES_SHARED(art::Locks::mutator_lock_)
132 REQUIRES(allow_disallow_lock_);
133
134 struct HashGcRoot {
135 size_t operator()(const art::GcRoot<art::mirror::Object>& r) const
136 REQUIRES_SHARED(art::Locks::mutator_lock_) {
137 return reinterpret_cast<uintptr_t>(r.Read<art::kWithoutReadBarrier>());
138 }
139 };
140
141 struct EqGcRoot {
142 bool operator()(const art::GcRoot<art::mirror::Object>& r1,
143 const art::GcRoot<art::mirror::Object>& r2) const
144 REQUIRES_SHARED(art::Locks::mutator_lock_) {
145 return r1.Read<art::kWithoutReadBarrier>() == r2.Read<art::kWithoutReadBarrier>();
146 }
147 };
148
149 std::unordered_map<art::GcRoot<art::mirror::Object>,
150 jlong,
151 HashGcRoot,
152 EqGcRoot> tagged_objects_
153 GUARDED_BY(allow_disallow_lock_)
154 GUARDED_BY(art::Locks::mutator_lock_);
Andreas Gampe3fe4d5a2016-10-21 12:32:31 -0700155 // To avoid repeatedly scanning the whole table, remember if we did that since the last sweep.
156 bool update_since_last_sweep_;
Andreas Gampecc13b222016-10-10 19:09:09 -0700157
158 EventHandler* event_handler_;
Andreas Gampe6dee92e2016-09-12 19:58:13 -0700159};
160
161} // namespace openjdkjvmti
162
163#endif // ART_RUNTIME_OPENJDKJVMTI_OBJECT_TAGGING_H_