changeset 8915:880619fd6a67

allow MethodSubstitutions and MacroSubstitutions to be forced (instead of depending on inlining)
author Lukas Stadler <lukas.stadler@jku.at>
date Mon, 08 Apr 2013 19:00:22 +0200
parents 7828409c364c
children 1ee23d592f7d
files graal/com.oracle.graal.api.replacements/src/com/oracle/graal/api/replacements/MacroSubstitution.java graal/com.oracle.graal.api.replacements/src/com/oracle/graal/api/replacements/MethodSubstitution.java graal/com.oracle.graal.api.replacements/src/com/oracle/graal/api/replacements/Replacements.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotReplacementsImpl.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/BoxingSubstitutions.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java
diffstat 7 files changed, 84 insertions(+), 27 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.api.replacements/src/com/oracle/graal/api/replacements/MacroSubstitution.java	Mon Apr 08 17:31:50 2013 +0200
+++ b/graal/com.oracle.graal.api.replacements/src/com/oracle/graal/api/replacements/MacroSubstitution.java	Mon Apr 08 19:00:22 2013 +0200
@@ -66,4 +66,10 @@
      * an {@link InvokeNode} as a parameter.
      */
     Class<? extends FixedWithNextNode> macro();
+
+    /**
+     * Determines if this method should be substituted in all cases, even if inlining thinks it is
+     * not important.
+     */
+    boolean isForcedInlining() default false;
 }
--- a/graal/com.oracle.graal.api.replacements/src/com/oracle/graal/api/replacements/MethodSubstitution.java	Mon Apr 08 17:31:50 2013 +0200
+++ b/graal/com.oracle.graal.api.replacements/src/com/oracle/graal/api/replacements/MethodSubstitution.java	Mon Apr 08 19:00:22 2013 +0200
@@ -54,4 +54,10 @@
      * is the same as the substitute method.
      */
     String signature() default "";
+
+    /**
+     * Determines if this method should be substituted in all cases, even if inlining thinks it is
+     * not important.
+     */
+    boolean isForcedInlining() default false;
 }
--- a/graal/com.oracle.graal.api.replacements/src/com/oracle/graal/api/replacements/Replacements.java	Mon Apr 08 17:31:50 2013 +0200
+++ b/graal/com.oracle.graal.api.replacements/src/com/oracle/graal/api/replacements/Replacements.java	Mon Apr 08 19:00:22 2013 +0200
@@ -77,4 +77,9 @@
      * snippet.
      */
     Collection<ResolvedJavaMethod> getAllReplacements();
+
+    /**
+     * Determines whether the replacement of this method is flagged as being inlined always.
+     */
+    boolean isForcedSubstitution(ResolvedJavaMethod methodAt);
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotReplacementsImpl.java	Mon Apr 08 17:31:50 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotReplacementsImpl.java	Mon Apr 08 19:00:22 2013 +0200
@@ -25,12 +25,14 @@
 import java.lang.reflect.*;
 
 import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.replacements.*;
 import com.oracle.graal.replacements.*;
 
 /**
- * Filters certain method substitutions based on whether there is underlying hardware support for them.
+ * Filters certain method substitutions based on whether there is underlying hardware support for
+ * them.
  */
 public class HotSpotReplacementsImpl extends ReplacementsImpl {
 
@@ -42,22 +44,22 @@
     }
 
     @Override
