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 *
47 _wh = src._wh;
48 }
49 // obj is always null after a copy.
50 _obj = nullptr;
51 }
52
53 void JvmtiTagMapKey::release_weak_handle() {
54 _wh.release(JvmtiExport::weak_tag_storage());
55 }
56
57 oop JvmtiTagMapKey::object() const {
58 assert(_obj == nullptr, "Must have a handle and not object");
59 return _wh.resolve();
60 }
61
62 oop JvmtiTagMapKey::object_no_keepalive() const {
63 assert(_obj == nullptr, "Must have a handle and not object");
64 return _wh.peek();
65 }
66
67 static const int INITIAL_TABLE_SIZE = 1007;
68 static const int MAX_TABLE_SIZE = 0x3fffffff;
69
70 JvmtiTagMapTable::JvmtiTagMapTable() : _table(INITIAL_TABLE_SIZE, MAX_TABLE_SIZE) {}
71
72 void JvmtiTagMapTable::clear() {
73 struct RemoveAll {
74 bool do_entry(JvmtiTagMapKey& entry, const jlong& tag) {
75 entry.release_weak_handle();
76 return true;
77 }
78 } remove_all;
79 // The unlink method of ResourceHashTable gets a pointer to a type whose 'do_entry(K,V)' method is callled
80 // while iterating over all the elements of the table. If the do_entry() method returns true the element
81 // will be removed.
82 // In this case, we always return true from do_entry to clear all the elements.
83 _table.unlink(&remove_all);
84
85 assert(_table.number_of_entries() == 0, "should have removed all entries");
86 }
87
88 JvmtiTagMapTable::~JvmtiTagMapTable() {
89 clear();
90 }
91
92 jlong JvmtiTagMapTable::find(oop obj) {
93 if (is_empty()) {
94 return 0;
95 }
96
97 if (obj->fast_no_hash_check()) {
98 // Objects in the table all have a hashcode.
99 return 0;
100 }
101
102 JvmtiTagMapKey jtme(obj);
103 jlong* found = _table.get(jtme);
104 return found == nullptr ? 0 : *found;
105 }
106
107 void JvmtiTagMapTable::add(oop obj, jlong tag) {
108 JvmtiTagMapKey new_entry(obj);
109 bool is_added;
110 if (obj->fast_no_hash_check()) {
111 // Can't be in the table so add it fast.
112 is_added = _table.put_when_absent(new_entry, tag);
113 } else {
114 jlong* value = _table.put_if_absent(new_entry, tag, &is_added);
115 *value = tag; // assign the new tag
116 }
117 if (is_added) {
118 if (_table.maybe_grow(5, true /* use_large_table_sizes */)) {
119 int max_bucket_size = DEBUG_ONLY(_table.verify()) NOT_DEBUG(0);
120 log_info(jvmti, table) ("JvmtiTagMap table resized to %d for %d entries max bucket %d",
121 _table.table_size(), _table.number_of_entries(), max_bucket_size);
122 }
123 }
124 }
125
126 void JvmtiTagMapTable::remove(oop obj) {
127 JvmtiTagMapKey jtme(obj);
128 auto clean = [] (JvmtiTagMapKey& entry, jlong tag) {
129 entry.release_weak_handle();
130 };
|
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 *
47 _wh = src._wh;
48 }
49 // obj is always null after a copy.
50 _obj = nullptr;
51 }
52
53 void JvmtiTagMapKey::release_weak_handle() {
54 _wh.release(JvmtiExport::weak_tag_storage());
55 }
56
57 oop JvmtiTagMapKey::object() const {
58 assert(_obj == nullptr, "Must have a handle and not object");
59 return _wh.resolve();
60 }
61
62 oop JvmtiTagMapKey::object_no_keepalive() const {
63 assert(_obj == nullptr, "Must have a handle and not object");
64 return _wh.peek();
65 }
66
67 unsigned JvmtiTagMapKey::get_hash(const JvmtiTagMapKey& entry) {
68 oop obj = entry._obj;
69 assert(obj != nullptr, "must lookup obj to hash");
70 if (obj->is_inline_type()) {
71 // For inline types, use the klass as a hash code and let the equals match the obj.
72 // It might have a long bucket but TBD to improve this if a customer situation arises.
73 return (unsigned)((int64_t)obj->klass() >> 3);
74 } else {
75 return (unsigned)obj->identity_hash();
76 }
77 }
78
79 // Inline types don't use hash for this table.
80 static inline bool fast_no_hash_check(oop obj) {
81 return (obj->fast_no_hash_check() && !obj->is_inline_type());
82 }
83
84 static const int INITIAL_TABLE_SIZE = 1007;
85 static const int MAX_TABLE_SIZE = 0x3fffffff;
86
87 JvmtiTagMapTable::JvmtiTagMapTable() : _table(INITIAL_TABLE_SIZE, MAX_TABLE_SIZE) {}
88
89 void JvmtiTagMapTable::clear() {
90 struct RemoveAll {
91 bool do_entry(JvmtiTagMapKey& entry, const jlong& tag) {
92 entry.release_weak_handle();
93 return true;
94 }
95 } remove_all;
96 // The unlink method of ResourceHashTable gets a pointer to a type whose 'do_entry(K,V)' method is callled
97 // while iterating over all the elements of the table. If the do_entry() method returns true the element
98 // will be removed.
99 // In this case, we always return true from do_entry to clear all the elements.
100 _table.unlink(&remove_all);
101
102 assert(_table.number_of_entries() == 0, "should have removed all entries");
103 }
104
105 JvmtiTagMapTable::~JvmtiTagMapTable() {
106 clear();
107 }
108
109 jlong JvmtiTagMapTable::find(oop obj) {
110 if (is_empty()) {
111 return 0;
112 }
113
114 if (fast_no_hash_check(obj)) {
115 // Objects in the table all have a hashcode, unless inlined types.
116 return 0;
117 }
118
119 JvmtiTagMapKey jtme(obj);
120 jlong* found = _table.get(jtme);
121 return found == nullptr ? 0 : *found;
122 }
123
124 void JvmtiTagMapTable::add(oop obj, jlong tag) {
125 JvmtiTagMapKey new_entry(obj);
126 bool is_added;
127 if (fast_no_hash_check(obj)) {
128 // Can't be in the table so add it fast.
129 is_added = _table.put_when_absent(new_entry, tag);
130 } else {
131 jlong* value = _table.put_if_absent(new_entry, tag, &is_added);
132 *value = tag; // assign the new tag
133 }
134 if (is_added) {
135 if (_table.maybe_grow(5, true /* use_large_table_sizes */)) {
136 int max_bucket_size = DEBUG_ONLY(_table.verify()) NOT_DEBUG(0);
137 log_info(jvmti, table) ("JvmtiTagMap table resized to %d for %d entries max bucket %d",
138 _table.table_size(), _table.number_of_entries(), max_bucket_size);
139 }
140 }
141 }
142
143 void JvmtiTagMapTable::remove(oop obj) {
144 JvmtiTagMapKey jtme(obj);
145 auto clean = [] (JvmtiTagMapKey& entry, jlong tag) {
146 entry.release_weak_handle();
147 };
|