void ConstantPoolCacheEntry::set_method_handle_common(constantPoolHandle cpool, Bytecodes::Code invoke_code, const CallInfo &call_info) { // NOTE: This CPCE can be the subject of data races. // There are three words to update: flags, refs[f2], f1 (in that order). // Writers must store all other values before f1. // Readers must test f1 first for non-null before reading other fields. // Competing writers must acquire exclusive access via a lock. // A losing writer waits on the lock until the winner writes f1 and leaves // the lock, so that when the losing writer returns, he can use the linked // cache entry. MonitorLockerEx ml(cpool->lock()); if (!is_f1_null()) { return; } const methodHandle adapter = call_info.resolved_method(); const Handle appendix = call_info.resolved_appendix(); const Handle method_type = call_info.resolved_method_type(); const bool has_appendix = appendix.not_null(); const bool has_method_type = method_type.not_null(); // Write the flags. set_method_flags(as_TosState(adapter->result_type()), ((has_appendix ? 1 : 0) << has_appendix_shift ) | ((has_method_type ? 1 : 0) << has_method_type_shift) | ( 1 << is_final_shift ), adapter->size_of_parameters()); if (TraceInvokeDynamic) { tty->print_cr("set_method_handle bc=%d appendix="PTR_FORMAT"%s method_type="PTR_FORMAT"%s method="PTR_FORMAT" ", invoke_code, (void *)appendix(), (has_appendix ? "" : " (unused)"), (void *)method_type(), (has_method_type ? "" : " (unused)"), (intptr_t)adapter()); adapter->print(); if (has_appendix) appendix()->print(); } // Method handle invokes and invokedynamic sites use both cp cache words. // refs[f2], if not null, contains a value passed as a trailing argument to the adapter. // In the general case, this could be the call site's MethodType, // for use with java.lang.Invokers.checkExactType, or else a CallSite object. // f1 contains the adapter method which manages the actual call. // In the general case, this is a compiled LambdaForm. // (The Java code is free to optimize these calls by binding other // sorts of methods and appendices to call sites.) // JVM-level linking is via f1, as if for invokespecial, and signatures are erased. // The appendix argument (if any) is added to the signature, and is counted in the parameter_size bits. // Even with the appendix, the method will never take more than 255 parameter slots. // // This means that given a call site like (List)mh.invoke("foo"), // the f1 method has signature '(Ljl/Object;Ljl/invoke/MethodType;)Ljl/Object;', // not '(Ljava/lang/String;)Ljava/util/List;'. // The fact that String and List are involved is encoded in the MethodType in refs[f2]. // This allows us to create fewer method oops, while keeping type safety. // objArrayHandle resolved_references = cpool->resolved_references(); // Store appendix, if any. if (has_appendix) { const int appendix_index = f2_as_index() + _indy_resolved_references_appendix_offset; assert(appendix_index >= 0 && appendix_index < resolved_references->length(), "oob"); assert(resolved_references->obj_at(appendix_index) == NULL, "init just once"); resolved_references->obj_at_put(appendix_index, appendix()); } // Store MethodType, if any. if (has_method_type) { const int method_type_index = f2_as_index() + _indy_resolved_references_method_type_offset; assert(method_type_index >= 0 && method_type_index < resolved_references->length(), "oob"); assert(resolved_references->obj_at(method_type_index) == NULL, "init just once"); resolved_references->obj_at_put(method_type_index, method_type()); } release_set_f1(adapter()); // This must be the last one to set (see NOTE above)! // The interpreter assembly code does not check byte_2, // but it is used by is_resolved, method_if_resolved, etc. set_bytecode_1(invoke_code); NOT_PRODUCT(verify(tty)); if (TraceInvokeDynamic) { this->print(tty, 0); } }
void ConstantPoolCacheEntry::set_method_handle_common(constantPoolHandle cpool, Bytecodes::Code invoke_code, methodHandle adapter, Handle appendix, Handle method_type) { // NOTE: This CPCE can be the subject of data races. // There are three words to update: flags, f2, f1 (in that order). // Writers must store all other values before f1. // Readers must test f1 first for non-null before reading other fields. // Competing writers must acquire exclusive access via a lock. // A losing writer waits on the lock until the winner writes f1 and leaves // the lock, so that when the losing writer returns, he can use the linked // cache entry. Thread* THREAD = Thread::current(); ObjectLocker ol(cpool, THREAD); if (!is_f1_null()) { return; } const bool has_appendix = appendix.not_null(); const bool has_method_type = method_type.not_null(); if (!has_appendix) { // The extra argument is not used, but we need a non-null value to signify linkage state. // Set it to something benign that will never leak memory. appendix = Universe::void_mirror(); } // Write the flags. set_method_flags(as_TosState(adapter->result_type()), ((has_appendix ? 1 : 0) << has_appendix_shift) | ((has_method_type ? 1 : 0) << has_method_type_shift) | ( 1 << is_vfinal_shift) | ( 1 << is_final_shift), adapter->size_of_parameters()); if (TraceInvokeDynamic) { tty->print_cr("set_method_handle bc=%d appendix="PTR_FORMAT"%s method_type="PTR_FORMAT"%s method="PTR_FORMAT" ", invoke_code, (intptr_t)appendix(), (has_appendix ? "" : " (unused)"), (intptr_t)method_type(), (has_method_type ? "" : " (unused)"), (intptr_t)adapter()); adapter->print(); if (has_appendix) appendix()->print(); } // Method handle invokes and invokedynamic sites use both cp cache words. // f1, if not null, contains a value passed as a trailing argument to the adapter. // In the general case, this could be the call site's MethodType, // for use with java.lang.Invokers.checkExactType, or else a CallSite object. // f2 contains the adapter method which manages the actual call. // In the general case, this is a compiled LambdaForm. // (The Java code is free to optimize these calls by binding other // sorts of methods and appendices to call sites.) // JVM-level linking is via f2, as if for invokevfinal, and signatures are erased. // The appendix argument (if any) is added to the signature, and is counted in the parameter_size bits. // In principle this means that the method (with appendix) could take up to 256 parameter slots. // // This means that given a call site like (List)mh.invoke("foo"), // the f2 method has signature '(Ljl/Object;Ljl/invoke/MethodType;)Ljl/Object;', // not '(Ljava/lang/String;)Ljava/util/List;'. // The fact that String and List are involved is encoded in the MethodType in f1. // This allows us to create fewer method oops, while keeping type safety. // set_f2_as_vfinal_method(adapter()); // Store MethodType, if any. if (has_method_type) { ConstantPoolCacheEntry* e2 = cpool->cache()->find_secondary_entry_for(this); // Write the flags. e2->set_method_flags(as_TosState(adapter->result_type()), ((has_method_type ? 1 : 0) << has_method_type_shift) | ( 1 << is_vfinal_shift) | ( 1 << is_final_shift), adapter->size_of_parameters()); e2->release_set_f1(method_type()); } assert(appendix.not_null(), "needed for linkage state"); release_set_f1(appendix()); // This must be the last one to set (see NOTE above)! if (!is_secondary_entry()) { // The interpreter assembly code does not check byte_2, // but it is used by is_resolved, method_if_resolved, etc. set_bytecode_2(invoke_code); } NOT_PRODUCT(verify(tty)); if (TraceInvokeDynamic) { this->print(tty, 0); } }