2424
2525#include " memory/allocation.hpp"
2626#include " memory/universe.hpp"
27+ #include " oops/fieldStreams.inline.hpp"
2728#include " oops/oop.inline.hpp"
2829#include " oops/weakHandle.inline.hpp"
2930#include " prims/jvmtiExport.hpp"
3233
3334JvmtiTagMapKey::JvmtiTagMapKey (oop obj) : _obj(obj) {}
3435
35- JvmtiTagMapKey::JvmtiTagMapKey (const JvmtiTagMapKey& src) {
36- // move object into WeakHandle when copying into the table
36+ JvmtiTagMapKey::JvmtiTagMapKey (const JvmtiTagMapKey& src) : _h() {
37+ // move object into Handle when copying into the table
3738 if (src._obj != nullptr ) {
39+ _is_weak = !src._obj ->klass ()->is_inline_klass ();
3840
3941 // obj was read with AS_NO_KEEPALIVE, or equivalent, like during
4042 // a heap walk. The object needs to be kept alive when it is published.
4143 Universe::heap ()->keep_alive (src._obj );
4244
43- _wh = WeakHandle (JvmtiExport::weak_tag_storage (), src._obj );
45+ if (_is_weak) {
46+ _wh = WeakHandle (JvmtiExport::weak_tag_storage (), src._obj );
47+ } else {
48+ _h = OopHandle (JvmtiExport::jvmti_oop_storage (), src._obj );
49+ }
4450 } else {
4551 // resizing needs to create a copy.
46- _wh = src._wh ;
52+ if (_is_weak) {
53+ _wh = src._wh ;
54+ } else {
55+ _h = src._h ;
56+ }
4757 }
4858 // obj is always null after a copy.
4959 _obj = nullptr ;
5060}
5161
52- void JvmtiTagMapKey::release_weak_handle () {
53- _wh.release (JvmtiExport::weak_tag_storage ());
62+ void JvmtiTagMapKey::release_handle () {
63+ if (_is_weak) {
64+ _wh.release (JvmtiExport::weak_tag_storage ());
65+ } else {
66+ _h.release (JvmtiExport::jvmti_oop_storage ());
67+ }
5468}
5569
5670oop JvmtiTagMapKey::object () const {
5771 assert (_obj == nullptr , " Must have a handle and not object" );
58- return _wh.resolve ();
72+ return _is_weak ? _wh. resolve () : _h .resolve ();
5973}
6074
6175oop JvmtiTagMapKey::object_no_keepalive () const {
6276 assert (_obj == nullptr , " Must have a handle and not object" );
63- return _wh.peek ();
77+ return _is_weak ? _wh. peek () : _h .peek ();
6478}
6579
6680unsigned JvmtiTagMapKey::get_hash (const JvmtiTagMapKey& entry) {
@@ -75,6 +89,77 @@ unsigned JvmtiTagMapKey::get_hash(const JvmtiTagMapKey& entry) {
7589 }
7690}
7791
92+ static bool equal_oops (oop obj1, oop obj2); // forward declaration
93+
94+ static bool equal_fields (char type, oop obj1, oop obj2, int offset) {
95+ switch (type) {
96+ case JVM_SIGNATURE_BOOLEAN:
97+ return obj1->bool_field (offset) == obj2->bool_field (offset);
98+ case JVM_SIGNATURE_CHAR:
99+ return obj1->char_field (offset) == obj2->char_field (offset);
100+ case JVM_SIGNATURE_FLOAT:
101+ return obj1->float_field (offset) == obj2->float_field (offset);
102+ case JVM_SIGNATURE_DOUBLE:
103+ return obj1->double_field (offset) == obj2->double_field (offset);
104+ case JVM_SIGNATURE_BYTE:
105+ return obj1->byte_field (offset) == obj2->byte_field (offset);
106+ case JVM_SIGNATURE_SHORT:
107+ return obj1->short_field (offset) == obj2->short_field (offset);
108+ case JVM_SIGNATURE_INT:
109+ return obj1->int_field (offset) == obj2->int_field (offset);
110+ case JVM_SIGNATURE_LONG:
111+ return obj1->long_field (offset) == obj2->long_field (offset);
112+ case JVM_SIGNATURE_CLASS:
113+ case JVM_SIGNATURE_ARRAY:
114+ return equal_oops (obj1->obj_field (offset), obj2->obj_field (offset));
115+ }
116+ ShouldNotReachHere ();
117+ }
118+
119+ // For heap-allocated objects offset is 0 and 'klass' is obj1->klass() (== obj2->klass()).
120+ // For flattened objects offset is the offset in the holder object, 'klass' is inlined object class.
121+ static bool equal_value_objects (oop obj1, oop obj2, InlineKlass* klass, int offset) {
122+ for (JavaFieldStream fld (klass); !fld.done (); fld.next ()) {
123+ // ignore static fields
124+ if (fld.access_flags ().is_static ()) {
125+ continue ;
126+ }
127+ int field_offset = offset + fld.offset () - (offset > 0 ? klass->payload_offset () : 0 );
128+ if (fld.is_flat ()) { // flat value field
129+ InstanceKlass* holder_klass = fld.field_holder ();
130+ InlineKlass* field_klass = holder_klass->get_inline_type_field_klass (fld.index ());
131+ if (!equal_value_objects (obj1, obj2, field_klass, field_offset)) {
132+ return false ;
133+ }
134+ } else {
135+ if (!equal_fields (fld.signature ()->char_at (0 ), obj1, obj2, field_offset)) {
136+ return false ;
137+ }
138+ }
139+ }
140+ return true ;
141+ }
142+
143+ static bool equal_oops (oop obj1, oop obj2) {
144+ if (obj1 == obj2) {
145+ return true ;
146+ }
147+
148+ if (EnableValhalla) {
149+ if (obj1 != nullptr && obj2 != nullptr && obj1->klass () == obj2->klass () && obj1->is_inline_type ()) {
150+ InlineKlass* vk = InlineKlass::cast (obj1->klass ());
151+ return equal_value_objects (obj1, obj2, vk, 0 );
152+ }
153+ }
154+ return false ;
155+ }
156+
157+ bool JvmtiTagMapKey::equals (const JvmtiTagMapKey& lhs, const JvmtiTagMapKey& rhs) {
158+ oop lhs_obj = lhs._obj != nullptr ? lhs._obj : lhs.object_no_keepalive ();
159+ oop rhs_obj = rhs._obj != nullptr ? rhs._obj : rhs.object_no_keepalive ();
160+ return equal_oops (lhs_obj, rhs_obj);
161+ }
162+
78163// Inline types don't use hash for this table.
79164static inline bool fast_no_hash_check (oop obj) {
80165 return (obj->fast_no_hash_check () && !obj->is_inline_type ());
@@ -88,7 +173,7 @@ JvmtiTagMapTable::JvmtiTagMapTable() : _table(INITIAL_TABLE_SIZE, MAX_TABLE_SIZE
88173void JvmtiTagMapTable::clear () {
89174 struct RemoveAll {
90175 bool do_entry (JvmtiTagMapKey& entry, const jlong& tag) {
91- entry.release_weak_handle ();
176+ entry.release_handle ();
92177 return true ;
93178 }
94179 } remove_all;
@@ -142,7 +227,7 @@ void JvmtiTagMapTable::add(oop obj, jlong tag) {
142227void JvmtiTagMapTable::remove (oop obj) {
143228 JvmtiTagMapKey jtme (obj);
144229 auto clean = [] (JvmtiTagMapKey& entry, jlong tag) {
145- entry.release_weak_handle ();
230+ entry.release_handle ();
146231 };
147232 _table.remove (jtme, clean);
148233}
@@ -160,7 +245,7 @@ void JvmtiTagMapTable::remove_dead_entries(GrowableArray<jlong>* objects) {
160245 if (_objects != nullptr ) {
161246 _objects->append (tag);
162247 }
163- entry.release_weak_handle ();
248+ entry.release_handle ();
164249 return true ;
165250 }
166251 return false ;;
0 commit comments