/** * Gets the method bridged to by a {@linkplain ResolvedJavaMethod#isBridge() bridge} method. The * value returned is the method called by {@code method} that has the same name as {@code bridge}. * * @param bridge a bridge method * @return the method called by {@code bridge} whose name is the same as {@code bridge.getName()} */ public static ResolvedJavaMethod getBridgedMethod(ResolvedJavaMethod bridge) { assert bridge.isBridge(); Bytecode code = new ResolvedJavaMethodBytecode(bridge); BytecodeStream stream = new BytecodeStream(code.getCode()); int opcode = stream.currentBC(); ResolvedJavaMethod bridged = null; while (opcode != Bytecodes.END) { switch (opcode) { case INVOKEVIRTUAL: case INVOKESPECIAL: case INVOKESTATIC: case INVOKEINTERFACE: { int cpi = stream.readCPI(); ConstantPool cp = code.getConstantPool(); cp.loadReferencedType(cpi, opcode); ResolvedJavaMethod method = (ResolvedJavaMethod) cp.lookupMethod(cpi, opcode); if (method.getName().equals(bridge.getName())) { if (!assertionsEnabled()) { return method; } assert bridged == null || bridged.equals(method) : String.format( "Found calls to different methods named %s in bridge method %s%n callee 1: %s%n callee 2: %s", bridge.getName(), bridge.format("%R %H.%n(%P)"), bridged.format("%R %H.%n(%P)"), method.format("%R %H.%n(%P)")); bridged = method; } break; } } stream.next(); opcode = stream.currentBC(); } if (bridged == null) { throw new InternalError("Couldn't find method bridged by " + bridge.format("%R %H.%n(%P)")); } return bridged; }
@Override public void lower(LoweringTool tool) { StructuredGraph replacementGraph = getLoweredSnippetGraph(tool); InvokeNode invoke = replaceWithInvoke(); assert invoke.verify(); if (replacementGraph != null) { // Pull out the receiver null check so that a replaced // receiver can be lowered if necessary if (!targetMethod.isStatic()) { ValueNode nonNullReceiver = InliningUtil.nonNullReceiver(invoke); if (nonNullReceiver instanceof Lowerable) { ((Lowerable) nonNullReceiver).lower(tool); } } InliningUtil.inline(invoke, replacementGraph, false, null); Debug.dump(Debug.INFO_LOG_LEVEL, graph(), "After inlining replacement %s", replacementGraph); } else { if (isPlaceholderBci(invoke.bci())) { throw new GraalError("%s: cannot lower to invoke with placeholder BCI: %s", graph(), this); } if (invoke.stateAfter() == null) { ResolvedJavaMethod method = graph().method(); if (method.getAnnotation(MethodSubstitution.class) != null || method.getAnnotation(Snippet.class) != null) { // One cause for this is that a MacroNode is created for a method that // no longer needs a MacroNode. For example, Class.getComponentType() // only needs a MacroNode prior to JDK9 as it was given a non-native // implementation in JDK9. throw new GraalError( "%s macro created for call to %s in %s must be lowerable to a snippet or intrinsic graph. " + "Maybe a macro node is not needed for this method in the current JDK?", getClass().getSimpleName(), targetMethod.format("%h.%n(%p)"), graph()); } throw new GraalError("%s: cannot lower to invoke without state: %s", graph(), this); } invoke.lower(tool); } }