void ConstantPoolCacheEntry::set_interface_call(methodHandle method, int index) { klassOop interf = method->method_holder(); assert(instanceKlass::cast(interf)->is_interface(), "must be an interface"); set_f1(interf); set_f2(index); set_flags(as_flags(as_TosState(method->result_type()), method->is_final_method(), false, false, false, true) | method()->size_of_parameters()); set_bytecode_1(Bytecodes::_invokeinterface); }
void ConstantPoolCacheEntry::set_interface_call(methodHandle method, int index) { assert(!is_secondary_entry(), ""); klassOop interf = method->method_holder(); assert(instanceKlass::cast(interf)->is_interface(), "must be an interface"); assert(!method->is_final_method(), "interfaces do not have final methods; cannot link to one here"); set_f1(interf); set_f2(index); set_method_flags(as_TosState(method->result_type()), 0, // no option bits method()->size_of_parameters()); set_bytecode_1(Bytecodes::_invokeinterface); }
uint64_t fingerprint() { // See if we fingerprinted this method already if (mh->constMethod()->fingerprint() != CONST64(0)) { return mh->constMethod()->fingerprint(); } if (mh->size_of_parameters() > max_size_of_parameters ) { _fingerprint = UCONST64(-1); mh->constMethod()->set_fingerprint(_fingerprint); return _fingerprint; } assert( (int)mh->result_type() <= (int)result_feature_mask, "bad result type"); _fingerprint = mh->result_type(); _fingerprint <<= static_feature_size; if (mh->is_static()) _fingerprint |= 1; _shift_count = result_feature_size + static_feature_size; iterate_parameters(); _fingerprint |= ((uint64_t)done_parm) << _shift_count;// mark end of sig mh->constMethod()->set_fingerprint(_fingerprint); return _fingerprint; }
void ConstantPoolCacheEntry::set_itable_call(Bytecodes::Code invoke_code, methodHandle method, int index) { assert(method->method_holder()->verify_itable_index(index), ""); assert(invoke_code == Bytecodes::_invokeinterface, ""); InstanceKlass* interf = method->method_holder(); assert(interf->is_interface(), "must be an interface"); assert(!method->is_final_method(), "interfaces do not have final methods; cannot link to one here"); set_f1(interf); set_f2(index); set_method_flags(as_TosState(method->result_type()), 0, // no option bits method()->size_of_parameters()); set_bytecode_1(Bytecodes::_invokeinterface); }
void ConstantPoolCacheEntry::set_method(Bytecodes::Code invoke_code, methodHandle method, int vtable_index) { assert(method->interpreter_entry() != NULL, "should have been set at this point"); assert(!method->is_old_version(), "attempt to write old method to cpCache"); bool change_to_virtual = (invoke_code == Bytecodes::_invokeinterface); int byte_no = -1; bool needs_vfinal_flag = false; switch (invoke_code) { case Bytecodes::_invokevirtual: case Bytecodes::_invokeinterface: { if (Klass::can_be_statically_bound(method())) { set_f2((intptr_t)method()); needs_vfinal_flag = true; } else { set_f2(vtable_index); } byte_no = 2; break; } case Bytecodes::_invokespecial: // Preserve the value of the vfinal flag on invokevirtual bytecode // which may be shared with this constant pool cache entry. needs_vfinal_flag = is_resolved(Bytecodes::_invokevirtual) && is_vfinal(); // fall through case Bytecodes::_invokestatic: set_f1(method()); byte_no = 1; break; default: ShouldNotReachHere(); break; } set_flags(as_flags(as_TosState(method->result_type()), method->is_final_method(), needs_vfinal_flag, false, change_to_virtual, true)| method()->size_of_parameters()); // Note: byte_no also appears in TemplateTable::resolve. if (byte_no == 1) { set_bytecode_1(invoke_code); } else if (byte_no == 2) { if (change_to_virtual) { // NOTE: THIS IS A HACK - BE VERY CAREFUL!!! // // Workaround for the case where we encounter an invokeinterface, but we // should really have an _invokevirtual since the resolved method is a // virtual method in java.lang.Object. This is a corner case in the spec // but is presumably legal. javac does not generate this code. // // We set bytecode_1() to _invokeinterface, because that is the // bytecode # used by the interpreter to see if it is resolved. // We set bytecode_2() to _invokevirtual. // See also interpreterRuntime.cpp. (8/25/2000) set_bytecode_1(invoke_code); set_bytecode_2(Bytecodes::_invokevirtual); } else { set_bytecode_2(invoke_code); } } else { ShouldNotReachHere(); } verify(tty); }
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_direct_or_vtable_call(Bytecodes::Code invoke_code, methodHandle method, int vtable_index) { bool is_vtable_call = (vtable_index >= 0); // FIXME: split this method on this boolean assert(method->interpreter_entry() != NULL, "should have been set at this point"); assert(!method->is_obsolete(), "attempt to write obsolete method to cpCache"); int byte_no = -1; bool change_to_virtual = false; switch (invoke_code) { case Bytecodes::_invokeinterface: // We get here from InterpreterRuntime::resolve_invoke when an invokeinterface // instruction somehow links to a non-interface method (in Object). // In that case, the method has no itable index and must be invoked as a virtual. // Set a flag to keep track of this corner case. change_to_virtual = true; // ...and fall through as if we were handling invokevirtual: case Bytecodes::_invokevirtual: { if (!is_vtable_call) { assert(method->can_be_statically_bound(), ""); // set_f2_as_vfinal_method checks if is_vfinal flag is true. set_method_flags(as_TosState(method->result_type()), ( 1 << is_vfinal_shift) | ((method->is_final_method() ? 1 : 0) << is_final_shift) | ((change_to_virtual ? 1 : 0) << is_forced_virtual_shift), method()->size_of_parameters()); set_f2_as_vfinal_method(method()); } else { assert(!method->can_be_statically_bound(), ""); assert(vtable_index >= 0, "valid index"); assert(!method->is_final_method(), "sanity"); set_method_flags(as_TosState(method->result_type()), ((change_to_virtual ? 1 : 0) << is_forced_virtual_shift), method()->size_of_parameters()); set_f2(vtable_index); } byte_no = 2; break; } case Bytecodes::_invokespecial: case Bytecodes::_invokestatic: assert(!is_vtable_call, ""); // Note: Read and preserve the value of the is_vfinal flag on any // invokevirtual bytecode shared with this constant pool cache entry. // It is cheap and safe to consult is_vfinal() at all times. // Once is_vfinal is set, it must stay that way, lest we get a dangling oop. set_method_flags(as_TosState(method->result_type()), ((is_vfinal() ? 1 : 0) << is_vfinal_shift) | ((method->is_final_method() ? 1 : 0) << is_final_shift), method()->size_of_parameters()); set_f1(method()); byte_no = 1; break; default: ShouldNotReachHere(); break; } // Note: byte_no also appears in TemplateTable::resolve. if (byte_no == 1) { assert(invoke_code != Bytecodes::_invokevirtual && invoke_code != Bytecodes::_invokeinterface, ""); set_bytecode_1(invoke_code); } else if (byte_no == 2) { if (change_to_virtual) { assert(invoke_code == Bytecodes::_invokeinterface, ""); // NOTE: THIS IS A HACK - BE VERY CAREFUL!!! // // Workaround for the case where we encounter an invokeinterface, but we // should really have an _invokevirtual since the resolved method is a // virtual method in java.lang.Object. This is a corner case in the spec // but is presumably legal. javac does not generate this code. // // We set bytecode_1() to _invokeinterface, because that is the // bytecode # used by the interpreter to see if it is resolved. // We set bytecode_2() to _invokevirtual. // See also interpreterRuntime.cpp. (8/25/2000) // Only set resolved for the invokeinterface case if method is public. // Otherwise, the method needs to be reresolved with caller for each // interface call. if (method->is_public()) set_bytecode_1(invoke_code); } else { assert(invoke_code == Bytecodes::_invokevirtual, ""); } // set up for invokevirtual, even if linking for invokeinterface also: set_bytecode_2(Bytecodes::_invokevirtual); } else { ShouldNotReachHere(); } NOT_PRODUCT(verify(tty)); }
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); } }