21 * questions. |
21 * questions. |
22 * |
22 * |
23 */ |
23 */ |
24 |
24 |
25 #include "precompiled.hpp" |
25 #include "precompiled.hpp" |
|
26 #include "classfile/resolutionErrors.hpp" |
26 #include "interpreter/bytecodeStream.hpp" |
27 #include "interpreter/bytecodeStream.hpp" |
27 #include "interpreter/bytecodes.hpp" |
28 #include "interpreter/bytecodes.hpp" |
28 #include "interpreter/interpreter.hpp" |
29 #include "interpreter/interpreter.hpp" |
29 #include "interpreter/rewriter.hpp" |
30 #include "interpreter/rewriter.hpp" |
30 #include "logging/log.hpp" |
31 #include "logging/log.hpp" |
106 |
107 |
107 // Sets f1, ordering with previous writes. |
108 // Sets f1, ordering with previous writes. |
108 void ConstantPoolCacheEntry::release_set_f1(Metadata* f1) { |
109 void ConstantPoolCacheEntry::release_set_f1(Metadata* f1) { |
109 assert(f1 != NULL, ""); |
110 assert(f1 != NULL, ""); |
110 OrderAccess::release_store(&_f1, f1); |
111 OrderAccess::release_store(&_f1, f1); |
|
112 } |
|
113 |
|
114 void ConstantPoolCacheEntry::set_indy_resolution_failed() { |
|
115 OrderAccess::release_store(&_flags, _flags | (1 << indy_resolution_failed_shift)); |
111 } |
116 } |
112 |
117 |
113 // Note that concurrent update of both bytecodes can leave one of them |
118 // Note that concurrent update of both bytecodes can leave one of them |
114 // reset to zero. This is harmless; the interpreter will simply re-resolve |
119 // reset to zero. This is harmless; the interpreter will simply re-resolve |
115 // the damaged entry. More seriously, the memory synchronization is needed |
120 // the damaged entry. More seriously, the memory synchronization is needed |
316 ObjectLocker ol(resolved_references, Thread::current()); |
321 ObjectLocker ol(resolved_references, Thread::current()); |
317 if (!is_f1_null()) { |
322 if (!is_f1_null()) { |
318 return; |
323 return; |
319 } |
324 } |
320 |
325 |
|
326 if (indy_resolution_failed()) { |
|
327 // Before we got here, another thread got a LinkageError exception during |
|
328 // resolution. Ignore our success and throw their exception. |
|
329 ConstantPoolCache* cpCache = cpool->cache(); |
|
330 int index = -1; |
|
331 for (int i = 0; i < cpCache->length(); i++) { |
|
332 if (cpCache->entry_at(i) == this) { |
|
333 index = i; |
|
334 break; |
|
335 } |
|
336 } |
|
337 guarantee(index >= 0, "Didn't find cpCache entry!"); |
|
338 int encoded_index = ResolutionErrorTable::encode_cpcache_index( |
|
339 ConstantPool::encode_invokedynamic_index(index)); |
|
340 Thread* THREAD = Thread::current(); |
|
341 ConstantPool::throw_resolution_error(cpool, encoded_index, THREAD); |
|
342 return; |
|
343 } |
|
344 |
321 const methodHandle adapter = call_info.resolved_method(); |
345 const methodHandle adapter = call_info.resolved_method(); |
322 const Handle appendix = call_info.resolved_appendix(); |
346 const Handle appendix = call_info.resolved_appendix(); |
323 const Handle method_type = call_info.resolved_method_type(); |
347 const Handle method_type = call_info.resolved_method_type(); |
324 const bool has_appendix = appendix.not_null(); |
348 const bool has_appendix = appendix.not_null(); |
325 const bool has_method_type = method_type.not_null(); |
349 const bool has_method_type = method_type.not_null(); |
385 NOT_PRODUCT(verify(tty)); |
409 NOT_PRODUCT(verify(tty)); |
386 if (TraceInvokeDynamic) { |
410 if (TraceInvokeDynamic) { |
387 ttyLocker ttyl; |
411 ttyLocker ttyl; |
388 this->print(tty, 0); |
412 this->print(tty, 0); |
389 } |
413 } |
|
414 } |
|
415 |
|
416 bool ConstantPoolCacheEntry::save_and_throw_indy_exc( |
|
417 const constantPoolHandle& cpool, int cpool_index, int index, constantTag tag, TRAPS) { |
|
418 |
|
419 assert(HAS_PENDING_EXCEPTION, "No exception got thrown!"); |
|
420 assert(PENDING_EXCEPTION->is_a(SystemDictionary::LinkageError_klass()), |
|
421 "No LinkageError exception"); |
|
422 |
|
423 // Use the resolved_references() lock for this cpCache entry. |
|
424 // resolved_references are created for all classes with Invokedynamic, MethodHandle |
|
425 // or MethodType constant pool cache entries. |
|
426 objArrayHandle resolved_references(Thread::current(), cpool->resolved_references()); |
|
427 assert(resolved_references() != NULL, |
|
428 "a resolved_references array should have been created for this class"); |
|
429 ObjectLocker ol(resolved_references, THREAD); |
|
430 |
|
431 // if f1 is not null or the indy_resolution_failed flag is set then another |
|
432 // thread either succeeded in resolving the method or got a LinkageError |
|
433 // exception, before this thread was able to record its failure. So, clear |
|
434 // this thread's exception and return false so caller can use the earlier |
|
435 // thread's result. |
|
436 if (!is_f1_null() || indy_resolution_failed()) { |
|
437 CLEAR_PENDING_EXCEPTION; |
|
438 return false; |
|
439 } |
|
440 |
|
441 Symbol* error = PENDING_EXCEPTION->klass()->name(); |
|
442 Symbol* message = java_lang_Throwable::detail_message(PENDING_EXCEPTION); |
|
443 assert("message != NULL", "Missing detail message"); |
|
444 |
|
445 SystemDictionary::add_resolution_error(cpool, index, error, message); |
|
446 set_indy_resolution_failed(); |
|
447 return true; |
390 } |
448 } |
391 |
449 |
392 Method* ConstantPoolCacheEntry::method_if_resolved(const constantPoolHandle& cpool) { |
450 Method* ConstantPoolCacheEntry::method_if_resolved(const constantPoolHandle& cpool) { |
393 // Decode the action of set_method and set_interface_call |
451 // Decode the action of set_method and set_interface_call |
394 Bytecodes::Code invoke_code = bytecode_1(); |
452 Bytecodes::Code invoke_code = bytecode_1(); |