blob: e276c524ca0f147a5ef8a809f8b3aa451b8f5eaf [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
20#include "base/mutex.h"
21#include "gc/system_weak.h"
22#include "gc_root-inl.h"
23#include "mirror/object.h"
24#include "thread-inl.h"
25
26namespace openjdkjvmti {
27
28class ObjectTagTable : public art::gc::SystemWeakHolder {
29 public:
30 ObjectTagTable() : art::gc::SystemWeakHolder(art::LockLevel::kAllocTrackerLock) {
31 }
32
33 void Add(art::mirror::Object* obj, jlong tag)
34 REQUIRES_SHARED(art::Locks::mutator_lock_)
35 REQUIRES(!allow_disallow_lock_) {
36 art::Thread* self = art::Thread::Current();
37 art::MutexLock mu(self, allow_disallow_lock_);
38 Wait(self);
39
40 if (first_free_ == tagged_objects_.size()) {
41 tagged_objects_.push_back(Entry(art::GcRoot<art::mirror::Object>(obj), tag));
42 first_free_++;
43 } else {
44 DCHECK_LT(first_free_, tagged_objects_.size());
45 DCHECK(tagged_objects_[first_free_].first.IsNull());
46 tagged_objects_[first_free_] = Entry(art::GcRoot<art::mirror::Object>(obj), tag);
47 // TODO: scan for free elements.
48 first_free_ = tagged_objects_.size();
49 }
50 }
51
52 bool GetTag(art::mirror::Object* obj, jlong* result)
53 REQUIRES_SHARED(art::Locks::mutator_lock_)
54 REQUIRES(!allow_disallow_lock_) {
55 art::Thread* self = art::Thread::Current();
56 art::MutexLock mu(self, allow_disallow_lock_);
57 Wait(self);
58
59 for (const auto& pair : tagged_objects_) {
60 if (pair.first.Read(nullptr) == obj) {
61 *result = pair.second;
62 return true;
63 }
64 }
65
66 return false;
67 }
68
69 bool Remove(art::mirror::Object* obj, jlong* tag)
70 REQUIRES_SHARED(art::Locks::mutator_lock_)
71 REQUIRES(!allow_disallow_lock_) {
72 art::Thread* self = art::Thread::Current();
73 art::MutexLock mu(self, allow_disallow_lock_);
74 Wait(self);
75
76 for (auto it = tagged_objects_.begin(); it != tagged_objects_.end(); ++it) {
77 if (it->first.Read(nullptr) == obj) {
78 if (tag != nullptr) {
79 *tag = it->second;
80 }
81 it->first = art::GcRoot<art::mirror::Object>(nullptr);
82
83 size_t index = it - tagged_objects_.begin();
84 if (index < first_free_) {
85 first_free_ = index;
86 }
87
88 // TODO: compaction.
89
90 return true;
91 }
92 }
93
94 return false;
95 }
96
97 void Sweep(art::IsMarkedVisitor* visitor)
98 REQUIRES_SHARED(art::Locks::mutator_lock_)
99 REQUIRES(!allow_disallow_lock_) {
100 art::Thread* self = art::Thread::Current();
101 art::MutexLock mu(self, allow_disallow_lock_);
102
103 for (auto it = tagged_objects_.begin(); it != tagged_objects_.end(); ++it) {
104 if (!it->first.IsNull()) {
105 art::mirror::Object* original_obj = it->first.Read();
106 art::mirror::Object* target_obj = visitor->IsMarked(original_obj);
107 if (original_obj != target_obj) {
108 it->first = art::GcRoot<art::mirror::Object>(target_obj);
109
110 if (target_obj == nullptr) {
111 HandleNullSweep(it->second);
112 }
113 }
114 } else {
115 size_t index = it - tagged_objects_.begin();
116 if (index < first_free_) {
117 first_free_ = index;
118 }
119 }
120 }
121 }
122
123 private:
124 using Entry = std::pair<art::GcRoot<art::mirror::Object>, jlong>;
125
126 void HandleNullSweep(jlong tag ATTRIBUTE_UNUSED) {
127 // TODO: Handle deallocation reporting here. We'll have to enqueue tags temporarily, as we
128 // probably shouldn't call the callbacks directly (to avoid any issues).
129 }
130
131 std::vector<Entry> tagged_objects_ GUARDED_BY(allow_disallow_lock_);
132 size_t first_free_ = 0;
133};
134
135} // namespace openjdkjvmti
136
137#endif // ART_RUNTIME_OPENJDKJVMTI_OBJECT_TAGGING_H_