changeset 8519:c91917e43c98

-Merge
author Christos Kotselidis <christos.kotselidis@oracle.com>
date Tue, 26 Mar 2013 10:51:42 +0100
parents 4a79f7c0d1a4 (current diff) 95e21e035363 (diff)
children 450abf358987
files graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/SystemSubstitutions.java
diffstat 6 files changed, 276 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.api.replacements/src/com/oracle/graal/api/replacements/Alias.java	Tue Mar 26 10:51:42 2013 +0100
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.api.replacements;
+
+import java.lang.annotation.*;
+
+/**
+ * Mechanism for accessing fields and methods otherwise inaccessible due to Java language access
+ * control rules.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.METHOD, ElementType.FIELD})
+public @interface Alias {
+
+    /**
+     * The name of the aliased field or method. If the default value is specified for this element,
+     * then the name of the annotated field or method is implied.
+     */
+    String name() default "";
+
+    /**
+     * Gets the <a
+     * href="http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.3.2">field
+     * descriptor</a> of the aliased field or the <a
+     * href="http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.3.3">method
+     * descriptor</a> of the aliased method.
+     * <p>
+     * If the default value is specified for this element, then the descriptor of the annotated
+     * field or method is implied.
+     */
+    String descriptor() default "";
+
+    /**
+     * Specifies the class in which the aliased field or method is declared. If the default value is
+     * specified for this element, then a non-default value must be given for the
+     * {@link #declaringClassName()} element.
+     */
+    Class declaringClass() default Alias.class;
+
+    /**
+     * Specifies the class in which the aliased field or method is declared. This method is provided
+     * for cases where the declaring class is not accessible (according to Java language access
+     * control rules) in the scope of the alias method.
+     * 
+     * If the default value is specified for this element, then a non-default value must be given
+     * for the {@link #declaringClassName()} element.
+     */
+    String declaringClassName() default "";
+
+    /**
+     * Specifies the suffix of the declaring class name if it is an inner class.
+     */
+    String innerClass() default "";
+
+    /**
+     * Specifies if the aliased target must exist. This property is useful, for example, to handle
+     * differences in JDK versions for private methods.
+     */
+    boolean optional() default false;
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/SystemSubstitutions.java	Tue Mar 26 10:50:50 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/SystemSubstitutions.java	Tue Mar 26 10:51:42 2013 +0100
@@ -65,5 +65,11 @@
     }
 
     @NodeIntrinsic(value = RuntimeCallNode.class, setStampFromReturnType = true)
-    public static native long callLong(@ConstantNodeParameter Descriptor descriptor);
+    public static long callLong(@ConstantNodeParameter Descriptor descriptor) {
+        if (descriptor == JAVA_TIME_MILLIS) {
+            return System.currentTimeMillis();
+        }
+        assert descriptor == JAVA_TIME_NANOS;
+        return System.nanoTime();
+    }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ThreadSubstitutions.java	Tue Mar 26 10:50:50 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ThreadSubstitutions.java	Tue Mar 26 10:51:42 2013 +0100
@@ -23,6 +23,7 @@
 package com.oracle.graal.hotspot.replacements;
 
 import static com.oracle.graal.hotspot.replacements.HotSpotSnippetUtils.*;
+import static com.oracle.graal.nodes.extended.UnsafeCastNode.*;
 
 import com.oracle.graal.api.replacements.*;
 import com.oracle.graal.hotspot.nodes.*;
@@ -39,13 +40,17 @@
         return CurrentThread.get();
     }
 
+    @Alias(declaringClass = Thread.class) private long eetop;
+
     @MethodSubstitution(isStatic = false)
