Mercurial > hg > graal-compiler
comparison src/share/vm/oops/constantPool.cpp @ 10152:c115fac239eb
8008962: NPG: Memory regression: One extra Monitor per ConstantPool
Summary: Re-use InstanceKlass::_init_lock locking ConstantPool as well.
Reviewed-by: dholmes, coleenp, acorn
author | iklam |
---|---|
date | Thu, 25 Apr 2013 12:55:49 -0700 |
parents | 15a99ca4ee34 |
children | 51af5fae397d |
comparison
equal
deleted
inserted
replaced
10151:15a99ca4ee34 | 10152:c115fac239eb |
---|---|
38 #include "oops/objArrayKlass.hpp" | 38 #include "oops/objArrayKlass.hpp" |
39 #include "runtime/fieldType.hpp" | 39 #include "runtime/fieldType.hpp" |
40 #include "runtime/init.hpp" | 40 #include "runtime/init.hpp" |
41 #include "runtime/javaCalls.hpp" | 41 #include "runtime/javaCalls.hpp" |
42 #include "runtime/signature.hpp" | 42 #include "runtime/signature.hpp" |
43 #include "runtime/synchronizer.hpp" | |
43 #include "runtime/vframe.hpp" | 44 #include "runtime/vframe.hpp" |
44 | 45 |
45 ConstantPool* ConstantPool::allocate(ClassLoaderData* loader_data, int length, TRAPS) { | 46 ConstantPool* ConstantPool::allocate(ClassLoaderData* loader_data, int length, TRAPS) { |
46 // Tags are RW but comment below applies to tags also. | 47 // Tags are RW but comment below applies to tags also. |
47 Array<u1>* tags = MetadataFactory::new_writeable_array<u1>(loader_data, length, 0, CHECK_NULL); | 48 Array<u1>* tags = MetadataFactory::new_writeable_array<u1>(loader_data, length, 0, CHECK_NULL); |
67 set_pool_holder(NULL); | 68 set_pool_holder(NULL); |
68 set_flags(0); | 69 set_flags(0); |
69 | 70 |
70 // only set to non-zero if constant pool is merged by RedefineClasses | 71 // only set to non-zero if constant pool is merged by RedefineClasses |
71 set_version(0); | 72 set_version(0); |
72 set_lock(new Monitor(Monitor::nonleaf + 2, "A constant pool lock")); | |
73 | 73 |
74 // initialize tag array | 74 // initialize tag array |
75 int length = tags->length(); | 75 int length = tags->length(); |
76 for (int index = 0; index < length; index++) { | 76 for (int index = 0; index < length; index++) { |
77 tags->at_put(index, JVM_CONSTANT_Invalid); | 77 tags->at_put(index, JVM_CONSTANT_Invalid); |
93 } | 93 } |
94 | 94 |
95 void ConstantPool::release_C_heap_structures() { | 95 void ConstantPool::release_C_heap_structures() { |
96 // walk constant pool and decrement symbol reference counts | 96 // walk constant pool and decrement symbol reference counts |
97 unreference_symbols(); | 97 unreference_symbols(); |
98 | |
99 delete _lock; | |
100 set_lock(NULL); | |
101 } | 98 } |
102 | 99 |
103 objArrayOop ConstantPool::resolved_references() const { | 100 objArrayOop ConstantPool::resolved_references() const { |
104 return (objArrayOop)JNIHandles::resolve(_resolved_references); | 101 return (objArrayOop)JNIHandles::resolve(_resolved_references); |
105 } | 102 } |
152 Handle refs_handle (THREAD, (oop)stom); // must handleize. | 149 Handle refs_handle (THREAD, (oop)stom); // must handleize. |
153 | 150 |
154 ClassLoaderData* loader_data = pool_holder()->class_loader_data(); | 151 ClassLoaderData* loader_data = pool_holder()->class_loader_data(); |
155 set_resolved_references(loader_data->add_handle(refs_handle)); | 152 set_resolved_references(loader_data->add_handle(refs_handle)); |
156 } | 153 } |
157 | |
158 // Also need to recreate the mutex. Make sure this matches the constructor | |
159 set_lock(new Monitor(Monitor::nonleaf + 2, "A constant pool lock")); | |
160 } | 154 } |
161 } | 155 } |
162 | 156 |
163 void ConstantPool::remove_unshareable_info() { | 157 void ConstantPool::remove_unshareable_info() { |
164 // Resolved references are not in the shared archive. | 158 // Resolved references are not in the shared archive. |
165 // Save the length for restoration. It is not necessarily the same length | 159 // Save the length for restoration. It is not necessarily the same length |
166 // as reference_map.length() if invokedynamic is saved. | 160 // as reference_map.length() if invokedynamic is saved. |
167 set_resolved_reference_length( | 161 set_resolved_reference_length( |
168 resolved_references() != NULL ? resolved_references()->length() : 0); | 162 resolved_references() != NULL ? resolved_references()->length() : 0); |
169 set_resolved_references(NULL); | 163 set_resolved_references(NULL); |
170 set_lock(NULL); | 164 } |
165 | |
166 oop ConstantPool::lock() { | |
167 if (_pool_holder) { | |
168 // We re-use the _pool_holder's init_lock to reduce footprint. | |
169 // Notes on deadlocks: | |
170 // [1] This lock is a Java oop, so it can be recursively locked by | |
171 // the same thread without self-deadlocks. | |
172 // [2] Deadlock will happen if there is circular dependency between | |
173 // the <clinit> of two Java classes. However, in this case, | |
174 // the deadlock would have happened long before we reach | |
175 // ConstantPool::lock(), so reusing init_lock does not | |
176 // increase the possibility of deadlock. | |
177 return _pool_holder->init_lock(); | |
178 } else { | |
179 return NULL; | |
180 } | |
171 } | 181 } |
172 | 182 |
173 int ConstantPool::cp_to_object_index(int cp_index) { | 183 int ConstantPool::cp_to_object_index(int cp_index) { |
174 // this is harder don't do this so much. | 184 // this is harder don't do this so much. |
175 for (int i = 0; i< reference_map()->length(); i++) { | 185 for (int i = 0; i< reference_map()->length(); i++) { |
206 // until the loader_data is registered. | 216 // until the loader_data is registered. |
207 Handle mirror_handle; | 217 Handle mirror_handle; |
208 | 218 |
209 Symbol* name = NULL; | 219 Symbol* name = NULL; |
210 Handle loader; | 220 Handle loader; |
211 { MonitorLockerEx ml(this_oop->lock()); | 221 { |
222 oop cplock = this_oop->lock(); | |
223 ObjectLocker ol(cplock , THREAD, cplock != NULL); | |
212 | 224 |
213 if (this_oop->tag_at(which).is_unresolved_klass()) { | 225 if (this_oop->tag_at(which).is_unresolved_klass()) { |
214 if (this_oop->tag_at(which).is_unresolved_klass_in_error()) { | 226 if (this_oop->tag_at(which).is_unresolved_klass_in_error()) { |
215 in_error = true; | 227 in_error = true; |
216 } else { | 228 } else { |
253 ResourceMark rm; | 265 ResourceMark rm; |
254 Symbol* error = PENDING_EXCEPTION->klass()->name(); | 266 Symbol* error = PENDING_EXCEPTION->klass()->name(); |
255 | 267 |
256 bool throw_orig_error = false; | 268 bool throw_orig_error = false; |
257 { | 269 { |
258 MonitorLockerEx ml(this_oop->lock()); | 270 oop cplock = this_oop->lock(); |
271 ObjectLocker ol(cplock, THREAD, cplock != NULL); | |
259 | 272 |
260 // some other thread has beaten us and has resolved the class. | 273 // some other thread has beaten us and has resolved the class. |
261 if (this_oop->tag_at(which).is_klass()) { | 274 if (this_oop->tag_at(which).is_klass()) { |
262 CLEAR_PENDING_EXCEPTION; | 275 CLEAR_PENDING_EXCEPTION; |
263 entry = this_oop->resolved_klass_at(which); | 276 entry = this_oop->resolved_klass_at(which); |
321 InstanceKlass::cast(k())->external_name()); | 334 InstanceKlass::cast(k())->external_name()); |
322 } | 335 } |
323 } | 336 } |
324 return k(); | 337 return k(); |
325 } else { | 338 } else { |
326 MonitorLockerEx ml(this_oop->lock()); | 339 oop cplock = this_oop->lock(); |
340 ObjectLocker ol(cplock, THREAD, cplock != NULL); | |
327 // Only updated constant pool - if it is resolved. | 341 // Only updated constant pool - if it is resolved. |
328 do_resolve = this_oop->tag_at(which).is_unresolved_klass(); | 342 do_resolve = this_oop->tag_at(which).is_unresolved_klass(); |
329 if (do_resolve) { | 343 if (do_resolve) { |
330 ClassLoaderData* this_key = this_oop->pool_holder()->class_loader_data(); | 344 ClassLoaderData* this_key = this_oop->pool_holder()->class_loader_data(); |
331 this_key->record_dependency(k(), CHECK_NULL); // Can throw OOM | 345 this_key->record_dependency(k(), CHECK_NULL); // Can throw OOM |
617 // in the resolution error table, so that the same exception is thrown again. | 631 // in the resolution error table, so that the same exception is thrown again. |
618 void ConstantPool::save_and_throw_exception(constantPoolHandle this_oop, int which, | 632 void ConstantPool::save_and_throw_exception(constantPoolHandle this_oop, int which, |
619 int tag, TRAPS) { | 633 int tag, TRAPS) { |
620 ResourceMark rm; | 634 ResourceMark rm; |
621 Symbol* error = PENDING_EXCEPTION->klass()->name(); | 635 Symbol* error = PENDING_EXCEPTION->klass()->name(); |
622 MonitorLockerEx ml(this_oop->lock()); // lock cpool to change tag. | 636 oop cplock = this_oop->lock(); |
637 ObjectLocker ol(cplock, THREAD, cplock != NULL); // lock cpool to change tag. | |
623 | 638 |
624 int error_tag = (tag == JVM_CONSTANT_MethodHandle) ? | 639 int error_tag = (tag == JVM_CONSTANT_MethodHandle) ? |
625 JVM_CONSTANT_MethodHandleInError : JVM_CONSTANT_MethodTypeInError; | 640 JVM_CONSTANT_MethodHandleInError : JVM_CONSTANT_MethodTypeInError; |
626 | 641 |
627 if (!PENDING_EXCEPTION-> | 642 if (!PENDING_EXCEPTION-> |
778 } | 793 } |
779 | 794 |
780 if (cache_index >= 0) { | 795 if (cache_index >= 0) { |
781 // Cache the oop here also. | 796 // Cache the oop here also. |
782 Handle result_handle(THREAD, result_oop); | 797 Handle result_handle(THREAD, result_oop); |
783 MonitorLockerEx ml(this_oop->lock()); // don't know if we really need this | 798 oop cplock = this_oop->lock(); |
799 ObjectLocker ol(cplock, THREAD, cplock != NULL); // don't know if we really need this | |
784 oop result = this_oop->resolved_references()->obj_at(cache_index); | 800 oop result = this_oop->resolved_references()->obj_at(cache_index); |
785 // Benign race condition: resolved_references may already be filled in while we were trying to lock. | 801 // Benign race condition: resolved_references may already be filled in while we were trying to lock. |
786 // The important thing here is that all threads pick up the same result. | 802 // The important thing here is that all threads pick up the same result. |
787 // It doesn't matter which racing thread wins, as long as only one | 803 // It doesn't matter which racing thread wins, as long as only one |
788 // result is used by all threads, and all future queries. | 804 // result is used by all threads, and all future queries. |