OpenJDK / graal / graal-jvmci-8
changeset 7360:12bd634440d0
support substitution of methods that are not in the bootstrap class path and/or whose signature contains non-accessible types
author | Doug Simon <doug.simon@oracle.com> |
---|---|
date | Sun, 13 Jan 2013 21:17:13 +0100 |
parents | 6a16788a29a6 |
children | b79ad92d5a26 |
files | graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetInstaller.java |
diffstat | 1 files changed, 88 insertions(+), 51 deletions(-) [+] |
line wrap: on
line diff
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetInstaller.java Sun Jan 13 21:14:40 2013 +0100 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetInstaller.java Sun Jan 13 21:17:13 2013 +0100 @@ -22,10 +22,14 @@ */ package com.oracle.graal.snippets; +import static com.oracle.graal.api.meta.MetaUtil.*; + import java.lang.reflect.*; import java.util.*; import java.util.concurrent.*; +import sun.misc.*; + import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.debug.*; @@ -56,7 +60,7 @@ /** * A graph cache used by this installer to avoid using the compiler * storage for each method processed during snippet installation. - * Without this, all processed methods are determined to be + * Without this, all processed methods are to be determined as * {@linkplain InliningUtil#canIntrinsify intrinsifiable}. */ private final Map<ResolvedJavaMethod, StructuredGraph> graphCache; @@ -69,21 +73,6 @@ this.graphCache = new HashMap<>(); } - private static Class<?> getOriginalClass(ClassSubstitution classSubs) throws GraalInternalError { - Class<?> originalClass = classSubs.value(); - if (originalClass == ClassSubstitution.class) { - assert !classSubs.className().isEmpty(); - try { - originalClass = Class.forName(classSubs.className()); - } catch (ClassNotFoundException e) { - throw new GraalInternalError("Could not resolve substituted class " + classSubs.className(), e); - } - } else { - assert classSubs.className().isEmpty(); - } - return originalClass; - } - /** * Finds all the snippet methods in a given class, builds a graph for them and * installs the graph with the key value of {@code Graph.class} in the @@ -112,42 +101,29 @@ * {@linkplain ResolvedJavaMethod#getCompilerStorage() compiler storage} of each original method. */ public void installSubstitutions(Class<?> substitutions) { - ClassSubstitution classSubs = substitutions.getAnnotation(ClassSubstitution.class); - Class< ? > originalClass = getOriginalClass(classSubs); - for (Method method : substitutions.getDeclaredMethods()) { - MethodSubstitution methodSubstitution = method.getAnnotation(MethodSubstitution.class); + ClassSubstitution classSubstitution = substitutions.getAnnotation(ClassSubstitution.class); + for (Method substituteMethod : substitutions.getDeclaredMethods()) { + MethodSubstitution methodSubstitution = substituteMethod.getAnnotation(MethodSubstitution.class); if (methodSubstitution == null) { continue; } - try { - String originalName = method.getName(); - Class<?>[] originalParameters = method.getParameterTypes(); - if (!methodSubstitution.value().isEmpty()) { - originalName = methodSubstitution.value(); - } - if (!methodSubstitution.isStatic()) { - assert originalParameters.length >= 1 : "must be a static method with the this object as its first parameter"; - Class<?>[] newParameters = new Class<?>[originalParameters.length - 1]; - System.arraycopy(originalParameters, 1, newParameters, 0, newParameters.length); - originalParameters = newParameters; - } - Method originalMethod = originalClass.getDeclaredMethod(originalName, originalParameters); - if (!originalMethod.getReturnType().isAssignableFrom(method.getReturnType())) { - throw new RuntimeException("Snippet has incompatible return type: " + method); - } - int modifiers = method.getModifiers(); - if (!Modifier.isStatic(modifiers)) { - throw new RuntimeException("Snippets must be static methods: " + method); - } else if (Modifier.isAbstract(modifiers) || Modifier.isNative(modifiers)) { - throw new RuntimeException("Snippet must not be abstract or native: " + method); - } - ResolvedJavaMethod snippet = runtime.lookupJavaMethod(method); - StructuredGraph graph = makeGraph(snippet, inliningPolicy(snippet), true); - //System.out.println("snippet: " + graph); - runtime.lookupJavaMethod(originalMethod).getCompilerStorage().put(Graph.class, graph); - } catch (NoSuchMethodException e) { - throw new GraalInternalError("Could not resolve method in " + originalClass + " to substitute with " + method, e); + + int modifiers = substituteMethod.getModifiers(); + if (!Modifier.isStatic(modifiers)) { + throw new RuntimeException("Substitution methods must be static: " + substituteMethod); + } else if (Modifier.isAbstract(modifiers) || Modifier.isNative(modifiers)) { + throw new RuntimeException("Substitution method must not be abstract or native: " + substituteMethod); } + + String originalName = originalName(substituteMethod, methodSubstitution); + Class[] originalParameters = originalParameters(substituteMethod, methodSubstitution); + ResolvedJavaMethod substitute = runtime.lookupJavaMethod(substituteMethod); + Method originalMethod = originalMethod(classSubstitution, originalName, originalParameters); + ResolvedJavaMethod substituted = runtime.lookupJavaMethod(originalMethod); + //System.out.println("substitution: " + MetaUtil.format("%H.%n(%p)", substituted) + " --> " + MetaUtil.format("%H.%n(%p)", substitute)); + StructuredGraph graph = makeGraph(substitute, inliningPolicy(substitute), true); + Object oldValue = substituted.getCompilerStorage().put(Graph.class, graph); + assert oldValue == null; } } @@ -167,7 +143,7 @@ } } - public StructuredGraph makeGraph(final ResolvedJavaMethod method, final SnippetInliningPolicy policy, final boolean isSubstitutionSnippet) { + public StructuredGraph makeGraph(final ResolvedJavaMethod method, final SnippetInliningPolicy policy, final boolean isSubstitution) { return Debug.scope("BuildSnippetGraph", new Object[] {method}, new Callable<StructuredGraph>() { @Override public StructuredGraph call() throws Exception { @@ -175,8 +151,8 @@ new SnippetIntrinsificationPhase(runtime, pool, SnippetTemplate.hasConstantParameter(method)).apply(graph); - if (isSubstitutionSnippet) { - // TODO (ds) remove the constraint of only processing substitution snippets + if (isSubstitution) { + // TODO (ds) remove the constraint of only processing substitutions // once issues with the arraycopy snippets have been resolved new SnippetFrameStateCleanupPhase().apply(graph); new DeadCodeEliminationPhase().apply(graph); @@ -247,4 +223,65 @@ } return graph; } + + private static String originalName(Method substituteMethod, MethodSubstitution methodSubstitution) { + String name = substituteMethod.getName(); + if (!methodSubstitution.value().isEmpty()) { + name = methodSubstitution.value(); + } + return name; + } + + private static Class resolveType(String className) { + try { + // Need to use launcher class path to handle classes + // that are not on the boot class path + ClassLoader cl = Launcher.getLauncher().getClassLoader(); + return Class.forName(className, false, cl); + } catch (ClassNotFoundException e) { + throw new GraalInternalError("Could not resolve type " + className); + } + } + + private static Class resolveType(JavaType type) { + JavaType base = type; + int dimensions = 0; + while (base.getComponentType() != null) { + base = base.getComponentType(); + dimensions++; + } + + Class baseClass = base.getKind() != Kind.Object ? base.getKind().toJavaClass() : resolveType(toJavaName(base)); + return dimensions == 0 ? baseClass : Array.newInstance(baseClass, new int[dimensions]).getClass(); + } + + private Class[] originalParameters(Method substituteMethod, MethodSubstitution methodSubstitution) { + Class[] parameters; + if (methodSubstitution.signature().isEmpty()) { + parameters = substituteMethod.getParameterTypes(); + if (!methodSubstitution.isStatic()) { + assert parameters.length > 0 : "must be a static method with the 'this' object as its first parameter"; + parameters = Arrays.copyOfRange(parameters, 1, parameters.length); + } + } else { + Signature signature = runtime.parseMethodDescriptor(methodSubstitution.signature()); + parameters = new Class[signature.getParameterCount(false)]; + for (int i = 0; i < parameters.length; i++) { + parameters[i] = resolveType(signature.getParameterType(i, null)); + } + } + return parameters; + } + + private static Method originalMethod(ClassSubstitution classSubstitution, String name, Class[] parameters) { + Class<?> originalClass = classSubstitution.value(); + if (originalClass == ClassSubstitution.class) { + originalClass = resolveType(classSubstitution.className()); + } + try { + return originalClass.getDeclaredMethod(name, parameters); + } catch (NoSuchMethodException | SecurityException e) { + throw new GraalInternalError(e); + } + } }