// Adjust the invocation bytecode for a signature-polymorphic method (MethodHandle.invoke, etc.) void Rewriter::maybe_rewrite_invokehandle(address opc, int cp_index, bool reverse) { if (!reverse) { if ((*opc) == (u1)Bytecodes::_invokevirtual || // allow invokespecial as an alias, although it would be very odd: (*opc) == (u1)Bytecodes::_invokespecial) { assert(_pool->tag_at(cp_index).is_method(), "wrong index"); // Determine whether this is a signature-polymorphic method. if (cp_index >= _method_handle_invokers.length()) return; int status = _method_handle_invokers[cp_index]; assert(status >= -1 && status <= 1, "oob tri-state"); if (status == 0) { if (_pool->klass_ref_at_noresolve(cp_index) == vmSymbols::java_lang_invoke_MethodHandle() && MethodHandles::is_signature_polymorphic_name(SystemDictionary::MethodHandle_klass(), _pool->name_ref_at(cp_index))) { assert(has_cp_cache(cp_index), "should already have an entry"); int cpc = maybe_add_cp_cache_entry(cp_index); // should already have an entry int cpc2 = add_secondary_cp_cache_entry(cpc); status = +1; } else { status = -1; } _method_handle_invokers[cp_index] = status; } // We use a special internal bytecode for such methods (if non-static). // The basic reason for this is that such methods need an extra "appendix" argument // to transmit the call site's intended call type. if (status > 0) { (*opc) = (u1)Bytecodes::_invokehandle; } } } else { // Do not need to look at cp_index. if ((*opc) == (u1)Bytecodes::_invokehandle) { (*opc) = (u1)Bytecodes::_invokevirtual; // Ignore corner case of original _invokespecial instruction. // This is safe because (a) the signature polymorphic method was final, and // (b) the implementation of MethodHandle will not call invokespecial on it. } } }
int cp_entry_to_cp_cache(int i) { assert(has_cp_cache(i), "oob"); return _cp_map[i]; }
int maybe_add_cp_cache_entry(int i) { return has_cp_cache(i) ? _cp_map[i] : add_cp_cache_entry(i); }