-    protected void registerMethodSubstitution(Member originalMethod, Method substituteMethod) {
+    protected ResolvedJavaMethod registerMethodSubstitution(Member originalMethod, Method substituteMethod) {
         if (substituteMethod.getDeclaringClass() == IntegerSubstitutions.class || substituteMethod.getDeclaringClass() == LongSubstitutions.class) {
             if (substituteMethod.getName().equals("bitCount")) {
                 if (!config.usePopCountInstruction) {
-                    return;
+                    return null;
                 }
             }
         } else if (substituteMethod.getDeclaringClass() == AESCryptSubstitutions.class || substituteMethod.getDeclaringClass() == CipherBlockChainingSubstitutions.class) {
             if (!config.useAESIntrinsics) {
-                return;
+                return null;
             }
             assert config.aescryptEncryptBlockStub != 0L;
             assert config.aescryptDecryptBlockStub != 0L;
             assert config.cipherBlockChainingEncryptAESCryptStub != 0L;
             assert config.cipherBlockChainingDecryptAESCryptStub != 0L;
         }
-        super.registerMethodSubstitution(originalMethod, substituteMethod);
+        return super.registerMethodSubstitution(originalMethod, substituteMethod);
     }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/BoxingSubstitutions.java	Mon Apr 08 17:31:50 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/BoxingSubstitutions.java	Mon Apr 08 19:00:22 2013 +0200
@@ -31,12 +31,12 @@
     @ClassSubstitution(Boolean.class)
     private static class BooleanSubstitutions {
 
-        @MethodSubstitution
+        @MethodSubstitution(isForcedInlining = true)
         public static Boolean valueOf(boolean value) {
             return BoxNode.box(value, Boolean.class, Kind.Boolean);
         }
 
-        @MethodSubstitution(isStatic = false)
+        @MethodSubstitution(isStatic = false, isForcedInlining = true)
         public static boolean booleanValue(Boolean value) {
             return UnboxNode.unbox(value, Kind.Boolean);
         }
@@ -45,12 +45,12 @@
     @ClassSubstitution(Byte.class)
     private static class ByteSubstitutions {
 
-        @MethodSubstitution
+        @MethodSubstitution(isForcedInlining = true)
         public static Byte valueOf(byte value) {
             return BoxNode.box(value, Byte.class, Kind.Byte);
         }
 
-        @MethodSubstitution(isStatic = false)
+        @MethodSubstitution(isStatic = false, isForcedInlining = true)
         public static byte byteValue(Byte value) {
             return UnboxNode.unbox(value, Kind.Byte);
         }
@@ -59,12 +59,12 @@
     @ClassSubstitution(Character.class)
     private static class CharacterSubstitutions {
 
-        @MethodSubstitution
+        @MethodSubstitution(isForcedInlining = true)
         public static Character valueOf(char value) {
             return BoxNode.box(value, Character.class, Kind.Char);
         }
 
-        @MethodSubstitution(isStatic = false)
+        @MethodSubstitution(isStatic = false, isForcedInlining = true)
         public static char charValue(Character value) {
             return UnboxNode.unbox(value, Kind.Char);
         }
@@ -73,12 +73,12 @@
     @ClassSubstitution(Double.class)
     private static class DoubleSubstitutions {
 
-        @MethodSubstitution
+        @MethodSubstitution(isForcedInlining = true)
         public static Double valueOf(double value) {
             return BoxNode.box(value, Double.class, Kind.Double);
         }
 
-        @MethodSubstitution(isStatic = false)
+        @MethodSubstitution(isStatic = false, isForcedInlining = true)
         public static double doubleValue(Double value) {
             return UnboxNode.unbox(value, Kind.Double);
         }
@@ -87,12 +87,12 @@
     @ClassSubstitution(Float.class)
     private static class FloatSubstitutions {
 
-        @MethodSubstitution
+        @MethodSubstitution(isForcedInlining = true)
         public static Float valueOf(float value) {
             return BoxNode.box(value, Float.class, Kind.Float);
         }
 
-        @MethodSubstitution(isStatic = false)
+        @MethodSubstitution(isStatic = false, isForcedInlining = true)
         public static float floatValue(Float value) {
             return UnboxNode.unbox(value, Kind.Float);
         }
@@ -101,12 +101,12 @@
     @ClassSubstitution(Integer.class)
     private static class IntegerSubstitutions {
 
-        @MethodSubstitution
+        @MethodSubstitution(isForcedInlining = true)
         public static Integer valueOf(int value) {
             return BoxNode.box(value, Integer.class, Kind.Int);
         }
 
-        @MethodSubstitution(isStatic = false)
+        @MethodSubstitution(isStatic = false, isForcedInlining = true)
         public static int intValue(Integer value) {
             return UnboxNode.unbox(value, Kind.Int);
         }
@@ -115,12 +115,12 @@
     @ClassSubstitution(Long.class)
     private static class LongSubstitutions {
 
-        @MethodSubstitution
+        @MethodSubstitution(isForcedInlining = true)
         public static Long valueOf(long value) {
             return BoxNode.box(value, Long.class, Kind.Long);
         }
 
-        @MethodSubstitution(isStatic = false)
+        @MethodSubstitution(isStatic = false, isForcedInlining = true)
         public static long longValue(Long value) {
             return UnboxNode.unbox(value, Kind.Long);
         }
@@ -129,12 +129,12 @@
     @ClassSubstitution(Short.class)
     private static class ShortSubstitutions {
 
-        @MethodSubstitution
+        @MethodSubstitution(isForcedInlining = true)
         public static Short valueOf(short value) {
             return BoxNode.box(value, Short.class, Kind.Short);
         }
 
-        @MethodSubstitution(isStatic = false)
+        @MethodSubstitution(isStatic = false, isForcedInlining = true)
         public static short shortValue(Short value) {
             return UnboxNode.unbox(value, Kind.Short);
         }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java	Mon Apr 08 17:31:50 2013 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java	Mon Apr 08 19:00:22 2013 +0200
@@ -28,6 +28,8 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.replacements.*;
+import com.oracle.graal.api.runtime.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
@@ -195,8 +197,14 @@
              * also getting queued in the compilation queue concurrently)
              */
 
-            if (GraalOptions.AlwaysInlineIntrinsics && onlyIntrinsics(info)) {
-                return InliningUtil.logInlinedMethod(info, "intrinsic");
+            if (GraalOptions.AlwaysInlineIntrinsics) {
+                if (onlyIntrinsics(info)) {
+                    return InliningUtil.logInlinedMethod(info, "intrinsic");
+                }
+            } else {
+                if (onlyForcedIntrinsics(info)) {
+                    return InliningUtil.logInlinedMethod(info, "intrinsic");
+                }
             }
 
             double bonus = 1;
@@ -342,6 +350,19 @@
             }
             return true;
         }
+
+        private static boolean onlyForcedIntrinsics(InlineInfo info) {
+            for (int i = 0; i < info.numberOfMethods(); i++) {
+                if (!InliningUtil.canIntrinsify(info.methodAt(i))) {
+                    return false;
+                }
+                Replacements replacements = Graal.getRequiredCapability(Replacements.class);
+                if (!replacements.isForcedSubstitution(info.methodAt(i))) {
+                    return false;
+                }
+            }
+            return true;
+        }
     }
 
     private static class CFInliningPolicy implements InliningPolicy {
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java	Mon Apr 08 17:31:50 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java	Mon Apr 08 19:00:22 2013 +0200
@@ -61,6 +61,7 @@
     private final Map<ResolvedJavaMethod, ResolvedJavaMethod> registeredMethodSubstitutions;
     private final Set<ResolvedJavaMethod> registeredSnippets;
     private final Map<ResolvedJavaMethod, Class<? extends FixedWithNextNode>> registerMacroSubstitutions;
+    private final Set<ResolvedJavaMethod> forcedSubstitutions;
 
     public ReplacementsImpl(MetaAccessProvider runtime, Assumptions assumptions, TargetDescription target) {
         this.runtime = runtime;
@@ -70,6 +71,7 @@
         this.registeredMethodSubstitutions = new HashMap<>();
         this.registeredSnippets = new HashSet<>();
         this.registerMacroSubstitutions = new HashMap<>();
+        this.forcedSubstitutions = new HashSet<>();
     }
 
     public void registerSnippets(Class<?> snippets) {
@@ -145,7 +147,10 @@
                 Class[] originalParameters = originalParameters(substituteMethod, methodSubstitution.signature(), methodSubstitution.isStatic());
                 Member originalMethod = originalMethod(classSubstitution, originalName, originalParameters);
                 if (originalMethod != null) {
-                    registerMethodSubstitution(originalMethod, substituteMethod);
+                    ResolvedJavaMethod original = registerMethodSubstitution(originalMethod, substituteMethod);
+                    if (original != null && methodSubstitution.isForcedInlining()) {
+                        forcedSubstitutions.add(original);
+                    }
                 }
             }
             if (macroSubstitution != null) {
@@ -153,7 +158,10 @@
                 Class[] originalParameters = originalParameters(substituteMethod, macroSubstitution.signature(), macroSubstitution.isStatic());
                 Member originalMethod = originalMethod(classSubstitution, originalName, originalParameters);
                 if (originalMethod != null) {
-                    registerMacroSubstitution(originalMethod, macroSubstitution.macro());
+                    ResolvedJavaMethod original = registerMacroSubstitution(originalMethod, macroSubstitution.macro());
+                    if (original != null && macroSubstitution.isForcedInlining()) {
+                        forcedSubstitutions.add(original);
+                    }
                 }
             }
         }
@@ -164,8 +172,9 @@
      * 
      * @param originalMember a method or constructor being substituted
      * @param substituteMethod the substitute method
+     * @return the original method
      */
-    protected void registerMethodSubstitution(Member originalMember, Method substituteMethod) {
+    protected ResolvedJavaMethod registerMethodSubstitution(Member originalMember, Method substituteMethod) {
         ResolvedJavaMethod substitute = runtime.lookupJavaMethod(substituteMethod);
         ResolvedJavaMethod original;
         if (originalMember instanceof Method) {
@@ -176,6 +185,7 @@
         Debug.log("substitution: " + MetaUtil.format("%H.%n(%p)", original) + " --> " + MetaUtil.format("%H.%n(%p)", substitute));
 
         registeredMethodSubstitutions.put(original, substitute);
+        return original;
     }
 
     /**
@@ -183,8 +193,9 @@
      * 
      * @param originalMethod a method or constructor being substituted
      * @param macro the substitute macro node class
+     * @return the original method
      */
-    protected void registerMacroSubstitution(Member originalMethod, Class<? extends FixedWithNextNode> macro) {
+    protected ResolvedJavaMethod registerMacroSubstitution(Member originalMethod, Class<? extends FixedWithNextNode> macro) {
         ResolvedJavaMethod originalJavaMethod;
         if (originalMethod instanceof Method) {
             originalJavaMethod = runtime.lookupJavaMethod((Method) originalMethod);
@@ -192,6 +203,7 @@
             originalJavaMethod = runtime.lookupJavaConstructor((Constructor) originalMethod);
         }
         registerMacroSubstitutions.put(originalJavaMethod, macro);
+        return originalJavaMethod;
     }
 
     private SnippetInliningPolicy inliningPolicy(ResolvedJavaMethod method) {
@@ -477,4 +489,9 @@
         result.addAll(registerMacroSubstitutions.keySet());
         return result;
     }
+
+    @Override
+    public boolean isForcedSubstitution(ResolvedJavaMethod method) {
+        return forcedSubstitutions.contains(method);
+    }
 }