1 /*
2 * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25 #ifndef SHARE_VM_PRIMS_TAGMAPTABLE_HPP
26 #define SHARE_VM_PRIMS_TAGMAPTABLE_HPP
27
28 #include "gc/shared/collectedHeap.hpp"
29 #include "memory/allocation.hpp"
30 #include "oops/weakHandle.hpp"
31 #include "utilities/resizeableResourceHash.hpp"
32
33 class JvmtiEnv;
34 class JvmtiTagMapKeyClosure;
35
36 // The oop is needed for lookup rather than creating a WeakHandle during
37 // lookup because the HeapWalker may walk soon to be dead objects and
38 // creating a WeakHandle for an otherwise dead object makes G1 unhappy.
39 //
40 // This class is the Key type for inserting in ResizeableResourceHashTable
41 // Its get_hash() and equals() methods are also used for getting the hash
42 // value of a Key and comparing two Keys, respectively.
43 class JvmtiTagMapKey : public CHeapObj<mtServiceability> {
44 WeakHandle _wh;
45 oop _obj; // temporarily hold obj while searching
46 public:
47 JvmtiTagMapKey(oop obj);
48 JvmtiTagMapKey(const JvmtiTagMapKey& src);
49 JvmtiTagMapKey& operator=(const JvmtiTagMapKey&) = delete;
50
51 oop object() const;
52 oop object_no_keepalive() const;
53 void release_weak_handle();
54
55 static unsigned get_hash(const JvmtiTagMapKey& entry) {
56 assert(entry._obj != nullptr, "must lookup obj to hash");
57 return (unsigned)entry._obj->identity_hash();
58 }
59
60 static bool equals(const JvmtiTagMapKey& lhs, const JvmtiTagMapKey& rhs) {
61 oop lhs_obj = lhs._obj != nullptr ? lhs._obj : lhs.object_no_keepalive();
62 oop rhs_obj = rhs._obj != nullptr ? rhs._obj : rhs.object_no_keepalive();
63 return lhs_obj == rhs_obj;
64 }
65 };
66
67 typedef
68 ResizeableResourceHashtable <JvmtiTagMapKey, jlong,
69 AnyObj::C_HEAP, mtServiceability,
70 JvmtiTagMapKey::get_hash,
71 JvmtiTagMapKey::equals> ResizableResourceHT;
72
73 class JvmtiTagMapTable : public CHeapObj<mtServiceability> {
74 private:
75 ResizableResourceHT _table;
76
77 public:
78 JvmtiTagMapTable();
79 ~JvmtiTagMapTable();
80
81 jlong find(oop obj);
82 void add(oop obj, jlong tag);
83
84 void remove(oop obj);
85
86 // iterate over all entries in the hashmap
87 void entry_iterate(JvmtiTagMapKeyClosure* closure);
88
89 bool is_empty() const { return _table.number_of_entries() == 0; }
90
91 // Cleanup cleared entries and store dead object tags in objects array
92 void remove_dead_entries(GrowableArray<jlong>* objects);
93 void clear();
94 };
95
96 // A supporting class for iterating over all entries in Hashmap
97 class JvmtiTagMapKeyClosure {
98 public:
99 virtual bool do_entry(JvmtiTagMapKey& key, jlong& value) = 0;
100 };
101
102 #endif // SHARE_VM_PRIMS_TAGMAPTABLE_HPP
|
1 /*
2 * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25 #ifndef SHARE_VM_PRIMS_TAGMAPTABLE_HPP
26 #define SHARE_VM_PRIMS_TAGMAPTABLE_HPP
27
28 #include "gc/shared/collectedHeap.hpp"
29 #include "memory/allocation.hpp"
30 #include "oops/layoutKind.hpp"
31 #include "oops/weakHandle.hpp"
32 #include "utilities/resizeableResourceHash.hpp"
33
34 class JvmtiEnv;
35
36 // Describes an object which can be tagged during heap walk operation.
37 // - generic heap object: _obj: oop, offset == 0, _inline_klass == nullptr;
38 // - value heap object: _obj: oop, offset == 0, _inline_klass == _obj.klass();
39 // - flat value object: _obj: holder object, offset == offset in the holder, _inline_klass == klass of the flattened object;
40 class JvmtiHeapwalkObject {
41 oop _obj; // for flattened value object this is holder object
42 int _offset; // == 0 for heap objects
43 InlineKlass* _inline_klass; // for value object, nullptr otherwise
44 LayoutKind _layout_kind; // layout kind in holder object, used only for flat->heap conversion
45
46 static InlineKlass* inline_klass_or_null(oop obj) {
47 Klass* k = obj->klass();
48 return k->is_inline_klass() ? InlineKlass::cast(k) : nullptr;
49 }
50 public:
51 JvmtiHeapwalkObject(): _obj(nullptr), _offset(0), _inline_klass(nullptr), _layout_kind(LayoutKind::UNKNOWN) {}
52 JvmtiHeapwalkObject(oop obj): _obj(obj), _offset(0), _inline_klass(inline_klass_or_null(obj)), _layout_kind(LayoutKind::REFERENCE) {}
53 JvmtiHeapwalkObject(oop obj, int offset, InlineKlass* ik, LayoutKind lk): _obj(obj), _offset(offset), _inline_klass(ik), _layout_kind(lk) {}
54
55 inline bool is_empty() const { return _obj == nullptr; }
56 inline bool is_value() const { return _inline_klass != nullptr; }
57 inline bool is_flat() const { return _offset != 0; }
58
59 inline oop obj() const { return _obj; }
60 inline int offset() const { return _offset; }
61 inline InlineKlass* inline_klass() const { return _inline_klass; }
62 inline LayoutKind layout_kind() const { return _layout_kind; }
63
64 inline Klass* klass() const { return is_value() ? _inline_klass : obj()->klass(); }
65
66 static bool equals(const JvmtiHeapwalkObject& obj1, const JvmtiHeapwalkObject& obj2);
67
68 bool operator==(const JvmtiHeapwalkObject& other) const {
69 // need to compare inline_klass too to handle the case when flat object has flat field at offset 0
70 return _obj == other._obj && _offset == other._offset && _inline_klass == other._inline_klass;
71 }
72 bool operator!=(const JvmtiHeapwalkObject& other) const {
73 return !(*this == other);
74 }
75 };
76
77
78 // The oop is needed for lookup rather than creating a WeakHandle during
79 // lookup because the HeapWalker may walk soon to be dead objects and
80 // creating a WeakHandle for an otherwise dead object makes G1 unhappy.
81 //
82 // This class is the Key type for inserting in ResizeableResourceHashTable
83 // Its get_hash() and equals() methods are also used for getting the hash
84 // value of a Key and comparing two Keys, respectively.
85 //
86 // Value objects: keep just one tag for all equal value objects including heap allocated value objects.
87 // We have to keep a strong reference to each unique value object with a non-zero tag.
88 // During heap walking flattened value object tags stored in separate JvmtiFlatTagMapTable,
89 // converted to standard strong entries in JvmtiTagMapTable outside of sefepoint.
90 // All equal value objects should have the same tag.
91 // Keep value objects alive (1 copy for each "value") until their tags are removed.
92
93 class JvmtiTagMapKey : public CHeapObj<mtServiceability> {
94 union {
95 WeakHandle _wh;
96 OopHandle _h; // for value objects (_is_weak == false)
97 };
98 bool _is_weak;
99 // temporarily hold obj while searching
100 const JvmtiHeapwalkObject* _obj;
101
102 public:
103 JvmtiTagMapKey(const JvmtiHeapwalkObject* obj);
104 // Copy ctor is called when we put entry to the hash table.
105 JvmtiTagMapKey(const JvmtiTagMapKey& src);
106
107 JvmtiTagMapKey& operator=(const JvmtiTagMapKey&) = delete;
108
109 JvmtiHeapwalkObject heapwalk_object() const;
110
111 oop object() const;
112 oop object_no_keepalive() const;
113 void release_handle();
114
115 static unsigned get_hash(const JvmtiTagMapKey& entry);
116 static bool equals(const JvmtiTagMapKey& lhs, const JvmtiTagMapKey& rhs);
117 };
118
119 typedef
120 ResizeableResourceHashtable <JvmtiTagMapKey, jlong,
121 AnyObj::C_HEAP, mtServiceability,
122 JvmtiTagMapKey::get_hash,
123 JvmtiTagMapKey::equals> ResizableResourceHT;
124
125 // A supporting class for iterating over all entries in Hashmap
126 class JvmtiTagMapKeyClosure {
127 public:
128 virtual bool do_entry(JvmtiTagMapKey& key, jlong& value) = 0;
129 };
130
131 class JvmtiTagMapTable : public CHeapObj<mtServiceability> {
132 private:
133 ResizableResourceHT _table;
134
135 jlong* lookup(const JvmtiHeapwalkObject& obj) const;
136
137 public:
138 JvmtiTagMapTable();
139 ~JvmtiTagMapTable();
140
141 int number_of_entries() const { return _table.number_of_entries(); }
142
143 jlong find(const JvmtiHeapwalkObject& obj) const;
144 // obj cannot be flat
145 void add(const JvmtiHeapwalkObject& obj, jlong tag);
146 // update the tag if the entry exists, returns false otherwise
147 bool update(const JvmtiHeapwalkObject& obj, jlong tag);
148
149 bool remove(const JvmtiHeapwalkObject& obj);
150
151 // iterate over all entries in the hashmap
152 void entry_iterate(JvmtiTagMapKeyClosure* closure);
153
154 bool is_empty() const { return _table.number_of_entries() == 0; }
155
156 // Cleanup cleared entries and store dead object tags in objects array
157 void remove_dead_entries(GrowableArray<jlong>* objects);
158 void clear();
159 };
160
161
162 // This class is the Key type for hash table to keep flattened value objects during heap walk operations.
163 // The objects needs to be moved to JvmtiTagMapTable outside of safepoint.
164 class JvmtiFlatTagMapKey: public CHeapObj<mtServiceability> {
165 private:
166 // holder object
167 OopHandle _h;
168 // temporarily holds holder object while searching
169 oop _holder;
170 int _offset;
171 InlineKlass* _inline_klass;
172 LayoutKind _layout_kind;
173 public:
174 JvmtiFlatTagMapKey(const JvmtiHeapwalkObject& obj);
175 // Copy ctor is called when we put entry to the hash table.
176 JvmtiFlatTagMapKey(const JvmtiFlatTagMapKey& src);
177
178 JvmtiFlatTagMapKey& operator=(const JvmtiFlatTagMapKey&) = delete;
179
180 JvmtiHeapwalkObject heapwalk_object() const;
181
182 oop holder() const;
183 oop holder_no_keepalive() const;
184 int offset() const { return _offset; }
185 InlineKlass* inline_klass() const { return _inline_klass; }
186 LayoutKind layout_kind() const { return _layout_kind; }
187
188 void release_handle();
189
190 static unsigned get_hash(const JvmtiFlatTagMapKey& entry);
191 static bool equals(const JvmtiFlatTagMapKey& lhs, const JvmtiFlatTagMapKey& rhs);
192 };
193
194 typedef
195 ResizeableResourceHashtable <JvmtiFlatTagMapKey, jlong,
196 AnyObj::C_HEAP, mtServiceability,
197 JvmtiFlatTagMapKey::get_hash,
198 JvmtiFlatTagMapKey::equals> FlatObjectHashtable;
199
200 // A supporting class for iterating over all entries in JvmtiFlatTagMapTable.
201 class JvmtiFlatTagMapKeyClosure {
202 public:
203 virtual bool do_entry(JvmtiFlatTagMapKey& key, jlong& value) = 0;
204 };
205
206 class JvmtiFlatTagMapTable: public CHeapObj<mtServiceability> {
207 private:
208 FlatObjectHashtable _table;
209
210 public:
211 JvmtiFlatTagMapTable();
212 ~JvmtiFlatTagMapTable();
213
214 int number_of_entries() const { return _table.number_of_entries(); }
215
216 jlong find(const JvmtiHeapwalkObject& obj) const;
217 // obj must be flat
218 void add(const JvmtiHeapwalkObject& obj, jlong tag);
219
220 // returns tag for the entry, 0 is not found
221 jlong remove(const JvmtiHeapwalkObject& obj);
222
223 // iterate over entries in the hashmap
224 void entry_iterate(JvmtiFlatTagMapKeyClosure* closure);
225
226 bool is_empty() const { return _table.number_of_entries() == 0; }
227
228 void clear();
229 };
230
231 #endif // SHARE_VM_PRIMS_TAGMAPTABLE_HPP
|