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