changeset 21133:bbc6a4347faf

Merge with b95deaa6ebf6100bb5a95ab25b2fdc6b9ef5f420
author Michael Van De Vanter <michael.van.de.vanter@oracle.com>
date Mon, 27 Apr 2015 20:01:10 -0700
parents fc6fd02ecf95 (current diff) b95deaa6ebf6 (diff)
children a5faa9aafc80
files
diffstat 18 files changed, 202 insertions(+), 26 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/GraphBuilderConfiguration.java	Sun Apr 26 20:50:30 2015 -0700
+++ b/graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/GraphBuilderConfiguration.java	Mon Apr 27 20:01:10 2015 -0700
@@ -34,6 +34,7 @@
         private final InvocationPlugins invocationPlugins;
         private LoadFieldPlugin loadFieldPlugin;
         private LoadIndexedPlugin loadIndexedPlugin;
+        private TypeCheckPlugin typeCheckPlugin;
         private ParameterPlugin parameterPlugin;
         private InlineInvokePlugin inlineInvokePlugin;
         private GenericInvocationPlugin genericInvocationPlugin;
@@ -49,6 +50,7 @@
             this.parameterPlugin = copyFrom.parameterPlugin;
             this.loadFieldPlugin = copyFrom.loadFieldPlugin;
             this.loadIndexedPlugin = copyFrom.loadIndexedPlugin;
+            this.typeCheckPlugin = copyFrom.typeCheckPlugin;
             this.inlineInvokePlugin = copyFrom.inlineInvokePlugin;
             this.loopExplosionPlugin = copyFrom.loopExplosionPlugin;
             this.genericInvocationPlugin = copyFrom.genericInvocationPlugin;
@@ -92,6 +94,14 @@
             this.loadIndexedPlugin = plugin;
         }
 
+        public TypeCheckPlugin getTypeCheckPlugin() {
+            return typeCheckPlugin;
+        }
+
+        public void setTypeCheckPlugin(TypeCheckPlugin typeCheckPlugin) {
+            this.typeCheckPlugin = typeCheckPlugin;
+        }
+
         public ParameterPlugin getParameterPlugin() {
             return parameterPlugin;
         }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/TypeCheckPlugin.java	Mon Apr 27 20:01:10 2015 -0700
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2015, 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.graphbuilderconf;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.nodes.*;
+
+public interface TypeCheckPlugin extends GraphBuilderPlugin {
+    /**
+     * Intercept the parsing of a CHECKCAST bytecode. If the method returns true, it must push
+     * {@link GraphBuilderContext#push push} an object value as the result of the cast.
+     *
+     * @param b The context.
+     * @param object The object to be type checked.
+     * @param type The type that the object is checked against.
+     * @param profile The profiling information for the type check, or null if no profiling
+     *            information is available.
+     * @return True if the plugin handled the cast, false if the bytecode parser should handle the
+     *         cast.
+     */
+    default boolean checkCast(GraphBuilderContext b, ValueNode object, ResolvedJavaType type, JavaTypeProfile profile) {
+        return false;
+    }
+
+    /**
+     * Intercept the parsing of a INSTANCEOF bytecode. If the method returns true, it must push
+     * {@link GraphBuilderContext#push push} an integer value with the result of the instanceof.
+     *
+     * @param b The context.
+     * @param object The object to be type checked.
+     * @param type The type that the object is checked against.
+     * @param profile The profiling information for the type check, or null if no profiling
+     *            information is available.
+     * @return True if the plugin handled the instanceof, false if the bytecode parser should handle
+     *         the instanceof.
+     */
+    default boolean instanceOf(GraphBuilderContext b, ValueNode object, ResolvedJavaType type, JavaTypeProfile profile) {
+        return false;
+    }
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/PrintStreamOption.java	Sun Apr 26 20:50:30 2015 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/PrintStreamOption.java	Mon Apr 27 20:01:10 2015 -0700
@@ -111,6 +111,11 @@
                     public void write(int b) throws IOException {
                         write(new byte[]{(byte) b}, 0, 1);
                     }
+
+                    @Override
+                    public void flush() throws IOException {
+                        compilerToVM.flushDebugOutput();
+                    }
                 };
                 ps = new PrintStream(ttyOut);
             }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java	Sun Apr 26 20:50:30 2015 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java	Mon Apr 27 20:01:10 2015 -0700