-    private static boolean isInterrupted(final Thread thisObject, boolean clearInterrupted) {
-        Word rawThread = HotSpotCurrentRawThreadNode.get();
-        Thread thread = (Thread) rawThread.readObject(threadObjectOffset(), FINAL_LOCATION);
+    public static boolean isInterrupted(final Thread thisObject, boolean clearInterrupted) {
+        Thread thread = CurrentThread.get();
         if (thisObject == thread) {
+            ThreadSubstitutions threadAlias = unsafeCast(thread, ThreadSubstitutions.class, false, true);
+            Word rawThread = Word.unsigned(threadAlias.eetop);
             Word osThread = rawThread.readWord(osThreadOffset(), FINAL_LOCATION);
-            boolean interrupted = osThread.readInt(osThreadInterruptedOffset(), UNKNOWN_LOCATION) != 0;
+            int int0 = osThread.readInt(osThreadInterruptedOffset(), UNKNOWN_LOCATION);
+            boolean interrupted = int0 != 0;
             if (!interrupted || !clearInterrupted) {
                 return interrupted;
             }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/AliasResolutionPhase.java	Tue Mar 26 10:51:42 2013 +0100
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.replacements;
+
+import static com.oracle.graal.api.meta.MetaUtil.*;
+import static com.oracle.graal.replacements.ReplacementsInstaller.*;
+import static java.lang.Thread.*;
+import static java.lang.reflect.Modifier.*;
+
+import java.lang.reflect.*;
+import java.util.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.replacements.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.phases.*;
+
+/**
+ * Resolves field and method {@linkplain Alias aliases} to the aliased fields and methods.
+ */
+public class AliasResolutionPhase extends Phase {
+
+    private final MetaAccessProvider runtime;
+
+    public AliasResolutionPhase(MetaAccessProvider runtime) {
+        this.runtime = runtime;
+    }
+
+    @Override
+    protected void run(StructuredGraph graph) {
+        for (LoadFieldNode loadField : graph.getNodes(LoadFieldNode.class)) {
+            ResolvedJavaField field = loadField.field();
+            Field aliasedField = getAliasedField(field);
+            if (aliasedField != null) {
+                LoadFieldNode replacement = graph.add(new LoadFieldNode(loadField.object(), runtime.lookupJavaField(aliasedField)));
+                graph.replaceFixedWithFixed(loadField, replacement);
+            }
+        }
+        for (StoreFieldNode storeField : graph.getNodes().filter(StoreFieldNode.class)) {
+            ResolvedJavaField field = storeField.field();
+            Field aliasedField = getAliasedField(field);
+            if (aliasedField != null) {
+                StoreFieldNode replacement = graph.add(new StoreFieldNode(storeField.object(), runtime.lookupJavaField(aliasedField), storeField.value()));
+                graph.replaceFixedWithFixed(storeField, replacement);
+            }
+        }
+
+        for (Invoke invoke : graph.getInvokes()) {
+            if (invoke.callTarget() instanceof MethodCallTargetNode) {
+                MethodCallTargetNode methodCallTarget = invoke.methodCallTarget();
+                ResolvedJavaMethod method = methodCallTarget.targetMethod();
+                Method aliasedMethod = getAliasedMethod(method);
+                if (aliasedMethod != null) {
+                    methodCallTarget.setTargetMethod(runtime.lookupJavaMethod(aliasedMethod));
+                }
+            }
+        }
+    }
+
+    private static Field getAliasedField(ResolvedJavaField field) {
+        Alias alias = field.getAnnotation(Alias.class);
+        if (alias == null) {
+            return null;
+        }
+        Class holder = declaringClass(alias, field);
+        if (holder == null) {
+            assert alias.optional();
+            return null;
+        }
+
+        String name = alias.name();
+        if (name.isEmpty()) {
+            name = field.getName();
+        }
+
+        Class type;
+        if (alias.descriptor().isEmpty()) {
+            type = getMirrorOrFail((ResolvedJavaType) field.getType(), currentThread().getContextClassLoader());
+        } else {
+            type = resolveType(alias.descriptor(), false);
+        }
+
+        for (Field f : holder.getDeclaredFields()) {
+            if (f.getName().equals(name) && f.getType().equals(type) && isStatic(f.getModifiers()) == isStatic(field.getModifiers())) {
+                return f;
+            }
+        }
+        if (alias.optional()) {
+            return null;
+        }
+        throw new GraalInternalError("Could not resolve field alias %s", format("%T %H.%n", field));
+    }
+
+    private Method getAliasedMethod(ResolvedJavaMethod method) {
+        Alias alias = method.getAnnotation(Alias.class);
+        if (alias == null) {
+            return null;
+        }
+        Class holder = declaringClass(alias, method);
+        if (holder == null) {
+            assert alias.optional();
+            return null;
+        }
+
+        String name = alias.name();
+        if (name.isEmpty()) {
+            name = method.getName();
+        }
+
+        Class[] parameters;
+        if (alias.descriptor().isEmpty()) {
+            parameters = NodeIntrinsificationPhase.signatureToTypes(method.getSignature(), null);
+        } else {
+            Signature signature = runtime.parseMethodDescriptor(alias.descriptor());
+            parameters = NodeIntrinsificationPhase.signatureToTypes(signature, null);
+        }
+
+        for (Method m : holder.getDeclaredMethods()) {
+            if (m.getName().equals(name) && Arrays.equals(m.getParameterTypes(), parameters) && isStatic(m.getModifiers()) == isStatic(method.getModifiers())) {
+                return m;
+            }
+        }
+        if (alias.optional()) {
+            return null;
+        }
+        throw new GraalInternalError("Could not resolve method alias %s", format("%R %H.%n(%P)", method));
+    }
+
+    private static Class getInnerClass(Class outerClass, String innerClassSimpleName) {
+        for (Class innerClass : outerClass.getDeclaredClasses()) {
+            if (innerClass.getSimpleName().equals(innerClassSimpleName)) {
+                return innerClass;
+            }
+        }
+        return null;
+    }
+
+    private static Class declaringClass(Alias alias, Object member) {
+        Class holder;
+        if (alias.declaringClass() == Alias.class) {
+            assert !alias.declaringClassName().isEmpty() : "declaring class missing for alias " + member;
+            holder = resolveType(alias.declaringClassName(), alias.optional());
+        } else {
+            assert alias.declaringClassName().isEmpty() : "declaring class specified more than once for alias " + member;
+            holder = alias.declaringClass();
+        }
+        if (holder != null && !alias.innerClass().isEmpty()) {
+            holder = getInnerClass(holder, alias.innerClass());
+        }
+        return holder;
+    }
+}
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsInstaller.java	Tue Mar 26 10:50:50 2013 +0100
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsInstaller.java	Tue Mar 26 10:51:42 2013 +0100
@@ -210,6 +210,7 @@
      * Does final processing of a snippet graph.
      */
     protected void finalizeGraph(ResolvedJavaMethod method, StructuredGraph graph) {
+        new AliasResolutionPhase(runtime).apply(graph);
         new NodeIntrinsificationPhase(runtime, pool).apply(graph);
         assert SnippetTemplate.hasConstantParameter(method) || NodeIntrinsificationVerificationPhase.verify(graph);
 
@@ -255,6 +256,7 @@
         Debug.dump(graph, "%s: %s", method.getName(), GraphBuilderPhase.class.getSimpleName());
 
         new WordTypeVerificationPhase(runtime, target.wordKind).apply(graph);
+        new AliasResolutionPhase(runtime).apply(graph);
         new NodeIntrinsificationPhase(runtime, pool).apply(graph);
 
         return graph;
@@ -277,6 +279,7 @@
      * Called after all inlining for a given graph is complete.
      */
     protected void afterInlining(StructuredGraph graph) {
+        new AliasResolutionPhase(runtime).apply(graph);
         new NodeIntrinsificationPhase(runtime, pool).apply(graph);
 
         new WordTypeRewriterPhase(runtime, target.wordKind).apply(graph);
@@ -340,7 +343,7 @@
      * @param optional if true, resolution failure returns null
      * @return the resolved class or null if resolution fails and {@code optional} is true
      */
-    private static Class resolveType(String className, boolean optional) {
+    static Class resolveType(String className, boolean optional) {
         try {
             // Need to use launcher class path to handle classes
             // that are not on the boot class path
--- a/make/Makefile	Tue Mar 26 10:50:50 2013 +0100
+++ b/make/Makefile	Tue Mar 26 10:51:42 2013 +0100
@@ -187,7 +187,8 @@
 
 $(GRAAL_VM_TARGETS):
 	$(CD) $(GAMMADIR)/make; \
-	$(MAKE) VM_TARGET=$@ generic_buildgraal $(ALT_OUT)
+	$(MAKE) BUILD_FLAVOR=$@ VM_TARGET=$@ \
+	  generic_buildgraal $(ALT_OUT)
 
 # Build compiler1 (client) rule, different for platforms
 generic_build1: buildshared