242 set_bytecode_1(Bytecodes::_invokeinterface); |
242 set_bytecode_1(Bytecodes::_invokeinterface); |
243 } |
243 } |
244 |
244 |
245 |
245 |
246 void ConstantPoolCacheEntry::set_method_handle(constantPoolHandle cpool, |
246 void ConstantPoolCacheEntry::set_method_handle(constantPoolHandle cpool, |
247 methodHandle adapter, Handle appendix, |
247 methodHandle adapter, |
|
248 Handle appendix, Handle method_type, |
248 objArrayHandle resolved_references) { |
249 objArrayHandle resolved_references) { |
249 set_method_handle_common(cpool, Bytecodes::_invokehandle, adapter, appendix, resolved_references); |
250 set_method_handle_common(cpool, Bytecodes::_invokehandle, adapter, appendix, method_type, resolved_references); |
250 } |
251 } |
251 |
252 |
252 void ConstantPoolCacheEntry::set_dynamic_call(constantPoolHandle cpool, |
253 void ConstantPoolCacheEntry::set_dynamic_call(constantPoolHandle cpool, |
253 methodHandle adapter, Handle appendix, |
254 methodHandle adapter, |
|
255 Handle appendix, Handle method_type, |
254 objArrayHandle resolved_references) { |
256 objArrayHandle resolved_references) { |
255 set_method_handle_common(cpool, Bytecodes::_invokedynamic, adapter, appendix, resolved_references); |
257 set_method_handle_common(cpool, Bytecodes::_invokedynamic, adapter, appendix, method_type, resolved_references); |
256 } |
258 } |
257 |
259 |
258 void ConstantPoolCacheEntry::set_method_handle_common(constantPoolHandle cpool, |
260 void ConstantPoolCacheEntry::set_method_handle_common(constantPoolHandle cpool, |
259 Bytecodes::Code invoke_code, |
261 Bytecodes::Code invoke_code, |
260 methodHandle adapter, |
262 methodHandle adapter, |
261 Handle appendix, |
263 Handle appendix, Handle method_type, |
262 objArrayHandle resolved_references) { |
264 objArrayHandle resolved_references) { |
263 // NOTE: This CPCE can be the subject of data races. |
265 // NOTE: This CPCE can be the subject of data races. |
264 // There are three words to update: flags, refs[f2], f1 (in that order). |
266 // There are three words to update: flags, refs[f2], f1 (in that order). |
265 // Writers must store all other values before f1. |
267 // Writers must store all other values before f1. |
266 // Readers must test f1 first for non-null before reading other fields. |
268 // Readers must test f1 first for non-null before reading other fields. |
272 MonitorLockerEx ml(cpool->lock()); |
274 MonitorLockerEx ml(cpool->lock()); |
273 if (!is_f1_null()) { |
275 if (!is_f1_null()) { |
274 return; |
276 return; |
275 } |
277 } |
276 |
278 |
277 bool has_appendix = appendix.not_null(); |
279 const bool has_appendix = appendix.not_null(); |
|
280 const bool has_method_type = method_type.not_null(); |
278 |
281 |
279 // Write the flags. |
282 // Write the flags. |
280 set_method_flags(as_TosState(adapter->result_type()), |
283 set_method_flags(as_TosState(adapter->result_type()), |
281 ((has_appendix ? 1 : 0) << has_appendix_shift) | |
284 ((has_appendix ? 1 : 0) << has_appendix_shift ) | |
282 ( 1 << is_final_shift), |
285 ((has_method_type ? 1 : 0) << has_method_type_shift) | |
|
286 ( 1 << is_final_shift ), |
283 adapter->size_of_parameters()); |
287 adapter->size_of_parameters()); |
284 |
288 |
285 if (TraceInvokeDynamic) { |
289 if (TraceInvokeDynamic) { |
286 tty->print_cr("set_method_handle bc=%d appendix="PTR_FORMAT"%s method="PTR_FORMAT" ", |
290 tty->print_cr("set_method_handle bc=%d appendix="PTR_FORMAT"%s method_type="PTR_FORMAT"%s method="PTR_FORMAT" ", |
287 invoke_code, |
291 invoke_code, |
288 (intptr_t)appendix(), (has_appendix ? "" : " (unused)"), |
292 (intptr_t)appendix(), (has_appendix ? "" : " (unused)"), |
|
293 (intptr_t)method_type(), (has_method_type ? "" : " (unused)"), |
289 (intptr_t)adapter()); |
294 (intptr_t)adapter()); |
290 adapter->print(); |
295 adapter->print(); |
291 if (has_appendix) appendix()->print(); |
296 if (has_appendix) appendix()->print(); |
292 } |
297 } |
293 |
298 |
308 // not '(Ljava/lang/String;)Ljava/util/List;'. |
313 // not '(Ljava/lang/String;)Ljava/util/List;'. |
309 // The fact that String and List are involved is encoded in the MethodType in refs[f2]. |
314 // The fact that String and List are involved is encoded in the MethodType in refs[f2]. |
310 // This allows us to create fewer method oops, while keeping type safety. |
315 // This allows us to create fewer method oops, while keeping type safety. |
311 // |
316 // |
312 |
317 |
|
318 // Store appendix, if any. |
313 if (has_appendix) { |
319 if (has_appendix) { |
314 int ref_index = f2_as_index(); |
320 const int appendix_index = f2_as_index() + _indy_resolved_references_appendix_offset; |
315 assert(ref_index >= 0 && ref_index < resolved_references->length(), "oob"); |
321 assert(appendix_index >= 0 && appendix_index < resolved_references->length(), "oob"); |
316 assert(resolved_references->obj_at(ref_index) == NULL, "init just once"); |
322 assert(resolved_references->obj_at(appendix_index) == NULL, "init just once"); |
317 resolved_references->obj_at_put(ref_index, appendix()); |
323 resolved_references->obj_at_put(appendix_index, appendix()); |
|
324 } |
|
325 |
|
326 // Store MethodType, if any. |
|
327 if (has_method_type) { |
|
328 const int method_type_index = f2_as_index() + _indy_resolved_references_method_type_offset; |
|
329 assert(method_type_index >= 0 && method_type_index < resolved_references->length(), "oob"); |
|
330 assert(resolved_references->obj_at(method_type_index) == NULL, "init just once"); |
|
331 resolved_references->obj_at_put(method_type_index, method_type()); |
318 } |
332 } |
319 |
333 |
320 release_set_f1(adapter()); // This must be the last one to set (see NOTE above)! |
334 release_set_f1(adapter()); // This must be the last one to set (see NOTE above)! |
321 |
335 |
322 // The interpreter assembly code does not check byte_2, |
336 // The interpreter assembly code does not check byte_2, |
323 // but it is used by is_resolved, method_if_resolved, etc. |
337 // but it is used by is_resolved, method_if_resolved, etc. |
324 set_bytecode_1(invoke_code); |
338 set_bytecode_1(invoke_code); |
325 NOT_PRODUCT(verify(tty)); |
339 NOT_PRODUCT(verify(tty)); |
326 if (TraceInvokeDynamic) { |
340 if (TraceInvokeDynamic) { |
327 this->print(tty, 0); |
341 this->print(tty, 0); |
328 } |
342 } |
374 |
388 |
375 |
389 |
376 oop ConstantPoolCacheEntry::appendix_if_resolved(constantPoolHandle cpool) { |
390 oop ConstantPoolCacheEntry::appendix_if_resolved(constantPoolHandle cpool) { |
377 if (is_f1_null() || !has_appendix()) |
391 if (is_f1_null() || !has_appendix()) |
378 return NULL; |
392 return NULL; |
379 int ref_index = f2_as_index(); |
393 const int ref_index = f2_as_index() + _indy_resolved_references_appendix_offset; |
|
394 objArrayOop resolved_references = cpool->resolved_references(); |
|
395 return resolved_references->obj_at(ref_index); |
|
396 } |
|
397 |
|
398 |
|
399 oop ConstantPoolCacheEntry::method_type_if_resolved(constantPoolHandle cpool) { |
|
400 if (is_f1_null() || !has_method_type()) |
|
401 return NULL; |
|
402 const int ref_index = f2_as_index() + _indy_resolved_references_method_type_offset; |
380 objArrayOop resolved_references = cpool->resolved_references(); |
403 objArrayOop resolved_references = cpool->resolved_references(); |
381 return resolved_references->obj_at(ref_index); |
404 return resolved_references->obj_at(ref_index); |
382 } |
405 } |
383 |
406 |
384 |
407 |
511 void ConstantPoolCache::initialize(intArray& inverse_index_map, intArray& invokedynamic_references_map) { |
534 void ConstantPoolCache::initialize(intArray& inverse_index_map, intArray& invokedynamic_references_map) { |
512 assert(inverse_index_map.length() == length(), "inverse index map must have same length as cache"); |
535 assert(inverse_index_map.length() == length(), "inverse index map must have same length as cache"); |
513 for (int i = 0; i < length(); i++) { |
536 for (int i = 0; i < length(); i++) { |
514 ConstantPoolCacheEntry* e = entry_at(i); |
537 ConstantPoolCacheEntry* e = entry_at(i); |
515 int original_index = inverse_index_map[i]; |
538 int original_index = inverse_index_map[i]; |
516 e->initialize_entry(original_index); |
539 e->initialize_entry(original_index); |
517 assert(entry_at(i) == e, "sanity"); |
540 assert(entry_at(i) == e, "sanity"); |
518 } |
541 } |
519 for (int ref = 0; ref < invokedynamic_references_map.length(); ref++) { |
542 for (int ref = 0; ref < invokedynamic_references_map.length(); ref++) { |
520 int cpci = invokedynamic_references_map[ref]; |
543 const int cpci = invokedynamic_references_map[ref]; |
521 if (cpci >= 0) |
544 if (cpci >= 0) { |
|
545 #ifdef ASSERT |
|
546 // invokedynamic and invokehandle have more entries; check if they |
|
547 // all point to the same constant pool cache entry. |
|
548 for (int entry = 1; entry < ConstantPoolCacheEntry::_indy_resolved_references_entries; entry++) { |
|
549 const int cpci_next = invokedynamic_references_map[ref + entry]; |
|
550 assert(cpci == cpci_next, err_msg_res("%d == %d", cpci, cpci_next)); |
|
551 } |
|
552 #endif |
522 entry_at(cpci)->initialize_resolved_reference_index(ref); |
553 entry_at(cpci)->initialize_resolved_reference_index(ref); |
|
554 ref += ConstantPoolCacheEntry::_indy_resolved_references_entries - 1; // skip extra entries |
|
555 } |
523 } |
556 } |
524 } |
557 } |
525 |
558 |
526 // RedefineClasses() API support: |
559 // RedefineClasses() API support: |
527 // If any entry of this constantPoolCache points to any of |
560 // If any entry of this constantPoolCache points to any of |