@@ -387,4 +387,6 @@
     boolean shouldDebugNonSafepoints();
 
     void writeDebugOutput(byte[] bytes, int offset, int length);
+
+    void flushDebugOutput();
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java	Sun Apr 26 20:50:30 2015 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java	Mon Apr 27 20:01:10 2015 -0700
@@ -206,4 +206,6 @@
     public native boolean shouldDebugNonSafepoints();
 
     public native void writeDebugOutput(byte[] bytes, int offset, int length);
+
+    public native void flushDebugOutput();
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotGraphBuilderPlugins.java	Sun Apr 26 20:50:30 2015 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotGraphBuilderPlugins.java	Mon Apr 27 20:01:10 2015 -0700
@@ -74,6 +74,7 @@
         plugins.setParameterPlugin(new HotSpotParameterPlugin(wordTypes));
         plugins.setLoadFieldPlugin(new HotSpotLoadFieldPlugin(metaAccess, constantReflection));
         plugins.setLoadIndexedPlugin(new HotSpotLoadIndexedPlugin(wordTypes));
+        plugins.setTypeCheckPlugin(wordOperationPlugin);
         plugins.setInlineInvokePlugin(new DefaultInlineInvokePlugin(replacements));
         plugins.setGenericInvocationPlugin(new DefaultGenericInvocationPlugin(metaAccess, nodeIntrinsification, wordOperationPlugin));
 
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractBytecodeParser.java	Sun Apr 26 20:50:30 2015 -0700
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractBytecodeParser.java	Mon Apr 27 20:01:10 2015 -0700
@@ -604,9 +604,13 @@
         JavaType type = lookupType(cpi, CHECKCAST);
         ValueNode object = frameState.apop();
         if (type instanceof ResolvedJavaType) {
-            JavaTypeProfile profileForTypeCheck = getProfileForTypeCheck((ResolvedJavaType) type);
-            ValueNode checkCastNode = append(createCheckCast((ResolvedJavaType) type, object, profileForTypeCheck, false));
-            frameState.apush(checkCastNode);
+            ResolvedJavaType resolvedType = (ResolvedJavaType) type;
+            JavaTypeProfile profile = getProfileForTypeCheck(resolvedType);
+            TypeCheckPlugin typeCheckPlugin = this.graphBuilderConfig.getPlugins().getTypeCheckPlugin();
+            if (typeCheckPlugin == null || !typeCheckPlugin.checkCast((GraphBuilderContext) this, object, resolvedType, profile)) {
+                ValueNode checkCastNode = append(createCheckCast(resolvedType, object, profile, false));
+                frameState.apush(checkCastNode);
+            }
         } else {
             handleUnresolvedCheckCast(type, object);
         }
@@ -622,8 +626,12 @@
         ValueNode object = frameState.apop();
         if (type instanceof ResolvedJavaType) {
             ResolvedJavaType resolvedType = (ResolvedJavaType) type;
-            ValueNode instanceOfNode = createInstanceOf((ResolvedJavaType) type, object, getProfileForTypeCheck(resolvedType));
-            frameState.ipush(append(genConditional(genUnique(instanceOfNode))));
+            JavaTypeProfile profile = getProfileForTypeCheck(resolvedType);
+            TypeCheckPlugin typeCheckPlugin = this.graphBuilderConfig.getPlugins().getTypeCheckPlugin();
+            if (typeCheckPlugin == null || !typeCheckPlugin.instanceOf((GraphBuilderContext) this, object, resolvedType, profile)) {
+                ValueNode instanceOfNode = createInstanceOf(resolvedType, object, profile);
+                frameState.ipush(append(genConditional(genUnique(instanceOfNode))));
+            }
         } else {
             handleUnresolvedInstanceOf(type, object);
         }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/InliningUtil.java	Sun Apr 26 20:50:30 2015 -0700
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/InliningUtil.java	Mon Apr 27 20:01:10 2015 -0700
@@ -427,7 +427,7 @@
     }
 
     public static BytecodePosition processSimpleInfopoint(Invoke invoke, SimpleInfopointNode infopointNode, BytecodePosition incomingPos) {
-        BytecodePosition pos = incomingPos != null ? incomingPos : new BytecodePosition(toBytecodePosition(invoke.stateAfter()), invoke.asNode().graph().method(), invoke.bci());
+        BytecodePosition pos = incomingPos != null ? incomingPos : new BytecodePosition(toBytecodePosition(invoke.stateAfter()).getCaller(), invoke.asNode().graph().method(), invoke.bci());
         infopointNode.addCaller(pos);
         return pos;
     }
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/WordTest.java	Sun Apr 26 20:50:30 2015 -0700
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/WordTest.java	Mon Apr 27 20:01:10 2015 -0700
@@ -110,6 +110,20 @@
         }
     }
 
