# HG changeset patch # User Christos Kotselidis # Date 1364291502 -3600 # Node ID c91917e43c98267ecbe10fa3c7efca351bb3e5ee # Parent 4a79f7c0d1a4a4710ba1a056d8de204e3a573cb6# Parent 95e21e0353635e76469671f634a8e0f93a3d12dc -Merge diff -r 4a79f7c0d1a4 -r c91917e43c98 graal/com.oracle.graal.api.replacements/src/com/oracle/graal/api/replacements/Alias.java --- /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 field + * descriptor of the aliased field or the method + * descriptor of the aliased method. + *

+ * 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; +} diff -r 4a79f7c0d1a4 -r c91917e43c98 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/SystemSubstitutions.java --- 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(); + } } diff -r 4a79f7c0d1a4 -r c91917e43c98 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ThreadSubstitutions.java --- 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; } diff -r 4a79f7c0d1a4 -r c91917e43c98 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/AliasResolutionPhase.java --- /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; + } +} diff -r 4a79f7c0d1a4 -r c91917e43c98 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsInstaller.java --- 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 diff -r 4a79f7c0d1a4 -r c91917e43c98 make/Makefile --- 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