+    @Test
+    public void testCast() {
+        test("cast", 1234L);
+    }
+
+    @Snippet
+    public static long cast(long input) {
+        WordBase base = Word.signed(input);
+        Unsigned unsigned = (Unsigned) base;
+        Pointer pointer = (Pointer) unsigned;
+        Word word = (Word) pointer;
+        return word.rawValue();
+    }
+
     @Snippet
     public static long unsignedLong(long word) {
         return Word.unsigned(word).rawValue();
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/WordOperationPlugin.java	Sun Apr 26 20:50:30 2015 -0700
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/WordOperationPlugin.java	Mon Apr 27 20:01:10 2015 -0700
@@ -43,9 +43,10 @@
 import com.oracle.graal.word.nodes.*;
 
 /**
- * A {@link GenericInvocationPlugin} for calls to {@linkplain Operation word operations}.
+ * A {@link GenericInvocationPlugin} for calls to {@linkplain Operation word operations}, and a
+ * {@link TypeCheckPlugin} to handle casts between word types.
  */
-public class WordOperationPlugin implements GenericInvocationPlugin {
+public class WordOperationPlugin implements GenericInvocationPlugin, TypeCheckPlugin {
     protected final WordTypes wordTypes;
     protected final Kind wordKind;
     protected final SnippetReflectionProvider snippetReflection;
@@ -71,6 +72,32 @@
         return true;
     }
 
+    @Override
+    public boolean checkCast(GraphBuilderContext b, ValueNode object, ResolvedJavaType type, JavaTypeProfile profile) {
+        if (!wordTypes.isWord(type)) {
+            if (object.getKind() != Kind.Object) {
+                throw b.bailout("Cannot cast a word value to a non-word type: " + type.toJavaName(true));
+            }
+            return false;
+        }
+
+        if (object.getKind() != wordTypes.getWordKind()) {
+            throw b.bailout("Cannot cast a non-word value to a word type: " + type.toJavaName(true));
+        }
+        b.push(Kind.Object, object);
+        return true;
+    }
+
+    @Override
+    public boolean instanceOf(GraphBuilderContext b, ValueNode object, ResolvedJavaType type, JavaTypeProfile profile) {
+        if (wordTypes.isWord(type)) {
+            throw b.bailout("Cannot use instanceof for word a type: " + type.toJavaName(true));
+        } else if (object.getKind() != Kind.Object) {
+            throw b.bailout("Cannot use instanceof on a word value: " + type.toJavaName(true));
+        }
+        return false;
+    }
+
     protected void processWordOperation(GraphBuilderContext b, ValueNode[] args, ResolvedJavaMethod wordMethod) throws GraalInternalError {
         Operation operation = wordMethod.getAnnotation(Word.Operation.class);
         Kind returnKind = wordMethod.getSignature().getReturnKind();
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationClosure.java	Sun Apr 26 20:50:30 2015 -0700
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationClosure.java	Mon Apr 27 20:01:10 2015 -0700
@@ -89,8 +89,11 @@
                 ReadCacheEntry identifier = new ReadCacheEntry(object, read.location());
                 ValueNode cachedValue = state.getCacheEntry(identifier);
                 if (cachedValue != null && read.stamp().isCompatible(cachedValue.stamp())) {
+                    // Anchor guard if it is not fixed and different from cachedValue's guard
                     if (read.getGuard() != null && !(read.getGuard() instanceof FixedNode)) {
-                        effects.addFixedNodeBefore(new ValueAnchorNode((ValueNode) read.getGuard()), read);
+                        if (!(cachedValue instanceof GuardedNode) || ((GuardedNode) cachedValue).getGuard() != read.getGuard()) {
+                            effects.addFixedNodeBefore(new ValueAnchorNode((ValueNode) read.getGuard()), read);
+                        }
                     }
                     effects.replaceAtUsages(read, cachedValue);
                     addScalarAlias(read, cachedValue);
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLDivNode.java	Sun Apr 26 20:50:30 2015 -0700
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLDivNode.java	Mon Apr 27 20:01:10 2015 -0700
@@ -41,10 +41,16 @@
         super(src);
     }
 
-    @Specialization
-    protected long div(long left, long right) {
-        /* No overflow is possible on a division. */
-        return left / right;
+    @Specialization(rewriteOn = ArithmeticException.class)
+    protected long div(long left, long right) throws ArithmeticException {
+        long result = left / right;
+        /*
+         * The division overflows if left is Long.MIN_VALUE and right is -1.
+         */
+        if ((left & right & result) < 0) {
+            throw new ArithmeticException("long overflow");
+        }
+        return result;
     }
 
     @Specialization
--- a/mx/mx_graal.py	Sun Apr 26 20:50:30 2015 -0700
+++ b/mx/mx_graal.py	Mon Apr 27 20:01:10 2015 -0700
@@ -601,6 +601,8 @@
 
 def _classifyGraalServices(classNames, graalJars):
     classification = {}
+    if not classNames:
+        return classification
     for className in classNames:
         classification[className] = None
     javap = mx.java().javap
@@ -680,14 +682,17 @@
                     assert serviceName and member == 'META-INF/services/' + serviceName
                     with zf.open(member) as serviceFile:
                         serviceImpls = servicesMap.setdefault(serviceName, [])
-                        serviceImpls.extend(serviceFile.readlines())
+                        for line in serviceFile.readlines():
+                            line = line.strip()
+                            if line:
+                                serviceImpls.append(line)
     graalServices = _filterGraalService(servicesMap.keys(), graalJars)
     for serviceName in graalServices:
         serviceImpls = servicesMap[serviceName]
         fd, tmp = tempfile.mkstemp(prefix=serviceName)
         f = os.fdopen(fd, 'w+')
         for serviceImpl in serviceImpls:
-            f.write(serviceImpl.rstrip() + os.linesep)
+            f.write(serviceImpl + os.linesep)
         target = join(destination, serviceName)
         f.close()
         shutil.move(tmp, target)
--- a/src/cpu/sparc/vm/graalGlobals_sparc.hpp	Sun Apr 26 20:50:30 2015 -0700
+++ b/src/cpu/sparc/vm/graalGlobals_sparc.hpp	Mon Apr 27 20:01:10 2015 -0700
@@ -60,4 +60,6 @@
 define_pd_global(intx, MethodProfileWidth,           0);
 #endif // COMPILERGRAAL
 
+define_pd_global(intx, MaxVectorSize,                8);
+
 #endif // CPU_SPARC_VM_GRAALGLOBALS_SPARC_HPP
--- a/src/cpu/x86/vm/graalGlobals_x86.hpp	Sun Apr 26 20:50:30 2015 -0700
+++ b/src/cpu/x86/vm/graalGlobals_x86.hpp	Mon Apr 27 20:01:10 2015 -0700
@@ -60,4 +60,6 @@
 define_pd_global(intx, MethodProfileWidth,           0);
 #endif // COMPILERGRAAL
 
+define_pd_global(intx, MaxVectorSize,                32);
+
 #endif // CPU_X86_VM_GRAALGLOBALS_X86_HPP
--- a/src/share/vm/graal/graalCompilerToVM.cpp	Sun Apr 26 20:50:30 2015 -0700
+++ b/src/share/vm/graal/graalCompilerToVM.cpp	Mon Apr 27 20:01:10 2015 -0700
@@ -1019,6 +1019,10 @@
   }
 C2V_END
 
+C2V_VMENTRY(void, flushDebugOutput, (JNIEnv*, jobject))
+  tty->flush();
+C2V_END
+
 
 #define CC (char*)  /*cast a literal from (const char*)*/
 #define FN_PTR(f) CAST_FROM_FN_PTR(void*, &(c2v_ ## f))
@@ -1099,6 +1103,7 @@
   {CC"materializeVirtualObjects",                    CC"("HS_STACK_FRAME_REF"Z)V",                                             FN_PTR(materializeVirtualObjects)},
   {CC"shouldDebugNonSafepoints",                     CC"()Z",                                                                  FN_PTR(shouldDebugNonSafepoints)},
   {CC"writeDebugOutput",                             CC"([BII)V",                                                              FN_PTR(writeDebugOutput)},
+  {CC"flushDebugOutput",                             CC"()V",                                                                  FN_PTR(flushDebugOutput)},
 };
 
 int CompilerToVM_methods_count() {
--- a/src/share/vm/graal/graalGlobals.hpp	Sun Apr 26 20:50:30 2015 -0700
+++ b/src/share/vm/graal/graalGlobals.hpp	Mon Apr 27 20:01:10 2015 -0700
@@ -67,7 +67,7 @@
   GRAAL_ONLY(product(bool, CodeInstallSafepointChecks, true,                \
           "Perform explicit safepoint checks while installing code"))       \
                                                                             \
-  NOT_COMPILER2(product(intx, MaxVectorSize, 32,                            \
+  NOT_COMPILER2(product_pd(intx, MaxVectorSize,                                \
           "Max vector size in bytes, "                                      \
           "actual size could be less depending on elements type"))          \
                                                                             \
--- a/src/share/vm/graal/graalRuntime.cpp	Sun Apr 26 20:50:30 2015 -0700
+++ b/src/share/vm/graal/graalRuntime.cpp	Mon Apr 27 20:01:10 2015 -0700
@@ -1099,19 +1099,43 @@
         GrowableArray<char*>* implNames = new GrowableArray<char*>();
         char* line = buffer;
         while (line - buffer < num_read) {
-          char* nl = strchr(line, '\n');
-          if (nl != NULL) {
-            *nl = '\0';
+          // find line end (\r, \n or \r\n)
+          char* nextline = NULL;
+          char* cr = strchr(line, '\r');
+          char* lf = strchr(line, '\n');
+          if (cr != NULL && lf != NULL) {
+            char* min = MIN2(cr, lf);
+            *min = '\0';
+            if (lf == cr + 1) {
+              nextline = lf + 1;
+            } else {
+              nextline = min + 1;
+            }
+          } else if (cr != NULL) {
+            *cr = '\0';
+            nextline = cr + 1;
+          } else if (lf != NULL) {
+            *lf = '\0';
+            nextline = lf + 1;
           }
-          // Turn all '.'s into '/'s
-          for (size_t index = 0; line[index] != '\0'; index++) {
-            if (line[index] == '.') {
-              line[index] = '/';
+          // trim left
+          while (*line == ' ' || *line == '\t') line++;
+          char* end = line + strlen(line);
+          // trim right
+          while (end > line && (*(end -1) == ' ' || *(end -1) == '\t')) end--;
+          *end = '\0';
+          // skip comments and empty lines
+          if (*line != '#' && strlen(line) > 0) {
+            // Turn all '.'s into '/'s
+            for (size_t index = 0; line[index] != '\0'; index++) {
+              if (line[index] == '.') {
+                line[index] = '/';
+              }
             }
+            implNames->append(line);
           }
-          implNames->append(line);
-          if (nl != NULL) {
-            line = nl + 1;
+          if (nextline != NULL) {
+            line = nextline;
           } else {
             // File without newline at the end
             break;