# HG changeset patch # User Christian Humer # Date 1380713191 -7200 # Node ID aff825fef0fdd804749ec760c8c625c5c32d7059 # Parent 91dbb0b7dc8b8a381ef725006f8997f7f9a8eb51# Parent 04b039d82e8691ee5844fbdcf890f3349bedf8bf Merge. diff -r 91dbb0b7dc8b -r aff825fef0fd .hgignore --- a/.hgignore Fri Sep 06 21:37:50 2013 +0200 +++ b/.hgignore Wed Oct 02 13:26:31 2013 +0200 @@ -1,5 +1,7 @@ ^mx/env ^mx/checkstyle-timestamps +^mx/eclipseinit.timestamp +^mx/netbeansinit.timestamp ^mx/eclipse-launches ^mx/ecj.jar ^mx/includes diff -r 91dbb0b7dc8b -r aff825fef0fd README_GRAAL.txt --- a/README_GRAAL.txt Fri Sep 06 21:37:50 2013 +0200 +++ b/README_GRAAL.txt Wed Oct 02 13:26:31 2013 +0200 @@ -11,11 +11,30 @@ % mx build -This builds the 'product' version of HotSpot with the Graal modifications. -To build the debug or fastdebug versions: +There are a number of VM configurations supported by mx which can +be explicitly specified using the --vm option. However, you'll typically +want one of these VM configurations: - mx build debug - mx build fastdebug +1. The 'server' configuration is a standard HotSpot VM that includes the + runtime support for Graal but uses the existing compilers for normal + compilation (e.g., when the interpreter threshold is hit for a method). + Compilation with Graal is only done by explicit requests to the + Graal API. This is how Truffle uses Graal. + +2. The 'graal' configuration is a VM where all compilation is performed + by Graal and no other compilers are built into the VM binary. This + VM will bootstrap Graal itself at startup unless the -XX:-BootstrapGraal + VM option is given. + +Unless you use the --vm option with the build command, you will be presented +with a dialogue to choose one of the above VM configurations for the build +as well as have the option to make it your default for subsequent commands +that need a VM specified. + +To build the debug or fastdebug builds: + +% mx --vmbuild debug build +% mx --vmbuild fastdebug build Running Graal ------------- @@ -24,47 +43,28 @@ % mx vm ... -To select the fastdebug or debug versions of the VM: - -% mx --fastdebug vm ... -% mx --debug vm ... +To select the fastdebug or debug builds of the VM: -Graal has an optional bootstrap step where it compiles itself before -compiling any application code. This bootstrap step currently takes about 7 seconds -on a fast x64 machine. It's useful to disable this bootstrap step when running small -programs with the -XX:-BootstrapGraal options. For example: +% mx --vmbuild fastdebug vm ... +% mx --vmbuild debug vm ... -% mx vm -XX:-BootstrapGraal ... - +Other VM Configurations +----------------------- -Other Build Configurations --------------------------- - -By default the build commands above create a HotSpot binary where Graal -is the only compiler. This binary is the Graal VM binary and identifies as -such with the -version option: +In addition to the VM configurations described above, there are +VM configurations that omit all VM support for Graal: -% mx vm -XX:-BootstrapGraal -version -java version "1.7.0_07" -Java(TM) SE Runtime Environment (build 1.7.0_07-b10) -OpenJDK 64-Bit Graal VM (build 25.0-b10-internal, mixed mode) - -It's also possible to build and execute the standard HotSpot binaries -using the --vm option: +% mx --vm server-nograal build +% mx --vm server-nograal vm -version +java version "1.7.0_25" +Java(TM) SE Runtime Environment (build 1.7.0_25-b15) +OpenJDK 64-Bit Server VM (build 25.0-b43-internal, mixed mode) -% mx --vm server build -% mx --vm server vm -version -java version "1.7.0_07" -Java(TM) SE Runtime Environment (build 1.7.0_07-b10) -OpenJDK 64-Bit Server VM (build 25.0-b10-internal, mixed mode) +% mx --vm client-nograal build +% mx --vm client-nograal vm -version +java version "1.7.0_25" +Java(TM) SE Runtime Environment (build 1.7.0_25-b15) +OpenJDK 64-Bit Cleint VM (build 25.0-b43-internal, mixed mode) -These standard binaries still include the code necessary to support use of the -Graal compiler for explicit compilation requests. However, in this configuration -the Graal compiler will not service VM issued compilation requests (e.g., upon -counter overflow in the interpreter). - -To build a HotSpot binary that completely omits all VM support for Graal, -define an environment variable OMIT_GRAAL (its value does not matter) and build -with the --vm option as above (doing a clean first if necessary): - -% env OMIT_GRAAL= mx --vm server build +These configurations aim to match as closely as possible the +VM(s) included in the OpenJDK binaries one can download. \ No newline at end of file diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/ArithmeticOperation.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/ArithmeticOperation.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/ArithmeticOperation.java Wed Oct 02 13:26:31 2013 +0200 @@ -22,9 +22,13 @@ */ package com.oracle.graal.api.code; +import com.oracle.graal.api.meta.*; + /** * An {@code ArithmeticOperation} is an operation that does primitive value arithmetic without side * effect. */ public interface ArithmeticOperation { + + Constant evalConst(Constant... inputs); } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CallingConvention.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CallingConvention.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CallingConvention.java Wed Oct 02 13:26:31 2013 +0200 @@ -151,7 +151,7 @@ private boolean verify() { for (int i = 0; i < argumentLocations.length; i++) { Value location = argumentLocations[i]; - assert isStackSlot(location) || isRegister(location); + assert isStackSlot(location) || isAllocatableValue(location); } return true; } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeCacheProvider.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeCacheProvider.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeCacheProvider.java Wed Oct 02 13:26:31 2013 +0200 @@ -72,13 +72,6 @@ ForeignCallLinkage lookupForeignCall(ForeignCallDescriptor descriptor); /** - * Encodes a deoptimization action and a deoptimization reason in an integer value. - * - * @return the encoded value as an integer - */ - int encodeDeoptActionAndReason(DeoptimizationAction action, DeoptimizationReason reason); - - /** * Determines if a {@link DataPatch} should be created for a given * {@linkplain Constant#getPrimitiveAnnotation() annotated} primitive constant that part of a * {@link CompilationResult}. A data patch is always created for an object constant. diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/DebugInfo.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/DebugInfo.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/DebugInfo.java Wed Oct 02 13:26:31 2013 +0200 @@ -44,7 +44,6 @@ private final BytecodePosition bytecodePosition; private final BitSet registerRefMap; private final BitSet frameRefMap; - private final short deoptimizationReason; private RegisterSaveLayout calleeSaveInfo; /** @@ -55,11 +54,10 @@ * @param registerRefMap the register map * @param frameRefMap the reference map for {@code frame}, which may be {@code null} */ - public DebugInfo(BytecodePosition codePos, BitSet registerRefMap, BitSet frameRefMap, short deoptimizationReason) { + public DebugInfo(BytecodePosition codePos, BitSet registerRefMap, BitSet frameRefMap) { this.bytecodePosition = codePos; this.registerRefMap = registerRefMap; this.frameRefMap = frameRefMap; - this.deoptimizationReason = deoptimizationReason; } /** @@ -127,15 +125,6 @@ } /** - * Identifies the reason in case a deoptimization happens at this program counter. - * - * @return the reason of the deoptimization - */ - public short getDeoptimizationReason() { - return deoptimizationReason; - } - - /** * Sets the map from the registers (in the caller's frame) to the slots where they are saved in * the current frame. */ diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/DelegatingCodeCacheProvider.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/DelegatingCodeCacheProvider.java Wed Oct 02 13:26:31 2013 +0200 @@ -0,0 +1,68 @@ +/* + * 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.code; + +import com.oracle.graal.api.meta.*; + +/** + * A {@link CodeCacheProvider} that delegates to another {@link CodeCacheProvider}. + */ +public class DelegatingCodeCacheProvider extends DelegatingMetaAccessProvider implements CodeCacheProvider { + + public DelegatingCodeCacheProvider(CodeCacheProvider delegate) { + super(delegate); + } + + @Override + protected CodeCacheProvider delegate() { + return (CodeCacheProvider) super.delegate(); + } + + public InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult compResult) { + return delegate().addMethod(method, compResult); + } + + public String disassemble(CompilationResult compResult, InstalledCode installedCode) { + return delegate().disassemble(compResult, installedCode); + } + + public RegisterConfig lookupRegisterConfig() { + return delegate().lookupRegisterConfig(); + } + + public int getMinimumOutgoingSize() { + return delegate().getMinimumOutgoingSize(); + } + + public ForeignCallLinkage lookupForeignCall(ForeignCallDescriptor descriptor) { + return delegate().lookupForeignCall(descriptor); + } + + public boolean needsDataPatch(Constant constant) { + return delegate().needsDataPatch(constant); + } + + public TargetDescription getTarget() { + return delegate().getTarget(); + } +} diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/DeoptimizationAction.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/DeoptimizationAction.java Fri Sep 06 21:37:50 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2012, 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.code; - -/** - * Specifies the action that should be taken by the runtime in case a certain deoptimization is - * triggered. - */ -public enum DeoptimizationAction { - /** - * Do not invalidate the machine code. This is typically used when deoptimizing at a point where - * it's highly likely nothing will change the likelihood of the deoptimization happening again. - * For example, a compiled array allocation where the size is negative. - */ - None(false), - - /** - * Do not invalidate the machine code, but schedule a recompilation if this deoptimization is - * triggered too often. - */ - RecompileIfTooManyDeopts(true), - - /** - * Invalidate the machine code and reset the profiling information. - */ - InvalidateReprofile(true), - - /** - * Invalidate the machine code and immediately schedule a recompilation. This is typically used - * when deoptimizing to resolve an unresolved symbol in which case extra profiling is not - * required to determine that the deoptimization will not re-occur. - */ - InvalidateRecompile(true), - - /** - * Invalidate the machine code and stop compiling the outermost method of this compilation. - */ - InvalidateStopCompiling(true); - - private final boolean invalidatesCompilation; - - private DeoptimizationAction(boolean invalidatesCompilation) { - this.invalidatesCompilation = invalidatesCompilation; - } - - public boolean doesInvalidateCompilation() { - return invalidatesCompilation; - } - -} diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/SpeculationLog.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/SpeculationLog.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/SpeculationLog.java Wed Oct 02 13:26:31 2013 +0200 @@ -36,11 +36,11 @@ public static final int MAX_CACHE_SIZE = 1 << 15; - private List speculations = new ArrayList<>(); + private List speculations = new ArrayList<>(); private boolean[] map = new boolean[10]; - private Set snapshot = new HashSet<>(); + private Set snapshot = new HashSet<>(); - public short addSpeculation(DeoptimizationReason reason) { + private short addSpeculation(Object reason) { short index = (short) speculations.indexOf(reason); if (index != -1) { // Nothing to add, reason already registered. @@ -68,7 +68,10 @@ } } - public boolean maySpeculate(DeoptimizationReason reason) { - return !snapshot.contains(reason); + public Constant maySpeculate(Object reason) { + if (snapshot.contains(reason)) { + return null; + } + return Constant.forShort(addSpeculation(reason)); } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestMetaAccessProvider.java --- a/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestMetaAccessProvider.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestMetaAccessProvider.java Wed Oct 02 13:26:31 2013 +0200 @@ -107,15 +107,13 @@ @Test public void lookupArrayLengthTest() { for (Constant c : constants) { + Integer actual = runtime.lookupArrayLength(c); if (c.getKind() != Kind.Object || c.isNull() || !c.asObject().getClass().isArray()) { - try { - int length = runtime.lookupArrayLength(c); - fail("Expected " + IllegalArgumentException.class.getName() + " for " + c + ", not " + length); - } catch (IllegalArgumentException e) { - // pass - } + assertNull(actual); } else { - assertEquals(Array.getLength(c.asObject()), runtime.lookupArrayLength(c)); + assertNotNull(actual); + int actualInt = actual; + assertEquals(Array.getLength(c.asObject()), actualInt); } } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaMethod.java --- a/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaMethod.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaMethod.java Wed Oct 02 13:26:31 2013 +0200 @@ -265,7 +265,9 @@ ResolvedJavaMethod method2 = runtime.lookupJavaMethod(getClass().getDeclaredMethod("nullPointerExceptionOnFirstLine", Object.class, String.class)); assertEquals(0, method1.getMaxStackSize()); // some versions of javac produce bytecode with a stacksize of 2 for this method - assertTrue(3 == method2.getMaxStackSize() || 2 == method2.getMaxStackSize()); + // JSR 292 also sometimes need one more stack slot + int method2StackSize = method2.getMaxStackSize(); + assertTrue(2 <= method2StackSize && method2StackSize <= 4); } private Method findTestMethod(Method apiMethod) { diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaType.java --- a/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaType.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaType.java Wed Oct 02 13:26:31 2013 +0200 @@ -399,9 +399,11 @@ } for (Method m : c.getDeclaredMethods()) { if (!isStatic(m.getModifiers()) && !isPrivate(m.getModifiers())) { - Method overridden = vtable.methods.put(new NameAndSignature(m), m); - if (overridden != null) { - // println(m + " overrides " + overridden); + if (isAbstract(m.getModifiers())) { + // A subclass makes a concrete method in a superclass abstract + vtable.methods.remove(new NameAndSignature(m)); + } else { + vtable.methods.put(new NameAndSignature(m), m); } } } @@ -438,7 +440,13 @@ @Test public void resolveMethodTest() { for (Class c : classes) { - if (!c.isPrimitive() && !c.isInterface()) { + if (c.isInterface() || c.isPrimitive()) { + ResolvedJavaType type = runtime.lookupJavaType(c); + for (Method m : c.getDeclaredMethods()) { + ResolvedJavaMethod impl = type.resolveMethod(runtime.lookupJavaMethod(m)); + assertEquals(m.toString(), null, impl); + } + } else { ResolvedJavaType type = runtime.lookupJavaType(c); VTable vtable = getVTable(c); for (Method impl : vtable.methods.values()) { @@ -449,6 +457,11 @@ checkResolveMethod(type, m, i); } } + for (Method m : c.getDeclaredMethods()) { + ResolvedJavaMethod impl = type.resolveMethod(runtime.lookupJavaMethod(m)); + ResolvedJavaMethod expected = isAbstract(m.getModifiers()) ? null : impl; + assertEquals(type + " " + m.toString(), expected, impl); + } } } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/DelegatingMetaAccessProvider.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/DelegatingMetaAccessProvider.java Wed Oct 02 13:26:31 2013 +0200 @@ -0,0 +1,93 @@ +/* + * 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.meta; + +import java.lang.reflect.*; + +/** + * A {@link MetaAccessProvider} that delegates to another {@link MetaAccessProvider}. + */ +public class DelegatingMetaAccessProvider implements MetaAccessProvider { + + private final MetaAccessProvider delegate; + + public DelegatingMetaAccessProvider(MetaAccessProvider delegate) { + this.delegate = delegate; + } + + protected MetaAccessProvider delegate() { + return delegate; + } + + public ResolvedJavaType lookupJavaType(Class clazz) { + return delegate.lookupJavaType(clazz); + } + + public ResolvedJavaMethod lookupJavaMethod(Method reflectionMethod) { + return delegate.lookupJavaMethod(reflectionMethod); + } + + public ResolvedJavaMethod lookupJavaConstructor(Constructor reflectionConstructor) { + return delegate.lookupJavaConstructor(reflectionConstructor); + } + + public ResolvedJavaField lookupJavaField(Field reflectionField) { + return delegate.lookupJavaField(reflectionField); + } + + public ResolvedJavaType lookupJavaType(Constant constant) { + return delegate.lookupJavaType(constant); + } + + public Signature parseMethodDescriptor(String methodDescriptor) { + return delegate.parseMethodDescriptor(methodDescriptor); + } + + public boolean constantEquals(Constant x, Constant y) { + return delegate.constantEquals(x, y); + } + + public Integer lookupArrayLength(Constant array) { + return delegate.lookupArrayLength(array); + } + + public Constant readUnsafeConstant(Kind kind, Object base, long displacement, boolean compressible) { + return delegate.readUnsafeConstant(kind, base, displacement, compressible); + } + + public boolean isReexecutable(ForeignCallDescriptor descriptor) { + return delegate.isReexecutable(descriptor); + } + + public LocationIdentity[] getKilledLocations(ForeignCallDescriptor descriptor) { + return delegate.getKilledLocations(descriptor); + } + + public boolean canDeoptimize(ForeignCallDescriptor descriptor) { + return delegate.canDeoptimize(descriptor); + } + + public Constant encodeDeoptActionAndReason(DeoptimizationAction action, DeoptimizationReason reason) { + return delegate().encodeDeoptActionAndReason(action, reason); + } +} diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/DeoptimizationAction.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/DeoptimizationAction.java Wed Oct 02 13:26:31 2013 +0200 @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2012, 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.meta; + +/** + * Specifies the action that should be taken by the runtime in case a certain deoptimization is + * triggered. + */ +public enum DeoptimizationAction { + /** + * Do not invalidate the machine code. This is typically used when deoptimizing at a point where + * it's highly likely nothing will change the likelihood of the deoptimization happening again. + * For example, a compiled array allocation where the size is negative. + */ + None(false), + + /** + * Do not invalidate the machine code, but schedule a recompilation if this deoptimization is + * triggered too often. + */ + RecompileIfTooManyDeopts(true), + + /** + * Invalidate the machine code and reset the profiling information. + */ + InvalidateReprofile(true), + + /** + * Invalidate the machine code and immediately schedule a recompilation. This is typically used + * when deoptimizing to resolve an unresolved symbol in which case extra profiling is not + * required to determine that the deoptimization will not re-occur. + */ + InvalidateRecompile(true), + + /** + * Invalidate the machine code and stop compiling the outermost method of this compilation. + */ + InvalidateStopCompiling(true); + + private final boolean invalidatesCompilation; + + private DeoptimizationAction(boolean invalidatesCompilation) { + this.invalidatesCompilation = invalidatesCompilation; + } + + public boolean doesInvalidateCompilation() { + return invalidatesCompilation; + } + +} diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaAccessProvider.java --- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaAccessProvider.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaAccessProvider.java Wed Oct 02 13:26:31 2013 +0200 @@ -79,11 +79,11 @@ boolean constantEquals(Constant x, Constant y); /** - * Returns the length of an array that is wrapped in a {@link Constant} object. - * - * @throws IllegalArgumentException if {@code array} is not an array + * Returns the length of an array that is wrapped in a {@link Constant} object. If {@code array} + * is not an array, or the array length is not available at this point, the return value is + * {@code null}. */ - int lookupArrayLength(Constant array); + Integer lookupArrayLength(Constant array); /** * Reads a value of this kind using a base address and a displacement. @@ -113,4 +113,11 @@ * Determines if deoptimization can occur during a given foreign call. */ boolean canDeoptimize(ForeignCallDescriptor descriptor); + + /** + * Encodes a deoptimization action and a deoptimization reason in an integer value. + * + * @return the encoded value as an integer + */ + Constant encodeDeoptActionAndReason(DeoptimizationAction action, DeoptimizationReason reason); } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaField.java --- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaField.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaField.java Wed Oct 02 13:26:31 2013 +0200 @@ -50,17 +50,21 @@ boolean isSynthetic(); /** - * Gets the constant value of this field for a given object, if available. + * Gets the constant value of this field. Note that a {@code static final} field may not be + * considered constant if its declaring class is not yet initialized or if it is a well known + * field that can be updated via other means (e.g., {@link System#setOut(java.io.PrintStream)}). * * @param receiver object from which this field's value is to be read. This value is ignored if * this field is static. - * @return the constant value of this field or {@code null} if the constant value is not - * available + * @return the constant value of this field or {@code null} if this field is not considered + * constant by the runtime */ Constant readConstantValue(Constant receiver); /** - * Gets the current value of this field for a given object, if available. + * Gets the current value of this field for a given object, if available. There is no guarantee + * that the same value will be returned by this method for a field unless the field is + * considered to be {@link #readConstantValue(Constant)} by the runtime. * * @param receiver object from which this field's value is to be read. This value is ignored if * this field is static. diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaMethod.java --- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaMethod.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaMethod.java Wed Oct 02 13:26:31 2013 +0200 @@ -175,12 +175,14 @@ boolean canBeInlined(); /** - * Returns the LineNumberTable of this method. + * Returns the LineNumberTable of this method or null if this method does not have a line + * numbers table. */ LineNumberTable getLineNumberTable(); /** - * Returns the localvariable table of this method. + * Returns the local variable table of this method or null if this method does not have a local + * variable table. */ LocalVariableTable getLocalVariableTable(); diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaType.java --- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaType.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaType.java Wed Oct 02 13:26:31 2013 +0200 @@ -112,7 +112,7 @@ int getModifiers(); /** - * Checks whether this type is initialized. If a type is initialized it implies that is was + * Checks whether this type is initialized. If a type is initialized it implies that it was * {@link #isLinked() linked} and that the static initializer has run. * * @return {@code true} if this type is initialized @@ -205,10 +205,13 @@ /** * Resolves the method implementation for virtual dispatches on objects of this dynamic type. + * This resolution process only searches "up" the class hierarchy of this type. A broader search + * that also walks "down" the hierarchy is implemented by + * {@link #findUniqueConcreteMethod(ResolvedJavaMethod)}. * * @param method the method to select the implementation of - * @return the method implementation that would be selected at runtime, or {@code null} if the - * runtime cannot resolve the method at this point in time. + * @return the concrete method that would be selected at runtime, or {@code null} if there is no + * concrete implementation of {@code method} in this type or any of its superclasses */ ResolvedJavaMethod resolveMethod(ResolvedJavaMethod method); diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Assembler.java --- a/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Assembler.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Assembler.java Wed Oct 02 13:26:31 2013 +0200 @@ -747,7 +747,7 @@ emitOperandHelper(0, dst); } - private void jcc(ConditionFlag cc, int jumpTarget, boolean forceDisp32) { + public void jcc(ConditionFlag cc, int jumpTarget, boolean forceDisp32) { int shortSize = 2; int longSize = 6; long disp = jumpTarget - codeBuffer.position(); diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.asm.ptx/src/com/oracle/graal/asm/ptx/PTXAddress.java --- a/graal/com.oracle.graal.asm.ptx/src/com/oracle/graal/asm/ptx/PTXAddress.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.asm.ptx/src/com/oracle/graal/asm/ptx/PTXAddress.java Wed Oct 02 13:26:31 2013 +0200 @@ -22,6 +22,7 @@ */ package com.oracle.graal.asm.ptx; +import com.oracle.graal.lir.Variable; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; @@ -31,7 +32,7 @@ */ public final class PTXAddress extends AbstractAddress { - private final Register base; + private final Variable base; private final long displacement; /** @@ -39,7 +40,7 @@ * * @param base the base register */ - public PTXAddress(Register base) { + public PTXAddress(Variable base) { this(base, 0); } @@ -50,7 +51,7 @@ * @param base the base register * @param displacement the displacement */ - public PTXAddress(Register base, long displacement) { + public PTXAddress(Variable base, long displacement) { this.base = base; this.displacement = displacement; } @@ -59,7 +60,7 @@ * @return Base register that defines the start of the address computation. If not present, is * denoted by {@link Value#ILLEGAL}. */ - public Register getBase() { + public Variable getBase() { return base; } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.asm.ptx/src/com/oracle/graal/asm/ptx/PTXAssembler.java --- a/graal/com.oracle.graal.asm.ptx/src/com/oracle/graal/asm/ptx/PTXAssembler.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.asm.ptx/src/com/oracle/graal/asm/ptx/PTXAssembler.java Wed Oct 02 13:26:31 2013 +0200 @@ -22,7 +22,17 @@ */ package com.oracle.graal.asm.ptx; -import com.oracle.graal.api.code.*; +import static com.oracle.graal.api.code.ValueUtil.*; + +import com.oracle.graal.api.code.Register; +import com.oracle.graal.api.code.RegisterConfig; +import com.oracle.graal.api.code.TargetDescription; +import com.oracle.graal.api.meta.Constant; +import com.oracle.graal.api.meta.Kind; +import com.oracle.graal.api.meta.Value; +import com.oracle.graal.nodes.calc.Condition; +import com.oracle.graal.graph.GraalInternalError; +import com.oracle.graal.lir.Variable; public class PTXAssembler extends AbstractPTXAssembler { @@ -30,535 +40,549 @@ super(target); } - public final void at() { - emitString("@%p" + " " + ""); + public enum ConditionOperator { + // @formatter:off + + // Signed integer operators + S_EQ("eq"), + S_NE("ne"), + S_LT("lt"), + S_LE("le"), + S_GT("gt"), + S_GE("ge"), + + // Unsigned integer operators + U_EQ("eq"), + U_NE("ne"), + U_LO("lo"), + U_LS("ls"), + U_HI("hi"), + U_HS("hs"), + + // Bit-size integer operators + B_EQ("eq"), + B_NE("ne"), + + // Floating-point operators + F_EQ("eq"), + F_NE("ne"), + F_LT("lt"), + F_LE("le"), + F_GT("gt"), + F_GE("ge"), + + // Floating-point operators accepting NaN + F_EQU("equ"), + F_NEU("neu"), + F_LTU("ltu"), + F_LEU("leu"), + F_GTU("gtu"), + F_GEU("geu"), + + // Floating-point operators testing for NaN + F_NUM("num"), + F_NAN("nan"); + + // @formatter:on + + private final String operator; + + private ConditionOperator(String op) { + this.operator = op; + } + + public String getOperator() { + return operator; + } + } + + public static class StandardFormat { + + protected Kind valueKind; + protected Variable dest; + protected Value source1; + protected Value source2; + private boolean logicInstruction = false; + + public StandardFormat(Variable dst, Value src1, Value src2) { + setDestination(dst); + setSource1(src1); + setSource2(src2); + setKind(dst.getKind()); + + // testAdd2B fails this assertion + // assert valueKind == src1.getKind(); + } + + public void setKind(Kind k) { + valueKind = k; + } + + public void setDestination(Variable var) { + assert var != null; + dest = var; + } + + public void setSource1(Value val) { + assert val != null; + source1 = val; + } + + public void setSource2(Value val) { + assert val != null; + source2 = val; + } + + public void setLogicInstruction(boolean b) { + logicInstruction = b; + } + + public String typeForKind(Kind k) { + if (logicInstruction) { + switch (k.getTypeChar()) { + case 's': + return "b16"; + case 'i': + return "b32"; + case 'j': + return "b64"; + default: + throw GraalInternalError.shouldNotReachHere(); + } + } else { + switch (k.getTypeChar()) { + case 'z': + return "u8"; + case 'b': + return "s8"; + case 's': + return "s16"; + case 'c': + return "u16"; + case 'i': + return "s32"; + case 'f': + return "f32"; + case 'j': + return "s64"; + case 'd': + return "f64"; + case 'a': + return "u64"; + case '-': + return "u32"; + default: + throw GraalInternalError.shouldNotReachHere(); + } + } + } + + public String emit() { + return (typeForKind(valueKind) + emitRegister(dest, true) + emitValue(source1, true) + emitValue(source2, false) + ";"); + } + + public String emitValue(Value v, boolean comma) { + assert v != null; + + if (isConstant(v)) { + return (emitConstant(v)); + } else { + return (emitRegister((Variable) v, comma)); + } + } + + public String emitRegister(Variable v, boolean comma) { + return (" %r" + v.index + (comma ? "," : "")); + } + + public String emitConstant(Value v) { + Constant constant = (Constant) v; + + switch (v.getKind().getTypeChar()) { + case 'i': + return (String.valueOf((int) constant.asLong())); + case 'f': + return (String.valueOf(constant.asFloat())); + case 'j': + return (String.valueOf(constant.asLong())); + case 'd': + return (String.valueOf(constant.asDouble())); + default: + throw GraalInternalError.shouldNotReachHere(); + } + } } - public final void atq() { - emitString("@%q" + " " + ""); + public static class SingleOperandFormat { + + protected Variable dest; + protected Value source; + + public SingleOperandFormat(Variable dst, Value src) { + setDestination(dst); + setSource(src); + } + + public void setDestination(Variable var) { + dest = var; + } + + public void setSource(Value var) { + source = var; + } + + public String typeForKind(Kind k) { + switch (k.getTypeChar()) { + case 'z': + return "u8"; + case 'b': + return "s8"; + case 's': + return "s16"; + case 'c': + return "u16"; + case 'i': + return "s32"; + case 'f': + return "f32"; + case 'j': + return "s64"; + case 'd': + return "f64"; + case 'a': + return "u64"; + default: + throw GraalInternalError.shouldNotReachHere(); + } + } + + public String emit() { + return (typeForKind(dest.getKind()) + " " + emitVariable(dest) + ", " + emitValue(source) + ";"); + } + + public String emitValue(Value v) { + assert v != null; + + if (isConstant(v)) { + return (emitConstant(v)); + } else { + return (emitVariable((Variable) v)); + } + } + + public String emitConstant(Value v) { + Constant constant = (Constant) v; + + switch (v.getKind().getTypeChar()) { + case 'i': + return (String.valueOf((int) constant.asLong())); + case 'f': + return (String.valueOf(constant.asFloat())); + case 'j': + return (String.valueOf(constant.asLong())); + case 'd': + return (String.valueOf(constant.asDouble())); + default: + throw GraalInternalError.shouldNotReachHere(); + } + } + + public String emitVariable(Variable v) { + String name = v.getName(); + + if (name == null) { + return (" %r" + v.index); + } else { + return name; + } + } + } + + public static class ConversionFormat extends SingleOperandFormat { + + public ConversionFormat(Variable dst, Value src) { + super(dst, src); + } + + @Override + public String emit() { + return (typeForKind(dest.getKind()) + "." + typeForKind(source.getKind()) + " " + + emitVariable(dest) + ", " + emitValue(source) + ";"); + } + } + + public static class LoadStoreFormat extends StandardFormat { + + protected PTXStateSpace space; + + public LoadStoreFormat(PTXStateSpace space, Variable dst, Value src1, Value src2) { + super(dst, src1, src2); + setStateSpace(space); + } + + public void setStateSpace(PTXStateSpace ss) { + space = ss; + } + + public String emitAddress(Value var, Value val) { + assert var instanceof Variable; + assert val instanceof Constant; + Constant constant = (Constant) val; + return ("[" + emitRegister((Variable) var, false) + " + " + constant.asBoxedValue() + "]"); + } + + @Override + public String emitRegister(Variable var, boolean comma) { + /* if (space == Parameter) { + return ("param" + var.index); + } else { + return ("%r" + var.index); + } */ + return ("%r" + var.index); + } + + public String emit(boolean isLoad) { + if (isLoad) { + return (space.getStateName() + "." + typeForKind(valueKind) + " " + + emitRegister(dest, false) + ", " + emitAddress(source1, source2) + ";"); + } else { + return (space.getStateName() + "." + typeForKind(valueKind) + " " + + emitAddress(source1, source2) + ", " + emitRegister(dest, false) + ";"); + } + } + } + + public static class Add extends StandardFormat { + + public Add(Variable dst, Value src1, Value src2) { + super(dst, src1, src2); + } + + public void emit(PTXAssembler asm) { + asm.emitString("add." + super.emit()); + } + } + + public static class And extends StandardFormat { + + public And(Variable dst, Value src1, Value src2) { + super(dst, src1, src2); + setLogicInstruction(true); + } + + public void emit(PTXAssembler asm) { + asm.emitString("and." + super.emit()); + } + } + + public static class Div extends StandardFormat { + + public Div(Variable dst, Value src1, Value src2) { + super(dst, src1, src2); + } + + public void emit(PTXAssembler asm) { + asm.emitString("div." + super.emit()); + } + } + + public static class Mul extends StandardFormat { + + public Mul(Variable dst, Value src1, Value src2) { + super(dst, src1, src2); + } + + public void emit(PTXAssembler asm) { + asm.emitString("mul.lo." + super.emit()); + } + } + + public static class Or extends StandardFormat { + + public Or(Variable dst, Value src1, Value src2) { + super(dst, src1, src2); + setLogicInstruction(true); + } + + public void emit(PTXAssembler asm) { + asm.emitString("or." + super.emit()); + } + } + + public static class Rem extends StandardFormat { + + public Rem(Variable dst, Value src1, Value src2) { + super(dst, src1, src2); + } + + public void emit(PTXAssembler asm) { + asm.emitString("rem." + super.emit()); + } + } + + public static class Shl extends StandardFormat { + + public Shl(Variable dst, Value src1, Value src2) { + super(dst, src1, src2); + setLogicInstruction(true); + } + + public void emit(PTXAssembler asm) { + asm.emitString("shl." + super.emit()); + } + } + + public static class Shr extends StandardFormat { + + public Shr(Variable dst, Value src1, Value src2) { + super(dst, src1, src2); + } + + public void emit(PTXAssembler asm) { + asm.emitString("shr." + super.emit()); + } + } + + public static class Sub extends StandardFormat { + + public Sub(Variable dst, Value src1, Value src2) { + super(dst, src1, src2); + } + + public void emit(PTXAssembler asm) { + asm.emitString("sub." + super.emit()); + } + } + + public static class Ushr extends StandardFormat { + + public Ushr(Variable dst, Value src1, Value src2) { + super(dst, src1, src2); + setKind(Kind.Illegal); // get around not having an Unsigned Kind + } + + public void emit(PTXAssembler asm) { + asm.emitString("shr." + super.emit()); + } + } + + public static class Xor extends StandardFormat { + + public Xor(Variable dst, Value src1, Value src2) { + super(dst, src1, src2); + setLogicInstruction(true); + } + + public void emit(PTXAssembler asm) { + asm.emitString("xor." + super.emit()); + } } // Checkstyle: stop method name check - public final void add_f32(Register d, Register a, Register b) { - emitString("add.f32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); - } - - public final void add_f64(Register d, Register a, Register b) { - emitString("add.f64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); - } - - public final void add_s16(Register d, Register a, Register b) { - emitString("add.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); - } - - public final void add_s32(Register d, Register a, Register b) { - emitString("add.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); - } - - public final void add_s64(Register d, Register a, Register b) { - emitString("add.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); - } - - public final void add_s16(Register d, Register a, short s16) { - emitString("add.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s16 + ";" + ""); - } - - public final void add_s32(Register d, Register a, int s32) { - emitString("add.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s32 + ";" + ""); - } - - public final void add_s64(Register d, Register a, long s64) { - emitString("add.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s64 + ";" + ""); - } - - public final void add_f32(Register d, Register a, float f32) { - emitString("add.f32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + f32 + ";" + ""); - } - - public final void add_f64(Register d, Register a, double f64) { - emitString("add.f64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + f64 + ";" + ""); - } - - public final void add_u16(Register d, Register a, Register b) { - emitString("add.u16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); - } - - public final void add_u32(Register d, Register a, Register b) { - emitString("add.u32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); - } - - public final void add_u64(Register d, Register a, Register b) { - emitString("add.u64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); - } - - public final void add_u16(Register d, Register a, short u16) { - emitString("add.u16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u16 + ";" + ""); - } - - public final void add_u32(Register d, Register a, int u32) { - emitString("add.u32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u32 + ";" + ""); - } - - public final void add_u64(Register d, Register a, long u64) { - emitString("add.u64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u64 + ";" + ""); - } - - public final void add_sat_s32(Register d, Register a, Register b) { - emitString("add.sat.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); - } - - public final void add_sat_s32(Register d, Register a, int s32) { - emitString("add.sat.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s32 + ";" + ""); - } - - public final void and_b16(Register d, Register a, Register b) { - emitString("and.b16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); - } - - public final void and_b32(Register d, Register a, Register b) { - emitString("and.b32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); - } - - public final void and_b64(Register d, Register a, Register b) { - emitString("and.b64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); - } - - public final void and_b16(Register d, Register a, short b16) { - emitString("and.b16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + b16 + ";" + ""); - } - - public final void and_b32(Register d, Register a, int b32) { - emitString("and.b32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + b32 + ";" + ""); - } - - public final void and_b64(Register d, Register a, long b64) { - emitString("and.b64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + b64 + ";" + ""); - } - - public final void bra(String tgt) { - emitString("bra" + " " + tgt + ";" + ""); + public final void bra(String tgt, int pred) { + emitString((pred >= 0) ? "" : ("@%p" + pred + " ") + "bra" + " " + tgt + ";" + ""); } public final void bra_uni(String tgt) { emitString("bra.uni" + " " + tgt + ";" + ""); } - public final void cvt_s32_f32(Register d, Register a) { - emitString("cvt.s32.f32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); - } + public static class Cvt extends ConversionFormat { + + public Cvt(Variable dst, Variable src) { + super(dst, src); + } - public final void cvt_s64_f32(Register d, Register a) { - emitString("cvt.s64.f32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); + public void emit(PTXAssembler asm) { + asm.emitString("cvt." + super.emit()); + } } - - public final void cvt_f64_f32(Register d, Register a) { - emitString("cvt.f64.f32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); - } + + public static class Mov extends SingleOperandFormat { - public final void cvt_f32_f64(Register d, Register a) { - emitString("cvt.f32.f64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); - } - - public final void cvt_s32_f64(Register d, Register a) { - emitString("cvt.s32.f64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); - } + public Mov(Variable dst, Value src) { + super(dst, src); + } - public final void cvt_s64_f64(Register d, Register a) { - emitString("cvt.s64.f64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); + /* + public Mov(Variable dst, AbstractAddress src) { + throw GraalInternalError.unimplemented("AbstractAddress Mov"); + } + */ + + public void emit(PTXAssembler asm) { + asm.emitString("mov." + super.emit()); + } } - - public final void cvt_f32_s32(Register d, Register a) { - emitString("cvt.f32.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); - } + + public static class Neg extends SingleOperandFormat { - public final void cvt_f64_s32(Register d, Register a) { - emitString("cvt.f64.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); - } + public Neg(Variable dst, Variable src) { + super(dst, src); + } - public final void cvt_s8_s32(Register d, Register a) { - emitString("cvt.s8.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); - } - - public final void cvt_b16_s32(Register d, Register a) { - emitString("cvt.b16.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); - } - - public final void cvt_s64_s32(Register d, Register a) { - emitString("cvt.s64.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); + public void emit(PTXAssembler asm) { + asm.emitString("neg." + super.emit()); + } } + + public static class Not extends SingleOperandFormat { - public final void cvt_s32_s64(Register d, Register a) { - emitString("cvt.s32.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); - } + public Not(Variable dst, Variable src) { + super(dst, src); + } - public final void div_f32(Register d, Register a, Register b) { - emitString("div.f32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + public void emit(PTXAssembler asm) { + asm.emitString("not." + super.emit()); + } } + + public static class Ld extends LoadStoreFormat { - public final void div_f64(Register d, Register a, Register b) { - emitString("div.f32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); - } + public Ld(PTXStateSpace space, Variable dst, Variable src1, Value src2) { + super(space, dst, src1, src2); + } - public final void div_s16(Register d, Register a, Register b) { - emitString("div.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); + public void emit(PTXAssembler asm) { + asm.emitString("ld." + super.emit(true)); + } } - public final void div_s32(Register d, Register a, Register b) { - emitString("div.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); - } - - public final void div_s64(Register d, Register a, Register b) { - emitString("div.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); - } - - public final void div_s16(Register d, Register a, short s16) { - emitString("div.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s16 + ";" + ""); - } - - public final void div_s32(Register d, Register a, int s32) { - emitString("div.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s32 + ";" + ""); - } - - public final void div_s32(Register d, int s32, Register b) { - emitString("div.s32" + " " + "%r" + d.encoding() + ", " + s32 + ", %r" + b.encoding() + ";" + ""); - } - - public final void div_f32(Register d, float f32, Register b) { - emitString("div.f32" + " " + "%r" + d.encoding() + ", " + f32 + ", %r" + b.encoding() + ";" + ""); - } - - public final void div_f64(Register d, double f64, Register b) { - emitString("div.f64" + " " + "%r" + d.encoding() + ", " + f64 + ", %r" + b.encoding() + ";" + ""); - } + public static class St extends LoadStoreFormat { - public final void div_s64(Register d, Register a, long s64) { - emitString("div.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s64 + ";" + ""); - } - - public final void div_f32(Register d, Register a, float f32) { - emitString("div.f32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + f32 + ";" + ""); - } - - public final void div_f64(Register d, Register a, double f64) { - emitString("div.f64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + f64 + ";" + ""); - } - - public final void div_u16(Register d, Register a, Register b) { - emitString("div.u16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); - } + public St(PTXStateSpace space, Variable dst, Variable src1, Value src2) { + super(space, dst, src1, src2); + } - public final void div_u32(Register d, Register a, Register b) { - emitString("div.u32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); - } - - public final void div_u64(Register d, Register a, Register b) { - emitString("div.u64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); - } - - public final void div_u16(Register d, Register a, short u16) { - emitString("div.u16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u16 + ";" + ""); - } - - public final void div_u32(Register d, Register a, int u32) { - emitString("div.u32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u32 + ";" + ""); - } - - public final void div_u64(Register d, Register a, long u64) { - emitString("div.u64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u64 + ";" + ""); + public void emit(PTXAssembler asm) { + asm.emitString("st." + super.emit(false)); + } } public final void exit() { emitString("exit;" + " " + ""); } - public final void ld_global_b8(Register d, Register a, long immOff) { - emitString("ld.global.b8" + " " + "%r" + d.encoding() + ", [" + a + " + " + immOff + "]" + ";" + ""); - } - - public final void ld_global_b16(Register d, Register a, long immOff) { - emitString("ld.global.b16" + " " + "%r" + d.encoding() + ", [" + a + " + " + immOff + "]" + ";" + ""); - } - - public final void ld_global_b32(Register d, Register a, long immOff) { - emitString("ld.global.b32" + " " + "%r" + d.encoding() + ", [" + a + " + " + immOff + "]" + ";" + ""); - } - - public final void ld_global_b64(Register d, Register a, long immOff) { - emitString("ld.global.b64" + " " + "%r" + d.encoding() + ", [" + a + " + " + immOff + "]" + ";" + ""); - } - - public final void ld_global_u8(Register d, Register a, long immOff) { - emitString("ld.global.u8" + " " + "%r" + d.encoding() + ", [" + a + " + " + immOff + "]" + ";" + ""); - } - - public final void ld_global_u16(Register d, Register a, long immOff) { - emitString("ld.global.u16" + " " + "%r" + d.encoding() + ", [" + a + " + " + immOff + "]" + ";" + ""); - } - - public final void ld_global_u32(Register d, Register a, long immOff) { - emitString("ld.global.u32" + " " + "%r" + d.encoding() + ", [" + a + " + " + immOff + "]" + ";" + ""); - } - - public final void ld_global_u64(Register d, Register a, long immOff) { - emitString("ld.global.u64" + " " + "%r" + d.encoding() + ", [" + a + " + " + immOff + "]" + ";" + ""); - } + public static class Param extends SingleOperandFormat { - public final void ld_global_s8(Register d, Register a, long immOff) { - emitString("ld.global.s8" + " " + "%r" + d.encoding() + ", [" + a + " + " + immOff + "]" + ";" + ""); - } - - public final void ld_global_s16(Register d, Register a, long immOff) { - emitString("ld.global.s16" + " " + "%r" + d.encoding() + ", [" + a + " + " + immOff + "]" + ";" + ""); - } - - public final void ld_global_s32(Register d, Register a, long immOff) { - emitString("ld.global.s32" + " " + "%r" + d.encoding() + ", [" + a + " + " + immOff + "]" + ";" + ""); - } - - public final void ld_global_s64(Register d, Register a, long immOff) { - emitString("ld.global.s64" + " " + "%r" + d.encoding() + ", [" + a + " + " + immOff + "]" + ";" + ""); - } - - public final void ld_global_f32(Register d, Register a, long immOff) { - emitString("ld.global.f32" + " " + "%r" + d.encoding() + ", [" + a + " + " + immOff + "]" + ";" + ""); - } - - public final void ld_global_f64(Register d, Register a, long immOff) { - emitString("ld.global.f64" + " " + "%r" + d.encoding() + ", [" + a + " + " + immOff + "]" + ";" + ""); - } - - // Load from state space to destination register - public final void ld_from_state_space(String s, Register d, Register a, long immOff) { - emitString("ld" + s + " " + "%r" + d.encoding() + ", [" + a + " + " + immOff + "]" + ";" + ""); - } - - // Load return address from return parameter which is in .param state space - public final void ld_return_address(String s, Register d, Register a, long immOff) { - emitString("ld.param." + s + " " + "%r" + d.encoding() + ", [" + a + " + " + immOff + "]" + ";" + ""); - } - - public final void mov_b16(Register d, Register a) { - emitString("mov.b16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); - } + private boolean lastParameter; - public final void mov_b32(Register d, Register a) { - emitString("mov.b32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); - } - - public final void mov_b64(Register d, Register a) { - emitString("mov.b64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); - } - - public final void mov_u16(Register d, Register a) { - emitString("mov.u16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); - } - - public final void mov_u32(Register d, Register a) { - emitString("mov.u32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); - } - - public final void mov_u64(Register d, Register a) { - emitString("mov.u64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); - } - - public final void mov_u64(@SuppressWarnings("unused") Register d, @SuppressWarnings("unused") AbstractAddress a) { - // emitString("mov.u64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); - } - - public final void mov_s16(Register d, Register a) { - emitString("mov.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); - } - - public final void mov_s32(Register d, Register a) { - emitString("mov.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); - } - - public final void mov_s64(Register d, Register a) { - emitString("mov.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); - } - - public final void mov_f32(Register d, Register a) { - emitString("mov.f32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); - } - - public final void mov_f64(Register d, Register a) { - emitString("mov.f64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); - } - - public final void mov_b16(Register d, short b16) { - emitString("mov.b16" + " " + "%r" + d.encoding() + ", " + b16 + ";" + ""); - } - - public final void mov_b32(Register d, int b32) { - emitString("mov.b32" + " " + "%r" + d.encoding() + ", " + b32 + ";" + ""); - } - - public final void mov_b64(Register d, long b64) { - emitString("mov.b64" + " " + "%r" + d.encoding() + ", " + b64 + ";" + ""); - } - - public final void mov_u16(Register d, short u16) { - emitString("mov.u16" + " " + "%r" + d.encoding() + ", " + u16 + ";" + ""); - } - - public final void mov_u32(Register d, int u32) { - emitString("mov.u32" + " " + "%r" + d.encoding() + ", " + u32 + ";" + ""); - } - - public final void mov_u64(Register d, long u64) { - emitString("mov.u64" + " " + "%r" + d.encoding() + ", " + u64 + ";" + ""); - } - - public final void mov_s16(Register d, short s16) { - emitString("mov.s16" + " " + "%r" + d.encoding() + ", " + s16 + ";" + ""); - } + public Param(Variable d, boolean lastParam) { + super(d, null); + setLastParameter(lastParam); + } - public final void mov_s32(Register d, int s32) { - emitString("mov.s32" + " " + "%r" + d.encoding() + ", " + s32 + ";" + ""); - } - - public final void mov_s64(Register d, long s64) { - emitString("mov.s64" + " " + "%r" + d.encoding() + ", " + s64 + ";" + ""); - } - - public final void mov_f32(Register d, float f32) { - emitString("mov.f32" + " " + "%r" + d.encoding() + ", " + f32 + ";" + ""); - } - - public final void mov_f64(Register d, double f64) { - emitString("mov.f64" + " " + "%r" + d.encoding() + ", " + f64 + ";" + ""); - } - - public final void mul_lo_f32(Register d, Register a, Register b) { - emitString("mul.lo.f32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); - } - - public final void mul_lo_f64(Register d, Register a, Register b) { - emitString("mul.lo.f64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); - } - - public final void mul_lo_s16(Register d, Register a, Register b) { - emitString("mul.lo.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); - } - - public final void mul_lo_s32(Register d, Register a, Register b) { - emitString("mul.lo.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); - } - - public final void mul_lo_s64(Register d, Register a, Register b) { - emitString("mul.lo.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); - } - - public final void mul_lo_s16(Register d, Register a, short s16) { - emitString("mul.lo.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s16 + ";" + ""); - } - - public final void mul_lo_s32(Register d, Register a, int s32) { - emitString("mul.lo.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s32 + ";" + ""); - } - - public final void mul_lo_s64(Register d, Register a, long s64) { - emitString("mul.lo.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s64 + ";" + ""); - } - - public final void mul_lo_f32(Register d, Register a, float f32) { - emitString("mul.lo.f32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + f32 + ";" + ""); - } - - public final void mul_lo_f64(Register d, Register a, double f64) { - emitString("mul.lo.f64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + f64 + ";" + ""); - } - - public final void mul_lo_u16(Register d, Register a, Register b) { - emitString("mul.lo.u16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); - } - - public final void mul_lo_u32(Register d, Register a, Register b) { - emitString("mul.lo.u32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); - } - - public final void mul_lo_u64(Register d, Register a, Register b) { - emitString("mul.lo.u64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); - } - - public final void mul_lo_u16(Register d, Register a, short u16) { - emitString("mul.lo.u16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u16 + ";" + ""); - } + public void setLastParameter(boolean value) { + lastParameter = value; + } - public final void mul_lo_u32(Register d, Register a, int u32) { - emitString("mul.lo.u32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u32 + ";" + ""); - } - - public final void mul_lo_u64(Register d, Register a, long u64) { - emitString("mul.lo.u64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u64 + ";" + ""); - } - - public final void neg_f32(Register d, Register a) { - emitString("neg.f32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); - } - - public final void neg_f64(Register d, Register a) { - emitString("neg.f64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); - } - - public final void neg_s16(Register d, Register a) { - emitString("neg.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); - } - - public final void neg_s32(Register d, Register a) { - emitString("neg.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); - } - - public final void neg_s64(Register d, Register a) { - emitString("neg.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); - } - - public final void not_s16(Register d, Register a) { - emitString("not.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); - } - - public final void not_s32(Register d, Register a) { - emitString("not.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); - } + public String emitParameter(Variable v) { + return (" %r" + v.index); + } - public final void not_s64(Register d, Register a) { - emitString("not.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); - } - - public final void or_b16(Register d, Register a, Register b) { - emitString("or.b16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); - } - - public final void or_b32(Register d, Register a, Register b) { - emitString("or.b32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); - } - - public final void or_b64(Register d, Register a, Register b) { - emitString("or.b64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); - } - - public final void or_b16(Register d, Register a, short b16) { - emitString("or.b16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + b16 + ";" + ""); - } - - public final void or_b32(Register d, Register a, int b32) { - emitString("or.b32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + b32 + ";" + ""); - } - - public final void or_b64(Register d, Register a, long b64) { - emitString("or.b64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + b64 + ";" + ""); - } - - public final void param_8_decl(Register d, boolean lastParam) { - emitString(".param" + " " + ".s8" + " " + d + (lastParam ? "" : ",")); - } - - public final void param_32_decl(Register d, boolean lastParam) { - emitString(".param" + " " + ".s32" + " " + d + (lastParam ? "" : ",")); - } - - public final void param_64_decl(Register d, boolean lastParam) { - emitString(".param" + " " + ".s64" + " " + d + (lastParam ? "" : ",")); + public void emit(PTXAssembler asm) { + asm.emitString(".param ." + typeForKind(dest.getKind()) + emitParameter(dest) + (lastParameter ? "" : ",")); + } } public final void popc_b32(Register d, Register a) { @@ -569,54 +593,6 @@ emitString("popc.b64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + ""); } - public final void rem_s16(Register d, Register a, Register b) { - emitString("rem.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); - } - - public final void rem_s32(Register d, Register a, Register b) { - emitString("rem.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); - } - - public final void rem_s64(Register d, Register a, Register b) { - emitString("rem.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); - } - - public final void rem_s16(Register d, Register a, short s16) { - emitString("rem.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s16 + ";" + ""); - } - - public final void rem_s32(Register d, Register a, int s32) { - emitString("rem.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s32 + ";" + ""); - } - - public final void rem_s64(Register d, Register a, long s64) { - emitString("rem.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s64 + ";" + ""); - } - - public final void rem_u16(Register d, Register a, Register b) { - emitString("rem.u16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); - } - - public final void rem_u32(Register d, Register a, Register b) { - emitString("rem.u32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); - } - - public final void rem_u64(Register d, Register a, Register b) { - emitString("rem.u64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); - } - - public final void rem_u16(Register d, Register a, short u16) { - emitString("rem.u16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u16 + ";" + ""); - } - - public final void rem_u32(Register d, Register a, int u32) { - emitString("rem.u32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u32 + ";" + ""); - } - - public final void rem_u64(Register d, Register a, long u64) { - emitString("rem.u64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u64 + ";" + ""); - } - public final void ret() { emitString("ret;" + " " + ""); } @@ -625,501 +601,168 @@ emitString("ret.uni;" + " " + ""); } - public final void setp_eq_f32(Register a, Register b) { - emitString("setp.eq.f32" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); - } - - public final void setp_ne_f32(Register a, Register b) { - emitString("setp.ne.f32" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); - } - - public final void setp_lt_f32(Register a, Register b) { - emitString("setp.lt.f32" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); - } + public static class Setp { - public final void setp_le_f32(Register a, Register b) { - emitString("setp.le.f32" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); - } - - public final void setp_gt_f32(Register a, Register b) { - emitString("setp.gt.f32" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); - } - - public final void setp_ge_f32(Register a, Register b) { - emitString("setp.ge.f32" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); - } - - public final void setp_eq_f32(float f32, Register b) { - emitString("setp.eq.f32" + " " + "%p" + ", " + f32 + ", %r" + b.encoding() + ";" + ""); - } + private ConditionOperator operator; + private Value first, second; + private Kind kind; + private int predicate; - public final void setp_ne_f32(float f32, Register b) { - emitString("setp.ne.f32" + " " + "%p" + ", " + f32 + ", %r" + b.encoding() + ";" + ""); - } - - public final void setp_lt_f32(float f32, Register b) { - emitString("setp.lt.f32" + " " + "%p" + ", " + f32 + ", %r" + b.encoding() + ";" + ""); - } - - public final void setp_le_f32(float f32, Register b) { - emitString("setp.le.f32" + " " + "%p" + ", " + f32 + ", %r" + b.encoding() + ";" + ""); - } - - public final void setp_gt_f32(float f32, Register b) { - emitString("setp.gt.f32" + " " + "%p" + ", " + f32 + ", %r" + b.encoding() + ";" + ""); - } - - public final void setp_ge_f32(float f32, Register b) { - emitString("setp.ge.f32" + " " + "%p" + ", " + f32 + ", %r" + b.encoding() + ";" + ""); - } - - public final void setp_eq_f64(double f64, Register b) { - emitString("setp.eq.f64" + " " + "%p" + ", " + f64 + ", %r" + b.encoding() + ";" + ""); - } - - public final void setp_ne_f64(double f64, Register b) { - emitString("setp.ne.f64" + " " + "%p" + ", " + f64 + ", %r" + b.encoding() + ";" + ""); - } - - public final void setp_lt_f64(double f64, Register b) { - emitString("setp.lt.f64" + " " + "%p" + ", " + f64 + ", %r" + b.encoding() + ";" + ""); - } + public Setp(Condition condition, Value first, Value second, int predicateRegisterNumber) { + setFirst(first); + setSecond(second); + setPredicate(predicateRegisterNumber); + setKind(); + setConditionOperator(operatorForConditon(condition)); + } - public final void setp_le_f64(double f64, Register b) { - emitString("setp.le.f64" + " " + "%p" + ", " + f64 + ", %r" + b.encoding() + ";" + ""); - } - - public final void setp_gt_f64(double f64, Register b) { - emitString("setp.gt.f64" + " " + "%p" + ", " + f64 + ", %r" + b.encoding() + ";" + ""); - } - - public final void setp_ge_f64(double f64, Register b) { - emitString("setp.ge.f64" + " " + "%p" + ", " + f64 + ", %r" + b.encoding() + ";" + ""); - } + public void setFirst(Value v) { + first = v; + } - public final void setp_eq_s64(Register a, Register b) { - emitString("setp.eq.s64" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); - } - - public final void setp_eq_s64(long s64, Register b) { - emitString("setp.eq.s64" + " " + "%p" + ", " + s64 + ", %r" + b.encoding() + ";" + ""); - } - - public final void setp_eq_s32(Register a, Register b) { - emitString("setp.eq.s32" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); - } - - public final void setp_ne_s32(Register a, Register b) { - emitString("setp.ne.s32" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); - } + public void setSecond(Value v) { + second = v; + } - public final void setp_lt_s32(Register a, Register b) { - emitString("setp.lt.s32" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); - } - - public final void setp_le_s32(Register a, Register b) { - emitString("setp.le.s32" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); - } - - public final void setp_gt_s32(Register a, Register b) { - emitString("setp.gt.s32" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); - } - - public final void setp_ge_s32(Register a, Register b) { - emitString("setp.ge.s32" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); - } + public void setPredicate(int p) { + predicate = p; + } - public final void setp_eq_s32(Register a, int s32) { - emitString("setp.eq.s32" + " " + "%p" + ", %r" + a.encoding() + ", " + s32 + ";" + ""); - } - - public final void setp_ne_s32(Register a, int s32) { - emitString("setp.ne.s32" + " " + "%p" + ", %r" + a.encoding() + ", " + s32 + ";" + ""); - } + public void setConditionOperator(ConditionOperator co) { + operator = co; + } - public final void setp_lt_s32(Register a, int s32) { - emitString("setp.lt.s32" + " " + "%p" + ", %r" + a.encoding() + ", " + s32 + ";" + ""); - } - - public final void setp_le_s32(Register a, int s32) { - emitString("setp.le.s32" + " " + "%p" + ", %r" + a.encoding() + ", " + s32 + ";" + ""); - } + private ConditionOperator operatorForConditon(Condition condition) { + char typeChar = kind.getTypeChar(); - public final void setp_gt_s32(Register a, int s32) { - emitString("setp.gt.s32" + " " + "%p" + ", %r" + a.encoding() + ", " + s32 + ";" + ""); - } - - public final void setp_ge_s32(Register a, int s32) { - emitString("setp.ge.s32" + " " + "%p" + ", %r" + a.encoding() + ", " + s32 + ";" + ""); - } - - public final void setp_eq_s32(int s32, Register b) { - emitString("setp.eq.s32" + " " + "%p" + ", " + s32 + ", %r" + b.encoding() + ";" + ""); - } - - public final void setp_ne_s32(int s32, Register b) { - emitString("setp.ne.s32" + " " + "%p" + ", " + s32 + ", %r" + b.encoding() + ";" + ""); - } - - public final void setp_lt_s32(int s32, Register b) { - emitString("setp.lt.s32" + " " + "%p" + ", " + s32 + ", %r" + b.encoding() + ";" + ""); - } - - public final void setp_le_s32(int s32, Register b) { - emitString("setp.le.s32" + " " + "%p" + ", " + s32 + ", %r" + b.encoding() + ";" + ""); - } - - public final void setp_gt_s32(int s32, Register b) { - emitString("setp.gt.s32" + " " + "%p" + ", " + s32 + ", %r" + b.encoding() + ";" + ""); - } + switch (typeChar) { + case 'z': + case 'c': + case 'a': + // unsigned + switch (condition) { + case EQ: return ConditionOperator.U_EQ; + case NE: return ConditionOperator.U_NE; + case LT: return ConditionOperator.U_LO; + case LE: return ConditionOperator.U_LS; + case GT: return ConditionOperator.U_HI; + case GE: return ConditionOperator.U_HS; + default: + throw GraalInternalError.shouldNotReachHere(); + } + case 'b': + case 's': + case 'i': + case 'j': + // signed + switch (condition) { + case EQ: return ConditionOperator.S_EQ; + case NE: return ConditionOperator.S_NE; + case LT: return ConditionOperator.S_LT; + case LE: return ConditionOperator.S_LE; + case GT: return ConditionOperator.S_GT; + case GE: + case AE: + return ConditionOperator.S_GE; + default: + throw GraalInternalError.shouldNotReachHere(); + } + case 'f': + case 'd': + // floating point - do these need to accept NaN?? + switch (condition) { + case EQ: return ConditionOperator.F_EQ; + case NE: return ConditionOperator.F_NE; + case LT: return ConditionOperator.F_LT; + case LE: return ConditionOperator.F_LE; + case GT: return ConditionOperator.F_GT; + case GE: return ConditionOperator.F_GE; + default: + throw GraalInternalError.shouldNotReachHere(); + } + default: + throw GraalInternalError.shouldNotReachHere(); + } + } - public final void setp_ge_s32(int s32, Register b) { - emitString("setp.ge.s32" + " " + "%p" + ", " + s32 + ", %r" + b.encoding() + ";" + ""); - } - - public final void setp_eq_u32(Register a, Register b) { - emitString("setp.eq.u32" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); - } - - public final void setp_ne_u32(Register a, Register b) { - emitString("setp.ne.u32" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); - } - - public final void setp_lt_u32(Register a, Register b) { - emitString("setp.lt.u32" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); - } - - public final void setp_le_u32(Register a, Register b) { - emitString("setp.le.u32" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); - } - - public final void setp_gt_u32(Register a, Register b) { - emitString("setp.gt.u32" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); - } - - public final void setp_ge_u32(Register a, Register b) { - emitString("setp.ge.u32" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); - } - - public final void setp_eq_u32(Register a, int u32) { - emitString("setp.eq.u32" + " " + "%p" + ", %r" + a.encoding() + ", " + u32 + ";" + ""); - } + public void setKind() { + // assert isConstant(first) && isConstant(second) == false; - public final void setp_ne_u32(Register a, int u32) { - emitString("setp.ne.u32" + " " + "%p" + ", %r" + a.encoding() + ", " + u32 + ";" + ""); - } - - public final void setp_lt_u32(Register a, int u32) { - emitString("setp.lt.u32" + " " + "%p" + ", %r" + a.encoding() + ", " + u32 + ";" + ""); - } - - public final void setp_le_u32(Register a, int u32) { - emitString("setp.le.u32" + " " + "%p" + ", %r" + a.encoding() + ", " + u32 + ";" + ""); - } - - public final void setp_gt_u32(Register a, int u32) { - emitString("setp.gt.u32" + " " + "%p" + ", %r" + a.encoding() + ", " + u32 + ";" + ""); - } + if (isConstant(first)) { + kind = second.getKind(); + } else { + kind = first.getKind(); + } + } + + public String emitValue(Value v) { + assert v != null; - public final void setp_ge_u32(Register a, int u32) { - emitString("setp.ge.u32" + " " + "%p" + ", %r" + a.encoding() + ", " + u32 + ";" + ""); - } - - public final void setp_eq_u32(int u32, Register b) { - emitString("setp.eq.u32" + " " + "%p" + ", " + u32 + ", %r" + b.encoding() + ";" + ""); - } - - public final void setp_ne_u32(int u32, Register b) { - emitString("setp.ne.u32" + " " + "%p" + ", " + u32 + ", %r" + b.encoding() + ";" + ""); - } - - public final void setp_lt_u32(int u32, Register b) { - emitString("setp.lt.u32" + " " + "%p" + ", " + u32 + ", %r" + b.encoding() + ";" + ""); - } + if (isConstant(v)) { + return (", " + emitConstant(v)); + } else { + return (", " + emitVariable((Variable) v)); + } + } - public final void setp_le_u32(int u32, Register b) { - emitString("setp.le.u32" + " " + "%p" + ", " + u32 + ", %r" + b.encoding() + ";" + ""); - } - - public final void setp_gt_u32(int u32, Register b) { - emitString("setp.gt.u32" + " " + "%p" + ", " + u32 + ", %r" + b.encoding() + ";" + ""); - } - - public final void setp_ge_u32(int u32, Register b) { - emitString("setp.ge.u32" + " " + "%p" + ", " + u32 + ", %r" + b.encoding() + ";" + ""); - } + public String typeForKind(Kind k) { + switch (k.getTypeChar()) { + case 'z': + return "u8"; + case 'b': + return "s8"; + case 's': + return "s16"; + case 'c': + return "u16"; + case 'i': + return "s32"; + case 'f': + return "f32"; + case 'j': + return "s64"; + case 'd': + return "f64"; + case 'a': + return "u64"; + default: + throw GraalInternalError.shouldNotReachHere(); + } + } - // Shift left - only types supported are .b16, .b32 and .b64 - public final void shl_b16(Register d, Register a, Register b) { - emitString("shl.b16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); - } - - public final void shl_b32(Register d, Register a, Register b) { - emitString("shl.b32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); - } + public String emitConstant(Value v) { + Constant constant = (Constant) v; - public final void shl_b64(Register d, Register a, Register b) { - emitString("shl.b64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); - } + switch (v.getKind().getTypeChar()) { + case 'i': + return (String.valueOf((int) constant.asLong())); + case 'f': + return (String.valueOf(constant.asFloat())); + case 'j': + return (String.valueOf(constant.asLong())); + case 'd': + return (String.valueOf(constant.asDouble())); + default: + throw GraalInternalError.shouldNotReachHere(); + } + } + + public String emitVariable(Variable v) { + return ("%r" + v.index); + } - public final void shl_b16_const(Register d, Register a, int b) { - emitString("shl.b16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + b + ";" + ""); - } - - public final void shl_b32_const(Register d, Register a, int b) { - emitString("shl.b32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + b + ";" + ""); + public void emit(PTXAssembler asm) { + asm.emitString("setp." + operator.getOperator() + "." + typeForKind(kind) + + " %p" + predicate + emitValue(first) + emitValue(second) + ";"); + } } - - public final void shl_b64_const(Register d, Register a, int b) { - emitString("shl.b64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + b + ";" + ""); - } - - // Shift Right instruction - public final void shr_s16(Register d, Register a, Register b) { - emitString("shr.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); - } - - public final void shr_s32(Register d, Register a, Register b) { - emitString("shr.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); - } - - public final void shr_s64(Register d, Register a, Register b) { - emitString("shr.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); - } - - public final void shr_s16(Register d, Register a, int u32) { - emitString("shr.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u32 + ";" + ""); - } - - public final void shr_s32(Register d, Register a, int u32) { - emitString("shr.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u32 + ";" + ""); - } - - public final void shr_s64(Register d, Register a, int u32) { - emitString("shr.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u32 + ";" + ""); - } - - public final void shr_u16(Register d, Register a, Register b) { - emitString("shr.u16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); - } - - public final void shr_u32(Register d, Register a, Register b) { - emitString("shr.u32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); - } - - public final void shr_u64(Register d, Register a, Register b) { - emitString("shr.u64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); - } - - public final void shr_u16(Register d, Register a, int u32) { - emitString("shr.u16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u32 + ";" + ""); - } - - public final void shr_u32(Register d, Register a, int u32) { - emitString("shr.u32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u32 + ";" + ""); - } - - public final void shr_u64(Register d, Register a, long u64) { - emitString("shr.u64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u64 + ";" + ""); - } - - // Store in global state space - - public final void st_global_b8(Register a, long immOff, Register b) { - emitString("st.global.b8" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + ""); - } - - public final void st_global_b16(Register a, long immOff, Register b) { - emitString("st.global.b16" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + ""); - } - - public final void st_global_b32(Register a, long immOff, Register b) { - emitString("st.global.b32" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + ""); - } - - public final void st_global_b64(Register a, long immOff, Register b) { - emitString("st.global.b64" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + ""); - } - - public final void st_global_u8(Register a, long immOff, Register b) { - emitString("st.global.u8" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + ""); - } - - public final void st_global_u16(Register a, long immOff, Register b) { - emitString("st.global.u16" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + ""); - } - - public final void st_global_u32(Register a, long immOff, Register b) { - emitString("st.global.u32" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + ""); - } - - public final void st_global_u64(Register a, long immOff, Register b) { - emitString("st.global.u64" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + ""); - } - - public final void st_global_s8(Register a, long immOff, Register b) { - emitString("st.global.s8" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + ""); - } - - public final void st_global_s16(Register a, long immOff, Register b) { - emitString("st.global.s16" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + ""); - } - - public final void st_global_s32(Register a, long immOff, Register b) { - emitString("st.global.s32" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + ""); - } - - public final void st_global_s64(Register a, long immOff, Register b) { - emitString("st.global.s64" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + ""); - } - - public final void st_global_f32(Register a, long immOff, Register b) { - emitString("st.global.f32" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + ""); - } - - public final void st_global_f64(Register a, long immOff, Register b) { - emitString("st.global.f64" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + ""); - } - - // Store return value - public final void st_global_return_value_s8(Register a, long immOff, Register b) { - emitString("st.global.s8" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + ""); - } - - public final void st_global_return_value_s32(Register a, long immOff, Register b) { - emitString("st.global.s32" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + ""); - } - - public final void st_global_return_value_s64(Register a, long immOff, Register b) { - emitString("st.global.s64" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + ""); - } - - public final void st_global_return_value_f32(Register a, long immOff, Register b) { - emitString("st.global.f32" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + ""); - } - - public final void st_global_return_value_f64(Register a, long immOff, Register b) { - emitString("st.global.f64" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + ""); - } - - public final void st_global_return_value_u32(Register a, long immOff, Register b) { - emitString("st.global.u32" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + ""); - } - - public final void st_global_return_value_u64(Register a, long immOff, Register b) { - emitString("st.global.u64" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + ""); - } - - // Subtract instruction - - public final void sub_f32(Register d, Register a, Register b) { - emitString("sub.f32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); - } - - public final void sub_f64(Register d, Register a, Register b) { - emitString("sub.f64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); - } - - public final void sub_s16(Register d, Register a, Register b) { - emitString("sub.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); - } - - public final void sub_s32(Register d, Register a, Register b) { - emitString("sub.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); - } - - public final void sub_s64(Register d, Register a, Register b) { - emitString("sub.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); - } - - public final void sub_s16(Register d, Register a, short s16) { - emitString("sub.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s16 + ";" + ""); - } - - public final void sub_s32(Register d, Register a, int s32) { - emitString("sub.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s32 + ";" + ""); - } - - public final void sub_s64(Register d, Register a, int s32) { - emitString("sub.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s32 + ";" + ""); - } - - public final void sub_s64(Register d, Register a, long s64) { - emitString("sub.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s64 + ";" + ""); - } - - public final void sub_f32(Register d, Register a, float f32) { - emitString("sub.f32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + f32 + ";" + ""); - } - - public final void sub_f64(Register d, Register a, double f64) { - emitString("sub.f64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + f64 + ";" + ""); - } - - public final void sub_s16(Register d, short s16, Register b) { - emitString("sub.s16" + " " + "%r" + d.encoding() + ", " + s16 + ", %r" + b.encoding() + ";" + ""); - } - - public final void sub_s32(Register d, int s32, Register b) { - emitString("sub.s32" + " " + "%r" + d.encoding() + ", " + s32 + ", %r" + b.encoding() + ";" + ""); - } - - public final void sub_s64(Register d, long s64, Register b) { - emitString("sub.s64" + " " + "%r" + d.encoding() + ", " + s64 + ", %r" + b.encoding() + ";" + ""); - } - - public final void sub_f32(Register d, float f32, Register b) { - emitString("sub.f32" + " " + "%r" + d.encoding() + ", %r" + b.encoding() + ", " + f32 + ";" + ""); - } - - public final void sub_f64(Register d, double f64, Register b) { - emitString("sub.f64" + " " + "%r" + d.encoding() + ", %r" + b.encoding() + ", " + f64 + ";" + ""); - } - - public final void sub_sat_s32(Register d, Register a, Register b) { - emitString("sub.sat.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); - } - - public final void sub_sat_s32(Register d, Register a, int s32) { - emitString("sub.sat.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s32 + ";" + ""); - } - - public final void sub_sat_s32(Register d, int s32, Register b) { - emitString("sub.sat.s32" + " " + "%r" + d.encoding() + ", " + s32 + ", %r" + b.encoding() + ";" + ""); - } - - public final void xor_b16(Register d, Register a, Register b) { - emitString("xor.b16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); - } - - public final void xor_b32(Register d, Register a, Register b) { - emitString("xor.b32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); - } - - public final void xor_b64(Register d, Register a, Register b) { - emitString("xor.b64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + ""); - } - - public final void xor_b16(Register d, Register a, short b16) { - emitString("xor.b16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + b16 + ";" + ""); - } - - public final void xor_b32(Register d, Register a, int b32) { - emitString("xor.b32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + b32 + ";" + ""); - } - - public final void xor_b64(Register d, Register a, long b64) { - emitString("xor.b64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + b64 + ";" + ""); - } - @Override public PTXAddress makeAddress(Register base, int displacement) { - return new PTXAddress(base, displacement); + throw GraalInternalError.shouldNotReachHere(); } @Override public PTXAddress getPlaceholder() { - // TODO Auto-generated method stub return null; } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.asm.ptx/src/com/oracle/graal/asm/ptx/PTXStateSpace.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.asm.ptx/src/com/oracle/graal/asm/ptx/PTXStateSpace.java Wed Oct 02 13:26:31 2013 +0200 @@ -0,0 +1,49 @@ +/* + * 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.asm.ptx; + +/** + * Represents the various PTX state spaces. + */ +public enum PTXStateSpace { + + Parameter("param"), + + Shared("shared"), + + Local("local"), + + Global("global"), + + Const("const"); + + private final String stateName; + + private PTXStateSpace(String name) { + this.stateName = name; + } + + public String getStateName() { + return stateName; + } +} diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAddress.java --- a/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAddress.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAddress.java Wed Oct 02 13:26:31 2013 +0200 @@ -121,7 +121,7 @@ throw GraalInternalError.shouldNotReachHere("address has index register"); } // TODO Should we also hide the register save area size here? - if (getBase() == sp || getBase() == fp) { + if (getBase().equals(sp) || getBase().equals(fp)) { return displacement + STACK_BIAS; } return displacement; diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java --- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java Wed Oct 02 13:26:31 2013 +0200 @@ -890,6 +890,6 @@ @Override public void visitInfopointNode(InfopointNode i) { - append(new InfopointOp(stateFor(i.stateAfter(), DeoptimizationReason.None), i.reason)); + append(new InfopointOp(stateFor(i.getState()), i.reason)); } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StaticDoubleSpillTest.java --- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StaticDoubleSpillTest.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StaticDoubleSpillTest.java Wed Oct 02 13:26:31 2013 +0200 @@ -25,7 +25,8 @@ import java.util.*; import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; -import org.junit.Test; + +import org.junit.*; /** * Tests the spilling of double variables into memory. @@ -118,6 +119,7 @@ } // Marked to only run on hardware until simulator spill bug is fixed. + @Ignore @Test public void test() { testGeneratedHsail(); diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StaticIntSpillTest.java --- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StaticIntSpillTest.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StaticIntSpillTest.java Wed Oct 02 13:26:31 2013 +0200 @@ -25,7 +25,8 @@ import java.util.*; import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; -import org.junit.Test; + +import org.junit.*; /** * Tests the spilling of integers into memory. @@ -87,6 +88,7 @@ } // Marked to only run on hardware until simulator spill bug is fixed. + @Ignore @Test public void test() { testGeneratedHsail(); diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILBackend.java --- a/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILBackend.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILBackend.java Wed Oct 02 13:26:31 2013 +0200 @@ -60,8 +60,16 @@ } @Override + public boolean shouldAllocateRegisters() { + return true; + } + + /** + * Use the HSAIL register set when the compilation target is HSAIL. + */ + @Override public FrameMap newFrameMap() { - return new HSAILFrameMap(runtime(), target, runtime().lookupRegisterConfig()); + return new HSAILFrameMap(runtime(), target, new HSAILRegisterConfig()); } @Override diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILCompilationResult.java --- a/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILCompilationResult.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILCompilationResult.java Wed Oct 02 13:26:31 2013 +0200 @@ -23,33 +23,25 @@ package com.oracle.graal.compiler.hsail; -import static com.oracle.graal.api.code.CodeUtil.*; - +import java.lang.reflect.*; import java.util.logging.*; import com.oracle.graal.api.code.*; -import com.oracle.graal.api.code.CallingConvention.*; -import com.oracle.graal.api.runtime.Graal; -import com.oracle.graal.compiler.GraalCompiler; -import com.oracle.graal.java.GraphBuilderConfiguration; -import com.oracle.graal.java.GraphBuilderPhase; -import com.oracle.graal.nodes.StructuredGraph; -import com.oracle.graal.nodes.spi.GraalCodeCacheProvider; -import com.oracle.graal.phases.OptimisticOptimizations; -import com.oracle.graal.phases.PhasePlan; -import com.oracle.graal.phases.PhasePlan.PhasePosition; +import com.oracle.graal.api.code.CallingConvention.Type; import com.oracle.graal.api.meta.*; -import com.oracle.graal.nodes.type.*; -import com.oracle.graal.graph.GraalInternalError; +import com.oracle.graal.api.runtime.*; +import com.oracle.graal.compiler.*; +import com.oracle.graal.compiler.target.*; import com.oracle.graal.debug.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.hsail.*; +import com.oracle.graal.java.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; import com.oracle.graal.phases.*; +import com.oracle.graal.phases.PhasePlan.PhasePosition; import com.oracle.graal.phases.tiers.*; -import com.oracle.graal.nodes.spi.Replacements; -import com.oracle.graal.compiler.target.Backend; -import com.oracle.graal.hsail.*; - -import java.lang.reflect.Method; /** * Class that represents a HSAIL compilation result. Includes the compiled HSAIL code. @@ -96,6 +88,33 @@ return getHSAILCompilationResult(graph); } + /** + * HSAIL doesn't have a calling convention as such. Function arguments are actually passed in + * memory but then loaded into registers in the function body. This routine makes sure that + * arguments to a kernel or function are loaded (by the kernel or function body) into registers + * of the appropriate sizes. For example, int and float parameters should appear in S registers, + * whereas double and long parameters should appear in d registers. + */ + public static CallingConvention getHSAILCallingConvention(CallingConvention.Type type, TargetDescription target, ResolvedJavaMethod method, boolean stackOnly) { + Signature sig = method.getSignature(); + JavaType retType = sig.getReturnType(null); + int sigCount = sig.getParameterCount(false); + JavaType[] argTypes; + int argIndex = 0; + if (!Modifier.isStatic(method.getModifiers())) { + argTypes = new JavaType[sigCount + 1]; + argTypes[argIndex++] = method.getDeclaringClass(); + } else { + argTypes = new JavaType[sigCount]; + } + for (int i = 0; i < sigCount; i++) { + argTypes[argIndex++] = sig.getParameterType(i, null); + } + + RegisterConfig registerConfig = new HSAILRegisterConfig(); + return registerConfig.getCallingConvention(type, retType, argTypes, target, stackOnly); + } + public static HSAILCompilationResult getHSAILCompilationResult(StructuredGraph graph) { Debug.dump(graph, "Graph"); TargetDescription target = new TargetDescription(new HSAIL(), true, 8, 0, true); @@ -105,7 +124,7 @@ phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase); phasePlan.addPhase(PhasePosition.AFTER_PARSING, new HSAILPhase()); new HSAILPhase().apply(graph); - CallingConvention cc = getCallingConvention(runtime, Type.JavaCallee, graph.method(), false); + CallingConvention cc = getHSAILCallingConvention(Type.JavaCallee, target, graph.method(), false); try { CompilationResult compResult = GraalCompiler.compileGraph(graph, cc, graph.method(), runtime, replacements, hsailBackend, target, null, phasePlan, OptimisticOptimizations.NONE, new SpeculationLog(), suitesProvider.getDefaultSuites(), new CompilationResult()); diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILLIRGenerator.java --- a/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILLIRGenerator.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILLIRGenerator.java Wed Oct 02 13:26:31 2013 +0200 @@ -143,12 +143,12 @@ } else { baseRegister = load(base); } - } else if (base == Value.ILLEGAL) { + } else if (base.equals(Value.ILLEGAL)) { baseRegister = Value.ILLEGAL; } else { baseRegister = asAllocatable(base); } - if (index != Value.ILLEGAL) { + if (!index.equals(Value.ILLEGAL)) { if (isConstant(index)) { finalDisp += asConstant(index).asLong() * scale; } else { @@ -160,7 +160,7 @@ } else { indexRegister = convertedIndex; } - if (baseRegister == Value.ILLEGAL) { + if (baseRegister.equals(Value.ILLEGAL)) { baseRegister = asAllocatable(indexRegister); } else { baseRegister = emitAdd(baseRegister, indexRegister); @@ -579,7 +579,7 @@ } @Override - public void emitDeoptimize(DeoptimizationAction action, DeoptimizingNode deopting) { + public void emitDeoptimize(Value actionAndReason, DeoptimizingNode deopting) { append(new ReturnOp(Value.ILLEGAL)); } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/ArrayPTXTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/ArrayPTXTest.java Wed Oct 02 13:26:31 2013 +0200 @@ -0,0 +1,91 @@ +/* + * 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.compiler.ptx.test; + +import static com.oracle.graal.lir.ptx.ThreadDimension.*; + +import com.oracle.graal.lir.ptx.ParallelOver; +import com.oracle.graal.lir.ptx.Warp; + +import java.lang.reflect.Method; +import java.util.Arrays; +import org.junit.Test; + +public class ArrayPTXTest extends PTXTestBase { + + @Test + public void testArray() { + int[] array1 = { + 1, 2, 3, 4, 5, 6, 7, 8, 9 + }; + int[] array2 = { + 1, 2, 3, 4, 5, 6, 7, 8, 9 + }; + int[] array3 = { + 1, 2, 3, 4, 5, 6, 7, 8, 9 + }; + + invoke(compile("testStoreArray1I"), array1, 2); + printReport("testStoreArray1I: " + Arrays.toString(array1)); + + invoke(compile("testStoreArrayWarp0"), array2, 2); + printReport("testStoreArrayWarp0: " + Arrays.toString(array2)); + + invoke(compile("testStoreArrayWarp1I"), array3, 2); + printReport("testStoreArrayWarp1I: " + Arrays.toString(array3)); + + } + + public static void testStoreArray1I(int[] array, int i) { + array[i] = 42; + } + + public static void testStoreArrayWarp0(int[] array, + @Warp(dimension = X) int i) { + array[i] = 42; + } + + public static void testStoreArrayWarp1I(@ParallelOver(dimension = X) int[] array, + @Warp(dimension = X) int i) { + array[i] = 42; + } + + + public static void printReport(String message) { + // CheckStyle: stop system..print check + System.out.println(message); + // CheckStyle: resume system..print check + } + + public static void main(String[] args) { + ArrayPTXTest test = new ArrayPTXTest(); + for (Method m : ArrayPTXTest.class.getMethods()) { + String name = m.getName(); + if (m.getAnnotation(Test.class) == null && name.startsWith("test")) { + // CheckStyle: stop system..print check + System.out.println(name + ": \n" + new String(test.compile(name).getTargetCode())); + // CheckStyle: resume system..print check + } + } + } +} diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/ArrayTest.java --- a/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/ArrayTest.java Fri Sep 06 21:37:50 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,117 +0,0 @@ -/* - * 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.compiler.ptx.test; - -import java.lang.reflect.Method; - -import org.junit.*; - -public class ArrayTest extends PTXTestBase { - - @Ignore - @Test - public void testArray() { - compile("testArray1I"); - compile("testArray1J"); - compile("testArray1B"); - compile("testArray1S"); - compile("testArray1C"); - compile("testArray1F"); - compile("testArray1D"); - compile("testArray1L"); - compile("testStoreArray1I"); - compile("testStoreArray1J"); - compile("testStoreArray1B"); - compile("testStoreArray1S"); - compile("testStoreArray1F"); - compile("testStoreArray1D"); - } - - public static int testArray1I(int[] array, int i) { - return array[i]; - } - - public static long testArray1J(long[] array, int i) { - return array[i]; - } - - public static byte testArray1B(byte[] array, int i) { - return array[i]; - } - - public static short testArray1S(short[] array, int i) { - return array[i]; - } - - public static char testArray1C(char[] array, int i) { - return array[i]; - } - - public static float testArray1F(float[] array, int i) { - return array[i]; - } - - public static double testArray1D(double[] array, int i) { - return array[i]; - } - - public static Object testArray1L(Object[] array, int i) { - return array[i]; - } - - public static void testStoreArray1I(int[] array, int i, int val) { - array[i] = val; - } - - public static void testStoreArray1B(byte[] array, int i, byte val) { - array[i] = val; - } - - public static void testStoreArray1S(short[] array, int i, short val) { - array[i] = val; - } - - public static void testStoreArray1J(long[] array, int i, long val) { - array[i] = val; - } - - public static void testStoreArray1F(float[] array, int i, float val) { - array[i] = val; - } - - public static void testStoreArray1D(double[] array, int i, double val) { - array[i] = val; - } - - public static void main(String[] args) { - ArrayTest test = new ArrayTest(); - for (Method m : ArrayTest.class.getMethods()) { - String name = m.getName(); - if (m.getAnnotation(Test.class) == null && name.startsWith("test")) { - // CheckStyle: stop system..print check - System.out.println(name + ": \n" + new String(test.compile(name).getTargetCode())); - // CheckStyle: resume system..print check - } - } - } -} diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/BasicPTXTest.java --- a/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/BasicPTXTest.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/BasicPTXTest.java Wed Oct 02 13:26:31 2013 +0200 @@ -24,11 +24,13 @@ import java.lang.reflect.Method; +import org.junit.Ignore; import org.junit.Test; /** * Test class for small Java methods compiled to PTX kernels. */ +@Ignore public class BasicPTXTest extends PTXTestBase { @Test diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/ControlPTXTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/ControlPTXTest.java Wed Oct 02 13:26:31 2013 +0200 @@ -0,0 +1,118 @@ +/* + * 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.compiler.ptx.test; + +import org.junit.*; + +import java.lang.reflect.Method; + +public class ControlPTXTest extends PTXTestBase { + + @Ignore + @Test + public void testControl() { + compile("testLoop"); + // compile("testSwitch1I"); + // compile("testStatic"); + // compile("testCall"); + // compile("testLookupSwitch1I"); + } + + public static int testLoop(int n) { + int sum = 0; + + for (int i = 0; i < n; i++) { + sum++; + } + return sum; + } + + public static int testSwitch1I(int a) { + switch (a) { + case 1: + return 2; + case 2: + return 3; + default: + return 4; + } + } + + public static int testLookupSwitch1I(int a) { + switch (a) { + case 0: + return 1; + case 1: + return 2; + case 2: + return 3; + case 3: + return 1; + case 4: + return 2; + case 5: + return 3; + case 6: + return 1; + case 7: + return 2; + case 8: + return 3; + case 9: + return 1; + case 10: + return 2; + case 11: + return 3; + default: + return -1; + } + } + + @SuppressWarnings("unused") private static Object foo = null; + + public static boolean testStatic(Object o) { + foo = o; + return true; + } + + private static int method(int a, int b) { + return a + b; + } + + public static int testCall(@SuppressWarnings("unused") Object o, int a, int b) { + return method(a, b); + } + + public static void main(String[] args) { + ControlPTXTest test = new ControlPTXTest(); + for (Method m : ControlPTXTest.class.getMethods()) { + String name = m.getName(); + if (m.getAnnotation(Test.class) == null && name.startsWith("test")) { + // CheckStyle: stop system..print check + System.out.println(name + ": \n" + new String(test.compile(name).getTargetCode())); + // CheckStyle: resume system..print check + } + } + } +} diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/ControlTest.java --- a/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/ControlTest.java Fri Sep 06 21:37:50 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,96 +0,0 @@ -/* - * 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.compiler.ptx.test; - -import org.junit.*; - -import java.lang.reflect.Method; - -public class ControlTest extends PTXTestBase { - - @Ignore - @Test - public void testControl() { - compile("testSwitch1I"); - compile("testStatic"); - compile("testCall"); - compile("testLookupSwitch1I"); - } - - public static int testSwitch1I(int a) { - switch (a) { - case 1: - return 2; - case 2: - return 3; - default: - return 4; - } - } - - public static int testLookupSwitch1I(int a) { - switch (a) { - case 0: return 1; - case 1: return 2; - case 2: return 3; - case 3: return 1; - case 4: return 2; - case 5: return 3; - case 6: return 1; - case 7: return 2; - case 8: return 3; - case 9: return 1; - case 10: return 2; - case 11: return 3; - default: return -1; - } - } - - @SuppressWarnings("unused") - private static Object foo = null; - - public static boolean testStatic(Object o) { - foo = o; - return true; - } - - private static int method(int a, int b) { - return a + b; - } - - public static int testCall(@SuppressWarnings("unused") Object o, int a, int b) { - return method(a, b); - } - - public static void main(String[] args) { - ControlTest test = new ControlTest(); - for (Method m : ControlTest.class.getMethods()) { - String name = m.getName(); - if (m.getAnnotation(Test.class) == null && name.startsWith("test")) { - // CheckStyle: stop system..print check - System.out.println(name + ": \n" + new String(test.compile(name).getTargetCode())); - // CheckStyle: resume system..print check - } - } - } -} diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/FloatPTXTest.java --- a/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/FloatPTXTest.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/FloatPTXTest.java Wed Oct 02 13:26:31 2013 +0200 @@ -29,14 +29,18 @@ import com.oracle.graal.api.code.CompilationResult; /* PTX ISA 3.1 - 8.7.3 Floating-Point Instructions */ +@Ignore public class FloatPTXTest extends PTXTestBase { + @Ignore @Test public void testAdd() { CompilationResult r = compile("testAdd2F"); if (r.getTargetCode() == null) { printReport("Compilation of testAdd2F FAILED"); } + + /* r = compile("testAdd2D"); if (r.getTargetCode() == null) { printReport("Compilation of testAdd2D FAILED"); @@ -58,6 +62,7 @@ if (r.getTargetCode() == null) { printReport("Compilation of testConstD FAILED"); } + */ } public static float testAdd2F(float a, float b) { @@ -84,6 +89,7 @@ return 32.0 + a; } + @Ignore @Test public void testSub() { CompilationResult r = compile("testSub2F"); @@ -141,6 +147,7 @@ return 32.0 - a; } + @Ignore @Test public void testMul() { CompilationResult r = compile("testMul2F"); @@ -198,6 +205,7 @@ return 32.0 * a; } + @Ignore @Test public void testDiv() { CompilationResult r = compile("testDiv2F"); @@ -255,6 +263,7 @@ return 32.0 / a; } + @Ignore @Test public void testNeg() { CompilationResult r = compile("testNeg2F"); @@ -276,6 +285,7 @@ return -a; } + @Ignore @Test public void testRem() { // need linkage to PTX remainder() @@ -360,9 +370,7 @@ FloatPTXTest test = new FloatPTXTest(); for (Method m : FloatPTXTest.class.getMethods()) { String name = m.getName(); - if (m.getAnnotation(Test.class) == null && - name.startsWith("test") && - name.startsWith("testRem") == false) { + if (m.getAnnotation(Test.class) == null && name.startsWith("test") && name.startsWith("testRem") == false) { // CheckStyle: stop system..print check System.out.println(name + ": \n" + new String(test.compile(name).getTargetCode())); // CheckStyle: resume system..print check diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/IntegerPTXTest.java --- a/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/IntegerPTXTest.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/IntegerPTXTest.java Wed Oct 02 13:26:31 2013 +0200 @@ -26,11 +26,19 @@ import java.lang.reflect.Method; - public class IntegerPTXTest extends PTXTestBase { @Test public void testAdd() { + /* + Integer r4 = (Integer) invoke(compile("testAdd2B"), (byte) 6, (byte) 4); + if (r4 == null) { + printReport("testAdd2B FAILED"); + } else if (r4.intValue() == testAdd2B((byte) 6, (byte) 4)) { + printReport("testAdd2B PASSED"); + } else { + printReport("testAdd2B FAILED"); + } */ Integer r4 = (Integer) invoke(compile("testAdd2I"), 18, 24); if (r4 == null) { @@ -41,16 +49,14 @@ printReport("testAdd2I FAILED"); } - Long r2 = (Long) invoke(compile("testAdd2L"), (long) 12, (long) 6); + /* Long r2 = (Long) invoke(compile("testAdd2L"), (long) 12, (long) 6); if (r2 == null) { printReport("testAdd2L FAILED"); } else if (r2.longValue() == testAdd2L(12, 6)) { printReport("testAdd2L PASSED"); } else { printReport("testAdd2L FAILED"); - } - - //invoke(compile("testAdd2B"), (byte) 6, (byte) 4); + } r4 = (Integer) invoke(compile("testAddIConst"), 5); if (r4 == null) { @@ -68,8 +74,7 @@ printReport("testAddConstI PASSED"); } else { printReport("testAddConstI FAILED"); - } - + } */ } public static int testAdd2I(int a, int b) { @@ -92,6 +97,7 @@ return 32 + a; } + @Ignore @Test public void testSub() { @@ -149,6 +155,7 @@ return 32 - a; } + @Ignore @Test public void testMul() { @@ -260,6 +267,7 @@ return 32 / a; } + @Ignore @Test public void testRem() { Integer r1 = (Integer) invoke(compile("testRem2I"), 8, 4); @@ -288,6 +296,7 @@ public static long testRem2L(long a, long b) { return a % b; } + @Ignore @Test public void testIntConversion() { diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/LogicPTXTest.java --- a/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/LogicPTXTest.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/LogicPTXTest.java Wed Oct 02 13:26:31 2013 +0200 @@ -24,10 +24,11 @@ import java.lang.reflect.Method; +import org.junit.Ignore; import org.junit.Test; - /* PTX ISA 3.1 - 8.7.5 Logic and Shift Instructions */ +@Ignore public class LogicPTXTest extends PTXTestBase { @Test @@ -105,7 +106,7 @@ compile("testShiftRight2I"); compile("testShiftRight2L"); compile("testUnsignedShiftRight2I"); - compile("testUnsignedShiftRight2L"); + // compile("testUnsignedShiftRight2L"); } public static int testShiftRight2I(int a, int b) { diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/PTXTestBase.java --- a/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/PTXTestBase.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/PTXTestBase.java Wed Oct 02 13:26:31 2013 +0200 @@ -30,12 +30,16 @@ import com.oracle.graal.api.runtime.Graal; import com.oracle.graal.compiler.GraalCompiler; import com.oracle.graal.compiler.ptx.PTXBackend; +import com.oracle.graal.compiler.ptx.PTXTargetMethodAssembler; import com.oracle.graal.compiler.test.GraalCompilerTest; import com.oracle.graal.debug.Debug; +import com.oracle.graal.hotspot.meta.HotSpotNmethod; import com.oracle.graal.hotspot.meta.HotSpotRuntime; import com.oracle.graal.hotspot.meta.HotSpotResolvedJavaMethod; +import com.oracle.graal.hotspot.ptx.PTXHotSpotRuntime; import com.oracle.graal.java.GraphBuilderConfiguration; import com.oracle.graal.java.GraphBuilderPhase; +import com.oracle.graal.lir.ptx.ParallelOver; import com.oracle.graal.nodes.StructuredGraph; import com.oracle.graal.nodes.spi.GraalCodeCacheProvider; import com.oracle.graal.phases.OptimisticOptimizations; @@ -43,6 +47,8 @@ import com.oracle.graal.phases.PhasePlan.PhasePosition; import com.oracle.graal.phases.tiers.*; import com.oracle.graal.ptx.PTX; + +import java.lang.annotation.Annotation; import java.lang.reflect.Modifier; public abstract class PTXTestBase extends GraalCompilerTest { @@ -50,32 +56,36 @@ private StructuredGraph sg; protected CompilationResult compile(String test) { - StructuredGraph graph = parse(test); - sg = graph; - Debug.dump(graph, "Graph"); - TargetDescription target = new TargetDescription(new PTX(), true, 1, 0, true); - PTXBackend ptxBackend = new PTXBackend(Graal.getRequiredCapability(GraalCodeCacheProvider.class), target); - PhasePlan phasePlan = new PhasePlan(); - GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getDefault(), OptimisticOptimizations.NONE); - phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase); - phasePlan.addPhase(PhasePosition.AFTER_PARSING, new PTXPhase()); - new PTXPhase().apply(graph); - CallingConvention cc = getCallingConvention(runtime, Type.JavaCallee, graph.method(), false); - /* - * Use Suites.createDefaultSuites() instead of GraalCompilerTest.suites. The - * GraalCompilerTest.suites variable contains the Suites for the HotSpotRuntime. This code - * will not run on hotspot, so it should use the plain Graal default suites, without hotspot - * specific phases. - * - * Ultimately we might want to have both the kernel and the code natively compiled for GPU fallback to CPU in cases - * of ECC failure on kernel invocation. - */ - CompilationResult result = GraalCompiler.compileGraph(graph, cc, graph.method(), runtime, - graalRuntime().getReplacements(), ptxBackend, target, - null, phasePlan, - OptimisticOptimizations.NONE, new SpeculationLog(), - Suites.createDefaultSuites(), new ExternalCompilationResult()); - return result; + if (runtime instanceof PTXHotSpotRuntime) { + StructuredGraph graph = parse(test); + sg = graph; + Debug.dump(graph, "Graph"); + TargetDescription target = new TargetDescription(new PTX(), true, 1, 0, true); + PTXBackend ptxBackend = new PTXBackend(Graal.getRequiredCapability(GraalCodeCacheProvider.class), target); + PhasePlan phasePlan = new PhasePlan(); + GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getDefault(), OptimisticOptimizations.NONE); + phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase); + phasePlan.addPhase(PhasePosition.AFTER_PARSING, new PTXPhase()); + new PTXPhase().apply(graph); + CallingConvention cc = getCallingConvention(runtime, Type.JavaCallee, graph.method(), false); + /* + * Use Suites.createDefaultSuites() instead of GraalCompilerTest.suites. The + * GraalCompilerTest.suites variable contains the Suites for the HotSpotRuntime. This code + * will not run on hotspot, so it should use the plain Graal default suites, without hotspot + * specific phases. + * + * Ultimately we might want to have both the kernel and the code natively compiled for GPU fallback to CPU in cases + * of ECC failure on kernel invocation. + */ + CompilationResult result = GraalCompiler.compileGraph(graph, cc, graph.method(), runtime, + graalRuntime().getReplacements(), ptxBackend, target, + null, phasePlan, + OptimisticOptimizations.NONE, new SpeculationLog(), + Suites.createDefaultSuites(), new ExternalCompilationResult()); + return result; + } else { + return null; + } } protected StructuredGraph getStructuredGraph() { @@ -83,6 +93,9 @@ } protected Object invoke(CompilationResult result, Object... args) { + if (result == null) { + return null; + } try { if (((ExternalCompilationResult) result).getEntryPoint() == 0) { Debug.dump(result, "[CUDA] *** Null entry point - Not launching kernel"); @@ -94,8 +107,47 @@ boolean isStatic = Modifier.isStatic(compiledMethod.getModifiers()); Object[] executeArgs = argsWithReceiver((isStatic ? null : this), args); HotSpotRuntime hsr = (HotSpotRuntime) runtime; - InstalledCode installedCode = hsr.addExternalMethod(sg.method(), result, sg); - Object r = installedCode.executeVarargs(executeArgs); + InstalledCode installedCode = hsr.addExternalMethod(compiledMethod, result, sg); + Annotation[][] params = compiledMethod.getParameterAnnotations(); + + int dimensionX = 1; + int dimensionY = 1; + int dimensionZ = 1; + + for (int p = 0; p < params.length; p++) { + Annotation[] annos = params[p]; + if (annos != null) { + for (int a = 0; a < annos.length; a++) { + Annotation aa = annos[a]; + if (args[p] instanceof int[] && aa.annotationType().equals(ParallelOver.class)) { + int[] iarray = (int[]) args[p]; + ParallelOver threadBlockDimension = (ParallelOver) aa; + switch (threadBlockDimension.dimension()) { + case X: + dimensionX = iarray.length; + break; + case Y: + dimensionY = iarray.length; + break; + case Z: + dimensionZ = iarray.length; + break; + } + } + } + } + } + Object r; + if (dimensionX != 1 || dimensionY != 1 || dimensionZ != 1) { + /* + * for now assert that the warp array block is no larger than the number of physical gpu cores. + */ + assert dimensionX * dimensionY * dimensionZ < PTXTargetMethodAssembler.getAvailableProcessors(); + + r = ((HotSpotNmethod) installedCode).executeParallel(dimensionX, dimensionY, dimensionZ, executeArgs); + } else { + r = installedCode.executeVarargs(executeArgs); + } return r; } catch (Throwable th) { th.printStackTrace(); diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXBackend.java --- a/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXBackend.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXBackend.java Wed Oct 02 13:26:31 2013 +0200 @@ -22,7 +22,7 @@ */ package com.oracle.graal.compiler.ptx; -import static com.oracle.graal.api.code.ValueUtil.*; +import static com.oracle.graal.lir.LIRValueUtil.*; import java.util.*; @@ -40,6 +40,7 @@ import com.oracle.graal.lir.LIRInstruction.OperandFlag; import com.oracle.graal.lir.LIRInstruction.OperandMode; import com.oracle.graal.lir.LIRInstruction.ValueProcedure; +import com.oracle.graal.lir.StandardOp.LabelOp; import com.oracle.graal.graph.GraalInternalError; /** @@ -52,6 +53,11 @@ } @Override + public boolean shouldAllocateRegisters() { + return false; + } + + @Override public FrameMap newFrameMap() { return new PTXFrameMap(runtime(), target, runtime().lookupRegisterConfig()); } @@ -80,7 +86,7 @@ @Override public TargetMethodAssembler newAssembler(LIRGenerator lirGen, CompilationResult compilationResult) { - // Omit the frame if the method: + // Omit the frame of the method: // - has no spill slots or other slots allocated during register allocation // - has no callee-saved registers // - has no incoming arguments passed on the stack @@ -89,14 +95,13 @@ AbstractAssembler masm = createAssembler(frameMap); HotSpotFrameContext frameContext = new HotSpotFrameContext(); TargetMethodAssembler tasm = new PTXTargetMethodAssembler(target, runtime(), frameMap, masm, frameContext, compilationResult); - tasm.setFrameSize(frameMap.frameSize()); + tasm.setFrameSize(0); return tasm; } - private static void emitKernelEntry(TargetMethodAssembler tasm, LIRGenerator lirGen, - ResolvedJavaMethod codeCacheOwner) { + private static void emitKernelEntry(TargetMethodAssembler tasm, LIRGenerator lirGen, ResolvedJavaMethod codeCacheOwner) { // Emit PTX kernel entry text based on PTXParameterOp - // instructions in the start block. Remove the instructions + // instructions in the start block. Remove the instructions // once kernel entry text and directives are emitted to // facilitate seemless PTX code generation subsequently. assert codeCacheOwner != null : lirGen.getGraph() + " is not associated with a method"; @@ -132,8 +137,6 @@ // Start emiting body of the PTX kernel. codeBuffer.emitString0(") {"); codeBuffer.emitString(""); - - codeBuffer.emitString(".reg .u64" + " %rax;"); } // Emit .reg space declarations @@ -144,23 +147,53 @@ final SortedSet signed32 = new TreeSet<>(); final SortedSet signed64 = new TreeSet<>(); + final SortedSet unsigned64 = new TreeSet<>(); + final SortedSet float32 = new TreeSet<>(); + final SortedSet float64 = new TreeSet<>(); ValueProcedure trackRegisterKind = new ValueProcedure() { @Override public Value doValue(Value value, OperandMode mode, EnumSet flags) { - if (isRegister(value)) { - RegisterValue regVal = (RegisterValue) value; + if (isVariable(value)) { + Variable regVal = (Variable) value; Kind regKind = regVal.getKind(); switch (regKind) { - case Int: - signed32.add(regVal.getRegister().encoding()); - break; - case Long: - signed64.add(regVal.getRegister().encoding()); - break; - default : - throw GraalInternalError.shouldNotReachHere("unhandled register type " + value.toString()); + case Int: + // If the register was used as a wider signed type + // do not add it here + if (!signed64.contains(regVal.index)) { + signed32.add(regVal.index); + } + break; + case Long: + // If the register was used as a narrower signed type + // remove it from there and add it to wider type. + if (signed32.contains(regVal.index)) { + signed32.remove(regVal.index); + } + signed64.add(regVal.index); + break; + case Float: + // If the register was used as a wider signed type + // do not add it here + if (!float64.contains(regVal.index)) { + float32.add(regVal.index); + } + break; + case Double: + // If the register was used as a narrower signed type + // remove it from there and add it to wider type. + if (float32.contains(regVal.index)) { + float32.remove(regVal.index); + } + float64.add(regVal.index); + break; + case Object: + unsigned64.add(regVal.index); + break; + default: + throw GraalInternalError.shouldNotReachHere("unhandled register type " + value.toString()); } } return value; @@ -169,7 +202,12 @@ for (Block b : lirGen.lir.codeEmittingOrder()) { for (LIRInstruction op : lirGen.lir.lir(b)) { - op.forEachOutput(trackRegisterKind); + if (op instanceof LabelOp) { + // Don't consider this as a definition + } else { + op.forEachTemp(trackRegisterKind); + op.forEachOutput(trackRegisterKind); + } } } @@ -179,6 +217,20 @@ for (Integer i : signed64) { codeBuffer.emitString(".reg .s64 %r" + i.intValue() + ";"); } + for (Integer i : unsigned64) { + codeBuffer.emitString(".reg .u64 %r" + i.intValue() + ";"); + } + for (Integer i : float32) { + codeBuffer.emitString(".reg .f32 %r" + i.intValue() + ";"); + } + for (Integer i : float64) { + codeBuffer.emitString(".reg .f64 %r" + i.intValue() + ";"); + } + // emit predicate register declaration + int maxPredRegNum = ((PTXLIRGenerator) lirGen).getNextPredRegNumber(); + if (maxPredRegNum > 0) { + codeBuffer.emitString(".reg .pred %p<" + maxPredRegNum + ">;"); + } } @Override @@ -192,6 +244,7 @@ try { emitRegisterDecl(tasm, lirGen, codeCacheOwner); } catch (GraalInternalError e) { + e.printStackTrace(); // TODO : Better error handling needs to be done once // all types of parameters are handled. codeBuffer.setPosition(0); @@ -202,6 +255,7 @@ try { lirGen.lir.emitCode(tasm); } catch (GraalInternalError e) { + e.printStackTrace(); // TODO : Better error handling needs to be done once // all types of parameters are handled. codeBuffer.setPosition(0); diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java --- a/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java Wed Oct 02 13:26:31 2013 +0200 @@ -24,6 +24,7 @@ package com.oracle.graal.compiler.ptx; import static com.oracle.graal.api.code.ValueUtil.*; +import static com.oracle.graal.api.meta.Value.*; import static com.oracle.graal.lir.ptx.PTXArithmetic.*; import static com.oracle.graal.lir.ptx.PTXBitManipulationOp.IntrinsicOpcode.*; import static com.oracle.graal.lir.ptx.PTXCompare.*; @@ -32,6 +33,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.*; import com.oracle.graal.compiler.gen.*; +import com.oracle.graal.debug.Debug; import com.oracle.graal.graph.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.StandardOp.JumpOp; @@ -44,8 +46,6 @@ import com.oracle.graal.lir.ptx.PTXArithmetic.Unary2Op; import com.oracle.graal.lir.ptx.PTXCompare.CompareOp; import com.oracle.graal.lir.ptx.PTXControlFlow.BranchOp; -import com.oracle.graal.lir.ptx.PTXControlFlow.CondMoveOp; -import com.oracle.graal.lir.ptx.PTXControlFlow.FloatCondMoveOp; import com.oracle.graal.lir.ptx.PTXControlFlow.ReturnOp; import com.oracle.graal.lir.ptx.PTXControlFlow.ReturnNoValOp; import com.oracle.graal.lir.ptx.PTXControlFlow.SequentialSwitchOp; @@ -59,13 +59,22 @@ import com.oracle.graal.lir.ptx.PTXMemOp.StoreReturnValOp; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.calc.ConvertNode.Op; import com.oracle.graal.nodes.java.*; +import java.lang.annotation.*; + + /** * This class implements the PTX specific portion of the LIR generator. */ public class PTXLIRGenerator extends LIRGenerator { + // Number of the predicate register that can be used when needed. + // This value will be recorded and incremented in the LIR instruction + // that sets a predicate register. (e.g., CompareOp) + private int nextPredRegNum; + public static final ForeignCallDescriptor ARITHMETIC_FREM = new ForeignCallDescriptor("arithmeticFrem", float.class, float.class, float.class); public static final ForeignCallDescriptor ARITHMETIC_DREM = new ForeignCallDescriptor("arithmeticDrem", double.class, double.class, double.class); @@ -73,13 +82,20 @@ @Override public LIRInstruction createMove(AllocatableValue result, Value input) { - throw new InternalError("NYI"); + throw GraalInternalError.unimplemented("PTXSpillMoveFactory.createMove()"); } } public PTXLIRGenerator(StructuredGraph graph, CodeCacheProvider runtime, TargetDescription target, FrameMap frameMap, CallingConvention cc, LIR lir) { super(graph, runtime, target, frameMap, cc, lir); lir.spillMoveFactory = new PTXSpillMoveFactory(); + int callVariables = cc.getArgumentCount() + (cc.getReturn() == Value.ILLEGAL ? 0 : 1); + lir.setFirstVariableNumber(callVariables); + nextPredRegNum = 0; + } + + public int getNextPredRegNumber() { + return nextPredRegNum; } @Override @@ -107,7 +123,9 @@ if (isRegister(value)) { return asRegister(value).asValue(value.getKind().getStackKind()); } else if (isStackSlot(value)) { - return StackSlot.get(value.getKind().getStackKind(), asStackSlot(value).getRawOffset(), asStackSlot(value).getRawAddFrameSize()); + return StackSlot.get(value.getKind().getStackKind(), + asStackSlot(value).getRawOffset(), + asStackSlot(value).getRawAddFrameSize()); } else { throw GraalInternalError.shouldNotReachHere(); } @@ -119,23 +137,62 @@ public void emitPrologue() { // Need to emit .param directives based on incoming arguments and return value CallingConvention incomingArguments = cc; - int argCount = incomingArguments.getArgumentCount(); - // Additional argument for return value. - Value[] params = new Value[argCount + 1]; - for (int i = 0; i < argCount; i++) { - params[i] = toParamKind(incomingArguments.getArgument(i)); + Object returnObject = incomingArguments.getReturn(); + AllocatableValue[] params; + int argCount; + + if (returnObject == Value.ILLEGAL) { + params = incomingArguments.getArguments(); + } else { + argCount = incomingArguments.getArgumentCount(); + params = new Variable[argCount + 1]; + for (int i = 0; i < argCount; i++) { + params[i] = incomingArguments.getArgument(i); + } + params[argCount] = (Variable) returnObject; } - // Add the return value as the last parameter. - params[argCount] = incomingArguments.getReturn(); append(new PTXParameterOp(params)); for (LocalNode local : graph.getNodes(LocalNode.class)) { Value param = params[local.index()]; - assert param.getKind() == local.kind().getStackKind(); - setResult(local, emitLoadParam(param.getKind(), param, null)); + Annotation[] annos = graph.method().getParameterAnnotations()[local.index()]; + Warp warpAnnotation = null; + + if (annos != null) { + for (int a = 0; a < annos.length; a++) { + if (annos[a].annotationType().equals(Warp.class)) { + warpAnnotation = (Warp) annos[a]; + } + } + } + if (warpAnnotation != null) { + setResult(local, emitWarpParam(param.getKind(), warpAnnotation)); + } else { + setResult(local, emitLoadParam(param.getKind(), param, null)); + } } } + public Variable emitWarpParam(Kind kind, Warp annotation) { + Variable result = newVariable(kind); + Variable tid = newVariable(Kind.Char); + + switch (annotation.dimension()) { + case X: + tid.setName("%tid.x"); + break; + case Y: + tid.setName("%tid.y"); + break; + case Z: + tid.setName("%tid.y"); + break; + } + emitMove(result, tid); + + return result; + } + @Override public Variable emitMove(Value input) { Variable result = newVariable(input.getKind()); @@ -156,37 +213,45 @@ public PTXAddressValue emitAddress(Value base, long displacement, Value index, int scale) { AllocatableValue baseRegister; long finalDisp = displacement; + if (isConstant(base)) { if (asConstant(base).isNull()) { baseRegister = Value.ILLEGAL; - } else if (asConstant(base).getKind() != Kind.Object) { + } else if (asConstant(base).getKind() != Kind.Object && !runtime.needsDataPatch(asConstant(base))) { finalDisp += asConstant(base).asLong(); baseRegister = Value.ILLEGAL; } else { baseRegister = load(base); } + } else if (base.equals(Value.ILLEGAL)) { + baseRegister = Value.ILLEGAL; } else { baseRegister = asAllocatable(base); } - if (index != Value.ILLEGAL && scale != 0) { + if (!index.equals(Value.ILLEGAL)) { if (isConstant(index)) { finalDisp += asConstant(index).asLong() * scale; } else { + Value convertedIndex; Value indexRegister; + + convertedIndex = emitConvert(Op.I2L, index); if (scale != 1) { - indexRegister = emitMul(index, Constant.forInt(scale)); + if (CodeUtil.isPowerOf2(scale)) { + indexRegister = emitShl(convertedIndex, Constant.forInt(CodeUtil.log2(scale))); + } else { + indexRegister = emitMul(convertedIndex, Constant.forInt(scale)); + } } else { - indexRegister = index; + indexRegister = convertedIndex; } - - if (baseRegister == Value.ILLEGAL) { + if (baseRegister.equals(Value.ILLEGAL)) { baseRegister = asAllocatable(indexRegister); } else { - Variable newBase = newVariable(Kind.Int); - emitMove(newBase, baseRegister); - baseRegister = newBase; - baseRegister = emitAdd(baseRegister, indexRegister); + Variable longBaseRegister = newVariable(Kind.Long); + emitMove(longBaseRegister, baseRegister); + baseRegister = emitAdd(longBaseRegister, indexRegister); } } } @@ -195,6 +260,8 @@ } private PTXAddressValue asAddress(Value address) { + assert address != null; + if (address instanceof PTXAddressValue) { return (PTXAddressValue) address; } else { @@ -219,7 +286,7 @@ @Override public Variable emitAddress(StackSlot address) { - throw new InternalError("NYI"); + throw GraalInternalError.unimplemented("PTXLIRGenerator.emitAddress()"); } @Override @@ -231,24 +298,24 @@ public void emitCompareBranch(Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef label) { switch (left.getKind().getStackKind()) { case Int: - append(new CompareOp(ICMP, cond, left, right)); - append(new BranchOp(cond, label)); + append(new CompareOp(ICMP, cond, left, right, nextPredRegNum)); + append(new BranchOp(cond, label, nextPredRegNum++)); break; case Long: - append(new CompareOp(LCMP, cond, left, right)); - append(new BranchOp(cond, label)); + append(new CompareOp(LCMP, cond, left, right, nextPredRegNum)); + append(new BranchOp(cond, label, nextPredRegNum++)); break; case Float: - append(new CompareOp(FCMP, cond, left, right)); - append(new BranchOp(cond, label)); + append(new CompareOp(FCMP, cond, left, right, nextPredRegNum)); + append(new BranchOp(cond, label, nextPredRegNum++)); break; case Double: - append(new CompareOp(DCMP, cond, left, right)); - append(new BranchOp(cond, label)); + append(new CompareOp(DCMP, cond, left, right, nextPredRegNum)); + append(new BranchOp(cond, label, nextPredRegNum++)); break; case Object: - append(new CompareOp(ACMP, cond, left, right)); - append(new BranchOp(cond, label)); + append(new CompareOp(ACMP, cond, left, right, nextPredRegNum)); + append(new BranchOp(cond, label, nextPredRegNum++)); break; default: throw GraalInternalError.shouldNotReachHere("" + left.getKind()); @@ -257,79 +324,22 @@ @Override public void emitOverflowCheckBranch(LabelRef label, boolean negated) { - throw new InternalError("NYI"); + throw GraalInternalError.unimplemented("PTXLIRGenerator.emitOverflowCheckBranch()"); } @Override public void emitIntegerTestBranch(Value left, Value right, boolean negated, LabelRef label) { - throw new InternalError("NYI"); + throw GraalInternalError.unimplemented("PTXLIRGenerator.emitIntegerTestBranch()"); } @Override public Variable emitConditionalMove(Value left, Value right, Condition cond, boolean unorderedIsTrue, Value trueValue, Value falseValue) { - boolean mirrored = emitCompare(cond, left, right); - Condition finalCondition = mirrored ? cond.mirror() : cond; - - Variable result = newVariable(trueValue.getKind()); - switch (left.getKind().getStackKind()) { - case Int: - case Long: - case Object: - append(new CondMoveOp(result, finalCondition, load(trueValue), loadNonConst(falseValue))); - break; - case Float: - case Double: - append(new FloatCondMoveOp(result, finalCondition, unorderedIsTrue, load(trueValue), load(falseValue))); - break; - default: - throw GraalInternalError.shouldNotReachHere("missing: " + left.getKind()); - } - return result; + // TODO: There is no conventional conditional move instruction in PTX. + // So, this method is changed to throw NYI exception. + // To be revisited if this needs to be really implemented. + throw GraalInternalError.unimplemented("PTXLIRGenerator.emitConditionalMove()"); } - /** - * This method emits the compare instruction, and may reorder the operands. It returns true if - * it did so. - * - * - * @param a the left operand of the comparison - * @param b the right operand of the comparison - * @return true if the left and right operands were switched, false otherwise - */ - private boolean emitCompare(Condition cond, Value a, Value b) { - Variable left; - Value right; - boolean mirrored; - if (LIRValueUtil.isVariable(b)) { - left = load(b); - right = loadNonConst(a); - mirrored = true; - } else { - left = load(a); - right = loadNonConst(b); - mirrored = false; - } - switch (left.getKind().getStackKind()) { - case Int: - append(new CompareOp(ICMP, cond, left, right)); - break; - case Long: - append(new CompareOp(LCMP, cond, left, right)); - break; - case Object: - append(new CompareOp(ACMP, cond, left, right)); - break; - case Float: - append(new CompareOp(FCMP, cond, left, right)); - break; - case Double: - append(new CompareOp(DCMP, cond, left, right)); - break; - default: - throw GraalInternalError.shouldNotReachHere(); - } - return mirrored; - } @Override public Variable emitIntegerTestMove(Value left, Value right, Value trueValue, Value falseValue) { @@ -483,12 +493,12 @@ @Override public Variable emitUDiv(Value a, Value b, DeoptimizingNode deopting) { - throw new InternalError("NYI"); + throw GraalInternalError.unimplemented("PTXLIRGenerator.emitUDiv()"); } @Override public Variable emitURem(Value a, Value b, DeoptimizingNode deopting) { - throw new InternalError("NYI"); + throw GraalInternalError.unimplemented("PTXLIRGenerator.emitURem()"); } @Override @@ -548,7 +558,7 @@ append(new Op2Stack(ISHL, result, a, loadNonConst(b))); break; case Long: - append(new Op1Stack(LSHL, result, loadNonConst(b))); + append(new Op2Stack(LSHL, result, a, loadNonConst(b))); break; default: throw GraalInternalError.shouldNotReachHere(); @@ -564,7 +574,7 @@ append(new Op2Stack(ISHR, result, a, loadNonConst(b))); break; case Long: - append(new Op1Stack(LSHR, result, loadNonConst(b))); + append(new Op2Stack(LSHR, result, a, loadNonConst(b))); break; default: throw GraalInternalError.shouldNotReachHere(); @@ -663,28 +673,28 @@ } @Override - public void emitDeoptimize(DeoptimizationAction action, DeoptimizingNode deopting) { + public void emitDeoptimize(Value actionAndReason, DeoptimizingNode deopting) { append(new ReturnOp(Value.ILLEGAL)); } @Override public void emitMembar(int barriers) { - throw new InternalError("NYI"); + throw GraalInternalError.unimplemented("PTXLIRGenerator.emitMembar()"); } @Override protected void emitDirectCall(DirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) { - throw new InternalError("NYI"); + throw GraalInternalError.unimplemented("PTXLIRGenerator.emitDirectCall()"); } @Override protected void emitIndirectCall(IndirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) { - throw new InternalError("NYI"); + throw GraalInternalError.unimplemented("PTXLIRGenerator.emitIndirectCall()"); } @Override protected void emitForeignCall(ForeignCallLinkage callTarget, Value result, Value[] arguments, Value[] temps, LIRFrameState info) { - throw new InternalError("NYI"); + throw GraalInternalError.unimplemented("PTXLIRGenerator.emitForeignCall()"); } @Override @@ -698,47 +708,47 @@ @Override public void emitBitScanForward(Variable result, Value value) { - throw new InternalError("NYI"); + throw GraalInternalError.unimplemented("PTXLIRGenerator.emitBitScanForward()"); } @Override public void emitBitScanReverse(Variable result, Value value) { - throw new InternalError("NYI"); + throw GraalInternalError.unimplemented("PTXLIRGenerator.emitBitScanReverse()"); } @Override public Value emitMathAbs(Value input) { - throw new InternalError("NYI"); + throw GraalInternalError.unimplemented("PTXLIRGenerator.emitMathAbs()"); } @Override public Value emitMathSqrt(Value input) { - throw new InternalError("NYI"); + throw GraalInternalError.unimplemented("PTXLIRGenerator.emitMathSqrt()"); } @Override public Value emitMathLog(Value input, boolean base10) { - throw new InternalError("NYI"); + throw GraalInternalError.unimplemented("PTXLIRGenerator.emitMathLog()"); } @Override public Value emitMathCos(Value input) { - throw new InternalError("NYI"); + throw GraalInternalError.unimplemented("PTXLIRGenerator.emitMathCos()"); } @Override public Value emitMathSin(Value input) { - throw new InternalError("NYI"); + throw GraalInternalError.unimplemented("PTXLIRGenerator.emitMathSin()"); } @Override public Value emitMathTan(Value input) { - throw new InternalError("NYI"); + throw GraalInternalError.unimplemented("PTXLIRGenerator.emitMathTan()"); } @Override public void emitByteSwap(Variable result, Value input) { - throw new InternalError("NYI"); + throw GraalInternalError.unimplemented("PTXLIRGenerator.emitByteSwap()"); } @Override @@ -755,10 +765,10 @@ // Making a copy of the switch value is necessary because jump table destroys the input // value if (key.getKind() == Kind.Int || key.getKind() == Kind.Long) { - append(new SequentialSwitchOp(keyConstants, keyTargets, defaultTarget, key, Value.ILLEGAL)); + append(new SequentialSwitchOp(keyConstants, keyTargets, defaultTarget, key, Value.ILLEGAL, nextPredRegNum)); } else { assert key.getKind() == Kind.Object : key.getKind(); - append(new SequentialSwitchOp(keyConstants, keyTargets, defaultTarget, key, newVariable(Kind.Object))); + append(new SequentialSwitchOp(keyConstants, keyTargets, defaultTarget, key, newVariable(Kind.Object), nextPredRegNum)); } } @@ -772,39 +782,39 @@ // Making a copy of the switch value is necessary because jump table destroys the input // value Variable tmp = emitMove(key); - append(new TableSwitchOp(lowKey, defaultTarget, targets, tmp, newVariable(target.wordKind))); + append(new TableSwitchOp(lowKey, defaultTarget, targets, tmp, newVariable(target.wordKind), nextPredRegNum++)); } @Override public void visitCompareAndSwap(LoweredCompareAndSwapNode node, Value address) { - throw new InternalError("NYI"); + throw GraalInternalError.unimplemented("PTXLIRGenerator.visitCompareAndSwap()"); } @Override public void visitBreakpointNode(BreakpointNode node) { - throw new InternalError("NYI"); + throw GraalInternalError.unimplemented("PTXLIRGenerator.visitBreakpointNode()"); } @Override public void visitSafepointNode(SafepointNode i) { - // LIRFrameState info = state(); + // LIRFrameState info = state(i); // append(new PTXSafepointOp(info, runtime().config, this)); - throw new InternalError("NYI"); + Debug.log("visitSafePointNode unimplemented"); } @Override public void emitUnwind(Value operand) { - throw new InternalError("NYI"); + throw GraalInternalError.unimplemented("PTXLIRGenerator.emitUnwind()"); } @Override public void emitNullCheck(ValueNode v, DeoptimizingNode deopting) { - throw new InternalError("NYI"); + throw GraalInternalError.unimplemented("PTXLIRGenerator.emitNullCheck()"); } @Override public void visitInfopointNode(InfopointNode i) { - throw new InternalError("NYI"); + throw GraalInternalError.unimplemented("PTXLIRGenerator.visitInfopointNode()"); } public Variable emitLoadParam(Kind kind, Value address, DeoptimizingNode deopting) { @@ -827,6 +837,13 @@ append(new StoreReturnValOp(kind, storeAddress, input, deopting != null ? state(deopting) : null)); } + @Override + public AllocatableValue resultOperandFor(Kind kind) { + if (kind == Kind.Void) { + return ILLEGAL; + } + return (new Variable(kind, 0)); + } @Override public void visitReturn(ReturnNode x) { diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXTargetMethodAssembler.java --- a/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXTargetMethodAssembler.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXTargetMethodAssembler.java Wed Oct 02 13:26:31 2013 +0200 @@ -36,6 +36,12 @@ private static CompilerToGPU toGPU = HotSpotGraalRuntime.graalRuntime().getCompilerToGPU(); private static boolean validDevice = toGPU.deviceInit(); + private static final int totalProcessors = (validDevice ? toGPU.availableProcessors() : 0); + + public static int getAvailableProcessors() { + return totalProcessors; + } + // detach ?? public PTXTargetMethodAssembler(TargetDescription target, CodeCacheProvider runtime, FrameMap frameMap, diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java --- a/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java Wed Oct 02 13:26:31 2013 +0200 @@ -837,7 +837,7 @@ } @Override - public void emitDeoptimize(DeoptimizationAction action, DeoptimizingNode deopting) { + public void emitDeoptimize(Value actionAndReason, DeoptimizingNode deopting) { append(new ReturnOp(Value.ILLEGAL)); } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/BoxingEliminationTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/BoxingEliminationTest.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/BoxingEliminationTest.java Wed Oct 02 13:26:31 2013 +0200 @@ -300,16 +300,16 @@ final ValueNode getResult(String snippet) { processMethod(snippet); - assertEquals(1, graph.getNodes(ReturnNode.class).count()); - return graph.getNodes(ReturnNode.class).first().result(); + assertEquals(1, graph.getNodes().filter(ReturnNode.class).count()); + return graph.getNodes().filter(ReturnNode.class).first().result(); } private void processMethod(final String snippet) { graph = parse(snippet); Assumptions assumptions = new Assumptions(false); HighTierContext context = new HighTierContext(runtime(), assumptions, replacements, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL); - new InliningPhase().apply(graph, context); - new PartialEscapePhase(false).apply(graph, context); + new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context); + new PartialEscapePhase(false, new CanonicalizerPhase(true)).apply(graph, context); } private void compareGraphs(final String snippet, final String referenceSnippet) { @@ -326,19 +326,19 @@ Assumptions assumptions = new Assumptions(false); HighTierContext context = new HighTierContext(runtime(), assumptions, replacements, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL); CanonicalizerPhase canonicalizer = new CanonicalizerPhase(true); - new InliningPhase().apply(graph, context); + new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context); if (loopPeeling) { new LoopTransformHighPhase().apply(graph); } new DeadCodeEliminationPhase().apply(graph); canonicalizer.apply(graph, context); - new PartialEscapePhase(false).apply(graph, context); + new PartialEscapePhase(false, canonicalizer).apply(graph, context); new DeadCodeEliminationPhase().apply(graph); canonicalizer.apply(graph, context); StructuredGraph referenceGraph = parse(referenceSnippet); - new InliningPhase().apply(referenceGraph, context); + new InliningPhase(new CanonicalizerPhase(true)).apply(referenceGraph, context); new DeadCodeEliminationPhase().apply(referenceGraph); new CanonicalizerPhase(true).apply(referenceGraph, context); diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CompareCanonicalizerTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CompareCanonicalizerTest.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CompareCanonicalizerTest.java Wed Oct 02 13:26:31 2013 +0200 @@ -30,12 +30,13 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.phases.common.*; +import com.oracle.graal.phases.tiers.*; public class CompareCanonicalizerTest extends GraalCompilerTest { private StructuredGraph getCanonicalizedGraph(String name) { StructuredGraph graph = parse(name); - new CanonicalizerPhase.Instance(runtime(), null, true).apply(graph); + new CanonicalizerPhase(true).apply(graph, new PhaseContext(runtime(), null, replacements)); return graph; } @@ -53,7 +54,7 @@ assertEquals(referenceGraph, graph); } Assumptions assumptions = new Assumptions(false); - new CanonicalizerPhase.Instance(runtime(), assumptions, true).apply(referenceGraph); + new CanonicalizerPhase(true).apply(referenceGraph, new PhaseContext(runtime(), assumptions, replacements)); for (int i = 1; i < 4; i++) { StructuredGraph graph = getCanonicalizedGraph("canonicalCompare" + i); assertEquals(referenceGraph, graph); diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ConditionTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ConditionTest.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ConditionTest.java Wed Oct 02 13:26:31 2013 +0200 @@ -45,7 +45,7 @@ Constant b = Constant.forInt(i < 100 ? a.asInt() : rand.nextInt()); boolean result1 = c1.foldCondition(a, b, null, false); boolean result2 = c2.foldCondition(a, b, null, false); - if (result1 && implies) { + if (result1) { assertTrue(result2); } } @@ -60,7 +60,7 @@ for (Condition c1 : Condition.values()) { for (Condition c2 : Condition.values()) { Condition join = c1.join(c2); - assertTrue(join == c2.join(c1)); + assertEquals(join, c2.join(c1)); if (join != null) { for (int i = 0; i < 1000; i++) { Constant a = Constant.forInt(rand.nextInt()); @@ -70,6 +70,8 @@ boolean resultJoin = join.foldCondition(a, b, null, false); if (result1 && result2) { assertTrue(resultJoin); + } else { + assertFalse(resultJoin); } } } @@ -83,7 +85,7 @@ for (Condition c1 : Condition.values()) { for (Condition c2 : Condition.values()) { Condition meet = c1.meet(c2); - assertTrue(meet == c2.meet(c1)); + assertEquals(meet, c2.meet(c1)); if (meet != null) { for (int i = 0; i < 1000; i++) { Constant a = Constant.forInt(rand.nextInt()); @@ -93,6 +95,8 @@ boolean resultMeet = meet.foldCondition(a, b, null, false); if (result1 || result2) { assertTrue(resultMeet); + } else { + assertFalse(resultMeet); } } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ConditionalEliminationTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ConditionalEliminationTest.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ConditionalEliminationTest.java Wed Oct 02 13:26:31 2013 +0200 @@ -32,6 +32,7 @@ import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind; import com.oracle.graal.phases.common.*; +import com.oracle.graal.phases.tiers.*; /** * Collection of tests for {@link ConditionalEliminationPhase} including those that triggered bugs @@ -141,7 +142,7 @@ StructuredGraph graph = parse("testNullnessSnippet"); new ConditionalEliminationPhase(runtime()).apply(graph); - new CanonicalizerPhase.Instance(runtime(), null, true).apply(graph); + new CanonicalizerPhase(true).apply(graph, new PhaseContext(runtime(), null, replacements)); for (ConstantNode constant : graph.getNodes().filter(ConstantNode.class)) { assertTrue("unexpected constant: " + constant, constant.asConstant().isNull() || constant.asConstant().asInt() > 0); } @@ -163,7 +164,7 @@ @Test public void testDisjunction() { StructuredGraph graph = parse("testDisjunctionSnippet"); - new CanonicalizerPhase.Instance(runtime(), null, true).apply(graph); + new CanonicalizerPhase(true).apply(graph, new PhaseContext(runtime(), null, replacements)); IfNode ifNode = (IfNode) graph.start().next(); InstanceOfNode instanceOf = (InstanceOfNode) ifNode.condition(); IsNullNode x = graph.unique(new IsNullNode(graph.getLocal(0))); @@ -171,9 +172,9 @@ ShortCircuitOrNode disjunction = graph.unique(new ShortCircuitOrNode(x, false, y, false, NOT_FREQUENT_PROBABILITY)); LogicNegationNode negation = graph.unique(new LogicNegationNode(disjunction)); ifNode.setCondition(negation); - new CanonicalizerPhase.Instance(runtime(), null, true).apply(graph); + new CanonicalizerPhase(true).apply(graph, new PhaseContext(runtime(), null, replacements)); new ConditionalEliminationPhase(runtime()).apply(graph); - new CanonicalizerPhase.Instance(runtime(), null, true).apply(graph); + new CanonicalizerPhase(true).apply(graph, new PhaseContext(runtime(), null, replacements)); for (ConstantNode constant : graph.getNodes().filter(ConstantNode.class)) { assertTrue("unexpected constant: " + constant, constant.asConstant().isNull() || constant.asConstant().asInt() > 0); } @@ -191,10 +192,10 @@ public void testInvoke() { test("testInvokeSnippet", new Integer(16)); StructuredGraph graph = parse("testInvokeSnippet"); - new CanonicalizerPhase.Instance(runtime(), null, true).apply(graph); + new CanonicalizerPhase(true).apply(graph, new PhaseContext(runtime(), null, replacements)); new ConditionalEliminationPhase(runtime()).apply(graph); - InvokeNode invoke = graph.getNodes(InvokeNode.class).first(); + InvokeNode invoke = graph.getNodes().filter(InvokeNode.class).first(); assertEquals(InvokeKind.Special, ((MethodCallTargetNode) invoke.callTarget()).invokeKind()); } @@ -221,11 +222,43 @@ @Test public void testTypeMerging() { StructuredGraph graph = parse("testTypeMergingSnippet"); - new CanonicalizerPhase.Instance(runtime(), null, true).apply(graph); + new CanonicalizerPhase(true).apply(graph, new PhaseContext(runtime(), null, replacements)); new ConditionalEliminationPhase(runtime()).apply(graph); - new CanonicalizerPhase.Instance(runtime(), null, true).apply(graph); + new CanonicalizerPhase(true).apply(graph, new PhaseContext(runtime(), null, replacements)); assertEquals(0, graph.getNodes().filter(StoreFieldNode.class).count()); } + public static String testInstanceOfCheckCastSnippet(Object e) { + if (e instanceof Entry) { + return ((Entry) e).name; + } + return null; + } + + @Test + public void testInstanceOfCheckCast() { + StructuredGraph graph = parse("testInstanceOfCheckCastSnippet"); + new CanonicalizerPhase(true).apply(graph, new PhaseContext(runtime(), null, replacements)); + new ConditionalEliminationPhase(runtime()).apply(graph); + new CanonicalizerPhase(true).apply(graph, new PhaseContext(runtime(), null, replacements)); + + assertEquals(0, graph.getNodes().filter(CheckCastNode.class).count()); + } + + @Test + @Ignore + public void testInstanceOfCheckCastLowered() { + StructuredGraph graph = parse("testInstanceOfCheckCastSnippet"); + + CanonicalizerPhase canonicalizer = new CanonicalizerPhase(true); + PhaseContext context = new PhaseContext(runtime(), null, replacements); + + new LoweringPhase(canonicalizer).apply(graph, context); + canonicalizer.apply(graph, context); + new ConditionalEliminationPhase(runtime()).apply(graph); + canonicalizer.apply(graph, context); + + assertEquals(0, graph.getNodes().filter(GuardNode.class).count()); + } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/DegeneratedLoopsTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/DegeneratedLoopsTest.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/DegeneratedLoopsTest.java Wed Oct 02 13:26:31 2013 +0200 @@ -83,7 +83,7 @@ public void run() { StructuredGraph graph = parse(snippet); HighTierContext context = new HighTierContext(runtime(), new Assumptions(false), replacements, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL); - new InliningPhase().apply(graph, context); + new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context); new CanonicalizerPhase(true).apply(graph, context); Debug.dump(graph, "Graph"); StructuredGraph referenceGraph = parse(REFERENCE_SNIPPET); diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/EliminateNestedCheckCastsTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/EliminateNestedCheckCastsTest.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/EliminateNestedCheckCastsTest.java Wed Oct 02 13:26:31 2013 +0200 @@ -31,6 +31,7 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.phases.common.*; +import com.oracle.graal.phases.tiers.*; public class EliminateNestedCheckCastsTest extends GraalCompilerTest { @@ -113,8 +114,8 @@ public StructuredGraph call() throws Exception { Debug.dump(graph, "After parsing: " + snippet); Assert.assertEquals(checkcasts, graph.getNodes().filter(CheckCastNode.class).count()); - new CanonicalizerPhase.Instance(runtime(), new Assumptions(false), true).apply(graph); - Assert.assertEquals(afterCanon, graph.getNodes(CheckCastNode.class).count()); + new CanonicalizerPhase(true).apply(graph, new PhaseContext(runtime(), new Assumptions(false), replacements)); + Assert.assertEquals(afterCanon, graph.getNodes().filter(CheckCastNode.class).count()); return graph; } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FinalizableSubclassTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FinalizableSubclassTest.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FinalizableSubclassTest.java Wed Oct 02 13:26:31 2013 +0200 @@ -69,7 +69,7 @@ GraphBuilderConfiguration conf = GraphBuilderConfiguration.getSnippetDefault(); new GraphBuilderPhase(runtime, conf, OptimisticOptimizations.ALL).apply(graph); HighTierContext context = new HighTierContext(runtime(), assumptions, replacements, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL); - new InliningPhase().apply(graph, context); + new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context); new CanonicalizerPhase(true).apply(graph, context); return graph; } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FloatingReadTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FloatingReadTest.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FloatingReadTest.java Wed Oct 02 13:26:31 2013 +0200 @@ -29,7 +29,6 @@ import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.spi.Lowerable.*; import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.tiers.*; @@ -60,7 +59,7 @@ public void run() { StructuredGraph graph = parse(snippet); PhaseContext context = new PhaseContext(runtime(), new Assumptions(false), replacements); - new LoweringPhase(LoweringType.BEFORE_GUARDS).apply(graph, context); + new LoweringPhase(new CanonicalizerPhase(true)).apply(graph, context); new FloatingReadPhase().apply(graph); ReturnNode returnNode = null; diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java Wed Oct 02 13:26:31 2013 +0200 @@ -25,9 +25,11 @@ import static com.oracle.graal.api.code.CodeUtil.*; import static com.oracle.graal.phases.GraalOptions.*; +import java.io.*; import java.lang.reflect.*; import java.util.*; import java.util.concurrent.*; +import java.util.concurrent.atomic.*; import org.junit.*; import org.junit.internal.*; @@ -87,7 +89,7 @@ } @BeforeClass - public static void initializeDebgging() { + public static void initializeDebugging() { DebugEnvironment.initialize(System.out); } @@ -114,8 +116,8 @@ protected void assertConstantReturn(StructuredGraph graph, int value) { String graphString = getCanonicalGraphString(graph, false); - Assert.assertEquals("unexpected number of ReturnNodes: " + graphString, graph.getNodes(ReturnNode.class).count(), 1); - ValueNode result = graph.getNodes(ReturnNode.class).first().result(); + Assert.assertEquals("unexpected number of ReturnNodes: " + graphString, graph.getNodes().filter(ReturnNode.class).count(), 1); + ValueNode result = graph.getNodes().filter(ReturnNode.class).first().result(); Assert.assertTrue("unexpected ReturnNode result node: " + graphString, result.isConstant()); Assert.assertEquals("unexpected ReturnNode result kind: " + graphString, result.asConstant().getKind(), Kind.Int); Assert.assertEquals("unexpected ReturnNode result: " + graphString, result.asConstant().asInt(), value); @@ -169,7 +171,7 @@ return parse(getMethod(methodName)); } - private static int compilationId = 0; + private static AtomicInteger compilationId = new AtomicInteger(); /** * Compares two given objects for {@linkplain Assert#assertEquals(Object, Object) equality}. @@ -206,11 +208,45 @@ } } + @SuppressWarnings("serial") + public static class MultiCauseAssertionError extends AssertionError { + + private Throwable[] causes; + + public MultiCauseAssertionError(String message, Throwable... causes) { + super(message); + this.causes = causes; + } + + @Override + public void printStackTrace(PrintStream out) { + super.printStackTrace(out); + int num = 0; + for (Throwable cause : causes) { + if (cause != null) { + out.print("cause " + (num++)); + cause.printStackTrace(out); + } + } + } + + @Override + public void printStackTrace(PrintWriter out) { + super.printStackTrace(out); + int num = 0; + for (Throwable cause : causes) { + if (cause != null) { + out.print("cause " + (num++) + ": "); + cause.printStackTrace(out); + } + } + } + } + protected void testN(int n, final String name, final Object... args) { - final Throwable[] errors = new Throwable[n]; + final List errors = new ArrayList<>(n); Thread[] threads = new Thread[n]; for (int i = 0; i < n; i++) { - final int idx = i; Thread t = new Thread(i + ":" + name) { @Override @@ -218,26 +254,23 @@ try { test(name, args); } catch (Throwable e) { - errors[idx] = e; + errors.add(e); } } }; threads[i] = t; t.start(); } - int failed = 0; for (int i = 0; i < n; i++) { try { threads[i].join(); } catch (InterruptedException e) { - errors[i] = e; - } - if (errors[i] != null) { - errors[i].printStackTrace(); - failed++; + errors.add(e); } } - Assert.assertTrue(failed + " of " + n + " failed", failed == 0); + if (!errors.isEmpty()) { + throw new MultiCauseAssertionError(errors.size() + " failures", errors.toArray(new Throwable[errors.size()])); + } } protected Object referenceInvoke(Method method, Object receiver, Object... args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { @@ -421,7 +454,7 @@ } } - final int id = compilationId++; + final int id = compilationId.incrementAndGet(); InstalledCode installedCode = Debug.scope("Compiling", new Object[]{runtime, new DebugDumpScope(String.valueOf(id), true)}, new Callable() { diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/IfCanonicalizerTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/IfCanonicalizerTest.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/IfCanonicalizerTest.java Wed Oct 02 13:26:31 2013 +0200 @@ -31,6 +31,7 @@ import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.phases.common.*; +import com.oracle.graal.phases.tiers.*; /** * In the following tests, the usages of local variable "a" are replaced with the integer constant @@ -144,7 +145,7 @@ n.replaceFirstInput(local, constant); } Debug.dump(graph, "Graph"); - new CanonicalizerPhase.Instance(runtime(), new Assumptions(false), true).apply(graph); + new CanonicalizerPhase(true).apply(graph, new PhaseContext(runtime(), new Assumptions(false), replacements)); for (FrameState fs : local.usages().filter(FrameState.class).snapshot()) { fs.replaceFirstInput(local, null); } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InfopointReasonTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InfopointReasonTest.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InfopointReasonTest.java Wed Oct 02 13:26:31 2013 +0200 @@ -74,7 +74,7 @@ final Method method = getMethod("testMethod"); final StructuredGraph graph = parseDebug(method); int graphLineSPs = 0; - for (InfopointNode ipn : graph.getNodes(InfopointNode.class)) { + for (InfopointNode ipn : graph.getNodes().filter(InfopointNode.class)) { if (ipn.reason == InfopointReason.LINE_NUMBER) { ++graphLineSPs; } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeExceptionTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeExceptionTest.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeExceptionTest.java Wed Oct 02 13:26:31 2013 +0200 @@ -67,7 +67,7 @@ } Assumptions assumptions = new Assumptions(false); HighTierContext context = new HighTierContext(runtime(), assumptions, replacements, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL); - new InliningPhase(hints).apply(graph, context); + new InliningPhase(hints, new CanonicalizerPhase(true)).apply(graph, context); new CanonicalizerPhase(true).apply(graph, context); new DeadCodeEliminationPhase().apply(graph); } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeHintsTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeHintsTest.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeHintsTest.java Wed Oct 02 13:26:31 2013 +0200 @@ -78,7 +78,7 @@ Assumptions assumptions = new Assumptions(false); HighTierContext context = new HighTierContext(runtime(), assumptions, replacements, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL); - new InliningPhase(hints).apply(graph, context); + new InliningPhase(hints, new CanonicalizerPhase(true)).apply(graph, context); new CanonicalizerPhase(true).apply(graph, context); new DeadCodeEliminationPhase().apply(graph); StructuredGraph referenceGraph = parse(REFERENCE_SNIPPET); diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/LockEliminationTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/LockEliminationTest.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/LockEliminationTest.java Wed Oct 02 13:26:31 2013 +0200 @@ -29,7 +29,6 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.java.*; -import com.oracle.graal.nodes.spi.Lowerable.LoweringType; import com.oracle.graal.phases.*; import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.tiers.*; @@ -62,7 +61,7 @@ test("testSynchronizedSnippet", new A(), new A()); StructuredGraph graph = getGraph("testSynchronizedSnippet"); - new CanonicalizerPhase.Instance(runtime(), null, true).apply(graph); + new CanonicalizerPhase(true).apply(graph, new PhaseContext(runtime(), null, replacements)); new LockEliminationPhase().apply(graph); assertEquals(1, graph.getNodes().filter(MonitorEnterNode.class).count()); assertEquals(1, graph.getNodes().filter(MonitorExitNode.class).count()); @@ -80,7 +79,7 @@ test("testSynchronizedMethodSnippet", new A()); StructuredGraph graph = getGraph("testSynchronizedMethodSnippet"); - new CanonicalizerPhase.Instance(runtime(), null, true).apply(graph); + new CanonicalizerPhase(true).apply(graph, new PhaseContext(runtime(), null, replacements)); new LockEliminationPhase().apply(graph); assertEquals(1, graph.getNodes().filter(MonitorEnterNode.class).count()); assertEquals(1, graph.getNodes().filter(MonitorExitNode.class).count()); @@ -93,10 +92,10 @@ Assumptions assumptions = new Assumptions(true); HighTierContext context = new HighTierContext(runtime(), assumptions, replacements, null, phasePlan, OptimisticOptimizations.ALL); new CanonicalizerPhase(true).apply(graph, context); - new InliningPhase().apply(graph, context); + new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context); new CanonicalizerPhase(true).apply(graph, context); new DeadCodeEliminationPhase().apply(graph); - new LoweringPhase(LoweringType.BEFORE_GUARDS).apply(graph, context); + new LoweringPhase(new CanonicalizerPhase(true)).apply(graph, context); new ValueAnchorCleanupPhase().apply(graph); new LockEliminationPhase().apply(graph); return graph; diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/LoopUnswitchTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/LoopUnswitchTest.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/LoopUnswitchTest.java Wed Oct 02 13:26:31 2013 +0200 @@ -30,6 +30,7 @@ import com.oracle.graal.loop.phases.*; import com.oracle.graal.nodes.*; import com.oracle.graal.phases.common.*; +import com.oracle.graal.phases.tiers.*; public class LoopUnswitchTest extends GraalCompilerTest { @@ -133,8 +134,8 @@ } Assumptions assumptions = new Assumptions(false); - new CanonicalizerPhase.Instance(runtime(), assumptions, true).apply(graph); - new CanonicalizerPhase.Instance(runtime(), assumptions, true).apply(referenceGraph); + new CanonicalizerPhase(true).apply(graph, new PhaseContext(runtime(), assumptions, replacements)); + new CanonicalizerPhase(true).apply(referenceGraph, new PhaseContext(runtime(), assumptions, replacements)); Debug.scope("Test", new DebugDumpScope("Test:" + snippet), new Runnable() { @Override diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MemoryScheduleTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MemoryScheduleTest.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MemoryScheduleTest.java Wed Oct 02 13:26:31 2013 +0200 @@ -36,7 +36,6 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.cfg.*; import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.spi.Lowerable.LoweringType; import com.oracle.graal.nodes.util.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.common.*; @@ -222,7 +221,7 @@ public void testArrayCopy() { SchedulePhase schedule = getFinalSchedule("testArrayCopySnippet", TestMode.INLINED_WITHOUT_FRAMESTATES, MemoryScheduling.OPTIMAL); StructuredGraph graph = schedule.getCFG().getStartBlock().getBeginNode().graph(); - ReturnNode ret = graph.getNodes(ReturnNode.class).first(); + ReturnNode ret = graph.getNodes().filter(ReturnNode.class).first(); assertTrue(ret.result() instanceof FloatingReadNode); assertEquals(schedule.getCFG().blockFor(ret), schedule.getCFG().blockFor(ret.result())); assertReadWithinReturnBlock(schedule, true); @@ -502,9 +501,9 @@ HighTierContext context = new HighTierContext(runtime(), assumptions, replacements, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL); new CanonicalizerPhase(true).apply(graph, context); if (mode == TestMode.INLINED_WITHOUT_FRAMESTATES) { - new InliningPhase().apply(graph, context); + new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context); } - new LoweringPhase(LoweringType.BEFORE_GUARDS).apply(graph, context); + new LoweringPhase(new CanonicalizerPhase(true)).apply(graph, context); if (mode == TestMode.WITHOUT_FRAMESTATES || mode == TestMode.INLINED_WITHOUT_FRAMESTATES) { for (Node node : graph.getNodes()) { if (node instanceof StateSplit) { @@ -523,8 +522,8 @@ MidTierContext midContext = new MidTierContext(runtime(), assumptions, replacements, runtime().getTarget(), OptimisticOptimizations.ALL); new GuardLoweringPhase().apply(graph, midContext); - new LoweringPhase(LoweringType.AFTER_GUARDS).apply(graph, midContext); - new LoweringPhase(LoweringType.AFTER_FSA).apply(graph, midContext); + new LoweringPhase(new CanonicalizerPhase(true)).apply(graph, midContext); + new LoweringPhase(new CanonicalizerPhase(true)).apply(graph, midContext); SchedulePhase schedule = new SchedulePhase(SchedulingStrategy.LATEST_OUT_OF_LOOPS, memsched); schedule.apply(graph); diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MonitorGraphTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MonitorGraphTest.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MonitorGraphTest.java Wed Oct 02 13:26:31 2013 +0200 @@ -95,7 +95,7 @@ } Assumptions assumptions = new Assumptions(false); HighTierContext context = new HighTierContext(runtime(), assumptions, replacements, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL); - new InliningPhase(hints).apply(graph, context); + new InliningPhase(hints, new CanonicalizerPhase(true)).apply(graph, context); new CanonicalizerPhase(true).apply(graph, context); new DeadCodeEliminationPhase().apply(graph); return graph; diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PushNodesThroughPiTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PushNodesThroughPiTest.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PushNodesThroughPiTest.java Wed Oct 02 13:26:31 2013 +0200 @@ -30,7 +30,6 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.spi.Lowerable.LoweringType; import com.oracle.graal.nodes.type.*; import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.tiers.*; @@ -94,7 +93,7 @@ StructuredGraph graph = parse(snippet); PhaseContext context = new PhaseContext(runtime(), new Assumptions(false), replacements); CanonicalizerPhase canonicalizer = new CanonicalizerPhase(true); - new LoweringPhase(LoweringType.BEFORE_GUARDS).apply(graph, context); + new LoweringPhase(canonicalizer).apply(graph, context); canonicalizer.apply(graph, context); new PushThroughPiPhase().apply(graph); canonicalizer.apply(graph, context); diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReadAfterCheckCastTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReadAfterCheckCastTest.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReadAfterCheckCastTest.java Wed Oct 02 13:26:31 2013 +0200 @@ -29,7 +29,6 @@ import com.oracle.graal.debug.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.spi.Lowerable.*; import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.tiers.*; @@ -85,7 +84,7 @@ public void run() { StructuredGraph graph = parse(snippet); PhaseContext context = new PhaseContext(runtime(), new Assumptions(false), replacements); - new LoweringPhase(LoweringType.BEFORE_GUARDS).apply(graph, context); + new LoweringPhase(new CanonicalizerPhase(true)).apply(graph, context); new FloatingReadPhase().apply(graph); new EliminatePartiallyRedundantGuardsPhase(true, false).apply(graph); new ReadEliminationPhase().apply(graph); diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReassociateAndCanonicalTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReassociateAndCanonicalTest.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReassociateAndCanonicalTest.java Wed Oct 02 13:26:31 2013 +0200 @@ -28,6 +28,7 @@ import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.phases.common.*; +import com.oracle.graal.phases.tiers.*; public class ReassociateAndCanonicalTest extends GraalCompilerTest { @@ -241,12 +242,12 @@ return (2 - rnd) - 1; } - private void test(String test, String ref) { + private void test(String test, String ref) { StructuredGraph testGraph = parse(test); Assumptions assumptions = new Assumptions(false); - new CanonicalizerPhase.Instance(runtime(), assumptions, true).apply(testGraph); + new CanonicalizerPhase(true).apply(testGraph, new PhaseContext(runtime(), assumptions, replacements)); StructuredGraph refGraph = parse(ref); - new CanonicalizerPhase.Instance(runtime(), assumptions, true).apply(refGraph); + new CanonicalizerPhase(true).apply(refGraph, new PhaseContext(runtime(), assumptions, replacements)); assertEquals(testGraph, refGraph); } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ScalarTypeSystemTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ScalarTypeSystemTest.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ScalarTypeSystemTest.java Wed Oct 02 13:26:31 2013 +0200 @@ -28,6 +28,7 @@ import com.oracle.graal.debug.*; import com.oracle.graal.nodes.*; import com.oracle.graal.phases.common.*; +import com.oracle.graal.phases.tiers.*; /** * In the following tests, the scalar type system of the compiler should be complete enough to see @@ -166,9 +167,9 @@ StructuredGraph graph = parse(snippet); Debug.dump(graph, "Graph"); Assumptions assumptions = new Assumptions(false); - new CanonicalizerPhase.Instance(runtime(), assumptions, true).apply(graph); + new CanonicalizerPhase(true).apply(graph, new PhaseContext(runtime(), assumptions, replacements)); new ConditionalEliminationPhase(runtime()).apply(graph); - new CanonicalizerPhase.Instance(runtime(), assumptions, true).apply(graph); + new CanonicalizerPhase(true).apply(graph, new PhaseContext(runtime(), assumptions, replacements)); StructuredGraph referenceGraph = parse(referenceSnippet); assertEquals(referenceGraph, graph); } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StampCanonicalizerTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StampCanonicalizerTest.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StampCanonicalizerTest.java Wed Oct 02 13:26:31 2013 +0200 @@ -28,6 +28,7 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.type.*; import com.oracle.graal.phases.common.*; +import com.oracle.graal.phases.tiers.*; /** * This class tests some specific patterns the stamp system should be able to canonicalize away @@ -109,7 +110,7 @@ private void testZeroReturn(String methodName) { StructuredGraph graph = parse(methodName); - new CanonicalizerPhase.Instance(runtime(), new Assumptions(false), true).apply(graph); + new CanonicalizerPhase(true).apply(graph, new PhaseContext(runtime(), new Assumptions(false), replacements)); new DeadCodeEliminationPhase().apply(graph); assertConstantReturn(graph, 0); } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StraighteningTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StraighteningTest.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StraighteningTest.java Wed Oct 02 13:26:31 2013 +0200 @@ -28,6 +28,7 @@ import com.oracle.graal.debug.*; import com.oracle.graal.nodes.*; import com.oracle.graal.phases.common.*; +import com.oracle.graal.phases.tiers.*; public class StraighteningTest extends GraalCompilerTest { @@ -89,7 +90,7 @@ // No debug scope to reduce console noise for @Test(expected = ...) tests StructuredGraph graph = parse(snippet); Debug.dump(graph, "Graph"); - new CanonicalizerPhase.Instance(runtime(), new Assumptions(false), true).apply(graph); + new CanonicalizerPhase(true).apply(graph, new PhaseContext(runtime(), new Assumptions(false), replacements)); StructuredGraph referenceGraph = parse(REFERENCE_SNIPPET); assertEquals(referenceGraph, graph); } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java Wed Oct 02 13:26:31 2013 +0200 @@ -35,6 +35,7 @@ import com.oracle.graal.nodes.java.*; import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.schedule.*; +import com.oracle.graal.phases.tiers.*; /** * In the following tests, the scalar type system of the compiler should be complete enough to see @@ -44,7 +45,7 @@ @Test public void test1() { - test("test1Snippet", CheckCastNode.class); + testHelper("test1Snippet", CheckCastNode.class); } public static int test1Snippet(Object a) { @@ -56,7 +57,7 @@ @Test public void test2() { - test("test2Snippet", CheckCastNode.class); + testHelper("test2Snippet", CheckCastNode.class); } public static int test2Snippet(Object a) { @@ -161,7 +162,7 @@ @Test public void test6() { - test("test6Snippet", CheckCastNode.class); + testHelper("test6Snippet", CheckCastNode.class); } public static int test6Snippet(int i) throws IOException { @@ -184,13 +185,13 @@ StructuredGraph graph = parse(snippet); Debug.dump(graph, "Graph"); Assumptions assumptions = new Assumptions(false); - new CanonicalizerPhase.Instance(runtime(), assumptions, true).apply(graph); + new CanonicalizerPhase(true).apply(graph, new PhaseContext(runtime(), assumptions, replacements)); new ConditionalEliminationPhase(runtime()).apply(graph); - new CanonicalizerPhase.Instance(runtime(), assumptions, true).apply(graph); + new CanonicalizerPhase(true).apply(graph, new PhaseContext(runtime(), assumptions, replacements)); // a second canonicalizer is needed to process nested MaterializeNodes - new CanonicalizerPhase.Instance(runtime(), assumptions, true).apply(graph); + new CanonicalizerPhase(true).apply(graph, new PhaseContext(runtime(), assumptions, replacements)); StructuredGraph referenceGraph = parse(referenceSnippet); - new CanonicalizerPhase.Instance(runtime(), assumptions, true).apply(referenceGraph); + new CanonicalizerPhase(true).apply(referenceGraph, new PhaseContext(runtime(), assumptions, replacements)); assertEquals(referenceGraph, graph); } @@ -236,14 +237,14 @@ } } - private void test(String snippet, Class clazz) { + private void testHelper(String snippet, Class clazz) { StructuredGraph graph = parse(snippet); Debug.dump(graph, "Graph"); Assumptions assumptions = new Assumptions(false); - new CanonicalizerPhase.Instance(runtime(), assumptions, true).apply(graph); + new CanonicalizerPhase(true).apply(graph, new PhaseContext(runtime(), assumptions, replacements)); new ConditionalEliminationPhase(runtime()).apply(graph); - new CanonicalizerPhase.Instance(runtime(), assumptions, true).apply(graph); + new CanonicalizerPhase(true).apply(graph, new PhaseContext(runtime(), assumptions, replacements)); Debug.dump(graph, "Graph"); - Assert.assertFalse("shouldn't have nodes of type " + clazz, graph.getNodes(clazz).iterator().hasNext()); + Assert.assertFalse("shouldn't have nodes of type " + clazz, graph.getNodes().filter(clazz).iterator().hasNext()); } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/CompiledMethodTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/CompiledMethodTest.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/CompiledMethodTest.java Wed Oct 02 13:26:31 2013 +0200 @@ -32,6 +32,7 @@ import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.phases.common.*; +import com.oracle.graal.phases.tiers.*; import com.oracle.graal.test.*; /** @@ -55,7 +56,7 @@ public void test1() { Method method = getMethod("testMethod"); final StructuredGraph graph = parse(method); - new CanonicalizerPhase.Instance(runtime(), new Assumptions(false), true).apply(graph); + new CanonicalizerPhase(true).apply(graph, new PhaseContext(runtime(), new Assumptions(false), replacements)); new DeadCodeEliminationPhase().apply(graph); for (Node node : graph.getNodes()) { diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EarlyReadEliminationTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EarlyReadEliminationTest.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EarlyReadEliminationTest.java Wed Oct 02 13:26:31 2013 +0200 @@ -42,7 +42,7 @@ graph = parse(snippet); Assumptions assumptions = new Assumptions(false); HighTierContext context = new HighTierContext(runtime(), assumptions, replacements, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL); - new InliningPhase().apply(graph, context); - new EarlyReadEliminationPhase().apply(graph, context); + new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context); + new EarlyReadEliminationPhase(new CanonicalizerPhase(true)).apply(graph, context); } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java Wed Oct 02 13:26:31 2013 +0200 @@ -234,17 +234,18 @@ Assumptions assumptions = new Assumptions(false); HighTierContext context = new HighTierContext(runtime(), assumptions, replacements, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL); - new InliningPhase().apply(graph, context); + new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context); new DeadCodeEliminationPhase().apply(graph); new CanonicalizerPhase(true).apply(graph, context); - new PartialEscapePhase(iterativeEscapeAnalysis).apply(graph, context); - Assert.assertEquals(1, graph.getNodes(ReturnNode.class).count()); - ReturnNode returnNode = graph.getNodes(ReturnNode.class).first(); + new PartialEscapePhase(iterativeEscapeAnalysis, new CanonicalizerPhase(true)).apply(graph, context); + Assert.assertEquals(1, graph.getNodes().filter(ReturnNode.class).count()); + ReturnNode returnNode = graph.getNodes().filter(ReturnNode.class).first(); if (expectedConstantResult != null) { Assert.assertTrue(returnNode.result().toString(), returnNode.result().isConstant()); Assert.assertEquals(expectedConstantResult, returnNode.result().asConstant()); } - int newInstanceCount = graph.getNodes(NewInstanceNode.class).count() + graph.getNodes(NewArrayNode.class).count() + graph.getNodes(CommitAllocationNode.class).count(); + int newInstanceCount = graph.getNodes().filter(NewInstanceNode.class).count() + graph.getNodes().filter(NewArrayNode.class).count() + + graph.getNodes().filter(CommitAllocationNode.class).count(); Assert.assertEquals(0, newInstanceCount); return returnNode; } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/IterativeInliningTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/IterativeInliningTest.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/IterativeInliningTest.java Wed Oct 02 13:26:31 2013 +0200 @@ -82,8 +82,8 @@ final ReturnNode getReturn(String snippet) { processMethod(snippet); - assertEquals(1, graph.getNodes(ReturnNode.class).count()); - return graph.getNodes(ReturnNode.class).first(); + assertEquals(1, graph.getNodes().filter(ReturnNode.class).count()); + return graph.getNodes().filter(ReturnNode.class).first(); } private void processMethod(final String snippet) { diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PEAReadEliminationTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PEAReadEliminationTest.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PEAReadEliminationTest.java Wed Oct 02 13:26:31 2013 +0200 @@ -236,15 +236,15 @@ final ReturnNode getReturn(String snippet) { processMethod(snippet); - assertEquals(1, graph.getNodes(ReturnNode.class).count()); - return graph.getNodes(ReturnNode.class).first(); + assertEquals(1, graph.getNodes().filter(ReturnNode.class).count()); + return graph.getNodes().filter(ReturnNode.class).first(); } protected void processMethod(final String snippet) { graph = parse(snippet); Assumptions assumptions = new Assumptions(false); HighTierContext context = new HighTierContext(runtime(), assumptions, replacements, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL); - new InliningPhase().apply(graph, context); - new PartialEscapePhase(false, true).apply(graph, context); + new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context); + new PartialEscapePhase(false, true, new CanonicalizerPhase(true)).apply(graph, context); } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PartialEscapeAnalysisTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PartialEscapeAnalysisTest.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PartialEscapeAnalysisTest.java Wed Oct 02 13:26:31 2013 +0200 @@ -126,7 +126,7 @@ @Test public void testCache() { - testMaterialize("testCacheSnippet", 0.5, 1); + testMaterialize("testCacheSnippet", 0.75, 1); } public static class CacheKey { @@ -167,13 +167,13 @@ final void testMaterialize(final String snippet, double expectedProbability, int expectedCount, Class... invalidNodeClasses) { StructuredGraph result = processMethod(snippet); try { - Assert.assertTrue("partial escape analysis should have removed all NewInstanceNode allocations", result.getNodes(NewInstanceNode.class).isEmpty()); - Assert.assertTrue("partial escape analysis should have removed all NewArrayNode allocations", result.getNodes(NewArrayNode.class).isEmpty()); + Assert.assertTrue("partial escape analysis should have removed all NewInstanceNode allocations", result.getNodes().filter(NewInstanceNode.class).isEmpty()); + Assert.assertTrue("partial escape analysis should have removed all NewArrayNode allocations", result.getNodes().filter(NewArrayNode.class).isEmpty()); NodesToDoubles nodeProbabilities = new ComputeProbabilityClosure(result).apply(); double probabilitySum = 0; int materializeCount = 0; - for (CommitAllocationNode materialize : result.getNodes(CommitAllocationNode.class)) { + for (CommitAllocationNode materialize : result.getNodes().filter(CommitAllocationNode.class)) { probabilitySum += nodeProbabilities.get(materialize) * materialize.getVirtualObjects().size(); materializeCount += materialize.getVirtualObjects().size(); } @@ -199,10 +199,10 @@ Assumptions assumptions = new Assumptions(false); HighTierContext context = new HighTierContext(runtime(), assumptions, replacements, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL); - new InliningPhase().apply(graph, context); + new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context); new DeadCodeEliminationPhase().apply(graph); new CanonicalizerPhase(true).apply(graph, context); - new PartialEscapePhase(false).apply(graph, context); + new PartialEscapePhase(false, new CanonicalizerPhase(true)).apply(graph, context); for (MergeNode merge : graph.getNodes(MergeNode.class)) { merge.setStateAfter(null); diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/inlining/InliningTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/inlining/InliningTest.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/inlining/InliningTest.java Wed Oct 02 13:26:31 2013 +0200 @@ -240,7 +240,7 @@ HighTierContext context = new HighTierContext(runtime(), assumptions, replacements, null, phasePlan, OptimisticOptimizations.ALL); Debug.dump(graph, "Graph"); new CanonicalizerPhase(true).apply(graph, context); - new InliningPhase().apply(graph, context); + new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context); Debug.dump(graph, "Graph"); new CanonicalizerPhase(true).apply(graph, context); new DeadCodeEliminationPhase().apply(graph); @@ -279,7 +279,7 @@ private static int[] countMethodInfopoints(StructuredGraph graph) { int start = 0; int end = 0; - for (InfopointNode ipn : graph.getNodes(InfopointNode.class)) { + for (InfopointNode ipn : graph.getNodes().filter(InfopointNode.class)) { if (ipn.reason == InfopointReason.METHOD_START) { ++start; } else if (ipn.reason == InfopointReason.METHOD_END) { diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java Wed Oct 02 13:26:31 2013 +0200 @@ -229,7 +229,7 @@ List codeEmittingOrder = ComputeBlockOrder.computeCodeEmittingOrder(blocks.length, startBlock, nodeProbabilities); List linearScanOrder = ComputeBlockOrder.computeLinearScanOrder(blocks.length, startBlock, nodeProbabilities); - LIR lir = new LIR(schedule.getCFG(), schedule.getBlockToNodesMap(), linearScanOrder, codeEmittingOrder, speculationLog); + LIR lir = new LIR(schedule.getCFG(), schedule.getBlockToNodesMap(), linearScanOrder, codeEmittingOrder); Debug.dump(lir, "After linear scan order"); return lir; @@ -238,7 +238,7 @@ } - public static LIRGenerator emitLIR(Backend backend, final TargetDescription target, final LIR lir, StructuredGraph graph, CallingConvention cc) { + public static LIRGenerator emitLIR(final Backend backend, final TargetDescription target, final LIR lir, StructuredGraph graph, CallingConvention cc) { final FrameMap frameMap = backend.newFrameMap(); final LIRGenerator lirGen = backend.newLIRGenerator(graph, frameMap, cc, lir); @@ -269,7 +269,9 @@ Debug.scope("Allocator", new Runnable() { public void run() { - new LinearScan(target, lir, lirGen, frameMap).allocate(); + if (backend.shouldAllocateRegisters()) { + new LinearScan(target, lir, lirGen, frameMap).allocate(); + } } }); return lirGen; diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalDebugConfig.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalDebugConfig.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalDebugConfig.java Wed Oct 02 13:26:31 2013 +0200 @@ -36,8 +36,6 @@ public class GraalDebugConfig implements DebugConfig { // @formatter:off - @Option(help = "Enable scope-based debugging", name = "Debug") - public static final OptionValue DebugEnabled = new OptionValue<>(true); @Option(help = "Pattern for scope(s) to in which dumping is enabled (see DebugFilter and Debug.dump)") public static final OptionValue Dump = new OptionValue<>(null); @Option(help = "Pattern for scope(s) to in which metering is enabled (see DebugFilter and Debug.metric)") @@ -53,7 +51,7 @@ "Partial - aggregate by partially qualified name (e.g., A.B.C.D.Counter and X.Y.Z.D.Counter will be merged to D.Counter)%n" + "Complete - aggregate by qualified name%n" + "Thread - aggregate by qualified name and thread") - public static final OptionValue DebugValueSummary = new OptionValue<>("Complete"); + public static final OptionValue DebugValueSummary = new OptionValue<>("Name"); @Option(help = "Send Graal IR to dump handlers on error") public static final OptionValue DumpOnError = new OptionValue<>(false); @Option(help = "Enable expensive assertions") @@ -68,6 +66,10 @@ }; // @formatter:on + public static boolean areDebugScopePatternsEnabled() { + return DumpOnError.getValue() || Dump.getValue() != null || Meter.getValue() != null || Time.getValue() != null || Log.getValue() != null; + } + private final DebugFilter logFilter; private final DebugFilter meterFilter; private final DebugFilter timerFilter; diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java Wed Oct 02 13:26:31 2013 +0200 @@ -48,7 +48,7 @@ protected HashMap virtualObjects = new HashMap<>(); protected IdentityHashMap objectStates = new IdentityHashMap<>(); - public LIRFrameState build(FrameState topState, short reason, LabelRef exceptionEdge) { + public LIRFrameState build(FrameState topState, LabelRef exceptionEdge) { assert virtualObjects.size() == 0; assert objectStates.size() == 0; @@ -101,11 +101,11 @@ } objectStates.clear(); - return newLIRFrameState(reason, exceptionEdge, frame, virtualObjectsArray); + return newLIRFrameState(exceptionEdge, frame, virtualObjectsArray); } - protected LIRFrameState newLIRFrameState(short reason, LabelRef exceptionEdge, BytecodeFrame frame, VirtualObject[] virtualObjectsArray) { - return new LIRFrameState(frame, virtualObjectsArray, exceptionEdge, reason); + protected LIRFrameState newLIRFrameState(LabelRef exceptionEdge, BytecodeFrame frame, VirtualObject[] virtualObjectsArray) { + return new LIRFrameState(frame, virtualObjectsArray, exceptionEdge); } protected BytecodeFrame computeFrameForState(FrameState state) { @@ -122,7 +122,7 @@ if (state.outerFrameState() != null) { caller = computeFrameForState(state.outerFrameState()); } - assert state.bci != FrameState.UNKNOWN_BCI : "bci == " + state.bci; + assert state.bci >= FrameState.BEFORE_BCI : "bci == " + state.bci; return new BytecodeFrame(caller, state.method(), state.bci, state.rethrowException(), state.duringCall(), values, numLocals, numStack, numLocks); } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java Wed Oct 02 13:26:31 2013 +0200 @@ -228,26 +228,26 @@ if (!deopt.canDeoptimize()) { return null; } - return stateFor(deopt.getDeoptimizationState(), deopt.getDeoptimizationReason()); + return stateFor(deopt.getDeoptimizationState()); } public LIRFrameState stateWithExceptionEdge(DeoptimizingNode deopt, LabelRef exceptionEdge) { if (!deopt.canDeoptimize()) { return null; } - return stateForWithExceptionEdge(deopt.getDeoptimizationState(), deopt.getDeoptimizationReason(), exceptionEdge); + return stateForWithExceptionEdge(deopt.getDeoptimizationState(), exceptionEdge); } - public LIRFrameState stateFor(FrameState state, DeoptimizationReason reason) { - return stateForWithExceptionEdge(state, reason, null); + public LIRFrameState stateFor(FrameState state) { + return stateForWithExceptionEdge(state, null); } - public LIRFrameState stateForWithExceptionEdge(FrameState state, DeoptimizationReason reason, LabelRef exceptionEdge) { + public LIRFrameState stateForWithExceptionEdge(FrameState state, LabelRef exceptionEdge) { if (needOnlyOopMaps()) { - return new LIRFrameState(null, null, null, (short) -1); + return new LIRFrameState(null, null, null); } assert state != null; - return debugInfoBuilder.build(state, lir.getDeoptimizationReasons().addSpeculation(reason), exceptionEdge); + return debugInfoBuilder.build(state, exceptionEdge); } /** @@ -616,7 +616,15 @@ @Override public Variable emitForeignCall(ForeignCallLinkage linkage, DeoptimizingNode info, Value... args) { - LIRFrameState state = !linkage.canDeoptimize() ? null : stateFor(info.getDeoptimizationState(), info.getDeoptimizationReason()); + LIRFrameState state = null; + if (linkage.canDeoptimize()) { + if (info != null) { + state = stateFor(info.getDeoptimizationState()); + } else { + assert needOnlyOopMaps(); + state = new LIRFrameState(null, null, null); + } + } // move the arguments into the correct location CallingConvention linkageCc = linkage.getOutgoingCallingConvention(); diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/HighTier.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/HighTier.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/HighTier.java Wed Oct 02 13:26:31 2013 +0200 @@ -22,12 +22,12 @@ */ package com.oracle.graal.compiler.phases; +import static com.oracle.graal.compiler.phases.HighTier.Options.*; import static com.oracle.graal.phases.GraalOptions.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.loop.phases.*; -import com.oracle.graal.nodes.spi.Lowerable.LoweringType; import com.oracle.graal.options.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.common.*; @@ -37,12 +37,15 @@ public class HighTier extends PhaseSuite { - // @formatter:off - @Option(help = "") - public static final OptionValue VerifyUsageWithEquals = new OptionValue<>(true); - @Option(help = "Enable inlining") - public static final OptionValue Inline = new OptionValue<>(true); - // @formatter:on + static class Options { + + // @formatter:off + @Option(help = "") + public static final OptionValue VerifyUsageWithEquals = new OptionValue<>(true); + @Option(help = "Enable inlining") + public static final OptionValue Inline = new OptionValue<>(true); + // @formatter:on + } public HighTier() { CanonicalizerPhase canonicalizer = new CanonicalizerPhase(!AOTCompilation.getValue()); @@ -60,12 +63,12 @@ if (IterativeInlining.getValue()) { appendPhase(new IterativeInliningPhase(canonicalizer)); } else { - appendPhase(new InliningPhase()); + appendPhase(new InliningPhase(canonicalizer)); appendPhase(new DeadCodeEliminationPhase()); if (ConditionalElimination.getValue() && OptCanonicalizer.getValue()) { appendPhase(canonicalizer); - appendPhase(new IterativeConditionalEliminationPhase()); + appendPhase(new IterativeConditionalEliminationPhase(canonicalizer)); } } } @@ -73,15 +76,15 @@ appendPhase(new CleanTypeProfileProxyPhase()); if (FullUnroll.getValue()) { - appendPhase(new LoopFullUnrollPhase(!AOTCompilation.getValue())); + appendPhase(new LoopFullUnrollPhase(canonicalizer)); } if (OptTailDuplication.getValue()) { - appendPhase(new TailDuplicationPhase()); + appendPhase(new TailDuplicationPhase(canonicalizer)); } if (PartialEscapeAnalysis.getValue()) { - appendPhase(new PartialEscapePhase(true)); + appendPhase(new PartialEscapePhase(true, canonicalizer)); } if (OptConvertDeoptsToGuards.getValue()) { @@ -98,6 +101,6 @@ appendPhase(canonicalizer); } - appendPhase(new LoweringPhase(LoweringType.BEFORE_GUARDS)); + appendPhase(new LoweringPhase(canonicalizer)); } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LowTier.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LowTier.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LowTier.java Wed Oct 02 13:26:31 2013 +0200 @@ -22,7 +22,8 @@ */ package com.oracle.graal.compiler.phases; -import com.oracle.graal.nodes.spi.Lowerable.LoweringType; +import static com.oracle.graal.phases.GraalOptions.*; + import com.oracle.graal.phases.*; import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.tiers.*; @@ -30,7 +31,9 @@ public class LowTier extends PhaseSuite { public LowTier() { - appendPhase(new LoweringPhase(LoweringType.AFTER_FSA)); + CanonicalizerPhase canonicalizer = new CanonicalizerPhase(!AOTCompilation.getValue()); + + appendPhase(new LoweringPhase(canonicalizer)); appendPhase(new ExpandLogicPhase()); diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/MidTier.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/MidTier.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/MidTier.java Wed Oct 02 13:26:31 2013 +0200 @@ -25,7 +25,6 @@ import static com.oracle.graal.phases.GraalOptions.*; import com.oracle.graal.loop.phases.*; -import com.oracle.graal.nodes.spi.Lowerable.LoweringType; import com.oracle.graal.phases.*; import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.tiers.*; @@ -47,11 +46,11 @@ appendPhase(new LockEliminationPhase()); if (OptReadElimination.getValue()) { - appendPhase(new EarlyReadEliminationPhase()); + appendPhase(new EarlyReadEliminationPhase(canonicalizer)); } if (OptFloatingReads.getValue()) { - IncrementalCanonicalizerPhase incCanonicalizer = new IncrementalCanonicalizerPhase<>(); + IncrementalCanonicalizerPhase incCanonicalizer = new IncrementalCanonicalizerPhase<>(canonicalizer); incCanonicalizer.appendPhase(new FloatingReadPhase()); appendPhase(incCanonicalizer); if (OptReadElimination.getValue()) { @@ -69,7 +68,7 @@ } if (ConditionalElimination.getValue() && OptCanonicalizer.getValue()) { - appendPhase(new IterativeConditionalEliminationPhase()); + appendPhase(new IterativeConditionalEliminationPhase(canonicalizer)); } if (OptEliminatePartiallyRedundantGuards.getValue()) { @@ -82,14 +81,16 @@ appendPhase(new LoopSafepointEliminationPhase()); - appendPhase(new SafepointInsertionPhase()); + appendPhase(new LoopSafepointInsertionPhase()); appendPhase(new GuardLoweringPhase()); - appendPhase(new LoweringPhase(LoweringType.AFTER_GUARDS)); + appendPhase(new LoweringPhase(canonicalizer)); appendPhase(new FrameStateAssignmentPhase()); + appendPhase(new DeoptimizationGroupingPhase()); + if (OptCanonicalizer.getValue()) { appendPhase(canonicalizer); } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/Backend.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/Backend.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/Backend.java Wed Oct 02 13:26:31 2013 +0200 @@ -55,6 +55,8 @@ public abstract TargetMethodAssembler newAssembler(LIRGenerator lirGen, CompilationResult compilationResult); + public abstract boolean shouldAllocateRegisters(); + /** * Emits the code for a given graph. * diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.debug.test/src/com/oracle/graal/debug/test/DebugHistogramTest.java --- a/graal/com.oracle.graal.debug.test/src/com/oracle/graal/debug/test/DebugHistogramTest.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.debug.test/src/com/oracle/graal/debug/test/DebugHistogramTest.java Wed Oct 02 13:26:31 2013 +0200 @@ -27,6 +27,7 @@ import org.junit.*; import com.oracle.graal.debug.*; +import com.oracle.graal.debug.internal.*; public class DebugHistogramTest { @@ -34,8 +35,13 @@ public void testEmptyHistogram() { DebugHistogram histogram = Debug.createHistogram("TestHistogram"); ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - histogram.print(new PrintStream(outputStream)); + + new DebugHistogramAsciiPrinter(new PrintStream(outputStream)).print(histogram); Assert.assertEquals("TestHistogram is empty.\n", outputStream.toString()); + + outputStream.reset(); + new DebugHistogramRPrinter(new PrintStream(outputStream)).print(histogram); + Assert.assertEquals("", outputStream.toString()); } @Test @@ -44,19 +50,28 @@ ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); histogram.add(new Integer(1)); histogram.add(new Integer(1)); - histogram.print(new PrintStream(outputStream)); + new DebugHistogramAsciiPrinter(new PrintStream(outputStream)).print(histogram); String[] lines = outputStream.toString().split("\n"); - Assert.assertEquals(4, lines.length); - Assert.assertEquals("TestHistogram has 1 unique elements and 2 total elements:", lines[0]); - Assert.assertEquals( - "--------------------------------------------------------------------------------------------------------------------------------------------------------------------------", - lines[1]); - Assert.assertEquals( - "| 1 | 2 | ==================================================================================================== |", - lines[2]); - Assert.assertEquals( - "--------------------------------------------------------------------------------------------------------------------------------------------------------------------------", - lines[3]); + // @formatter:off + String[] expected = { + "TestHistogram has 1 unique elements and 2 total elements:", + "--------------------------------------------------------------------------------------------------------------------------------------------------------------------------", + "| 1 | 2 | ==================================================================================================== |", + "--------------------------------------------------------------------------------------------------------------------------------------------------------------------------" + }; + // @formatter:on + Assert.assertArrayEquals(expected, lines); + + outputStream.reset(); + new DebugHistogramRPrinter(new PrintStream(outputStream)).print(histogram); + lines = outputStream.toString().split("\n"); + // @formatter:off + expected = new String[] { + "TestHistogram <- c(2);", + "names(TestHistogram) <- c(\"1\");" + }; + // @formatter:on + Assert.assertArrayEquals(expected, lines); } @Test @@ -66,22 +81,29 @@ histogram.add(new Integer(1)); histogram.add(new Integer(2)); histogram.add(new Integer(2)); - histogram.print(new PrintStream(outputStream)); + new DebugHistogramAsciiPrinter(new PrintStream(outputStream)).print(histogram); String[] lines = outputStream.toString().split("\n"); - Assert.assertEquals(5, lines.length); - Assert.assertEquals("TestHistogram has 2 unique elements and 3 total elements:", lines[0]); - Assert.assertEquals( - "--------------------------------------------------------------------------------------------------------------------------------------------------------------------------", - lines[1]); - Assert.assertEquals( - "| 2 | 2 | ==================================================================================================== |", - lines[2]); - Assert.assertEquals( - "| 1 | 1 | ================================================== |", - lines[3]); - Assert.assertEquals( - "--------------------------------------------------------------------------------------------------------------------------------------------------------------------------", - lines[4]); + // @formatter:off + String[] expected = new String[] { + "TestHistogram has 2 unique elements and 3 total elements:", + "--------------------------------------------------------------------------------------------------------------------------------------------------------------------------", + "| 2 | 2 | ==================================================================================================== |", + "| 1 | 1 | ================================================== |", + "--------------------------------------------------------------------------------------------------------------------------------------------------------------------------" + }; + // @formatter:on + Assert.assertArrayEquals(expected, lines); + + outputStream.reset(); + new DebugHistogramRPrinter(new PrintStream(outputStream)).print(histogram); + lines = outputStream.toString().split("\n"); + // @formatter:off + expected = new String[] { + "TestHistogram <- c(2, 1);", + "names(TestHistogram) <- c(\"2\", \"1\");" + }; + // @formatter:on + Assert.assertArrayEquals(expected, lines); } @Test @@ -89,7 +111,7 @@ DebugHistogram histogram = Debug.createHistogram("TestHistogram"); ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); histogram.add("MyCustomValue"); - histogram.print(new PrintStream(outputStream), Integer.MAX_VALUE, 10, 10); + new DebugHistogramAsciiPrinter(new PrintStream(outputStream), Integer.MAX_VALUE, 10, 10).print(histogram); String[] lines = outputStream.toString().split("\n"); Assert.assertEquals(4, lines.length); Assert.assertEquals("TestHistogram has 1 unique elements and 1 total elements:", lines[0]); diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java --- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java Wed Oct 02 13:26:31 2013 +0200 @@ -22,24 +22,49 @@ */ package com.oracle.graal.debug; -import com.oracle.graal.debug.internal.*; +import static com.oracle.graal.debug.Debug.Initialization.*; import java.io.*; import java.util.*; import java.util.concurrent.*; +import com.oracle.graal.debug.internal.*; + +/** + * Scope based debugging facility. This facility is {@link #isEnabled()} if assertions are enabled + * for the {@link Debug} class or the {@value Initialization#INITIALIZER_PROPERTY_NAME} system + * property is {@code "true"} when {@link Debug} is initialized. + */ public class Debug { - private static boolean ENABLED = false; + /** + * Class to assist with initialization of {@link Debug}. + */ + public static class Initialization { + + public static final String INITIALIZER_PROPERTY_NAME = "graal.debug.enable"; - public static void enable() { - ENABLED = true; + private static boolean initialized; + + /** + * Determines if {@link Debug} has been initialized. + */ + public static boolean isDebugInitialized() { + return initialized; + } + } - public static void disable() { - ENABLED = false; + @SuppressWarnings("all") + private static boolean initialize() { + boolean assertionsEnabled = false; + assert assertionsEnabled = true; + Initialization.initialized = true; + return assertionsEnabled || Boolean.getBoolean(INITIALIZER_PROPERTY_NAME); } + private static final boolean ENABLED = initialize(); + public static boolean isEnabled() { return ENABLED; } @@ -330,7 +355,7 @@ public static DebugMetric metric(String name) { if (ENABLED) { - return new MetricImpl(name); + return new MetricImpl(name, true); } else { return VOID_METRIC; } @@ -342,6 +367,9 @@ } } + /** + * Creates an object for counting value frequencies. + */ public static DebugHistogram createHistogram(String name) { return new DebugHistogramImpl(name); } @@ -402,11 +430,19 @@ public void add(long value) { } + + public void setConditional(boolean flag) { + throw new InternalError("Cannot make void metric conditional"); + } + + public boolean isConditional() { + return false; + } }; public static DebugTimer timer(String name) { if (ENABLED) { - return new TimerImpl(name); + return new TimerImpl(name, true); } else { return VOID_TIMER; } @@ -417,5 +453,13 @@ public TimerCloseable start() { return TimerImpl.VOID_CLOSEABLE; } + + public void setConditional(boolean flag) { + throw new InternalError("Cannot make void timer conditional"); + } + + public boolean isConditional() { + return false; + } }; } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugHistogram.java --- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugHistogram.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugHistogram.java Wed Oct 02 13:26:31 2013 +0200 @@ -22,15 +22,75 @@ */ package com.oracle.graal.debug; -import java.io.*; +import java.util.*; +/** + * Facility for recording value frequencies. + */ public interface DebugHistogram { + /** + * Gets the name specified when this objected was {@linkplain Debug#createHistogram(String) + * created}. + */ String getName(); + /** + * Increments the count for a given value. + */ void add(Object value); - void print(PrintStream os); + /** + * A value and a frequency. The ordering imposed by {@link #compareTo(CountedValue)} places + * values with higher frequencies first. + */ + public class CountedValue implements Comparable { + + private int count; + private final Object value; + + public CountedValue(int count, Object value) { + this.count = count; + this.value = value; + } + + public int compareTo(CountedValue o) { + if (count < o.count) { + return 1; + } else if (count > o.count) { + return -1; + } + return 0; + } - void print(PrintStream os, int limit, int nameSize, int barSize); + @Override + public String toString() { + return count + " -> " + value; + } + + public void inc() { + count++; + } + + public int getCount() { + return count; + } + + public Object getValue() { + return value; + } + } + + /** + * Gets a list of the counted values, sorted in descending order of frequency. + */ + List getValues(); + + /** + * Interface for a service that can render a visualization of a histogram. + */ + public interface Printer { + + void print(DebugHistogram histogram); + } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugMetric.java --- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugMetric.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugMetric.java Wed Oct 02 13:26:31 2013 +0200 @@ -22,9 +22,32 @@ */ package com.oracle.graal.debug; +/** + * A counter for some value of interest. + */ public interface DebugMetric { + /** + * Adds 1 to this counter if metering is {@link Debug#isMeterEnabled() enabled} or this is an + * {@linkplain #isConditional() unconditional} metric. + */ void increment(); + /** + * Adds {@code value} to this counter if metering is {@link Debug#isMeterEnabled() enabled} or + * this is an {@linkplain #isConditional() unconditional} metric. + */ void add(long value); + + /** + * Sets a flag determining if this counter is only enabled if metering is + * {@link Debug#isMeterEnabled() enabled}. + */ + void setConditional(boolean flag); + + /** + * Determines if this counter is only enabled if metering is {@link Debug#isMeterEnabled() + * enabled}. + */ + boolean isConditional(); } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugTimer.java --- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugTimer.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugTimer.java Wed Oct 02 13:26:31 2013 +0200 @@ -24,7 +24,36 @@ import com.oracle.graal.debug.internal.*; +/** + * A timer for some activity of interest. A timer should be deployed using the try-with-resources + * pattern: + * + *
+ * try (TimerCloseable a = timer.start()) {
+ *     // the code to time
+ * }
+ * 
+ */ public interface DebugTimer { + /** + * Starts this timer if timing is {@linkplain Debug#isTimeEnabled() enabled} or this is an + * {@linkplain #isConditional() unconditional} timer. + * + * @return an object that must be closed once the activity has completed to add the elapsed time + * since this call to the total for this timer + */ TimerCloseable start(); + + /** + * Sets a flag determining if this timer is only enabled if metering is + * {@link Debug#isMeterEnabled() enabled}. + */ + void setConditional(boolean flag); + + /** + * Determines if this timer is only enabled if metering is {@link Debug#isMeterEnabled() + * enabled}. + */ + boolean isConditional(); } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/DebugHistogramAsciiPrinter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/DebugHistogramAsciiPrinter.java Wed Oct 02 13:26:31 2013 +0200 @@ -0,0 +1,101 @@ +/* + * 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.debug.internal; + +import java.io.*; +import java.util.*; + +import com.oracle.graal.debug.*; +import com.oracle.graal.debug.DebugHistogram.*; + +/** + * Renders a textual representation of a histogram to a given print stream. + */ +public class DebugHistogramAsciiPrinter implements Printer { + + public static final int NumberSize = 10; + public static final int DefaultNameSize = 50; + public static final int DefaultBarSize = 100; + + private PrintStream os; + private int limit; + private int nameSize; + private int barSize; + + public DebugHistogramAsciiPrinter(PrintStream os) { + this(os, Integer.MAX_VALUE, DefaultNameSize, DefaultBarSize); + } + + /** + * @param os where to print + * @param limit limits printing to the {@code limit} most frequent values + * @param nameSize the width of the value names column + * @param barSize the width of the value frequency column + */ + public DebugHistogramAsciiPrinter(PrintStream os, int limit, int nameSize, int barSize) { + this.os = os; + this.limit = limit; + this.nameSize = nameSize; + this.barSize = barSize; + } + + public void print(DebugHistogram histogram) { + List list = histogram.getValues(); + if (list.isEmpty()) { + os.printf("%s is empty.\n", histogram.getName()); + return; + } + + // Sum up the total number of elements. + int total = 0; + for (CountedValue cv : list) { + total += cv.getCount(); + } + + // Print header. + os.printf("%s has %d unique elements and %d total elements:\n", histogram.getName(), list.size(), total); + + int max = list.get(0).getCount(); + final int lineSize = nameSize + NumberSize + barSize + 10; + printLine(os, '-', lineSize); + String formatString = "| %-" + nameSize + "s | %-" + NumberSize + "d | %-" + barSize + "s |\n"; + for (int i = 0; i < list.size() && i < limit; ++i) { + CountedValue cv = list.get(i); + int value = cv.getCount(); + char[] bar = new char[(int) (((double) value / (double) max) * barSize)]; + Arrays.fill(bar, '='); + String objectString = String.valueOf(cv.getValue()); + if (objectString.length() > nameSize) { + objectString = objectString.substring(0, nameSize - 3) + "..."; + } + os.printf(formatString, objectString, value, new String(bar)); + } + printLine(os, '-', lineSize); + } + + private static void printLine(PrintStream printStream, char c, int lineSize) { + char[] charArr = new char[lineSize]; + Arrays.fill(charArr, c); + printStream.printf("%s\n", new String(charArr)); + } +} diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/DebugHistogramImpl.java --- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/DebugHistogramImpl.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/DebugHistogramImpl.java Wed Oct 02 13:26:31 2013 +0200 @@ -22,28 +22,25 @@ */ package com.oracle.graal.debug.internal; -import java.io.*; import java.util.*; import com.oracle.graal.debug.*; public class DebugHistogramImpl implements DebugHistogram { - public static final int NumberSize = 10; - public static final int DefaultNameSize = 50; - public static final int DefaultBarSize = 100; private final String name; - private HashMap map = new HashMap<>(); + private HashMap map = new HashMap<>(); public DebugHistogramImpl(String name) { this.name = name; } public void add(Object value) { - if (!map.containsKey(value)) { - map.put(value, 1); + CountedValue cv = map.get(value); + if (cv == null) { + map.put(value, new CountedValue(1, value)); } else { - map.put(value, map.get(value) + 1); + cv.inc(); } } @@ -52,59 +49,9 @@ return name; } - @Override - public void print(PrintStream os) { - print(os, Integer.MAX_VALUE, DefaultNameSize, DefaultBarSize); - } - - public void print(PrintStream os, int limit, int nameSize, int barSize) { - - List list = new ArrayList<>(map.keySet()); - if (list.size() == 0) { - // No elements in the histogram. - os.printf("%s is empty.\n", name); - return; - } - - // Sort from highest to smallest. - Collections.sort(list, new Comparator() { - - @Override - public int compare(Object o1, Object o2) { - return map.get(o2) - map.get(o1); - } - }); - - // Sum up the total number of elements. - int total = 0; - for (Object o : list) { - total += map.get(o); - } - - // Print header. - os.printf("%s has %d unique elements and %d total elements:\n", name, list.size(), total); - - int max = map.get(list.get(0)); - final int lineSize = nameSize + NumberSize + barSize + 10; - printLine(os, '-', lineSize); - String formatString = "| %-" + nameSize + "s | %-" + NumberSize + "d | %-" + barSize + "s |\n"; - for (int i = 0; i < list.size() && i < limit; ++i) { - Object o = list.get(i); - int value = map.get(o); - char[] bar = new char[(int) (((double) value / (double) max) * barSize)]; - Arrays.fill(bar, '='); - String objectString = o.toString(); - if (objectString.length() > nameSize) { - objectString = objectString.substring(0, nameSize - 3) + "..."; - } - os.printf(formatString, objectString, value, new String(bar)); - } - printLine(os, '-', lineSize); - } - - private static void printLine(PrintStream printStream, char c, int lineSize) { - char[] charArr = new char[lineSize]; - Arrays.fill(charArr, c); - printStream.printf("%s\n", new String(charArr)); + public List getValues() { + ArrayList res = new ArrayList<>(map.values()); + Collections.sort(res); + return res; } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/DebugHistogramRPrinter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/DebugHistogramRPrinter.java Wed Oct 02 13:26:31 2013 +0200 @@ -0,0 +1,81 @@ +/* + * 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.debug.internal; + +import java.io.*; +import java.util.*; + +import com.oracle.graal.debug.*; +import com.oracle.graal.debug.DebugHistogram.CountedValue; +import com.oracle.graal.debug.DebugHistogram.Printer; + +/** + * Renders a histogram as an R script to a given print stream. The R script emitted for a histogram + * is a simple set of statements for defining a vector of named objects. + */ +public class DebugHistogramRPrinter implements Printer { + + private PrintStream os; + private int limit; + + public DebugHistogramRPrinter(PrintStream os) { + this(os, Integer.MAX_VALUE); + } + + /** + * @param os where to print + * @param limit limits printing to the {@code limit} most frequent values + */ + public DebugHistogramRPrinter(PrintStream os, int limit) { + this.os = os; + this.limit = limit; + } + + public void print(DebugHistogram histogram) { + List list = histogram.getValues(); + if (list.isEmpty()) { + return; + } + + String var = histogram.getName().replace('-', '.').replace(' ', '_'); + os.print(var + " <- c("); + for (int i = 0; i < list.size() && i < limit; ++i) { + CountedValue cv = list.get(i); + if (i != 0) { + os.print(", "); + } + os.print(cv.getCount()); + } + os.println(");"); + + os.print("names(" + var + ") <- c("); + for (int i = 0; i < list.size() && i < limit; ++i) { + CountedValue cv = list.get(i); + if (i != 0) { + os.print(", "); + } + os.print("\"" + cv.getValue() + "\""); + } + os.println(");"); + } +} diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/DebugScope.java --- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/DebugScope.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/DebugScope.java Wed Oct 02 13:26:31 2013 +0200 @@ -92,7 +92,6 @@ private static ThreadLocal instanceTL = new ThreadLocal<>(); private static ThreadLocal configTL = new ThreadLocal<>(); private static ThreadLocal lastExceptionThrownTL = new ThreadLocal<>(); - private static DebugTimer scopeTime = Debug.timer("ScopeTime"); private final DebugScope parent; private IndentImpl lastUsedIndent; @@ -210,6 +209,9 @@ for (DebugDumpHandler dumpHandler : config.dumpHandlers()) { dumpHandler.dump(object, message); } + } else { + PrintStream out = System.out; + out.println("Forced dump ignored because debugging is disabled - use -G:Dump=xxx option"); } } @@ -239,7 +241,7 @@ } instanceTL.set(newChild); newChild.updateFlags(); - try (TimerCloseable a = scopeTime.start()) { + try { return executeScope(runnable, callable); } finally { newChild.context = null; diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/DebugValue.java --- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/DebugValue.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/DebugValue.java Wed Oct 02 13:26:31 2013 +0200 @@ -30,10 +30,12 @@ private final String name; private int index; + private boolean conditional; - protected DebugValue(String name) { + protected DebugValue(String name, boolean conditional) { this.name = name; this.index = -1; + this.conditional = conditional; } protected long getCurrentValue() { @@ -46,6 +48,14 @@ DebugScope.getInstance().setCurrentValue(index, l); } + public void setConditional(boolean flag) { + conditional = flag; + } + + public boolean isConditional() { + return conditional; + } + private void ensureInitialized() { if (index == -1) { index = KeyRegistry.register(this); diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/MetricImpl.java --- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/MetricImpl.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/MetricImpl.java Wed Oct 02 13:26:31 2013 +0200 @@ -26,8 +26,8 @@ public final class MetricImpl extends DebugValue implements DebugMetric { - public MetricImpl(String name) { - super(name); + public MetricImpl(String name, boolean conditional) { + super(name, conditional); } public void increment() { @@ -35,7 +35,7 @@ } public void add(long value) { - if (Debug.isMeterEnabled()) { + if (!isConditional() || Debug.isMeterEnabled()) { super.addToCurrentValue(value); } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/TimerCloseable.java --- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/TimerCloseable.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/TimerCloseable.java Wed Oct 02 13:26:31 2013 +0200 @@ -22,6 +22,12 @@ */ package com.oracle.graal.debug.internal; +import com.oracle.graal.debug.*; + +/** + * An object returned by {@link DebugTimer#start()} that when closed, stops the associated timer and + * adds the elapsed time since {@code start()} to the total for the timer. + */ public interface TimerCloseable extends AutoCloseable { void close(); diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/TimerImpl.java --- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/TimerImpl.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/TimerImpl.java Wed Oct 02 13:26:31 2013 +0200 @@ -37,59 +37,78 @@ } }; - private ThreadLocal valueToSubstract = new ThreadLocal<>(); + /** + * Records the most recent active timer. + */ + private static ThreadLocal currentTimer = new ThreadLocal<>(); + + private final DebugValue flat; - public TimerImpl(String name) { - super(name); + public TimerImpl(String name, boolean conditional) { + super(name + "_Accm", conditional); + this.flat = new DebugValue(name + "_Flat", conditional) { + + @Override + public String toString(long value) { + return valueToString(value); + } + }; } @Override public TimerCloseable start() { - if (Debug.isTimeEnabled()) { + if (!isConditional() || Debug.isTimeEnabled()) { long startTime; if (threadMXBean.isCurrentThreadCpuTimeSupported()) { startTime = threadMXBean.getCurrentThreadCpuTime(); } else { startTime = System.nanoTime(); } - if (valueToSubstract.get() == null) { - valueToSubstract.set(0L); - } - long previousValueToSubstract = valueToSubstract.get(); + AbstractTimer result; if (threadMXBean.isCurrentThreadCpuTimeSupported()) { - result = new CpuTimeTimer(startTime, previousValueToSubstract); + result = new CpuTimeTimer(startTime); } else { - result = new SystemNanosTimer(startTime, previousValueToSubstract); + result = new SystemNanosTimer(startTime); } - valueToSubstract.set(0L); + currentTimer.set(result); return result; } else { return VOID_CLOSEABLE; } } + public static String valueToString(long value) { + return String.format("%d.%d ms", value / 1000000, (value / 100000) % 10); + } + @Override public String toString(long value) { - return String.format("%d.%d ms", value / 1000000, (value / 100000) % 10); + return valueToString(value); } private abstract class AbstractTimer implements TimerCloseable { + private final AbstractTimer parent; private final long startTime; - private final long previousValueToSubstract; + private long nestedTimeToSubtract; - private AbstractTimer(long startTime, long previousValueToSubstract) { + private AbstractTimer(long startTime) { + this.parent = currentTimer.get(); this.startTime = startTime; - this.previousValueToSubstract = previousValueToSubstract; } @Override public void close() { - long timeSpan = currentTime() - startTime; - long oldValueToSubstract = valueToSubstract.get(); - valueToSubstract.set(timeSpan + previousValueToSubstract); - TimerImpl.this.addToCurrentValue(timeSpan - oldValueToSubstract); + long endTime = currentTime(); + long timeSpan = endTime - startTime; + if (parent != null) { + parent.nestedTimeToSubtract += timeSpan; + } + currentTimer.set(parent); + long flatTime = timeSpan - nestedTimeToSubtract; + TimerImpl.this.addToCurrentValue(timeSpan); + flat.addToCurrentValue(flatTime); } protected abstract long currentTime(); @@ -97,8 +116,8 @@ private final class SystemNanosTimer extends AbstractTimer { - public SystemNanosTimer(long startTime, long previousValueToSubstract) { - super(startTime, previousValueToSubstract); + public SystemNanosTimer(long startTime) { + super(startTime); } @Override @@ -109,8 +128,8 @@ private final class CpuTimeTimer extends AbstractTimer { - public CpuTimeTimer(long startTime, long previousValueToSubstract) { - super(startTime, previousValueToSubstract); + public CpuTimeTimer(long startTime) { + super(startTime); } @Override diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/TypedNodeIteratorTest.java --- a/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/TypedNodeIteratorTest.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/TypedNodeIteratorTest.java Wed Oct 02 13:26:31 2013 +0200 @@ -32,7 +32,7 @@ public class TypedNodeIteratorTest { - private static class TestNode extends Node implements Node.IterableNodeType, TestNodeInterface { + private static class TestNode extends Node implements IterableNodeType, TestNodeInterface { private final String name; diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/TypedNodeIteratorTest2.java --- a/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/TypedNodeIteratorTest2.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/TypedNodeIteratorTest2.java Wed Oct 02 13:26:31 2013 +0200 @@ -43,7 +43,7 @@ } } - private static class NodeB extends NodeA implements Node.IterableNodeType { + private static class NodeB extends NodeA implements IterableNodeType { public NodeB(String name) { super(name); diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java Wed Oct 02 13:26:31 2013 +0200 @@ -25,7 +25,6 @@ import java.util.*; import com.oracle.graal.graph.GraphEvent.NodeEvent; -import com.oracle.graal.graph.Node.IterableNodeType; import com.oracle.graal.graph.Node.ValueNumberable; import com.oracle.graal.graph.iterators.*; @@ -57,8 +56,8 @@ private int deletedNodeCount; private GraphEventLog eventLog; - NodeChangedListener inputChanged; - NodeChangedListener usagesDroppedZero; + NodeChangedListener inputChangedListener; + NodeChangedListener usagesDroppedToZeroListener; private final HashMap cachedNodes = new HashMap<>(); private static final class CacheEntry { @@ -66,6 +65,8 @@ private final Node node; public CacheEntry(Node node) { + assert node.getNodeClass().valueNumberable(); + assert node.getNodeClass().isLeafNode(); this.node = node; } @@ -82,8 +83,8 @@ if (obj instanceof CacheEntry) { CacheEntry other = (CacheEntry) obj; NodeClass nodeClass = node.getNodeClass(); - if (other.node.getNodeClass() == nodeClass) { - return nodeClass.valueNumberable() && nodeClass.valueEqual(node, other.node) && nodeClass.edgesEqual(node, other.node); + if (other.node.getClass() == node.getClass()) { + return nodeClass.valueEqual(node, other.node); } } return false; @@ -156,7 +157,7 @@ int usageModCount(Node node) { int id = extractOriginalNodeId(node); if (id >= 0 && id < nodeUsageModCounts.length) { - return nodeUsageModCounts[node.id]; + return nodeUsageModCounts[id]; } return 0; } @@ -187,8 +188,7 @@ */ public Graph copy(String newName) { Graph copy = new Graph(newName); - Map emptyMap = Collections.emptyMap(); - copy.addDuplicates(getNodes(), emptyMap); + copy.addDuplicates(getNodes(), this, this.getNodeCount(), (Map) null); return copy; } @@ -223,6 +223,24 @@ * @return the node which was added to the graph */ public T add(T node) { + if (node.getNodeClass().valueNumberable()) { + throw new IllegalStateException("Using add for value numberable node. Consider using either unique or addWithoutUnique."); + } + return addHelper(node); + } + + public T addWithoutUnique(T node) { + return addHelper(node); + } + + public T addOrUnique(T node) { + if (node.getNodeClass().valueNumberable()) { + return uniqueHelper(node); + } + return add(node); + } + + private T addHelper(T node) { node.initialize(this); return node; } @@ -232,24 +250,54 @@ void nodeChanged(Node node); } - public void trackInputChange(NodeChangedListener inputChangedListener) { - assert this.inputChanged == null; - this.inputChanged = inputChangedListener; + private static class ChainedNodeChangedListener implements NodeChangedListener { + + NodeChangedListener head; + NodeChangedListener next; + + ChainedNodeChangedListener(NodeChangedListener head, NodeChangedListener next) { + this.head = head; + this.next = next; + } + + public void nodeChanged(Node node) { + head.nodeChanged(node); + next.nodeChanged(node); + } + } + + public void trackInputChange(NodeChangedListener listener) { + if (inputChangedListener == null) { + inputChangedListener = listener; + } else { + inputChangedListener = new ChainedNodeChangedListener(listener, inputChangedListener); + } } public void stopTrackingInputChange() { - assert inputChanged != null; - inputChanged = null; + assert inputChangedListener != null; + if (inputChangedListener instanceof ChainedNodeChangedListener) { + inputChangedListener = ((ChainedNodeChangedListener) inputChangedListener).next; + } else { + inputChangedListener = null; + } } - public void trackUsagesDroppedZero(NodeChangedListener usagesDroppedZeroListener) { - assert this.usagesDroppedZero == null; - this.usagesDroppedZero = usagesDroppedZeroListener; + public void trackUsagesDroppedZero(NodeChangedListener listener) { + if (usagesDroppedToZeroListener == null) { + usagesDroppedToZeroListener = listener; + } else { + usagesDroppedToZeroListener = new ChainedNodeChangedListener(listener, usagesDroppedToZeroListener); + } } public void stopTrackingUsagesDroppedZero() { - assert usagesDroppedZero != null; - usagesDroppedZero = null; + assert usagesDroppedToZeroListener != null; + if (usagesDroppedToZeroListener instanceof ChainedNodeChangedListener) { + usagesDroppedToZeroListener = ((ChainedNodeChangedListener) usagesDroppedToZeroListener).next; + } else { + usagesDroppedToZeroListener = null; + } } /** @@ -261,53 +309,76 @@ * @return the node which was added to the graph or a similar which was already in the * graph. */ - @SuppressWarnings("unchecked") public T unique(T node) { assert checkValueNumberable(node); + return uniqueHelper(node); + } - for (Node input : node.inputs()) { - if (input != null) { - for (Node usage : input.usages()) { - if (usage != node && node.getNodeClass().valueEqual(node, usage) && node.getNodeClass().edgesEqual(node, usage)) { - return (T) usage; - } - } - return add(node); + @SuppressWarnings("unchecked") + T uniqueHelper(T node) { + assert node.getNodeClass().valueNumberable(); + Node other = this.findDuplicate(node); + if (other != null) { + return (T) other; + } else { + Node result = addHelper(node); + if (node.getNodeClass().isLeafNode()) { + putNodeIntoCache(result); } - } - Node cachedNode = cachedNodes.get(new CacheEntry(node)); - if (cachedNode != null && cachedNode.isAlive()) { - return (T) cachedNode; - } else { - Node result = add(node); - cachedNodes.put(new CacheEntry(node), result); return (T) result; } } + void putNodeIntoCache(Node node) { + assert node.graph() == this || node.graph() == null; + assert node.getNodeClass().valueNumberable(); + assert node.getNodeClass().isLeafNode() : node.getClass(); + cachedNodes.put(new CacheEntry(node), node); + } + + Node findNodeInCache(Node node) { + CacheEntry key = new CacheEntry(node); + Node result = cachedNodes.get(key); + if (result != null && result.isDeleted()) { + cachedNodes.remove(key); + return null; + } + return result; + } + public Node findDuplicate(Node node) { - if (node.getNodeClass().valueNumberable()) { + NodeClass nodeClass = node.getNodeClass(); + assert nodeClass.valueNumberable(); + if (nodeClass.isLeafNode()) { + Node cachedNode = findNodeInCache(node); + if (cachedNode != null) { + return cachedNode; + } else { + return null; + } + } else { + + int minCount = Integer.MAX_VALUE; + Node minCountNode = null; for (Node input : node.inputs()) { if (input != null) { - for (Node usage : input.usages()) { - if (usage != node && node.getNodeClass().valueEqual(node, usage) && node.getNodeClass().edgesEqual(node, usage)) { - return usage; - } + int estimate = input.getUsageCountUpperBound(); + if (estimate == 0) { + return null; + } else if (estimate < minCount) { + minCount = estimate; + minCountNode = input; } - return null; } } - } - CacheEntry key = new CacheEntry(node); - Node cachedNode = cachedNodes.get(key); - if (cachedNode != null) { - if (!cachedNode.isAlive()) { - cachedNodes.remove(key); + if (minCountNode != null) { + for (Node usage : minCountNode.usages()) { + if (usage != node && nodeClass == usage.getNodeClass() && nodeClass.valueEqual(node, usage) && nodeClass.edgesEqual(node, usage)) { + return usage; + } + } return null; } - return cachedNode != node ? cachedNode : null; - } else { - cachedNodes.put(key, node); return null; } } @@ -319,6 +390,10 @@ return true; } + public boolean isNew(int mark, Node node) { + return node.id >= mark; + } + /** * Gets a mark that can be used with {@link #getNewNodes(int)}. */ @@ -518,7 +593,7 @@ * {@code type}. * * @param type the type of node to return - * @return an {@link Iterable} providing all the matching nodes. + * @return an {@link Iterable} providing all the matching nodes */ public NodeIterable getNodes(final Class type) { final NodeClass nodeClass = NodeClass.get(type); @@ -671,14 +746,14 @@ * @param replacementsMap the replacement map (can be null if no replacement is to be performed) * @return a map which associates the original nodes from {@code nodes} to their duplicates */ - public Map addDuplicates(Iterable newNodes, Map replacementsMap) { + public Map addDuplicates(Iterable newNodes, final Graph oldGraph, int estimatedNodeCount, Map replacementsMap) { DuplicationReplacement replacements; if (replacementsMap == null) { replacements = null; } else { replacements = new MapReplacement(replacementsMap); } - return addDuplicates(newNodes, replacements); + return addDuplicates(newNodes, oldGraph, estimatedNodeCount, replacements); } public interface DuplicationReplacement { @@ -702,19 +777,8 @@ } - private static final DuplicationReplacement NO_REPLACEMENT = new DuplicationReplacement() { - - @Override - public Node replacement(Node original) { - return original; - } - }; - @SuppressWarnings("all") - public Map addDuplicates(Iterable newNodes, DuplicationReplacement replacements) { - if (replacements == null) { - replacements = NO_REPLACEMENT; - } - return NodeClass.addGraphDuplicate(this, newNodes, replacements); + public Map addDuplicates(Iterable newNodes, final Graph oldGraph, int estimatedNodeCount, DuplicationReplacement replacements) { + return NodeClass.addGraphDuplicate(this, oldGraph, estimatedNodeCount, newNodes, replacements); } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.graph/src/com/oracle/graal/graph/IterableNodeType.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/IterableNodeType.java Wed Oct 02 13:26:31 2013 +0200 @@ -0,0 +1,32 @@ +/* + * 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.graph; + +/** + * A marker for a node type supporting {@linkplain Graph#getNodes(Class) fast iteration} of its + * instances in a graph. The support for fast iteration comes with a memory cost (e.g., extra data + * structures {@link Graph}) so only node types for which fast iteration provides a compilation + * performance benefit should implement this interface. + */ +public interface IterableNodeType { +} diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java Wed Oct 02 13:26:31 2013 +0200 @@ -104,6 +104,9 @@ /** * Determines if the stamp of the instantiated intrinsic node has its stamp set from the * return type of the annotated method. + *

+ * When it is set to true, the stamp that is passed in to the constructor of ValueNode is + * ignored and can therefore safely be {@code null}. */ boolean setStampFromReturnType() default false; } @@ -111,9 +114,6 @@ public interface ValueNumberable { } - public interface IterableNodeType { - } - private Graph graph; int id; @@ -240,6 +240,16 @@ } } + int getUsageCountUpperBound() { + if (usage0 == null) { + return 0; + } + if (usage1 == null) { + return 1; + } + return 2 + extraUsages.length; + } + /** * Gets the list of nodes that use this node (e.g., as an input). */ @@ -423,15 +433,15 @@ assert assertTrue(result, "not found in usages, old input: %s", oldInput); } if (newInput != null) { - NodeChangedListener inputChanged = graph.inputChanged; - if (inputChanged != null) { - inputChanged.nodeChanged(this); + NodeChangedListener listener = graph.inputChangedListener; + if (listener != null) { + listener.nodeChanged(this); } newInput.addUsage(this); } else if (oldInput != null && oldInput.usages().isEmpty()) { - NodeChangedListener nodeChangedListener = graph.usagesDroppedZero; - if (nodeChangedListener != null) { - nodeChangedListener.nodeChanged(oldInput); + NodeChangedListener listener = graph.usagesDroppedToZeroListener; + if (listener != null) { + listener.nodeChanged(oldInput); } } } @@ -449,7 +459,7 @@ oldSuccessor.predecessor = null; } if (newSuccessor != null) { - assert assertTrue(newSuccessor.predecessor == null, "unexpected non-null predecessor in new successor (%s): %s", newSuccessor, newSuccessor.predecessor); + assert assertTrue(newSuccessor.predecessor == null, "unexpected non-null predecessor in new successor (%s): %s, this=%s", newSuccessor, newSuccessor.predecessor, this); newSuccessor.predecessor = this; } } @@ -485,9 +495,9 @@ boolean result = usage.getNodeClass().replaceFirstInput(usage, this, other); assert assertTrue(result, "not found in inputs, usage: %s", usage); if (other != null) { - NodeChangedListener inputChanged = graph.inputChanged; - if (inputChanged != null) { - inputChanged.nodeChanged(usage); + NodeChangedListener listener = graph.inputChangedListener; + if (listener != null) { + listener.nodeChanged(usage); } other.addUsage(usage); } @@ -532,9 +542,9 @@ for (Node input : inputs()) { removeThisFromUsages(input); if (input.usages().isEmpty()) { - NodeChangedListener nodeChangedListener = graph.usagesDroppedZero; - if (nodeChangedListener != null) { - nodeChangedListener.nodeChanged(input); + NodeChangedListener listener = graph.usagesDroppedToZeroListener; + if (listener != null) { + listener.nodeChanged(input); } } } @@ -584,15 +594,31 @@ return newNode; } - public Node clone(Graph into) { + static int count = 0; + + public final Node clone(Graph into) { + return clone(into, true); + } + + final Node clone(Graph into, boolean clearInputsAndSuccessors) { + NodeClass nodeClass = getNodeClass(); + if (nodeClass.valueNumberable() && nodeClass.isLeafNode()) { + Node otherNode = into.findNodeInCache(this); + if (otherNode != null) { + return otherNode; + } + } + Node newNode = null; try { newNode = (Node) this.clone(); } catch (CloneNotSupportedException e) { throw new GraalInternalError(e).addContext(this); } - getNodeClass().clearInputs(newNode); - getNodeClass().clearSuccessors(newNode); + if (clearInputsAndSuccessors) { + nodeClass.clearInputs(newNode); + nodeClass.clearSuccessors(newNode); + } newNode.graph = into; newNode.typeCacheNext = null; newNode.id = INITIAL_ID; @@ -601,9 +627,17 @@ newNode.usage1 = null; newNode.extraUsages = NO_NODES; newNode.predecessor = null; + + if (nodeClass.valueNumberable() && nodeClass.isLeafNode()) { + into.putNodeIntoCache(newNode); + } + newNode.afterClone(this); return newNode; } + protected void afterClone(@SuppressWarnings("unused") Node other) { + } + public boolean verify() { assertTrue(isAlive(), "cannot verify inactive nodes (id=%d)", id); assertTrue(graph() != null, "null graph"); @@ -779,6 +813,7 @@ boolean neighborsAlternate = ((flags & FormattableFlags.LEFT_JUSTIFY) == FormattableFlags.LEFT_JUSTIFY); int neighborsFlags = (neighborsAlternate ? FormattableFlags.ALTERNATE | FormattableFlags.LEFT_JUSTIFY : 0); + NodeClass nodeClass = getNodeClass(); if (width > 0) { if (this.predecessor != null) { formatter.format(" pred={"); @@ -789,10 +824,10 @@ NodeClassIterator inputIter = inputs().iterator(); while (inputIter.hasNext()) { Position position = inputIter.nextPosition(); - Node input = getNodeClass().get(this, position); + Node input = nodeClass.get(this, position); if (input != null) { formatter.format(" "); - formatter.format(getNodeClass().getName(position)); + formatter.format(nodeClass.getName(position)); formatter.format("={"); input.formatTo(formatter, neighborsFlags, width - 1, 0); formatter.format("}"); @@ -817,10 +852,10 @@ NodeClassIterator succIter = successors().iterator(); while (succIter.hasNext()) { Position position = succIter.nextPosition(); - Node successor = getNodeClass().get(this, position); + Node successor = nodeClass.get(this, position); if (successor != null) { formatter.format(" "); - formatter.format(getNodeClass().getName(position)); + formatter.format(nodeClass.getName(position)); formatter.format("={"); successor.formatTo(formatter, neighborsFlags, 0, precision - 1); formatter.format("}"); diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java Wed Oct 02 13:26:31 2013 +0200 @@ -26,12 +26,11 @@ import java.lang.reflect.*; import java.util.*; -import java.util.Map.Entry; import java.util.concurrent.*; +import com.oracle.graal.debug.*; import com.oracle.graal.graph.Graph.DuplicationReplacement; import com.oracle.graal.graph.Node.Input; -import com.oracle.graal.graph.Node.IterableNodeType; import com.oracle.graal.graph.Node.Successor; import com.oracle.graal.graph.Node.Verbosity; @@ -139,12 +138,16 @@ private final long[] successorOffsets; private final Class[] dataTypes; private final boolean canGVN; + private final boolean isLeafNode; private final int startGVNNumber; private final String shortName; private final String nameTemplate; private final int iterableId; private int[] iterableIds; + private static final DebugMetric ITERABLE_NODE_TYPES = Debug.metric("IterableNodeTypes"); + private final DebugMetric nodeIterableCount; + private NodeClass(Class clazz) { super(clazz); assert NODE_CLASS.isAssignableFrom(clazz); @@ -185,14 +188,15 @@ } this.nameTemplate = newNameTemplate == null ? newShortName : newNameTemplate; this.shortName = newShortName; - if (Node.IterableNodeType.class.isAssignableFrom(clazz)) { + if (IterableNodeType.class.isAssignableFrom(clazz)) { + ITERABLE_NODE_TYPES.increment(); this.iterableId = nextIterableId++; List existingClasses = new LinkedList<>(); for (FieldIntrospection nodeClass : allClasses.values()) { if (clazz.isAssignableFrom(nodeClass.clazz)) { existingClasses.add((NodeClass) nodeClass); } - if (nodeClass.clazz.isAssignableFrom(clazz) && Node.IterableNodeType.class.isAssignableFrom(nodeClass.clazz)) { + if (nodeClass.clazz.isAssignableFrom(clazz) && IterableNodeType.class.isAssignableFrom(nodeClass.clazz)) { NodeClass superNodeClass = (NodeClass) nodeClass; superNodeClass.iterableIds = Arrays.copyOf(superNodeClass.iterableIds, superNodeClass.iterableIds.length + 1); superNodeClass.iterableIds[superNodeClass.iterableIds.length - 1] = this.iterableId; @@ -209,6 +213,9 @@ this.iterableId = NOT_ITERABLE; this.iterableIds = null; } + + isLeafNode = (this.inputOffsets.length == 0 && this.successorOffsets.length == 0); + nodeIterableCount = Debug.metric("NodeIterable_" + shortName); } @Override @@ -236,6 +243,7 @@ } public int[] iterableIds() { + nodeIterableCount.increment(); return iterableIds; } @@ -247,6 +255,10 @@ return canGVN; } + public boolean isLeafNode() { + return isLeafNode; + } + public static int cacheSize() { return nextIterableId; } @@ -417,6 +429,7 @@ */ public static final class NodeClassIterator implements Iterator { + private final NodeClass nodeClass; private final Node node; private final int modCount; private final int directCount; @@ -434,6 +447,7 @@ */ private NodeClassIterator(Node node, long[] offsets, int directCount) { this.node = node; + this.nodeClass = node.getNodeClass(); this.modCount = MODIFICATION_COUNTS_ENABLED ? node.modCount() : 0; this.offsets = offsets; this.directCount = directCount; @@ -500,9 +514,9 @@ public Position nextPosition() { try { if (index < directCount) { - return new Position(offsets == node.getNodeClass().inputOffsets, index, NOT_ITERABLE); + return new Position(offsets == nodeClass.inputOffsets, index, NOT_ITERABLE); } else { - return new Position(offsets == node.getNodeClass().inputOffsets, index, subIndex); + return new Position(offsets == nodeClass.inputOffsets, index, subIndex); } } finally { forward(); @@ -581,7 +595,7 @@ } public boolean valueEqual(Node a, Node b) { - if (!canGVN || a.getNodeClass() != b.getNodeClass()) { + if (!canGVN || a.getClass() != b.getClass()) { return a == b; } for (int i = 0; i < dataOffsets.length; ++i) { @@ -659,6 +673,84 @@ return fieldNames.get(pos.input ? inputOffsets[pos.index] : successorOffsets[pos.index]); } + void updateInputSuccInPlace(Node node, InplaceUpdateClosure duplicationReplacement) { + int index = 0; + while (index < directInputCount) { + Node input = getNode(node, inputOffsets[index]); + if (input != null) { + Node newInput = duplicationReplacement.replacement(input, true); + node.updateUsages(null, newInput); + putNode(node, inputOffsets[index], newInput); + } + index++; + } + + if (index < inputOffsets.length) { + updateInputLists(node, duplicationReplacement, index); + } + + index = 0; + while (index < directSuccessorCount) { + Node successor = getNode(node, successorOffsets[index]); + if (successor != null) { + Node newSucc = duplicationReplacement.replacement(successor, false); + node.updatePredecessor(null, newSucc); + putNode(node, successorOffsets[index], newSucc); + } + index++; + } + + if (index < successorOffsets.length) { + updateSuccLists(node, duplicationReplacement, index); + } + } + + private void updateInputLists(Node node, InplaceUpdateClosure duplicationReplacement, int startIndex) { + int index = startIndex; + while (index < inputOffsets.length) { + NodeList list = getNodeList(node, inputOffsets[index]); + putNodeList(node, inputOffsets[index], updateInputListCopy(list, node, duplicationReplacement)); + assert list != null : clazz; + index++; + } + } + + private void updateSuccLists(Node node, InplaceUpdateClosure duplicationReplacement, int startIndex) { + int index = startIndex; + while (index < successorOffsets.length) { + NodeList list = getNodeList(node, successorOffsets[index]); + putNodeList(node, successorOffsets[index], updateSuccListCopy(list, node, duplicationReplacement)); + assert list != null : clazz; + index++; + } + } + + private static NodeInputList updateInputListCopy(NodeList list, Node node, InplaceUpdateClosure duplicationReplacement) { + int size = list.size(); + NodeInputList result = new NodeInputList<>(node, size); + for (int i = 0; i < list.count(); ++i) { + Node oldNode = list.get(i); + if (oldNode != null) { + Node newNode = duplicationReplacement.replacement(oldNode, true); + result.set(i, newNode); + } + } + return result; + } + + private static NodeSuccessorList updateSuccListCopy(NodeList list, Node node, InplaceUpdateClosure duplicationReplacement) { + int size = list.size(); + NodeSuccessorList result = new NodeSuccessorList<>(node, size); + for (int i = 0; i < list.count(); ++i) { + Node oldNode = list.get(i); + if (oldNode != null) { + Node newNode = duplicationReplacement.replacement(oldNode, false); + result.set(i, newNode); + } + } + return result; + } + public void set(Node node, Position pos, Node x) { long offset = pos.input ? inputOffsets[pos.index] : successorOffsets[pos.index]; if (pos.subIndex == NOT_ITERABLE) { @@ -955,78 +1047,113 @@ return nameTemplate; } - static Map addGraphDuplicate(Graph graph, Iterable nodes, DuplicationReplacement replacements) { - Map newNodes = new IdentityHashMap<>(); - Map replacementsMap = new IdentityHashMap<>(); - // create node duplicates + interface InplaceUpdateClosure { + + Node replacement(Node node, boolean isInput); + } + + static Map addGraphDuplicate(final Graph graph, final Graph oldGraph, int estimatedNodeCount, Iterable nodes, final DuplicationReplacement replacements) { + final Map newNodes = (estimatedNodeCount > (oldGraph.getNodeCount() + oldGraph.getDeletedNodeCount() >> 4)) ? new NodeNodeMap(oldGraph) : new IdentityHashMap(); + createNodeDuplicates(graph, nodes, replacements, newNodes); + + InplaceUpdateClosure replacementClosure = new InplaceUpdateClosure() { + + public Node replacement(Node node, boolean isInput) { + Node target = newNodes.get(node); + if (target == null) { + Node replacement = node; + if (replacements != null) { + replacement = replacements.replacement(node); + } + if (replacement != node) { + target = replacement; + } else if (node.graph() == graph && isInput) { + // patch to the outer world + target = node; + } + + } + return target; + } + + }; + + // re-wire inputs + for (Node oldNode : nodes) { + Node node = newNodes.get(oldNode); + NodeClass oldNodeClass = oldNode.getNodeClass(); + NodeClass nodeClass = node.getNodeClass(); + if (replacements == null || replacements.replacement(oldNode) == oldNode) { + nodeClass.updateInputSuccInPlace(node, replacementClosure); + } else { + transferValuesDifferentNodeClass(graph, replacements, newNodes, oldNode, node, oldNodeClass, nodeClass); + } + } + + return newNodes; + } + + private static void createNodeDuplicates(final Graph graph, Iterable nodes, final DuplicationReplacement replacements, final Map newNodes) { for (Node node : nodes) { if (node != null) { assert !node.isDeleted() : "trying to duplicate deleted node: " + node; - Node replacement = replacements.replacement(node); + Node replacement = node; + if (replacements != null) { + replacement = replacements.replacement(node); + } if (replacement != node) { assert replacement != null; newNodes.put(node, replacement); } else { - Node newNode = node.clone(graph); + Node newNode = node.clone(graph, false); + assert newNode.usages().count() == 0 || newNode.inputs().count() == 0; assert newNode.getClass() == node.getClass(); newNodes.put(node, newNode); } } } - // re-wire inputs - for (Entry entry : newNodes.entrySet()) { - Node oldNode = entry.getKey(); - Node node = entry.getValue(); - for (NodeClassIterator iter = oldNode.inputs().iterator(); iter.hasNext();) { - Position pos = iter.nextPosition(); - if (!pos.isValidFor(node, oldNode)) { - continue; + } + + private static void transferValuesDifferentNodeClass(final Graph graph, final DuplicationReplacement replacements, final Map newNodes, Node oldNode, Node node, NodeClass oldNodeClass, + NodeClass nodeClass) { + for (NodeClassIterator iter = oldNode.inputs().iterator(); iter.hasNext();) { + Position pos = iter.nextPosition(); + if (!nodeClass.isValid(pos, oldNodeClass)) { + continue; + } + Node input = oldNodeClass.get(oldNode, pos); + Node target = newNodes.get(input); + if (target == null) { + Node replacement = input; + if (replacements != null) { + replacement = replacements.replacement(input); } - Node input = oldNode.getNodeClass().get(oldNode, pos); - Node target = newNodes.get(input); - if (target == null) { - target = replacementsMap.get(input); - if (target == null) { - Node replacement = replacements.replacement(input); - if (replacement != input) { - replacementsMap.put(input, replacement); - assert isAssignable(node.getNodeClass().fieldTypes.get(node.getNodeClass().inputOffsets[pos.index]), replacement); - target = replacement; - } else if (input.graph() == graph) { // patch to the outer world - target = input; - } - } + if (replacement != input) { + assert isAssignable(nodeClass.fieldTypes.get(nodeClass.inputOffsets[pos.index]), replacement); + target = replacement; + } else if (input.graph() == graph) { // patch to the outer world + target = input; } - node.getNodeClass().set(node, pos, target); } + nodeClass.set(node, pos, target); } - // re-wire successors - for (Entry entry : newNodes.entrySet()) { - Node oldNode = entry.getKey(); - Node node = entry.getValue(); - for (NodeClassIterator iter = oldNode.successors().iterator(); iter.hasNext();) { - Position pos = iter.nextPosition(); - if (!pos.isValidFor(node, oldNode)) { - continue; + for (NodeClassIterator iter = oldNode.successors().iterator(); iter.hasNext();) { + Position pos = iter.nextPosition(); + if (!nodeClass.isValid(pos, oldNodeClass)) { + continue; + } + Node succ = oldNodeClass.get(oldNode, pos); + Node target = newNodes.get(succ); + if (target == null) { + Node replacement = replacements.replacement(succ); + if (replacement != succ) { + assert isAssignable(nodeClass.fieldTypes.get(node.getNodeClass().successorOffsets[pos.index]), replacement); + target = replacement; } - Node succ = oldNode.getNodeClass().get(oldNode, pos); - Node target = newNodes.get(succ); - if (target == null) { - target = replacementsMap.get(succ); - if (target == null) { - Node replacement = replacements.replacement(succ); - if (replacement != succ) { - replacementsMap.put(succ, replacement); - assert isAssignable(node.getNodeClass().fieldTypes.get(node.getNodeClass().successorOffsets[pos.index]), replacement); - target = replacement; - } - } - } - node.getNodeClass().set(node, pos, target); } + nodeClass.set(node, pos, target); } - return newNodes; } private static boolean isAssignable(Class fieldType, Node replacement) { diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeMap.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeMap.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeMap.java Wed Oct 02 13:26:31 2013 +0200 @@ -26,11 +26,11 @@ import java.util.*; import java.util.Map.Entry; -public final class NodeMap { +public class NodeMap { private final Graph graph; private final boolean autogrow; - private Object[] values; + protected Object[] values; public NodeMap(Graph graph) { this(graph, false); @@ -54,6 +54,29 @@ return (T) values[node.id()]; } + public boolean isEmpty() { + return !entries().iterator().hasNext(); + } + + public boolean containsKey(Object key) { + if (key instanceof Node) { + Node node = (Node) key; + if (node.graph() == graph()) { + return get(node) != null; + } + } + return false; + } + + public boolean containsValue(Object value) { + for (Object o : values) { + if (o == value) { + return true; + } + } + return false; + } + public Graph graph() { return graph; } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeNodeMap.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeNodeMap.java Wed Oct 02 13:26:31 2013 +0200 @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2011, 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.graph; + +import java.util.*; + +public final class NodeNodeMap extends NodeMap implements Map { + + public NodeNodeMap(Graph graph) { + super(graph, true); + } + + public NodeNodeMap(NodeNodeMap copyFrom) { + super(copyFrom); + } + + public Node get(Object key) { + return super.get((Node) key); + } + + public Node put(Node key, Node value) { + Node oldValue = super.get(key); + super.set(key, value); + return oldValue; + } + + public Node remove(Object key) { + throw new UnsupportedOperationException("Cannot remove keys from this map"); + } + + public void putAll(Map m) { + for (Entry entry : m.entrySet()) { + put(entry.getKey(), entry.getValue()); + } + } + + public Set keySet() { + throw new UnsupportedOperationException("Cannot get key set from this map"); + } + + public Collection values() { + ArrayList result = new ArrayList<>(this.size()); + for (int i = 0; i < values.length; ++i) { + Object v = values[i]; + if (v != null) { + result.add((Node) v); + } + } + return result; + } + + public Set> entrySet() { + throw new UnsupportedOperationException("Cannot get entry set for this map"); + } +} diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64DeoptimizeOp.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64DeoptimizeOp.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64DeoptimizeOp.java Wed Oct 02 13:26:31 2013 +0200 @@ -23,12 +23,8 @@ package com.oracle.graal.hotspot.amd64; import static com.oracle.graal.hotspot.HotSpotBackend.*; -import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.amd64.*; -import com.oracle.graal.hotspot.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.amd64.*; import com.oracle.graal.lir.asm.*; @@ -36,21 +32,14 @@ @Opcode("DEOPT") final class AMD64DeoptimizeOp extends AMD64LIRInstruction { - private DeoptimizationAction action; - private DeoptimizationReason reason; @State private LIRFrameState info; - AMD64DeoptimizeOp(DeoptimizationAction action, DeoptimizationReason reason, LIRFrameState info) { - this.action = action; - this.reason = reason; + AMD64DeoptimizeOp(LIRFrameState info) { this.info = info; } @Override public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - HotSpotGraalRuntime runtime = graalRuntime(); - Register thread = runtime.getRuntime().threadRegister(); - masm.movl(new AMD64Address(thread, runtime.getConfig().pendingDeoptimizationOffset), tasm.runtime.encodeDeoptActionAndReason(action, reason)); AMD64Call.directCall(tasm, masm, tasm.runtime.lookupForeignCall(UNCOMMON_TRAP), null, false, info); } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java Wed Oct 02 13:26:31 2013 +0200 @@ -63,6 +63,11 @@ } @Override + public boolean shouldAllocateRegisters() { + return true; + } + + @Override public FrameMap newFrameMap() { return new AMD64FrameMap(runtime(), target, runtime().lookupRegisterConfig()); } @@ -231,11 +236,10 @@ FrameMap frameMap = tasm.frameMap; RegisterConfig regConfig = frameMap.registerConfig; HotSpotVMConfig config = runtime().config; - Label unverifiedStub = installedCodeOwner == null || isStatic(installedCodeOwner.getModifiers()) ? null : new Label(); + Label verifiedStub = new Label(); // Emit the prefix - - if (unverifiedStub != null) { + if (installedCodeOwner != null && !isStatic(installedCodeOwner.getModifiers())) { tasm.recordMark(Marks.MARK_UNVERIFIED_ENTRY); CallingConvention cc = regConfig.getCallingConvention(JavaCallee, null, new JavaType[]{runtime().lookupJavaType(Object.class)}, target, false); Register inlineCacheKlass = rax; // see definition of IC_Klass in @@ -252,11 +256,12 @@ } else { asm.cmpq(inlineCacheKlass, src); } - asm.jcc(ConditionFlag.NotEqual, unverifiedStub); + AMD64Call.directConditionalJmp(tasm, asm, runtime().lookupForeignCall(IC_MISS_HANDLER), ConditionFlag.NotEqual); } asm.align(config.codeEntryAlignment); tasm.recordMark(Marks.MARK_OSR_ENTRY); + asm.bind(verifiedStub); tasm.recordMark(Marks.MARK_VERIFIED_ENTRY); // Emit code for the LIR @@ -273,10 +278,5 @@ // it has no calls that can cause such "return" entries assert !frameMap.accessesCallerFrame() : lirGen.getGraph(); } - - if (unverifiedStub != null) { - asm.bind(unverifiedStub); - AMD64Call.directJmp(tasm, asm, runtime().lookupForeignCall(IC_MISS_HANDLER)); - } } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotDeoptimizeCallerOp.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotDeoptimizeCallerOp.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotDeoptimizeCallerOp.java Wed Oct 02 13:26:31 2013 +0200 @@ -23,12 +23,8 @@ package com.oracle.graal.hotspot.amd64; import static com.oracle.graal.hotspot.HotSpotBackend.*; -import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.amd64.*; -import com.oracle.graal.hotspot.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.amd64.*; import com.oracle.graal.lir.asm.*; @@ -39,21 +35,9 @@ @Opcode("DEOPT_CALLER") final class AMD64HotSpotDeoptimizeCallerOp extends AMD64HotSpotEpilogueOp { - private final DeoptimizationAction action; - private final DeoptimizationReason reason; - - AMD64HotSpotDeoptimizeCallerOp(DeoptimizationAction action, DeoptimizationReason reason) { - this.action = action; - this.reason = reason; - } - @Override public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { leaveFrameAndRestoreRbp(tasm, masm); - - HotSpotGraalRuntime runtime = graalRuntime(); - Register thread = runtime.getRuntime().threadRegister(); - masm.movl(new AMD64Address(thread, runtime.getConfig().pendingDeoptimizationOffset), tasm.runtime.encodeDeoptActionAndReason(action, reason)); AMD64Call.directJmp(tasm, masm, tasm.runtime.lookupForeignCall(UNCOMMON_TRAP)); } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java Wed Oct 02 13:26:31 2013 +0200 @@ -25,6 +25,7 @@ import static com.oracle.graal.amd64.AMD64.*; import static com.oracle.graal.api.code.ValueUtil.*; import static com.oracle.graal.hotspot.HotSpotBackend.*; +import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; import java.lang.reflect.*; import java.util.*; @@ -36,6 +37,7 @@ import com.oracle.graal.asm.amd64.AMD64Address.Scale; import com.oracle.graal.compiler.amd64.*; import com.oracle.graal.compiler.gen.*; +import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.amd64.AMD64HotSpotMove.CompareAndSwapCompressedOp; @@ -176,7 +178,7 @@ @Override protected void emitReturn(Value input) { - append(new AMD64HotSpotReturnOp(input)); + append(new AMD64HotSpotReturnOp(input, getStub() != null)); } @Override @@ -242,7 +244,7 @@ Variable result; if (linkage.canDeoptimize()) { - assert info != null; + assert info != null || stub != null; append(new AMD64HotSpotCRuntimeCallPrologueOp()); result = super.emitForeignCall(linkage, info, args); append(new AMD64HotSpotCRuntimeCallEpilogueOp()); @@ -287,7 +289,7 @@ @Override public void visitSafepointNode(SafepointNode i) { LIRFrameState info = state(i); - append(new AMD64SafepointOp(info, runtime().config, this)); + append(new AMD64HotSpotSafepointOp(info, runtime().config, this)); } @SuppressWarnings("hiding") @@ -361,14 +363,29 @@ append(new AMD64HotSpotUnwindOp(exceptionParameter)); } + private void moveDeoptimizationActionAndReasonToThread(Value actionAndReason) { + int pendingDeoptimizationOffset = graalRuntime().getConfig().pendingDeoptimizationOffset; + RegisterValue thread = runtime().threadRegister().asValue(HotSpotGraalRuntime.wordKind()); + AMD64AddressValue pendingDeoptAddress = new AMD64AddressValue(actionAndReason.getKind(), thread, pendingDeoptimizationOffset); + if (actionAndReason instanceof Constant && !runtime.needsDataPatch((Constant) actionAndReason)) { + Constant constantActionAndReason = (Constant) actionAndReason; + assert !runtime.needsDataPatch(constantActionAndReason); + append(new StoreConstantOp(constantActionAndReason.getKind(), pendingDeoptAddress, constantActionAndReason, null)); + } else { + append(new StoreOp(actionAndReason.getKind(), pendingDeoptAddress, load(actionAndReason), null)); + } + } + @Override - public void emitDeoptimize(DeoptimizationAction action, DeoptimizingNode deopting) { - append(new AMD64DeoptimizeOp(action, deopting.getDeoptimizationReason(), state(deopting))); + public void emitDeoptimize(Value actionAndReason, DeoptimizingNode deopting) { + moveDeoptimizationActionAndReasonToThread(actionAndReason); + append(new AMD64DeoptimizeOp(state(deopting))); } @Override public void emitDeoptimizeCaller(DeoptimizationAction action, DeoptimizationReason reason) { - append(new AMD64HotSpotDeoptimizeCallerOp(action, reason)); + moveDeoptimizationActionAndReasonToThread(runtime.encodeDeoptActionAndReason(action, reason)); + append(new AMD64HotSpotDeoptimizeCallerOp()); } @Override @@ -522,4 +539,13 @@ append(new CondMoveOp(result, Condition.EQ, load(Constant.TRUE), Constant.FALSE)); setResult(node, result); } + + @Override + public void visitInfopointNode(InfopointNode i) { + if (i.getState() != null && i.getState().bci == FrameState.AFTER_BCI) { + Debug.log("Ignoring InfopointNode for AFTER_BCI"); + } else { + super.visitInfopointNode(i); + } + } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotReturnOp.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotReturnOp.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotReturnOp.java Wed Oct 02 13:26:31 2013 +0200 @@ -22,10 +22,16 @@ */ package com.oracle.graal.hotspot.amd64; +import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; +import static com.oracle.graal.phases.GraalOptions.*; +import com.oracle.graal.amd64.*; +import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.amd64.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.hotspot.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.asm.*; @@ -36,14 +42,31 @@ final class AMD64HotSpotReturnOp extends AMD64HotSpotEpilogueOp { @Use({REG, ILLEGAL}) protected Value value; + private final boolean isStub; - AMD64HotSpotReturnOp(Value value) { + AMD64HotSpotReturnOp(Value value, boolean isStub) { this.value = value; + this.isStub = isStub; } + private static Register findPollOnReturnScratchRegister() { + RegisterConfig config = HotSpotGraalRuntime.graalRuntime().getRuntime().lookupRegisterConfig(); + for (Register r : config.getAllocatableRegisters(Kind.Long)) { + if (r != config.getReturnRegister(Kind.Long) && r != AMD64.rbp) { + return r; + } + } + throw GraalInternalError.shouldNotReachHere(); + } + + private static final Register scratchForSafepointOnReturn = findPollOnReturnScratchRegister(); + @Override public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { leaveFrameAndRestoreRbp(tasm, masm); + if (!isStub && (tasm.frameContext != null || !OptEliminateSafepoints.getValue())) { + AMD64HotSpotSafepointOp.emitCode(tasm, masm, graalRuntime().getConfig(), true, null, scratchForSafepointOnReturn); + } masm.ret(0); } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotSafepointOp.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotSafepointOp.java Wed Oct 02 13:26:31 2013 +0200 @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2011, 2012, 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.hotspot.amd64; + +import static com.oracle.graal.amd64.AMD64.*; +import static com.oracle.graal.hotspot.bridge.Marks.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.asm.amd64.*; +import com.oracle.graal.hotspot.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.amd64.*; +import com.oracle.graal.lir.asm.*; +import com.oracle.graal.nodes.spi.*; + +/** + * Emits a safepoint poll. + */ +@Opcode("SAFEPOINT") +public class AMD64HotSpotSafepointOp extends AMD64LIRInstruction { + + @State protected LIRFrameState state; + @Temp({OperandFlag.REG}) private AllocatableValue temp; + + private final HotSpotVMConfig config; + + public AMD64HotSpotSafepointOp(LIRFrameState state, HotSpotVMConfig config, LIRGeneratorTool tool) { + this.state = state; + this.config = config; + temp = tool.newVariable(tool.target().wordKind); + } + + @Override + public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler asm) { + RegisterValue scratch = (RegisterValue) temp; + emitCode(tasm, asm, config, false, state, scratch.getRegister()); + } + + public static void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler asm, HotSpotVMConfig config, boolean atReturn, LIRFrameState state, Register scratch) { + final int pos = asm.codeBuffer.position(); + if (config.isPollingPageFar) { + asm.movq(scratch, config.safepointPollingAddress); + tasm.recordMark(atReturn ? MARK_POLL_RETURN_FAR : MARK_POLL_FAR); + if (state != null) { + tasm.recordInfopoint(pos, state, InfopointReason.SAFEPOINT); + } + asm.movq(scratch, new AMD64Address(scratch)); + } else { + tasm.recordMark(atReturn ? MARK_POLL_RETURN_NEAR : MARK_POLL_NEAR); + if (state != null) { + tasm.recordInfopoint(pos, state, InfopointReason.SAFEPOINT); + } + // The C++ code transforms the polling page offset into an RIP displacement + // to the real address at that offset in the polling page. + asm.movq(scratch, new AMD64Address(rip, 0)); + } + } +} diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64SafepointOp.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64SafepointOp.java Fri Sep 06 21:37:50 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,71 +0,0 @@ -/* - * Copyright (c) 2011, 2012, 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.hotspot.amd64; - -import static com.oracle.graal.amd64.AMD64.*; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.asm.amd64.*; -import com.oracle.graal.hotspot.*; -import com.oracle.graal.hotspot.bridge.*; -import com.oracle.graal.lir.*; -import com.oracle.graal.lir.amd64.*; -import com.oracle.graal.lir.asm.*; -import com.oracle.graal.nodes.spi.*; - -/** - * Emits a safepoint poll. - */ -@Opcode("SAFEPOINT") -public class AMD64SafepointOp extends AMD64LIRInstruction { - - @State protected LIRFrameState state; - @Temp({OperandFlag.REG}) private AllocatableValue temp; - - private final HotSpotVMConfig config; - - public AMD64SafepointOp(LIRFrameState state, HotSpotVMConfig config, LIRGeneratorTool tool) { - this.state = state; - this.config = config; - temp = tool.newVariable(tool.target().wordKind); - } - - @Override - public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler asm) { - final int pos = asm.codeBuffer.position(); - RegisterValue scratch = (RegisterValue) temp; - if (config.isPollingPageFar) { - asm.movq(scratch.getRegister(), config.safepointPollingAddress); - tasm.recordMark(Marks.MARK_POLL_FAR); - tasm.recordInfopoint(pos, state, InfopointReason.SAFEPOINT); - asm.movq(scratch.getRegister(), new AMD64Address(scratch.getRegister())); - } else { - tasm.recordMark(Marks.MARK_POLL_NEAR); - tasm.recordInfopoint(pos, state, InfopointReason.SAFEPOINT); - // The C++ code transforms the polling page offset into an RIP displacement - // to the real address at that offset in the polling page. - asm.movq(scratch.getRegister(), new AMD64Address(rip, 0)); - } - } -} diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotBackend.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotBackend.java Wed Oct 02 13:26:31 2013 +0200 @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2012, 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.hotspot.ptx; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.asm.*; +import com.oracle.graal.compiler.gen.*; +import com.oracle.graal.hotspot.*; +import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.asm.*; +import com.oracle.graal.nodes.*; + +/** + * HotSpot PTX specific backend. + */ +public class PTXHotSpotBackend extends HotSpotBackend { + + public PTXHotSpotBackend(HotSpotRuntime runtime, TargetDescription target) { + super(runtime, target); + } + + @Override + public boolean shouldAllocateRegisters() { + throw new InternalError("NYI"); + } + + @Override + public FrameMap newFrameMap() { + throw new InternalError("NYI"); + } + + @Override + public TargetMethodAssembler newAssembler(LIRGenerator lirGen, CompilationResult compilationResult) { + throw new InternalError("NYI"); + } + + @Override + public void emitCode(TargetMethodAssembler tasm, LIRGenerator lirGen, ResolvedJavaMethod installedCodeOwner) { + throw new InternalError("NYI"); + } + + @Override + protected AbstractAssembler createAssembler(FrameMap frameMap) { + throw new InternalError("NYI"); + } + + @Override + public LIRGenerator newLIRGenerator(StructuredGraph graph, FrameMap frameMap, CallingConvention cc, LIR lir) { + throw new InternalError("NYI"); + } +} diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotGraalRuntime.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotGraalRuntime.java Wed Oct 02 13:26:31 2013 +0200 @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2012, 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.hotspot.ptx; + +import com.oracle.graal.ptx.*; +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.hotspot.*; +import com.oracle.graal.hotspot.meta.*; + +/** + * PTX specific implementation of {@link HotSpotGraalRuntime}. + */ +public class PTXHotSpotGraalRuntime extends HotSpotGraalRuntime { + + protected PTXHotSpotGraalRuntime() { + } + + /** + * Called from C++ code to retrieve the singleton instance, creating it first if necessary. + */ + public static HotSpotGraalRuntime makeInstance() { + HotSpotGraalRuntime graalRuntime = graalRuntime(); + if (graalRuntime == null) { + HotSpotGraalRuntimeFactory factory = findFactory("PTX"); + if (factory != null) { + graalRuntime = factory.createRuntime(); + } else { + graalRuntime = new PTXHotSpotGraalRuntime(); + } + graalRuntime.completeInitialization(); + } + return graalRuntime; + } + + protected Architecture createArchitecture() { + return new PTX(); + } + + @Override + protected TargetDescription createTarget() { + final int stackFrameAlignment = 16; + final int implicitNullCheckLimit = 4096; + final boolean inlineObjects = true; + return new TargetDescription(createArchitecture(), true, stackFrameAlignment, implicitNullCheckLimit, inlineObjects); + } + + @Override + protected HotSpotBackend createBackend() { + return new PTXHotSpotBackend(getRuntime(), getTarget()); + } + + @Override + protected HotSpotRuntime createRuntime() { + return new PTXHotSpotRuntime(config, this); + } + + @Override + protected Value[] getNativeABICallerSaveRegisters() { + throw new InternalError("NYI"); + } +} diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotRegisterConfig.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotRegisterConfig.java Wed Oct 02 13:26:31 2013 +0200 @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2011, 2012, 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.hotspot.ptx; + +import static com.oracle.graal.ptx.PTX.*; + +import java.util.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.code.CallingConvention.Type; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.lir.Variable; +import com.oracle.graal.graph.*; + +public class PTXHotSpotRegisterConfig implements RegisterConfig { + + private final Register[] allocatable; + + @Override + public Register[] getAllocatableRegisters() { + return allocatable.clone(); + } + + @Override + public Register[] getAllocatableRegisters(PlatformKind kind) { + throw GraalInternalError.unimplemented("PTXHotSpotRegisterConfig.getAllocatableRegisters()"); + } + + @Override + public RegisterAttributes[] getAttributesMap() { + throw GraalInternalError.unimplemented("PTXHotSpotRegisterConfig.getAttributesMap()"); + } + + private final Register[] javaGeneralParameterRegisters; + private final Register[] nativeGeneralParameterRegisters; + + private static Register[] initAllocatable() { + Register[] registers = new Register[] { + r0, r1, r2, r3, r4, r5, r6, r7, + r8, r9, r10, r11, r12, r13, r14, r15, + }; + + return registers; + } + + public PTXHotSpotRegisterConfig() { + javaGeneralParameterRegisters = paramRegisters; + nativeGeneralParameterRegisters = gprRegisters; + + allocatable = initAllocatable(); + } + + @Override + public Register[] getCallerSaveRegisters() { + // No caller save registers; return empty array + return new Register[]{}; + } + + @Override + public Register getRegisterForRole(int index) { + throw GraalInternalError.unimplemented("PTXHotSpotRegisterConfig.getRegisterForRole()"); + } + + @Override + public CallingConvention getCallingConvention(Type type, JavaType returnType, JavaType[] parameterTypes, TargetDescription target, boolean stackOnly) { + if (type == Type.NativeCall) { + return callingConvention(nativeGeneralParameterRegisters, returnType, parameterTypes, type, target, stackOnly); + } + return callingConvention(javaGeneralParameterRegisters, returnType, parameterTypes, type, target, stackOnly); + } + + @Override + public Register[] getCallingConventionRegisters(Type type, Kind kind) { + throw GraalInternalError.unimplemented("PTXHotSpotRegisterConfig.getRegisterForRole()"); + } + + private static CallingConvention callingConvention(@SuppressWarnings("unused") Register[] generalParameterRegisters, + JavaType returnType, JavaType[] parameterTypes, + Type type, TargetDescription target, boolean stackOnly) { + + assert stackOnly == false; + + int currentGeneral = 0; + int currentStackOffset = 0; + + Kind returnKind = returnType == null ? Kind.Void : returnType.getKind(); + AllocatableValue returnLocation = returnKind == Kind.Void ? Value.ILLEGAL : new Variable(returnKind, currentGeneral++); + AllocatableValue[] locations = new AllocatableValue[parameterTypes.length]; + + for (int i = 0; i < parameterTypes.length; i++) { + final Kind kind = parameterTypes[i].getKind(); + + switch (kind) { + case Byte: + case Boolean: + case Short: + case Char: + case Int: + case Long: + case Float: + case Double: + case Object: + if (!stackOnly) { + locations[i] = new Variable(kind, currentGeneral++); + } + break; + default: + throw GraalInternalError.shouldNotReachHere(); + } + + if (locations[i] == null) { + locations[i] = StackSlot.get(kind.getStackKind(), currentStackOffset, !type.out); + currentStackOffset += Math.max(target.arch.getSizeInBytes(kind), target.wordSize); + } + } + + return new CallingConvention(currentStackOffset, returnLocation, locations); + } + + @Override + public Register getReturnRegister(Kind kind) { + throw GraalInternalError.unimplemented("PTXHotSpotRegisterConfig.getRegisterForRole()"); + } + + @Override + public Register getFrameRegister() { + // No frame register + return null; + } + + public CalleeSaveLayout getCalleeSaveLayout() { + return null; + } + + @Override + public String toString() { + return String.format("Allocatable: " + Arrays.toString(getAllocatableRegisters()) + "%n" + "CallerSave: " + Arrays.toString(getCallerSaveRegisters()) + "%n"); + } +} diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotRuntime.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotRuntime.java Wed Oct 02 13:26:31 2013 +0200 @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2012, 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.hotspot.ptx; + +import static com.oracle.graal.ptx.PTX.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.debug.Debug; +import com.oracle.graal.hotspot.*; +import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.graph.Node; +import com.oracle.graal.nodes.calc.ConvertNode; + +public class PTXHotSpotRuntime extends HotSpotRuntime { + + public PTXHotSpotRuntime(HotSpotVMConfig config, HotSpotGraalRuntime graalRuntime) { + super(config, graalRuntime); + + } + + @Override + public void lower(Node n, LoweringTool tool) { + if (n instanceof ConvertNode) { + // PTX has a cvt instruction that "takes a variety of + // operand types and sizes, as its job is to convert from + // nearly any data type to any other data type (and + // size)." [Section 6.2 of PTX ISA manual] + // So, there is no need to lower the operation. + return; + } else { + super.lower(n, tool); + } + } + + @Override + public void registerReplacements(Replacements replacements) { + Debug.log("PTXHotSpotRuntime.registerReplacements unimplemented"); + } + + // PTX code does not use stack or stack pointer + @Override + public Register stackPointerRegister() { + return Register.None; + } + + // PTX code does not have heap register + @Override + public Register heapBaseRegister() { + return Register.None; + } + + // Thread register is %tid. + @Override + public Register threadRegister() { + return tid; + } + + @Override + protected RegisterConfig createRegisterConfig() { + return new PTXHotSpotRegisterConfig(); + } +} diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCDeoptimizeOp.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCDeoptimizeOp.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCDeoptimizeOp.java Wed Oct 02 13:26:31 2013 +0200 @@ -22,39 +22,24 @@ */ package com.oracle.graal.hotspot.sparc; -import static com.oracle.graal.asm.sparc.SPARCMacroAssembler.*; import static com.oracle.graal.hotspot.HotSpotBackend.*; -import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; -import static com.oracle.graal.sparc.SPARC.*; -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.sparc.*; -import com.oracle.graal.hotspot.*; import com.oracle.graal.lir.*; +import com.oracle.graal.lir.asm.*; import com.oracle.graal.lir.sparc.*; -import com.oracle.graal.lir.asm.*; @Opcode("DEOPT") final class SPARCDeoptimizeOp extends SPARCLIRInstruction { - private DeoptimizationAction action; - private DeoptimizationReason reason; @State private LIRFrameState info; - SPARCDeoptimizeOp(DeoptimizationAction action, DeoptimizationReason reason, LIRFrameState info) { - this.action = action; - this.reason = reason; + SPARCDeoptimizeOp(LIRFrameState info) { this.info = info; } @Override public void emitCode(TargetMethodAssembler tasm, SPARCMacroAssembler masm) { - HotSpotGraalRuntime runtime = graalRuntime(); - Register thread = runtime.getRuntime().threadRegister(); - Register scratch = g3; - new Mov(tasm.runtime.encodeDeoptActionAndReason(action, reason), scratch).emit(masm); - new Stw(scratch, new SPARCAddress(thread, runtime.getConfig().pendingDeoptimizationOffset)).emit(masm); // TODO the patched call address looks odd (and is invalid) compared to other runtime calls: // 0xffffffff749bb5fc: call 0xffffffff415a720c ; {runtime_call} // [Exception Handler] diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java Wed Oct 02 13:26:31 2013 +0200 @@ -60,6 +60,11 @@ } @Override + public boolean shouldAllocateRegisters() { + return true; + } + + @Override public FrameMap newFrameMap() { return new SPARCFrameMap(runtime(), target, runtime().lookupRegisterConfig()); } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotDeoptimizeCallerOp.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotDeoptimizeCallerOp.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotDeoptimizeCallerOp.java Wed Oct 02 13:26:31 2013 +0200 @@ -22,18 +22,14 @@ */ package com.oracle.graal.hotspot.sparc; +import static com.oracle.graal.hotspot.HotSpotBackend.*; import static com.oracle.graal.sparc.SPARC.*; -import static com.oracle.graal.asm.sparc.SPARCMacroAssembler.*; -import static com.oracle.graal.hotspot.HotSpotBackend.*; -import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.sparc.*; -import com.oracle.graal.hotspot.*; import com.oracle.graal.lir.*; +import com.oracle.graal.lir.asm.*; import com.oracle.graal.lir.sparc.*; -import com.oracle.graal.lir.asm.*; /** * Removes the current frame and tail calls the uncommon trap routine. @@ -41,14 +37,6 @@ @Opcode("DEOPT_CALLER") final class SPARCHotSpotDeoptimizeCallerOp extends SPARCHotSpotEpilogueOp { - private final DeoptimizationAction action; - private final DeoptimizationReason reason; - - SPARCHotSpotDeoptimizeCallerOp(DeoptimizationAction action, DeoptimizationReason reason) { - this.action = action; - this.reason = reason; - } - @Override public void emitCode(TargetMethodAssembler tasm, SPARCMacroAssembler masm) { leaveFrame(tasm); @@ -58,14 +46,7 @@ // final boolean isStub = true; // HotSpotFrameContext frameContext = backend.new HotSpotFrameContext(isStub); // frameContext.enter(tasm); - - HotSpotGraalRuntime runtime = graalRuntime(); - Register thread = runtime.getRuntime().threadRegister(); - - Register scratch = g5; - new Mov(tasm.runtime.encodeDeoptActionAndReason(action, reason), scratch).emit(masm); - new Stw(scratch, new SPARCAddress(thread, runtime.getConfig().pendingDeoptimizationOffset)).emit(masm); - + Register scratch = g3; SPARCCall.indirectJmp(tasm, masm, scratch, tasm.runtime.lookupForeignCall(UNCOMMON_TRAP)); // frameContext.leave(tasm); diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java Wed Oct 02 13:26:31 2013 +0200 @@ -24,6 +24,7 @@ import static com.oracle.graal.api.code.ValueUtil.*; import static com.oracle.graal.hotspot.HotSpotBackend.*; +import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; import static com.oracle.graal.sparc.SPARC.*; import java.lang.reflect.*; @@ -39,7 +40,10 @@ import com.oracle.graal.hotspot.stubs.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.sparc.*; -import com.oracle.graal.lir.sparc.SPARCMove.*; +import com.oracle.graal.lir.sparc.SPARCMove.CompareAndSwapOp; +import com.oracle.graal.lir.sparc.SPARCMove.LoadOp; +import com.oracle.graal.lir.sparc.SPARCMove.StoreConstantOp; +import com.oracle.graal.lir.sparc.SPARCMove.StoreOp; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind; @@ -103,9 +107,14 @@ } @Override + protected void emitReturn(Value input) { + append(new SPARCHotSpotReturnOp(input, getStub() != null)); + } + + @Override public void visitSafepointNode(SafepointNode i) { LIRFrameState info = state(i); - append(new SPARCSafepointOp(info, runtime().config, this)); + append(new SPARCHotSpotSafepointOp(info, runtime().config, this)); } @Override @@ -175,14 +184,23 @@ append(new SPARCHotSpotUnwindOp(exceptionParameter)); } + private void moveDeoptimizationActionAndReasonToThread(Value actionAndReason) { + int pendingDeoptimizationOffset = graalRuntime().getConfig().pendingDeoptimizationOffset; + RegisterValue thread = runtime().threadRegister().asValue(HotSpotGraalRuntime.wordKind()); + SPARCAddressValue pendingDeoptAddress = new SPARCAddressValue(actionAndReason.getKind(), thread, pendingDeoptimizationOffset); + append(new StoreOp(actionAndReason.getKind(), pendingDeoptAddress, emitMove(actionAndReason), null)); + } + @Override - public void emitDeoptimize(DeoptimizationAction action, DeoptimizingNode deopting) { - append(new SPARCDeoptimizeOp(action, deopting.getDeoptimizationReason(), state(deopting))); + public void emitDeoptimize(Value actionAndReason, DeoptimizingNode deopting) { + moveDeoptimizationActionAndReasonToThread(actionAndReason); + append(new SPARCDeoptimizeOp(state(deopting))); } @Override public void emitDeoptimizeCaller(DeoptimizationAction action, DeoptimizationReason reason) { - append(new SPARCHotSpotDeoptimizeCallerOp(action, reason)); + moveDeoptimizationActionAndReasonToThread(runtime.encodeDeoptActionAndReason(action, reason)); + append(new SPARCHotSpotDeoptimizeCallerOp()); } @Override diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotReturnOp.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotReturnOp.java Wed Oct 02 13:26:31 2013 +0200 @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2012, 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.hotspot.sparc; + +import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; +import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; +import static com.oracle.graal.phases.GraalOptions.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.asm.sparc.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.asm.*; +import com.oracle.graal.lir.sparc.SPARCControlFlow.ReturnOp; +import com.oracle.graal.sparc.*; + +/** + * Returns from a function. + */ +@Opcode("RETURN") +final class SPARCHotSpotReturnOp extends SPARCHotSpotEpilogueOp { + + @Use({REG, ILLEGAL}) protected Value value; + private final boolean isStub; + + SPARCHotSpotReturnOp(Value value, boolean isStub) { + this.value = value; + this.isStub = isStub; + } + + @Override + public void emitCode(TargetMethodAssembler tasm, SPARCMacroAssembler masm) { + if (!isStub && (tasm.frameContext != null || !OptEliminateSafepoints.getValue())) { + // Using the same scratch register as LIR_Assembler::return_op + // in c1_LIRAssembler_sparc.cpp + SPARCHotSpotSafepointOp.emitCode(tasm, masm, graalRuntime().getConfig(), true, null, SPARC.l0); + } + ReturnOp.emitCodeHelper(tasm, masm); + } +} diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotSafepointOp.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotSafepointOp.java Wed Oct 02 13:26:31 2013 +0200 @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2011, 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.hotspot.sparc; + +import static com.oracle.graal.asm.sparc.SPARCMacroAssembler.*; +import static com.oracle.graal.hotspot.bridge.Marks.*; +import static com.oracle.graal.sparc.SPARC.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.asm.sparc.*; +import com.oracle.graal.hotspot.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.sparc.*; +import com.oracle.graal.lir.asm.*; +import com.oracle.graal.nodes.spi.*; + +/** + * Emits a safepoint poll. + */ +@Opcode("SAFEPOINT") +public class SPARCHotSpotSafepointOp extends SPARCLIRInstruction { + + @State protected LIRFrameState state; + @Temp({OperandFlag.REG}) private AllocatableValue temp; + + private final HotSpotVMConfig config; + + public SPARCHotSpotSafepointOp(LIRFrameState state, HotSpotVMConfig config, LIRGeneratorTool tool) { + this.state = state; + this.config = config; + temp = tool.newVariable(tool.target().wordKind); + } + + @Override + public void emitCode(TargetMethodAssembler tasm, SPARCMacroAssembler masm) { + Register scratch = ((RegisterValue) temp).getRegister(); + emitCode(tasm, masm, config, false, state, scratch); + } + + public static void emitCode(TargetMethodAssembler tasm, SPARCMacroAssembler masm, HotSpotVMConfig config, boolean atReturn, LIRFrameState state, Register scratch) { + final int pos = masm.codeBuffer.position(); + new Setx(config.safepointPollingAddress, scratch).emit(masm); + assert !config.isPollingPageFar; + tasm.recordMark(atReturn ? MARK_POLL_RETURN_NEAR : MARK_POLL_NEAR); + if (state != null) { + tasm.recordInfopoint(pos, state, InfopointReason.SAFEPOINT); + } + new Ldx(new SPARCAddress(scratch, 0), g0).emit(masm); + } +} diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCSafepointOp.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCSafepointOp.java Fri Sep 06 21:37:50 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2011, 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.hotspot.sparc; - -import static com.oracle.graal.asm.sparc.SPARCMacroAssembler.*; -import static com.oracle.graal.sparc.SPARC.*; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.asm.sparc.*; -import com.oracle.graal.hotspot.*; -import com.oracle.graal.lir.*; -import com.oracle.graal.lir.sparc.*; -import com.oracle.graal.lir.asm.*; -import com.oracle.graal.nodes.spi.*; - -/** - * Emits a safepoint poll. - */ -@Opcode("SAFEPOINT") -public class SPARCSafepointOp extends SPARCLIRInstruction { - - @State protected LIRFrameState state; - @Temp({OperandFlag.REG}) private AllocatableValue temp; - - private final HotSpotVMConfig config; - - public SPARCSafepointOp(LIRFrameState state, HotSpotVMConfig config, LIRGeneratorTool tool) { - this.state = state; - this.config = config; - temp = tool.newVariable(tool.target().wordKind); - } - - @Override - public void emitCode(TargetMethodAssembler tasm, SPARCMacroAssembler masm) { - final int pos = masm.codeBuffer.position(); - Register scratch = ((RegisterValue) temp).getRegister(); - new Setx(config.safepointPollingAddress, scratch).emit(masm); - tasm.recordInfopoint(pos, state, InfopointReason.SAFEPOINT); - new Ldx(new SPARCAddress(scratch, 0), g0).emit(masm); - } -} diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/AheadOfTimeCompilationTest.java --- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/AheadOfTimeCompilationTest.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/AheadOfTimeCompilationTest.java Wed Oct 02 13:26:31 2013 +0200 @@ -66,7 +66,7 @@ assertEquals(1, result.getNodes().filter(ConstantNode.class).count()); assertEquals(runtime.getTarget().wordKind, result.getNodes().filter(ConstantNode.class).first().kind()); assertEquals(2, result.getNodes(FloatingReadNode.class).count()); - assertEquals(0, result.getNodes(ReadNode.class).count()); + assertEquals(0, result.getNodes().filter(ReadNode.class).count()); } @Test @@ -75,7 +75,7 @@ assertEquals(1, result.getNodes().filter(ConstantNode.class).count()); assertEquals(Kind.Object, result.getNodes().filter(ConstantNode.class).first().kind()); assertEquals(0, result.getNodes(FloatingReadNode.class).count()); - assertEquals(0, result.getNodes(ReadNode.class).count()); + assertEquals(0, result.getNodes().filter(ReadNode.class).count()); } public static Class getClassObject() { @@ -92,7 +92,7 @@ assertEquals(type.klass(), filter.first().asConstant()); assertEquals(1, result.getNodes(FloatingReadNode.class).count()); - assertEquals(0, result.getNodes(ReadNode.class).count()); + assertEquals(0, result.getNodes().filter(ReadNode.class).count()); } @Test @@ -106,7 +106,7 @@ assertEquals(AheadOfTimeCompilationTest.class, mirror); assertEquals(0, result.getNodes(FloatingReadNode.class).count()); - assertEquals(0, result.getNodes(ReadNode.class).count()); + assertEquals(0, result.getNodes().filter(ReadNode.class).count()); } public static Class getPrimitiveClassObject() { @@ -121,7 +121,7 @@ assertEquals(runtime.getTarget().wordKind, filter.first().kind()); assertEquals(2, result.getNodes(FloatingReadNode.class).count()); - assertEquals(0, result.getNodes(ReadNode.class).count()); + assertEquals(0, result.getNodes().filter(ReadNode.class).count()); } @Test @@ -134,7 +134,7 @@ assertEquals(Integer.TYPE, mirror); assertEquals(0, result.getNodes(FloatingReadNode.class).count()); - assertEquals(0, result.getNodes(ReadNode.class).count()); + assertEquals(0, result.getNodes().filter(ReadNode.class).count()); } public static String getStringObject() { @@ -162,7 +162,7 @@ assertEquals("test string", mirror); assertEquals(0, result.getNodes(FloatingReadNode.class).count()); - assertEquals(0, result.getNodes(ReadNode.class).count()); + assertEquals(0, result.getNodes().filter(ReadNode.class).count()); } public static Boolean getBoxedBoolean() { @@ -175,7 +175,7 @@ StructuredGraph result = compile("getBoxedBoolean", true); assertEquals(2, result.getNodes(FloatingReadNode.class).count()); - assertEquals(1, result.getNodes(UnsafeCastNode.class).count()); + assertEquals(1, result.getNodes(PiNode.class).count()); assertEquals(1, result.getNodes().filter(ConstantNode.class).count()); ConstantNode constant = result.getNodes().filter(ConstantNode.class).first(); assertEquals(Kind.Long, constant.kind()); @@ -186,7 +186,7 @@ public void testBoxedBoolean() { StructuredGraph result = compile("getBoxedBoolean", false); assertEquals(0, result.getNodes(FloatingReadNode.class).count()); - assertEquals(0, result.getNodes(UnsafeCastNode.class).count()); + assertEquals(0, result.getNodes(PiNode.class).count()); assertEquals(1, result.getNodes().filter(ConstantNode.class).count()); ConstantNode constant = result.getNodes().filter(ConstantNode.class).first(); assertEquals(Kind.Object, constant.kind()); diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotCryptoSubstitutionTest.java --- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotCryptoSubstitutionTest.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotCryptoSubstitutionTest.java Wed Oct 02 13:26:31 2013 +0200 @@ -60,30 +60,42 @@ } @Test - public void testAESEncryptSubstitution() throws Exception { + public void testEncryptSubstitution() throws Exception { byte[] seed = {0x4, 0x7, 0x1, 0x1}; SecureRandom random = new SecureRandom(seed); KeyGenerator aesKeyGen = KeyGenerator.getInstance("AES"); + KeyGenerator desKeyGen = KeyGenerator.getInstance("DESede"); aesKeyGen.init(128, random); + desKeyGen.init(168, random); SecretKey aesKey = aesKeyGen.generateKey(); + SecretKey desKey = desKeyGen.generateKey(); byte[] input = readClassfile16(getClass()); - ByteArrayOutputStream expected = new ByteArrayOutputStream(); - expected.write(runEncryptDecrypt(aesKey, "AES/CBC/NoPadding", input)); - expected.write(runEncryptDecrypt(aesKey, "AES/CBC/PKCS5Padding", input)); + ByteArrayOutputStream aesExpected = new ByteArrayOutputStream(); + aesExpected.write(runEncryptDecrypt(aesKey, "AES/CBC/NoPadding", input)); + aesExpected.write(runEncryptDecrypt(aesKey, "AES/CBC/PKCS5Padding", input)); if (compiledAndInstall("com.sun.crypto.provider.AESCrypt", "encryptBlock", "decryptBlock")) { ByteArrayOutputStream actual = new ByteArrayOutputStream(); actual.write(runEncryptDecrypt(aesKey, "AES/CBC/NoPadding", input)); actual.write(runEncryptDecrypt(aesKey, "AES/CBC/PKCS5Padding", input)); - Assert.assertArrayEquals(expected.toByteArray(), actual.toByteArray()); + Assert.assertArrayEquals(aesExpected.toByteArray(), actual.toByteArray()); } + ByteArrayOutputStream desExpected = new ByteArrayOutputStream(); + desExpected.write(runEncryptDecrypt(desKey, "DESede/CBC/NoPadding", input)); + desExpected.write(runEncryptDecrypt(desKey, "DESede/CBC/PKCS5Padding", input)); + if (compiledAndInstall("com.sun.crypto.provider.CipherBlockChaining", "encrypt", "decrypt")) { ByteArrayOutputStream actual = new ByteArrayOutputStream(); actual.write(runEncryptDecrypt(aesKey, "AES/CBC/NoPadding", input)); actual.write(runEncryptDecrypt(aesKey, "AES/CBC/PKCS5Padding", input)); - Assert.assertArrayEquals(expected.toByteArray(), actual.toByteArray()); + Assert.assertArrayEquals(aesExpected.toByteArray(), actual.toByteArray()); + + actual.reset(); + actual.write(runEncryptDecrypt(desKey, "DESede/CBC/NoPadding", input)); + actual.write(runEncryptDecrypt(desKey, "DESede/CBC/PKCS5Padding", input)); + Assert.assertArrayEquals(desExpected.toByteArray(), actual.toByteArray()); } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierAdditionTest.java --- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierAdditionTest.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierAdditionTest.java Wed Oct 02 13:26:31 2013 +0200 @@ -35,11 +35,11 @@ import com.oracle.graal.compiler.test.*; import com.oracle.graal.debug.*; import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.hotspot.nodes.*; import com.oracle.graal.hotspot.phases.*; -import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.HeapAccess.BarrierType; +import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.spi.Lowerable.LoweringType; import com.oracle.graal.phases.*; import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.tiers.*; @@ -249,10 +249,10 @@ StructuredGraph graph = parse(snippet); HighTierContext highContext = new HighTierContext(runtime(), new Assumptions(false), replacements, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL); MidTierContext midContext = new MidTierContext(runtime(), new Assumptions(false), replacements, runtime().getTarget(), OptimisticOptimizations.ALL); - new InliningPhase(new InliningPhase.InlineEverythingPolicy()).apply(graph, highContext); - new LoweringPhase(LoweringType.BEFORE_GUARDS).apply(graph, highContext); + new InliningPhase(new InliningPhase.InlineEverythingPolicy(), new CanonicalizerPhase(true)).apply(graph, highContext); + new LoweringPhase(new CanonicalizerPhase(true)).apply(graph, highContext); new GuardLoweringPhase().apply(graph, midContext); - new LoweringPhase(LoweringType.AFTER_GUARDS).apply(graph, midContext); + new LoweringPhase(new CanonicalizerPhase(true)).apply(graph, midContext); new WriteBarrierAdditionPhase().apply(graph); Debug.dump(graph, "After Write Barrier Addition"); @@ -263,7 +263,7 @@ barriers = graph.getNodes(SerialWriteBarrier.class).count(); } Assert.assertEquals(expectedBarriers, barriers); - for (WriteNode write : graph.getNodes(WriteNode.class)) { + for (WriteNode write : graph.getNodes().filter(WriteNode.class)) { if (useG1GC()) { if (write.getBarrierType() != BarrierType.NONE) { Assert.assertEquals(1, write.successors().count()); @@ -278,7 +278,7 @@ } } - for (ReadNode read : graph.getNodes(ReadNode.class)) { + for (ReadNode read : graph.getNodes().filter(ReadNode.class)) { if (read.getBarrierType() != BarrierType.NONE) { if (read.location() instanceof ConstantLocationNode) { Assert.assertEquals(referentOffset(), ((ConstantLocationNode) (read.location())).getDisplacement()); diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierVerificationTest.java --- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierVerificationTest.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierVerificationTest.java Wed Oct 02 13:26:31 2013 +0200 @@ -33,10 +33,10 @@ import com.oracle.graal.debug.*; import com.oracle.graal.debug.internal.*; import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.hotspot.nodes.*; import com.oracle.graal.hotspot.phases.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.spi.Lowerable.LoweringType; import com.oracle.graal.phases.*; import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.graph.*; @@ -633,14 +633,14 @@ public AssertionError call() { final StructuredGraph graph = parse(snippet); HighTierContext highTierContext = new HighTierContext(runtime(), new Assumptions(false), replacements, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL); - new InliningPhase().apply(graph, highTierContext); + new InliningPhase(new CanonicalizerPhase(true)).apply(graph, highTierContext); MidTierContext midTierContext = new MidTierContext(runtime(), new Assumptions(false), replacements, runtime().getTarget(), OptimisticOptimizations.ALL); - new LoweringPhase(LoweringType.BEFORE_GUARDS).apply(graph, highTierContext); + new LoweringPhase(new CanonicalizerPhase(true)).apply(graph, highTierContext); new GuardLoweringPhase().apply(graph, midTierContext); - new SafepointInsertionPhase().apply(graph); - new LoweringPhase(LoweringType.AFTER_GUARDS).apply(graph, highTierContext); + new LoopSafepointInsertionPhase().apply(graph); + new LoweringPhase(new CanonicalizerPhase(true)).apply(graph, highTierContext); new WriteBarrierAdditionPhase().apply(graph); diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java Wed Oct 02 13:26:31 2013 +0200 @@ -128,8 +128,7 @@ CompilationStatistics stats = CompilationStatistics.create(method, entryBCI != StructuredGraph.INVOCATION_ENTRY_BCI); final boolean printCompilation = PrintCompilation.getValue() && !TTY.isSuppressed(); if (printCompilation) { - TTY.println(String.format("%-6d Graal %-70s %-45s %-50s %s...", id, method.getDeclaringClass().getName(), method.getName(), method.getSignature(), - entryBCI == StructuredGraph.INVOCATION_ENTRY_BCI ? "" : "(OSR@" + entryBCI + ") ")); + TTY.println(getMethodDescription() + "..."); } if (HotSpotPrintCompilation.getValue()) { printCompilation(); @@ -161,7 +160,10 @@ }); } finally { filter.remove(); - if (printCompilation) { + final boolean printAfterCompilation = PrintAfterCompilation.getValue() && !TTY.isSuppressed(); + if (printAfterCompilation) { + TTY.println(getMethodDescription() + String.format(" | %4dms %5dB", System.currentTimeMillis() - start, (result != null ? result.getTargetCodeSize() : -1))); + } else if (printCompilation) { TTY.println(String.format("%-6d Graal %-70s %-45s %-50s | %4dms %5dB", id, "", "", "", System.currentTimeMillis() - start, (result != null ? result.getTargetCodeSize() : -1))); } } @@ -193,6 +195,11 @@ } } + private String getMethodDescription() { + return String.format("%-6d Graal %-70s %-45s %-50s %s", id, method.getDeclaringClass().getName(), method.getName(), method.getSignature().getMethodDescriptor(), + entryBCI == StructuredGraph.INVOCATION_ENTRY_BCI ? "" : "(OSR@" + entryBCI + ") "); + } + /** * Print a HotSpot-style compilation message to the console. */ diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilerThread.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilerThread.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilerThread.java Wed Oct 02 13:26:31 2013 +0200 @@ -22,7 +22,6 @@ */ package com.oracle.graal.hotspot; -import static com.oracle.graal.compiler.GraalDebugConfig.*; import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; import java.io.*; @@ -52,7 +51,7 @@ @Override public void run() { GraalDebugConfig hotspotDebugConfig = null; - if (DebugEnabled.getValue()) { + if (Debug.isEnabled()) { PrintStream log = graalRuntime().getVMToCompiler().log(); DebugEnvironment.initialize(log); } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotDebugInfoBuilder.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotDebugInfoBuilder.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotDebugInfoBuilder.java Wed Oct 02 13:26:31 2013 +0200 @@ -61,7 +61,7 @@ } @Override - protected LIRFrameState newLIRFrameState(short reason, LabelRef exceptionEdge, BytecodeFrame frame, VirtualObject[] virtualObjectsArray) { - return new HotSpotLIRFrameState(frame, virtualObjectsArray, exceptionEdge, reason); + protected LIRFrameState newLIRFrameState(LabelRef exceptionEdge, BytecodeFrame frame, VirtualObject[] virtualObjectsArray) { + return new HotSpotLIRFrameState(frame, virtualObjectsArray, exceptionEdge); } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotLIRFrameState.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotLIRFrameState.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotLIRFrameState.java Wed Oct 02 13:26:31 2013 +0200 @@ -34,8 +34,8 @@ */ class HotSpotLIRFrameState extends LIRFrameState { - public HotSpotLIRFrameState(BytecodeFrame topFrame, VirtualObject[] virtualObjects, LabelRef exceptionEdge, short deoptimizationReason) { - super(topFrame, virtualObjects, exceptionEdge, deoptimizationReason); + public HotSpotLIRFrameState(BytecodeFrame topFrame, VirtualObject[] virtualObjects, LabelRef exceptionEdge) { + super(topFrame, virtualObjects, exceptionEdge); } @Override diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptions.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptions.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptions.java Wed Oct 02 13:26:31 2013 +0200 @@ -23,6 +23,7 @@ package com.oracle.graal.hotspot; +import static com.oracle.graal.compiler.GraalDebugConfig.*; import static java.nio.file.Files.*; import java.io.*; @@ -30,6 +31,7 @@ import java.nio.file.*; import java.util.*; +import com.oracle.graal.debug.*; import com.oracle.graal.hotspot.logging.*; import com.oracle.graal.options.*; @@ -174,6 +176,19 @@ } /** + * Called from VM code once all Graal command line options have been processed by + * {@link #setOption(String)}. + * + * @param ciTime the value of the CITime HotSpot VM option + */ + public static void finalizeOptions(boolean ciTime) { + if (areDebugScopePatternsEnabled() || ciTime) { + assert !Debug.Initialization.isDebugInitialized(); + System.setProperty(Debug.Initialization.INITIALIZER_PROPERTY_NAME, "true"); + } + } + + /** * Wraps some given text to one or more lines of a given maximum width. * * @param text text to wrap diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Wed Oct 02 13:26:31 2013 +0200 @@ -38,7 +38,7 @@ private static final long serialVersionUID = -4744897993263044184L; - private final HotSpotDiagnosticMXBean diagnostic = ManagementFactoryHelper.getDiagnosticMXBean(); + private static final HotSpotDiagnosticMXBean diagnostic = ManagementFactoryHelper.getDiagnosticMXBean(); HotSpotVMConfig(CompilerToVM c2vm) { c2vm.initializeConfiguration(this); @@ -52,9 +52,9 @@ * @return value of option * @throws IllegalArgumentException if option doesn't exist */ - private int getVMOptionInt(String name) { + public static int getVMOptionInt(String name) { String value = diagnostic.getVMOption(name).getValue(); - return new Integer(value).intValue(); + return Integer.valueOf(value).intValue(); } /** @@ -64,7 +64,7 @@ * @param defaultValue default value if option is not exists (e.g. development options) * @return value of option or defaultValue if option doesn't exist */ - private int getVMOption(String name, int defaultValue) { + public static int getVMOption(String name, int defaultValue) { try { return getVMOptionInt(name); } catch (IllegalArgumentException e) { @@ -79,9 +79,9 @@ * @return value of option * @throws IllegalArgumentException if option doesn't exist */ - private boolean getVMOption(String name) { + public static boolean getVMOption(String name) { String value = diagnostic.getVMOption(name).getValue(); - return new Boolean(value).booleanValue(); + return Boolean.valueOf(value).booleanValue(); } /** @@ -91,7 +91,7 @@ * @param defaultValue default value if option is not exists (e.g. development options) * @return value of option or defaultValue if option doesn't exist */ - private boolean getVMOption(String name, boolean defaultValue) { + public static boolean getVMOption(String name, boolean defaultValue) { try { return getVMOption(name); } catch (IllegalArgumentException e) { diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToGPU.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToGPU.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToGPU.java Wed Oct 02 13:26:31 2013 +0200 @@ -45,6 +45,8 @@ */ boolean deviceDetach(); + int availableProcessors(); + /** * Attempts to generate and return a bound function to the * loaded method kernel on the GPU. @@ -55,4 +57,8 @@ long generateKernel(byte[] code, String name) throws InvalidInstalledCodeException; Object executeExternalMethodVarargs(Object[] args, HotSpotInstalledCode hotspotInstalledCode) throws InvalidInstalledCodeException; + + + Object executeParallelMethodVarargs(int dimX, int dimY, int dimZ, + Object[] args, HotSpotInstalledCode hotspotInstalledCode) throws InvalidInstalledCodeException; } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToGPUImpl.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToGPUImpl.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToGPUImpl.java Wed Oct 02 13:26:31 2013 +0200 @@ -38,5 +38,12 @@ public native boolean deviceDetach(); - public native Object executeExternalMethodVarargs(Object[] args, HotSpotInstalledCode hotspotInstalledCode) throws InvalidInstalledCodeException; + public native int availableProcessors(); + + public native Object executeExternalMethodVarargs(Object[] args, + HotSpotInstalledCode hotspotInstalledCode) throws InvalidInstalledCodeException; + + public native Object executeParallelMethodVarargs(int dimX, int dimY, int dimZ, + Object[] args, + HotSpotInstalledCode hotspotInstalledCode) throws InvalidInstalledCodeException; } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java Wed Oct 02 13:26:31 2013 +0200 @@ -29,6 +29,7 @@ import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; import static com.oracle.graal.java.GraphBuilderPhase.*; import static com.oracle.graal.phases.GraalOptions.*; +import static com.oracle.graal.phases.common.InliningUtil.*; import java.io.*; import java.lang.reflect.*; @@ -51,7 +52,6 @@ import com.oracle.graal.options.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.PhasePlan.PhasePosition; -import com.oracle.graal.phases.common.*; import com.oracle.graal.printer.*; import com.oracle.graal.replacements.*; @@ -105,8 +105,6 @@ private PrintStream log = System.out; - private boolean quietMeterAndTime; - private long compilerStartTime; public VMToCompilerImpl(HotSpotGraalRuntime compiler) { @@ -165,13 +163,12 @@ } if (config.ciTime) { - quietMeterAndTime = (Meter.getValue() == null && Time.getValue() == null); - DebugEnabled.setValue(true); - Meter.setValue(""); - Time.setValue(""); + BytecodesParsed.setConditional(false); + InlinedBytecodes.setConditional(false); + CompilationTime.setConditional(false); } - if (DebugEnabled.getValue()) { + if (Debug.isEnabled()) { DebugEnvironment.initialize(log); String summary = DebugValueSummary.getValue(); @@ -374,7 +371,7 @@ CompilationStatistics.clear(phase); if (graalRuntime.getConfig().ciTime) { parsedBytecodesPerSecond = MetricRateInPhase.snapshot(phase, parsedBytecodesPerSecond, BytecodesParsed, CompilationTime, TimeUnit.SECONDS); - inlinedBytecodesPerSecond = MetricRateInPhase.snapshot(phase, inlinedBytecodesPerSecond, InliningUtil.InlinedBytecodes, CompilationTime, TimeUnit.SECONDS); + inlinedBytecodesPerSecond = MetricRateInPhase.snapshot(phase, inlinedBytecodesPerSecond, InlinedBytecodes, CompilationTime, TimeUnit.SECONDS); } } @@ -435,7 +432,7 @@ bootstrapRunning = false; - TTY.println(" in %d ms", System.currentTimeMillis() - startTime); + TTY.println(" in %d ms (compiled %d methods)", System.currentTimeMillis() - startTime, compileQueue.getCompletedTaskCount()); if (graalRuntime.getCache() != null) { graalRuntime.getCache().clear(); } @@ -476,7 +473,7 @@ CompilationTask.withinEnqueue.set(Boolean.FALSE); } - if (Debug.isEnabled() && !quietMeterAndTime) { + if (Debug.isEnabled() && areDebugScopePatternsEnabled()) { List topLevelMaps = DebugValueMap.getTopLevelMaps(); List debugValues = KeyRegistry.getDebugValues(); if (debugValues.size() > 0) { diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotNmethod.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotNmethod.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotNmethod.java Wed Oct 02 13:26:31 2013 +0200 @@ -123,6 +123,15 @@ return true; } + public Object executeParallel(int dimX, int dimY, int dimZ, Object... args) throws InvalidInstalledCodeException { + assert checkArgs(args); + + assert isExternal(); // for now + + return graalRuntime().getCompilerToGPU().executeParallelMethodVarargs(dimX, dimY, dimZ, args, this); + + } + @Override public Object executeVarargs(Object... args) throws InvalidInstalledCodeException { assert checkArgs(args); diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaField.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaField.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaField.java Wed Oct 02 13:26:31 2013 +0200 @@ -167,8 +167,14 @@ return true; } - private static final String SystemClassName = MetaUtil.toInternalName(System.class.getName()); + private static final String SystemClassName = "Ljava/lang/System;"; + /** + * {@inheritDoc} + *

+ * The {@code value} field in {@link OptionValue} is considered constant if the type of + * {@code receiver} is (assignable to) {@link StableOptionValue}. + */ @Override public Constant readConstantValue(Constant receiver) { assert !AOTCompilation.getValue() || isCalledForSnippets() : receiver; @@ -198,6 +204,7 @@ } else { Class clazz = object.getClass(); if (StableOptionValue.class.isAssignableFrom(clazz)) { + assert getName().equals("value") : "Unexpected field in " + StableOptionValue.class.getName() + " hierarchy:" + this; StableOptionValue option = (StableOptionValue) object; return Constant.forObject(option.getValue()); } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java Wed Oct 02 13:26:31 2013 +0200 @@ -218,6 +218,10 @@ @Override public int getMaxLocals() { + int modifiers = getModifiers(); + if (Modifier.isAbstract(modifiers) || Modifier.isNative(modifiers)) { + return 0; + } HotSpotVMConfig config = graalRuntime().getConfig(); long metaspaceConstMethod = unsafe.getLong(metaspaceMethod + config.methodConstMethodOffset); return unsafe.getShort(metaspaceConstMethod + config.methodMaxLocalsOffset) & 0xFFFF; @@ -225,6 +229,10 @@ @Override public int getMaxStackSize() { + int modifiers = getModifiers(); + if (Modifier.isAbstract(modifiers) || Modifier.isNative(modifiers)) { + return 0; + } HotSpotVMConfig config = graalRuntime().getConfig(); long metaspaceConstMethod = unsafe.getLong(metaspaceMethod + config.methodConstMethodOffset); return config.extraStackEntries + (unsafe.getShort(metaspaceConstMethod + config.constMethodMaxStackOffset) & 0xFFFF); @@ -407,6 +415,9 @@ @Override public LineNumberTable getLineNumberTable() { long[] values = graalRuntime().getCompilerToVM().getLineNumberTable(this); + if (values == null) { + return null; + } assert values.length % 2 == 0; int[] bci = new int[values.length / 2]; int[] line = new int[values.length / 2]; @@ -422,6 +433,9 @@ @Override public LocalVariableTable getLocalVariableTable() { Local[] locals = graalRuntime().getCompilerToVM().getLocalVariableTable(this); + if (locals == null) { + return null; + } return new LocalVariableTableImpl(locals); } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java Wed Oct 02 13:26:31 2013 +0200 @@ -345,7 +345,11 @@ @Override public ResolvedJavaMethod resolveMethod(ResolvedJavaMethod method) { assert method instanceof HotSpotMethod; - return (ResolvedJavaMethod) graalRuntime().getCompilerToVM().resolveMethod(this, method.getName(), ((HotSpotSignature) method.getSignature()).getMethodDescriptor()); + ResolvedJavaMethod res = (ResolvedJavaMethod) graalRuntime().getCompilerToVM().resolveMethod(this, method.getName(), ((HotSpotSignature) method.getSignature()).getMethodDescriptor()); + if (res == null || isAbstract(res.getModifiers())) { + return null; + } + return res; } @Override diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Wed Oct 02 13:26:31 2013 +0200 @@ -23,8 +23,8 @@ package com.oracle.graal.hotspot.meta; import static com.oracle.graal.api.code.CallingConvention.Type.*; -import static com.oracle.graal.api.code.DeoptimizationAction.*; import static com.oracle.graal.api.code.MemoryBarriers.*; +import static com.oracle.graal.api.meta.DeoptimizationAction.*; import static com.oracle.graal.api.meta.DeoptimizationReason.*; import static com.oracle.graal.api.meta.LocationIdentity.*; import static com.oracle.graal.graph.UnsafeAccess.*; @@ -49,6 +49,7 @@ import static com.oracle.graal.hotspot.stubs.StubUtil.*; import static com.oracle.graal.hotspot.stubs.UnwindExceptionToCallerStub.*; import static com.oracle.graal.java.GraphBuilderPhase.RuntimeCalls.*; +import static com.oracle.graal.nodes.java.ArrayLengthNode.*; import static com.oracle.graal.nodes.java.RegisterFinalizerNode.*; import static com.oracle.graal.phases.GraalOptions.*; import static com.oracle.graal.replacements.Log.*; @@ -85,7 +86,6 @@ import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.spi.Lowerable.LoweringType; import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.virtual.*; import com.oracle.graal.phases.tiers.*; @@ -290,7 +290,7 @@ registerForeignCall(VM_MESSAGE_C, c.vmMessageAddress, NativeCall, DESTROYS_REGISTERS, NOT_LEAF, REEXECUTABLE, NO_LOCATIONS); link(new NewInstanceStub(this, r, target, registerStubCall(NEW_INSTANCE, REEXECUTABLE, NOT_LEAF, ANY_LOCATION))); - link(new NewArrayStub(this, r, target, registerStubCall(NEW_ARRAY, REEXECUTABLE, NOT_LEAF, ANY_LOCATION))); + link(new NewArrayStub(this, r, target, registerStubCall(NEW_ARRAY, REEXECUTABLE, NOT_LEAF, INIT_LOCATION))); link(new ExceptionHandlerStub(this, r, target, foreignCalls.get(EXCEPTION_HANDLER))); link(new UnwindExceptionToCallerStub(this, r, target, registerStubCall(UNWIND_EXCEPTION_TO_CALLER, NOT_REEXECUTABLE, NOT_LEAF, ANY_LOCATION))); link(new VerifyOopStub(this, r, target, registerStubCall(VERIFY_OOP, REEXECUTABLE, LEAF, NO_LOCATIONS))); @@ -301,8 +301,8 @@ linkForeignCall(r, CREATE_OUT_OF_BOUNDS_EXCEPTION, c.createOutOfBoundsExceptionAddress, PREPEND_THREAD, NOT_LEAF, REEXECUTABLE, ANY_LOCATION); linkForeignCall(r, MONITORENTER, c.monitorenterAddress, PREPEND_THREAD, NOT_LEAF, NOT_REEXECUTABLE, ANY_LOCATION); linkForeignCall(r, MONITOREXIT, c.monitorexitAddress, PREPEND_THREAD, NOT_LEAF, NOT_REEXECUTABLE, ANY_LOCATION); - linkForeignCall(r, NEW_MULTI_ARRAY, c.newMultiArrayAddress, PREPEND_THREAD, NOT_LEAF, REEXECUTABLE, ANY_LOCATION); - linkForeignCall(r, DYNAMIC_NEW_ARRAY, c.dynamicNewArrayAddress, PREPEND_THREAD, NOT_LEAF, REEXECUTABLE, ANY_LOCATION); + linkForeignCall(r, NEW_MULTI_ARRAY, c.newMultiArrayAddress, PREPEND_THREAD, NOT_LEAF, REEXECUTABLE, INIT_LOCATION); + linkForeignCall(r, DYNAMIC_NEW_ARRAY, c.dynamicNewArrayAddress, PREPEND_THREAD, NOT_LEAF, REEXECUTABLE, INIT_LOCATION); linkForeignCall(r, LOG_PRINTF, c.logPrintfAddress, PREPEND_THREAD, LEAF, REEXECUTABLE, NO_LOCATIONS); linkForeignCall(r, LOG_OBJECT, c.logObjectAddress, PREPEND_THREAD, NOT_LEAF, REEXECUTABLE, NO_LOCATIONS); linkForeignCall(r, LOG_PRIMITIVE, c.logPrimitiveAddress, PREPEND_THREAD, NOT_LEAF, REEXECUTABLE, NO_LOCATIONS); @@ -477,9 +477,9 @@ } @Override - public int lookupArrayLength(Constant array) { + public Integer lookupArrayLength(Constant array) { if (array.getKind() != Kind.Object || array.isNull() || !array.asObject().getClass().isArray()) { - throw new IllegalArgumentException(array + " is not an array"); + return null; } return Array.getLength(array.asObject()); } @@ -555,10 +555,9 @@ assert loadField.kind() != Kind.Illegal; BarrierType barrierType = getFieldLoadBarrierType(field); ReadNode memoryRead = graph.add(new ReadNode(object, createFieldLocation(graph, field), loadField.stamp(), barrierType, (loadField.kind() == Kind.Object))); + graph.replaceFixedWithFixed(loadField, memoryRead); tool.createNullCheckGuard(memoryRead, object); - graph.replaceFixedWithFixed(loadField, memoryRead); - if (loadField.isVolatile()) { MembarNode preMembar = graph.add(new MembarNode(JMM_PRE_VOLATILE_READ)); graph.addBeforeFixed(memoryRead, preMembar); @@ -606,18 +605,21 @@ LocationNode arrayLocation = createArrayLocation(graph, elementKind, storeIndexed.index()); ValueNode value = storeIndexed.value(); ValueNode array = storeIndexed.array(); + + CheckCastNode checkcastNode = null; + CheckCastDynamicNode checkcastDynamicNode = null; if (elementKind == Kind.Object && !ObjectStamp.isObjectAlwaysNull(value)) { // Store check! ResolvedJavaType arrayType = ObjectStamp.typeOrNull(array); if (arrayType != null && ObjectStamp.isExactType(array)) { ResolvedJavaType elementType = arrayType.getComponentType(); if (!MetaUtil.isJavaLangObject(elementType)) { - CheckCastNode checkcast = graph.add(new CheckCastNode(elementType, value, null, true)); - graph.addBeforeFixed(storeIndexed, checkcast); - value = checkcast; + checkcastNode = graph.add(new CheckCastNode(elementType, value, null, true)); + graph.addBeforeFixed(storeIndexed, checkcastNode); + value = checkcastNode; } } else { - LoadHubNode arrayClass = graph.add(new LoadHubNode(array, wordKind, boundsCheck.asNode())); + FloatingReadNode arrayClass = createReadHub(graph, wordKind, array, boundsCheck); LocationNode location = ConstantLocationNode.create(FINAL_LOCATION, wordKind, config.arrayClassElementOffset, graph); /* * Anchor the read of the element klass to the cfg, because it is only valid @@ -625,9 +627,9 @@ * parts of the compiled method. */ FloatingReadNode arrayElementKlass = graph.unique(new FloatingReadNode(arrayClass, location, null, StampFactory.forKind(wordKind()), BeginNode.prevBegin(storeIndexed))); - CheckCastDynamicNode checkcast = graph.add(new CheckCastDynamicNode(arrayElementKlass, value, true)); - graph.addBeforeFixed(storeIndexed, checkcast); - value = checkcast; + checkcastDynamicNode = graph.add(new CheckCastDynamicNode(arrayElementKlass, value, true)); + graph.addBeforeFixed(storeIndexed, checkcastDynamicNode); + value = checkcastDynamicNode; } } BarrierType barrierType = getArrayStoreBarrierType(storeIndexed); @@ -636,12 +638,18 @@ memoryWrite.setStateAfter(storeIndexed.stateAfter()); graph.replaceFixedWithFixed(storeIndexed, memoryWrite); + // Lower the associated checkcast node. + if (checkcastNode != null) { + checkcastNode.lower(tool); + } else if (checkcastDynamicNode != null) { + checkcastDynamicSnippets.lower(checkcastDynamicNode); + } } else if (n instanceof UnsafeLoadNode) { - if (tool.getLoweringType().ordinal() > LoweringType.BEFORE_GUARDS.ordinal()) { + if (graph.getGuardsStage().ordinal() > StructuredGraph.GuardsStage.FLOATING_GUARDS.ordinal()) { UnsafeLoadNode load = (UnsafeLoadNode) n; assert load.kind() != Kind.Illegal; boolean compressible = (!load.object().isNullConstant() && load.accessKind() == Kind.Object); - if (addReadBarrier(load, tool)) { + if (addReadBarrier(load)) { unsafeLoadSnippets.lower(load, tool); } else { IndexedLocationNode location = IndexedLocationNode.create(ANY_LOCATION, load.accessKind(), load.displacement(), load.offset(), graph, 1); @@ -676,14 +684,8 @@ StoreHubNode storeHub = (StoreHubNode) n; WriteNode hub = createWriteHub(graph, wordKind, storeHub.getObject(), storeHub.getValue()); graph.replaceFixed(storeHub, hub); - } else if (n instanceof FixedGuardNode) { - FixedGuardNode node = (FixedGuardNode) n; - GuardingNode guard = tool.createGuard(node.condition(), node.getReason(), node.getAction(), node.isNegated()); - ValueAnchorNode newAnchor = graph.add(new ValueAnchorNode(guard.asNode())); - node.replaceAtUsages(guard.asNode()); - graph.replaceFixedWithFixed(node, newAnchor); } else if (n instanceof CommitAllocationNode) { - if (tool.getLoweringType() == LoweringType.AFTER_GUARDS) { + if (graph.getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS) { CommitAllocationNode commit = (CommitAllocationNode) n; ValueNode[] allocations = new ValueNode[commit.getVirtualObjects().size()]; @@ -749,6 +751,7 @@ for (int lockDepth : commit.getLocks().get(objIndex)) { MonitorEnterNode enter = graph.add(new MonitorEnterNode(allocations[objIndex], lockDepth)); graph.addBeforeFixed(commit, enter); + enter.lower(tool); } } for (Node usage : commit.usages().snapshot()) { @@ -759,7 +762,7 @@ graph.removeFixed(commit); } } else if (n instanceof OSRStartNode) { - if (tool.getLoweringType() == LoweringType.AFTER_GUARDS) { + if (graph.getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS) { OSRStartNode osrStart = (OSRStartNode) n; StartNode newStart = graph.add(new StartNode()); LocalNode buffer = graph.unique(new LocalNode(0, StampFactory.forKind(wordKind()))); @@ -788,31 +791,31 @@ } else if (n instanceof CheckCastDynamicNode) { checkcastDynamicSnippets.lower((CheckCastDynamicNode) n); } else if (n instanceof InstanceOfNode) { - if (tool.getLoweringType() == LoweringType.AFTER_GUARDS) { + if (graph.getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS) { instanceofSnippets.lower((InstanceOfNode) n, tool); } } else if (n instanceof InstanceOfDynamicNode) { - if (tool.getLoweringType() == LoweringType.AFTER_GUARDS) { + if (graph.getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS) { instanceofSnippets.lower((InstanceOfDynamicNode) n, tool); } } else if (n instanceof NewInstanceNode) { - if (tool.getLoweringType() == LoweringType.AFTER_FSA) { + if (graph.getGuardsStage() == StructuredGraph.GuardsStage.AFTER_FSA) { newObjectSnippets.lower((NewInstanceNode) n); } } else if (n instanceof NewArrayNode) { - if (tool.getLoweringType() == LoweringType.AFTER_FSA) { + if (graph.getGuardsStage() == StructuredGraph.GuardsStage.AFTER_FSA) { newObjectSnippets.lower((NewArrayNode) n); } } else if (n instanceof DynamicNewArrayNode) { - if (tool.getLoweringType() == LoweringType.AFTER_FSA) { + if (graph.getGuardsStage() == StructuredGraph.GuardsStage.AFTER_FSA) { newObjectSnippets.lower((DynamicNewArrayNode) n); } } else if (n instanceof MonitorEnterNode) { - if (tool.getLoweringType() == LoweringType.AFTER_GUARDS) { + if (graph.getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS) { monitorSnippets.lower((MonitorEnterNode) n, tool); } } else if (n instanceof MonitorExitNode) { - if (tool.getLoweringType() == LoweringType.AFTER_GUARDS) { + if (graph.getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS) { monitorSnippets.lower((MonitorExitNode) n, tool); } } else if (n instanceof G1PreWriteBarrier) { @@ -830,7 +833,7 @@ } else if (n instanceof G1ArrayRangePostWriteBarrier) { writeBarrierSnippets.lower((G1ArrayRangePostWriteBarrier) n, tool); } else if (n instanceof NewMultiArrayNode) { - if (tool.getLoweringType() == LoweringType.AFTER_FSA) { + if (graph.getGuardsStage() == StructuredGraph.GuardsStage.AFTER_FSA) { newObjectSnippets.lower((NewMultiArrayNode) n); } } else if (n instanceof LoadExceptionObjectNode) { @@ -838,8 +841,6 @@ } else if (n instanceof IntegerDivNode || n instanceof IntegerRemNode || n instanceof UnsignedDivNode || n instanceof UnsignedRemNode) { // Nothing to do for division nodes. The HotSpot signal handler catches divisions by // zero and the MIN_VALUE / -1 cases. - } else if (n instanceof UnwindNode || n instanceof DeoptimizeNode) { - // Nothing to do, using direct LIR lowering for these nodes. } else if (n instanceof BoxNode) { boxingSnippets.lower((BoxNode) n, tool); } else if (n instanceof UnboxNode) { @@ -850,8 +851,8 @@ } } - private static boolean addReadBarrier(UnsafeLoadNode load, LoweringTool tool) { - if (useG1GC() && tool.getLoweringType() == LoweringType.AFTER_GUARDS && load.object().kind() == Kind.Object && load.accessKind() == Kind.Object && + private static boolean addReadBarrier(UnsafeLoadNode load) { + if (useG1GC() && load.graph().getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS && load.object().kind() == Kind.Object && load.accessKind() == Kind.Object && !ObjectStamp.isObjectAlwaysNull(load.object())) { ResolvedJavaType type = ObjectStamp.typeOrNull(load.object()); if (type != null && !type.isArray()) { @@ -877,11 +878,11 @@ private FloatingReadNode createReadHub(StructuredGraph graph, Kind wordKind, ValueNode object, GuardingNode guard) { LocationNode location = ConstantLocationNode.create(FINAL_LOCATION, wordKind, config.hubOffset, graph); assert !object.isConstant() || object.asConstant().isNull(); - return graph.add(new FloatingReadNode(object, location, null, StampFactory.forKind(wordKind()), guard, BarrierType.NONE, useCompressedKlassPointers())); + return graph.unique(new FloatingReadNode(object, location, null, StampFactory.forKind(wordKind()), guard, BarrierType.NONE, useCompressedKlassPointers())); } private WriteNode createWriteHub(StructuredGraph graph, Kind wordKind, ValueNode object, ValueNode value) { - LocationNode location = ConstantLocationNode.create(ANY_LOCATION, wordKind, config.hubOffset, graph); + LocationNode location = ConstantLocationNode.create(HUB_LOCATION, wordKind, config.hubOffset, graph); assert !object.isConstant() || object.asConstant().isNull(); return graph.add(new WriteNode(object, value, location, BarrierType.NONE, useCompressedKlassPointers())); } @@ -991,13 +992,19 @@ } } - private static GuardingNode createBoundsCheck(AccessIndexedNode n, LoweringTool tool) { - StructuredGraph graph = n.graph(); - ArrayLengthNode arrayLength = graph.add(new ArrayLengthNode(n.array())); - GuardingNode guard = tool.createGuard(graph.unique(new IntegerBelowThanNode(n.index(), arrayLength)), BoundsCheckException, InvalidateReprofile); + private GuardingNode createBoundsCheck(AccessIndexedNode n, LoweringTool tool) { + StructuredGraph g = n.graph(); + ValueNode array = n.array(); + ValueNode arrayLength = readArrayLength(array, tool.getRuntime()); + if (arrayLength == null) { + Stamp stamp = StampFactory.positiveInt(); + ReadNode readArrayLength = g.add(new ReadNode(array, ConstantLocationNode.create(FINAL_LOCATION, Kind.Int, config.arrayLengthOffset, g), stamp, BarrierType.NONE, false)); + g.addBeforeFixed(n, readArrayLength); + tool.createNullCheckGuard(readArrayLength, array); + arrayLength = readArrayLength; + } - graph.addBeforeFixed(n, arrayLength); - return guard; + return tool.createGuard(g.unique(new IntegerBelowThanNode(n.index(), arrayLength)), BoundsCheckException, InvalidateReprofile); } public ResolvedJavaType lookupJavaType(Class clazz) { @@ -1069,13 +1076,13 @@ } @Override - public int encodeDeoptActionAndReason(DeoptimizationAction action, DeoptimizationReason reason) { + public Constant encodeDeoptActionAndReason(DeoptimizationAction action, DeoptimizationReason reason) { final int actionShift = 0; final int reasonShift = 3; int actionValue = convertDeoptAction(action); int reasonValue = convertDeoptReason(reason); - return (~(((reasonValue) << reasonShift) + ((actionValue) << actionShift))); + return Constant.forInt(~(((reasonValue) << reasonShift) + ((actionValue) << actionShift))); } public int convertDeoptAction(DeoptimizationAction action) { diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ArrayRangeWriteBarrier.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ArrayRangeWriteBarrier.java Wed Oct 02 13:26:31 2013 +0200 @@ -0,0 +1,45 @@ +/* + * 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.hotspot.nodes; + +import com.oracle.graal.nodes.*; + +public abstract class ArrayRangeWriteBarrier extends WriteBarrier { + + @Input private ValueNode startIndex; + @Input private ValueNode length; + + public ArrayRangeWriteBarrier(ValueNode object, ValueNode startIndex, ValueNode length) { + super(object, null, null, true); + this.startIndex = startIndex; + this.length = length; + } + + public ValueNode getStartIndex() { + return startIndex; + } + + public ValueNode getLength() { + return length; + } +} diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/BeginLockScopeNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/BeginLockScopeNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/BeginLockScopeNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -29,7 +29,6 @@ import com.oracle.graal.hotspot.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.word.*; /** @@ -42,8 +41,8 @@ private int lockDepth; - public BeginLockScopeNode(int lockDepth) { - super(StampFactory.forWord()); + private BeginLockScopeNode(int lockDepth) { + super(null); this.lockDepth = lockDepth; } @@ -66,6 +65,6 @@ gen.setResult(this, result); } - @NodeIntrinsic + @NodeIntrinsic(setStampFromReturnType = true) public static native Word beginLockScope(@ConstantNodeParameter int lockDepth); } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CStringNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CStringNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CStringNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -27,7 +27,6 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.word.*; /** @@ -38,13 +37,13 @@ private final String string; - public CStringNode(String string) { - super(StampFactory.forWord()); + private CStringNode(String string) { + super(null); this.string = string; } @Override - public void lower(LoweringTool tool, LoweringType loweringType) { + public void lower(LoweringTool tool) { byte[] formatBytes = string.getBytes(); long cstring = unsafe.allocateMemory(formatBytes.length + 1); for (int i = 0; i < formatBytes.length; i++) { @@ -55,6 +54,6 @@ graph().replaceFloating(this, replacement); } - @NodeIntrinsic + @NodeIntrinsic(setStampFromReturnType = true) public static native Word cstring(@ConstantNodeParameter String string); } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassCastNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassCastNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -0,0 +1,64 @@ +/* + * 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.hotspot.nodes; + +import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.hotspot.replacements.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.java.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.replacements.nodes.*; + +/** + * {@link MacroNode Macro node} for {@link Class#cast(Object)}. + * + * @see ClassSubstitutions#isInstance(Class, Object) + */ +public class ClassCastNode extends MacroNode implements Canonicalizable { + + public ClassCastNode(Invoke invoke) { + super(invoke); + } + + private ValueNode getJavaClass() { + return arguments.get(0); + } + + private ValueNode getObject() { + return arguments.get(1); + } + + public ValueNode canonical(CanonicalizerTool tool) { + ValueNode javaClass = getJavaClass(); + if (javaClass.isConstant()) { + ValueNode object = getObject(); + Class c = (Class) javaClass.asConstant().asObject(); + if (c != null && !c.isPrimitive()) { + HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) HotSpotResolvedObjectType.fromClass(c); + CheckCastNode checkcast = graph().add(new CheckCastNode(type, object, null, false)); + return checkcast; + } + } + return this; + } +} diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CurrentJavaThreadNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CurrentJavaThreadNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CurrentJavaThreadNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -28,16 +28,15 @@ import com.oracle.graal.graph.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.word.*; /** * Gets the address of the C++ JavaThread object for the current thread. */ -public class CurrentJavaThreadNode extends FloatingNode implements LIRLowerable { +public final class CurrentJavaThreadNode extends FloatingNode implements LIRLowerable { - public CurrentJavaThreadNode() { - super(StampFactory.forWord()); + private CurrentJavaThreadNode() { + super(null); } @Override @@ -54,7 +53,7 @@ } } - @NodeIntrinsic + @NodeIntrinsic(setStampFromReturnType = true) public static Word get() { return Word.unsigned(unsafeReadWord(Thread.currentThread(), eetopOffset())); } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CurrentLockNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CurrentLockNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CurrentLockNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -28,7 +28,6 @@ import com.oracle.graal.compiler.target.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.word.*; /** @@ -38,8 +37,8 @@ private int lockDepth; - public CurrentLockNode(int lockDepth) { - super(StampFactory.forWord()); + private CurrentLockNode(int lockDepth) { + super(null); this.lockDepth = lockDepth; } @@ -53,6 +52,6 @@ gen.setResult(this, result); } - @NodeIntrinsic + @NodeIntrinsic(setStampFromReturnType = true) public static native Word currentLock(@ConstantNodeParameter int lockDepth); } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DeoptimizeCallerNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DeoptimizeCallerNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DeoptimizeCallerNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -22,7 +22,6 @@ */ package com.oracle.graal.hotspot.nodes; -import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DeoptimizingStubCall.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DeoptimizingStubCall.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DeoptimizingStubCall.java Wed Oct 02 13:26:31 2013 +0200 @@ -22,7 +22,6 @@ */ package com.oracle.graal.hotspot.nodes; -import com.oracle.graal.api.meta.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.type.*; @@ -36,9 +35,4 @@ public boolean canDeoptimize() { return true; } - - @Override - public DeoptimizationReason getDeoptimizationReason() { - return null; - } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DimensionsNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DimensionsNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DimensionsNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -27,7 +27,6 @@ import com.oracle.graal.compiler.gen.*; import com.oracle.graal.compiler.target.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.word.*; /** @@ -38,8 +37,8 @@ private final int rank; - public DimensionsNode(int rank) { - super(StampFactory.forWord()); + private DimensionsNode(int rank) { + super(null); this.rank = rank; } @@ -51,6 +50,6 @@ gen.setResult(this, result); } - @NodeIntrinsic + @NodeIntrinsic(setStampFromReturnType = true) public static native Word allocaDimsArray(@ConstantNodeParameter int rank); } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1ArrayRangePostWriteBarrier.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1ArrayRangePostWriteBarrier.java Wed Oct 02 13:26:31 2013 +0200 @@ -0,0 +1,32 @@ +/* + * 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.hotspot.nodes; + +import com.oracle.graal.nodes.*; + +public final class G1ArrayRangePostWriteBarrier extends ArrayRangeWriteBarrier { + + public G1ArrayRangePostWriteBarrier(ValueNode object, ValueNode startIndex, ValueNode length) { + super(object, startIndex, length); + } +} diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1ArrayRangePreWriteBarrier.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1ArrayRangePreWriteBarrier.java Wed Oct 02 13:26:31 2013 +0200 @@ -0,0 +1,32 @@ +/* + * 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.hotspot.nodes; + +import com.oracle.graal.nodes.*; + +public final class G1ArrayRangePreWriteBarrier extends ArrayRangeWriteBarrier { + + public G1ArrayRangePreWriteBarrier(ValueNode object, ValueNode startIndex, ValueNode length) { + super(object, startIndex, length); + } +} diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1PostWriteBarrier.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1PostWriteBarrier.java Wed Oct 02 13:26:31 2013 +0200 @@ -0,0 +1,33 @@ +/* + * 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.hotspot.nodes; + +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.extended.*; + +public class G1PostWriteBarrier extends WriteBarrier { + + public G1PostWriteBarrier(ValueNode object, ValueNode value, LocationNode location, boolean precise) { + super(object, value, location, precise); + } +} diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1PreWriteBarrier.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1PreWriteBarrier.java Wed Oct 02 13:26:31 2013 +0200 @@ -0,0 +1,71 @@ +/* + * 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.hotspot.nodes; + +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.extended.*; + +public class G1PreWriteBarrier extends WriteBarrier implements DeoptimizingNode { + + @Input private FrameState deoptimizationState; + private final boolean nullCheck; + private final boolean doLoad; + + public G1PreWriteBarrier(ValueNode object, ValueNode expectedObject, LocationNode location, boolean doLoad, boolean nullCheck) { + super(object, expectedObject, location, true); + this.doLoad = doLoad; + this.nullCheck = nullCheck; + } + + public ValueNode getExpectedObject() { + return getValue(); + } + + public boolean doLoad() { + return doLoad; + } + + public boolean getNullCheck() { + return nullCheck; + } + + @Override + public boolean canDeoptimize() { + return nullCheck; + } + + @Override + public FrameState getDeoptimizationState() { + return deoptimizationState; + } + + @Override + public void setDeoptimizationState(FrameState state) { + updateUsages(deoptimizationState, state); + deoptimizationState = state; + } + + public FrameState getState() { + return deoptimizationState; + } +} diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1ReferentFieldReadBarrier.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1ReferentFieldReadBarrier.java Wed Oct 02 13:26:31 2013 +0200 @@ -0,0 +1,50 @@ +/* + * 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.hotspot.nodes; + +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.extended.*; + +/** + * The {@code G1ReferentFieldReadBarrier} is added when a read access is performed to the referent + * field of a {@link java.lang.ref.Reference} object (through a {@code LoadFieldNode} or an + * {@code UnsafeLoadNode}). The return value of the read is passed to the snippet implementing the + * read barrier and consequently is added to the SATB queue if the concurrent marker is enabled. + */ +public class G1ReferentFieldReadBarrier extends WriteBarrier { + + private final boolean doLoad; + + public G1ReferentFieldReadBarrier(ValueNode object, ValueNode expectedObject, LocationNode location, boolean doLoad) { + super(object, expectedObject, location, true); + this.doLoad = doLoad; + } + + public ValueNode getExpectedObject() { + return getValue(); + } + + public boolean doLoad() { + return doLoad; + } +} diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorCounterNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorCounterNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorCounterNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -27,7 +27,6 @@ import com.oracle.graal.compiler.gen.*; import com.oracle.graal.compiler.target.*; import com.oracle.graal.nodes.calc.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.word.*; /** @@ -35,8 +34,8 @@ */ public final class MonitorCounterNode extends FloatingNode implements LIRGenLowerable { - public MonitorCounterNode() { - super(StampFactory.forWord()); + private MonitorCounterNode() { + super(null); } @Override @@ -47,6 +46,6 @@ gen.setResult(this, result); } - @NodeIntrinsic + @NodeIntrinsic(setStampFromReturnType = true) public static native Word counter(); } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/SerialArrayRangeWriteBarrier.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/SerialArrayRangeWriteBarrier.java Wed Oct 02 13:26:31 2013 +0200 @@ -0,0 +1,32 @@ +/* + * 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.hotspot.nodes; + +import com.oracle.graal.nodes.*; + +public final class SerialArrayRangeWriteBarrier extends ArrayRangeWriteBarrier { + + public SerialArrayRangeWriteBarrier(ValueNode object, ValueNode startIndex, ValueNode length) { + super(object, startIndex, length); + } +} diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/SerialWriteBarrier.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/SerialWriteBarrier.java Wed Oct 02 13:26:31 2013 +0200 @@ -0,0 +1,33 @@ +/* + * 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.hotspot.nodes; + +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.extended.*; + +public class SerialWriteBarrier extends WriteBarrier { + + public SerialWriteBarrier(ValueNode object, ValueNode value, LocationNode location, boolean precise) { + super(object, value, location, precise); + } +} diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/StubForeignCallNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/StubForeignCallNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/StubForeignCallNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -23,7 +23,6 @@ package com.oracle.graal.hotspot.nodes; import com.oracle.graal.api.code.*; - import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; @@ -35,11 +34,10 @@ * Node for a {@linkplain ForeignCallDescriptor foreign} call from within a stub. */ @NodeInfo(nameTemplate = "StubForeignCall#{p#descriptor/s}") -public class StubForeignCallNode extends FixedWithNextNode implements DeoptimizingNode, LIRLowerable, MemoryCheckpoint.Multi { +public class StubForeignCallNode extends FixedWithNextNode implements LIRLowerable, MemoryCheckpoint.Multi { @Input private final NodeInputList arguments; private final MetaAccessProvider runtime; - @Input private FrameState deoptState; private final ForeignCallDescriptor descriptor; @@ -72,7 +70,7 @@ assert graph().start() instanceof StubStartNode; ForeignCallLinkage linkage = gen.getRuntime().lookupForeignCall(descriptor); Value[] operands = operands(gen); - Value result = gen.emitForeignCall(linkage, this, operands); + Value result = gen.emitForeignCall(linkage, null, operands); if (result != null) { gen.setResult(this, result); } @@ -85,23 +83,4 @@ } return super.toString(verbosity); } - - @Override - public boolean canDeoptimize() { - return false; - } - - @Override - public FrameState getDeoptimizationState() { - return null; - } - - @Override - public void setDeoptimizationState(FrameState state) { - } - - @Override - public DeoptimizationReason getDeoptimizationReason() { - return null; - } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/WriteBarrier.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/WriteBarrier.java Wed Oct 02 13:26:31 2013 +0200 @@ -0,0 +1,67 @@ +/* + * 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.hotspot.nodes; + +import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; + +public abstract class WriteBarrier extends FixedWithNextNode implements Lowerable, IterableNodeType { + + @Input private ValueNode object; + @Input private ValueNode value; + @Input private LocationNode location; + private final boolean precise; + + public WriteBarrier(ValueNode object, ValueNode value, LocationNode location, boolean precise) { + super(StampFactory.forVoid()); + this.object = object; + this.value = value; + this.location = location; + this.precise = precise; + } + + public ValueNode getValue() { + return value; + } + + public ValueNode getObject() { + return object; + } + + public LocationNode getLocation() { + return location; + } + + public boolean usePrecise() { + return precise; + } + + @Override + public void lower(LoweringTool tool) { + assert graph().getGuardsStage() == StructuredGraph.GuardsStage.AFTER_FSA; + tool.getRuntime().lower(this, tool); + } +} diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/LoadJavaMirrorWithKlassPhase.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/LoadJavaMirrorWithKlassPhase.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/LoadJavaMirrorWithKlassPhase.java Wed Oct 02 13:26:31 2013 +0200 @@ -61,7 +61,7 @@ Stamp stamp = StampFactory.exactNonNull(runtime.lookupJavaType(Class.class)); LocationNode location = graph.unique(ConstantLocationNode.create(FINAL_LOCATION, stamp.kind(), runtime.config.classMirrorOffset, graph)); - FloatingReadNode freadNode = graph.add(new FloatingReadNode(klassNode, location, null, stamp)); + FloatingReadNode freadNode = graph.unique(new FloatingReadNode(klassNode, location, null, stamp)); graph.replaceFloating(node, freadNode); } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/VerifyHotSpotOptionsPhase.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/VerifyHotSpotOptionsPhase.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/VerifyHotSpotOptionsPhase.java Wed Oct 02 13:26:31 2013 +0200 @@ -57,31 +57,41 @@ for (OptionDescriptor desc : opts) { if (HotSpotOptions.isHotSpotOption(desc)) { HotSpotResolvedObjectType holder = (HotSpotResolvedObjectType) runtime.lookupJavaType(desc.getDeclaringClass()); - if (!checked.contains(holder)) { - checked.add(holder); - for (ResolvedJavaMethod method : holder.getMethods()) { - if (method.isClassInitializer()) { - StructuredGraph graph = new StructuredGraph(method); - new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getEagerDefault(), OptimisticOptimizations.ALL).apply(graph); - new VerifyHotSpotOptionsPhase(holder, runtime).apply(graph); - } - } - } + checkType(holder, desc, runtime, checked); } } } return true; } + private static void checkType(HotSpotResolvedObjectType type, OptionDescriptor option, HotSpotRuntime runtime, Set checked) { + if (!checked.contains(type)) { + checked.add(type); + HotSpotResolvedObjectType superType = type.getSupertype(); + if (superType != null && !MetaUtil.isJavaLangObject(superType)) { + checkType(superType, option, runtime, checked); + } + for (ResolvedJavaMethod method : type.getMethods()) { + if (method.isClassInitializer()) { + StructuredGraph graph = new StructuredGraph(method); + new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getEagerDefault(), OptimisticOptimizations.ALL).apply(graph); + new VerifyHotSpotOptionsPhase(type, runtime, option).apply(graph); + } + } + } + } + private final HotSpotRuntime runtime; private final ResolvedJavaType declaringClass; private final ResolvedJavaType optionValueType; private final Set boxingTypes; + private final OptionDescriptor option; - public VerifyHotSpotOptionsPhase(ResolvedJavaType declaringClass, HotSpotRuntime runtime) { + public VerifyHotSpotOptionsPhase(ResolvedJavaType declaringClass, HotSpotRuntime runtime, OptionDescriptor option) { this.runtime = runtime; this.declaringClass = declaringClass; this.optionValueType = runtime.lookupJavaType(OptionValue.class); + this.option = option; this.boxingTypes = new HashSet<>(); for (Class c : new Class[]{Boolean.class, Byte.class, Short.class, Character.class, Integer.class, Float.class, Long.class, Double.class}) { this.boxingTypes.add(runtime.lookupJavaType(c)); @@ -136,7 +146,9 @@ private void error(Node node, String message) { String loc = GraphUtil.approxSourceLocation(node); - throw new GraalInternalError(String.format("HotSpot option declarer %s contains code pattern implying action other than initialization of an option:%n %s%n %s", + throw new GraalInternalError(String.format("The " + option.getName() + " option is declared in " + option.getDeclaringClass() + + " whose class hierarchy contains a class initializer (in %s) with a code pattern at or near %s implying an action other than initialization of an option:%n%n %s%n%n" + + "The recommended solution is to move " + option.getName() + " into a separate class (e.g., " + option.getDeclaringClass().getName() + ".Options).%n", toJavaName(declaringClass), loc, message)); } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/WriteBarrierAdditionPhase.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/WriteBarrierAdditionPhase.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/WriteBarrierAdditionPhase.java Wed Oct 02 13:26:31 2013 +0200 @@ -24,6 +24,8 @@ import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.hotspot.nodes.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.HeapAccess.BarrierType; import com.oracle.graal.nodes.extended.*; @@ -37,18 +39,18 @@ @Override protected void run(StructuredGraph graph) { - for (ReadNode node : graph.getNodes(ReadNode.class)) { - addReadNodeBarriers(node, graph); - } - for (WriteNode node : graph.getNodes(WriteNode.class)) { - addWriteNodeBarriers(node, graph); - } - for (LoweredCompareAndSwapNode node : graph.getNodes(LoweredCompareAndSwapNode.class)) { - addCASBarriers(node, graph); - } - for (ArrayRangeWriteNode node : graph.getNodes(ArrayRangeWriteNode.class)) { - if (node.isObjectArray()) { - addArrayRangeBarriers(node, graph); + for (Node n : graph.getNodes()) { + if (n instanceof ReadNode) { + addReadNodeBarriers((ReadNode) n, graph); + } else if (n instanceof WriteNode) { + addWriteNodeBarriers((WriteNode) n, graph); + } else if (n instanceof LoweredCompareAndSwapNode) { + addCASBarriers((LoweredCompareAndSwapNode) n, graph); + } else if (n instanceof ArrayRangeWriteNode) { + ArrayRangeWriteNode node = (ArrayRangeWriteNode) n; + if (node.isObjectArray()) { + addArrayRangeBarriers(node, graph); + } } } } @@ -63,53 +65,60 @@ } } - private static void addWriteNodeBarriers(WriteNode node, StructuredGraph graph) { + protected static void addG1PreWriteBarrier(AccessNode node, ValueNode object, ValueNode value, LocationNode location, boolean doLoad, boolean nullCheck, StructuredGraph graph) { + G1PreWriteBarrier preBarrier = graph.add(new G1PreWriteBarrier(object, value, location, doLoad, nullCheck)); + preBarrier.setDeoptimizationState(node.getDeoptimizationState()); + node.setNullCheck(false); + node.setDeoptimizationState(null); + graph.addBeforeFixed(node, preBarrier); + } + + protected void addG1PostWriteBarrier(AccessNode node, ValueNode object, ValueNode value, LocationNode location, boolean precise, StructuredGraph graph) { + graph.addAfterFixed(node, graph.add(new G1PostWriteBarrier(object, value, location, precise))); + } + + protected void addSerialPostWriteBarrier(AccessNode node, ValueNode object, ValueNode value, LocationNode location, boolean precise, StructuredGraph graph) { + graph.addAfterFixed(node, graph.add(new SerialWriteBarrier(object, value, location, precise))); + } + + private void addWriteNodeBarriers(WriteNode node, StructuredGraph graph) { BarrierType barrierType = node.getBarrierType(); if (barrierType == BarrierType.PRECISE) { if (useG1GC()) { if (!node.isInitialization()) { - G1PreWriteBarrier preBarrier = graph.add(new G1PreWriteBarrier(node.object(), null, node.location(), true, node.getNullCheck())); - preBarrier.setDeoptimizationState(node.getDeoptimizationState()); - node.setNullCheck(false); - node.setDeoptimizationState(null); - graph.addBeforeFixed(node, preBarrier); + addG1PreWriteBarrier(node, node.object(), null, node.location(), true, node.getNullCheck(), graph); } - graph.addAfterFixed(node, graph.add(new G1PostWriteBarrier(node.object(), node.value(), node.location(), true))); + addG1PostWriteBarrier(node, node.object(), node.value(), node.location(), true, graph); } else { - graph.addAfterFixed(node, graph.add(new SerialWriteBarrier(node.object(), node.value(), node.location(), true))); + addSerialPostWriteBarrier(node, node.object(), node.value(), node.location(), true, graph); } } else if (barrierType == BarrierType.IMPRECISE) { if (useG1GC()) { - G1PreWriteBarrier preBarrier = graph.add(new G1PreWriteBarrier(node.object(), null, node.location(), true, node.getNullCheck())); - preBarrier.setDeoptimizationState(node.getDeoptimizationState()); - node.setNullCheck(false); - node.setDeoptimizationState(null); - graph.addBeforeFixed(node, preBarrier); - graph.addAfterFixed(node, graph.add(new G1PostWriteBarrier(node.object(), node.value(), node.location(), false))); + addG1PreWriteBarrier(node, node.object(), null, node.location(), true, node.getNullCheck(), graph); + addG1PostWriteBarrier(node, node.object(), node.value(), node.location(), false, graph); } else { - graph.addAfterFixed(node, graph.add(new SerialWriteBarrier(node.object(), node.value(), node.location(), false))); + addSerialPostWriteBarrier(node, node.object(), node.value(), node.location(), false, graph); } } else { assert barrierType == BarrierType.NONE; } - } - private static void addCASBarriers(LoweredCompareAndSwapNode node, StructuredGraph graph) { + private void addCASBarriers(LoweredCompareAndSwapNode node, StructuredGraph graph) { BarrierType barrierType = node.getBarrierType(); if (barrierType == BarrierType.PRECISE) { if (useG1GC()) { - graph.addBeforeFixed(node, graph.add(new G1PreWriteBarrier(node.object(), node.getExpectedValue(), node.location(), false, false))); - graph.addAfterFixed(node, graph.add(new G1PostWriteBarrier(node.object(), node.getNewValue(), node.location(), true))); + addG1PreWriteBarrier(node, node.object(), node.getExpectedValue(), node.location(), false, false, graph); + addG1PostWriteBarrier(node, node.object(), node.getNewValue(), node.location(), true, graph); } else { - graph.addAfterFixed(node, graph.add(new SerialWriteBarrier(node.object(), node.getNewValue(), node.location(), true))); + addSerialPostWriteBarrier(node, node.object(), node.getNewValue(), node.location(), true, graph); } } else if (barrierType == BarrierType.IMPRECISE) { if (useG1GC()) { - graph.addBeforeFixed(node, graph.add(new G1PreWriteBarrier(node.object(), node.getExpectedValue(), node.location(), false, false))); - graph.addAfterFixed(node, graph.add(new G1PostWriteBarrier(node.object(), node.getNewValue(), node.location(), false))); + addG1PreWriteBarrier(node, node.object(), node.getExpectedValue(), node.location(), false, false, graph); + addG1PostWriteBarrier(node, node.object(), node.getNewValue(), node.location(), false, graph); } else { - graph.addAfterFixed(node, graph.add(new SerialWriteBarrier(node.object(), node.getNewValue(), node.location(), false))); + addSerialPostWriteBarrier(node, node.object(), node.getNewValue(), node.location(), false, graph); } } else { assert barrierType == BarrierType.NONE; @@ -129,5 +138,4 @@ graph.addAfterFixed(node, serialArrayRangeWriteBarrier); } } - } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/WriteBarrierVerificationPhase.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/WriteBarrierVerificationPhase.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/WriteBarrierVerificationPhase.java Wed Oct 02 13:26:31 2013 +0200 @@ -28,6 +28,7 @@ import java.util.*; import com.oracle.graal.graph.*; +import com.oracle.graal.hotspot.nodes.*; import com.oracle.graal.hotspot.replacements.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.HeapAccess.BarrierType; diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -24,9 +24,10 @@ import static com.oracle.graal.compiler.GraalCompiler.*; +import java.util.concurrent.*; + import com.oracle.graal.api.meta.*; import com.oracle.graal.debug.*; -import com.oracle.graal.graph.Node.IterableNodeType; import com.oracle.graal.loop.phases.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @@ -37,7 +38,7 @@ import com.oracle.graal.phases.tiers.*; import com.oracle.graal.replacements.nodes.*; -public class ArrayCopyNode extends MacroNode implements Virtualizable, IterableNodeType, Lowerable { +public class ArrayCopyNode extends MacroNode implements Virtualizable, Lowerable { public ArrayCopyNode(Invoke invoke) { super(invoke); @@ -63,7 +64,7 @@ return arguments.get(4); } - private StructuredGraph selectSnippet(LoweringTool tool, Replacements replacements) { + private StructuredGraph selectSnippet(LoweringTool tool, final Replacements replacements) { ResolvedJavaType srcType = ObjectStamp.typeOrNull(getSource().stamp()); ResolvedJavaType destType = ObjectStamp.typeOrNull(getDestination().stamp()); @@ -74,8 +75,15 @@ return null; } Kind componentKind = srcType.getComponentType().getKind(); - ResolvedJavaMethod snippetMethod = tool.getRuntime().lookupJavaMethod(ArrayCopySnippets.getSnippetForKind(componentKind)); - return replacements.getSnippet(snippetMethod); + final ResolvedJavaMethod snippetMethod = tool.getRuntime().lookupJavaMethod(ArrayCopySnippets.getSnippetForKind(componentKind)); + return Debug.scope("ArrayCopySnippet", snippetMethod, new Callable() { + + @Override + public StructuredGraph call() throws Exception { + return replacements.getSnippet(snippetMethod); + } + }); + } private static void unrollFixedLengthLoop(StructuredGraph snippetGraph, int length, LoweringTool tool) { @@ -87,31 +95,43 @@ // additions, etc. PhaseContext context = new PhaseContext(tool.getRuntime(), tool.assumptions(), tool.getReplacements()); new CanonicalizerPhase(true).apply(snippetGraph, context); - new LoopFullUnrollPhase(true).apply(snippetGraph, context); + new LoopFullUnrollPhase(new CanonicalizerPhase(true)).apply(snippetGraph, context); new CanonicalizerPhase(true).apply(snippetGraph, context); } @Override - protected StructuredGraph getSnippetGraph(LoweringTool tool) { + protected StructuredGraph getLoweredSnippetGraph(final LoweringTool tool) { if (!shouldIntrinsify(getTargetMethod())) { return null; } - Replacements replacements = tool.getReplacements(); + final Replacements replacements = tool.getReplacements(); StructuredGraph snippetGraph = selectSnippet(tool, replacements); if (snippetGraph == null) { - ResolvedJavaMethod snippetMethod = tool.getRuntime().lookupJavaMethod(ArrayCopySnippets.genericArraycopySnippet); - snippetGraph = replacements.getSnippet(snippetMethod).copy(); + final ResolvedJavaMethod snippetMethod = tool.getRuntime().lookupJavaMethod(ArrayCopySnippets.genericArraycopySnippet); + snippetGraph = Debug.scope("ArrayCopySnippet", snippetMethod, new Callable() { + + @Override + public StructuredGraph call() throws Exception { + return replacements.getSnippet(snippetMethod).copy(); + } + }); replaceSnippetInvokes(snippetGraph); } else { assert snippetGraph != null : "ArrayCopySnippets should be installed"; - + snippetGraph = snippetGraph.copy(); if (getLength().isConstant() && getLength().asConstant().asInt() <= GraalOptions.MaximumEscapeAnalysisArrayLength.getValue()) { - snippetGraph = snippetGraph.copy(); - unrollFixedLengthLoop(snippetGraph, getLength().asConstant().asInt(), tool); + final StructuredGraph copy = snippetGraph; + Debug.scope("ArrayCopySnippetSpecialization", snippetGraph.method(), new Runnable() { + + @Override + public void run() { + unrollFixedLengthLoop(copy, getLength().asConstant().asInt(), tool); + } + }); } } - return snippetGraph; + return lowerReplacement(snippetGraph, tool); } private static boolean checkBounds(int position, int length, VirtualObjectNode virtualObject) { diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CallSiteTargetNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CallSiteTargetNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CallSiteTargetNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -66,13 +66,15 @@ } @Override - public void lower(LoweringTool tool, LoweringType loweringType) { + public void lower(LoweringTool tool) { ConstantNode target = getConstantCallTarget(tool.getRuntime(), tool.assumptions()); if (target != null) { graph().replaceFixedWithFloating(this, target); } else { - graph().replaceFixedWithFixed(this, createInvoke()); + InvokeNode invoke = createInvoke(); + graph().replaceFixedWithFixed(this, invoke); + invoke.lower(tool); } } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CheckCastDynamicSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CheckCastDynamicSnippets.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CheckCastDynamicSnippets.java Wed Oct 02 13:26:31 2013 +0200 @@ -22,12 +22,12 @@ */ package com.oracle.graal.hotspot.replacements; -import static com.oracle.graal.api.code.DeoptimizationAction.*; +import static com.oracle.graal.api.meta.DeoptimizationAction.*; import static com.oracle.graal.api.meta.DeoptimizationReason.*; import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*; import static com.oracle.graal.hotspot.replacements.TypeCheckSnippetUtils.*; +import static com.oracle.graal.nodes.PiNode.*; import static com.oracle.graal.nodes.extended.BranchProbabilityNode.*; -import static com.oracle.graal.nodes.extended.UnsafeCastNode.*; import static com.oracle.graal.replacements.SnippetTemplate.*; import com.oracle.graal.api.code.*; @@ -59,7 +59,7 @@ } } BeginNode anchorNode = BeginNode.anchor(); - return unsafeCast(verifyOop(object), StampFactory.forNodeIntrinsic(), anchorNode); + return piCast(verifyOop(object), StampFactory.forNodeIntrinsic(), anchorNode); } public static class Templates extends AbstractTemplates { @@ -74,7 +74,7 @@ StructuredGraph graph = checkcast.graph(); ValueNode object = checkcast.object(); - Arguments args = new Arguments(dynamic); + Arguments args = new Arguments(dynamic, graph.getGuardsStage()); args.add("hub", checkcast.hub()); args.add("object", object); diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ClassSubstitutions.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ClassSubstitutions.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ClassSubstitutions.java Wed Oct 02 13:26:31 2013 +0200 @@ -23,7 +23,7 @@ package com.oracle.graal.hotspot.replacements; import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*; -import static com.oracle.graal.nodes.extended.UnsafeCastNode.*; +import static com.oracle.graal.nodes.PiNode.*; import java.lang.reflect.*; @@ -96,7 +96,7 @@ if (superKlass.equal(0)) { return null; } else { - return unsafeCast(superKlass.readObject(classMirrorOffset(), LocationIdentity.FINAL_LOCATION), Class.class, true, true); + return piCast(superKlass.readObject(classMirrorOffset(), LocationIdentity.FINAL_LOCATION), Class.class, true, true); } } } @@ -110,7 +110,7 @@ Word klass = loadWordFromObject(thisObj, klassOffset()); if (klass.notEqual(0)) { if ((readLayoutHelper(klass) & arrayKlassLayoutHelperIdentifier()) != 0) { - return unsafeCast(klass.readObject(arrayKlassComponentMirrorOffset(), LocationIdentity.FINAL_LOCATION), Class.class, true, true); + return piCast(klass.readObject(arrayKlassComponentMirrorOffset(), LocationIdentity.FINAL_LOCATION), Class.class, true, true); } } return null; @@ -121,4 +121,7 @@ public static boolean isInstance(final Class thisObj, Object obj) { return !isPrimitive(thisObj) && ConditionalNode.materializeIsInstance(thisObj, obj); } + + @MacroSubstitution(macro = ClassCastNode.class, isStatic = false) + public static native Object cast(final Class thisObj, Object obj); } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java Wed Oct 02 13:26:31 2013 +0200 @@ -22,7 +22,7 @@ */ package com.oracle.graal.hotspot.replacements; -import static com.oracle.graal.api.code.DeoptimizationAction.*; +import static com.oracle.graal.api.meta.DeoptimizationAction.*; import static com.oracle.graal.api.meta.DeoptimizationReason.*; import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*; @@ -215,24 +215,25 @@ Arguments args; + StructuredGraph graph = hub.graph(); if (hintInfo.hintHitProbability >= hintHitProbabilityThresholdForDeoptimizingSnippet()) { - Hints hints = createHints(hintInfo, runtime, false, hub.graph()); - args = new Arguments(instanceofWithProfile); + Hints hints = createHints(hintInfo, runtime, false, graph); + args = new Arguments(instanceofWithProfile, graph.getGuardsStage()); args.add("object", object); args.addVarargs("hints", Word.class, StampFactory.forKind(wordKind()), hints.hubs); args.addVarargs("hintIsPositive", boolean.class, StampFactory.forKind(Kind.Boolean), hints.isPositive); } else if (hintInfo.exact != null) { - args = new Arguments(instanceofExact); + args = new Arguments(instanceofExact, graph.getGuardsStage()); args.add("object", object); - args.add("exactHub", ConstantNode.forConstant(((HotSpotResolvedObjectType) hintInfo.exact).klass(), runtime, hub.graph())); + args.add("exactHub", ConstantNode.forConstant(((HotSpotResolvedObjectType) hintInfo.exact).klass(), runtime, graph)); } else if (type.isPrimaryType()) { - args = new Arguments(instanceofPrimary); + args = new Arguments(instanceofPrimary, graph.getGuardsStage()); args.add("hub", hub); args.add("object", object); args.addConst("superCheckOffset", type.superCheckOffset()); } else { - Hints hints = createHints(hintInfo, runtime, false, hub.graph()); - args = new Arguments(instanceofSecondary); + Hints hints = createHints(hintInfo, runtime, false, graph); + args = new Arguments(instanceofSecondary, graph.getGuardsStage()); args.add("hub", hub); args.add("object", object); args.addVarargs("hints", Word.class, StampFactory.forKind(getWordKind()), hints.hubs); @@ -250,7 +251,7 @@ InstanceOfDynamicNode instanceOf = (InstanceOfDynamicNode) replacer.instanceOf; ValueNode object = instanceOf.object(); - Arguments args = new Arguments(instanceofDynamic); + Arguments args = new Arguments(instanceofDynamic, instanceOf.graph().getGuardsStage()); args.add("mirror", instanceOf.mirror()); args.add("object", object); args.add("trueValue", replacer.trueValue); diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/LoadExceptionObjectSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/LoadExceptionObjectSnippets.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/LoadExceptionObjectSnippets.java Wed Oct 02 13:26:31 2013 +0200 @@ -24,7 +24,7 @@ import static com.oracle.graal.hotspot.meta.HotSpotRuntime.*; import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*; -import static com.oracle.graal.nodes.extended.UnsafeCastNode.*; +import static com.oracle.graal.nodes.PiNode.*; import static com.oracle.graal.replacements.SnippetTemplate.*; import com.oracle.graal.api.code.*; @@ -57,7 +57,7 @@ Object exception = readExceptionOop(thread); writeExceptionOop(thread, null); writeExceptionPc(thread, Word.zero()); - return unsafeCast(exception, StampFactory.forNodeIntrinsic()); + return piCast(exception, StampFactory.forNodeIntrinsic()); } public static class Templates extends AbstractTemplates { @@ -78,7 +78,7 @@ loadExceptionC.setStateAfter(loadExceptionObject.stateAfter()); graph.replaceFixedWithFixed(loadExceptionObject, loadExceptionC); } else { - Arguments args = new Arguments(loadException); + Arguments args = new Arguments(loadException, loadExceptionObject.graph().getGuardsStage()); template(args).instantiate(runtime, loadExceptionObject, DEFAULT_REPLACER, args); } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java Wed Oct 02 13:26:31 2013 +0200 @@ -405,9 +405,9 @@ Arguments args; if (useFastLocking) { - args = new Arguments(monitorenter); + args = new Arguments(monitorenter, graph.getGuardsStage()); } else { - args = new Arguments(monitorenterStub); + args = new Arguments(monitorenterStub, graph.getGuardsStage()); } args.add("object", monitorenterNode.object()); args.addConst("lockDepth", monitorenterNode.getLockDepth()); @@ -430,9 +430,9 @@ Arguments args; if (useFastLocking) { - args = new Arguments(monitorexit); + args = new Arguments(monitorexit, graph.getGuardsStage()); } else { - args = new Arguments(monitorexitStub); + args = new Arguments(monitorexitStub, graph.getGuardsStage()); } args.add("object", monitorexitNode.object()); args.addConst("lockDepth", monitorexitNode.getLockDepth()); @@ -507,7 +507,7 @@ invoke.setStateAfter(graph.add(stateAfter)); graph.addBeforeFixed(ret, invoke); - Arguments args = new Arguments(checkCounter); + Arguments args = new Arguments(checkCounter, graph.getGuardsStage()); args.addConst("errMsg", msg); inlineeGraph = template(args).copySpecializedGraph(); diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java Wed Oct 02 13:26:31 2013 +0200 @@ -23,11 +23,10 @@ package com.oracle.graal.hotspot.replacements; import static com.oracle.graal.api.code.UnsignedMath.*; -import static com.oracle.graal.api.meta.LocationIdentity.*; import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*; +import static com.oracle.graal.nodes.PiArrayNode.*; +import static com.oracle.graal.nodes.PiNode.*; import static com.oracle.graal.nodes.extended.BranchProbabilityNode.*; -import static com.oracle.graal.nodes.extended.UnsafeArrayCastNode.*; -import static com.oracle.graal.nodes.extended.UnsafeCastNode.*; import static com.oracle.graal.phases.GraalOptions.*; import static com.oracle.graal.replacements.SnippetTemplate.*; import static com.oracle.graal.replacements.nodes.ExplodeLoopNode.*; @@ -35,6 +34,8 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.debug.*; +import com.oracle.graal.graph.Node.ConstantNodeParameter; +import com.oracle.graal.graph.Node.NodeIntrinsic; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.nodes.*; import com.oracle.graal.nodes.*; @@ -56,6 +57,8 @@ */ public class NewObjectSnippets implements Snippets { + public static final LocationIdentity INIT_LOCATION = new NamedLocationIdentity("Initialization"); + @Snippet public static Word allocate(int size) { Word thread = thread(); @@ -87,8 +90,7 @@ new_stub.inc(); result = NewInstanceStubCall.call(hub); } - BeginNode anchorNode = BeginNode.anchor(); - return unsafeCast(verifyOop(result), StampFactory.forNodeIntrinsic(), anchorNode); + return piCast(verifyOop(result), StampFactory.forNodeIntrinsic()); } /** @@ -121,8 +123,7 @@ newarray_stub.inc(); result = NewArrayStubCall.call(hub, length); } - BeginNode anchorNode = BeginNode.anchor(); - return unsafeArrayCast(verifyOop(result), length, StampFactory.forNodeIntrinsic(), anchorNode); + return piArrayCast(verifyOop(result), length, StampFactory.forNodeIntrinsic()); } public static final ForeignCallDescriptor DYNAMIC_NEW_ARRAY = new ForeignCallDescriptor("dynamic_new_array", Object.class, Class.class, int.class); @@ -182,7 +183,7 @@ Word dims = DimensionsNode.allocaDimsArray(rank); ExplodeLoopNode.explodeLoop(); for (int i = 0; i < rank; i++) { - dims.writeInt(i * 4, dimensions[i], ANY_LOCATION); + dims.writeInt(i * 4, dimensions[i], INIT_LOCATION); } return NewMultiArrayStubCall.call(hub, rank, dims); } @@ -204,12 +205,12 @@ new_seqInit.inc(); explodeLoop(); for (int offset = instanceHeaderSize(); offset < size; offset += wordSize()) { - memory.writeWord(offset, Word.zero(), ANY_LOCATION); + memory.writeWord(offset, Word.zero(), INIT_LOCATION); } } else { new_loopInit.inc(); for (int offset = instanceHeaderSize(); offset < size; offset += wordSize()) { - memory.writeWord(offset, Word.zero(), ANY_LOCATION); + memory.writeWord(offset, Word.zero(), INIT_LOCATION); } } } @@ -220,7 +221,7 @@ * Formats some allocated memory with an object header and zeroes out the rest. */ public static Object formatArray(Word hub, int allocationSize, int length, int headerSize, Word memory, Word prototypeMarkWord, boolean fillContents) { - memory.writeInt(arrayLengthOffset(), length, ANY_LOCATION); + memory.writeInt(arrayLengthOffset(), length, INIT_LOCATION); /* * store hub last as the concurrent garbage collectors assume length is valid if hub field * is not null @@ -228,7 +229,7 @@ initializeObjectHeader(memory, prototypeMarkWord, hub); if (fillContents) { for (int offset = headerSize; offset < allocationSize; offset += wordSize()) { - memory.writeWord(offset, Word.zero(), ANY_LOCATION); + memory.writeWord(offset, Word.zero(), INIT_LOCATION); } } return memory.toObject(); @@ -255,7 +256,7 @@ ConstantNode hub = ConstantNode.forConstant(type.klass(), runtime, graph); int size = instanceSize(type); - Arguments args = new Arguments(allocateInstance); + Arguments args = new Arguments(allocateInstance, graph.getGuardsStage()); args.addConst("size", size); args.add("hub", hub); args.add("prototypeMarkWord", type.prototypeMarkWord()); @@ -278,7 +279,7 @@ final int headerSize = HotSpotRuntime.getArrayBaseOffset(elementKind); int log2ElementSize = CodeUtil.log2(((HotSpotRuntime) runtime).getScalingFactor(elementKind)); - Arguments args = new Arguments(allocateArray); + Arguments args = new Arguments(allocateArray, graph.getGuardsStage()); args.add("hub", hub); args.add("length", newArrayNode.length()); args.add("prototypeMarkWord", arrayType.prototypeMarkWord()); @@ -292,7 +293,7 @@ } public void lower(DynamicNewArrayNode newArrayNode) { - Arguments args = new Arguments(allocateArrayDynamic); + Arguments args = new Arguments(allocateArrayDynamic, newArrayNode.graph().getGuardsStage()); args.add("elementType", newArrayNode.getElementType()); args.add("length", newArrayNode.length()); args.addConst("fillContents", newArrayNode.fillContents()); @@ -311,7 +312,7 @@ HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) newmultiarrayNode.type(); ConstantNode hub = ConstantNode.forConstant(type.klass(), runtime, graph); - Arguments args = new Arguments(newmultiarray); + Arguments args = new Arguments(newmultiarray, graph.getGuardsStage()); args.add("hub", hub); args.addConst("rank", rank); args.addVarargs("dimensions", int.class, StampFactory.forKind(Kind.Int), dims); diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -25,9 +25,11 @@ import static com.oracle.graal.compiler.GraalCompiler.*; import java.lang.reflect.*; +import java.util.concurrent.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.debug.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; @@ -51,7 +53,7 @@ } @Override - protected StructuredGraph getSnippetGraph(LoweringTool tool) { + protected StructuredGraph getLoweredSnippetGraph(LoweringTool tool) { if (!shouldIntrinsify(getTargetMethod())) { return null; } @@ -69,12 +71,18 @@ } else { method = ObjectCloneSnippets.instanceCloneMethod; } - ResolvedJavaMethod snippetMethod = tool.getRuntime().lookupJavaMethod(method); - Replacements replacements = tool.getReplacements(); - StructuredGraph snippetGraph = replacements.getSnippet(snippetMethod); + final ResolvedJavaMethod snippetMethod = tool.getRuntime().lookupJavaMethod(method); + final Replacements replacements = tool.getReplacements(); + StructuredGraph snippetGraph = Debug.scope("ArrayCopySnippet", snippetMethod, new Callable() { + + @Override + public StructuredGraph call() throws Exception { + return replacements.getSnippet(snippetMethod); + } + }); assert snippetGraph != null : "ObjectCloneSnippets should be installed"; - return snippetGraph; + return lowerReplacement(snippetGraph.copy(), tool); } private static boolean isCloneableType(ResolvedJavaType type, MetaAccessProvider metaAccess) { diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneSnippets.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneSnippets.java Wed Oct 02 13:26:31 2013 +0200 @@ -29,7 +29,6 @@ import java.lang.reflect.*; -import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; @@ -56,9 +55,12 @@ Word prototypeMarkWord = hub.readWord(prototypeMarkWordOffset(), PROTOTYPE_MARK_WORD_LOCATION); Object result = NewObjectSnippets.allocateInstance(instanceSize, hub, prototypeMarkWord, false); - Pointer memory = Word.fromObject(result); for (int offset = instanceHeaderSize(); offset < instanceSize; offset += wordSize()) { - memory.writeWord(offset, Word.fromObject(src).readWord(offset, ANY_LOCATION), ANY_LOCATION); + /* + * TODO atomicity problem on 32-bit architectures: The JVM spec requires double values + * to be copied atomically, but here they are copied as two 4-byte word values. + */ + ObjectAccess.writeWord(result, offset, ObjectAccess.readWord(src, offset, ANY_LOCATION), ANY_LOCATION); } return result; @@ -73,9 +75,12 @@ Word prototypeMarkWord = hub.readWord(prototypeMarkWordOffset(), PROTOTYPE_MARK_WORD_LOCATION); Object result = NewObjectSnippets.allocateArray(hub, arrayLength, prototypeMarkWord, headerSize, log2ElementSize, false); - Pointer memory = Word.fromObject(result); for (int offset = headerSize; offset < sizeInBytes; offset += wordSize()) { - memory.writeWord(offset, Word.fromObject(src).readWord(offset, ANY_LOCATION), ANY_LOCATION); + /* + * TODO atomicity problem on 32-bit architectures: The JVM spec requires double values + * to be copied atomically, but here they are copied as two 4-byte word values. + */ + ObjectAccess.writeWord(result, offset, ObjectAccess.readWord(src, offset, ANY_LOCATION), ANY_LOCATION); } return result; } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectSubstitutions.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectSubstitutions.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectSubstitutions.java Wed Oct 02 13:26:31 2013 +0200 @@ -23,7 +23,7 @@ package com.oracle.graal.hotspot.replacements; import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*; -import static com.oracle.graal.nodes.extended.UnsafeCastNode.*; +import static com.oracle.graal.nodes.PiNode.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.api.replacements.*; @@ -41,7 +41,7 @@ @MethodSubstitution(isStatic = false, forced = true) public static Class getClass(final Object thisObj) { Word hub = loadHub(thisObj); - return unsafeCast(hub.readObject(Word.signed(classMirrorOffset()), LocationIdentity.FINAL_LOCATION), Class.class, true, true); + return piCast(hub.readObject(Word.signed(classMirrorOffset()), LocationIdentity.FINAL_LOCATION), Class.class, true, true); } @MethodSubstitution(isStatic = false) diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ReflectionGetCallerClassNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ReflectionGetCallerClassNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ReflectionGetCallerClassNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -47,13 +47,15 @@ } @Override - public void lower(LoweringTool tool, LoweringType loweringType) { + public void lower(LoweringTool tool) { ConstantNode callerClassNode = getCallerClassNode(tool.getRuntime()); if (callerClassNode != null) { graph().replaceFixedWithFloating(this, callerClassNode); } else { - graph().replaceFixedWithFixed(this, createInvoke()); + InvokeNode invoke = createInvoke(); + graph().replaceFixedWithFixed(this, invoke); + invoke.lower(tool); } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeArrayCopyNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeArrayCopyNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeArrayCopyNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -92,8 +92,8 @@ } @Override - public void lower(LoweringTool tool, LoweringType loweringType) { - if (loweringType == LoweringType.AFTER_FSA) { + public void lower(LoweringTool tool) { + if (graph().getGuardsStage() == StructuredGraph.GuardsStage.AFTER_FSA) { UnsafeArrayCopySnippets.Templates templates = tool.getReplacements().getSnippetTemplateCache(UnsafeArrayCopySnippets.Templates.class); templates.lower(this); } @@ -112,11 +112,7 @@ @Override public LocationIdentity getLocationIdentity() { - if (elementKind == null) { - return ANY_LOCATION; - } else { - return NamedLocationIdentity.getArrayLocation(elementKind); - } + return ANY_LOCATION; } @NodeIntrinsic diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeArrayCopySnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeArrayCopySnippets.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeArrayCopySnippets.java Wed Oct 02 13:26:31 2013 +0200 @@ -192,6 +192,11 @@ } } else { for (long i = 0; i < byteLength; i += VECTOR_SIZE) { + /* + * TODO atomicity problem on 32-bit architectures: The JVM spec requires double + * values to be copied atomically, but not long values. For example, on Intel 32-bit + * this code is not atomic as long as the vector kind remains Kind.Long. + */ Long a = UnsafeLoadNode.load(src, arrayBaseOffset, i + srcOffset, VECTOR_KIND); UnsafeStoreNode.store(dest, arrayBaseOffset, i + destOffset, a.longValue(), VECTOR_KIND); } @@ -225,22 +230,22 @@ int log2ElementSize = (layoutHelper >> layoutHelperLog2ElementSizeShift()) & layoutHelperLog2ElementSizeMask(); int headerSize = (layoutHelper >> layoutHelperHeaderSizeShift()) & layoutHelperHeaderSizeMask(); - Word srcOffset = (Word) Word.fromObject(src).add(headerSize).add(srcPos << log2ElementSize); - Word destOffset = (Word) Word.fromObject(dest).add(headerSize).add(destPos << log2ElementSize); - Word destStart = destOffset; - long sizeInBytes = ((long) length) << log2ElementSize; - Word destEnd = destOffset.add(Word.unsigned(length).shiftLeft(log2ElementSize)); + Unsigned srcOffset = Word.unsigned(srcPos).shiftLeft(log2ElementSize).add(headerSize); + Unsigned destOffset = Word.unsigned(destPos).shiftLeft(log2ElementSize).add(headerSize); + Unsigned destStart = destOffset; + Unsigned sizeInBytes = Word.unsigned(length).shiftLeft(log2ElementSize); + Unsigned destEnd = destOffset.add(Word.unsigned(length).shiftLeft(log2ElementSize)); - int nonVectorBytes = (int) (sizeInBytes % VECTOR_SIZE); - Word destNonVectorEnd = destStart.add(nonVectorBytes); + Unsigned nonVectorBytes = sizeInBytes.unsignedRemainder(Word.unsigned(VECTOR_SIZE)); + Unsigned destNonVectorEnd = destStart.add(nonVectorBytes); while (destOffset.belowThan(destNonVectorEnd)) { - destOffset.writeByte(0, srcOffset.readByte(0, ANY_LOCATION), ANY_LOCATION); + ObjectAccess.writeByte(dest, destOffset, ObjectAccess.readByte(src, srcOffset, ANY_LOCATION), ANY_LOCATION); destOffset = destOffset.add(1); srcOffset = srcOffset.add(1); } while (destOffset.belowThan(destEnd)) { - destOffset.writeWord(0, srcOffset.readWord(0, ANY_LOCATION), ANY_LOCATION); + ObjectAccess.writeWord(dest, destOffset, ObjectAccess.readWord(src, srcOffset, ANY_LOCATION), ANY_LOCATION); destOffset = destOffset.add(wordSize()); srcOffset = srcOffset.add(wordSize()); } @@ -279,7 +284,7 @@ assert snippet != null : "arraycopy snippet for " + elementKind.name() + " not found"; } - Arguments args = new Arguments(snippet); + Arguments args = new Arguments(snippet, node.graph().getGuardsStage()); node.addSnippetArguments(args); SnippetTemplate template = template(args); diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeLoadSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeLoadSnippets.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeLoadSnippets.java Wed Oct 02 13:26:31 2013 +0200 @@ -58,7 +58,7 @@ } public void lower(UnsafeLoadNode load, @SuppressWarnings("unused") LoweringTool tool) { - Arguments args = new Arguments(unsafeLoad); + Arguments args = new Arguments(unsafeLoad, load.graph().getGuardsStage()); args.add("object", load.object()); args.add("offset", load.offset()); args.add("disp", load.displacement()); diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/WriteBarrierSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/WriteBarrierSnippets.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/WriteBarrierSnippets.java Wed Oct 02 13:26:31 2013 +0200 @@ -49,18 +49,20 @@ public class WriteBarrierSnippets implements Snippets { private static final SnippetCounter.Group countersWriteBarriers = SnippetCounters.getValue() ? new SnippetCounter.Group("WriteBarriers") : null; - private static final SnippetCounter serialFieldWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "serialFieldWriteBarrier", "Number of Serial Field Write Barriers"); - private static final SnippetCounter serialArrayWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "serialArrayWriteBarrier", "Number of Serial Array Write Barriers"); - private static final SnippetCounter g1AttemptedPostWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "g1AttemptedPostWriteBarrierCounter", - "Number of attempted G1 Post Write Barriers"); - private static final SnippetCounter g1AttemptedPreWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "g1AttemptedPreWriteBarrierCounter", "Number of G1 attempted Pre Write Barriers"); - private static final SnippetCounter g1AttemptedRefFieldBarrierCounter = new SnippetCounter(countersWriteBarriers, "g1AttemptedRefFieldBarrierCounter", - "Number of G1 attempted Ref Field Read Barriers"); - private static final SnippetCounter g1EffectivePostWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "g1EffectivePostWriteBarrierCounter", - "Number of effective G1 Post Write Barriers"); - private static final SnippetCounter g1EffectivePreWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "g1EffectivePreWriteBarrierCounter", "Number of G1 effective Pre Write Barriers"); - private static final SnippetCounter g1EffectiveRefFieldBarrierCounter = new SnippetCounter(countersWriteBarriers, "g1EffectiveRefFieldBarrierCounter", - "Number of G1 effective Ref Field Read Barriers"); + private static final SnippetCounter serialWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "serialWriteBarrier", "Number of Serial Write Barriers"); + private static final SnippetCounter g1AttemptedPreWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "g1AttemptedPreWriteBarrier", "Number of G1 attempted Pre Write Barriers"); + private static final SnippetCounter g1EffectivePreWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "g1EffectivePreWriteBarrier", "Number of G1 effective Pre Write Barriers"); + private static final SnippetCounter g1ExecutedPreWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "g1ExecutedPreWriteBarrier", "Number of G1 executed Pre Write Barriers"); + private static final SnippetCounter g1AttemptedPostWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "g1AttemptedPostWriteBarrier", "Number of attempted G1 Post Write Barriers"); + private static final SnippetCounter g1EffectiveAfterXORPostWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "g1EffectiveAfterXORPostWriteBarrier", + "Number of effective G1 Post Write Barriers (after passing the XOR test)"); + private static final SnippetCounter g1EffectiveAfterNullPostWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "g1EffectiveAfterNullPostWriteBarrier", + "Number of effective G1 Post Write Barriers (after passing the NULL test)"); + private static final SnippetCounter g1ExecutedPostWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "g1ExecutedPostWriteBarrier", "Number of executed G1 Post Write Barriers"); + + public static final LocationIdentity GC_CARD_LOCATION = new NamedLocationIdentity("GC-Card"); + public static final LocationIdentity GC_LOG_LOCATION = new NamedLocationIdentity("GC-Log"); + public static final LocationIdentity GC_INDEX_LOCATION = new NamedLocationIdentity("GC-Index"); @Snippet public static void serialWriteBarrier(Object object, Object location, @ConstantParameter boolean usePrecise, @ConstantParameter boolean alwaysNull) { @@ -72,11 +74,10 @@ Pointer oop; if (usePrecise) { oop = Word.fromArray(fixedObject, location); - serialArrayWriteBarrierCounter.inc(); } else { oop = Word.fromObject(fixedObject); - serialFieldWriteBarrierCounter.inc(); } + serialWriteBarrierCounter.inc(); Word base = (Word) oop.unsignedShiftRight(cardTableShift()); long startAddress = cardTableStart(); int displacement = 0; @@ -85,7 +86,7 @@ } else { base = base.add(Word.unsigned(cardTableStart())); } - base.writeByte(displacement, (byte) 0); + base.writeByte(displacement, (byte) 0, GC_CARD_LOCATION); } @Snippet @@ -132,8 +133,9 @@ log(trace, "[%d] G1-Pre Thread %p Marking %d\n", gcCycle, thread.rawValue(), markingValue); log(trace, "[%d] G1-Pre Thread %p DoLoad %d\n", gcCycle, thread.rawValue(), doLoad ? 1L : 0L); } + g1AttemptedPreWriteBarrierCounter.inc(); // If the concurrent marker is enabled, the barrier is issued. - if (probability(NOT_LIKELY_PROBABILITY, markingValue != (byte) 0)) { + if (probability(NOT_FREQUENT_PROBABILITY, markingValue != (byte) 0)) { // If the previous value has to be loaded (before the write), the load is issued. // The load is always issued except the cases of CAS and referent field. if (probability(LIKELY_PROBABILITY, doLoad)) { @@ -142,25 +144,19 @@ log(trace, "[%d] G1-Pre Thread %p Previous Object %p\n ", gcCycle, thread.rawValue(), previousOop.rawValue()); verifyOop(previousOop.toObject()); } - g1AttemptedPreWriteBarrierCounter.inc(); - } else { - g1AttemptedRefFieldBarrierCounter.inc(); } + g1EffectivePreWriteBarrierCounter.inc(); // If the previous value is null the barrier should not be issued. if (probability(FREQUENT_PROBABILITY, previousOop.notEqual(0))) { - if (doLoad) { - g1EffectivePreWriteBarrierCounter.inc(); - } else { - g1EffectiveRefFieldBarrierCounter.inc(); - } + g1ExecutedPreWriteBarrierCounter.inc(); // If the thread-local SATB buffer is full issue a native call which will // initialize a new one and add the entry. if (probability(FREQUENT_PROBABILITY, indexValue.notEqual(0))) { Word nextIndex = indexValue.subtract(wordSize()); Word logAddress = bufferAddress.add(nextIndex); // Log the object to be marked as well as update the SATB's buffer next index. - logAddress.writeWord(0, previousOop); - indexAddress.writeWord(0, nextIndex); + logAddress.writeWord(0, previousOop, GC_LOG_LOCATION); + indexAddress.writeWord(0, nextIndex, GC_INDEX_LOCATION); } else { g1PreBarrierStub(G1WBPRECALL, previousOop.toObject()); } @@ -213,15 +209,20 @@ Word cardAddress = cardBase.add(displacement); g1AttemptedPostWriteBarrierCounter.inc(); - if (probability(LIKELY_PROBABILITY, xorResult.notEqual(0))) { + if (probability(FREQUENT_PROBABILITY, xorResult.notEqual(0))) { + g1EffectiveAfterXORPostWriteBarrierCounter.inc(); + // If the written value is not null continue with the barrier addition. if (probability(FREQUENT_PROBABILITY, writtenValue.notEqual(0))) { byte cardByte = cardAddress.readByte(0); + g1EffectiveAfterNullPostWriteBarrierCounter.inc(); + // If the card is already dirty, (hence already enqueued) skip the insertion. - if (probability(LIKELY_PROBABILITY, cardByte != (byte) 0)) { - g1EffectivePostWriteBarrierCounter.inc(); + if (probability(NOT_FREQUENT_PROBABILITY, cardByte != (byte) 0)) { log(trace, "[%d] G1-Post Thread: %p Card: %p \n", gcCycle, thread.rawValue(), Word.unsigned(cardByte).rawValue()); - cardAddress.writeByte(0, (byte) 0); + cardAddress.writeByte(0, (byte) 0, GC_CARD_LOCATION); + g1ExecutedPostWriteBarrierCounter.inc(); + // If the thread local card queue is full, issue a native call which will // initialize a new one and add the card entry. if (probability(FREQUENT_PROBABILITY, indexValue.notEqual(0))) { @@ -229,8 +230,8 @@ Word logAddress = bufferAddress.add(nextIndex); // Log the object to be scanned as well as update // the card queue's next index. - logAddress.writeWord(0, cardAddress); - indexAddress.writeWord(0, nextIndex); + logAddress.writeWord(0, cardAddress, GC_LOG_LOCATION); + indexAddress.writeWord(0, nextIndex, GC_INDEX_LOCATION); } else { g1PostBarrierStub(G1WBPOSTCALL, cardAddress); } @@ -264,8 +265,8 @@ indexValue = indexValue - wordSize(); Word logAddress = bufferAddress.add(Word.unsigned(indexValue)); // Log the object to be marked as well as update the SATB's buffer next index. - logAddress.writeWord(0, oop); - indexAddress.writeWord(0, Word.unsigned(indexValue)); + logAddress.writeWord(0, oop, GC_LOG_LOCATION); + indexAddress.writeWord(0, Word.unsigned(indexValue), GC_INDEX_LOCATION); } else { g1PreBarrierStub(G1WBPRECALL, oop.toObject()); } @@ -298,7 +299,7 @@ byte cardByte = cardAddress.readByte(0); // If the card is already dirty, (hence already enqueued) skip the insertion. if (cardByte != (byte) 0) { - cardAddress.writeByte(0, (byte) 0); + cardAddress.writeByte(0, (byte) 0, GC_CARD_LOCATION); // If the thread local card queue is full, issue a native call which will // initialize a new one and add the card entry. if (indexValue != 0) { @@ -306,8 +307,8 @@ Word logAddress = bufferAddress.add(Word.unsigned(indexValue)); // Log the object to be scanned as well as update // the card queue's next index. - logAddress.writeWord(0, cardAddress); - indexAddress.writeWord(0, Word.unsigned(indexValue)); + logAddress.writeWord(0, cardAddress, GC_LOG_LOCATION); + indexAddress.writeWord(0, Word.unsigned(indexValue), GC_INDEX_LOCATION); } else { g1PostBarrierStub(G1WBPOSTCALL, cardAddress); } @@ -340,7 +341,7 @@ } public void lower(SerialWriteBarrier writeBarrier, @SuppressWarnings("unused") LoweringTool tool) { - Arguments args = new Arguments(serialWriteBarrier); + Arguments args = new Arguments(serialWriteBarrier, writeBarrier.graph().getGuardsStage()); args.add("object", writeBarrier.getObject()); args.add("location", writeBarrier.getLocation()); args.addConst("usePrecise", writeBarrier.usePrecise()); @@ -349,7 +350,7 @@ } public void lower(SerialArrayRangeWriteBarrier arrayRangeWriteBarrier, @SuppressWarnings("unused") LoweringTool tool) { - Arguments args = new Arguments(serialArrayRangeWriteBarrier); + Arguments args = new Arguments(serialArrayRangeWriteBarrier, arrayRangeWriteBarrier.graph().getGuardsStage()); args.add("object", arrayRangeWriteBarrier.getObject()); args.add("startIndex", arrayRangeWriteBarrier.getStartIndex()); args.add("length", arrayRangeWriteBarrier.getLength()); @@ -357,7 +358,7 @@ } public void lower(G1PreWriteBarrier writeBarrierPre, @SuppressWarnings("unused") LoweringTool tool) { - Arguments args = new Arguments(g1PreWriteBarrier); + Arguments args = new Arguments(g1PreWriteBarrier, writeBarrierPre.graph().getGuardsStage()); args.add("object", writeBarrierPre.getObject()); args.add("expectedObject", writeBarrierPre.getExpectedObject()); args.add("location", writeBarrierPre.getLocation()); @@ -368,7 +369,7 @@ } public void lower(G1ReferentFieldReadBarrier readBarrier, @SuppressWarnings("unused") LoweringTool tool) { - Arguments args = new Arguments(g1ReferentReadBarrier); + Arguments args = new Arguments(g1ReferentReadBarrier, readBarrier.graph().getGuardsStage()); args.add("object", readBarrier.getObject()); args.add("expectedObject", readBarrier.getExpectedObject()); args.add("location", readBarrier.getLocation()); @@ -379,7 +380,7 @@ } public void lower(G1PostWriteBarrier writeBarrierPost, @SuppressWarnings("unused") LoweringTool tool) { - Arguments args = new Arguments(g1PostWriteBarrier); + Arguments args = new Arguments(g1PostWriteBarrier, writeBarrierPost.graph().getGuardsStage()); args.add("object", writeBarrierPost.getObject()); args.add("value", writeBarrierPost.getValue()); args.add("location", writeBarrierPost.getLocation()); @@ -390,7 +391,7 @@ } public void lower(G1ArrayRangePreWriteBarrier arrayRangeWriteBarrier, @SuppressWarnings("unused") LoweringTool tool) { - Arguments args = new Arguments(g1ArrayRangePreWriteBarrier); + Arguments args = new Arguments(g1ArrayRangePreWriteBarrier, arrayRangeWriteBarrier.graph().getGuardsStage()); args.add("object", arrayRangeWriteBarrier.getObject()); args.add("startIndex", arrayRangeWriteBarrier.getStartIndex()); args.add("length", arrayRangeWriteBarrier.getLength()); @@ -398,7 +399,7 @@ } public void lower(G1ArrayRangePostWriteBarrier arrayRangeWriteBarrier, @SuppressWarnings("unused") LoweringTool tool) { - Arguments args = new Arguments(g1ArrayRangePostWriteBarrier); + Arguments args = new Arguments(g1ArrayRangePostWriteBarrier, arrayRangeWriteBarrier.graph().getGuardsStage()); args.add("object", arrayRangeWriteBarrier.getObject()); args.add("startIndex", arrayRangeWriteBarrier.getStartIndex()); args.add("length", arrayRangeWriteBarrier.getLength()); diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ForeignCallStub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ForeignCallStub.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ForeignCallStub.java Wed Oct 02 13:26:31 2013 +0200 @@ -29,6 +29,7 @@ import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; import java.lang.reflect.*; +import java.util.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; @@ -223,13 +224,16 @@ boolean isObjectResult = linkage.getOutgoingCallingConvention().getReturn().getKind() == Kind.Object; GraphBuilder builder = new GraphBuilder(this); LocalNode[] locals = createLocals(builder, args); + List invokes = new ArrayList<>(3); ReadRegisterNode thread = prependThread || isObjectResult ? builder.append(new ReadRegisterNode(runtime.threadRegister(), true, false)) : null; ValueNode result = createTargetCall(builder, locals, thread); - createInvoke(builder, StubUtil.class, "handlePendingException", ConstantNode.forBoolean(isObjectResult, builder.graph)); + invokes.add(createInvoke(builder, StubUtil.class, "handlePendingException", ConstantNode.forBoolean(isObjectResult, builder.graph))); if (isObjectResult) { InvokeNode object = createInvoke(builder, HotSpotReplacementsUtil.class, "getAndClearObjectResult", thread); result = createInvoke(builder, StubUtil.class, "verifyObject", object); + invokes.add(object); + invokes.add((InvokeNode) result); } builder.append(new ReturnNode(linkage.getDescriptor().getResultType() == void.class ? null : result)); @@ -237,10 +241,15 @@ Debug.dump(builder.graph, "Initial stub graph"); } - for (InvokeNode invoke : builder.graph.getNodes(InvokeNode.class).snapshot()) { + /* Rewrite all word types that can come in from the method argument types. */ + new WordTypeRewriterPhase(runtime, wordKind()).apply(builder.graph); + /* Inline all method calls that are create above. */ + for (InvokeNode invoke : invokes) { inline(invoke); } - assert builder.graph.getNodes(InvokeNode.class).isEmpty(); + /* Clean up all code that is now dead after inlining. */ + new DeadCodeEliminationPhase().apply(builder.graph); + assert builder.graph.getNodes().filter(InvokeNode.class).isEmpty(); if (Debug.isDumpEnabled()) { Debug.dump(builder.graph, "Stub graph before compilation"); @@ -294,13 +303,9 @@ } private void inline(InvokeNode invoke) { - StructuredGraph graph = invoke.graph(); ResolvedJavaMethod method = ((MethodCallTargetNode) invoke.callTarget()).targetMethod(); ReplacementsImpl repl = new ReplacementsImpl(runtime, new Assumptions(false), runtime.getTarget()); StructuredGraph calleeGraph = repl.makeGraph(method, null, null); InliningUtil.inline(invoke, calleeGraph, false); - new NodeIntrinsificationPhase(runtime).apply(graph); - new WordTypeRewriterPhase(runtime, wordKind()).apply(graph); - new DeadCodeEliminationPhase().apply(graph); } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java Wed Oct 02 13:26:31 2013 +0200 @@ -36,6 +36,7 @@ import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.nodes.*; import com.oracle.graal.hotspot.replacements.*; +import com.oracle.graal.nodes.StructuredGraph.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.replacements.*; import com.oracle.graal.replacements.Snippet.ConstantParameter; @@ -66,7 +67,7 @@ Constant intArrayHub = intArrayType.klass(); intArrayHub = Constant.forIntegerKind(graalRuntime().getTarget().wordKind, intArrayHub.asLong(), null); - Arguments args = new Arguments(stub); + Arguments args = new Arguments(stub, GuardsStage.FLOATING_GUARDS); args.add("hub", null); args.add("length", null); args.addConst("intArrayHub", intArrayHub); diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java Wed Oct 02 13:26:31 2013 +0200 @@ -37,6 +37,7 @@ import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.nodes.*; import com.oracle.graal.hotspot.replacements.*; +import com.oracle.graal.nodes.StructuredGraph.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.replacements.*; import com.oracle.graal.replacements.Snippet.ConstantParameter; @@ -67,7 +68,7 @@ Constant intArrayHub = intArrayType.klass(); intArrayHub = Constant.forIntegerKind(graalRuntime().getTarget().wordKind, intArrayHub.asLong(), null); - Arguments args = new Arguments(stub); + Arguments args = new Arguments(stub, GuardsStage.FLOATING_GUARDS); args.add("hub", null); args.addConst("intArrayHub", intArrayHub); return args; diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/SnippetStub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/SnippetStub.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/SnippetStub.java Wed Oct 02 13:26:31 2013 +0200 @@ -29,6 +29,7 @@ import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.StructuredGraph.GuardsStage; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.replacements.*; import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates; @@ -79,7 +80,7 @@ * Adds the arguments to this snippet stub. */ protected Arguments makeArguments(SnippetInfo stub) { - Arguments args = new Arguments(stub); + Arguments args = new Arguments(stub, GuardsStage.FLOATING_GUARDS); for (int i = 0; i < stub.getParameterCount(); i++) { args.add(stub.getParameterName(i), null); } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/StubUtil.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/StubUtil.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/StubUtil.java Wed Oct 02 13:26:31 2013 +0200 @@ -22,7 +22,7 @@ */ package com.oracle.graal.hotspot.stubs; -import static com.oracle.graal.api.code.DeoptimizationAction.*; +import static com.oracle.graal.api.meta.DeoptimizationAction.*; import static com.oracle.graal.api.meta.DeoptimizationReason.*; import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; import static com.oracle.graal.hotspot.nodes.CStringNode.*; diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.hsail/src/com/oracle/graal/hsail/HSAILRegisterConfig.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hsail/src/com/oracle/graal/hsail/HSAILRegisterConfig.java Wed Oct 02 13:26:31 2013 +0200 @@ -0,0 +1,188 @@ +/* + * Copyright (c) 2009, 2012, 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.hsail; + +import com.oracle.graal.api.code.*; + +import com.oracle.graal.api.code.CallingConvention.Type; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; + +import static com.oracle.graal.hsail.HSAIL.*; + +/** + * This class defines a higher level interface for the register allocator to be able to access info + * about the {@link HSAIL} register set. + * + * Note: In HSAIL, the number of registers of each type is actually a variable number that must + * satisfy the equation: Total num of registers = No. of S registers + 2 * (No. of D registers) + 4 + * * (No. of Q registers) = 128 In other words we can have up to 128S or 64 D or 32Q or a blend. + * + * For now we haven't implemented support for a variable sized register file. Instead we've fixed + * the number of registers of each type so that they satisfy the above equation. See {@link HSAIL} + * for more details. + */ +public class HSAILRegisterConfig implements RegisterConfig { + + private final Register[] allocatable = {s0, s1, s2, s3, s4, s5, s6, /* s7, */s8, s9, s10, s11, s12, s13, s14, s15, s16, s17, s18, s19, s20, s21, s22, s23, s24, s25, s26, s27, s28, s29, s30, s31, + d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13, d14, d15, q0, q1, q2, q3, q4, q5, q6, q7, q8, q9, q10, q11, q12, q13, q14, q15}; + + private final Register[] regBitness32 = {s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15, s16, s17, s18, s19, s20, s21, s22, s23, s24, s25, s26, s27, s28, s29, s30, s31}; + private final Register[] regBitness64 = {d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13, d14, d15}; + private final RegisterAttributes[] attributesMap = RegisterAttributes.createMap(this, HSAIL.allRegisters); + + @Override + public Register getReturnRegister(Kind kind) { + switch (kind) { + case Boolean: + case Byte: + case Char: + case Short: + case Int: + case Long: + case Object: + return s0; + case Float: + case Double: + return d0; + case Void: + case Illegal: + return null; + default: + throw new UnsupportedOperationException("no return register for type " + kind); + } + } + + @Override + public Register getFrameRegister() { + // TODO Auto-generated method stub + return null; + } + + @Override + public CallingConvention getCallingConvention(Type type, JavaType returnType, JavaType[] parameterTypes, TargetDescription target, boolean stackOnly) { + return callingConvention(regBitness32, regBitness64, returnType, parameterTypes, type, target, stackOnly); + } + + private CallingConvention callingConvention(Register[] generalParameterRegisters, Register[] longParameterRegisters, JavaType returnType, JavaType[] parameterTypes, Type type, + TargetDescription target, boolean stackOnly) { + AllocatableValue[] locations = new AllocatableValue[parameterTypes.length]; + + int currentRegs32 = 0; + int currentRegs64 = 0; + int currentStackOffset = 0; + + for (int i = 0; i < parameterTypes.length; i++) { + final Kind kind = parameterTypes[i].getKind(); + + switch (kind) { + case Byte: + case Boolean: + case Short: + case Char: + case Int: + case Float: + + if (!stackOnly && currentRegs32 < generalParameterRegisters.length) { + Register register = generalParameterRegisters[currentRegs32++]; + locations[i] = register.asValue(kind); + } + break; + case Long: + case Object: + case Double: + if (!stackOnly && currentRegs64 < longParameterRegisters.length) { + Register register = longParameterRegisters[currentRegs64++]; + locations[i] = register.asValue(kind); + } + break; + default: + throw GraalInternalError.shouldNotReachHere(); + } + + if (locations[i] == null) { + locations[i] = StackSlot.get(kind.getStackKind(), currentStackOffset, !type.out); + currentStackOffset += Math.max(target.arch.getSizeInBytes(kind), target.wordSize); + } + } + + Kind returnKind = returnType == null ? Kind.Void : returnType.getKind(); + AllocatableValue returnLocation = returnKind == Kind.Void ? Value.ILLEGAL : getReturnRegister(returnKind).asValue(returnKind); + return new CallingConvention(currentStackOffset, returnLocation, locations); + } + + @Override + public Register[] getCallingConventionRegisters(Type type, Kind kind) { + throw new GraalInternalError("getCallingConventinoRegisters unimplemented"); + } + + @Override + public Register[] getAllocatableRegisters() { + return allocatable.clone(); + } + + @Override + public Register[] getAllocatableRegisters(PlatformKind kind) { + Kind k = (Kind) kind; + switch (k) { + case Int: + case Short: + case Byte: + case Float: + return regBitness32.clone(); + case Long: + case Double: + case Object: + return regBitness64.clone(); + + default: + throw new GraalInternalError("unknown register allocation"); + } + } + + @Override + public Register[] getCallerSaveRegisters() { + // TODO Auto-generated method stub + return new Register[0]; + } + + @Override + public CalleeSaveLayout getCalleeSaveLayout() { + return null; + } + + @Override + public RegisterAttributes[] getAttributesMap() { + return attributesMap.clone(); + } + + @Override + public Register getRegisterForRole(int id) { + throw new UnsupportedOperationException(); + } + + public HSAILRegisterConfig() { + + } +} diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.java/src/com/oracle/graal/java/FrameStateBuilder.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/FrameStateBuilder.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/FrameStateBuilder.java Wed Oct 02 13:26:31 2013 +0200 @@ -195,7 +195,7 @@ return null; } - PhiNode phi = graph.add(new PhiNode(currentValue.kind(), block)); + PhiNode phi = graph.addWithoutUnique(new PhiNode(currentValue.kind(), block)); for (int i = 0; i < block.phiPredecessorCount(); i++) { phi.addInput(currentValue); } @@ -293,7 +293,7 @@ } assert !block.isPhiAtMerge(value) : "phi function for this block already created"; - PhiNode phi = graph.add(new PhiNode(value.kind(), block)); + PhiNode phi = graph.addWithoutUnique(new PhiNode(value.kind(), block)); phi.addInput(value); return phi; } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Wed Oct 02 13:26:31 2013 +0200 @@ -22,8 +22,8 @@ */ package com.oracle.graal.java; -import static com.oracle.graal.api.code.DeoptimizationAction.*; import static com.oracle.graal.api.code.TypeCheckHints.*; +import static com.oracle.graal.api.meta.DeoptimizationAction.*; import static com.oracle.graal.api.meta.DeoptimizationReason.*; import static com.oracle.graal.bytecode.Bytecodes.*; import static com.oracle.graal.java.GraphBuilderPhase.RuntimeCalls.*; @@ -50,7 +50,6 @@ import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.util.*; import com.oracle.graal.phases.*; -import com.oracle.graal.phases.util.*; /** * The {@code GraphBuilder} class parses the bytecode of a method and builds the IR graph. @@ -81,6 +80,11 @@ protected StructuredGraph currentGraph; + /** + * Head of placeholder list. + */ + protected BlockPlaceholderNode placeholders; + private final MetaAccessProvider runtime; private ConstantPool constantPool; private ResolvedJavaMethod method; @@ -109,13 +113,24 @@ /** * Node that marks the begin of block during bytecode parsing. When a block is identified the * first time as a jump target, the placeholder is created and used as the successor for the - * jump. When the block is seen the second time, a MergeNode is created to correctly merge the - * now two different predecessor states. + * jump. When the block is seen the second time, a {@link MergeNode} is created to correctly + * merge the now two different predecessor states. */ - private static class BlockPlaceholderNode extends FixedWithNextNode implements Node.IterableNodeType { + private static class BlockPlaceholderNode extends FixedWithNextNode { + + // Cannot be explicitly declared as a Node type since it is not an input; + // would cause the !NODE_CLASS.isAssignableFrom(type) guarantee + // in NodeClass.FieldScanner.scanField() to fail. + private final Object nextPlaceholder; - public BlockPlaceholderNode() { + public BlockPlaceholderNode(GraphBuilderPhase builder) { super(StampFactory.forVoid()); + nextPlaceholder = builder.placeholders; + builder.placeholders = this; + } + + BlockPlaceholderNode nextPlaceholder() { + return (BlockPlaceholderNode) nextPlaceholder; } } @@ -200,17 +215,14 @@ lastInstr = genMonitorEnter(methodSynchronizedObject); } frameState.clearNonLiveLocals(blockMap.startBlock.localsLiveIn); + ((StateSplit) lastInstr).setStateAfter(frameState.create(0)); if (graphBuilderConfig.eagerInfopointMode()) { - ((StateSplit) lastInstr).setStateAfter(frameState.create(0)); - InfopointNode ipn = currentGraph.add(new InfopointNode(InfopointReason.METHOD_START)); + InfopointNode ipn = currentGraph.add(new InfopointNode(InfopointReason.METHOD_START, frameState.create(0))); lastInstr.setNext(ipn); lastInstr = ipn; } - // finish the start block - ((StateSplit) lastInstr).setStateAfter(frameState.create(0)); - currentBlock = blockMap.startBlock; blockMap.startBlock.entryState = frameState; if (blockMap.startBlock.isLoopHeader) { @@ -236,9 +248,12 @@ connectLoopEndToBegin(); // remove Placeholders - for (BlockPlaceholderNode n : currentGraph.getNodes(BlockPlaceholderNode.class)) { - currentGraph.removeFixed(n); + for (BlockPlaceholderNode n = placeholders; n != null; n = n.nextPlaceholder()) { + if (!n.isDeleted()) { + currentGraph.removeFixed(n); + } } + placeholders = null; // remove dead FrameStates for (Node n : currentGraph.getNodes(FrameState.class)) { @@ -305,6 +320,7 @@ * @param type the unresolved type of the constant */ protected void handleUnresolvedLoadConstant(JavaType type) { + assert !graphBuilderConfig.eagerResolving(); append(new DeoptimizeNode(InvalidateRecompile, Unresolved)); frameState.push(Kind.Object, appendConstant(Constant.NULL_OBJECT)); } @@ -314,6 +330,7 @@ * @param object the object value whose type is being checked against {@code type} */ protected void handleUnresolvedCheckCast(JavaType type, ValueNode object) { + assert !graphBuilderConfig.eagerResolving(); append(new FixedGuardNode(currentGraph.unique(new IsNullNode(object)), Unresolved, InvalidateRecompile)); frameState.apush(appendConstant(Constant.NULL_OBJECT)); } @@ -323,7 +340,8 @@ * @param object the object value whose type is being checked against {@code type} */ protected void handleUnresolvedInstanceOf(JavaType type, ValueNode object) { - BlockPlaceholderNode successor = currentGraph.add(new BlockPlaceholderNode()); + assert !graphBuilderConfig.eagerResolving(); + BlockPlaceholderNode successor = currentGraph.add(new BlockPlaceholderNode(this)); DeoptimizeNode deopt = currentGraph.add(new DeoptimizeNode(InvalidateRecompile, Unresolved)); append(new IfNode(currentGraph.unique(new IsNullNode(object)), successor, deopt, 1)); lastInstr = successor; @@ -334,6 +352,7 @@ * @param type the type being instantiated */ protected void handleUnresolvedNewInstance(JavaType type) { + assert !graphBuilderConfig.eagerResolving(); append(new DeoptimizeNode(InvalidateRecompile, Unresolved)); frameState.apush(appendConstant(Constant.NULL_OBJECT)); } @@ -343,6 +362,7 @@ * @param length the length of the array */ protected void handleUnresolvedNewObjectArray(JavaType type, ValueNode length) { + assert !graphBuilderConfig.eagerResolving(); append(new DeoptimizeNode(InvalidateRecompile, Unresolved)); frameState.apush(appendConstant(Constant.NULL_OBJECT)); } @@ -352,6 +372,7 @@ * @param dims the dimensions for the multi-array */ protected void handleUnresolvedNewMultiArray(JavaType type, ValueNode[] dims) { + assert !graphBuilderConfig.eagerResolving(); append(new DeoptimizeNode(InvalidateRecompile, Unresolved)); frameState.apush(appendConstant(Constant.NULL_OBJECT)); } @@ -361,6 +382,7 @@ * @param receiver the object containing the field or {@code null} if {@code field} is static */ protected void handleUnresolvedLoadField(JavaField field, ValueNode receiver) { + assert !graphBuilderConfig.eagerResolving(); Kind kind = field.getKind(); append(new DeoptimizeNode(InvalidateRecompile, Unresolved)); frameState.push(kind.getStackKind(), appendConstant(Constant.defaultForKind(kind))); @@ -372,6 +394,7 @@ * @param receiver the object containing the field or {@code null} if {@code field} is static */ protected void handleUnresolvedStoreField(JavaField field, ValueNode value, ValueNode receiver) { + assert !graphBuilderConfig.eagerResolving(); append(new DeoptimizeNode(InvalidateRecompile, Unresolved)); } @@ -380,10 +403,12 @@ * @param type */ protected void handleUnresolvedExceptionType(Representation representation, JavaType type) { + assert !graphBuilderConfig.eagerResolving(); append(new DeoptimizeNode(InvalidateRecompile, Unresolved)); } protected void handleUnresolvedInvoke(JavaMethod javaMethod, InvokeKind invokeKind) { + assert !graphBuilderConfig.eagerResolving(); boolean withReceiver = invokeKind != InvokeKind.Static; append(new DeoptimizeNode(InvalidateRecompile, Unresolved)); frameState.popArguments(javaMethod.getSignature().getParameterSlots(withReceiver), javaMethod.getSignature().getParameterCount(withReceiver)); @@ -925,8 +950,8 @@ if (ObjectStamp.isObjectNonNull(receiver.stamp())) { return; } - BlockPlaceholderNode trueSucc = currentGraph.add(new BlockPlaceholderNode()); - BlockPlaceholderNode falseSucc = currentGraph.add(new BlockPlaceholderNode()); + BlockPlaceholderNode trueSucc = currentGraph.add(new BlockPlaceholderNode(this)); + BlockPlaceholderNode falseSucc = currentGraph.add(new BlockPlaceholderNode(this)); append(new IfNode(currentGraph.unique(new IsNullNode(receiver)), trueSucc, falseSucc, 0.01)); lastInstr = falseSucc; @@ -949,8 +974,8 @@ } private void emitBoundsCheck(ValueNode index, ValueNode length) { - BlockPlaceholderNode trueSucc = currentGraph.add(new BlockPlaceholderNode()); - BlockPlaceholderNode falseSucc = currentGraph.add(new BlockPlaceholderNode()); + BlockPlaceholderNode trueSucc = currentGraph.add(new BlockPlaceholderNode(this)); + BlockPlaceholderNode falseSucc = currentGraph.add(new BlockPlaceholderNode(this)); append(new IfNode(currentGraph.unique(new IntegerBelowThanNode(index, length)), trueSucc, falseSucc, 0.99)); lastInstr = trueSucc; @@ -1147,7 +1172,7 @@ } if (invokeKind != InvokeKind.Static) { emitExplicitExceptions(args[0], null); - if (invokeKind != InvokeKind.Special) { + if (invokeKind != InvokeKind.Special && this.optimisticOpts.useTypeCheckHints()) { JavaTypeProfile profile = profilingInfo.getTypeProfile(bci()); args[0] = TypeProfileProxyNode.create(args[0], profile); } @@ -1448,7 +1473,7 @@ // This is the first time we see this block as a branch target. // Create and return a placeholder that later can be replaced with a MergeNode when we // see this block again. - block.firstInstruction = currentGraph.add(new BlockPlaceholderNode()); + block.firstInstruction = currentGraph.add(new BlockPlaceholderNode(this)); Target target = checkLoopExit(block.firstInstruction, block, state); FixedNode result = target.fixed; block.entryState = target.state == state ? state.copy() : target.state; @@ -1601,19 +1626,13 @@ ValueNode x = returnKind == Kind.Void ? null : frameState.pop(returnKind); assert frameState.stackSize() == 0; - if (Modifier.isSynchronized(method.getModifiers())) { - append(new ValueAnchorNode(true, x)); - assert !frameState.rethrowException(); - } - synchronizedEpilogue(FrameState.AFTER_BCI); if (frameState.lockDepth() != 0) { throw new BailoutException("unbalanced monitors"); } if (graphBuilderConfig.eagerInfopointMode()) { - InfopointNode ipn = append(new InfopointNode(InfopointReason.METHOD_END)); - ipn.setStateAfter(frameState.create(FrameState.AFTER_BCI)); + append(new InfopointNode(InfopointReason.METHOD_END, frameState.create(FrameState.AFTER_BCI))); } append(new ReturnNode(x)); @@ -1643,9 +1662,9 @@ if (initialized && graphBuilderConfig.getSkippedExceptionTypes() != null) { ResolvedJavaType resolvedCatchType = (ResolvedJavaType) catchType; for (ResolvedJavaType skippedType : graphBuilderConfig.getSkippedExceptionTypes()) { - initialized &= !skippedType.isAssignableFrom(resolvedCatchType); - if (!initialized) { - break; + if (skippedType.isAssignableFrom(resolvedCatchType)) { + append(new DeoptimizeNode(InvalidateReprofile, UnreachedCode)); + return; } } } @@ -1673,20 +1692,7 @@ } private static boolean isBlockEnd(Node n) { - return trueSuccessorCount(n) > 1 || n instanceof ReturnNode || n instanceof UnwindNode || n instanceof DeoptimizeNode; - } - - private static int trueSuccessorCount(Node n) { - if (n == null) { - return 0; - } - int i = 0; - for (Node s : n.successors()) { - if (Util.isFixed(s)) { - i++; - } - } - return i; + return n instanceof ControlSplitNode || n instanceof ControlSinkNode; } private void iterateBytecodesForBlock(Block block) { @@ -1728,8 +1734,7 @@ if (graphBuilderConfig.eagerInfopointMode() && lnt != null) { currentLineNumber = lnt.getLineNumber(bci); if (currentLineNumber != previousLineNumber) { - InfopointNode ipn = append(new InfopointNode(InfopointReason.LINE_NUMBER)); - ipn.setStateAfter(frameState.create(bci)); + append(new InfopointNode(InfopointReason.LINE_NUMBER, frameState.create(bci))); previousLineNumber = currentLineNumber; } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/ArrayCopyGeneric.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/ArrayCopyGeneric.java Wed Oct 02 13:26:31 2013 +0200 @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2011, 2012, 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.jtt.optimize; + +import com.oracle.graal.jtt.*; + +import org.junit.*; + +/* + * Tests calls to the array copy method. + */ +public class ArrayCopyGeneric extends JTTTest { + + public Object[] arraysFrom; + public Object[] arraysTo; + + public void init() { + arraysFrom = new Object[]{new byte[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, new short[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, new int[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, + new long[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, new float[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, new double[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}}; + arraysTo = new Object[]{new byte[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, new short[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, new int[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, + new long[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, new float[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, new double[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}}; + } + + public Object test() { + init(); + + for (int i = 0; i < arraysFrom.length; i++) { + Object from = arraysFrom[i]; + Object to = arraysTo[i]; + System.arraycopy(from, 1, to, 2, 2); + System.arraycopy(from, 8, to, 7, 2); + } + return arraysTo; + } + + @Test + public void run0() throws Throwable { + runTest("test"); + } +} diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Call.java --- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Call.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Call.java Wed Oct 02 13:26:31 2013 +0200 @@ -28,6 +28,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.amd64.*; +import com.oracle.graal.asm.amd64.AMD64Assembler.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.asm.*; import com.oracle.graal.nodes.spi.*; @@ -182,6 +183,14 @@ masm.ensureUniquePC(); } + public static void directConditionalJmp(TargetMethodAssembler tasm, AMD64MacroAssembler masm, InvokeTarget target, ConditionFlag cond) { + int before = masm.codeBuffer.position(); + masm.jcc(cond, 0, true); + int after = masm.codeBuffer.position(); + tasm.recordDirectCall(before, after, target, null); + masm.ensureUniquePC(); + } + public static void indirectCall(TargetMethodAssembler tasm, AMD64MacroAssembler masm, Register dst, InvokeTarget callTarget, LIRFrameState info) { int before = masm.codeBuffer.position(); masm.call(dst); diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64FrameMap.java --- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64FrameMap.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64FrameMap.java Wed Oct 02 13:26:31 2013 +0200 @@ -28,12 +28,12 @@ /** * AMD64 specific frame map. - * + * * This is the format of an AMD64 stack frame: - * + * *

  *   Base       Contents
- * 
+ *
  *            :                                :  -----
  *   caller   | incoming overflow argument n   |    ^
  *   frame    :     ...                        :    | positive
@@ -55,9 +55,9 @@
  *            :     ...                        :    | positive   |      |
  *            | outgoing overflow argument 0   |    | offsets    v      v
  *    %sp-->  +--------------------------------+---------------------------
- * 
+ *
  * 
- * + * * The spill slot area also includes stack allocated memory blocks (ALLOCA blocks). The size of such * a block may be greater than the size of a normal spill slot or the word size. *

@@ -67,7 +67,7 @@ * call-free methods also have this space reserved. Then the VM can use the memory at offset 0 * relative to the stack pointer. */ -public final class AMD64FrameMap extends FrameMap { +public class AMD64FrameMap extends FrameMap { public AMD64FrameMap(CodeCacheProvider runtime, TargetDescription target, RegisterConfig registerConfig) { super(runtime, target, registerConfig); diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILAddressValue.java --- a/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILAddressValue.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILAddressValue.java Wed Oct 02 13:26:31 2013 +0200 @@ -66,7 +66,7 @@ } public HSAILAddress toAddress() { - Register baseReg = base == Value.ILLEGAL ? Register.None : asRegister(base); + Register baseReg = base.equals(Value.ILLEGAL) ? Register.None : asRegister(base); return new HSAILAddress(baseReg, displacement); } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXAddressValue.java --- a/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXAddressValue.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXAddressValue.java Wed Oct 02 13:26:31 2013 +0200 @@ -25,7 +25,6 @@ import static com.oracle.graal.api.code.ValueUtil.*; import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; -import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.ptx.*; import com.oracle.graal.lir.*; @@ -69,8 +68,8 @@ } public PTXAddress toAddress() { - Register baseReg = base == Value.ILLEGAL ? Register.None : asRegister(base); - return new PTXAddress(baseReg, displacement); + // Register baseReg = base == Value.ILLEGAL ? Register.None : asRegister(base); + return new PTXAddress((Variable) base, displacement); } @Override diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXArithmetic.java --- a/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXArithmetic.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXArithmetic.java Wed Oct 02 13:26:31 2013 +0200 @@ -22,7 +22,9 @@ */ package com.oracle.graal.lir.ptx; +import static com.oracle.graal.asm.ptx.PTXAssembler.*; import static com.oracle.graal.api.code.ValueUtil.*; +import static com.oracle.graal.lir.LIRValueUtil.*; import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; import com.oracle.graal.api.meta.*; @@ -61,7 +63,22 @@ @Override public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) { - PTXMove.move(tasm, masm, result, x); + switch (opcode) { + case I2L: + case I2C: + case I2B: + case I2F: + case I2D: + case F2I: + case F2L: + case F2D: + case D2I: + case D2L: + case D2F: + break; // cvt handles the move + default: + PTXMove.move(tasm, masm, result, x); + } emit(tasm, masm, opcode, result, x, null); } } @@ -255,9 +272,15 @@ protected static void emit(@SuppressWarnings("unused") TargetMethodAssembler tasm, PTXAssembler masm, PTXArithmetic opcode, Value result) { + + Variable var = (Variable) result; switch (opcode) { - case L2I: masm.and_b32(asIntReg(result), asIntReg(result), 0xFFFFFFFF); break; - case I2C: masm.and_b16(asIntReg(result), asIntReg(result), (short) 0xFFFF); break; + case L2I: + new And(var, var, Constant.forLong(0xFFFFFFFF)).emit(masm); + break; + case I2C: + new And(var, var, Constant.forInt((short) 0xFFFF)).emit(masm); + break; default: throw GraalInternalError.shouldNotReachHere("missing: " + opcode); } @@ -265,74 +288,60 @@ public static void emit(TargetMethodAssembler tasm, PTXAssembler masm, PTXArithmetic opcode, Value dst, Value src, LIRFrameState info) { int exceptionOffset = -1; - if (isRegister(src)) { + Variable dest = (Variable) dst; + + if (isVariable(src)) { + Variable source = (Variable) src; switch (opcode) { case INEG: - masm.neg_s32(asIntReg(dst), asIntReg(src)); + case FNEG: + case DNEG: + new Neg(dest, source).emit(masm); break; case INOT: - masm.not_s32(asIntReg(dst), asIntReg(src)); - break; case LNOT: - masm.not_s64(asLongReg(dst), asLongReg(src)); + new Not(dest, source).emit(masm); break; case I2L: - masm.cvt_s64_s32(asLongReg(dst), asIntReg(src)); - break; case I2C: - masm.cvt_b16_s32(asIntReg(dst), asIntReg(src)); - break; case I2B: - masm.cvt_s8_s32(asIntReg(dst), asIntReg(src)); - break; case I2F: - masm.cvt_f32_s32(asFloatReg(dst), asIntReg(src)); - break; case I2D: - masm.cvt_f64_s32(asDoubleReg(dst), asIntReg(src)); - break; - case FNEG: - masm.neg_f32(asFloatReg(dst), asFloatReg(src)); - break; - case DNEG: - masm.neg_f64(asDoubleReg(dst), asDoubleReg(src)); - break; case F2I: - masm.cvt_s32_f32(asIntReg(dst), asFloatReg(src)); - break; case F2L: - masm.cvt_s64_f32(asLongReg(dst), asFloatReg(src)); - break; case F2D: - masm.cvt_f64_f32(asDoubleReg(dst), asFloatReg(src)); - break; case D2I: - masm.cvt_s32_f64(asIntReg(dst), asDoubleReg(src)); - break; case D2L: - masm.cvt_s64_f64(asLongReg(dst), asDoubleReg(src)); - break; case D2F: - masm.cvt_f32_f64(asFloatReg(dst), asDoubleReg(src)); + new Cvt(dest, source).emit(masm); break; case LSHL: - masm.shl_b64(asLongReg(dst), asLongReg(dst), asIntReg(src)); + new Shl(dest, dest, src).emit(masm); break; case LSHR: - masm.shr_s64(asLongReg(dst), asLongReg(dst), asIntReg(src)); + new Shr(dest, dest, src).emit(masm); break; default: throw GraalInternalError.shouldNotReachHere("missing: " + opcode); } } else if (isConstant(src)) { switch (opcode) { - case ISUB: masm.sub_s32(asIntReg(dst), asIntReg(dst), tasm.asIntConst(src)); break; - case IAND: masm.and_b32(asIntReg(dst), asIntReg(dst), tasm.asIntConst(src)); break; - default: throw GraalInternalError.shouldNotReachHere(); + case ISUB: + new Sub(dest, dest, src).emit(masm); + break; + case IAND: + new And(dest, dest, src).emit(masm); + break; + case LSHL: + new Shl(dest, dest, src).emit(masm); + break; + default: + throw GraalInternalError.shouldNotReachHere(); } } else { switch (opcode) { - default: throw GraalInternalError.shouldNotReachHere(); + default: + throw GraalInternalError.shouldNotReachHere(); } } @@ -342,84 +351,68 @@ } } - public static void emit(TargetMethodAssembler tasm, PTXAssembler masm, PTXArithmetic opcode, Value dst, Value src1, Value src2, LIRFrameState info) { + public static void emit(TargetMethodAssembler tasm, PTXAssembler masm, PTXArithmetic opcode, + Value dst, Value src1, Value src2, LIRFrameState info) { int exceptionOffset = -1; - if (isConstant(src1)) { - switch (opcode) { - case ISUB: masm.sub_s32(asIntReg(dst), tasm.asIntConst(src1), asIntReg(src2)); break; - case IAND: masm.and_b32(asIntReg(dst), asIntReg(src2), tasm.asIntConst(src1)); break; - case IDIV: masm.div_s32(asIntReg(dst), tasm.asIntConst(src1), asIntReg(src2)); break; - case FSUB: masm.sub_f32(asFloatReg(dst), tasm.asFloatConst(src1), asFloatReg(src2)); break; - case FDIV: masm.div_f32(asFloatReg(dst), tasm.asFloatConst(src1), asFloatReg(src2)); break; - case DSUB: masm.sub_f64(asDoubleReg(dst), tasm.asDoubleConst(src1), asDoubleReg(src2)); break; - case DDIV: masm.div_f64(asDoubleReg(dst), tasm.asDoubleConst(src1), asDoubleReg(src2)); break; - default: - throw GraalInternalError.shouldNotReachHere(); - } - } else if (isConstant(src2)) { - switch (opcode) { - case IADD: masm.add_s32(asIntReg(dst), asIntReg(src1), tasm.asIntConst(src2)); break; - case ISUB: masm.sub_s32(asIntReg(dst), asIntReg(src1), tasm.asIntConst(src2)); break; - case IMUL: masm.mul_lo_s32(asIntReg(dst), asIntReg(src1), tasm.asIntConst(src2)); break; - case IAND: masm.and_b32(asIntReg(dst), asIntReg(src1), tasm.asIntConst(src2)); break; - case ISHL: masm.shl_b32_const(asIntReg(dst), asIntReg(src1), tasm.asIntConst(src2)); break; - case ISHR: masm.shr_s32(asIntReg(dst), asIntReg(src1), tasm.asIntConst(src2)); break; - case IUSHR: masm.shr_u32(asIntReg(dst), asIntReg(src1), tasm.asIntConst(src2)); break; - case IXOR: masm.xor_b32(asIntReg(dst), asIntReg(src1), tasm.asIntConst(src2)); break; - case LXOR: masm.xor_b64(asLongReg(dst), asLongReg(src1), tasm.asLongConst(src2)); break; - case LUSHR: masm.shr_u64(asLongReg(dst), asLongReg(src1), tasm.asLongConst(src2)); break; - case FADD: masm.add_f32(asFloatReg(dst), asFloatReg(src1), tasm.asFloatConst(src2)); break; - case FMUL: masm.mul_lo_f32(asFloatReg(dst), asFloatReg(src1), tasm.asFloatConst(src2)); break; - case FDIV: masm.div_f32(asFloatReg(dst), asFloatReg(src1), tasm.asFloatConst(src2)); break; - case DADD: masm.add_f64(asDoubleReg(dst), asDoubleReg(src1), tasm.asDoubleConst(src2)); break; - case DMUL: masm.mul_lo_f64(asDoubleReg(dst), asDoubleReg(src1), tasm.asDoubleConst(src2)); break; - case DDIV: masm.div_f64(asDoubleReg(dst), asDoubleReg(src1), tasm.asDoubleConst(src2)); break; - default: - throw GraalInternalError.shouldNotReachHere(); - } - } else { - switch (opcode) { - // case A: new Add(Int, dst, src1, src2); - // case S: new Sub(Int, dst, src1, src2); - // case U: new Shl(UnsignedInt, dst, src1, src2); - // case L: new Shl(UnsignedLong, dst, src1, src2); - // case F: new Add(Float, dst, src1, src2); - // case D: new Mul(Double, dst, src1, src2); - case IADD: masm.add_s32(asIntReg(dst), asIntReg(src1), asIntReg(src2)); break; - case ISUB: masm.sub_s32(asIntReg(dst), asIntReg(src1), asIntReg(src2)); break; - case IMUL: masm.mul_lo_s32(asIntReg(dst), asIntReg(src1), asIntReg(src2)); break; - case IDIV: masm.div_s32(asIntReg(dst), asIntReg(src1), asIntReg(src2)); break; - case IAND: masm.and_b32(asIntReg(dst), asIntReg(src1), asIntReg(src2)); break; - case IOR: masm.or_b32(asIntReg(dst), asIntReg(src1), asIntReg(src2)); break; - case IXOR: masm.xor_b32(asIntReg(dst), asIntReg(src1), asIntReg(src2)); break; - case ISHL: masm.shl_b32(asIntReg(dst), asIntReg(src1), asIntReg(src2)); break; - case ISHR: masm.shr_s32(asIntReg(dst), asIntReg(src1), asIntReg(src2)); break; - case IUSHR: masm.shr_u32(asIntReg(dst), asIntReg(src1), asIntReg(src2)); break; - case IREM: masm.rem_s32(asIntReg(dst), asIntReg(src1), asIntReg(src2)); break; - case LADD: masm.add_s64(asLongReg(dst), asLongReg(src1), asLongReg(src2)); break; - case LSUB: masm.sub_s64(asLongReg(dst), asLongReg(src1), asLongReg(src2)); break; - case LMUL: masm.mul_lo_s64(asLongReg(dst), asLongReg(src1), asLongReg(src2)); break; - case LDIV: masm.div_s64(asLongReg(dst), asLongReg(src1), asLongReg(src2)); break; - case LAND: masm.and_b64(asLongReg(dst), asLongReg(src1), asLongReg(src2)); break; - case LOR: masm.or_b64(asLongReg(dst), asLongReg(src1), asLongReg(src2)); break; - case LXOR: masm.xor_b64(asLongReg(dst), asLongReg(src1), asLongReg(src2)); break; - case LSHL: masm.shl_b64(asLongReg(dst), asLongReg(src1), asLongReg(src2)); break; - case LSHR: masm.shr_s64(asLongReg(dst), asLongReg(src1), asLongReg(src2)); break; - case LUSHR: masm.shr_u64(asLongReg(dst), asLongReg(src1), asIntReg(src2)); break; - case LREM: masm.rem_s64(asLongReg(dst), asLongReg(src1), asLongReg(src2)); break; - case FADD: masm.add_f32(asFloatReg(dst), asFloatReg(src1), asFloatReg(src2)); break; - case FSUB: masm.sub_f32(asFloatReg(dst), asFloatReg(src1), asFloatReg(src2)); break; - case FMUL: masm.mul_lo_f32(asFloatReg(dst), asFloatReg(src1), asFloatReg(src2)); break; - case FDIV: masm.div_f32(asFloatReg(dst), asFloatReg(src1), asFloatReg(src2)); break; - case FREM: masm.div_f32(asFloatReg(dst), asFloatReg(src1), asFloatReg(src2)); break; - case DADD: masm.add_f64(asDoubleReg(dst), asDoubleReg(src1), asDoubleReg(src2)); break; - case DSUB: masm.sub_f64(asDoubleReg(dst), asDoubleReg(src1), asDoubleReg(src2)); break; - case DMUL: masm.mul_lo_f64(asDoubleReg(dst), asDoubleReg(src1), asDoubleReg(src2)); break; - case DDIV: masm.div_f64(asDoubleReg(dst), asDoubleReg(src1), asDoubleReg(src2)); break; - case DREM: masm.div_f64(asDoubleReg(dst), asDoubleReg(src1), asDoubleReg(src2)); break; + Variable dest = (Variable) dst; + + switch (opcode) { + case IADD: + case LADD: + case FADD: + case DADD: + new Add(dest, src1, src2).emit(masm); + break; + case IAND: + case LAND: + new And(dest, src1, src2).emit(masm); + break; + case ISUB: + case LSUB: + case FSUB: + case DSUB: + new Sub(dest, src1, src2).emit(masm); + break; + case IMUL: + case LMUL: + case FMUL: + case DMUL: + new Mul(dest, src1, src2).emit(masm); + break; + case IDIV: + case LDIV: + case FDIV: + case DDIV: + new Div(dest, src1, src2).emit(masm); + break; + case IOR: + case LOR: + new Or(dest, src1, src2).emit(masm); + break; + case IXOR: + case LXOR: + new Xor(dest, src1, src2).emit(masm); + break; + case ISHL: + case LSHL: + new Shl(dest, src1, src2).emit(masm); + break; + case ISHR: + case LSHR: + new Shr(dest, src1, src2).emit(masm); + break; + case IUSHR: + case LUSHR: + new Ushr(dest, src1, src2).emit(masm); + break; + case IREM: + case LREM: + case FREM: + case DREM: + new Rem(dest, src1, src2).emit(masm); + break; default: throw GraalInternalError.shouldNotReachHere("missing: " + opcode); - } } if (info != null) { @@ -429,11 +422,73 @@ } private static void verifyKind(PTXArithmetic opcode, Value result, Value x, Value y) { - if (((opcode.name().startsWith("I") && result.getKind() == Kind.Int && x.getKind().getStackKind() == Kind.Int && y.getKind().getStackKind() == Kind.Int) - || (opcode.name().startsWith("L") && result.getKind() == Kind.Long && x.getKind() == Kind.Long && y.getKind() == Kind.Long) - || (opcode.name().startsWith("F") && result.getKind() == Kind.Float && x.getKind() == Kind.Float && y.getKind() == Kind.Float) - || (opcode.name().startsWith("D") && result.getKind() == Kind.Double && x.getKind() == Kind.Double && y.getKind() == Kind.Double)) == false) { - throw GraalInternalError.shouldNotReachHere("opcode: " + opcode.name() + " x: " + x.getKind() + " y: " + y.getKind()); + Kind rk; + Kind xk; + Kind yk; + Kind xsk; + Kind ysk; + + switch (opcode) { + case IADD: + case ISUB: + case IMUL: + case IDIV: + case IREM: + case IAND: + case IOR: + case IXOR: + case ISHL: + case ISHR: + case IUSHR: + rk = result.getKind(); + xsk = x.getKind().getStackKind(); + ysk = y.getKind().getStackKind(); + assert rk == Kind.Int && xsk == Kind.Int && ysk == Kind.Int; + break; + case LADD: + case LSUB: + case LMUL: + case LDIV: + case LREM: + case LAND: + case LOR: + case LXOR: + rk = result.getKind(); + xk = x.getKind(); + yk = y.getKind(); + assert rk == Kind.Long && xk == Kind.Long && yk == Kind.Long; + break; + case LSHL: + case LSHR: + case LUSHR: + rk = result.getKind(); + xk = x.getKind(); + yk = y.getKind(); + assert rk == Kind.Long && xk == Kind.Long && (yk == Kind.Int || yk == Kind.Long); + break; + case FADD: + case FSUB: + case FMUL: + case FDIV: + case FREM: + rk = result.getKind(); + xk = x.getKind(); + yk = y.getKind(); + assert rk == Kind.Float && xk == Kind.Float && yk == Kind.Float; + break; + case DADD: + case DSUB: + case DMUL: + case DDIV: + case DREM: + rk = result.getKind(); + xk = x.getKind(); + yk = y.getKind(); + assert rk == Kind.Double && xk == Kind.Double && yk == Kind.Double : + "opcode=" + opcode + ", result kind=" + rk + ", x kind=" + xk + ", y kind=" + yk; + break; + default: + throw GraalInternalError.shouldNotReachHere("missing: " + opcode); } } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXCompare.java --- a/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXCompare.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXCompare.java Wed Oct 02 13:26:31 2013 +0200 @@ -22,10 +22,10 @@ */ package com.oracle.graal.lir.ptx; +import static com.oracle.graal.asm.ptx.PTXAssembler.*; import static com.oracle.graal.api.code.ValueUtil.*; import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; -import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.ptx.*; import com.oracle.graal.graph.*; @@ -41,18 +41,21 @@ @Opcode private final PTXCompare opcode; @Use({REG, STACK, CONST}) protected Value x; @Use({REG, STACK, CONST}) protected Value y; + // Number of predicate register that would be set by this instruction. + protected int predRegNum; private final Condition condition; - public CompareOp(PTXCompare opcode, Condition condition, Value x, Value y) { + public CompareOp(PTXCompare opcode, Condition condition, Value x, Value y, int predReg) { this.opcode = opcode; this.condition = condition; this.x = x; this.y = y; + predRegNum = predReg; } @Override public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) { - emit(tasm, masm, opcode, condition, x, y); + emit(masm, opcode, condition, x, y, predRegNum); } @Override @@ -64,40 +67,18 @@ } } - public static void emit(TargetMethodAssembler tasm, PTXAssembler masm, PTXCompare opcode, Condition condition, Value x, Value y) { + public static void emit(PTXAssembler masm, PTXCompare opcode, + Condition condition, Value x, Value y, int p) { if (isConstant(x)) { + new Setp(condition, x, y, p).emit(masm); + } else if (isConstant(y)) { switch (opcode) { case ICMP: - emitCompareConstReg(masm, condition, tasm.asIntConst(x), asIntReg(y)); - break; - case FCMP: - emitCompareConstReg(masm, condition, tasm.asFloatConst(x), asFloatReg(y)); - break; - case DCMP: - emitCompareConstReg(masm, condition, tasm.asDoubleConst(x), asDoubleReg(y)); - break; - default: - throw GraalInternalError.shouldNotReachHere(); - } - } else if (isConstant(y)) { - Register a = asIntReg(x); - int b = tasm.asIntConst(y); - switch (opcode) { - case ICMP: - emitCompareRegConst(masm, condition, a, b); + new Setp(condition, x, y, p).emit(masm); break; case ACMP: if (((Constant) y).isNull()) { - switch (condition) { - case EQ: - masm.setp_eq_s32(a, b); - break; - case NE: - masm.setp_ne_s32(a, b); - break; - default: - throw GraalInternalError.shouldNotReachHere(); - } + new Setp(condition, x, y, p).emit(masm); } else { throw GraalInternalError.shouldNotReachHere("Only null object constants are allowed in comparisons"); } @@ -106,183 +87,8 @@ throw GraalInternalError.shouldNotReachHere(); } } else { - switch (opcode) { - case ICMP: - emitCompareRegReg(masm, condition, asIntReg(x), asIntReg(y)); - break; - case LCMP: - emitCompareRegReg(masm, condition, asLongReg(x), asLongReg(y)); - break; - case FCMP: - emitCompareRegReg(masm, condition, asFloatReg(x), asFloatReg(y)); - break; - case DCMP: - emitCompareRegReg(masm, condition, asDoubleReg(x), asDoubleReg(y)); - break; - default: - throw GraalInternalError.shouldNotReachHere("missing: " + opcode); - } - } - } - - private static void emitCompareConstReg(PTXAssembler masm, Condition condition, float a, Register b) { - switch (condition) { - case EQ: - masm.setp_eq_f32(a, b); - break; - case NE: - masm.setp_ne_f32(a, b); - break; - case LT: - masm.setp_lt_f32(a, b); - break; - case LE: - masm.setp_le_f32(a, b); - break; - case GT: - masm.setp_gt_f32(a, b); - break; - case GE: - masm.setp_ge_f32(a, b); - break; - default: - throw GraalInternalError.shouldNotReachHere(); - } - } - - private static void emitCompareConstReg(PTXAssembler masm, Condition condition, double a, Register b) { - switch (condition) { - case EQ: - masm.setp_eq_f64(a, b); - break; - case NE: - masm.setp_ne_f64(a, b); - break; - case LT: - masm.setp_lt_f64(a, b); - break; - case LE: - masm.setp_le_f64(a, b); - break; - case GT: - masm.setp_gt_f64(a, b); - break; - case GE: - masm.setp_ge_f64(a, b); - break; - default: - throw GraalInternalError.shouldNotReachHere(); + new Setp(condition, x, y, p).emit(masm); } } - private static void emitCompareConstReg(PTXAssembler masm, Condition condition, int a, Register b) { - switch (condition) { - case EQ: - masm.setp_eq_s32(a, b); - break; - case NE: - masm.setp_ne_s32(a, b); - break; - case LT: - masm.setp_lt_s32(a, b); - break; - case LE: - masm.setp_le_s32(a, b); - break; - case GT: - masm.setp_gt_s32(a, b); - break; - case GE: - masm.setp_ge_s32(a, b); - break; - case AT: - masm.setp_gt_u32(a, b); - break; - case AE: - masm.setp_ge_u32(a, b); - break; - case BT: - masm.setp_lt_u32(a, b); - break; - case BE: - masm.setp_le_u32(a, b); - break; - default: - throw GraalInternalError.shouldNotReachHere(); - } - } - - private static void emitCompareRegConst(PTXAssembler masm, Condition condition, Register a, int b) { - switch (condition) { - case EQ: - masm.setp_eq_s32(a, b); - break; - case NE: - masm.setp_ne_s32(a, b); - break; - case LT: - masm.setp_lt_s32(a, b); - break; - case LE: - masm.setp_le_s32(a, b); - break; - case GT: - masm.setp_gt_s32(a, b); - break; - case GE: - masm.setp_ge_s32(a, b); - break; - case AT: - masm.setp_gt_u32(a, b); - break; - case AE: - masm.setp_ge_u32(a, b); - break; - case BT: - masm.setp_lt_u32(a, b); - break; - case BE: - masm.setp_le_u32(a, b); - break; - default: - throw GraalInternalError.shouldNotReachHere(); - } - } - - private static void emitCompareRegReg(PTXAssembler masm, Condition condition, Register a, Register b) { - switch (condition) { - case EQ: - masm.setp_eq_s32(a, b); - break; - case NE: - masm.setp_ne_s32(a, b); - break; - case LT: - masm.setp_lt_s32(a, b); - break; - case LE: - masm.setp_le_s32(a, b); - break; - case GT: - masm.setp_gt_s32(a, b); - break; - case GE: - masm.setp_ge_s32(a, b); - break; - case AT: - masm.setp_gt_u32(a, b); - break; - case AE: - masm.setp_ge_u32(a, b); - break; - case BT: - masm.setp_lt_u32(a, b); - break; - case BE: - masm.setp_le_u32(a, b); - break; - default: - throw GraalInternalError.shouldNotReachHere(); - } - } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXControlFlow.java --- a/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXControlFlow.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXControlFlow.java Wed Oct 02 13:26:31 2013 +0200 @@ -22,11 +22,11 @@ */ package com.oracle.graal.lir.ptx; -import static com.oracle.graal.api.code.ValueUtil.*; +import static com.oracle.graal.asm.ptx.PTXAssembler.*; import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; +import static com.oracle.graal.nodes.calc.Condition.*; import com.oracle.graal.api.code.CompilationResult.JumpTable; -import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.*; import com.oracle.graal.asm.ptx.*; @@ -72,16 +72,17 @@ protected Condition condition; protected LabelRef destination; + protected int predRegNum; - public BranchOp(Condition condition, LabelRef destination) { + public BranchOp(Condition condition, LabelRef destination, int predReg) { this.condition = condition; this.destination = destination; + this.predRegNum = predReg; } @Override public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) { - masm.at(); - masm.bra(masm.nameOf(destination.label())); + masm.bra(masm.nameOf(destination.label()), predRegNum); } @Override @@ -151,45 +152,36 @@ private LabelRef defaultTarget; @Alive({REG}) protected Value key; @Temp({REG, ILLEGAL}) protected Value scratch; + // Number of predicate register that would be set by this instruction. + protected int predRegNum; - public SequentialSwitchOp(Constant[] keyConstants, LabelRef[] keyTargets, LabelRef defaultTarget, Value key, Value scratch) { + public SequentialSwitchOp(Constant[] keyConstants, LabelRef[] keyTargets, LabelRef defaultTarget, Value key, Value scratch, int predReg) { assert keyConstants.length == keyTargets.length; this.keyConstants = keyConstants; this.keyTargets = keyTargets; this.defaultTarget = defaultTarget; this.key = key; this.scratch = scratch; + predRegNum = predReg; } @Override public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) { - if (key.getKind() == Kind.Int) { - Register intKey = asIntReg(key); + Kind keyKind = key.getKind(); + + if (keyKind == Kind.Int || keyKind == Kind.Long) { for (int i = 0; i < keyConstants.length; i++) { if (tasm.runtime.needsDataPatch(keyConstants[i])) { tasm.recordDataReferenceInCode(keyConstants[i], 0, true); } - long lc = keyConstants[i].asLong(); - assert NumUtil.isInt(lc); - masm.setp_eq_s32((int) lc, intKey); - masm.at(); - masm.bra(masm.nameOf(keyTargets[i].label())); + new Setp(EQ, keyConstants[i], key, predRegNum).emit(masm); + masm.bra(masm.nameOf(keyTargets[i].label()), predRegNum); } - } else if (key.getKind() == Kind.Long) { - Register longKey = asLongReg(key); + } else if (keyKind == Kind.Object) { for (int i = 0; i < keyConstants.length; i++) { - masm.setp_eq_s64(tasm.asLongConst(keyConstants[i]), longKey); - masm.at(); - masm.bra(masm.nameOf(keyTargets[i].label())); - } - } else if (key.getKind() == Kind.Object) { - Register intKey = asObjectReg(key); - Register temp = asObjectReg(scratch); - for (int i = 0; i < keyConstants.length; i++) { - PTXMove.move(tasm, masm, temp.asValue(Kind.Object), keyConstants[i]); - masm.setp_eq_u32(intKey, temp); - masm.at(); - masm.bra(keyTargets[i].label().toString()); + PTXMove.move(tasm, masm, scratch, keyConstants[i]); + new Setp(EQ, keyConstants[i], scratch, predRegNum).emit(masm); + masm.bra(keyTargets[i].label().toString(), predRegNum); } } else { throw new GraalInternalError("sequential switch only supported for int, long and object"); @@ -219,38 +211,40 @@ private final LabelRef[] targets; @Alive protected Value index; @Temp protected Value scratch; + // Number of predicate register that would be set by this instruction. + protected int predRegNum; - public TableSwitchOp(final int lowKey, final LabelRef defaultTarget, final LabelRef[] targets, Variable index, Variable scratch) { + public TableSwitchOp(final int lowKey, final LabelRef defaultTarget, final LabelRef[] targets, Variable index, Variable scratch, int predReg) { this.lowKey = lowKey; this.defaultTarget = defaultTarget; this.targets = targets; this.index = index; this.scratch = scratch; + predRegNum = predReg; } @Override public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) { - tableswitch(tasm, masm, lowKey, defaultTarget, targets, asIntReg(index), asLongReg(scratch)); + tableswitch(tasm, masm, lowKey, defaultTarget, targets, index, scratch, predRegNum); } } @SuppressWarnings("unused") - private static void tableswitch(TargetMethodAssembler tasm, PTXAssembler masm, int lowKey, LabelRef defaultTarget, LabelRef[] targets, Register value, Register scratch) { + private static void tableswitch(TargetMethodAssembler tasm, PTXAssembler masm, int lowKey, LabelRef defaultTarget, LabelRef[] targets, Value value, Value scratch, int predNum) { Buffer buf = masm.codeBuffer; // Compare index against jump table bounds int highKey = lowKey + targets.length - 1; if (lowKey != 0) { // subtract the low value from the switch value - masm.sub_s32(value, value, lowKey); - masm.setp_gt_s32(value, highKey - lowKey); + // new Sub(value, value, lowKey).emit(masm); + new Setp(GT, value, Constant.forInt(highKey - lowKey), predNum).emit(masm); } else { - masm.setp_gt_s32(value, highKey); + new Setp(GT, value, Constant.forInt(highKey), predNum).emit(masm); } // Jump to default target if index is not within the jump table if (defaultTarget != null) { - masm.at(); - masm.bra(defaultTarget.label().toString()); + masm.bra(defaultTarget.label().toString(), predNum); } // address of jump table diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXMemOp.java --- a/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXMemOp.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXMemOp.java Wed Oct 02 13:26:31 2013 +0200 @@ -22,7 +22,8 @@ */ package com.oracle.graal.lir.ptx; -import static com.oracle.graal.api.code.ValueUtil.*; +import static com.oracle.graal.asm.ptx.PTXAssembler.*; +import static com.oracle.graal.asm.ptx.PTXStateSpace.*; import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; import com.oracle.graal.api.meta.*; @@ -34,15 +35,15 @@ public class PTXMemOp { // Load operation from .global state space - @Opcode("LOAD") + @Opcode("LOAD_REGBASE_DISP") public static class LoadOp extends PTXLIRInstruction { private final Kind kind; - @Def({REG}) protected AllocatableValue result; + @Def({REG}) protected Variable result; @Use({COMPOSITE}) protected PTXAddressValue address; @State protected LIRFrameState state; - public LoadOp(Kind kind, AllocatableValue result, PTXAddressValue address, LIRFrameState state) { + public LoadOp(Kind kind, Variable result, PTXAddressValue address, LIRFrameState state) { this.kind = kind; this.result = result; this.address = address; @@ -54,28 +55,14 @@ PTXAddress addr = address.toAddress(); switch (kind) { case Byte: - masm.ld_global_s8(asRegister(result), addr.getBase(), addr.getDisplacement()); - break; case Short: - masm.ld_global_s16(asRegister(result), addr.getBase(), addr.getDisplacement()); - break; case Char: - masm.ld_global_u16(asRegister(result), addr.getBase(), addr.getDisplacement()); - break; case Int: - masm.ld_global_s32(asRegister(result), addr.getBase(), addr.getDisplacement()); - break; case Long: - masm.ld_global_s64(asRegister(result), addr.getBase(), addr.getDisplacement()); - break; case Float: - masm.ld_global_f32(asRegister(result), addr.getBase(), addr.getDisplacement()); - break; case Double: - masm.ld_global_f64(asRegister(result), addr.getBase(), addr.getDisplacement()); - break; case Object: - masm.ld_global_u32(asRegister(result), addr.getBase(), addr.getDisplacement()); + new Ld(Global, result, addr.getBase(), Constant.forLong(addr.getDisplacement())).emit(masm); break; default: throw GraalInternalError.shouldNotReachHere(); @@ -89,10 +76,10 @@ private final Kind kind; @Use({COMPOSITE}) protected PTXAddressValue address; - @Use({REG}) protected AllocatableValue input; + @Use({REG}) protected Variable input; @State protected LIRFrameState state; - public StoreOp(Kind kind, PTXAddressValue address, AllocatableValue input, LIRFrameState state) { + public StoreOp(Kind kind, PTXAddressValue address, Variable input, LIRFrameState state) { this.kind = kind; this.address = address; this.input = input; @@ -101,29 +88,16 @@ @Override public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) { - assert isRegister(input); PTXAddress addr = address.toAddress(); switch (kind) { case Byte: - masm.st_global_s8(addr.getBase(), addr.getDisplacement(), asRegister(input)); - break; case Short: - masm.st_global_s8(addr.getBase(), addr.getDisplacement(), asRegister(input)); - break; case Int: - masm.st_global_s32(addr.getBase(), addr.getDisplacement(), asRegister(input)); - break; case Long: - masm.st_global_s64(addr.getBase(), addr.getDisplacement(), asRegister(input)); - break; case Float: - masm.st_global_f32(addr.getBase(), addr.getDisplacement(), asRegister(input)); - break; case Double: - masm.st_global_f64(addr.getBase(), addr.getDisplacement(), asRegister(input)); - break; case Object: - masm.st_global_u64(addr.getBase(), addr.getDisplacement(), asRegister(input)); + new St(Global, input, addr.getBase(), Constant.forLong(addr.getDisplacement())).emit(masm); break; default: throw GraalInternalError.shouldNotReachHere("missing: " + address.getKind()); @@ -132,15 +106,15 @@ } // Load operation from .param state space - @Opcode("LOAD") + @Opcode("LOAD_PARAM") public static class LoadParamOp extends PTXLIRInstruction { private final Kind kind; - @Def({REG}) protected AllocatableValue result; + @Def({REG}) protected Variable result; @Use({COMPOSITE}) protected PTXAddressValue address; @State protected LIRFrameState state; - public LoadParamOp(Kind kind, AllocatableValue result, PTXAddressValue address, LIRFrameState state) { + public LoadParamOp(Kind kind, Variable result, PTXAddressValue address, LIRFrameState state) { this.kind = kind; this.result = result; this.address = address; @@ -152,28 +126,14 @@ PTXAddress addr = address.toAddress(); switch (kind) { case Byte: - masm.ld_from_state_space(".param.s8", asRegister(result), addr.getBase(), addr.getDisplacement()); - break; case Short: - masm.ld_from_state_space(".param.s16", asRegister(result), addr.getBase(), addr.getDisplacement()); - break; case Char: - masm.ld_from_state_space(".param.u16", asRegister(result), addr.getBase(), addr.getDisplacement()); - break; case Int: - masm.ld_from_state_space(".param.s32", asRegister(result), addr.getBase(), addr.getDisplacement()); - break; case Long: - masm.ld_from_state_space(".param.s64", asRegister(result), addr.getBase(), addr.getDisplacement()); - break; case Float: - masm.ld_from_state_space(".param.f32", asRegister(result), addr.getBase(), addr.getDisplacement()); - break; case Double: - masm.ld_from_state_space(".param.f64", asRegister(result), addr.getBase(), addr.getDisplacement()); - break; case Object: - masm.ld_from_state_space(".param.u64", asRegister(result), addr.getBase(), addr.getDisplacement()); + new Ld(Parameter, result, addr.getBase(), Constant.forLong(addr.getDisplacement())).emit(masm); break; default: throw GraalInternalError.shouldNotReachHere(); @@ -187,11 +147,11 @@ public static class LoadReturnAddrOp extends PTXLIRInstruction { private final Kind kind; - @Def({REG}) protected AllocatableValue result; + @Def({REG}) protected Variable result; @Use({COMPOSITE}) protected PTXAddressValue address; @State protected LIRFrameState state; - public LoadReturnAddrOp(Kind kind, AllocatableValue result, PTXAddressValue address, LIRFrameState state) { + public LoadReturnAddrOp(Kind kind, Variable result, PTXAddressValue address, LIRFrameState state) { this.kind = kind; this.result = result; this.address = address; @@ -203,10 +163,10 @@ PTXAddress addr = address.toAddress(); switch (kind) { case Int: - masm.ld_return_address("u32", asRegister(result), addr.getBase(), addr.getDisplacement()); - break; case Long: - masm.ld_return_address("u64", asRegister(result), addr.getBase(), addr.getDisplacement()); + case Float: + case Double: + new Ld(Parameter, result, addr.getBase(), Constant.forLong(addr.getDisplacement())).emit(masm); break; default: throw GraalInternalError.shouldNotReachHere(); @@ -220,10 +180,10 @@ private final Kind kind; @Use({COMPOSITE}) protected PTXAddressValue address; - @Use({REG}) protected AllocatableValue input; + @Use({REG}) protected Variable input; @State protected LIRFrameState state; - public StoreReturnValOp(Kind kind, PTXAddressValue address, AllocatableValue input, LIRFrameState state) { + public StoreReturnValOp(Kind kind, PTXAddressValue address, Variable input, LIRFrameState state) { this.kind = kind; this.address = address; this.input = input; @@ -232,29 +192,17 @@ @Override public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) { - assert isRegister(input); PTXAddress addr = address.toAddress(); - // masm.st_global_return_value_s64(addr.getBase(), addr.getDisplacement(), asRegister(input)); switch (kind) { case Byte: case Short: - masm.st_global_return_value_s8(addr.getBase(), addr.getDisplacement(), asRegister(input)); - break; case Int: - masm.st_global_return_value_s32(addr.getBase(), addr.getDisplacement(), asRegister(input)); - break; case Long: - masm.st_global_return_value_s64(addr.getBase(), addr.getDisplacement(), asRegister(input)); - break; case Float: - masm.st_global_return_value_f32(addr.getBase(), addr.getDisplacement(), asRegister(input)); - break; case Double: - masm.st_global_return_value_f64(addr.getBase(), addr.getDisplacement(), asRegister(input)); - break; case Object: - masm.st_global_return_value_u64(addr.getBase(), addr.getDisplacement(), asRegister(input)); + new St(Global, input, addr.getBase(), Constant.forLong(addr.getDisplacement())).emit(masm); break; default: throw GraalInternalError.shouldNotReachHere("missing: " + address.getKind()); diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXMove.java --- a/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXMove.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXMove.java Wed Oct 02 13:26:31 2013 +0200 @@ -22,7 +22,9 @@ */ package com.oracle.graal.lir.ptx; +import static com.oracle.graal.asm.ptx.PTXAssembler.*; import static com.oracle.graal.api.code.ValueUtil.*; +import static com.oracle.graal.lir.LIRValueUtil.*; import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; import com.oracle.graal.api.code.*; @@ -170,14 +172,14 @@ } public static void move(TargetMethodAssembler tasm, PTXAssembler masm, Value result, Value input) { - if (isRegister(input)) { - if (isRegister(result)) { + if (isVariable(input)) { + if (isVariable(result)) { reg2reg(masm, result, input); } else { throw GraalInternalError.shouldNotReachHere(); } } else if (isConstant(input)) { - if (isRegister(result)) { + if (isVariable(result)) { const2reg(tasm, masm, result, (Constant) input); } else { throw GraalInternalError.shouldNotReachHere(); @@ -188,24 +190,19 @@ } private static void reg2reg(PTXAssembler masm, Value result, Value input) { - if (asRegister(input).equals(asRegister(result))) { + Variable dest = (Variable) result; + Variable source = (Variable) input; + + if (dest.index == source.index) { return; } switch (input.getKind()) { case Int: - masm.mov_s32(asRegister(result), asRegister(input)); - break; case Long: - masm.mov_s64(asRegister(result), asRegister(input)); - break; case Float: - masm.mov_f32(asRegister(result), asRegister(input)); - break; case Double: - masm.mov_f64(asRegister(result), asRegister(input)); - break; case Object: - masm.mov_u64(asRegister(result), asRegister(input)); + new Mov(dest, source).emit(masm); break; default: throw GraalInternalError.shouldNotReachHere("missing: " + input.getKind()); @@ -213,27 +210,24 @@ } private static void const2reg(TargetMethodAssembler tasm, PTXAssembler masm, Value result, Constant input) { + Variable dest = (Variable) result; + switch (input.getKind().getStackKind()) { case Int: - if (tasm.runtime.needsDataPatch(input)) { - tasm.recordDataReferenceInCode(input, 0, true); - } - masm.mov_s32(asRegister(result), input.asInt()); - break; case Long: if (tasm.runtime.needsDataPatch(input)) { tasm.recordDataReferenceInCode(input, 0, true); } - masm.mov_s64(asRegister(result), input.asLong()); + new Mov(dest, input).emit(masm); break; case Object: if (input.isNull()) { - masm.mov_u64(asRegister(result), 0x0L); + new Mov(dest, Constant.forLong(0x0L)).emit(masm); } else if (tasm.target.inlineObjects) { tasm.recordDataReferenceInCode(input, 0, true); - masm.mov_u64(asRegister(result), 0xDEADDEADDEADDEADL); + new Mov(dest, Constant.forLong(0xDEADDEADDEADDEADL)).emit(masm); } else { - masm.mov_u64(asRegister(result), tasm.recordDataReferenceInCode(input, 0, false)); + // new Mov(dest, tasm.recordDataReferenceInCode(input, 0, false)); } break; default: diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXParameterOp.java --- a/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXParameterOp.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXParameterOp.java Wed Oct 02 13:26:31 2013 +0200 @@ -23,12 +23,11 @@ package com.oracle.graal.lir.ptx; -import static com.oracle.graal.api.code.ValueUtil.*; +import static com.oracle.graal.asm.ptx.PTXAssembler.*; import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.ptx.*; -import com.oracle.graal.graph.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.asm.*; @@ -46,23 +45,7 @@ // Emit parameter directives for arguments int argCount = params.length; for (int i = 0; i < argCount; i++) { - Kind paramKind = params[i].getKind(); - switch (paramKind) { - case Int : - masm.param_32_decl(asIntReg(params[i]), (i == (argCount - 1))); - break; - case Long : - masm.param_64_decl(asLongReg(params[i]), (i == (argCount - 1))); - break; - case Float : - masm.param_32_decl(asFloatReg(params[i]), (i == (argCount - 1))); - break; - case Double : - masm.param_64_decl(asDoubleReg(params[i]), (i == (argCount - 1))); - break; - default : - throw GraalInternalError.shouldNotReachHere("unhandled parameter type " + paramKind.toString()); - } + new Param((Variable) params[i], (i == (argCount - 1))).emit(masm); } } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/ParallelOver.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/ParallelOver.java Wed Oct 02 13:26:31 2013 +0200 @@ -0,0 +1,36 @@ +/* + * 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.lir.ptx; + +import static com.oracle.graal.lir.ptx.ThreadDimension.*; + +import java.lang.annotation.*; +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.PARAMETER}) +public @interface ParallelOver { + + String value() default ""; + + ThreadDimension dimension() default X; +} + diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/ThreadDimension.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/ThreadDimension.java Wed Oct 02 13:26:31 2013 +0200 @@ -0,0 +1,30 @@ +/* + * 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.lir.ptx; + +public enum ThreadDimension { +X, +Y, +Z +} + diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/Warp.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/Warp.java Wed Oct 02 13:26:31 2013 +0200 @@ -0,0 +1,37 @@ +/* + * 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.lir.ptx; + +import static com.oracle.graal.lir.ptx.ThreadDimension.*; + +import java.lang.annotation.*; + +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.PARAMETER}) +public @interface Warp { + + String value() default ""; + + ThreadDimension dimension() default X; +} + diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCControlFlow.java --- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCControlFlow.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCControlFlow.java Wed Oct 02 13:26:31 2013 +0200 @@ -247,8 +247,12 @@ @Override public void emitCode(TargetMethodAssembler tasm, SPARCMacroAssembler masm) { + emitCodeHelper(tasm, masm); + } + + public static void emitCodeHelper(TargetMethodAssembler tasm, SPARCMacroAssembler masm) { new Ret().emit(masm); - // On SPARC we always leave the frame. + // On SPARC we always leave the frame (in the delay slot). tasm.frameContext.leave(tasm); } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.lir/src/com/oracle/graal/lir/FrameMap.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/FrameMap.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/FrameMap.java Wed Oct 02 13:26:31 2013 +0200 @@ -116,7 +116,7 @@ /** * Gets the frame size of the compiled frame, not including the size of the * {@link Architecture#getReturnAddressSize() return address slot}. - * + * * @return The size of the frame (in bytes). */ public int frameSize() { @@ -136,7 +136,7 @@ /** * Gets the total frame size of the compiled frame, including the size of the * {@link Architecture#getReturnAddressSize() return address slot}. - * + * * @return The total size of the frame (in bytes). */ public abstract int totalFrameSize(); @@ -149,7 +149,7 @@ /** * Aligns the given frame size to the stack alignment size and return the aligned size. - * + * * @param size the initial frame size to be aligned * @return the aligned frame size */ @@ -181,7 +181,7 @@ /** * Computes the offset of a stack slot relative to the frame register. - * + * * @param slot a stack slot * @return the offset of the stack slot */ @@ -197,7 +197,7 @@ /** * Computes the index of a stack slot relative to slot 0. This is also the bit index of stack * slots in the reference map. - * + * * @param slot a stack slot * @return the index of the stack slot */ @@ -209,7 +209,7 @@ /** * Gets the offset from the stack pointer to the stack area where callee-saved registers are * stored. - * + * * @return The offset to the callee save area (in bytes). */ public abstract int offsetToCalleeSaveArea(); @@ -217,7 +217,7 @@ /** * Informs the frame map that the compiled code calls a particular method, which may need stack * space for outgoing arguments. - * + * * @param cc The calling convention for the called method. */ public void callsMethod(CallingConvention cc) { @@ -226,7 +226,7 @@ /** * Reserves space for stack-based outgoing arguments. - * + * * @param argsSize The amount of space (in bytes) to reserve for stack-based outgoing arguments. */ public void reserveOutgoing(int argsSize) { @@ -239,7 +239,7 @@ * Reserves a new spill slot in the frame of the method being compiled. The returned slot is * aligned on its natural alignment, i.e., an 8-byte spill slot is aligned at an 8-byte * boundary. - * + * * @param kind The kind of the spill slot to be reserved. * @param additionalOffset * @return A spill slot denoting the reserved memory area. @@ -247,9 +247,20 @@ protected abstract StackSlot allocateNewSpillSlot(PlatformKind kind, int additionalOffset); /** + * Returns the spill slot size for the given {@link PlatformKind}. + * The default value is the size in bytes for the target architecture. + * @param kind the {@link PlatformKind} to be stored in the spill slot. + * @return the size in bytes + */ + protected int spillSlotSize(PlatformKind kind) { + return target.arch.getSizeInBytes(kind); + } + + /** * Reserves a spill slot in the frame of the method being compiled. The returned slot is aligned - * on its natural alignment, i.e., an 8-byte spill slot is aligned at an 8-byte boundary. - * + * on its natural alignment, i.e., an 8-byte spill slot is aligned at an 8-byte boundary, + * unless overridden by a subclass. + * * @param kind The kind of the spill slot to be reserved. * @return A spill slot denoting the reserved memory area. */ @@ -267,7 +278,7 @@ } } } - int size = target.arch.getSizeInBytes(kind); + int size = spillSlotSize(kind); spillSize = NumUtil.roundUp(spillSize + size, size); return allocateNewSpillSlot(kind, 0); } @@ -288,7 +299,7 @@ /** * Reserves a block of memory in the frame of the method being compiled. The returned block is * aligned on a word boundary. If the requested size is 0, the method returns {@code null}. - * + * * @param size The size to reserve (in bytes). * @param refs Specifies if the block is all references. If true, the block will be in all * reference maps for this method. The caller is responsible to initialize the memory @@ -340,7 +351,7 @@ * Marks the specified location as a reference in the reference map of the debug information. * The tracked location can be a {@link RegisterValue} or a {@link StackSlot}. Note that a * {@link Constant} is automatically tracked. - * + * * @param location The location to be added to the reference map. * @param registerRefMap A register reference map, as created by {@link #initRegisterRefMap()}. * @param frameRefMap A frame reference map, as created by {@link #initFrameRefMap()}. diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIR.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIR.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIR.java Wed Oct 02 13:26:31 2013 +0200 @@ -24,7 +24,6 @@ import java.util.*; -import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; @@ -56,6 +55,8 @@ */ private final List codeEmittingOrder; + private int firstVariableNumber; + private int numVariables; public SpillMoveFactory spillMoveFactory; @@ -69,22 +70,15 @@ private boolean hasArgInCallerFrame; - private final SpeculationLog speculationLog; - /** * Creates a new LIR instance for the specified compilation. */ - public LIR(ControlFlowGraph cfg, BlockMap> blockToNodesMap, List linearScanOrder, List codeEmittingOrder, SpeculationLog speculationLog) { + public LIR(ControlFlowGraph cfg, BlockMap> blockToNodesMap, List linearScanOrder, List codeEmittingOrder) { this.cfg = cfg; this.blockToNodesMap = blockToNodesMap; this.codeEmittingOrder = codeEmittingOrder; this.linearScanOrder = linearScanOrder; this.lirInstructions = new BlockMap<>(cfg); - this.speculationLog = speculationLog; - } - - public SpeculationLog getDeoptimizationReasons() { - return speculationLog; } /** @@ -135,7 +129,11 @@ } public int nextVariable() { - return numVariables++; + return firstVariableNumber + numVariables++; + } + + public void setFirstVariableNumber(int num) { + firstVariableNumber = num; } public void emitCode(TargetMethodAssembler tasm) { diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRFrameState.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRFrameState.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRFrameState.java Wed Oct 02 13:26:31 2013 +0200 @@ -42,13 +42,11 @@ private final VirtualObject[] virtualObjects; public final LabelRef exceptionEdge; private DebugInfo debugInfo; - private final short deoptimizationReason; - public LIRFrameState(BytecodeFrame topFrame, VirtualObject[] virtualObjects, LabelRef exceptionEdge, short deoptimizationReason) { + public LIRFrameState(BytecodeFrame topFrame, VirtualObject[] virtualObjects, LabelRef exceptionEdge) { this.topFrame = topFrame; this.virtualObjects = virtualObjects; this.exceptionEdge = exceptionEdge; - this.deoptimizationReason = deoptimizationReason; } public boolean hasDebugInfo() { @@ -112,7 +110,7 @@ } public void finish(BitSet registerRefMap, BitSet frameRefMap) { - debugInfo = new DebugInfo(topFrame, registerRefMap, frameRefMap, deoptimizationReason); + debugInfo = new DebugInfo(topFrame, registerRefMap, frameRefMap); } @Override diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRIntrospection.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRIntrospection.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRIntrospection.java Wed Oct 02 13:26:31 2013 +0200 @@ -40,6 +40,7 @@ private static final Class VALUE_CLASS = Value.class; private static final Class CONSTANT_CLASS = Constant.class; + private static final Class VARIABLE_CLASS = Variable.class; private static final Class REGISTER_VALUE_CLASS = RegisterValue.class; private static final Class STACK_SLOT_CLASS = StackSlot.class; private static final Class VALUE_ARRAY_CLASS = Value[].class; @@ -106,7 +107,8 @@ private static boolean verifyFlags(Field field, Class type, EnumSet flags) { if (flags.contains(REG)) { - assert type.isAssignableFrom(REGISTER_VALUE_CLASS) : "Cannot assign RegisterValue to field with REG flag:" + field; + assert type.isAssignableFrom(REGISTER_VALUE_CLASS) || + type.isAssignableFrom(VARIABLE_CLASS) : "Cannot assign RegisterValue / Variable to field with REG flag:" + field; } if (flags.contains(STACK)) { assert type.isAssignableFrom(STACK_SLOT_CLASS) : "Cannot assign StackSlot to field with STACK flag:" + field; diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.lir/src/com/oracle/graal/lir/Variable.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/Variable.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/Variable.java Wed Oct 02 13:26:31 2013 +0200 @@ -38,6 +38,8 @@ */ public final int index; + private String name; + /** * Creates a new variable. * @@ -50,9 +52,21 @@ this.index = index; } + public void setName(String name) { + this.name = name; + } + + public String getName() { + return name; + } + @Override public String toString() { - return "v" + index + getKindSuffix(); + if (name != null) { + return name; + } else { + return "v" + index + getKindSuffix(); + } } @Override diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.loop/src/com/oracle/graal/loop/CountedLoopInfo.java --- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/CountedLoopInfo.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/CountedLoopInfo.java Wed Oct 02 13:26:31 2013 +0200 @@ -24,7 +24,6 @@ import static com.oracle.graal.nodes.calc.IntegerArithmeticNode.*; -import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.loop.InductionVariable.Direction; diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragment.java --- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragment.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragment.java Wed Oct 02 13:26:31 2013 +0200 @@ -129,15 +129,10 @@ } }; } else { - dr = new DuplicationReplacement() { - - @Override - public Node replacement(Node o) { - return o; - } - }; + dr = null; } - duplicationMap = graph().addDuplicates(original().nodes(), dr); + NodeIterable nodesIterable = original().nodes(); + duplicationMap = graph().addDuplicates(nodesIterable, graph(), nodesIterable.count(), dr); finishDuplication(); nodesReady = true; } else { @@ -295,7 +290,7 @@ final ValueNode replaceWith; ProxyNode newVpn = getDuplicatedNode(vpn); if (newVpn != null) { - PhiNode phi = graph.add(vpn.type() == PhiType.Value ? new PhiNode(vpn.kind(), merge) : new PhiNode(vpn.type(), merge, vpn.getIdentity())); + PhiNode phi = graph.addWithoutUnique(vpn.type() == PhiType.Value ? new PhiNode(vpn.kind(), merge) : new PhiNode(vpn.type(), merge, vpn.getIdentity())); phi.addInput(vpn); phi.addInput(newVpn); replaceWith = phi; diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentInside.java --- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentInside.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentInside.java Wed Oct 02 13:26:31 2013 +0200 @@ -125,16 +125,36 @@ final StructuredGraph graph = graph(); return new DuplicationReplacement() { + private HashMap seenNode = new HashMap<>(); + @Override public Node replacement(Node original) { if (original == loopBegin) { - return graph.add(new BeginNode()); + Node value = seenNode.get(original); + if (value != null) { + return value; + } + BeginNode newValue = graph.add(new BeginNode()); + seenNode.put(original, newValue); + return newValue; } if (original instanceof LoopExitNode && ((LoopExitNode) original).loopBegin() == loopBegin) { - return graph.add(new BeginNode()); + Node value = seenNode.get(original); + if (value != null) { + return value; + } + BeginNode newValue = graph.add(new BeginNode()); + seenNode.put(original, newValue); + return newValue; } if (original instanceof LoopEndNode && ((LoopEndNode) original).loopBegin() == loopBegin) { - return graph.add(new EndNode()); + Node value = seenNode.get(original); + if (value != null) { + return value; + } + EndNode newValue = graph.add(new EndNode()); + seenNode.put(original, newValue); + return newValue; } return original; } @@ -160,7 +180,7 @@ } // create a new phi (we don't patch the old one since some usages of the old one may // still be valid) - PhiNode newPhi = graph.add(phi.type() == PhiType.Value ? new PhiNode(phi.kind(), loopBegin) : new PhiNode(phi.type(), loopBegin, phi.getIdentity())); + PhiNode newPhi = graph.addWithoutUnique(phi.type() == PhiType.Value ? new PhiNode(phi.kind(), loopBegin) : new PhiNode(phi.type(), loopBegin, phi.getIdentity())); newPhi.addInput(first); for (LoopEndNode end : loopBegin.orderedLoopEnds()) { newPhi.addInput(phi.valueAt(end)); @@ -250,7 +270,7 @@ } for (final PhiNode phi : loopBegin.phis().snapshot()) { - final PhiNode firstPhi = graph.add(phi.type() == PhiType.Value ? new PhiNode(phi.kind(), newExitMerge) : new PhiNode(phi.type(), newExitMerge, phi.getIdentity())); + final PhiNode firstPhi = graph.addWithoutUnique(phi.type() == PhiType.Value ? new PhiNode(phi.kind(), newExitMerge) : new PhiNode(phi.type(), newExitMerge, phi.getIdentity())); for (AbstractEndNode end : newExitMerge.forwardEnds()) { LoopEndNode loopEnd = reverseEnds.get(end); ValueNode prim = prim(phi.valueAt(loopEnd)); diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentWhole.java --- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentWhole.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentWhole.java Wed Oct 02 13:26:31 2013 +0200 @@ -68,10 +68,15 @@ final Graph graph = this.graph(); return new DuplicationReplacement() { + private EndNode endNode; + @Override public Node replacement(Node o) { if (o == entry) { - return graph.add(new EndNode()); + if (endNode == null) { + endNode = graph.add(new EndNode()); + } + return endNode; } return o; } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopPolicies.java --- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopPolicies.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopPolicies.java Wed Oct 02 13:26:31 2013 +0200 @@ -48,11 +48,11 @@ return false; } CountedLoopInfo counted = loop.counted(); - long exactTrips = counted.constantMaxTripCount(); + long maxTrips = counted.constantMaxTripCount(); int maxNodes = (counted.isExactTripCount() && counted.isConstantExactTripCount()) ? ExactFullUnrollMaxNodes.getValue() : FullUnrollMaxNodes.getValue(); maxNodes = Math.min(maxNodes, MaximumDesiredSize.getValue() - loop.loopBegin().graph().getNodeCount()); int size = Math.max(1, loop.size() - 1 - loop.loopBegin().phis().count()); - return size * exactTrips <= maxNodes; + return size * maxTrips <= maxNodes; } public static boolean shouldTryUnswitch(LoopEx loop) { diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopTransformations.java --- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopTransformations.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopTransformations.java Wed Oct 02 13:26:31 2013 +0200 @@ -25,13 +25,13 @@ import static com.oracle.graal.phases.GraalOptions.*; import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.NodeClass.NodeClassIterator; import com.oracle.graal.graph.NodeClass.Position; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.phases.common.*; +import com.oracle.graal.phases.tiers.*; public abstract class LoopTransformations { @@ -53,7 +53,7 @@ loop.inside().duplicate().insertBefore(loop); } - public static void fullUnroll(LoopEx loop, MetaAccessProvider runtime, Assumptions assumptions, boolean canonicalizeReads) { + public static void fullUnroll(LoopEx loop, PhaseContext context, CanonicalizerPhase canonicalizer) { // assert loop.isCounted(); //TODO (gd) strenghten : counted with known trip count int iterations = 0; LoopBeginNode loopBegin = loop.loopBegin(); @@ -61,7 +61,7 @@ while (!loopBegin.isDeleted()) { int mark = graph.getMark(); peel(loop); - new CanonicalizerPhase.Instance(runtime, assumptions, canonicalizeReads, mark, null).apply(graph); + canonicalizer.applyIncremental(graph, context, mark); if (iterations++ > UNROLL_LIMIT || graph.getNodeCount() > MaximumDesiredSize.getValue() * 3) { throw new BailoutException("FullUnroll : Graph seems to grow out of proportion"); } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopFullUnrollPhase.java --- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopFullUnrollPhase.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopFullUnrollPhase.java Wed Oct 02 13:26:31 2013 +0200 @@ -26,15 +26,16 @@ import com.oracle.graal.loop.*; import com.oracle.graal.nodes.*; import com.oracle.graal.phases.*; +import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.tiers.*; public class LoopFullUnrollPhase extends BasePhase { private static final DebugMetric FULLY_UNROLLED_LOOPS = Debug.metric("FullUnrolls"); - private final boolean canonicalizeReads; + private final CanonicalizerPhase canonicalizer; - public LoopFullUnrollPhase(boolean canonicalizeReads) { - this.canonicalizeReads = canonicalizeReads; + public LoopFullUnrollPhase(CanonicalizerPhase canonicalizer) { + this.canonicalizer = canonicalizer; } @Override @@ -48,7 +49,7 @@ for (LoopEx loop : dataCounted.countedLoops()) { if (LoopPolicies.shouldFullUnroll(loop)) { Debug.log("FullUnroll %s", loop); - LoopTransformations.fullUnroll(loop, context.getRuntime(), context.getAssumptions(), canonicalizeReads); + LoopTransformations.fullUnroll(loop, context, canonicalizer); FULLY_UNROLLED_LOOPS.increment(); Debug.dump(graph, "After fullUnroll %s", loop); peeled = true; diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractBeginNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractBeginNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractBeginNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -32,7 +32,7 @@ import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; -public abstract class AbstractBeginNode extends FixedWithNextNode implements StateSplit, LIRLowerable, Simplifiable, Node.IterableNodeType, GuardingNode { +public abstract class AbstractBeginNode extends FixedWithNextNode implements StateSplit, LIRLowerable, Simplifiable, GuardingNode, IterableNodeType { @Input(notDataflow = true) private FrameState stateAfter; @@ -186,8 +186,7 @@ } } - @Override - public AbstractBeginNode asNode() { - return this; + public FrameState getState() { + return stateAfter(); } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractDeoptimizeNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractDeoptimizeNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2013, 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.nodes; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.type.*; + +/** + * This node represents an unconditional explicit request for immediate deoptimization. + * + * After this node, execution will continue using a fallback execution engine (such as an + * interpreter) at the position described by the {@link #getDeoptimizationState() deoptimization + * state}. + * + */ +@NodeInfo(shortName = "Deopt", nameTemplate = "Deopt {p#reason/s}") +public abstract class AbstractDeoptimizeNode extends ControlSinkNode implements IterableNodeType, DeoptimizingNode { + + @Input private FrameState deoptState; + + public AbstractDeoptimizeNode() { + super(StampFactory.forVoid()); + } + + @Override + public boolean canDeoptimize() { + return true; + } + + @Override + public FrameState getDeoptimizationState() { + return deoptState; + } + + @Override + public void setDeoptimizationState(FrameState f) { + updateUsages(deoptState, f); + deoptState = f; + } + + public FrameState getState() { + return deoptState; + } + + public abstract ValueNode getActionAndReason(MetaAccessProvider runtime); +} diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractEndNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractEndNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractEndNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -28,7 +28,7 @@ import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; -public abstract class AbstractEndNode extends FixedNode implements Node.IterableNodeType, LIRLowerable { +public abstract class AbstractEndNode extends FixedNode implements IterableNodeType, LIRLowerable { protected AbstractEndNode() { super(StampFactory.forVoid()); diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractStateSplit.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractStateSplit.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractStateSplit.java Wed Oct 02 13:26:31 2013 +0200 @@ -41,6 +41,10 @@ stateAfter = x; } + public FrameState getState() { + return stateAfter(); + } + public boolean hasSideEffect() { return true; } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ArrayRangeWriteBarrier.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ArrayRangeWriteBarrier.java Fri Sep 06 21:37:50 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,43 +0,0 @@ -/* - * 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.nodes; - -public abstract class ArrayRangeWriteBarrier extends WriteBarrier { - - @Input private ValueNode startIndex; - @Input private ValueNode length; - - public ValueNode getStartIndex() { - return startIndex; - } - - public ValueNode getLength() { - return length; - } - - public ArrayRangeWriteBarrier(ValueNode object, ValueNode startIndex, ValueNode length) { - super(object, null, true); - this.startIndex = startIndex; - this.length = length; - } -} diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ControlSinkNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ControlSinkNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ControlSinkNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -22,10 +22,9 @@ */ package com.oracle.graal.nodes; -import com.oracle.graal.graph.*; import com.oracle.graal.nodes.type.*; -public abstract class ControlSinkNode extends FixedNode implements Node.IterableNodeType { +public abstract class ControlSinkNode extends FixedNode { public ControlSinkNode(Stamp stamp) { super(stamp); diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -22,30 +22,15 @@ */ package com.oracle.graal.nodes; -import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; -/** - * This node represents an unconditional explicit request for immediate deoptimization. - * - * After this node, execution will continue using a fallback execution engine (such as an - * interpreter) at the position described by the {@link #getDeoptimizationState() deoptimization - * state}. - * - */ -@NodeInfo(shortName = "Deopt", nameTemplate = "Deopt {p#reason/s}") -public class DeoptimizeNode extends ControlSinkNode implements Node.IterableNodeType, Lowerable, LIRLowerable, DeoptimizingNode { - - @Input private FrameState deoptState; +public class DeoptimizeNode extends AbstractDeoptimizeNode implements LIRLowerable { private final DeoptimizationAction action; private final DeoptimizationReason reason; public DeoptimizeNode(DeoptimizationAction action, DeoptimizationReason reason) { - super(StampFactory.forVoid()); this.action = action; this.reason = reason; } @@ -59,36 +44,15 @@ } @Override - public void lower(LoweringTool tool, LoweringType loweringType) { - tool.getRuntime().lower(this, tool); + public void generate(LIRGeneratorTool gen) { + gen.emitDeoptimize(gen.getRuntime().encodeDeoptActionAndReason(action, reason), this); } @Override - public void generate(LIRGeneratorTool gen) { - gen.emitDeoptimize(action, this); + public ValueNode getActionAndReason(MetaAccessProvider runtime) { + return ConstantNode.forConstant(runtime.encodeDeoptActionAndReason(action, reason), runtime, graph()); } @NodeIntrinsic public static native void deopt(@ConstantNodeParameter DeoptimizationAction action, @ConstantNodeParameter DeoptimizationReason reason); - - @Override - public boolean canDeoptimize() { - return true; - } - - @Override - public FrameState getDeoptimizationState() { - return deoptState; - } - - @Override - public void setDeoptimizationState(FrameState f) { - updateUsages(deoptState, f); - deoptState = f; - } - - @Override - public DeoptimizationReason getDeoptimizationReason() { - return reason; - } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizingFixedWithNextNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizingFixedWithNextNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizingFixedWithNextNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -42,4 +42,8 @@ updateUsages(deoptState, f); deoptState = f; } + + public FrameState getState() { + return deoptState; + } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizingNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizingNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizingNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -22,12 +22,12 @@ */ package com.oracle.graal.nodes; -import com.oracle.graal.api.meta.*; +import com.oracle.graal.nodes.spi.*; /** * Interface implemented by nodes which need deoptimization information. */ -public interface DeoptimizingNode { +public interface DeoptimizingNode extends NodeWithState { /** * Determines if this node needs deoptimization information. @@ -45,13 +45,4 @@ * @param state the FrameState which represents the deoptimization information */ void setDeoptimizationState(FrameState state); - - /** - * Returns the reason for deoptimization triggered by this node. If deoptimization at this point - * can happen for external reasons (i.e. not explicitely triggered by this node) this method can - * return null. - * - * @return the reason for deoptimization triggered by this node. - */ - DeoptimizationReason getDeoptimizationReason(); } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DynamicDeoptimizeNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DynamicDeoptimizeNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2013, 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.nodes; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.nodes.spi.*; + +public class DynamicDeoptimizeNode extends AbstractDeoptimizeNode implements LIRLowerable { + @Input private ValueNode actionAndReason; + + public DynamicDeoptimizeNode(ValueNode actionAndReason) { + this.actionAndReason = actionAndReason; + } + + public ValueNode getActionAndReason() { + return actionAndReason; + } + + @Override + public ValueNode getActionAndReason(MetaAccessProvider runtime) { + return getActionAndReason(); + } + + public void generate(LIRGeneratorTool generator) { + generator.emitDeoptimize(generator.operand(actionAndReason), this); + } +} diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/EntryMarkerNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/EntryMarkerNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/EntryMarkerNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -29,7 +29,7 @@ * This node will be inserted at point specified by {@link StructuredGraph#getEntryBCI()}, usually * by the graph builder. */ -public class EntryMarkerNode extends AbstractBeginNode implements Node.IterableNodeType, Simplifiable, LIRLowerable { +public class EntryMarkerNode extends AbstractBeginNode implements IterableNodeType, Simplifiable, LIRLowerable { @Override public void simplify(SimplifierTool tool) { diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -22,7 +22,6 @@ */ package com.oracle.graal.nodes; -import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.extended.*; @@ -31,7 +30,7 @@ import com.oracle.graal.nodes.util.*; @NodeInfo(nameTemplate = "FixedGuard(!={p#negated}) {p#reason/s}") -public final class FixedGuardNode extends DeoptimizingFixedWithNextNode implements Simplifiable, Lowerable, Node.IterableNodeType, GuardingNode { +public final class FixedGuardNode extends DeoptimizingFixedWithNextNode implements Simplifiable, Lowerable, IterableNodeType, GuardingNode { @Input private LogicNode condition; private final DeoptimizationReason reason; @@ -106,9 +105,12 @@ } @Override - public void lower(LoweringTool tool, LoweringType loweringType) { - if (loweringType == LoweringType.BEFORE_GUARDS) { - tool.getRuntime().lower(this, tool); + public void lower(LoweringTool tool) { + if (graph().getGuardsStage() == StructuredGraph.GuardsStage.FLOATING_GUARDS) { + ValueNode guard = tool.createGuard(condition(), getReason(), getAction(), isNegated()).asNode(); + this.replaceAtUsages(guard); + ValueAnchorNode newAnchor = graph().add(new ValueAnchorNode(guard.asNode())); + graph().replaceFixedWithFixed(this, newAnchor); } else { FixedNode next = next(); setNext(null); @@ -130,17 +132,7 @@ } @Override - public FixedGuardNode asNode() { - return this; - } - - @Override public boolean canDeoptimize() { return true; } - - @Override - public DeoptimizationReason getDeoptimizationReason() { - return reason; - } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -35,4 +35,9 @@ assertTrue(this.successors().isNotEmpty() || this.predecessor() != null, "FixedNode should not float"); return super.verify(); } + + @Override + public FixedNode asNode() { + return this; + } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedWithNextNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedWithNextNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedWithNextNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -44,4 +44,9 @@ public FixedWithNextNode(Stamp stamp) { super(stamp); } + + @Override + public FixedWithNextNode asNode() { + return this; + } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FloatingGuardedNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FloatingGuardedNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FloatingGuardedNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -49,10 +49,4 @@ updateUsages(this.guard == null ? null : this.guard.asNode(), guard == null ? null : guard.asNode()); this.guard = guard; } - - @Override - public FloatingNode asNode() { - return this; - } - } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java Wed Oct 02 13:26:31 2013 +0200 @@ -35,7 +35,7 @@ * stack) at a particular point in the abstract interpretation. */ @NodeInfo(nameTemplate = "FrameState@{p#method/s}:{p#bci}") -public final class FrameState extends VirtualState implements Node.IterableNodeType { +public final class FrameState extends VirtualState implements IterableNodeType { protected final int localsSize; @@ -103,7 +103,6 @@ public FrameState(ResolvedJavaMethod method, int bci, List values, int localsSize, int stackSize, boolean rethrowException, boolean duringCall, List virtualObjectMappings) { assert stackSize >= 0; - assert (bci >= 0 && method != null) || (bci < 0 && method == null && values.isEmpty()); this.method = method; this.bci = bci; this.localsSize = localsSize; @@ -125,29 +124,24 @@ } public FrameState(ResolvedJavaMethod method, int bci, ValueNode[] locals, List stack, ValueNode[] locks, boolean rethrowException, boolean duringCall) { - this.method = method; - this.bci = bci; - this.localsSize = locals.length; - this.stackSize = stack.size(); - final ValueNode[] newValues = new ValueNode[locals.length + stack.size() + locks.length]; - int pos = 0; + this(method, bci, createValues(locals, stack, locks), locals.length, stack.size(), rethrowException, duringCall, Collections. emptyList()); + } + + private static List createValues(ValueNode[] locals, List stack, ValueNode[] locks) { + List newValues = new ArrayList<>(locals.length + stack.size() + locks.length); for (ValueNode value : locals) { - newValues[pos++] = value; + newValues.add(value); + assert value == null || value.isAlive(); } for (ValueNode value : stack) { - newValues[pos++] = value; + newValues.add(value); + assert value == null || value.isAlive(); } for (ValueNode value : locks) { - newValues[pos++] = value; - } - for (ValueNode value : newValues) { + newValues.add(value); assert value == null || value.isAlive(); } - this.values = new NodeInputList<>(this, newValues); - this.virtualObjectMappings = new NodeInputList<>(this); - this.rethrowException = rethrowException; - this.duringCall = duringCall; - assert !rethrowException || stackSize == 1 : "must have exception on top of the stack"; + return newValues; } public NodeInputList values() { diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/G1ArrayRangePostWriteBarrier.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/G1ArrayRangePostWriteBarrier.java Fri Sep 06 21:37:50 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,30 +0,0 @@ -/* - * 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.nodes; - -public final class G1ArrayRangePostWriteBarrier extends ArrayRangeWriteBarrier { - - public G1ArrayRangePostWriteBarrier(ValueNode object, ValueNode startIndex, ValueNode length) { - super(object, startIndex, length); - } -} diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/G1ArrayRangePreWriteBarrier.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/G1ArrayRangePreWriteBarrier.java Fri Sep 06 21:37:50 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,30 +0,0 @@ -/* - * 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.nodes; - -public final class G1ArrayRangePreWriteBarrier extends ArrayRangeWriteBarrier { - - public G1ArrayRangePreWriteBarrier(ValueNode object, ValueNode startIndex, ValueNode length) { - super(object, startIndex, length); - } -} diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/G1PostWriteBarrier.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/G1PostWriteBarrier.java Fri Sep 06 21:37:50 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,39 +0,0 @@ -/* - * 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.nodes; - -import com.oracle.graal.nodes.extended.*; - -public class G1PostWriteBarrier extends WriteBarrier { - - @Input private ValueNode value; - - public ValueNode getValue() { - return value; - } - - public G1PostWriteBarrier(ValueNode object, ValueNode value, LocationNode location, boolean precise) { - super(object, location, precise); - this.value = value; - } -} diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/G1PreWriteBarrier.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/G1PreWriteBarrier.java Fri Sep 06 21:37:50 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,75 +0,0 @@ -/* - * 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.nodes; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.nodes.extended.*; - -public class G1PreWriteBarrier extends WriteBarrier implements DeoptimizingNode { - - @Input private ValueNode expectedObject; - private final boolean doLoad; - - @Input private FrameState deoptimizationState; - private final boolean nullCheck; - - public ValueNode getExpectedObject() { - return expectedObject; - } - - public boolean doLoad() { - return doLoad; - } - - public boolean getNullCheck() { - return nullCheck; - } - - public G1PreWriteBarrier(ValueNode object, ValueNode expectedObject, LocationNode location, boolean doLoad, boolean nullCheck) { - super(object, location, true); - this.doLoad = doLoad; - this.nullCheck = nullCheck; - this.expectedObject = expectedObject; - } - - @Override - public boolean canDeoptimize() { - return nullCheck; - } - - @Override - public FrameState getDeoptimizationState() { - return deoptimizationState; - } - - @Override - public void setDeoptimizationState(FrameState state) { - updateUsages(deoptimizationState, state); - deoptimizationState = state; - } - - @Override - public DeoptimizationReason getDeoptimizationReason() { - return DeoptimizationReason.NullCheckException; - } -} diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/G1ReferentFieldReadBarrier.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/G1ReferentFieldReadBarrier.java Fri Sep 06 21:37:50 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,51 +0,0 @@ -/* - * 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.nodes; - -import com.oracle.graal.nodes.extended.*; - -/** - * The {@code G1ReferentFieldReadBarrier} is added when a read access is performed to the referent - * field of a {@link java.lang.ref.Reference} object (through a {@code LoadFieldNode} or an - * {@code UnsafeLoadNode}). The return value of the read is passed to the snippet implementing the - * read barrier and consequently is added to the SATB queue if the concurrent marker is enabled. - */ -public class G1ReferentFieldReadBarrier extends WriteBarrier { - - @Input private ValueNode expectedObject; - private final boolean doLoad; - - public ValueNode getExpectedObject() { - return expectedObject; - } - - public boolean doLoad() { - return doLoad; - } - - public G1ReferentFieldReadBarrier(ValueNode object, ValueNode expectedObject, LocationNode location, boolean doLoad) { - super(object, location, true); - this.doLoad = doLoad; - this.expectedObject = expectedObject; - } -} diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -22,7 +22,6 @@ */ package com.oracle.graal.nodes; -import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.extended.*; @@ -42,7 +41,7 @@ * control flow would have reached the guarded node (without taking exceptions into account). */ @NodeInfo(nameTemplate = "Guard(!={p#negated}) {p#reason/s}") -public final class GuardNode extends FloatingGuardedNode implements Canonicalizable, Node.IterableNodeType, GuardingNode, GuardedNode { +public final class GuardNode extends FloatingGuardedNode implements Canonicalizable, IterableNodeType, GuardingNode, GuardedNode { @Input private LogicNode condition; private final DeoptimizationReason reason; diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardedValueNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardedValueNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardedValueNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -34,7 +34,7 @@ * * A GuardedValueNode will only go away if its guard is null or {@link StructuredGraph#start()}. */ -public class GuardedValueNode extends FloatingGuardedNode implements LIRLowerable, Virtualizable, Node.IterableNodeType, GuardingNode, Canonicalizable, ValueProxy { +public class GuardedValueNode extends FloatingGuardedNode implements LIRLowerable, Virtualizable, IterableNodeType, GuardingNode, Canonicalizable, ValueProxy { @Input private ValueNode object; diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardingPiNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardingPiNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardingPiNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -22,7 +22,6 @@ */ package com.oracle.graal.nodes; -import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.calc.*; @@ -76,14 +75,15 @@ } @Override - public void lower(LoweringTool tool, LoweringType loweringType) { - if (loweringType == LoweringType.AFTER_GUARDS) { + public void lower(LoweringTool tool) { + if (graph().getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS) { throw new GraalInternalError("Cannot create guards in after-guard lowering"); } - FixedGuardNode guard = graph().add(new FixedGuardNode(condition, reason, action, negated)); - PiNode pi = graph().add(new PiNode(object, stamp(), guard)); + GuardingNode guard = tool.createGuard(condition, reason, action, negated); + ValueAnchorNode anchor = graph().add(new ValueAnchorNode((ValueNode) guard)); + PiNode pi = graph().unique(new PiNode(object, stamp(), (ValueNode) guard)); replaceAtUsages(pi); - graph().replaceFixedWithFixed(this, guard); + graph().replaceFixedWithFixed(this, anchor); } @Override @@ -93,8 +93,17 @@ @Override public ValueNode canonical(CanonicalizerTool tool) { + if (stamp() == StampFactory.illegal(object.kind())) { + // The guard always fails + return graph().add(new DeoptimizeNode(action, reason)); + } if (condition instanceof LogicConstantNode) { LogicConstantNode c = (LogicConstantNode) condition; + if (c.getValue() == negated) { + // The guard always fails + return graph().add(new DeoptimizeNode(action, reason)); + } + if (c.getValue() != negated && stamp().equals(object().stamp())) { return object; } @@ -115,11 +124,6 @@ @ConstantNodeParameter DeoptimizationAction action, @ConstantNodeParameter Stamp stamp); @Override - public ValueNode asNode() { - return this; - } - - @Override public ValueNode getOriginalValue() { return object; } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -578,7 +578,7 @@ // removed MergeNode newMerge = graph().add(new MergeNode()); PhiNode oldPhi = (PhiNode) oldMerge.usages().first(); - PhiNode newPhi = graph().add(new PhiNode(oldPhi.stamp(), newMerge)); + PhiNode newPhi = graph().addWithoutUnique(new PhiNode(oldPhi.stamp(), newMerge)); for (AbstractEndNode end : ends) { newPhi.addInput(phiValues.get(end)); diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InfopointNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InfopointNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InfopointNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -23,20 +23,21 @@ package com.oracle.graal.nodes; import com.oracle.graal.api.code.*; -import com.oracle.graal.graph.Node.IterableNodeType; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; /** * Nodes of this type are inserted into the graph to denote points of interest to debugging. */ -public class InfopointNode extends AbstractStateSplit implements LIRLowerable, IterableNodeType { +public class InfopointNode extends FixedWithNextNode implements LIRLowerable, NodeWithState { public final InfopointReason reason; + @Input private FrameState state; - public InfopointNode(InfopointReason reason) { + public InfopointNode(InfopointReason reason, FrameState state) { super(StampFactory.forVoid()); this.reason = reason; + this.state = state; } @Override @@ -44,24 +45,13 @@ generator.visitInfopointNode(this); } - @Override - public boolean hasSideEffect() { - return false; - } - - @Override - public void setStateAfter(FrameState state) { - // shield this node from frame state removal - // TODO turn InfopointNode into a FixedWithNextNode subclass with a self-maintained - // FrameState that is correctly dealt with by scheduling and partial escape analysis - if (state != null) { - super.setStateAfter(state); - } + public FrameState getState() { + return state; } @Override public boolean verify() { - return stateAfter() != null && super.verify(); + return getState() != null && super.verify(); } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -35,7 +35,7 @@ * The {@code InvokeNode} represents all kinds of method calls. */ @NodeInfo(nameTemplate = "Invoke#{p#targetMethod/s}") -public final class InvokeNode extends AbstractStateSplit implements StateSplit, Node.IterableNodeType, Invoke, LIRLowerable, MemoryCheckpoint.Single { +public final class InvokeNode extends AbstractStateSplit implements Invoke, LIRLowerable, MemoryCheckpoint.Single { @Input private CallTargetNode callTarget; @Input private FrameState deoptState; @@ -108,7 +108,7 @@ } @Override - public void lower(LoweringTool tool, LoweringType loweringType) { + public void lower(LoweringTool tool) { tool.getRuntime().lower(this, tool); } @@ -133,11 +133,6 @@ } @Override - public FixedNode asNode() { - return this; - } - - @Override public FrameState stateDuring() { FrameState stateAfter = stateAfter(); if (stateAfter == null) { @@ -179,11 +174,6 @@ } @Override - public DeoptimizationReason getDeoptimizationReason() { - return null; - } - - @Override public FrameState getDeoptimizationState() { if (deoptState == null) { FrameState stateDuring = stateDuring(); @@ -208,4 +198,14 @@ updateUsages(this.guard == null ? null : this.guard.asNode(), guard == null ? null : guard.asNode()); this.guard = guard; } + + @Override + public FrameState getState() { + if (deoptState != null) { + assert stateAfter() == null; + return deoptState; + } else { + return super.getState(); + } + } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -32,7 +32,7 @@ import com.oracle.graal.nodes.util.*; @NodeInfo(nameTemplate = "Invoke!#{p#targetMethod/s}") -public class InvokeWithExceptionNode extends ControlSplitNode implements Node.IterableNodeType, Invoke, MemoryCheckpoint.Single, LIRLowerable { +public class InvokeWithExceptionNode extends ControlSplitNode implements IterableNodeType, Invoke, MemoryCheckpoint.Single, LIRLowerable { private static final double EXCEPTION_PROBA = 1e-5; @@ -119,11 +119,6 @@ } @Override - public FixedNode asNode() { - return this; - } - - @Override public void setNext(FixedNode x) { if (x != null) { this.setNext(AbstractBeginNode.begin(x)); @@ -133,7 +128,7 @@ } @Override - public void lower(LoweringTool tool, LoweringType loweringType) { + public void lower(LoweringTool tool) { tool.getRuntime().lower(this, tool); } @@ -224,11 +219,6 @@ } @Override - public DeoptimizationReason getDeoptimizationReason() { - return null; - } - - @Override public FrameState getDeoptimizationState() { if (deoptState == null) { FrameState stateDuring = stateDuring(); @@ -253,4 +243,14 @@ updateUsages(this.guard == null ? null : this.guard.asNode(), guard == null ? null : guard.asNode()); this.guard = guard; } + + @Override + public FrameState getState() { + if (deoptState != null) { + assert stateAfter() == null; + return deoptState; + } else { + return stateAfter(); + } + } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LocalNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LocalNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LocalNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -29,7 +29,7 @@ * The {@code Local} instruction is a placeholder for an incoming argument to a function call. */ @NodeInfo(nameTemplate = "Local({p#index})") -public final class LocalNode extends AbstractLocalNode implements Node.IterableNodeType { +public final class LocalNode extends AbstractLocalNode implements IterableNodeType { public LocalNode(int index, Stamp stamp) { super(index, stamp); diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LogicNegationNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LogicNegationNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LogicNegationNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -28,7 +28,7 @@ /** * Logic node that negates its argument. */ -public class LogicNegationNode extends LogicNode implements Canonicalizable, Node.IterableNodeType { +public class LogicNegationNode extends LogicNode implements Canonicalizable, IterableNodeType { @Input private LogicNode input; diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LogicNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LogicNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LogicNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -30,4 +30,22 @@ public LogicNode() { super(StampFactory.condition()); } + + public static LogicNode and(LogicNode a, LogicNode b, double shortCircuitProbability) { + return and(a, false, b, false, shortCircuitProbability); + } + + public static LogicNode and(LogicNode a, boolean negateA, LogicNode b, boolean negateB, double shortCircuitProbability) { + StructuredGraph graph = a.graph(); + ShortCircuitOrNode notAorNotB = graph.unique(new ShortCircuitOrNode(a, !negateA, b, !negateB, shortCircuitProbability)); + return graph.unique(new LogicNegationNode(notAorNotB)); + } + + public static LogicNode or(LogicNode a, LogicNode b, double shortCircuitProbability) { + return or(a, false, b, false, shortCircuitProbability); + } + + public static LogicNode or(LogicNode a, boolean negateA, LogicNode b, boolean negateB, double shortCircuitProbability) { + return a.graph().unique(new ShortCircuitOrNode(a, negateA, b, negateB, shortCircuitProbability)); + } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopBeginNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopBeginNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopBeginNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -31,7 +31,7 @@ import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; -public class LoopBeginNode extends MergeNode implements Node.IterableNodeType, LIRLowerable { +public class LoopBeginNode extends MergeNode implements IterableNodeType, LIRLowerable { private double loopFrequency; private int nextEndIndex; diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopExitNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopExitNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopExitNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -22,9 +22,10 @@ */ package com.oracle.graal.nodes; +import com.oracle.graal.graph.*; import com.oracle.graal.nodes.spi.*; -public class LoopExitNode extends BeginStateSplitNode { +public class LoopExitNode extends BeginStateSplitNode implements IterableNodeType { @Input(notDataflow = true) private LoopBeginNode loopBegin; diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryMapNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryMapNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -0,0 +1,37 @@ +/* + * 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.nodes; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.type.*; + +public abstract class MemoryMapNode extends FloatingNode { + + public MemoryMapNode() { + super(StampFactory.forVoid()); + } + + public abstract Node getLastLocationAccess(LocationIdentity locationIdentity); +} diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MergeNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MergeNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MergeNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -33,7 +33,7 @@ /** * Denotes the merging of multiple control-flow paths. */ -public class MergeNode extends BeginStateSplitNode implements Node.IterableNodeType, LIRLowerable { +public class MergeNode extends BeginStateSplitNode implements IterableNodeType, LIRLowerable { @Input(notDataflow = true) private final NodeInputList ends = new NodeInputList<>(this); diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -34,7 +34,7 @@ * variable. */ @NodeInfo(nameTemplate = "{p#type/s}Phi({i#values})") -public class PhiNode extends FloatingNode implements Canonicalizable, Node.IterableNodeType, GuardingNode { +public class PhiNode extends FloatingNode implements Canonicalizable, IterableNodeType, GuardingNode { public static enum PhiType { Value(null), // normal value phis @@ -248,9 +248,4 @@ public boolean isLoopPhi() { return merge() instanceof LoopBeginNode; } - - @Override - public PhiNode asNode() { - return this; - } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiArrayNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiArrayNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2012, 2012, 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.nodes; + +import com.oracle.graal.nodes.java.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; + +/** + * A {@link PiNode} that also provides an array length in addition to a more refined stamp. A usage + * that reads the array length, such as an {@link ArrayLengthNode}, can be canonicalized base on + * this information. + */ +public final class PiArrayNode extends PiNode implements ArrayLengthProvider { + + @Input private ValueNode length; + + public ValueNode length() { + return length; + } + + public PiArrayNode(ValueNode object, ValueNode length, Stamp stamp) { + super(object, stamp); + this.length = length; + } + + @Override + public ValueNode canonical(CanonicalizerTool tool) { + if (!(object() instanceof ArrayLengthProvider) || length() != ((ArrayLengthProvider) object()).length()) { + return this; + } + return super.canonical(tool); + } + + @NodeIntrinsic + public static native T piArrayCast(Object object, int length, @ConstantNodeParameter Stamp stamp); +} diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -36,7 +36,7 @@ * is as narrow or narrower than the PiNode's type. The PiNode, and therefore also the scheduling * restriction enforced by the anchor, will go away. */ -public class PiNode extends FloatingGuardedNode implements LIRLowerable, Virtualizable, Node.IterableNodeType, GuardingNode, Canonicalizable, ValueProxy { +public class PiNode extends FloatingGuardedNode implements LIRLowerable, Virtualizable, IterableNodeType, GuardingNode, Canonicalizable, ValueProxy { @Input private ValueNode object; @@ -49,11 +49,15 @@ this.object = object; } - public PiNode(ValueNode object, Stamp stamp, GuardingNode anchor) { - super(stamp, anchor); + public PiNode(ValueNode object, Stamp stamp, ValueNode anchor) { + super(stamp, (GuardingNode) anchor); this.object = object; } + public PiNode(ValueNode object, ResolvedJavaType toType, boolean exactType, boolean nonNull) { + this(object, StampFactory.object(toType, exactType, nonNull || ObjectStamp.isObjectNonNull(object.stamp()))); + } + @Override public void generate(LIRGeneratorTool generator) { if (object.kind() != Kind.Void && object.kind() != Kind.Illegal) { @@ -63,6 +67,9 @@ @Override public boolean inferStamp() { + if (stamp() == StampFactory.forNodeIntrinsic()) { + return false; + } return updateStamp(stamp().join(object().stamp())); } @@ -70,6 +77,7 @@ public void virtualize(VirtualizerTool tool) { State state = tool.getObjectState(object); if (state != null && state.getState() == EscapeState.Virtual) { + assert ObjectStamp.typeOrNull(this).isAssignableFrom(state.getVirtualObject().type()); tool.replaceWithVirtual(state.getVirtualObject()); } } @@ -87,4 +95,16 @@ public ValueNode getOriginalValue() { return object; } + + @NodeIntrinsic + public static native T piCast(Object object, @ConstantNodeParameter Stamp stamp); + + @NodeIntrinsic + public static native T piCast(Object object, @ConstantNodeParameter Stamp stamp, GuardingNode anchor); + + @SuppressWarnings("unused") + @NodeIntrinsic + public static T piCast(Object object, @ConstantNodeParameter Class toType, @ConstantNodeParameter boolean exactType, @ConstantNodeParameter boolean nonNull) { + return toType.cast(object); + } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ProxyNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ProxyNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ProxyNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -35,7 +35,7 @@ * loop. */ @NodeInfo(nameTemplate = "{p#type/s}Proxy") -public class ProxyNode extends FloatingNode implements Node.IterableNodeType, ValueNumberable, Canonicalizable, Virtualizable, LIRLowerable, ValueProxy, GuardingNode { +public class ProxyNode extends FloatingNode implements IterableNodeType, ValueNumberable, Canonicalizable, Virtualizable, LIRLowerable, ValueProxy, GuardingNode { @Input(notDataflow = true) private AbstractBeginNode proxyPoint; @Input private ValueNode value; @@ -120,8 +120,4 @@ public ValueNode getOriginalValue() { return value; } - - public ValueNode asNode() { - return this; - } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ReturnNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ReturnNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ReturnNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -22,13 +22,13 @@ */ package com.oracle.graal.nodes; -import com.oracle.graal.graph.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; -public final class ReturnNode extends ControlSinkNode implements LIRLowerable, Node.IterableNodeType { +public final class ReturnNode extends ControlSinkNode implements LIRLowerable { @Input private ValueNode result; + @Input private MemoryMapNode memoryMap; public ValueNode result() { return result; @@ -41,8 +41,13 @@ * void return */ public ReturnNode(ValueNode result) { + this(result, null); + } + + public ReturnNode(ValueNode result, MemoryMapNode memoryMap) { super(StampFactory.forVoid()); this.result = result; + this.memoryMap = memoryMap; } @Override @@ -54,4 +59,13 @@ public void generate(LIRGeneratorTool gen) { gen.visitReturn(this); } + + public void setMemoryMap(MemoryMapNode memoryMap) { + updateUsages(this.memoryMap, memoryMap); + this.memoryMap = memoryMap; + } + + public MemoryMapNode getMemoryMap() { + return memoryMap; + } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SafepointNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SafepointNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SafepointNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -22,22 +22,16 @@ */ package com.oracle.graal.nodes; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; /** * Marks a position in the graph where a safepoint should be emitted. */ -public class SafepointNode extends DeoptimizingFixedWithNextNode implements LIRLowerable, Node.IterableNodeType { +public class SafepointNode extends DeoptimizingFixedWithNextNode implements LIRLowerable { public SafepointNode() { - this(StampFactory.forVoid()); - } - - public SafepointNode(Stamp stamp) { - super(stamp); + super(StampFactory.forVoid()); } @Override @@ -46,11 +40,6 @@ } @Override - public DeoptimizationReason getDeoptimizationReason() { - return null; - } - - @Override public boolean canDeoptimize() { return true; } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SerialArrayRangeWriteBarrier.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SerialArrayRangeWriteBarrier.java Fri Sep 06 21:37:50 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,30 +0,0 @@ -/* - * 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.nodes; - -public final class SerialArrayRangeWriteBarrier extends ArrayRangeWriteBarrier { - - public SerialArrayRangeWriteBarrier(ValueNode object, ValueNode startIndex, ValueNode length) { - super(object, startIndex, length); - } -} diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SerialWriteBarrier.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SerialWriteBarrier.java Fri Sep 06 21:37:50 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,39 +0,0 @@ -/* - * 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.nodes; - -import com.oracle.graal.nodes.extended.*; - -public class SerialWriteBarrier extends WriteBarrier { - - @Input private ValueNode value; - - public ValueNode getValue() { - return value; - } - - public SerialWriteBarrier(ValueNode object, ValueNode value, LocationNode location, boolean precise) { - super(object, location, precise); - this.value = value; - } -} diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ShortCircuitAndNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ShortCircuitAndNode.java Fri Sep 06 21:37:50 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,99 +0,0 @@ -/* - * Copyright (c) 2013, 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.nodes; - -import com.oracle.graal.nodes.spi.*; - -/** - * The short-circuit AND (i.e. {@code &&} in Java) operator. - */ -public class ShortCircuitAndNode extends ShortCircuitBooleanNode implements Canonicalizable { - - public ShortCircuitAndNode(LogicNode x, boolean xNegated, LogicNode y, boolean yNegated, double shortCircuitProbability) { - super(x, xNegated, y, yNegated, shortCircuitProbability); - } - - @Override - public LogicNode canonical(CanonicalizerTool tool) { - ShortCircuitBooleanNode ret = canonicalizeNegation(); - if (ret != null) { - return ret; - } - - LogicNode x = getX(); - LogicNode y = getY(); - if (x == y) { - // @formatter:off - // a && a = a - // a && !a = false - // !a && a = false - // !a && !a = !a - // @formatter:on - if (isXNegated()) { - if (isYNegated()) { - // !a && !a = !a - return graph().unique(new LogicNegationNode(x)); - } else { - // !a && a = false - return LogicConstantNode.contradiction(graph()); - } - } else { - if (isYNegated()) { - // a && !a = false - return LogicConstantNode.contradiction(graph()); - } else { - // a && a = a - return x; - } - } - } - if (x instanceof LogicConstantNode) { - if (((LogicConstantNode) x).getValue() ^ isXNegated()) { - if (isYNegated()) { - return graph().unique(new LogicNegationNode(y)); - } else { - return y; - } - } else { - return LogicConstantNode.contradiction(graph()); - } - } - if (y instanceof LogicConstantNode) { - if (((LogicConstantNode) y).getValue() ^ isYNegated()) { - if (isXNegated()) { - return graph().unique(new LogicNegationNode(x)); - } else { - return x; - } - } else { - return LogicConstantNode.contradiction(graph()); - } - } - return this; - } - - @Override - protected ShortCircuitBooleanNode createCopy(LogicNode xCond, boolean xNeg, LogicNode yCond, boolean yNeg, double probability) { - return new ShortCircuitAndNode(xCond, xNeg, yCond, yNeg, probability); - } -} diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ShortCircuitBooleanNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ShortCircuitBooleanNode.java Fri Sep 06 21:37:50 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,93 +0,0 @@ -/* - * Copyright (c) 2013, 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.nodes; - -import com.oracle.graal.graph.*; - -/** - * Base class for the short-circuit boolean operators. - */ -public abstract class ShortCircuitBooleanNode extends LogicNode implements Node.IterableNodeType { - - @Input private LogicNode x; - @Input private LogicNode y; - private boolean xNegated; - private boolean yNegated; - private double shortCircuitProbability; - - public ShortCircuitBooleanNode(LogicNode x, boolean xNegated, LogicNode y, boolean yNegated, double shortCircuitProbability) { - this.x = x; - this.xNegated = xNegated; - this.y = y; - this.yNegated = yNegated; - this.shortCircuitProbability = shortCircuitProbability; - } - - public LogicNode getX() { - return x; - } - - public LogicNode getY() { - return y; - } - - public boolean isXNegated() { - return xNegated; - } - - public boolean isYNegated() { - return yNegated; - } - - /** - * Gets the probability that the {@link #getY() y} part of this binary node is not - * evaluated. This is the probability that this operator will short-circuit its execution. - */ - public double getShortCircuitProbability() { - return shortCircuitProbability; - } - - protected abstract ShortCircuitBooleanNode createCopy(LogicNode xCond, boolean xNeg, LogicNode yCond, boolean yNeg, double probability); - - protected ShortCircuitBooleanNode canonicalizeNegation() { - LogicNode xCond = x; - boolean xNeg = xNegated; - while (xCond instanceof LogicNegationNode) { - xCond = ((LogicNegationNode) xCond).getInput(); - xNeg = !xNeg; - } - - LogicNode yCond = y; - boolean yNeg = yNegated; - while (yCond instanceof LogicNegationNode) { - yCond = ((LogicNegationNode) yCond).getInput(); - yNeg = !yNeg; - } - - if (xCond != x || yCond != y) { - return graph().unique(createCopy(xCond, xNeg, yCond, yNeg, shortCircuitProbability)); - } else { - return null; - } - } -} diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ShortCircuitOrNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ShortCircuitOrNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ShortCircuitOrNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -22,27 +22,79 @@ */ package com.oracle.graal.nodes; +import com.oracle.graal.graph.*; import com.oracle.graal.nodes.spi.*; -/** - * The short-circuit OR (i.e. {@code ||} in Java) operator. - */ -public class ShortCircuitOrNode extends ShortCircuitBooleanNode implements Canonicalizable { +public class ShortCircuitOrNode extends LogicNode implements IterableNodeType, Canonicalizable { + + @Input private LogicNode x; + @Input private LogicNode y; + private boolean xNegated; + private boolean yNegated; + private double shortCircuitProbability; public ShortCircuitOrNode(LogicNode x, boolean xNegated, LogicNode y, boolean yNegated, double shortCircuitProbability) { - super(x, xNegated, y, yNegated, shortCircuitProbability); + this.x = x; + this.xNegated = xNegated; + this.y = y; + this.yNegated = yNegated; + this.shortCircuitProbability = shortCircuitProbability; + } + + public LogicNode getX() { + return x; + } + + public LogicNode getY() { + return y; + } + + public boolean isXNegated() { + return xNegated; + } + + public boolean isYNegated() { + return yNegated; + } + + /** + * Gets the probability that the {@link #getY() y} part of this binary node is not + * evaluated. This is the probability that this operator will short-circuit its execution. + */ + public double getShortCircuitProbability() { + return shortCircuitProbability; + } + + protected ShortCircuitOrNode canonicalizeNegation() { + LogicNode xCond = x; + boolean xNeg = xNegated; + while (xCond instanceof LogicNegationNode) { + xCond = ((LogicNegationNode) xCond).getInput(); + xNeg = !xNeg; + } + + LogicNode yCond = y; + boolean yNeg = yNegated; + while (yCond instanceof LogicNegationNode) { + yCond = ((LogicNegationNode) yCond).getInput(); + yNeg = !yNeg; + } + + if (xCond != x || yCond != y) { + return graph().unique(new ShortCircuitOrNode(xCond, xNeg, yCond, yNeg, shortCircuitProbability)); + } else { + return null; + } } @Override public LogicNode canonical(CanonicalizerTool tool) { - ShortCircuitBooleanNode ret = canonicalizeNegation(); + ShortCircuitOrNode ret = canonicalizeNegation(); if (ret != null) { return ret; } - LogicNode x = getX(); - LogicNode y = getY(); - if (x == y) { + if (getX() == getY()) { // @formatter:off // a || a = a // a || !a = true @@ -52,7 +104,7 @@ if (isXNegated()) { if (isYNegated()) { // !a || !a = !a - return graph().unique(new LogicNegationNode(x)); + return graph().unique(new LogicNegationNode(getX())); } else { // !a || a = true return LogicConstantNode.tautology(graph()); @@ -63,37 +115,32 @@ return LogicConstantNode.tautology(graph()); } else { // a || a = a - return x; + return getX(); } } } - if (x instanceof LogicConstantNode) { - if (((LogicConstantNode) x).getValue() ^ isXNegated()) { + if (getX() instanceof LogicConstantNode) { + if (((LogicConstantNode) getX()).getValue() ^ isXNegated()) { return LogicConstantNode.tautology(graph()); } else { if (isYNegated()) { - return graph().unique(new LogicNegationNode(y)); + return graph().unique(new LogicNegationNode(getY())); } else { - return y; + return getY(); } } } - if (y instanceof LogicConstantNode) { - if (((LogicConstantNode) y).getValue() ^ isYNegated()) { + if (getY() instanceof LogicConstantNode) { + if (((LogicConstantNode) getY()).getValue() ^ isYNegated()) { return LogicConstantNode.tautology(graph()); } else { if (isXNegated()) { - return graph().unique(new LogicNegationNode(x)); + return graph().unique(new LogicNegationNode(getX())); } else { - return x; + return getX(); } } } return this; } - - @Override - protected ShortCircuitBooleanNode createCopy(LogicNode xCond, boolean xNeg, LogicNode yCond, boolean yNeg, double probability) { - return new ShortCircuitOrNode(xCond, xNeg, yCond, yNeg, probability); - } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StateSplit.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StateSplit.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StateSplit.java Wed Oct 02 13:26:31 2013 +0200 @@ -22,10 +22,12 @@ */ package com.oracle.graal.nodes; +import com.oracle.graal.nodes.spi.*; + /** * A state split is a node that may have a frame state associated with it. */ -public interface StateSplit { +public interface StateSplit extends NodeWithState { /** * Gets the state of the JVM frame after execution of this node. diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java Wed Oct 02 13:26:31 2013 +0200 @@ -37,6 +37,35 @@ */ public class StructuredGraph extends Graph { + /** + * The different stages of the compilation of a {@link Graph} regarding the status of + * {@link GuardNode guards}, {@link DeoptimizingNode deoptimizations} and {@link FrameState + * framestates}. The stage of a graph progresses monotonously. + * + */ + public static enum GuardsStage { + /** + * During this stage, there can be {@link FloatingNode floating} {@link DeoptimizingNode} + * such as {@link GuardNode GuardNodes}. New {@link DeoptimizingNode DeoptimizingNodes} can + * be introduced without constraints. {@link FrameState} nodes are associated with + * {@link StateSplit} nodes. + */ + FLOATING_GUARDS, + /** + * During this stage, all {@link DeoptimizingNode DeoptimizingNodes} must be + * {@link FixedNode fixed} but new {@link DeoptimizingNode DeoptimizingNodes} can still be + * introduced. {@link FrameState} nodes are still associated with {@link StateSplit} nodes. + */ + FIXED_DEOPTS, + /** + * During this stage, all {@link DeoptimizingNode DeoptimizingNodes} must be + * {@link FixedNode fixed}. New {@link DeoptimizingNode DeoptimizingNodes} can not be + * introduced any more. {@link FrameState} nodes are now associated with + * {@link DeoptimizingNode} nodes. + */ + AFTER_FSA + } + public static final int INVOCATION_ENTRY_BCI = -1; public static final long INVALID_GRAPH_ID = -1; @@ -48,6 +77,8 @@ private final ResolvedJavaMethod method; private final long graphId; private final int entryBCI; + private GuardsStage guardsStage = GuardsStage.FLOATING_GUARDS; + private boolean isAfterFloatingReadPhase = false; /** * Creates a new Graph containing a single {@link AbstractBeginNode} as the {@link #start() @@ -148,7 +179,7 @@ StructuredGraph copy = new StructuredGraph(newName, newMethod, graphId, entryBCI); HashMap replacements = new HashMap<>(); replacements.put(start, copy.start); - copy.addDuplicates(getNodes(), replacements); + copy.addDuplicates(getNodes(), this, this.getNodeCount(), replacements); return copy; } @@ -386,4 +417,22 @@ singleEnd.replaceAndDelete(sux); } } + + public GuardsStage getGuardsStage() { + return guardsStage; + } + + public void setGuardsStage(GuardsStage guardsStage) { + assert guardsStage.ordinal() >= this.guardsStage.ordinal(); + this.guardsStage = guardsStage; + } + + public boolean isAfterFloatingReadPhase() { + return isAfterFloatingReadPhase; + } + + public void setAfterFloatingReadPhase(boolean state) { + assert state : "cannot 'unapply' floating read phase on graph"; + isAfterFloatingReadPhase = state; + } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/TypeProfileProxyNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/TypeProfileProxyNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/TypeProfileProxyNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -32,7 +32,7 @@ /** * A node that attaches a type profile to a proxied input node. */ -public final class TypeProfileProxyNode extends FloatingNode implements Canonicalizable, Node.IterableNodeType, ValueProxy { +public final class TypeProfileProxyNode extends FloatingNode implements Canonicalizable, IterableNodeType, ValueProxy { @Input private ValueNode object; private final JavaTypeProfile profile; @@ -52,7 +52,7 @@ // Only null profiling is not beneficial enough to keep the node around. return object; } - return object.graph().add(new TypeProfileProxyNode(object, profile)); + return object.graph().addWithoutUnique(new TypeProfileProxyNode(object, profile)); } private TypeProfileProxyNode(ValueNode object, JavaTypeProfile profile) { diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/UnwindNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/UnwindNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/UnwindNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -23,14 +23,13 @@ package com.oracle.graal.nodes; import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; /** * Unwinds the current frame to an exception handler in the caller frame. */ -public final class UnwindNode extends ControlSinkNode implements Lowerable, LIRLowerable, Node.IterableNodeType { +public final class UnwindNode extends ControlSinkNode implements LIRLowerable { @Input private ValueNode exception; @@ -48,9 +47,4 @@ public void generate(LIRGeneratorTool gen) { gen.emitUnwind(gen.operand(exception())); } - - @Override - public void lower(LoweringTool tool, LoweringType loweringType) { - tool.getRuntime().lower(this, tool); - } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -140,4 +140,8 @@ assertTrue(kind() == kind().getStackKind(), "Should have a stack kind : %s", kind()); return super.verify(); } + + public ValueNode asNode() { + return this; + } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/WriteBarrier.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/WriteBarrier.java Fri Sep 06 21:37:50 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,60 +0,0 @@ -/* - * 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.nodes; - -import com.oracle.graal.graph.*; -import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; - -public abstract class WriteBarrier extends FixedWithNextNode implements Lowerable, Node.IterableNodeType { - - @Input private ValueNode object; - @Input private LocationNode location; - private final boolean precise; - - public ValueNode getObject() { - return object; - } - - public LocationNode getLocation() { - return location; - } - - public boolean usePrecise() { - return precise; - } - - public WriteBarrier(ValueNode object, LocationNode location, boolean precise) { - super(StampFactory.forVoid()); - this.object = object; - this.location = location; - this.precise = precise; - } - - @Override - public void lower(LoweringTool generator, LoweringType loweringType) { - assert loweringType == LoweringType.AFTER_FSA; - generator.getRuntime().lower(this, generator); - } -} diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AndNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AndNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AndNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -41,6 +41,12 @@ } @Override + public Constant evalConst(Constant... inputs) { + assert inputs.length == 2; + return Constant.forIntegerKind(kind(), inputs[0].asLong() & inputs[1].asLong(), null); + } + + @Override public ValueNode canonical(CanonicalizerTool tool) { if (x() == y()) { return x(); @@ -49,12 +55,7 @@ return graph().unique(new AndNode(kind(), y(), x())); } if (x().isConstant()) { - if (kind() == Kind.Int) { - return ConstantNode.forInt(x().asConstant().asInt() & y().asConstant().asInt(), graph()); - } else { - assert kind() == Kind.Long; - return ConstantNode.forLong(x().asConstant().asLong() & y().asConstant().asLong(), graph()); - } + return ConstantNode.forPrimitive(evalConst(x().asConstant(), y().asConstant()), graph()); } else if (y().isConstant()) { if (kind() == Kind.Int) { int c = y().asConstant().asInt(); diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BinaryNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BinaryNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BinaryNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -150,14 +150,22 @@ return null; } + //@formatter:off /* * In reassociate, complexity comes from the handling of IntegerSub (non commutative) which can - * be mixed with IntegerAdd. if first tries to find m1, m2 which match the criterion : (a o m2) - * o m1 (m2 o a) o m1 m1 o (a o m2) m1 o (m2 o a) It then produces 4 boolean for the -/+ case - * invertA : should the final expression be like *-a (rather than a+*) aSub : should the final - * expression be like a-* (rather than a+*) invertM1 : should the final expression contain -m1 + * be mixed with IntegerAdd. It first tries to find m1, m2 which match the criterion : + * (a o m2) o m1 + * (m2 o a) o m1 + * m1 o (a o m2) + * m1 o (m2 o a) + * It then produces 4 boolean for the -/+ cases: + * invertA : should the final expression be like *-a (rather than a+*) + * aSub : should the final expression be like a-* (rather than a+*) + * invertM1 : should the final expression contain -m1 * invertM2 : should the final expression contain -m2 + * */ + //@formatter:on /** * Tries to re-associate values which satisfy the criterion. For example with a constantness * criterion : (a + 2) + 1 => a + (1 + 2)
diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConditionalNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConditionalNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConditionalNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -116,7 +116,7 @@ } private ConditionalNode(ValueNode type, ValueNode object) { - this(type.graph().add(new InstanceOfDynamicNode(type, object))); + this(type.graph().unique(new InstanceOfDynamicNode(type, object))); } @NodeIntrinsic diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConvertNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConvertNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConvertNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -150,52 +150,59 @@ this.value = value; } + public Constant evalConst(Constant... inputs) { + assert inputs.length == 1; + Constant c = inputs[0]; + switch (opcode) { + case I2L: + return Constant.forLong(c.asInt()); + case L2I: + return Constant.forInt((int) c.asLong()); + case I2B: + return Constant.forByte((byte) c.asInt()); + case I2C: + return Constant.forChar((char) c.asInt()); + case I2S: + return Constant.forShort((short) c.asInt()); + case F2D: + return Constant.forDouble(c.asFloat()); + case D2F: + return Constant.forFloat((float) c.asDouble()); + case I2F: + return Constant.forFloat(c.asInt()); + case I2D: + return Constant.forDouble(c.asInt()); + case F2I: + return Constant.forInt((int) c.asFloat()); + case D2I: + return Constant.forInt((int) c.asDouble()); + case L2F: + return Constant.forFloat(c.asLong()); + case L2D: + return Constant.forDouble(c.asLong()); + case F2L: + return Constant.forLong((long) c.asFloat()); + case D2L: + return Constant.forLong((long) c.asDouble()); + case UNSIGNED_I2L: + return Constant.forLong(c.asInt() & 0xffffffffL); + case MOV_I2F: + return Constant.forFloat(java.lang.Float.intBitsToFloat(c.asInt())); + case MOV_L2D: + return Constant.forDouble(java.lang.Double.longBitsToDouble(c.asLong())); + case MOV_F2I: + return Constant.forInt(java.lang.Float.floatToRawIntBits(c.asFloat())); + case MOV_D2L: + return Constant.forLong(java.lang.Double.doubleToRawLongBits(c.asDouble())); + default: + throw GraalInternalError.shouldNotReachHere(); + } + } + @Override public ValueNode canonical(CanonicalizerTool tool) { - if (value instanceof ConstantNode) { - Constant c = ((ConstantNode) value).asConstant(); - switch (opcode) { - case I2L: - return ConstantNode.forLong(c.asInt(), graph()); - case L2I: - return ConstantNode.forInt((int) c.asLong(), graph()); - case I2B: - return ConstantNode.forByte((byte) c.asInt(), graph()); - case I2C: - return ConstantNode.forChar((char) c.asInt(), graph()); - case I2S: - return ConstantNode.forShort((short) c.asInt(), graph()); - case F2D: - return ConstantNode.forDouble(c.asFloat(), graph()); - case D2F: - return ConstantNode.forFloat((float) c.asDouble(), graph()); - case I2F: - return ConstantNode.forFloat(c.asInt(), graph()); - case I2D: - return ConstantNode.forDouble(c.asInt(), graph()); - case F2I: - return ConstantNode.forInt((int) c.asFloat(), graph()); - case D2I: - return ConstantNode.forInt((int) c.asDouble(), graph()); - case L2F: - return ConstantNode.forFloat(c.asLong(), graph()); - case L2D: - return ConstantNode.forDouble(c.asLong(), graph()); - case F2L: - return ConstantNode.forLong((long) c.asFloat(), graph()); - case D2L: - return ConstantNode.forLong((long) c.asDouble(), graph()); - case UNSIGNED_I2L: - return ConstantNode.forLong(c.asInt() & 0xffffffffL, graph()); - case MOV_I2F: - return ConstantNode.forFloat(java.lang.Float.intBitsToFloat(c.asInt()), graph()); - case MOV_L2D: - return ConstantNode.forDouble(java.lang.Double.longBitsToDouble(c.asLong()), graph()); - case MOV_F2I: - return ConstantNode.forInt(java.lang.Float.floatToRawIntBits(c.asFloat()), graph()); - case MOV_D2L: - return ConstantNode.forLong(java.lang.Double.doubleToRawLongBits(c.asDouble()), graph()); - } + if (value.isConstant()) { + return ConstantNode.forPrimitive(evalConst(value.asConstant()), graph()); } return this; } @@ -235,7 +242,7 @@ } @Override - public void lower(LoweringTool tool, LoweringType loweringType) { + public void lower(LoweringTool tool) { tool.getRuntime().lower(this, tool); } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FixedBinaryNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FixedBinaryNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FixedBinaryNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -44,9 +44,4 @@ this.x = x; this.y = y; } - - @Override - public DeoptimizationReason getDeoptimizationReason() { - return DeoptimizationReason.ArithmeticException; - } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatAddNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatAddNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatAddNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -34,18 +34,23 @@ super(kind, x, y, isStrictFP); } + public Constant evalConst(Constant... inputs) { + assert inputs.length == 2; + if (kind() == Kind.Float) { + return Constant.forFloat(x().asConstant().asFloat() + y().asConstant().asFloat()); + } else { + assert kind() == Kind.Double; + return Constant.forDouble(x().asConstant().asDouble() + y().asConstant().asDouble()); + } + } + @Override public ValueNode canonical(CanonicalizerTool tool) { if (x().isConstant() && !y().isConstant()) { return graph().unique(new FloatAddNode(kind(), y(), x(), isStrictFP())); } if (x().isConstant()) { - if (kind() == Kind.Float) { - return ConstantNode.forFloat(x().asConstant().asFloat() + y().asConstant().asFloat(), graph()); - } else { - assert kind() == Kind.Double; - return ConstantNode.forDouble(x().asConstant().asDouble() + y().asConstant().asDouble(), graph()); - } + return ConstantNode.forPrimitive(evalConst(x().asConstant(), y().asConstant()), graph()); } else if (y().isConstant()) { if (kind() == Kind.Float) { float c = y().asConstant().asFloat(); diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatDivNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatDivNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatDivNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -34,19 +34,20 @@ super(kind, x, y, isStrictFP); } + public Constant evalConst(Constant... inputs) { + assert inputs.length == 2; + if (kind() == Kind.Float) { + return Constant.forFloat(x().asConstant().asFloat() / y().asConstant().asFloat()); + } else { + assert kind() == Kind.Double; + return Constant.forDouble(x().asConstant().asDouble() / y().asConstant().asDouble()); + } + } + @Override public ValueNode canonical(CanonicalizerTool tool) { if (x().isConstant() && y().isConstant()) { - if (kind() == Kind.Float) { - if (y().asConstant().asFloat() != 0) { - return ConstantNode.forFloat(x().asConstant().asFloat() / y().asConstant().asFloat(), graph()); - } - } else { - assert kind() == Kind.Double; - if (y().asConstant().asDouble() != 0) { - return ConstantNode.forDouble(x().asConstant().asDouble() / y().asConstant().asDouble(), graph()); - } - } + return ConstantNode.forPrimitive(evalConst(x().asConstant(), y().asConstant()), graph()); } return this; } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatMulNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatMulNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatMulNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -34,18 +34,23 @@ super(kind, x, y, isStrictFP); } + public Constant evalConst(Constant... inputs) { + assert inputs.length == 2; + if (kind() == Kind.Float) { + return Constant.forFloat(x().asConstant().asFloat() * y().asConstant().asFloat()); + } else { + assert kind() == Kind.Double; + return Constant.forDouble(x().asConstant().asDouble() * y().asConstant().asDouble()); + } + } + @Override public ValueNode canonical(CanonicalizerTool tool) { if (x().isConstant() && !y().isConstant()) { return graph().unique(new FloatMulNode(kind(), y(), x(), isStrictFP())); } if (x().isConstant()) { - if (kind() == Kind.Float) { - return ConstantNode.forFloat(x().asConstant().asFloat() * y().asConstant().asFloat(), graph()); - } else { - assert kind() == Kind.Double; - return ConstantNode.forDouble(x().asConstant().asDouble() * y().asConstant().asDouble(), graph()); - } + return ConstantNode.forPrimitive(evalConst(x().asConstant(), y().asConstant()), graph()); } return this; } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatRemNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatRemNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatRemNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -34,15 +34,20 @@ super(kind, x, y, isStrictFP); } + public Constant evalConst(Constant... inputs) { + assert inputs.length == 2; + if (kind() == Kind.Float) { + return Constant.forFloat(x().asConstant().asFloat() % y().asConstant().asFloat()); + } else { + assert kind() == Kind.Double; + return Constant.forDouble(x().asConstant().asDouble() % y().asConstant().asDouble()); + } + } + @Override public ValueNode canonical(CanonicalizerTool tool) { if (x().isConstant() && y().isConstant()) { - if (kind() == Kind.Float) { - return ConstantNode.forFloat(x().asConstant().asFloat() % y().asConstant().asFloat(), graph()); - } else { - assert kind() == Kind.Double; - return ConstantNode.forDouble(x().asConstant().asDouble() % y().asConstant().asDouble(), graph()); - } + return ConstantNode.forPrimitive(evalConst(x().asConstant(), y().asConstant()), graph()); } return this; } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatSubNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatSubNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatSubNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -34,18 +34,23 @@ super(kind, x, y, isStrictFP); } + public Constant evalConst(Constant... inputs) { + assert inputs.length == 2; + if (kind() == Kind.Float) { + return Constant.forFloat(x().asConstant().asFloat() - y().asConstant().asFloat()); + } else { + assert kind() == Kind.Double; + return Constant.forDouble(x().asConstant().asDouble() - y().asConstant().asDouble()); + } + } + @Override public ValueNode canonical(CanonicalizerTool tool) { if (x() == y()) { return ConstantNode.forFloatingKind(kind(), 0.0f, graph()); } if (x().isConstant() && y().isConstant()) { - if (kind() == Kind.Float) { - return ConstantNode.forFloat(x().asConstant().asFloat() - y().asConstant().asFloat(), graph()); - } else { - assert kind() == Kind.Double; - return ConstantNode.forDouble(x().asConstant().asDouble() - y().asConstant().asDouble(), graph()); - } + return ConstantNode.forPrimitive(evalConst(x().asConstant(), y().asConstant()), graph()); } else if (y().isConstant()) { if (kind() == Kind.Float) { float c = y().asConstant().asFloat(); diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatingNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatingNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatingNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -31,4 +31,9 @@ public FloatingNode(Stamp stamp) { super(stamp); } + + @Override + public FloatingNode asNode() { + return this; + } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerAddNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerAddNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerAddNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -41,6 +41,12 @@ } @Override + public Constant evalConst(Constant... inputs) { + assert inputs.length == 2; + return Constant.forIntegerKind(kind(), inputs[0].asLong() + inputs[1].asLong(), null); + } + + @Override public ValueNode canonical(CanonicalizerTool tool) { if (x().isConstant() && !y().isConstant()) { return graph().unique(new IntegerAddNode(kind(), y(), x())); @@ -60,12 +66,7 @@ } } if (x().isConstant()) { - if (kind() == Kind.Int) { - return ConstantNode.forInt(x().asConstant().asInt() + y().asConstant().asInt(), graph()); - } else { - assert kind() == Kind.Long; - return ConstantNode.forLong(x().asConstant().asLong() + y().asConstant().asLong(), graph()); - } + return ConstantNode.forPrimitive(evalConst(x().asConstant(), y().asConstant()), graph()); } else if (y().isConstant()) { long c = y().asConstant().asLong(); if (c == 0) { diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerDivNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerDivNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerDivNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -110,7 +110,7 @@ } @Override - public void lower(LoweringTool tool, LoweringType loweringType) { + public void lower(LoweringTool tool) { tool.getRuntime().lower(this, tool); } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerMulNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerMulNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerMulNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -36,17 +36,18 @@ } @Override + public Constant evalConst(Constant... inputs) { + assert inputs.length == 2; + return Constant.forIntegerKind(kind(), inputs[0].asLong() * inputs[1].asLong(), null); + } + + @Override public ValueNode canonical(CanonicalizerTool tool) { if (x().isConstant() && !y().isConstant()) { return graph().unique(new IntegerMulNode(kind(), y(), x())); } if (x().isConstant()) { - if (kind() == Kind.Int) { - return ConstantNode.forInt(x().asConstant().asInt() * y().asConstant().asInt(), graph()); - } else { - assert kind() == Kind.Long; - return ConstantNode.forLong(x().asConstant().asLong() * y().asConstant().asLong(), graph()); - } + return ConstantNode.forPrimitive(evalConst(x().asConstant(), y().asConstant()), graph()); } else if (y().isConstant()) { long c = y().asConstant().asLong(); if (c == 1) { diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerRemNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerRemNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerRemNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -61,7 +61,7 @@ } @Override - public void lower(LoweringTool tool, LoweringType loweringType) { + public void lower(LoweringTool tool) { tool.getRuntime().lower(this, tool); } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerSubNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerSubNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerSubNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -41,6 +41,12 @@ } @Override + public Constant evalConst(Constant... inputs) { + assert inputs.length == 2; + return Constant.forIntegerKind(kind(), inputs[0].asLong() - inputs[1].asLong(), null); + } + + @Override public ValueNode canonical(CanonicalizerTool tool) { if (x() == y()) { return ConstantNode.forIntegerKind(kind(), 0, graph()); @@ -80,12 +86,7 @@ } } if (x().isConstant() && y().isConstant()) { - if (kind() == Kind.Int) { - return ConstantNode.forInt(x().asConstant().asInt() - y().asConstant().asInt(), graph()); - } else { - assert kind() == Kind.Long; - return ConstantNode.forLong(x().asConstant().asLong() - y().asConstant().asLong(), graph()); - } + return ConstantNode.forPrimitive(evalConst(x().asConstant(), y().asConstant()), graph()); } else if (y().isConstant()) { long c = y().asConstant().asLong(); if (c == 0) { diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/LeftShiftNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/LeftShiftNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/LeftShiftNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -41,8 +41,21 @@ } @Override + public Constant evalConst(Constant... inputs) { + assert inputs.length == 2; + if (kind() == Kind.Int) { + return Constant.forInt(inputs[0].asInt() << inputs[1].asInt()); + } else { + assert kind() == Kind.Long; + return Constant.forLong(inputs[0].asLong() << inputs[1].asLong()); + } + } + + @Override public ValueNode canonical(CanonicalizerTool tool) { - if (y().isConstant()) { + if (x().isConstant() && y().isConstant()) { + return ConstantNode.forPrimitive(evalConst(x().asConstant(), y().asConstant()), graph()); + } else if (y().isConstant()) { int amount = y().asConstant().asInt(); int originalAmout = amount; int mask; @@ -53,14 +66,6 @@ mask = 0x3f; } amount &= mask; - if (x().isConstant()) { - if (kind() == Kind.Int) { - return ConstantNode.forInt(x().asConstant().asInt() << amount, graph()); - } else { - assert kind() == Kind.Long; - return ConstantNode.forLong(x().asConstant().asLong() << amount, graph()); - } - } if (amount == 0) { return x(); } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NegateNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NegateNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NegateNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -22,6 +22,8 @@ */ package com.oracle.graal.nodes.calc; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; @@ -52,19 +54,26 @@ this.x = x; } + public Constant evalConst(Constant... inputs) { + assert inputs.length == 1; + switch (inputs[0].getKind()) { + case Int: + return Constant.forInt(-inputs[0].asInt()); + case Long: + return Constant.forLong(-inputs[0].asLong()); + case Float: + return Constant.forFloat(-inputs[0].asFloat()); + case Double: + return Constant.forDouble(-inputs[0].asDouble()); + default: + throw GraalInternalError.shouldNotReachHere(); + } + } + @Override public ValueNode canonical(CanonicalizerTool tool) { if (x().isConstant()) { - switch (x().kind()) { - case Int: - return ConstantNode.forInt(-x().asConstant().asInt(), graph()); - case Long: - return ConstantNode.forLong(-x().asConstant().asLong(), graph()); - case Float: - return ConstantNode.forFloat(-x().asConstant().asFloat(), graph()); - case Double: - return ConstantNode.forDouble(-x().asConstant().asDouble(), graph()); - } + return ConstantNode.forPrimitive(evalConst(x.asConstant()), graph()); } if (x() instanceof NegateNode) { return ((NegateNode) x()).x(); diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NormalizeCompareNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NormalizeCompareNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NormalizeCompareNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -48,7 +48,7 @@ } @Override - public void lower(LoweringTool tool, LoweringType loweringType) { + public void lower(LoweringTool tool) { LogicNode equalComp; LogicNode lessComp; if (x().kind() == Kind.Double || x().kind() == Kind.Float) { diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NotNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NotNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NotNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -43,6 +43,12 @@ return updateStamp(StampTool.not(x().stamp())); } + @Override + public Constant evalConst(Constant... inputs) { + assert inputs.length == 1; + return Constant.forIntegerKind(kind(), ~inputs[0].asLong(), null); + } + /** * Creates new NegateNode instance. * @@ -57,12 +63,7 @@ @Override public ValueNode canonical(CanonicalizerTool tool) { if (x().isConstant()) { - switch (x().kind()) { - case Int: - return ConstantNode.forInt(~x().asConstant().asInt(), graph()); - case Long: - return ConstantNode.forLong(~x().asConstant().asLong(), graph()); - } + return ConstantNode.forPrimitive(evalConst(x().asConstant()), graph()); } if (x() instanceof NotNode) { return ((NotNode) x()).x(); diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/OrNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/OrNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/OrNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -41,6 +41,12 @@ } @Override + public Constant evalConst(Constant... inputs) { + assert inputs.length == 2; + return Constant.forIntegerKind(kind(), inputs[0].asLong() | inputs[1].asLong(), null); + } + + @Override public ValueNode canonical(CanonicalizerTool tool) { if (x() == y()) { return x(); @@ -49,12 +55,7 @@ return graph().unique(new OrNode(kind(), y(), x())); } if (x().isConstant()) { - if (kind() == Kind.Int) { - return ConstantNode.forInt(x().asConstant().asInt() | y().asConstant().asInt(), graph()); - } else { - assert kind() == Kind.Long; - return ConstantNode.forLong(x().asConstant().asLong() | y().asConstant().asLong(), graph()); - } + return ConstantNode.forPrimitive(evalConst(x().asConstant(), y().asConstant()), graph()); } else if (y().isConstant()) { if (kind() == Kind.Int) { int c = y().asConstant().asInt(); diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/RightShiftNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/RightShiftNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/RightShiftNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -36,11 +36,24 @@ } @Override + public Constant evalConst(Constant... inputs) { + assert inputs.length == 2; + if (kind() == Kind.Int) { + return Constant.forInt(inputs[0].asInt() >> inputs[1].asInt()); + } else { + assert kind() == Kind.Long; + return Constant.forLong(inputs[0].asLong() >> inputs[1].asLong()); + } + } + + @Override public ValueNode canonical(CanonicalizerTool tool) { if (x().stamp() instanceof IntegerStamp && ((IntegerStamp) x().stamp()).isPositive()) { return graph().unique(new UnsignedRightShiftNode(kind(), x(), y())); } - if (y().isConstant()) { + if (x().isConstant() && y().isConstant()) { + return ConstantNode.forPrimitive(evalConst(x().asConstant(), y().asConstant()), graph()); + } else if (y().isConstant()) { int amount = y().asConstant().asInt(); int originalAmout = amount; int mask; @@ -51,14 +64,6 @@ mask = 0x3f; } amount &= mask; - if (x().isConstant()) { - if (kind() == Kind.Int) { - return ConstantNode.forInt(x().asConstant().asInt() >> amount, graph()); - } else { - assert kind() == Kind.Long; - return ConstantNode.forLong(x().asConstant().asLong() >> amount, graph()); - } - } if (amount == 0) { return x(); } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedDivNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedDivNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedDivNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -62,7 +62,7 @@ } @Override - public void lower(LoweringTool tool, LoweringType loweringType) { + public void lower(LoweringTool tool) { tool.getRuntime().lower(this, tool); } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRemNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRemNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRemNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -61,7 +61,7 @@ } @Override - public void lower(LoweringTool tool, LoweringType loweringType) { + public void lower(LoweringTool tool) { tool.getRuntime().lower(this, tool); } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRightShiftNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRightShiftNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRightShiftNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -41,8 +41,21 @@ } @Override + public Constant evalConst(Constant... inputs) { + assert inputs.length == 2; + if (kind() == Kind.Int) { + return Constant.forInt(inputs[0].asInt() >>> inputs[1].asInt()); + } else { + assert kind() == Kind.Long; + return Constant.forLong(inputs[0].asLong() >>> inputs[1].asLong()); + } + } + + @Override public ValueNode canonical(CanonicalizerTool tool) { - if (y().isConstant()) { + if (x().isConstant() && y().isConstant()) { + return ConstantNode.forPrimitive(evalConst(x().asConstant(), y().asConstant()), graph()); + } else if (y().isConstant()) { int amount = y().asConstant().asInt(); int originalAmout = amount; int mask; @@ -53,14 +66,6 @@ mask = 0x3f; } amount &= mask; - if (x().isConstant()) { - if (kind() == Kind.Int) { - return ConstantNode.forInt(x().asConstant().asInt() >>> amount, graph()); - } else { - assert kind() == Kind.Long; - return ConstantNode.forLong(x().asConstant().asLong() >>> amount, graph()); - } - } if (amount == 0) { return x(); } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/XorNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/XorNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/XorNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -41,6 +41,12 @@ } @Override + public Constant evalConst(Constant... inputs) { + assert inputs.length == 2; + return Constant.forIntegerKind(kind(), inputs[0].asLong() ^ inputs[1].asLong(), null); + } + + @Override public ValueNode canonical(CanonicalizerTool tool) { if (x() == y()) { return ConstantNode.forIntegerKind(kind(), 0, graph()); @@ -49,12 +55,7 @@ return graph().unique(new XorNode(kind(), y(), x())); } if (x().isConstant()) { - if (kind() == Kind.Int) { - return ConstantNode.forInt(x().asConstant().asInt() ^ y().asConstant().asInt(), graph()); - } else { - assert kind() == Kind.Long; - return ConstantNode.forLong(x().asConstant().asLong() ^ y().asConstant().asLong(), graph()); - } + return ConstantNode.forPrimitive(evalConst(x().asConstant(), y().asConstant()), graph()); } else if (y().isConstant()) { if (kind() == Kind.Int) { int c = y().asConstant().asInt(); diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/ControlFlowGraph.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/ControlFlowGraph.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/ControlFlowGraph.java Wed Oct 02 13:26:31 2013 +0200 @@ -154,12 +154,10 @@ private void identifyBlocks() { // Find all block headers int numBlocks = 0; - for (Node node : graph.getNodes()) { - if (node instanceof AbstractBeginNode) { - Block block = new Block((AbstractBeginNode) node); - numBlocks++; - identifyBlock(block); - } + for (AbstractBeginNode begin : graph.getNodes(AbstractBeginNode.class)) { + Block block = new Block(begin); + numBlocks++; + identifyBlock(block); } // Compute postorder. diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/DynamicCounterNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/DynamicCounterNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/DynamicCounterNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -166,7 +166,7 @@ } @Override - public void lower(LoweringTool tool, LoweringType loweringType) { + public void lower(LoweringTool tool) { if (!enabled) { throw new GraalInternalError("counter nodes shouldn't exist when not enabled"); } @@ -183,6 +183,8 @@ graph().addBeforeFixed(this, load); graph().addBeforeFixed(this, store); + load.lower(tool); + store.lower(tool); } graph().removeFixed(this); } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AbstractCallNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AbstractCallNode.java Fri Sep 06 21:37:50 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,42 +0,0 @@ -/* - * 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.nodes.extended; - -import com.oracle.graal.graph.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.type.*; - -public abstract class AbstractCallNode extends AbstractStateSplit implements StateSplit { - - @Input private final NodeInputList arguments; - - public AbstractCallNode(Stamp stamp, ValueNode[] arguments) { - super(stamp); - this.arguments = new NodeInputList<>(this, arguments); - } - - public NodeInputList arguments() { - return arguments; - } - -} diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AccessNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AccessNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AccessNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -22,7 +22,6 @@ */ package com.oracle.graal.nodes.extended; -import com.oracle.graal.api.meta.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.type.*; @@ -78,21 +77,11 @@ } @Override - public AccessNode asNode() { - return this; - } - - @Override public boolean canDeoptimize() { return nullCheck; } @Override - public DeoptimizationReason getDeoptimizationReason() { - return DeoptimizationReason.NullCheckException; - } - - @Override public GuardingNode getGuard() { return guard; } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ArrayRangeWriteNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ArrayRangeWriteNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ArrayRangeWriteNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -22,14 +22,13 @@ */ package com.oracle.graal.nodes.extended; -import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.type.*; /** * Base class for nodes that modify a range of an array. */ -public abstract class ArrayRangeWriteNode extends AbstractStateSplit implements Node.IterableNodeType { +public abstract class ArrayRangeWriteNode extends AbstractStateSplit { protected ArrayRangeWriteNode(Stamp stamp) { super(stamp); diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BoxNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BoxNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BoxNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -53,7 +53,7 @@ } @Override - public void lower(LoweringTool tool, LoweringType loweringType) { + public void lower(LoweringTool tool) { tool.getRuntime().lower(this, tool); } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BranchProbabilityNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BranchProbabilityNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BranchProbabilityNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -123,7 +123,7 @@ } @Override - public void lower(LoweringTool tool, LoweringType loweringType) { + public void lower(LoweringTool tool) { throw new GraalInternalError("Branch probability could not be injected, because the probability value did not reduce to a constant value."); } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingAccessNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingAccessNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingAccessNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -22,7 +22,6 @@ */ package com.oracle.graal.nodes.extended; -import com.oracle.graal.api.meta.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.type.*; @@ -70,21 +69,11 @@ } @Override - public FloatingAccessNode asNode() { - return this; - } - - @Override public boolean canDeoptimize() { return nullCheck; } @Override - public DeoptimizationReason getDeoptimizationReason() { - return DeoptimizationReason.NullCheckException; - } - - @Override public FrameState getDeoptimizationState() { return deoptState; } @@ -100,6 +89,10 @@ return barrierType; } + public FrameState getState() { + return deoptState; + } + @Override public boolean isCompressible() { return compressible; diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -32,7 +32,7 @@ * A floating read of a value from memory specified in terms of an object base and an object * relative location. This node does not null check the object. */ -public final class FloatingReadNode extends FloatingAccessNode implements Node.IterableNodeType, LIRLowerable, Canonicalizable { +public final class FloatingReadNode extends FloatingAccessNode implements IterableNodeType, LIRLowerable, Canonicalizable { @Input private Node lastLocationAccess; @@ -53,6 +53,11 @@ return lastLocationAccess; } + public void setLastLocationAccess(Node newlla) { + updateUsages(lastLocationAccess, newlla); + lastLocationAccess = newlla; + } + @Override public void generate(LIRGeneratorTool gen) { Value address = location().generateAddress(gen, gen.operand(object())); diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ForeignCallNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ForeignCallNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ForeignCallNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -130,7 +130,12 @@ } @Override - public DeoptimizationReason getDeoptimizationReason() { - return null; + public FrameState getState() { + if (deoptState != null) { + assert stateAfter() == null; + return deoptState; + } else { + return super.getState(); + } } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadHubNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadHubNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadHubNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -58,8 +58,8 @@ } @Override - public void lower(LoweringTool tool, LoweringType loweringType) { - if (loweringType == LoweringType.AFTER_GUARDS) { + public void lower(LoweringTool tool) { + if (graph().getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS) { tool.getRuntime().lower(this, tool); } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadMethodNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadMethodNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadMethodNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -51,7 +51,7 @@ } @Override - public void lower(LoweringTool tool, LoweringType loweringType) { + public void lower(LoweringTool tool) { tool.getRuntime().lower(this, tool); } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/NullCheckNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/NullCheckNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/NullCheckNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -22,7 +22,6 @@ */ package com.oracle.graal.nodes.extended; -import com.oracle.graal.api.meta.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; @@ -49,14 +48,4 @@ public boolean canDeoptimize() { return true; } - - @Override - public DeoptimizationReason getDeoptimizationReason() { - return DeoptimizationReason.NullCheckException; - } - - @Override - public ValueNode asNode() { - return this; - } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/OSRLocalNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/OSRLocalNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/OSRLocalNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -27,7 +27,7 @@ import com.oracle.graal.nodes.type.*; @NodeInfo(nameTemplate = "OSRLocal({p#index})") -public class OSRLocalNode extends AbstractLocalNode implements Node.IterableNodeType { +public class OSRLocalNode extends AbstractLocalNode implements IterableNodeType { public OSRLocalNode(int index, Stamp stamp) { super(index, stamp); diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/OSRStartNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/OSRStartNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/OSRStartNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -29,7 +29,7 @@ public class OSRStartNode extends StartNode implements Lowerable { @Override - public void lower(LoweringTool tool, LoweringType loweringType) { + public void lower(LoweringTool tool) { tool.getRuntime().lower(this, tool); } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -23,7 +23,6 @@ package com.oracle.graal.nodes.extended; import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; @@ -32,7 +31,7 @@ /** * Reads an {@linkplain AccessNode accessed} value. */ -public final class ReadNode extends FloatableAccessNode implements Node.IterableNodeType, LIRLowerable, Canonicalizable, PiPushable, Virtualizable { +public final class ReadNode extends FloatableAccessNode implements LIRLowerable, Canonicalizable, PiPushable, Virtualizable { public ReadNode(ValueNode object, ValueNode location, Stamp stamp, BarrierType barrierType, boolean compressible) { super(object, location, stamp, barrierType, compressible); diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/StoreHubNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/StoreHubNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/StoreHubNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -46,7 +46,7 @@ } @Override - public void lower(LoweringTool tool, LoweringType loweringType) { + public void lower(LoweringTool tool) { tool.getRuntime().lower(this, tool); } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SwitchNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SwitchNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SwitchNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -170,10 +170,9 @@ } @Override - public SwitchNode clone(Graph into) { - SwitchNode newSwitch = (SwitchNode) super.clone(into); - newSwitch.keyProbabilities = Arrays.copyOf(keyProbabilities, keyProbabilities.length); - newSwitch.keySuccessors = Arrays.copyOf(keySuccessors, keySuccessors.length); - return newSwitch; + public void afterClone(Node other) { + SwitchNode oldSwitch = (SwitchNode) other; + keyProbabilities = Arrays.copyOf(oldSwitch.keyProbabilities, oldSwitch.keyProbabilities.length); + keySuccessors = Arrays.copyOf(oldSwitch.keySuccessors, oldSwitch.keySuccessors.length); } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnboxNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnboxNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnboxNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -48,7 +48,7 @@ } @Override - public void lower(LoweringTool tool, LoweringType loweringType) { + public void lower(LoweringTool tool) { tool.getRuntime().lower(this, tool); } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeArrayCastNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeArrayCastNode.java Fri Sep 06 21:37:50 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2012, 2012, 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.nodes.extended; - -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; - -/** - * The {@code UnsafeCastNode} produces the same value as its input, but with a different type. - */ -public final class UnsafeArrayCastNode extends UnsafeCastNode implements ArrayLengthProvider { - - @Input private ValueNode length; - - public ValueNode length() { - return length; - } - - public UnsafeArrayCastNode(ValueNode object, ValueNode length, Stamp stamp) { - super(object, stamp); - this.length = length; - } - - public UnsafeArrayCastNode(ValueNode object, ValueNode length, Stamp stamp, GuardingNode anchor) { - super(object, stamp, anchor); - this.length = length; - } - - private UnsafeArrayCastNode(ValueNode object, ValueNode length, Stamp stamp, ValueNode anchor) { - this(object, length, stamp, (GuardingNode) anchor); - } - - @Override - public ValueNode canonical(CanonicalizerTool tool) { - if (!(object() instanceof ArrayLengthProvider) || length() != ((ArrayLengthProvider) object()).length()) { - return this; - } - return super.canonical(tool); - } - - @NodeIntrinsic - public static native T unsafeArrayCast(Object object, int length, @ConstantNodeParameter Stamp stamp); - - @NodeIntrinsic - public static native T unsafeArrayCast(Object object, int length, @ConstantNodeParameter Stamp stamp, Object anchor); -} diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -23,25 +23,29 @@ package com.oracle.graal.nodes.extended; import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; /** - * The {@code UnsafeCastNode} produces the same value as its input, but with a different type. + * The {@code UnsafeCastNode} produces the same value as its input, but with a different type. It + * allows unsafe casts "sideways" in the type hierarchy. It does not allow to "drop" type + * information, i.e., an unsafe cast is removed if the input object has a more precise or equal type + * than the type this nodes casts to. */ -public class UnsafeCastNode extends PiNode implements Canonicalizable, LIRLowerable { +public class UnsafeCastNode extends FloatingGuardedNode implements LIRLowerable, GuardingNode, IterableNodeType, Canonicalizable, ValueProxy { + + @Input private ValueNode object; public UnsafeCastNode(ValueNode object, Stamp stamp) { - super(object, stamp); - } - - public UnsafeCastNode(ValueNode object, Stamp stamp, GuardingNode anchor) { - super(object, stamp, anchor); + super(stamp); + this.object = object; } public UnsafeCastNode(ValueNode object, Stamp stamp, ValueNode anchor) { - this(object, stamp, (GuardingNode) anchor); + super(stamp, (GuardingNode) anchor); + this.object = object; } public UnsafeCastNode(ValueNode object, ResolvedJavaType toType, boolean exactType, boolean nonNull) { @@ -49,66 +53,44 @@ } @Override - public boolean inferStamp() { - if (stamp() == StampFactory.forNodeIntrinsic()) { - return false; - } - if (stamp() instanceof ObjectStamp && object().stamp() instanceof ObjectStamp) { - return updateStamp(((ObjectStamp) object().stamp()).castTo((ObjectStamp) stamp())); - } - return false; + public ValueNode getOriginalValue() { + return object; } @Override public ValueNode canonical(CanonicalizerTool tool) { - if (kind() != object().kind()) { + assert kind() == Kind.Object && object.kind() == Kind.Object; + + ObjectStamp my = (ObjectStamp) stamp(); + ObjectStamp other = (ObjectStamp) object.stamp(); + + if (my.type() == null || other.type() == null) { + return this; + } + if (my.isExactType() && !other.isExactType()) { return this; } - - if (stamp() instanceof ObjectStamp && object().stamp() instanceof ObjectStamp) { - ObjectStamp my = (ObjectStamp) stamp(); - ObjectStamp other = (ObjectStamp) object().stamp(); - - if (my.type() == null || other.type() == null) { - return this; - } - if (my.isExactType() && !other.isExactType()) { - return this; - } - if (my.nonNull() && !other.nonNull()) { - return this; - } - if (!my.type().isAssignableFrom(other.type())) { - return this; - } + if (my.nonNull() && !other.nonNull()) { + return this; + } + if (!my.type().isAssignableFrom(other.type())) { + return this; } - return object(); + /* + * The unsafe cast does not add any new type information, so it can be removed. Note that + * this means that the unsafe cast cannot be used to "drop" type information (in which case + * it must not be canonicalized in any case). + */ + return object; } @Override public void generate(LIRGeneratorTool generator) { - if (kind() != object().kind()) { - assert generator.target().arch.getSizeInBytes(kind()) == generator.target().arch.getSizeInBytes(object().kind()) : "unsafe cast cannot be used to change the size of a value"; - AllocatableValue result = generator.newVariable(kind()); - generator.emitMove(result, generator.operand(object())); - generator.setResult(this, result); - } else { - // The LIR only cares about the kind of an operand, not the actual type of an object. So - // we do not have to - // introduce a new operand when the kind is the same. - generator.setResult(this, generator.operand(object())); - } - } - - @NodeIntrinsic - public static native T unsafeCast(Object object, @ConstantNodeParameter Stamp stamp); - - @NodeIntrinsic - public static native T unsafeCast(Object object, @ConstantNodeParameter Stamp stamp, GuardingNode anchor); - - @SuppressWarnings("unused") - @NodeIntrinsic - public static T unsafeCast(Object object, @ConstantNodeParameter Class toType, @ConstantNodeParameter boolean exactType, @ConstantNodeParameter boolean nonNull) { - return toType.cast(object); + assert kind() == Kind.Object && object.kind() == Kind.Object; + /* + * The LIR only cares about the kind of an operand, not the actual type of an object. So we + * do not have to introduce a new operand. + */ + generator.setResult(this, generator.operand(object)); } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeLoadNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeLoadNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeLoadNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -49,7 +49,7 @@ } @Override - public void lower(LoweringTool tool, LoweringType loweringType) { + public void lower(LoweringTool tool) { tool.getRuntime().lower(this, tool); } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -68,7 +68,7 @@ } @Override - public void lower(LoweringTool tool, LoweringType loweringType) { + public void lower(LoweringTool tool) { tool.getRuntime().lower(this, tool); } @@ -107,6 +107,10 @@ return unsafeStoreNode; } + public FrameState getState() { + return stateAfter; + } + // specialized on value type until boxing/unboxing is sorted out in intrinsification @SuppressWarnings("unused") diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ValueAnchorNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ValueAnchorNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ValueAnchorNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -22,8 +22,6 @@ */ package com.oracle.graal.nodes.extended; -import static com.oracle.graal.graph.iterators.NodePredicates.*; - import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @@ -32,82 +30,44 @@ /** * The ValueAnchor instruction keeps non-CFG (floating) nodes above a certain point in the graph. */ -public final class ValueAnchorNode extends FixedWithNextNode implements Canonicalizable, LIRLowerable, Node.IterableNodeType, Virtualizable, GuardingNode { - - @Input private final NodeInputList anchored; +public final class ValueAnchorNode extends FixedWithNextNode implements Canonicalizable, LIRLowerable, IterableNodeType, Virtualizable, GuardingNode { - public ValueAnchorNode(ValueNode... values) { - this(false, values); - } + @Input private ValueNode anchored; - public ValueAnchorNode(boolean permanent, ValueNode... values) { + public ValueAnchorNode(ValueNode value) { super(StampFactory.dependency()); - this.permanent = permanent; - this.anchored = new NodeInputList<>(this, values); + this.anchored = value; } - private boolean permanent; - @Override public void generate(LIRGeneratorTool gen) { // Nothing to emit, since this node is used for structural purposes only. } - public void addAnchoredNode(ValueNode value) { - if (!anchored.contains(value)) { - this.anchored.add(value); - } - } - - public void removeAnchoredNode(ValueNode value) { - this.anchored.remove(value); - } - - public NodeInputList getAnchoredNodes() { + public ValueNode getAnchoredNode() { return anchored; } - public void setPermanent(boolean permanent) { - this.permanent = permanent; - } - - public boolean isPermanent() { - return permanent; - } - @Override public ValueNode canonical(CanonicalizerTool tool) { - if (permanent) { + if (anchored != null && !anchored.isConstant() && !(anchored instanceof FixedNode)) { + // Found entry that needs this anchor. return this; } - if (this.predecessor() instanceof ValueAnchorNode) { - ValueAnchorNode previousAnchor = (ValueAnchorNode) this.predecessor(); - if (previousAnchor.usages().isEmpty()) { // avoid creating cycles - // transfer values and remove - for (ValueNode node : anchored.nonNull().distinct()) { - previousAnchor.addAnchoredNode(node); - } - return previousAnchor; - } + + if (usages().isNotEmpty()) { + // A not uses this anchor => anchor is necessary. + return this; } - for (Node node : anchored.nonNull().and(isNotA(FixedNode.class))) { - if (!(node instanceof ConstantNode)) { - return this; // still necessary - } - } - if (usages().isEmpty()) { - return null; // no node which require an anchor found - } - return this; + + // Anchor is not necessary any more => remove. + return null; } @Override public void virtualize(VirtualizerTool tool) { - if (permanent) { - return; - } - for (ValueNode node : anchored.nonNull().and(isNotA(AbstractBeginNode.class))) { - State state = tool.getObjectState(node); + if (anchored != null && !(anchored instanceof AbstractBeginNode)) { + State state = tool.getObjectState(anchored); if (state == null || state.getState() != EscapeState.Virtual) { return; } @@ -115,8 +75,8 @@ tool.delete(); } - @Override - public ValueNode asNode() { - return this; + public void removeAnchoredNode() { + this.updateUsages(anchored, null); + this.anchored = null; } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -23,7 +23,6 @@ package com.oracle.graal.nodes.extended; import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.LocationNode.Location; import com.oracle.graal.nodes.spi.*; @@ -33,7 +32,7 @@ /** * Writes a given {@linkplain #value() value} a {@linkplain AccessNode memory location}. */ -public final class WriteNode extends AccessNode implements StateSplit, LIRLowerable, MemoryCheckpoint.Single, Node.IterableNodeType, Virtualizable { +public final class WriteNode extends AccessNode implements StateSplit, LIRLowerable, MemoryCheckpoint.Single, Virtualizable { @Input private ValueNode value; @Input(notDataflow = true) private FrameState stateAfter; diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AbstractNewArrayNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AbstractNewArrayNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AbstractNewArrayNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -22,8 +22,6 @@ */ package com.oracle.graal.nodes.java; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; @@ -31,7 +29,7 @@ /** * The {@code AbstractNewArrayNode} is used for all 1-dimensional array allocations. */ -public class AbstractNewArrayNode extends DeoptimizingFixedWithNextNode implements Canonicalizable, Lowerable, ArrayLengthProvider, Node.IterableNodeType { +public class AbstractNewArrayNode extends DeoptimizingFixedWithNextNode implements Canonicalizable, Lowerable, ArrayLengthProvider { @Input private ValueNode length; private final boolean fillContents; @@ -88,7 +86,7 @@ } @Override - public void lower(LoweringTool tool, LoweringType loweringType) { + public void lower(LoweringTool tool) { tool.getRuntime().lower(this, tool); } @@ -96,9 +94,4 @@ public boolean canDeoptimize() { return true; } - - @Override - public DeoptimizationReason getDeoptimizationReason() { - return DeoptimizationReason.RuntimeConstraint; - } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessFieldNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessFieldNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessFieldNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -83,7 +83,7 @@ } @Override - public void lower(LoweringTool tool, LoweringType loweringType) { + public void lower(LoweringTool tool) { tool.getRuntime().lower(this, tool); } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessIndexedNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessIndexedNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessIndexedNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -64,7 +64,7 @@ } @Override - public void lower(LoweringTool tool, LoweringType loweringType) { + public void lower(LoweringTool tool) { tool.getRuntime().lower(this, tool); } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessMonitorNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessMonitorNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessMonitorNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -33,7 +33,7 @@ * The Java bytecode specification allows non-balanced locking. Graal does not handle such cases and * throws a {@link BailoutException} instead during graph building. */ -public abstract class AccessMonitorNode extends AbstractStateSplit implements StateSplit, MemoryCheckpoint { +public abstract class AccessMonitorNode extends AbstractStateSplit implements MemoryCheckpoint { @Input private ValueNode object; diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ArrayLengthNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ArrayLengthNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ArrayLengthNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -45,24 +45,40 @@ @Override public ValueNode canonical(CanonicalizerTool tool) { - if (array() instanceof ArrayLengthProvider) { - ValueNode length = ((ArrayLengthProvider) array()).length(); + ValueNode length = readArrayLength(array(), tool.runtime()); + if (length != null) { + return length; + } + return this; + } + + /** + * Gets the length of an array if possible. + * + * @param array an array + * @return a node representing the length of {@code array} or null if it is not available + */ + public static ValueNode readArrayLength(ValueNode array, MetaAccessProvider runtime) { + if (array instanceof ArrayLengthProvider) { + ValueNode length = ((ArrayLengthProvider) array).length(); if (length != null) { return length; } } - MetaAccessProvider runtime = tool.runtime(); - if (runtime != null && array().isConstant() && !array().isNullConstant()) { - Constant constantValue = array().asConstant(); + if (runtime != null && array.isConstant() && !array.isNullConstant()) { + Constant constantValue = array.asConstant(); if (constantValue != null && constantValue.isNonNull()) { - return ConstantNode.forInt(runtime.lookupArrayLength(constantValue), graph()); + Integer constantLength = runtime.lookupArrayLength(constantValue); + if (constantLength != null) { + return ConstantNode.forInt(constantLength, array.graph()); + } } } - return this; + return null; } @Override - public void lower(LoweringTool tool, LoweringType loweringType) { + public void lower(LoweringTool tool) { tool.getRuntime().lower(this, tool); } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastDynamicNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastDynamicNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastDynamicNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -23,7 +23,6 @@ package com.oracle.graal.nodes.java; import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; @@ -32,7 +31,7 @@ * Implements a type check where the type being checked is loaded at runtime. This is used, for * instance, to implement an object array store check. */ -public final class CheckCastDynamicNode extends FixedWithNextNode implements Canonicalizable, Lowerable, Node.IterableNodeType { +public final class CheckCastDynamicNode extends FixedWithNextNode implements Canonicalizable, Lowerable { @Input private ValueNode object; @Input private ValueNode hub; @@ -59,7 +58,7 @@ } @Override - public void lower(LoweringTool tool, LoweringType loweringType) { + public void lower(LoweringTool tool) { tool.getRuntime().lower(this, tool); } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -22,11 +22,10 @@ */ package com.oracle.graal.nodes.java; -import static com.oracle.graal.api.code.DeoptimizationAction.*; +import static com.oracle.graal.api.meta.DeoptimizationAction.*; import static com.oracle.graal.api.meta.DeoptimizationReason.*; import static com.oracle.graal.nodes.extended.BranchProbabilityNode.*; -import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.api.meta.ProfilingInfo.TriState; import com.oracle.graal.graph.*; @@ -38,7 +37,7 @@ /** * Implements a type check against a compile-time known type. */ -public final class CheckCastNode extends FixedWithNextNode implements Canonicalizable, Lowerable, Node.IterableNodeType, Virtualizable, ValueProxy { +public final class CheckCastNode extends FixedWithNextNode implements Canonicalizable, Lowerable, Virtualizable, ValueProxy { @Input private ValueNode object; private final ResolvedJavaType type; @@ -96,8 +95,8 @@ * {@code LoweringPhase.checkUsagesAreScheduled()}. */ @Override - public void lower(LoweringTool tool, LoweringType loweringType) { - InstanceOfNode typeTest = graph().add(new InstanceOfNode(type, object, profile)); + public void lower(LoweringTool tool) { + InstanceOfNode typeTest = graph().addWithoutUnique(new InstanceOfNode(type, object, profile)); Stamp stamp = StampFactory.declared(type); if (stamp() instanceof ObjectStamp && object().stamp() instanceof ObjectStamp) { stamp = ((ObjectStamp) object().stamp()).castTo((ObjectStamp) stamp); @@ -115,14 +114,16 @@ graph().addBeforeFixed(this, nullGuard); condition = typeTest; stamp = stamp.join(StampFactory.objectNonNull()); + nullGuard.lower(tool); } else { // TODO (ds) replace with probability of null-seen when available double shortCircuitProbability = NOT_FREQUENT_PROBABILITY; - condition = graph().unique(new ShortCircuitOrNode(graph().unique(new IsNullNode(object)), false, typeTest, false, shortCircuitProbability)); + condition = LogicNode.or(graph().unique(new IsNullNode(object)), typeTest, shortCircuitProbability); } } GuardingPiNode checkedObject = graph().add(new GuardingPiNode(object, condition, false, forStoreCheck ? ArrayStoreException : ClassCastException, InvalidateReprofile, stamp)); graph().replaceFixedWithFixed(this, checkedObject); + checkedObject.lower(tool); } @Override @@ -159,7 +160,7 @@ if (ObjectStamp.isObjectAlwaysNull(object())) { return object(); } - if (tool.assumptions().useOptimisticAssumptions()) { + if (tool.assumptions() != null && tool.assumptions().useOptimisticAssumptions()) { ResolvedJavaType exactType = type.findUniqueConcreteSubtype(); if (exactType != null && exactType != type) { // Propagate more precise type information to usages of the checkcast. diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CompareAndSwapNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CompareAndSwapNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CompareAndSwapNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -34,7 +34,7 @@ * Represents an atomic compare-and-swap operation The result is a boolean that contains whether the * value matched the expected value. */ -public class CompareAndSwapNode extends AbstractStateSplit implements StateSplit, Lowerable, MemoryCheckpoint.Single { +public class CompareAndSwapNode extends AbstractStateSplit implements Lowerable, MemoryCheckpoint.Single { @Input private ValueNode object; @Input private ValueNode offset; @@ -78,7 +78,7 @@ } @Override - public void lower(LoweringTool tool, LoweringType loweringType) { + public void lower(LoweringTool tool) { tool.getRuntime().lower(this, tool); } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ExceptionObjectNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ExceptionObjectNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ExceptionObjectNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -64,7 +64,7 @@ * runtime/interpreter would not have a valid location for the exception object to be rethrown. */ @Override - public void lower(LoweringTool tool, LoweringType loweringType) { + public void lower(LoweringTool tool) { if (isLowered()) { return; } @@ -89,6 +89,7 @@ graph().addAfterFixed(this, loadException); setStateAfter(null); setStamp(StampFactory.forVoid()); + loadException.lower(tool); } @Override diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfDynamicNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfDynamicNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfDynamicNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -50,7 +50,7 @@ } @Override - public void lower(LoweringTool tool, LoweringType loweringType) { + public void lower(LoweringTool tool) { tool.getRuntime().lower(this, tool); } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -51,7 +51,7 @@ } @Override - public void lower(LoweringTool tool, LoweringType loweringType) { + public void lower(LoweringTool tool) { tool.getRuntime().lower(this, tool); } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadExceptionObjectNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadExceptionObjectNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadExceptionObjectNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -44,7 +44,7 @@ } @Override - public void lower(LoweringTool tool, LoweringType loweringType) { + public void lower(LoweringTool tool) { tool.getRuntime().lower(this, tool); } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadFieldNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadFieldNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadFieldNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -36,7 +36,7 @@ * The {@code LoadFieldNode} represents a read of a static or instance field. */ @NodeInfo(nameTemplate = "LoadField#{p#field/s}") -public final class LoadFieldNode extends AccessFieldNode implements Canonicalizable, Node.IterableNodeType, VirtualizableRoot { +public final class LoadFieldNode extends AccessFieldNode implements Canonicalizable, IterableNodeType, VirtualizableRoot { /** * Creates a new LoadFieldNode instance. @@ -100,7 +100,7 @@ } constants[i] = constantValue; } - PhiNode newPhi = graph().add(new PhiNode(stamp(), phi.merge())); + PhiNode newPhi = graph().addWithoutUnique(new PhiNode(stamp(), phi.merge())); for (int i = 0; i < phi.valueCount(); i++) { newPhi.addInput(ConstantNode.forConstant(constants[i], runtime, graph())); } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadIndexedNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadIndexedNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadIndexedNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -31,7 +31,7 @@ /** * The {@code LoadIndexedNode} represents a read from an element of an array. */ -public final class LoadIndexedNode extends AccessIndexedNode implements Node.IterableNodeType, Virtualizable { +public final class LoadIndexedNode extends AccessIndexedNode implements IterableNodeType, Virtualizable { /** * Creates a new LoadIndexedNode. diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoweredCompareAndSwapNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoweredCompareAndSwapNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoweredCompareAndSwapNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -23,7 +23,6 @@ package com.oracle.graal.nodes.java; import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; @@ -32,7 +31,7 @@ /** * Represents the lowered version of an atomic compare-and-swap operation{@code CompareAndSwapNode}. */ -public class LoweredCompareAndSwapNode extends AccessNode implements StateSplit, LIRLowerable, MemoryCheckpoint.Single, Node.IterableNodeType { +public class LoweredCompareAndSwapNode extends AccessNode implements StateSplit, LIRLowerable, MemoryCheckpoint.Single { @Input private ValueNode expectedValue; @Input private ValueNode newValue; diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -30,7 +30,7 @@ import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; -public class MethodCallTargetNode extends CallTargetNode implements Node.IterableNodeType, Canonicalizable { +public class MethodCallTargetNode extends CallTargetNode implements IterableNodeType, Canonicalizable { public enum InvokeKind { Interface, Special, Static, Virtual diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorEnterNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorEnterNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorEnterNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -50,7 +50,7 @@ } @Override - public void lower(LoweringTool tool, LoweringType loweringType) { + public void lower(LoweringTool tool) { tool.getRuntime().lower(this, tool); } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorExitNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorExitNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MonitorExitNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -31,7 +31,7 @@ /** * The {@code MonitorEnterNode} represents a monitor release. */ -public final class MonitorExitNode extends AccessMonitorNode implements Virtualizable, Lowerable, Node.IterableNodeType, MonitorExit, MemoryCheckpoint.Single, MonitorReference { +public final class MonitorExitNode extends AccessMonitorNode implements Virtualizable, Lowerable, IterableNodeType, MonitorExit, MemoryCheckpoint.Single, MonitorReference { private int lockDepth; @@ -51,7 +51,7 @@ } @Override - public void lower(LoweringTool tool, LoweringType loweringType) { + public void lower(LoweringTool tool) { tool.getRuntime().lower(this, tool); } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewInstanceNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewInstanceNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewInstanceNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -33,7 +33,7 @@ * The {@code NewInstanceNode} represents the allocation of an instance class object. */ @NodeInfo(nameTemplate = "New {p#instanceClass/s}") -public final class NewInstanceNode extends DeoptimizingFixedWithNextNode implements Node.IterableNodeType, Canonicalizable, Lowerable, VirtualizableAllocation { +public final class NewInstanceNode extends DeoptimizingFixedWithNextNode implements Canonicalizable, Lowerable, VirtualizableAllocation { private final ResolvedJavaType instanceClass; private final boolean fillContents; @@ -77,7 +77,7 @@ } @Override - public void lower(LoweringTool tool, LoweringType loweringType) { + public void lower(LoweringTool tool) { tool.getRuntime().lower(this, tool); } @@ -100,9 +100,4 @@ public boolean canDeoptimize() { return true; } - - @Override - public DeoptimizationReason getDeoptimizationReason() { - return DeoptimizationReason.RuntimeConstraint; - } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewMultiArrayNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewMultiArrayNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewMultiArrayNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -62,7 +62,7 @@ } @Override - public void lower(LoweringTool tool, LoweringType loweringType) { + public void lower(LoweringTool tool) { tool.getRuntime().lower(this, tool); } @@ -74,9 +74,4 @@ public boolean canDeoptimize() { return true; } - - @Override - public DeoptimizationReason getDeoptimizationReason() { - return DeoptimizationReason.RuntimeConstraint; - } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -32,7 +32,7 @@ * This node is used to perform the finalizer registration at the end of the java.lang.Object * constructor. */ -public final class RegisterFinalizerNode extends AbstractStateSplit implements StateSplit, Canonicalizable, LIRLowerable, Virtualizable, DeoptimizingNode { +public final class RegisterFinalizerNode extends AbstractStateSplit implements Canonicalizable, LIRLowerable, Virtualizable, DeoptimizingNode { public static final ForeignCallDescriptor REGISTER_FINALIZER = new ForeignCallDescriptor("registerFinalizer", void.class, Object.class); @@ -105,11 +105,6 @@ deoptState = f; } - @Override - public DeoptimizationReason getDeoptimizationReason() { - return null; - } - @SuppressWarnings("unused") @NodeIntrinsic public static void register(Object thisObj) { diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/SelfReplacingMethodCallTargetNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/SelfReplacingMethodCallTargetNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/SelfReplacingMethodCallTargetNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -28,7 +28,7 @@ import com.oracle.graal.api.meta.ResolvedJavaMethod; import com.oracle.graal.graph.GraalInternalError; import com.oracle.graal.graph.NodeInputList; -import com.oracle.graal.nodes.ValueNode; +import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.LIRGeneratorTool; import com.oracle.graal.nodes.spi.Lowerable; import com.oracle.graal.nodes.spi.LoweringTool; @@ -68,7 +68,7 @@ } @Override - public void lower(LoweringTool tool, LoweringType loweringType) { + public void lower(LoweringTool tool) { InvokeKind invokeKind = Modifier.isStatic(replacementTargetMethod.getModifiers()) ? InvokeKind.Static : InvokeKind.Special; MethodCallTargetNode replacement = graph().add( new MethodCallTargetNode(invokeKind, replacementTargetMethod, replacementArguments.toArray(new ValueNode[replacementArguments.size()]), replacementReturnType)); diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreFieldNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreFieldNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreFieldNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -79,4 +79,8 @@ } } } + + public FrameState getState() { + return stateAfter; + } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreIndexedNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreIndexedNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreIndexedNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -81,4 +81,8 @@ } } } + + public FrameState getState() { + return stateAfter; + } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/DelegatingGraalCodeCacheProvider.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/DelegatingGraalCodeCacheProvider.java Wed Oct 02 13:26:31 2013 +0200 @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2011, 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.nodes.spi; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.extended.*; + +/** + * A {@link GraalCodeCacheProvider} that delegates to another {@link GraalCodeCacheProvider}. + */ +public class DelegatingGraalCodeCacheProvider extends DelegatingCodeCacheProvider implements GraalCodeCacheProvider { + + public DelegatingGraalCodeCacheProvider(CodeCacheProvider delegate) { + super(delegate); + } + + @Override + protected GraalCodeCacheProvider delegate() { + return (GraalCodeCacheProvider) super.delegate(); + } + + public InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult compResult, Graph graph) { + return delegate().addMethod(method, compResult, graph); + } + + public void lower(Node n, LoweringTool tool) { + delegate().lower(n, tool); + } + + public ValueNode reconstructArrayIndex(LocationNode location) { + return delegate().reconstructArrayIndex(location); + } +} diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java Wed Oct 02 13:26:31 2013 +0200 @@ -63,7 +63,7 @@ void emitMembar(int barriers); - void emitDeoptimize(DeoptimizationAction action, DeoptimizingNode deopting); + void emitDeoptimize(Value actionAndReason, DeoptimizingNode deopting); void emitNullCheck(ValueNode v, DeoptimizingNode deopting); diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/Lowerable.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/Lowerable.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/Lowerable.java Wed Oct 02 13:26:31 2013 +0200 @@ -22,11 +22,19 @@ */ package com.oracle.graal.nodes.spi; +import com.oracle.graal.nodes.*; + +/** + * Interface implemented by nodes that can replace themselves with lower level nodes during a phase + * that transforms a graph to replace higher level nodes with lower level nodes. + */ public interface Lowerable { - public enum LoweringType { - BEFORE_GUARDS, AFTER_GUARDS, AFTER_FSA - } + /** + * Expand this node into lower level nodes expressing the same semantics. If the introduced + * nodes are themselves lowerable, they should be recursively lowered as part of this call. + */ + void lower(LoweringTool tool); - void lower(LoweringTool tool, LoweringType loweringType); + ValueNode asNode(); } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LoweringTool.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LoweringTool.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LoweringTool.java Wed Oct 02 13:26:31 2013 +0200 @@ -28,14 +28,11 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.cfg.*; import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.spi.Lowerable.LoweringType; public interface LoweringTool { GraalCodeCacheProvider getRuntime(); - LoweringType getLoweringType(); - Replacements getReplacements(); GuardingNode createNullCheckGuard(GuardedNode guardedNode, ValueNode object); diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/NodeWithState.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/NodeWithState.java Wed Oct 02 13:26:31 2013 +0200 @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2013, 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.nodes.spi; + +import com.oracle.graal.nodes.*; + +public interface NodeWithState { + FrameState getState(); +} diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/IntegerStamp.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/IntegerStamp.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/IntegerStamp.java Wed Oct 02 13:26:31 2013 +0200 @@ -22,6 +22,8 @@ */ package com.oracle.graal.nodes.type; +import java.util.*; + import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; @@ -133,10 +135,12 @@ str.append(" [").append(lowerBound).append(" - ").append(upperBound).append(']'); } if (downMask != 0) { - str.append(" \u21ca").append(Long.toHexString(downMask)); + str.append(" \u21ca"); + new Formatter(str).format("%016x", downMask); } if (upMask != defaultMask(kind())) { - str.append(" \u21c8").append(Long.toHexString(upMask)); + str.append(" \u21c8"); + new Formatter(str).format("%016x", upMask); } return str.toString(); } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampFactory.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampFactory.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampFactory.java Wed Oct 02 13:26:31 2013 +0200 @@ -22,8 +22,6 @@ */ package com.oracle.graal.nodes.type; -import com.oracle.graal.api.code.*; - import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.type.GenericStamp.GenericStampType; @@ -43,7 +41,6 @@ private static final Stamp conditionStamp = new GenericStamp(GenericStampType.Condition); private static final Stamp voidStamp = new GenericStamp(GenericStampType.Void); private static final Stamp nodeIntrinsicStamp = new ObjectStamp(null, false, false, false); - private static final Stamp wordStamp = new ObjectStamp(null, false, false, false); private static final Stamp positiveInt = forInteger(Kind.Int, 0, Integer.MAX_VALUE, 0, Integer.MAX_VALUE); private static void setCache(Kind kind, Stamp stamp) { @@ -85,14 +82,6 @@ return nodeIntrinsicStamp; } - /** - * A stamp used only in the graph of intrinsics, e.g., snippets. It is then replaced by the - * actual primitive type stamp for the target-specific {@link TargetDescription#wordKind}. - */ - public static Stamp forWord() { - return wordStamp; - } - public static Stamp intValue() { return forKind(Kind.Int); } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/CommitAllocationNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/CommitAllocationNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/CommitAllocationNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -31,7 +31,7 @@ import com.oracle.graal.nodes.type.*; @NodeInfo(nameTemplate = "Alloc {i#virtualObjects}") -public final class CommitAllocationNode extends FixedWithNextNode implements VirtualizableAllocation, Lowerable, Node.IterableNodeType, Simplifiable { +public final class CommitAllocationNode extends FixedWithNextNode implements VirtualizableAllocation, Lowerable, Simplifiable { @Input private final NodeInputList virtualObjects = new NodeInputList<>(this); @Input private final NodeInputList values = new NodeInputList<>(this); @@ -55,7 +55,7 @@ @Override public boolean verify() { - assertTrue(virtualObjects.size() == locks.size(), "lockCounts size doesn't match"); + assertTrue(virtualObjects.size() == locks.size(), "lockCounts size doesn't match " + virtualObjects + ", " + locks); int valueCount = 0; for (VirtualObjectNode virtual : virtualObjects) { valueCount += virtual.entryCount(); @@ -65,15 +65,13 @@ } @Override - public void lower(LoweringTool tool, LoweringType loweringType) { + public void lower(LoweringTool tool) { tool.getRuntime().lower(this, tool); } @Override - public Node clone(Graph into) { - CommitAllocationNode clone = (CommitAllocationNode) super.clone(into); - clone.locks = new ArrayList<>(locks); - return clone; + public void afterClone(Node other) { + locks = new ArrayList<>(((CommitAllocationNode) other).locks); } @Override diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/EscapeObjectState.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/EscapeObjectState.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/EscapeObjectState.java Wed Oct 02 13:26:31 2013 +0200 @@ -25,7 +25,7 @@ import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; -public abstract class EscapeObjectState extends VirtualState implements Node.IterableNodeType { +public abstract class EscapeObjectState extends VirtualState implements IterableNodeType { @Input private VirtualObjectNode object; diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -28,7 +28,7 @@ import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; -public abstract class VirtualObjectNode extends ValueNode implements LIRLowerable, Node.IterableNodeType { +public abstract class VirtualObjectNode extends ValueNode implements LIRLowerable, IterableNodeType { private boolean hasIdentity; diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java Wed Oct 02 13:26:31 2013 +0200 @@ -31,24 +31,25 @@ import com.oracle.graal.graph.Graph.NodeChangedListener; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; -import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.util.*; import com.oracle.graal.phases.*; +import com.oracle.graal.phases.PhasePlan.PhasePosition; import com.oracle.graal.phases.tiers.*; public class CanonicalizerPhase extends BasePhase { private static final int MAX_ITERATION_PER_NODE = 10; private static final DebugMetric METRIC_CANONICALIZED_NODES = Debug.metric("CanonicalizedNodes"); + private static final DebugMetric METRIC_PROCESSED_NODES = Debug.metric("ProcessedNodes"); private static final DebugMetric METRIC_CANONICALIZATION_CONSIDERED_NODES = Debug.metric("CanonicalizationConsideredNodes"); private static final DebugMetric METRIC_INFER_STAMP_CALLED = Debug.metric("InferStampCalled"); private static final DebugMetric METRIC_STAMP_CHANGED = Debug.metric("StampChanged"); private static final DebugMetric METRIC_SIMPLIFICATION_CONSIDERED_NODES = Debug.metric("SimplificationConsideredNodes"); - public static final DebugMetric METRIC_GLOBAL_VALUE_NUMBERING_HITS = Debug.metric("GlobalValueNumberingHits"); + private static final DebugMetric METRIC_GLOBAL_VALUE_NUMBERING_HITS = Debug.metric("GlobalValueNumberingHits"); private final boolean canonicalizeReads; + private final CustomCanonicalizer customCanonicalizer; public interface CustomCanonicalizer { @@ -56,15 +57,57 @@ } public CanonicalizerPhase(boolean canonicalizeReads) { + this(canonicalizeReads, null); + } + + public CanonicalizerPhase(boolean canonicalizeReads, CustomCanonicalizer customCanonicalizer) { this.canonicalizeReads = canonicalizeReads; + this.customCanonicalizer = customCanonicalizer; } @Override protected void run(StructuredGraph graph, PhaseContext context) { - new Instance(context.getRuntime(), context.getAssumptions(), canonicalizeReads).run(graph); + new Instance(context.getRuntime(), context.getAssumptions(), canonicalizeReads, customCanonicalizer).run(graph); + } + + /** + * @param newNodesMark only the {@linkplain Graph#getNewNodes(int) new nodes} specified by this + * mark are processed + */ + public void applyIncremental(StructuredGraph graph, PhaseContext context, int newNodesMark) { + applyIncremental(graph, context, newNodesMark, true); + } + + public void applyIncremental(StructuredGraph graph, PhaseContext context, int newNodesMark, boolean dumpGraph) { + new Instance(context.getRuntime(), context.getAssumptions(), canonicalizeReads, newNodesMark, customCanonicalizer).apply(graph, dumpGraph); } - public static class Instance extends Phase { + /** + * @param workingSet the initial working set of nodes on which the canonicalizer works, should + * be an auto-grow node bitmap + */ + public void applyIncremental(StructuredGraph graph, PhaseContext context, Iterable workingSet) { + applyIncremental(graph, context, workingSet, true); + } + + public void applyIncremental(StructuredGraph graph, PhaseContext context, Iterable workingSet, boolean dumpGraph) { + new Instance(context.getRuntime(), context.getAssumptions(), canonicalizeReads, workingSet, customCanonicalizer).apply(graph, dumpGraph); + } + + public void applyIncremental(StructuredGraph graph, PhaseContext context, Iterable workingSet, int newNodesMark) { + applyIncremental(graph, context, workingSet, newNodesMark, true); + } + + public void applyIncremental(StructuredGraph graph, PhaseContext context, Iterable workingSet, int newNodesMark, boolean dumpGraph) { + new Instance(context.getRuntime(), context.getAssumptions(), canonicalizeReads, workingSet, newNodesMark, customCanonicalizer).apply(graph, dumpGraph); + } + + @Deprecated + public void addToPhasePlan(PhasePlan plan, PhaseContext context) { + plan.addPhase(PhasePosition.AFTER_PARSING, new Instance(context.getRuntime(), context.getAssumptions(), canonicalizeReads, customCanonicalizer)); + } + + private static final class Instance extends Phase { private final int newNodesMark; private final Assumptions assumptions; @@ -76,34 +119,19 @@ private NodeWorkList workList; private Tool tool; - public Instance(MetaAccessProvider runtime, Assumptions assumptions, boolean canonicalizeReads) { - this(runtime, assumptions, canonicalizeReads, null, 0, null); + private Instance(MetaAccessProvider runtime, Assumptions assumptions, boolean canonicalizeReads, CustomCanonicalizer customCanonicalizer) { + this(runtime, assumptions, canonicalizeReads, null, 0, customCanonicalizer); } - /** - * @param runtime - * @param assumptions - * @param workingSet the initial working set of nodes on which the canonicalizer works, - * should be an auto-grow node bitmap - * @param customCanonicalizer - * @param canonicalizeReads flag to indicate if - * {@link LoadFieldNode#canonical(CanonicalizerTool)} and - * {@link ReadNode#canonical(CanonicalizerTool)} should canonicalize reads of - * constant fields. - */ - public Instance(MetaAccessProvider runtime, Assumptions assumptions, boolean canonicalizeReads, Iterable workingSet, CustomCanonicalizer customCanonicalizer) { + private Instance(MetaAccessProvider runtime, Assumptions assumptions, boolean canonicalizeReads, Iterable workingSet, CustomCanonicalizer customCanonicalizer) { this(runtime, assumptions, canonicalizeReads, workingSet, 0, customCanonicalizer); } - /** - * @param newNodesMark only the {@linkplain Graph#getNewNodes(int) new nodes} specified by - * this mark are processed otherwise all nodes in the graph are processed - */ - public Instance(MetaAccessProvider runtime, Assumptions assumptions, boolean canonicalizeReads, int newNodesMark, CustomCanonicalizer customCanonicalizer) { + private Instance(MetaAccessProvider runtime, Assumptions assumptions, boolean canonicalizeReads, int newNodesMark, CustomCanonicalizer customCanonicalizer) { this(runtime, assumptions, canonicalizeReads, null, newNodesMark, customCanonicalizer); } - public Instance(MetaAccessProvider runtime, Assumptions assumptions, boolean canonicalizeReads, Iterable workingSet, int newNodesMark, CustomCanonicalizer customCanonicalizer) { + private Instance(MetaAccessProvider runtime, Assumptions assumptions, boolean canonicalizeReads, Iterable workingSet, int newNodesMark, CustomCanonicalizer customCanonicalizer) { super("Canonicalizer"); this.newNodesMark = newNodesMark; this.assumptions = assumptions; @@ -160,14 +188,13 @@ if (!tryCanonicalize(node)) { if (node instanceof ValueNode) { ValueNode valueNode = (ValueNode) node; - if (tryInferStamp(valueNode)) { - Constant constant = valueNode.stamp().asConstant(); - if (constant != null) { - performReplacement(valueNode, ConstantNode.forConstant(constant, runtime, valueNode.graph())); - } else { - // the improved stamp may enable additional canonicalization - tryCanonicalize(valueNode); - } + boolean improvedStamp = tryInferStamp(valueNode); + Constant constant = valueNode.stamp().asConstant(); + if (constant != null && !(node instanceof ConstantNode)) { + performReplacement(valueNode, ConstantNode.forConstant(constant, runtime, valueNode.graph())); + } else if (improvedStamp) { + // the improved stamp may enable additional canonicalization + tryCanonicalize(valueNode); } } } @@ -188,7 +215,8 @@ } public static boolean tryGlobalValueNumbering(Node node) { - if (node.getNodeClass().valueNumberable()) { + NodeClass nodeClass = node.getNodeClass(); + if (nodeClass.valueNumberable() && !nodeClass.isLeafNode()) { Node newNode = node.graph().findDuplicate(node); if (newNode != null) { assert !(node instanceof FixedNode || newNode instanceof FixedNode); @@ -248,6 +276,8 @@ // -------------------------------------------- // Fixed-connected| 2 | X | 6 | // -------------------------------------------- +// ControlSink| X | X | 7 | +// -------------------------------------------- // X: must not happen (checked with assertions) // @formatter:on private boolean performReplacement(final Node node, ValueNode canonical) { @@ -272,9 +302,16 @@ assert node instanceof FixedWithNextNode && node.predecessor() != null : node + " -> " + canonical + " : node should be fixed & connected (" + node.predecessor() + ")"; FixedWithNextNode fixedWithNext = (FixedWithNextNode) node; - // When removing a fixed node, new canonicalization opportunities for its -// successor - // may arise + if (canonical instanceof ControlSinkNode) { + // case 7 + FixedWithNextNode pred = (FixedWithNextNode) node.predecessor(); + GraphUtil.killCFG(fixedWithNext); + pred.setNext((FixedNode) canonical); + return true; + } + + // When removing a fixed node, new canonicalization + // opportunities for its successor may arise assert fixedWithNext.next() != null; tool.addToWorkList(fixedWithNext.next()); diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java Wed Oct 02 13:26:31 2013 +0200 @@ -258,6 +258,14 @@ metricTypeRegistered.increment(); } } + + public void clear() { + knownTypes.clear(); + knownNonNull.clear(); + knownNull.clear(); + trueConditions.clear(); + falseConditions.clear(); + } } public static ResolvedJavaType widen(ResolvedJavaType a, ResolvedJavaType b) { @@ -355,6 +363,9 @@ private void registerControlSplitInfo(Node pred, AbstractBeginNode begin) { assert pred != null && begin != null; + if (begin instanceof LoopExitNode) { + state.clear(); + } if (pred instanceof IfNode) { IfNode ifNode = (IfNode) pred; @@ -494,15 +505,15 @@ } ValueAnchorNode anchor = null; if (replacementAnchor == null) { - anchor = graph.add(new ValueAnchorNode()); + anchor = graph.add(new ValueAnchorNode(null)); replacementAnchor = anchor; } PiNode piNode; if (isNull) { ConstantNode nullObject = ConstantNode.forObject(null, metaAccessProvider, graph); - piNode = graph.unique(new PiNode(nullObject, StampFactory.forConstant(nullObject.value, metaAccessProvider), replacementAnchor)); + piNode = graph.unique(new PiNode(nullObject, StampFactory.forConstant(nullObject.value, metaAccessProvider), replacementAnchor.asNode())); } else { - piNode = graph.unique(new PiNode(object, StampFactory.declared(type, nonNull), replacementAnchor)); + piNode = graph.unique(new PiNode(object, StampFactory.declared(type, nonNull), replacementAnchor.asNode())); } checkCast.replaceAtUsages(piNode); if (anchor != null) { diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/DeoptimizationGroupingPhase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/DeoptimizationGroupingPhase.java Wed Oct 02 13:26:31 2013 +0200 @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2013, 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.phases.common; + +import java.util.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.cfg.*; +import com.oracle.graal.phases.*; +import com.oracle.graal.phases.tiers.*; + +/** + * This phase tries to find {@link AbstractDeoptimizeNode DeoptimizeNodes} which use the same + * {@link FrameState} and merges them together. + */ +public class DeoptimizationGroupingPhase extends BasePhase { + + @Override + protected void run(StructuredGraph graph, MidTierContext context) { + ControlFlowGraph cfg = null; + for (FrameState fs : graph.getNodes(FrameState.class)) { + FixedNode target = null; + PhiNode phi = null; + List obsoletes = null; + for (AbstractDeoptimizeNode deopt : fs.usages().filter(AbstractDeoptimizeNode.class)) { + if (target == null) { + target = deopt; + } else { + if (cfg == null) { + cfg = ControlFlowGraph.compute(graph, true, true, false, false); + } + MergeNode merge; + if (target instanceof AbstractDeoptimizeNode) { + merge = graph.add(new MergeNode()); + EndNode firstEnd = graph.add(new EndNode()); + phi = graph.addWithoutUnique(new PhiNode(Kind.Int, merge)); + merge.addForwardEnd(firstEnd); + phi.addInput(((AbstractDeoptimizeNode) target).getActionAndReason(context.getRuntime())); + target.predecessor().replaceFirstSuccessor(target, firstEnd); + + exitLoops((AbstractDeoptimizeNode) target, firstEnd, cfg); + + merge.setNext(graph.add(new DynamicDeoptimizeNode(phi))); + obsoletes = new LinkedList<>(); + obsoletes.add((AbstractDeoptimizeNode) target); + target = merge; + } else { + merge = (MergeNode) target; + } + EndNode newEnd = graph.add(new EndNode()); + merge.addForwardEnd(newEnd); + phi.addInput(deopt.getActionAndReason(context.getRuntime())); + deopt.predecessor().replaceFirstSuccessor(deopt, newEnd); + exitLoops(deopt, newEnd, cfg); + obsoletes.add(deopt); + } + } + if (obsoletes != null) { + ((DynamicDeoptimizeNode) ((MergeNode) target).next()).setDeoptimizationState(fs); + for (AbstractDeoptimizeNode obsolete : obsoletes) { + obsolete.safeDelete(); + } + } + } + } + + private static void exitLoops(AbstractDeoptimizeNode deopt, EndNode end, ControlFlowGraph cfg) { + Block block = cfg.blockFor(deopt); + Loop loop = block.getLoop(); + while (loop != null) { + end.graph().addBeforeFixed(end, end.graph().add(new LoopExitNode(loop.loopBegin()))); + loop = loop.parent; + } + } +} diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/EliminatePartiallyRedundantGuardsPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/EliminatePartiallyRedundantGuardsPhase.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/EliminatePartiallyRedundantGuardsPhase.java Wed Oct 02 13:26:31 2013 +0200 @@ -25,7 +25,6 @@ import java.util.*; import java.util.Map.*; -import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; @@ -133,7 +132,7 @@ } Graph graph = merge.graph(); for (GuardNode guard : hits) { - PhiNode phi = graph.add(new PhiNode(PhiType.Guard, merge, null)); + PhiNode phi = graph.addWithoutUnique(new PhiNode(PhiType.Guard, merge, null)); for (AbstractEndNode otherEnd : merge.forwardEnds()) { phi.addInput(graph.unique(new GuardNode(guard.condition(), AbstractBeginNode.prevBegin(otherEnd), guard.reason(), guard.action(), guard.negated()))); } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ExpandLogicPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ExpandLogicPhase.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ExpandLogicPhase.java Wed Oct 02 13:26:31 2013 +0200 @@ -31,33 +31,21 @@ @Override protected void run(StructuredGraph graph) { - for (ShortCircuitBooleanNode logic : graph.getNodes(ShortCircuitBooleanNode.class)) { + for (ShortCircuitOrNode logic : graph.getNodes(ShortCircuitOrNode.class)) { processBinary(logic); } - assert graph.getNodes(ShortCircuitBooleanNode.class).isEmpty(); + assert graph.getNodes(ShortCircuitOrNode.class).isEmpty(); } - private static void processBinary(ShortCircuitBooleanNode binary) { + private static void processBinary(ShortCircuitOrNode binary) { while (binary.usages().isNotEmpty()) { Node usage = binary.usages().first(); - if (usage instanceof ShortCircuitBooleanNode) { - processBinary((ShortCircuitBooleanNode) usage); + if (usage instanceof ShortCircuitOrNode) { + processBinary((ShortCircuitOrNode) usage); } else if (usage instanceof IfNode) { - if (binary instanceof ShortCircuitAndNode) { - processIf(binary.getX(), binary.isXNegated(), binary.getY(), binary.isYNegated(), (IfNode) usage, false, binary.getShortCircuitProbability()); - } else if (binary instanceof ShortCircuitOrNode) { - processIf(binary.getX(), !binary.isXNegated(), binary.getY(), !binary.isYNegated(), (IfNode) usage, true, binary.getShortCircuitProbability()); - } else { - throw GraalInternalError.shouldNotReachHere(); - } + processIf(binary.getX(), binary.isXNegated(), binary.getY(), binary.isYNegated(), (IfNode) usage, binary.getShortCircuitProbability()); } else if (usage instanceof ConditionalNode) { - if (binary instanceof ShortCircuitOrNode) { - processConditional(binary.getX(), binary.isXNegated(), binary.getY(), binary.isYNegated(), (ConditionalNode) usage, false); - } else if (binary instanceof ShortCircuitOrNode) { - processConditional(binary.getX(), !binary.isXNegated(), binary.getY(), !binary.isYNegated(), (ConditionalNode) usage, true); - } else { - throw GraalInternalError.shouldNotReachHere(); - } + processConditional(binary.getX(), binary.isXNegated(), binary.getY(), binary.isYNegated(), (ConditionalNode) usage); } else { throw GraalInternalError.shouldNotReachHere(); } @@ -65,33 +53,44 @@ binary.safeDelete(); } - private static void processIf(LogicNode x, boolean xNegated, LogicNode y, boolean yNegated, IfNode ifNode, boolean negateTargets, double shortCircuitProbability) { - AbstractBeginNode trueTarget = negateTargets ? ifNode.falseSuccessor() : ifNode.trueSuccessor(); - AbstractBeginNode falseTarget = negateTargets ? ifNode.trueSuccessor() : ifNode.falseSuccessor(); + private static void processIf(LogicNode x, boolean xNegated, LogicNode y, boolean yNegated, IfNode ifNode, double shortCircuitProbability) { + AbstractBeginNode trueTarget = ifNode.trueSuccessor(); + AbstractBeginNode falseTarget = ifNode.falseSuccessor(); double firstIfProbability = shortCircuitProbability; - double secondIfProbability = 1 - ifNode.probability(trueTarget); + /* + * P(Y | not(X)) = P(Y inter not(X)) / P(not(X)) = (P(X union Y) - P(X)) / (1 - P(X)) + * + * P(X) = shortCircuitProbability + * + * P(X union Y) = ifNode.probability(trueTarget) + */ + double secondIfProbability = (ifNode.probability(trueTarget) - shortCircuitProbability) / (1 - shortCircuitProbability); + secondIfProbability = Math.min(1.0, Math.max(0.0, secondIfProbability)); + if (Double.isNaN(secondIfProbability)) { + secondIfProbability = 0.5; + } ifNode.clearSuccessors(); Graph graph = ifNode.graph(); - MergeNode falseTargetMerge = graph.add(new MergeNode()); - falseTargetMerge.setNext(falseTarget); - EndNode firstFalseEnd = graph.add(new EndNode()); - EndNode secondFalseEnd = graph.add(new EndNode()); - falseTargetMerge.addForwardEnd(firstFalseEnd); - falseTargetMerge.addForwardEnd(secondFalseEnd); - AbstractBeginNode firstFalseTarget = AbstractBeginNode.begin(firstFalseEnd); - AbstractBeginNode secondFalseTarget = AbstractBeginNode.begin(secondFalseEnd); - AbstractBeginNode secondIf = AbstractBeginNode.begin(graph.add(new IfNode(y, yNegated ? firstFalseTarget : trueTarget, yNegated ? trueTarget : firstFalseTarget, secondIfProbability))); - IfNode firstIf = graph.add(new IfNode(x, xNegated ? secondFalseTarget : secondIf, xNegated ? secondIf : secondFalseTarget, firstIfProbability)); + MergeNode trueTargetMerge = graph.add(new MergeNode()); + trueTargetMerge.setNext(trueTarget); + EndNode firstTrueEnd = graph.add(new EndNode()); + EndNode secondTrueEnd = graph.add(new EndNode()); + trueTargetMerge.addForwardEnd(firstTrueEnd); + trueTargetMerge.addForwardEnd(secondTrueEnd); + AbstractBeginNode firstTrueTarget = AbstractBeginNode.begin(firstTrueEnd); + AbstractBeginNode secondTrueTarget = AbstractBeginNode.begin(secondTrueEnd); + AbstractBeginNode secondIf = AbstractBeginNode.begin(graph.add(new IfNode(y, yNegated ? falseTarget : secondTrueTarget, yNegated ? secondTrueTarget : falseTarget, secondIfProbability))); + IfNode firstIf = graph.add(new IfNode(x, xNegated ? secondIf : firstTrueTarget, xNegated ? firstTrueTarget : secondIf, firstIfProbability)); ifNode.replaceAtPredecessor(firstIf); ifNode.safeDelete(); } - private static void processConditional(LogicNode x, boolean xNegated, LogicNode y, boolean yNegated, ConditionalNode conditional, boolean negateTargets) { - ValueNode trueTarget = negateTargets ? conditional.falseValue() : conditional.trueValue(); - ValueNode falseTarget = negateTargets ? conditional.trueValue() : conditional.falseValue(); + private static void processConditional(LogicNode x, boolean xNegated, LogicNode y, boolean yNegated, ConditionalNode conditional) { + ValueNode trueTarget = conditional.trueValue(); + ValueNode falseTarget = conditional.falseValue(); Graph graph = conditional.graph(); ConditionalNode secondConditional = graph.unique(new ConditionalNode(y, yNegated ? falseTarget : trueTarget, yNegated ? trueTarget : falseTarget)); - ConditionalNode firstConditional = graph.unique(new ConditionalNode(x, xNegated ? falseTarget : secondConditional, xNegated ? secondConditional : falseTarget)); + ConditionalNode firstConditional = graph.unique(new ConditionalNode(x, xNegated ? secondConditional : trueTarget, xNegated ? trueTarget : secondConditional)); conditional.replaceAndDelete(firstConditional); } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java Wed Oct 02 13:26:31 2013 +0200 @@ -37,24 +37,29 @@ public class FloatingReadPhase extends Phase { - private static class MemoryMap { + public enum ExecutionMode { + ANALYSIS_ONLY, CREATE_FLOATING_READS + } + + public static class MemoryMapImpl extends MemoryMapNode { private IdentityHashMap lastMemorySnapshot; - public MemoryMap(MemoryMap memoryMap) { + public MemoryMapImpl(MemoryMapImpl memoryMap) { lastMemorySnapshot = new IdentityHashMap<>(memoryMap.lastMemorySnapshot); } - public MemoryMap(StartNode start) { + public MemoryMapImpl(StartNode start) { this(); lastMemorySnapshot.put(ANY_LOCATION, start); } - public MemoryMap() { + public MemoryMapImpl() { lastMemorySnapshot = new IdentityHashMap<>(); } - private ValueNode getLastLocationAccess(LocationIdentity locationIdentity) { + @Override + public ValueNode getLastLocationAccess(LocationIdentity locationIdentity) { ValueNode lastLocationAccess; if (locationIdentity == FINAL_LOCATION) { return null; @@ -68,17 +73,43 @@ } } - @Override - public String toString() { - return "Map=" + lastMemorySnapshot.toString(); + public boolean isEmpty() { + if (lastMemorySnapshot.size() == 0) { + return true; + } + if (lastMemorySnapshot.size() == 1) { + if (lastMemorySnapshot.get(ANY_LOCATION) instanceof StartNode) { + return true; + } + } + return false; } + + public Set getLocations() { + return lastMemorySnapshot.keySet(); + } + + } + + private final ExecutionMode execmode; + + public FloatingReadPhase() { + this(ExecutionMode.CREATE_FLOATING_READS); + } + + public FloatingReadPhase(ExecutionMode execmode) { + this.execmode = execmode; } @Override protected void run(StructuredGraph graph) { Map> modifiedInLoops = new IdentityHashMap<>(); ReentrantNodeIterator.apply(new CollectMemoryCheckpointsClosure(modifiedInLoops), graph.start(), new HashSet(), null); - ReentrantNodeIterator.apply(new FloatingReadClosure(modifiedInLoops), graph.start(), new MemoryMap(graph.start()), null); + ReentrantNodeIterator.apply(new FloatingReadClosure(modifiedInLoops, execmode), graph.start(), new MemoryMapImpl(graph.start()), null); + if (execmode == ExecutionMode.CREATE_FLOATING_READS) { + assert !graph.isAfterFloatingReadPhase(); + graph.setAfterFloatingReadPhase(true); + } } private static class CollectMemoryCheckpointsClosure extends NodeIteratorClosure> { @@ -133,17 +164,19 @@ } - private static class FloatingReadClosure extends NodeIteratorClosure { + private static class FloatingReadClosure extends NodeIteratorClosure { private final Map> modifiedInLoops; + private final ExecutionMode execmode; - public FloatingReadClosure(Map> modifiedInLoops) { + public FloatingReadClosure(Map> modifiedInLoops, ExecutionMode execmode) { this.modifiedInLoops = modifiedInLoops; + this.execmode = execmode; } @Override - protected MemoryMap processNode(FixedNode node, MemoryMap state) { - if (node instanceof FloatableAccessNode) { + protected MemoryMapImpl processNode(FixedNode node, MemoryMapImpl state) { + if (node instanceof FloatableAccessNode && execmode == ExecutionMode.CREATE_FLOATING_READS) { processFloatable((FloatableAccessNode) node, state); } else if (node instanceof MemoryCheckpoint.Single) { processCheckpoint((MemoryCheckpoint.Single) node, state); @@ -151,27 +184,31 @@ processCheckpoint((MemoryCheckpoint.Multi) node, state); } assert MemoryCheckpoint.TypeAssertion.correctType(node) : node; + + if (execmode == ExecutionMode.ANALYSIS_ONLY && node instanceof ReturnNode) { + ((ReturnNode) node).setMemoryMap(node.graph().unique(new MemoryMapImpl(state))); + } return state; } - private static void processCheckpoint(MemoryCheckpoint.Single checkpoint, MemoryMap state) { - LocationIdentity identity = checkpoint.getLocationIdentity(); + private static void processCheckpoint(MemoryCheckpoint.Single checkpoint, MemoryMapImpl state) { + processIdentity(checkpoint.getLocationIdentity(), checkpoint, state); + } + + private static void processCheckpoint(MemoryCheckpoint.Multi checkpoint, MemoryMapImpl state) { + for (LocationIdentity identity : checkpoint.getLocationIdentities()) { + processIdentity(identity, checkpoint, state); + } + } + + private static void processIdentity(LocationIdentity identity, MemoryCheckpoint checkpoint, MemoryMapImpl state) { if (identity == ANY_LOCATION) { state.lastMemorySnapshot.clear(); } state.lastMemorySnapshot.put(identity, (ValueNode) checkpoint); } - private static void processCheckpoint(MemoryCheckpoint.Multi checkpoint, MemoryMap state) { - for (LocationIdentity identity : checkpoint.getLocationIdentities()) { - if (identity == ANY_LOCATION) { - state.lastMemorySnapshot.clear(); - } - state.lastMemorySnapshot.put(identity, (ValueNode) checkpoint); - } - } - - private static void processFloatable(FloatableAccessNode accessNode, MemoryMap state) { + private static void processFloatable(FloatableAccessNode accessNode, MemoryMapImpl state) { StructuredGraph graph = accessNode.graph(); assert accessNode.getNullCheck() == false; LocationIdentity locationIdentity = accessNode.location().getLocationIdentity(); @@ -190,11 +227,11 @@ } @Override - protected MemoryMap merge(MergeNode merge, List states) { - MemoryMap newState = new MemoryMap(); + protected MemoryMapImpl merge(MergeNode merge, List states) { + MemoryMapImpl newState = new MemoryMapImpl(); Set keys = new HashSet<>(); - for (MemoryMap other : states) { + for (MemoryMapImpl other : states) { keys.addAll(other.lastMemorySnapshot.keySet()); } assert !keys.contains(FINAL_LOCATION); @@ -203,7 +240,7 @@ int mergedStatesCount = 0; boolean isPhi = false; ValueNode merged = null; - for (MemoryMap state : states) { + for (MemoryMapImpl state : states) { ValueNode last = state.getLastLocationAccess(key); if (isPhi) { ((PhiNode) merged).addInput(last); @@ -213,7 +250,7 @@ } else if (merged == null) { merged = last; } else { - PhiNode phi = merge.graph().add(new PhiNode(PhiType.Memory, merge, key)); + PhiNode phi = merge.graph().addWithoutUnique(new PhiNode(PhiType.Memory, merge, key)); for (int j = 0; j < mergedStatesCount; j++) { phi.addInput(merged); } @@ -230,8 +267,8 @@ } @Override - protected MemoryMap afterSplit(AbstractBeginNode node, MemoryMap oldState) { - MemoryMap result = new MemoryMap(oldState); + protected MemoryMapImpl afterSplit(AbstractBeginNode node, MemoryMapImpl oldState) { + MemoryMapImpl result = new MemoryMapImpl(oldState); if (node.predecessor() instanceof InvokeWithExceptionNode) { /* * InvokeWithException cannot be the lastLocationAccess for a FloatingReadNode. @@ -247,7 +284,7 @@ } @Override - protected Map processLoop(LoopBeginNode loop, MemoryMap initialState) { + protected Map processLoop(LoopBeginNode loop, MemoryMapImpl initialState) { Set modifiedLocations = modifiedInLoops.get(loop); if (modifiedLocations.contains(ANY_LOCATION)) { // create phis for all locations if ANY is modified in the loop @@ -257,15 +294,15 @@ Map phis = new HashMap<>(); for (LocationIdentity location : modifiedLocations) { - PhiNode phi = loop.graph().add(new PhiNode(PhiType.Memory, loop, location)); + PhiNode phi = loop.graph().addWithoutUnique(new PhiNode(PhiType.Memory, loop, location)); phi.addInput(initialState.getLastLocationAccess(location)); phis.put(location, phi); initialState.lastMemorySnapshot.put(location, phi); } - LoopInfo loopInfo = ReentrantNodeIterator.processLoop(this, loop, initialState); + LoopInfo loopInfo = ReentrantNodeIterator.processLoop(this, loop, initialState); - for (Map.Entry entry : loopInfo.endStates.entrySet()) { + for (Map.Entry entry : loopInfo.endStates.entrySet()) { int endIndex = loop.phiPredecessorIndex(entry.getKey()); for (Map.Entry phiEntry : phis.entrySet()) { LocationIdentity key = phiEntry.getKey(); @@ -273,9 +310,9 @@ phi.initializeValueAt(endIndex, entry.getValue().getLastLocationAccess(key)); } } - for (Map.Entry entry : loopInfo.exitStates.entrySet()) { + for (Map.Entry entry : loopInfo.exitStates.entrySet()) { LoopExitNode exit = entry.getKey(); - MemoryMap state = entry.getValue(); + MemoryMapImpl state = entry.getValue(); for (LocationIdentity location : modifiedLocations) { ValueNode lastAccessAtExit = state.lastMemorySnapshot.get(location); if (lastAccessAtExit != null) { diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FrameStateAssignmentPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FrameStateAssignmentPhase.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FrameStateAssignmentPhase.java Wed Oct 02 13:26:31 2013 +0200 @@ -27,11 +27,22 @@ import com.oracle.graal.graph.*; import com.oracle.graal.graph.iterators.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.StructuredGraph.GuardsStage; import com.oracle.graal.nodes.util.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.graph.*; import com.oracle.graal.phases.graph.ReentrantNodeIterator.NodeIteratorClosure; +/** + * This phase transfers {@link FrameState} nodes from {@link StateSplit} nodes to + * {@link DeoptimizingNode DeoptimizingNodes}. + * + * This allow to enter the {@link GuardsStage#AFTER_FSA AFTER_FSA} stage of the graph where no new + * node that may cause deoptimization can be introduced anymore. + *

+ * This Phase processes the graph in post order, assigning the {@link FrameState} from the last + * {@link StateSplit} node to {@link DeoptimizingNode DeoptimizingNodes}. + */ public class FrameStateAssignmentPhase extends Phase { private static class FrameStateAssignmentClosure extends NodeIteratorClosure { @@ -77,6 +88,8 @@ protected void run(StructuredGraph graph) { assert checkFixedDeopts(graph); ReentrantNodeIterator.apply(new FrameStateAssignmentClosure(), graph.start(), null, null); + + graph.setGuardsStage(GuardsStage.AFTER_FSA); } private static boolean checkFixedDeopts(StructuredGraph graph) { diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java Wed Oct 02 13:26:31 2013 +0200 @@ -29,6 +29,7 @@ import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.StructuredGraph.GuardsStage; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.cfg.*; import com.oracle.graal.nodes.extended.*; @@ -36,15 +37,16 @@ import com.oracle.graal.phases.*; import com.oracle.graal.phases.graph.*; import com.oracle.graal.phases.schedule.*; +import com.oracle.graal.phases.schedule.SchedulePhase.SchedulingStrategy; import com.oracle.graal.phases.tiers.*; /** * This phase lowers {@link GuardNode GuardNodes} into corresponding control-flow structure and * {@link DeoptimizeNode DeoptimizeNodes}. * - * This allow to enter a phase of the compiler where all node that may cause deoptimization are - * fixed. - * + * This allow to enter the {@link GuardsStage#FIXED_DEOPTS FIXED_DEOPTS} stage of the graph where + * all node that may cause deoptimization are fixed. + *

* It first makes a schedule in order to know where the control flow should be placed. Then, for * each block, it applies two passes. The first one tries to replace null-check guards with implicit * null checks performed by access to the objects that need to be null checked. The second phase @@ -181,19 +183,20 @@ @Override protected void run(StructuredGraph graph, MidTierContext context) { - SchedulePhase schedule = new SchedulePhase(); + SchedulePhase schedule = new SchedulePhase(SchedulingStrategy.EARLIEST); schedule.apply(graph); for (Block block : schedule.getCFG().getBlocks()) { processBlock(block, schedule, context.getTarget().implicitNullCheckLimit); } + + graph.setGuardsStage(GuardsStage.FIXED_DEOPTS); } private static void processBlock(Block block, SchedulePhase schedule, int implicitNullCheckLimit) { - List nodes = schedule.nodesFor(block); if (OptImplicitNullChecks.getValue() && implicitNullCheckLimit > 0) { - new UseImplicitNullChecks(implicitNullCheckLimit).processNodes(nodes, block.getBeginNode()); + new UseImplicitNullChecks(implicitNullCheckLimit).processNodes(block, schedule); } - new LowerGuards(block).processNodes(nodes, block.getBeginNode()); + new LowerGuards(block).processNodes(block, schedule); } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IncrementalCanonicalizerPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IncrementalCanonicalizerPhase.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IncrementalCanonicalizerPhase.java Wed Oct 02 13:26:31 2013 +0200 @@ -22,29 +22,48 @@ */ package com.oracle.graal.phases.common; -import static com.oracle.graal.phases.GraalOptions.*; +import java.util.*; +import com.oracle.graal.graph.Graph.NodeChangedListener; +import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.phases.*; -import com.oracle.graal.phases.common.CanonicalizerPhase.CustomCanonicalizer; import com.oracle.graal.phases.tiers.*; +/** + * A phase suite that applies {@linkplain CanonicalizerPhase canonicalization} to a graph after all + * phases in the suite have been applied if any of the phases changed the graph. + */ public class IncrementalCanonicalizerPhase extends PhaseSuite { - private final CustomCanonicalizer customCanonicalizer; + private final CanonicalizerPhase canonicalizer; - public IncrementalCanonicalizerPhase() { - this(null); - } - - public IncrementalCanonicalizerPhase(CustomCanonicalizer customCanonicalizer) { - this.customCanonicalizer = customCanonicalizer; + public IncrementalCanonicalizerPhase(CanonicalizerPhase canonicalizer) { + this.canonicalizer = canonicalizer; } @Override protected void run(StructuredGraph graph, C context) { - int mark = graph.getMark(); + int newNodesMark = graph.getMark(); + final Set changedNodes = new HashSet<>(); + + NodeChangedListener listener = new NodeChangedListener() { + + @Override + public void nodeChanged(Node node) { + changedNodes.add(node); + } + }; + graph.trackInputChange(listener); + graph.trackUsagesDroppedZero(listener); + super.run(graph, context); - new CanonicalizerPhase.Instance(context.getRuntime(), context.getAssumptions(), !AOTCompilation.getValue(), mark, customCanonicalizer).apply(graph); + + graph.stopTrackingInputChange(); + graph.stopTrackingUsagesDroppedZero(); + + if (graph.getMark() != newNodesMark || !changedNodes.isEmpty()) { + canonicalizer.applyIncremental(graph, context, changedNodes, newNodesMark, false); + } } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java Wed Oct 02 13:26:31 2013 +0200 @@ -39,7 +39,6 @@ import com.oracle.graal.nodes.util.*; import com.oracle.graal.options.*; import com.oracle.graal.phases.PhasePlan.PhasePosition; -import com.oracle.graal.phases.common.CanonicalizerPhase.CustomCanonicalizer; import com.oracle.graal.phases.common.InliningUtil.InlineInfo; import com.oracle.graal.phases.common.InliningUtil.Inlineable; import com.oracle.graal.phases.common.InliningUtil.InlineableGraph; @@ -59,7 +58,7 @@ } private final InliningPolicy inliningPolicy; - private final CustomCanonicalizer customCanonicalizer; + private final CanonicalizerPhase canonicalizer; private int inliningCount; private int maxMethodPerInlining = Integer.MAX_VALUE; @@ -68,27 +67,19 @@ private static final DebugMetric metricInliningPerformed = Debug.metric("InliningPerformed"); private static final DebugMetric metricInliningConsidered = Debug.metric("InliningConsidered"); private static final DebugMetric metricInliningStoppedByMaxDesiredSize = Debug.metric("InliningStoppedByMaxDesiredSize"); - private static final DebugMetric metricInliningRuns = Debug.metric("Runs"); + private static final DebugMetric metricInliningRuns = Debug.metric("InliningRuns"); - public InliningPhase() { - this(new GreedyInliningPolicy(null), null); - } - - public InliningPhase(CustomCanonicalizer canonicalizer) { + public InliningPhase(CanonicalizerPhase canonicalizer) { this(new GreedyInliningPolicy(null), canonicalizer); } - public InliningPhase(Map hints) { - this(new GreedyInliningPolicy(hints), null); + public InliningPhase(Map hints, CanonicalizerPhase canonicalizer) { + this(new GreedyInliningPolicy(hints), canonicalizer); } - public InliningPhase(InliningPolicy policy) { - this(policy, null); - } - - private InliningPhase(InliningPolicy policy, CustomCanonicalizer customCanonicalizer) { + public InliningPhase(InliningPolicy policy, CanonicalizerPhase canonicalizer) { this.inliningPolicy = policy; - this.customCanonicalizer = customCanonicalizer; + this.canonicalizer = canonicalizer; } public void setMaxMethodsPerInlining(int max) { @@ -163,7 +154,7 @@ MethodInvocation calleeInvocation = data.pushInvocation(info, parentAssumptions, invokeProbability, invokeRelevance); for (int i = 0; i < info.numberOfMethods(); i++) { - Inlineable elem = getInlineableElement(info.methodAt(i), info.invoke(), calleeInvocation.assumptions(), context); + Inlineable elem = getInlineableElement(info.methodAt(i), info.invoke(), context.replaceAssumptions(calleeInvocation.assumptions())); info.setInlinableElement(i, elem); if (elem instanceof InlineableGraph) { data.pushGraph(((InlineableGraph) elem).getGraph(), invokeProbability * info.probabilityAt(i), invokeRelevance * info.relevanceAt(i)); @@ -200,7 +191,7 @@ if (OptCanonicalizer.getValue()) { int markBeforeCanonicalization = callerGraph.getMark(); - new CanonicalizerPhase.Instance(context.getRuntime(), callerAssumptions, !AOTCompilation.getValue(), invokeUsages, markBeforeInlining, customCanonicalizer).apply(callerGraph); + canonicalizer.applyIncremental(callerGraph, context, invokeUsages, markBeforeInlining); // process invokes that are possibly created during canonicalization for (Node newNode : callerGraph.getNewNodes(markBeforeCanonicalization)) { @@ -223,16 +214,16 @@ } } - private static Inlineable getInlineableElement(final ResolvedJavaMethod method, Invoke invoke, Assumptions assumptions, HighTierContext context) { + private Inlineable getInlineableElement(final ResolvedJavaMethod method, Invoke invoke, HighTierContext context) { Class macroNodeClass = InliningUtil.getMacroNodeClass(context.getReplacements(), method); if (macroNodeClass != null) { return new InlineableMacroNode(macroNodeClass); } else { - return new InlineableGraph(buildGraph(method, invoke, assumptions, context)); + return new InlineableGraph(buildGraph(method, invoke, context)); } } - private static StructuredGraph buildGraph(final ResolvedJavaMethod method, final Invoke invoke, final Assumptions assumptions, final HighTierContext context) { + private StructuredGraph buildGraph(final ResolvedJavaMethod method, final Invoke invoke, final HighTierContext context) { final StructuredGraph newGraph; final boolean parseBytecodes; @@ -258,7 +249,7 @@ @Override public StructuredGraph call() throws Exception { if (parseBytecodes) { - parseBytecodes(newGraph, assumptions, context); + parseBytecodes(newGraph, context); } boolean callerHasMoreInformationAboutArguments = false; @@ -285,7 +276,7 @@ } if (OptCanonicalizer.getValue()) { - new CanonicalizerPhase.Instance(context.getRuntime(), assumptions, !AOTCompilation.getValue()).apply(newGraph); + canonicalizer.apply(newGraph, context); } return newGraph; @@ -303,7 +294,7 @@ return null; } - private static StructuredGraph parseBytecodes(StructuredGraph newGraph, Assumptions assumptions, HighTierContext context) { + private StructuredGraph parseBytecodes(StructuredGraph newGraph, HighTierContext context) { boolean hasMatureProfilingInfo = newGraph.method().getProfilingInfo().isMature(); if (context.getPhasePlan() != null) { @@ -314,7 +305,7 @@ new DeadCodeEliminationPhase().apply(newGraph); if (OptCanonicalizer.getValue()) { - new CanonicalizerPhase.Instance(context.getRuntime(), assumptions, !AOTCompilation.getValue()).apply(newGraph); + canonicalizer.apply(newGraph, context); } if (CacheGraphs.getValue() && context.getGraphCache() != null) { @@ -416,7 +407,7 @@ } } - private static final class GreedyInliningPolicy extends AbstractInliningPolicy { + public static class GreedyInliningPolicy extends AbstractInliningPolicy { public GreedyInliningPolicy(Map hints) { super(hints); @@ -646,10 +637,15 @@ } } + private static final Object[] NO_CONTEXT = {}; + /** - * Gets the call hierarchy of this inling from outer most call to inner most callee. + * Gets the call hierarchy of this inlining from outer most call to inner most callee. */ public Object[] inliningContext() { + if (!Debug.isDumpEnabled()) { + return NO_CONTEXT; + } Object[] result = new Object[graphQueue.size()]; int i = 0; for (GraphInfo g : graphQueue) { diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java Wed Oct 02 13:26:31 2013 +0200 @@ -22,7 +22,7 @@ */ package com.oracle.graal.phases.common; -import static com.oracle.graal.api.code.DeoptimizationAction.*; +import static com.oracle.graal.api.meta.DeoptimizationAction.*; import static com.oracle.graal.api.meta.DeoptimizationReason.*; import static com.oracle.graal.nodes.type.StampFactory.*; import static com.oracle.graal.phases.GraalOptions.*; @@ -38,7 +38,8 @@ import com.oracle.graal.api.meta.ResolvedJavaType.Representation; import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; -import com.oracle.graal.graph.Node.*; +import com.oracle.graal.graph.Graph.DuplicationReplacement; +import com.oracle.graal.graph.Node.Verbosity; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; @@ -349,10 +350,11 @@ * Represents an inlining opportunity where the compiler can statically determine a monomorphic * target method and therefore is able to determine the called method exactly. */ - private static class ExactInlineInfo extends AbstractInlineInfo { + public static class ExactInlineInfo extends AbstractInlineInfo { protected final ResolvedJavaMethod concrete; private Inlineable inlineableElement; + private boolean suppressNullCheck; public ExactInlineInfo(Invoke invoke, ResolvedJavaMethod concrete) { super(invoke); @@ -360,9 +362,13 @@ assert concrete != null; } + public void suppressNullCheck() { + suppressNullCheck = true; + } + @Override public void inline(MetaAccessProvider runtime, Assumptions assumptions, Replacements replacements) { - inline(invoke, concrete, inlineableElement, assumptions, true); + inline(invoke, concrete, inlineableElement, assumptions, !suppressNullCheck); } @Override @@ -478,7 +484,7 @@ private void createGuard(StructuredGraph graph, MetaAccessProvider runtime) { ValueNode nonNullReceiver = InliningUtil.nonNullReceiver(invoke); ConstantNode typeHub = ConstantNode.forConstant(type.getEncoding(Representation.ObjectHub), runtime, graph); - LoadHubNode receiverHub = graph.add(new LoadHubNode(nonNullReceiver, typeHub.kind(), null)); + LoadHubNode receiverHub = graph.unique(new LoadHubNode(nonNullReceiver, typeHub.kind(), null)); CompareNode typeCheck = CompareNode.createCompareNode(Condition.EQ, receiverHub, typeHub); FixedGuardNode guard = graph.add(new FixedGuardNode(typeCheck, DeoptimizationReason.TypeCheckedInliningViolated, DeoptimizationAction.InvalidateReprofile)); @@ -604,11 +610,11 @@ ValueNode originalReceiver = ((MethodCallTargetNode) invoke.callTarget()).receiver(); // setup merge and phi nodes for results and exceptions MergeNode returnMerge = graph.add(new MergeNode()); - returnMerge.setStateAfter(invoke.stateAfter().duplicate(invoke.stateAfter().bci)); + returnMerge.setStateAfter(invoke.stateAfter()); PhiNode returnValuePhi = null; if (invoke.asNode().kind() != Kind.Void) { - returnValuePhi = graph.add(new PhiNode(invoke.asNode().kind(), returnMerge)); + returnValuePhi = graph.addWithoutUnique(new PhiNode(invoke.asNode().kind(), returnMerge)); } MergeNode exceptionMerge = null; @@ -621,7 +627,7 @@ FixedNode exceptionSux = exceptionEdge.next(); graph.addBeforeFixed(exceptionSux, exceptionMerge); - exceptionObjectPhi = graph.add(new PhiNode(Kind.Object, exceptionMerge)); + exceptionObjectPhi = graph.addWithoutUnique(new PhiNode(Kind.Object, exceptionMerge)); exceptionMerge.setStateAfter(exceptionEdge.stateAfter().duplicateModified(invoke.stateAfter().bci, true, Kind.Object, exceptionObjectPhi)); } @@ -707,7 +713,8 @@ if (opportunities > 0) { metricInliningTailDuplication.increment(); Debug.log("MultiTypeGuardInlineInfo starting tail duplication (%d opportunities)", opportunities); - TailDuplicationPhase.tailDuplicate(returnMerge, TailDuplicationPhase.TRUE_DECISION, replacementNodes, new PhaseContext(runtime, assumptions, replacements)); + TailDuplicationPhase.tailDuplicate(returnMerge, TailDuplicationPhase.TRUE_DECISION, replacementNodes, new PhaseContext(runtime, assumptions, replacements), new CanonicalizerPhase( + !AOTCompilation.getValue())); } } } @@ -763,7 +770,7 @@ assert ptypes.size() >= 1; ValueNode nonNullReceiver = nonNullReceiver(invoke); Kind hubKind = ((MethodCallTargetNode) invoke.callTarget()).targetMethod().getDeclaringClass().getEncoding(Representation.ObjectHub).getKind(); - LoadHubNode hub = graph.add(new LoadHubNode(nonNullReceiver, hubKind, null)); + LoadHubNode hub = graph.unique(new LoadHubNode(nonNullReceiver, hubKind, null)); if (!invokeIsOnlySuccessor && chooseMethodDispatch()) { assert successors.length == concretes.size() + 1; @@ -1287,7 +1294,7 @@ * false if no such check is required */ public static Map inline(Invoke invoke, StructuredGraph inlineGraph, boolean receiverNullCheck) { - NodeInputList parameters = invoke.callTarget().arguments(); + final NodeInputList parameters = invoke.callTarget().arguments(); StructuredGraph graph = invoke.asNode().graph(); FrameState stateAfter = invoke.stateAfter(); @@ -1296,17 +1303,17 @@ nonNullReceiver(invoke); } - IdentityHashMap replacements = new IdentityHashMap<>(); - ArrayList nodes = new ArrayList<>(); + ArrayList nodes = new ArrayList<>(inlineGraph.getNodes().count()); ReturnNode returnNode = null; UnwindNode unwindNode = null; - StartNode entryPointNode = inlineGraph.start(); + final StartNode entryPointNode = inlineGraph.start(); FixedNode firstCFGNode = entryPointNode.next(); + if (firstCFGNode == null) { + throw new IllegalStateException("Inlined graph is in invalid state"); + } for (Node node : inlineGraph.getNodes()) { - if (node == entryPointNode || node == entryPointNode.stateAfter()) { + if (node == entryPointNode || node == entryPointNode.stateAfter() || node instanceof LocalNode) { // Do nothing. - } else if (node instanceof LocalNode) { - replacements.put(node, parameters.get(((LocalNode) node).index())); } else { nodes.add(node); if (node instanceof ReturnNode) { @@ -1318,13 +1325,24 @@ } } } - // ensure proper anchoring of things that were anchored to the StartNode - replacements.put(entryPointNode, AbstractBeginNode.prevBegin(invoke.asNode())); + + final AbstractBeginNode prevBegin = AbstractBeginNode.prevBegin(invoke.asNode()); + DuplicationReplacement localReplacement = new DuplicationReplacement() { + + public Node replacement(Node node) { + if (node instanceof LocalNode) { + return parameters.get(((LocalNode) node).index()); + } else if (node == entryPointNode) { + return prevBegin; + } + return node; + } + }; assert invoke.asNode().successors().first() != null : invoke; assert invoke.asNode().predecessor() != null; - Map duplicates = graph.addDuplicates(nodes, replacements); + Map duplicates = graph.addDuplicates(nodes, inlineGraph, inlineGraph.getNodeCount(), localReplacement); FixedNode firstCFGNodeDuplicate = (FixedNode) duplicates.get(firstCFGNode); invoke.asNode().replaceAtPredecessor(firstCFGNodeDuplicate); @@ -1367,7 +1385,8 @@ if (stateAfter != null) { FrameState outerFrameState = null; int callerLockDepth = stateAfter.nestedLockDepth(); - for (Node node : duplicates.values()) { + for (Node inlinedNode : inlineGraph.getNodes()) { + Node node = duplicates.get(inlinedNode); if (node instanceof FrameState) { FrameState frameState = (FrameState) node; assert frameState.bci != FrameState.BEFORE_BCI : frameState; @@ -1391,12 +1410,6 @@ frameState.setOuterFrameState(outerFrameState); } } - } else if (node instanceof ValueAnchorNode) { - /* - * Synchronized inlinees have a valid point to deopt to after the monitor exit - * at the end, so there's no need for the value anchor to be permanent anymore. - */ - ((ValueAnchorNode) node).setPermanent(false); } if (callerLockDepth != 0 && node instanceof MonitorReference) { MonitorReference monitor = (MonitorReference) node; @@ -1409,8 +1422,8 @@ Node returnValue = null; if (returnNode != null) { if (returnNode.result() instanceof LocalNode) { - returnValue = replacements.get(returnNode.result()); - } else { + returnValue = localReplacement.replacement(returnNode.result()); + } else if (returnNode.result() != null) { returnValue = duplicates.get(returnNode.result()); } invoke.asNode().replaceAtUsages(returnValue); diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InsertStateAfterPlaceholderPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InsertStateAfterPlaceholderPhase.java Fri Sep 06 21:37:50 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,83 +0,0 @@ -/* - * Copyright (c) 2012, 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.phases.common; - -import com.oracle.graal.graph.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; -import com.oracle.graal.phases.*; - -public class InsertStateAfterPlaceholderPhase extends Phase { - - private static class PlaceholderNode extends AbstractStateSplit implements StateSplit, Node.IterableNodeType, LIRLowerable, Canonicalizable { - - public PlaceholderNode() { - super(StampFactory.forVoid()); - } - - @Override - public void generate(LIRGeneratorTool gen) { - // nothing to do - } - - @Override - public boolean hasSideEffect() { - return false; - } - - @Override - public ValueNode canonical(CanonicalizerTool tool) { - if (!usages().isEmpty()) { - return this; - } - if (stateAfter() == null) { - return null; - } - FixedNode next = next(); - if (next instanceof PlaceholderNode && ((PlaceholderNode) next).stateAfter() != null) { - return null; - } - return this; - } - } - - @Override - protected void run(StructuredGraph graph) { - boolean needsPlaceHolder = false; - for (Node node : graph.getNodes().filterInterface(StateSplit.class)) { - StateSplit stateSplit = (StateSplit) node; - if (stateSplit.hasSideEffect() && stateSplit.stateAfter() != null) { - needsPlaceHolder = true; - } - } - if (needsPlaceHolder) { - for (ReturnNode ret : graph.getNodes(ReturnNode.class)) { - PlaceholderNode p = graph.add(new PlaceholderNode()); - p.setStateAfter(graph.add(new FrameState(FrameState.AFTER_BCI))); - graph.addBeforeFixed(ret, p); - } - } - } - -} diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IterativeConditionalEliminationPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IterativeConditionalEliminationPhase.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IterativeConditionalEliminationPhase.java Wed Oct 02 13:26:31 2013 +0200 @@ -22,8 +22,6 @@ */ package com.oracle.graal.phases.common; -import static com.oracle.graal.phases.GraalOptions.*; - import com.oracle.graal.api.code.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; @@ -36,6 +34,12 @@ private static final int MAX_ITERATIONS = 256; + private final CanonicalizerPhase canonicalizer; + + public IterativeConditionalEliminationPhase(CanonicalizerPhase canonicalizer) { + this.canonicalizer = canonicalizer; + } + @Override protected void run(StructuredGraph graph, PhaseContext context) { ConditionalEliminationPhase eliminate = new ConditionalEliminationPhase(context.getRuntime()); @@ -55,7 +59,7 @@ listener.getChangedNodes().add(node); } } - new CanonicalizerPhase.Instance(context.getRuntime(), context.getAssumptions(), !AOTCompilation.getValue(), listener.getChangedNodes(), null).apply(graph); + canonicalizer.applyIncremental(graph, context, listener.getChangedNodes()); listener.getChangedNodes().clear(); if (++count > MAX_ITERATIONS) { throw new BailoutException("Number of iterations in conditional elimination phase exceeds " + MAX_ITERATIONS); diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoopSafepointInsertionPhase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoopSafepointInsertionPhase.java Wed Oct 02 13:26:31 2013 +0200 @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2011, 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.phases.common; + +import static com.oracle.graal.phases.GraalOptions.*; + +import com.oracle.graal.nodes.*; +import com.oracle.graal.phases.*; + +/** + * Adds safepoints to loops. + */ +public class LoopSafepointInsertionPhase extends Phase { + + @Override + protected void run(StructuredGraph graph) { + if (GenLoopSafepoints.getValue()) { + for (LoopEndNode loopEndNode : graph.getNodes(LoopEndNode.class)) { + if (loopEndNode.canSafepoint()) { + SafepointNode safepointNode = graph.add(new SafepointNode()); + graph.addBeforeFixed(loopEndNode, safepointNode); + } + } + } + } +} diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java Wed Oct 02 13:26:31 2013 +0200 @@ -31,11 +31,11 @@ import com.oracle.graal.graph.*; import com.oracle.graal.graph.iterators.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.StructuredGraph.GuardsStage; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.cfg.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.spi.Lowerable.LoweringType; import com.oracle.graal.nodes.type.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.schedule.*; @@ -73,20 +73,22 @@ } @Override - public LoweringType getLoweringType() { - return loweringType; - } - - @Override public GuardingNode createNullCheckGuard(GuardedNode guardedNode, ValueNode object) { if (ObjectStamp.isObjectNonNull(object)) { // Short cut creation of null check guard if the object is known to be non-null. return null; } - GuardingNode guard = createGuard(object.graph().unique(new IsNullNode(object)), DeoptimizationReason.NullCheckException, DeoptimizationAction.InvalidateReprofile, true); - assert guardedNode.getGuard() == null; - guardedNode.setGuard(guard); - return guard; + StructuredGraph graph = object.graph(); + if (graph.getGuardsStage().ordinal() > GuardsStage.FLOATING_GUARDS.ordinal()) { + NullCheckNode nullCheck = graph.add(new NullCheckNode(object)); + graph.addBeforeFixed((FixedNode) guardedNode, nullCheck); + return nullCheck; + } else { + GuardingNode guard = createGuard(graph.unique(new IsNullNode(object)), DeoptimizationReason.NullCheckException, DeoptimizationAction.InvalidateReprofile, true); + assert guardedNode.getGuard() == null; + guardedNode.setGuard(guard); + return guard; + } } @Override @@ -101,8 +103,8 @@ @Override public GuardingNode createGuard(LogicNode condition, DeoptimizationReason deoptReason, DeoptimizationAction action, boolean negated) { - if (loweringType != LoweringType.BEFORE_GUARDS) { - throw new GraalInternalError("Cannot create guards in after-guard lowering"); + if (condition.graph().getGuardsStage().ordinal() > StructuredGraph.GuardsStage.FLOATING_GUARDS.ordinal()) { + throw new GraalInternalError("Cannot create guards after guard lowering"); } if (OptEliminateGuards.getValue()) { for (Node usage : condition.usages()) { @@ -134,39 +136,61 @@ } } - private final LoweringType loweringType; + private final CanonicalizerPhase canonicalizer; - public LoweringPhase(LoweringType loweringType) { - super("Lowering (" + loweringType.name() + ")"); - this.loweringType = loweringType; + public LoweringPhase(CanonicalizerPhase canonicalizer) { + this.canonicalizer = canonicalizer; } - private static boolean containsLowerable(NodeIterable nodes) { - for (Node n : nodes) { - if (n instanceof Lowerable) { - return true; - } - } - return false; + /** + * Checks that second lowering of a given graph did not introduce any new nodes. + * + * @param graph a graph that was just {@linkplain #lower lowered} + * @throws AssertionError if the check fails + */ + private boolean checkPostLowering(StructuredGraph graph, PhaseContext context) { + int expectedMark = graph.getMark(); + lower(graph, context, 1); + int mark = graph.getMark(); + assert mark == expectedMark : graph + ": a second round in the current lowering phase introduced these new nodes: " + graph.getNewNodes(mark).snapshot(); + return true; } @Override protected void run(final StructuredGraph graph, PhaseContext context) { - int i = 0; - while (true) { - Round round = new Round(i++, context); - int mark = graph.getMark(); + lower(graph, context, 0); + assert checkPostLowering(graph, context); + } + + private void lower(StructuredGraph graph, PhaseContext context, int i) { + IncrementalCanonicalizerPhase incrementalCanonicalizer = new IncrementalCanonicalizerPhase<>(canonicalizer); + incrementalCanonicalizer.appendPhase(new Round(i, context)); + incrementalCanonicalizer.apply(graph, context); + assert graph.verify(); + } - IncrementalCanonicalizerPhase canonicalizer = new IncrementalCanonicalizerPhase<>(); - canonicalizer.appendPhase(round); - canonicalizer.apply(graph, context); - - if (!containsLowerable(graph.getNewNodes(mark))) { - // No new lowerable nodes - done! - break; + /** + * Checks that lowering of a given node did not introduce any new {@link Lowerable} nodes that + * could be lowered in the current {@link LoweringPhase}. Such nodes must be recursively lowered + * as part of lowering {@code node}. + * + * @param node a node that was just lowered + * @param preLoweringMark the graph mark before {@code node} was lowered + * @throws AssertionError if the check fails + */ + private static boolean checkPostNodeLowering(Node node, LoweringToolImpl loweringTool, int preLoweringMark) { + StructuredGraph graph = (StructuredGraph) node.graph(); + int postLoweringMark = graph.getMark(); + NodeIterable newNodesAfterLowering = graph.getNewNodes(preLoweringMark); + for (Node n : newNodesAfterLowering) { + if (n instanceof Lowerable) { + ((Lowerable) n).lower(loweringTool); + int mark = graph.getMark(); + assert postLoweringMark == mark : graph + ": lowering of " + node + " produced lowerable " + n + " that should have been recursively lowered as it introduces these new nodes: " + + graph.getNewNodes(postLoweringMark).snapshot(); } - assert graph.verify(); } + return true; } private final class Round extends Phase { @@ -175,7 +199,7 @@ private final SchedulePhase schedule; private Round(int iteration, PhaseContext context) { - super(String.format("Lowering iteration %d", iteration)); + super("LoweringIteration" + iteration); this.context = context; this.schedule = new SchedulePhase(); } @@ -210,7 +234,9 @@ if (parentAnchor == null && OptEliminateGuards.getValue()) { for (GuardNode guard : anchor.asNode().usages().filter(GuardNode.class)) { - activeGuards.clear(guard); + if (activeGuards.contains(guard)) { + activeGuards.clear(guard); + } } } } @@ -239,17 +265,23 @@ if (node instanceof Lowerable) { assert checkUsagesAreScheduled(node); - ((Lowerable) node).lower(loweringTool, loweringType); + int preLoweringMark = node.graph().getMark(); + ((Lowerable) node).lower(loweringTool); + assert checkPostNodeLowering(node, loweringTool, preLoweringMark); } if (!nextNode.isAlive()) { - // can happen when the rest of the block is killed by lowering (e.g. by a - // unconditional deopt) + // can happen when the rest of the block is killed by lowering + // (e.g. by an unconditional deopt) break; } else { Node nextLastFixed = nextNode.predecessor(); if (!(nextLastFixed instanceof FixedWithNextNode)) { // insert begin node, to have a valid last fixed for next lowerable node. + // This is about lowering a FixedWithNextNode to a control split while this + // FixedWithNextNode is followed by some kind of BeginNode. + // For example the when a FixedGuard followed by a loop exit is lowered to a + // control-split + deopt. BeginNode begin = node.graph().add(new BeginNode()); nextLastFixed.replaceFirstSuccessor(nextNode, begin); begin.setNext(nextNode); diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ReadEliminationPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ReadEliminationPhase.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ReadEliminationPhase.java Wed Oct 02 13:26:31 2013 +0200 @@ -87,7 +87,7 @@ } if (lastLocationAccess instanceof PhiNode) { PhiNode phi = (PhiNode) lastLocationAccess; - PhiNode newPhi = phi.graph().add(new PhiNode(n.kind(), phi.merge())); + PhiNode newPhi = phi.graph().addWithoutUnique(new PhiNode(n.kind(), phi.merge())); nodeMap.set(lastLocationAccess, newPhi); for (ValueNode value : phi.values()) { newPhi.addInput(getValue(n, value, nodeMap)); diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/SafepointInsertionPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/SafepointInsertionPhase.java Fri Sep 06 21:37:50 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2011, 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.phases.common; - -import static com.oracle.graal.phases.GraalOptions.*; - -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.java.*; -import com.oracle.graal.phases.*; - -/** - * Adds safepoints to loops and return points. - */ -public class SafepointInsertionPhase extends Phase { - - @Override - protected void run(StructuredGraph graph) { - if (GenLoopSafepoints.getValue()) { - for (LoopEndNode loopEndNode : graph.getNodes(LoopEndNode.class)) { - if (!loopEndNode.canSafepoint()) { - continue; - } - SafepointNode safepointNode = graph.add(new SafepointNode()); - graph.addBeforeFixed(loopEndNode, safepointNode); - } - } - - if (GenSafepoints.getValue()) { - if (!OptEliminateSafepoints.getValue() || graph.getNodes(MethodCallTargetNode.class).isNotEmpty()) { - for (ReturnNode returnNode : graph.getNodes(ReturnNode.class)) { - SafepointNode safepoint = graph.add(new SafepointNode()); - graph.addBeforeFixed(returnNode, safepoint); - } - } - } - } -} diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java Wed Oct 02 13:26:31 2013 +0200 @@ -42,8 +42,8 @@ /** * This class is a phase that looks for opportunities for tail duplication. The static method - * {@link #tailDuplicate(MergeNode, TailDuplicationDecision, List, PhaseContext)} can also be used - * to drive tail duplication from other places, e.g., inlining. + * {@link #tailDuplicate(MergeNode, TailDuplicationDecision, List, PhaseContext, CanonicalizerPhase)} + * can also be used to drive tail duplication from other places, e.g., inlining. */ public class TailDuplicationPhase extends BasePhase { @@ -53,6 +53,8 @@ private static final DebugMetric metricDuplicationConsidered = Debug.metric("DuplicationConsidered"); private static final DebugMetric metricDuplicationPerformed = Debug.metric("DuplicationPerformed"); + private final CanonicalizerPhase canonicalizer; + /** * This interface is used by tail duplication to let clients decide if tail duplication should * be performed. @@ -129,6 +131,10 @@ } }; + public TailDuplicationPhase(CanonicalizerPhase canonicalizer) { + this.canonicalizer = canonicalizer; + } + @Override protected void run(StructuredGraph graph, PhaseContext phaseContext) { NodesToDoubles nodeProbabilities = new ComputeProbabilityClosure(graph).apply(); @@ -137,7 +143,7 @@ // duplication. for (MergeNode merge : graph.getNodes(MergeNode.class).snapshot()) { if (!(merge instanceof LoopBeginNode) && nodeProbabilities.get(merge) >= TailDuplicationProbability.getValue()) { - tailDuplicate(merge, DEFAULT_DECISION, null, phaseContext); + tailDuplicate(merge, DEFAULT_DECISION, null, phaseContext, canonicalizer); } } } @@ -159,7 +165,7 @@ * {@link PiNode} in the duplicated branch that corresponds to the entry. * @param phaseContext */ - public static boolean tailDuplicate(MergeNode merge, TailDuplicationDecision decision, List replacements, PhaseContext phaseContext) { + public static boolean tailDuplicate(MergeNode merge, TailDuplicationDecision decision, List replacements, PhaseContext phaseContext, CanonicalizerPhase canonicalizer) { assert !(merge instanceof LoopBeginNode); assert replacements == null || replacements.size() == merge.forwardEndCount(); FixedNode fixed = merge; @@ -172,7 +178,7 @@ metricDuplicationConsidered.increment(); if (decision.doTransform(merge, fixedCount)) { metricDuplicationPerformed.increment(); - new DuplicationOperation(merge, replacements).duplicate(phaseContext); + new DuplicationOperation(merge, replacements, canonicalizer).duplicate(phaseContext); return true; } } @@ -190,6 +196,8 @@ private final HashMap bottomPhis = new HashMap<>(); private final List replacements; + private final CanonicalizerPhase canonicalizer; + /** * Initializes the tail duplication operation without actually performing any work. * @@ -197,10 +205,11 @@ * @param replacements A list of replacement {@link PiNode}s, or null. If this is non-null, * then the size of the list needs to match the number of end nodes at the merge. */ - public DuplicationOperation(MergeNode merge, List replacements) { + public DuplicationOperation(MergeNode merge, List replacements, CanonicalizerPhase canonicalizer) { this.merge = merge; this.replacements = replacements; this.graph = merge.graph(); + this.canonicalizer = canonicalizer; } /** @@ -251,11 +260,11 @@ for (final AbstractEndNode forwardEnd : merge.forwardEnds()) { Map duplicates; if (replacements == null || replacements.get(endIndex) == null) { - duplicates = graph.addDuplicates(duplicatedNodes, (DuplicationReplacement) null); + duplicates = graph.addDuplicates(duplicatedNodes, graph, duplicatedNodes.size(), (DuplicationReplacement) null); } else { HashMap replace = new HashMap<>(); replace.put(replacements.get(endIndex).object(), replacements.get(endIndex)); - duplicates = graph.addDuplicates(duplicatedNodes, replace); + duplicates = graph.addDuplicates(duplicatedNodes, graph, duplicatedNodes.size(), replace); } for (Map.Entry phi : bottomPhis.entrySet()) { phi.getValue().initializeValueAt(merge.forwardEndIndex(forwardEnd), (ValueNode) duplicates.get(phi.getKey())); @@ -289,7 +298,7 @@ phi.setMerge(mergeAfter); } } - new CanonicalizerPhase.Instance(phaseContext.getRuntime(), phaseContext.getAssumptions(), !AOTCompilation.getValue(), graph.getNewNodes(startMark), null).apply(graph); + canonicalizer.applyIncremental(graph, phaseContext, startMark); Debug.dump(graph, "After tail duplication at %s", merge); } @@ -300,7 +309,7 @@ * @return The new {@link ValueAnchorNode} that was created. */ private ValueAnchorNode addValueAnchor() { - ValueAnchorNode anchor = graph.add(new ValueAnchorNode()); + ValueAnchorNode anchor = graph.add(new ValueAnchorNode(null)); graph.addAfterFixed(merge, anchor); for (Node usage : merge.usages().snapshot()) { if (usage instanceof PhiNode && ((PhiNode) usage).merge() == merge) { @@ -467,7 +476,7 @@ // introduce a new phi PhiNode newPhi = bottomPhis.get(node); if (newPhi == null) { - newPhi = graph.add(new PhiNode(node.kind(), newBottomMerge)); + newPhi = graph.addWithoutUnique(new PhiNode(node.kind(), newBottomMerge)); bottomPhis.put(node, newPhi); newPhi.addInput(node); } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ValueAnchorCleanupPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ValueAnchorCleanupPhase.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ValueAnchorCleanupPhase.java Wed Oct 02 13:26:31 2013 +0200 @@ -73,14 +73,15 @@ protected void node(FixedNode node) { if (node instanceof ValueAnchorNode) { ValueAnchorNode anchor = (ValueAnchorNode) node; - for (ValueNode anchored : anchor.getAnchoredNodes().snapshot()) { + ValueNode anchored = anchor.getAnchoredNode(); + if (anchored != null) { if (state.anchoredValues.contains(anchored)) { - anchor.removeAnchoredNode(anchored); + anchor.removeAnchoredNode(); } else { state.anchoredValues.add(anchored); } } - if (!anchor.isPermanent() && anchor.getAnchoredNodes().isEmpty() && anchor.usages().isEmpty()) { + if (anchor.getAnchoredNode() == null && anchor.usages().isEmpty()) { node.graph().removeFixed(anchor); } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.phases/src/com/oracle/graal/phases/BasePhase.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/BasePhase.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/BasePhase.java Wed Oct 02 13:26:31 2013 +0200 @@ -22,7 +22,10 @@ */ package com.oracle.graal.phases; +import java.util.regex.*; + import com.oracle.graal.debug.*; +import com.oracle.graal.debug.internal.*; import com.oracle.graal.nodes.*; /** @@ -32,19 +35,35 @@ */ public abstract class BasePhase { - private String name; - private static final DebugMetric metricPhaseRuns = Debug.metric("Runs"); - protected static final DebugMetric METRIC_PROCESSED_NODES = Debug.metric("ProcessedNodes"); + private final String name; + + private final DebugTimer phaseTimer; + private final DebugMetric phaseMetric; + + private static final Pattern NAME_PATTERN = Pattern.compile("[A-Z][A-Za-z0-9]+"); + + private static boolean checkName(String name) { + assert NAME_PATTERN.matcher(name).matches() : "illegal phase name: " + name; + return true; + } protected BasePhase() { - this.name = this.getClass().getSimpleName(); - if (name.endsWith("Phase")) { - name = name.substring(0, name.length() - "Phase".length()); + String nm = this.getClass().getSimpleName(); + if (nm.endsWith("Phase")) { + name = nm.substring(0, nm.length() - "Phase".length()); + } else { + name = nm; } + assert checkName(name); + phaseTimer = Debug.timer("PhaseTime_" + name); + phaseMetric = Debug.metric("PhaseCount_" + name); } protected BasePhase(String name) { + assert checkName(name); this.name = name; + phaseTimer = Debug.timer("PhaseTime_" + name); + phaseMetric = Debug.metric("PhaseCount_" + name); } protected String getDetailedName() { @@ -56,17 +75,20 @@ } public final void apply(final StructuredGraph graph, final C context, final boolean dumpGraph) { - Debug.scope(name, this, new Runnable() { + try (TimerCloseable a = phaseTimer.start()) { + + Debug.scope(name, this, new Runnable() { - public void run() { - BasePhase.this.run(graph, context); - metricPhaseRuns.increment(); - if (dumpGraph) { - Debug.dump(graph, "After phase %s", name); + public void run() { + BasePhase.this.run(graph, context); + phaseMetric.increment(); + if (dumpGraph) { + Debug.dump(graph, "After phase %s", name); + } + assert graph.verify(); } - assert graph.verify(); - } - }); + }); + } } public final String getName() { diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java Wed Oct 02 13:26:31 2013 +0200 @@ -167,6 +167,8 @@ @Option(help = "") public static final OptionValue PrintCompilation = new OptionValue<>(false); @Option(help = "") + public static final OptionValue PrintAfterCompilation = new OptionValue<>(false); + @Option(help = "") public static final OptionValue PrintProfilingInformation = new OptionValue<>(false); @Option(help = "") public static final OptionValue PrintIRWithLIR = new OptionValue<>(false); diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.phases/src/com/oracle/graal/phases/OptimisticOptimizations.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/OptimisticOptimizations.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/OptimisticOptimizations.java Wed Oct 02 13:26:31 2013 +0200 @@ -126,4 +126,9 @@ private static boolean checkDeoptimizations(ProfilingInfo profilingInfo, DeoptimizationReason reason) { return profilingInfo.getDeoptimizationCount(reason) < GraalOptions.DeoptsToDisableOptimisticOptimization.getValue(); } + + @Override + public String toString() { + return enabledOpts.toString(); + } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.phases/src/com/oracle/graal/phases/PhaseSuite.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/PhaseSuite.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/PhaseSuite.java Wed Oct 02 13:26:31 2013 +0200 @@ -26,6 +26,9 @@ import com.oracle.graal.nodes.*; +/** + * A compiler phase that can apply an ordered collection of phases to a graph. + */ public class PhaseSuite extends BasePhase { private final List> phases; diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ComputeProbabilityClosure.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ComputeProbabilityClosure.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ComputeProbabilityClosure.java Wed Oct 02 13:26:31 2013 +0200 @@ -77,8 +77,8 @@ private void adjustControlSplitProbabilities() { HashSet result = new HashSet<>(); NodeBitMap visitedNodes = new NodeBitMap(graph); - for (DeoptimizeNode n : graph.getNodes(DeoptimizeNode.class)) { - if (n.action().doesInvalidateCompilation()) { + for (AbstractDeoptimizeNode n : graph.getNodes(AbstractDeoptimizeNode.class)) { + if (!(n instanceof DeoptimizeNode) || ((DeoptimizeNode) n).action().doesInvalidateCompilation()) { findParentControlSplitNodes(result, n, visitedNodes); } } @@ -90,7 +90,7 @@ } } - private static void findParentControlSplitNodes(HashSet result, DeoptimizeNode n, NodeBitMap visitedNodes) { + private static void findParentControlSplitNodes(HashSet result, AbstractDeoptimizeNode n, NodeBitMap visitedNodes) { ArrayDeque nodes = new ArrayDeque<>(); nodes.push(n); @@ -142,9 +142,9 @@ private boolean verifyProbabilities() { if (doesNotAlwaysDeopt(graph)) { - for (DeoptimizeNode n : graph.getNodes(DeoptimizeNode.class)) { - if (n.action().doesInvalidateCompilation() && nodeProbabilities.get(n) > 0.01) { - throw new AssertionError(String.format("%s with reason %s and probability %f in graph %s", n, n.reason(), nodeProbabilities.get(n), graph)); + for (AbstractDeoptimizeNode n : graph.getNodes(AbstractDeoptimizeNode.class)) { + if (nodeProbabilities.get(n) > 0.01 && (!(n instanceof DeoptimizeNode) || ((DeoptimizeNode) n).action().doesInvalidateCompilation())) { + throw new AssertionError(String.format("%s with probability %f in graph %s", n, nodeProbabilities.get(n), graph)); } } } @@ -152,7 +152,7 @@ } private static boolean doesNotAlwaysDeopt(StructuredGraph graph) { - return graph.getNodes(ReturnNode.class).iterator().hasNext(); + return graph.getNodes().filter(ReturnNode.class).iterator().hasNext(); } private void computeLoopFactors() { diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ReentrantNodeIterator.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ReentrantNodeIterator.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ReentrantNodeIterator.java Wed Oct 02 13:26:31 2013 +0200 @@ -44,6 +44,15 @@ protected abstract StateT afterSplit(AbstractBeginNode node, StateT oldState); protected abstract Map processLoop(LoopBeginNode loop, StateT initialState); + + /** + * Determine whether iteration should continue in the current state. + * + * @param currentState + */ + protected boolean continueIteration(StateT currentState) { + return true; + } } private ReentrantNodeIterator() { @@ -59,12 +68,14 @@ LoopInfo info = new LoopInfo<>(); for (LoopEndNode end : loop.loopEnds()) { - assert blockEndStates.containsKey(end) : "no end state for " + end; - info.endStates.put(end, blockEndStates.get(end)); + if (blockEndStates.containsKey(end)) { + info.endStates.put(end, blockEndStates.get(end)); + } } for (LoopExitNode exit : loop.loopExits()) { - assert blockEndStates.containsKey(exit) : "no exit state for " + exit; - info.exitStates.put(exit, blockEndStates.get(exit)); + if (blockEndStates.containsKey(exit)) { + info.exitStates.put(exit, blockEndStates.get(exit)); + } } return info; } @@ -83,64 +94,69 @@ } else { FixedNode next = ((FixedWithNextNode) current).next(); state = closure.processNode(current, state); - current = next; + current = closure.continueIteration(state) ? next : null; } } if (current != null) { state = closure.processNode(current, state); - NodeClassIterator successors = current.successors().iterator(); - if (!successors.hasNext()) { - if (current instanceof LoopEndNode) { - blockEndStates.put(current, state); - } else if (current instanceof EndNode) { - // add the end node and see if the merge is ready for processing - MergeNode merge = ((EndNode) current).merge(); - if (merge instanceof LoopBeginNode) { - Map loopExitState = closure.processLoop((LoopBeginNode) merge, state); - for (Map.Entry entry : loopExitState.entrySet()) { - blockEndStates.put(entry.getKey(), entry.getValue()); - nodeQueue.add(entry.getKey()); - } - } else { - assert !blockEndStates.containsKey(current); + if (closure.continueIteration(state)) { + NodeClassIterator successors = current.successors().iterator(); + if (!successors.hasNext()) { + if (current instanceof LoopEndNode) { blockEndStates.put(current, state); - boolean endsVisited = true; - for (AbstractEndNode forwardEnd : merge.forwardEnds()) { - if (!blockEndStates.containsKey(forwardEnd)) { - endsVisited = false; - break; + } else if (current instanceof EndNode) { + // add the end node and see if the merge is ready for processing + MergeNode merge = ((EndNode) current).merge(); + if (merge instanceof LoopBeginNode) { + Map loopExitState = closure.processLoop((LoopBeginNode) merge, state); + for (Map.Entry entry : loopExitState.entrySet()) { + blockEndStates.put(entry.getKey(), entry.getValue()); + nodeQueue.add(entry.getKey()); + } + } else { + assert !blockEndStates.containsKey(current); + blockEndStates.put(current, state); + boolean endsVisited = true; + for (AbstractEndNode forwardEnd : merge.forwardEnds()) { + if (!blockEndStates.containsKey(forwardEnd)) { + endsVisited = false; + break; + } + } + if (endsVisited) { + ArrayList states = new ArrayList<>(merge.forwardEndCount()); + for (int i = 0; i < merge.forwardEndCount(); i++) { + AbstractEndNode forwardEnd = merge.forwardEndAt(i); + assert blockEndStates.containsKey(forwardEnd); + StateT other = blockEndStates.get(forwardEnd); + states.add(other); + } + state = closure.merge(merge, states); + current = closure.continueIteration(state) ? merge : null; + continue; } } - if (endsVisited) { - ArrayList states = new ArrayList<>(merge.forwardEndCount()); - for (int i = 0; i < merge.forwardEndCount(); i++) { - AbstractEndNode forwardEnd = merge.forwardEndAt(i); - assert blockEndStates.containsKey(forwardEnd); - StateT other = blockEndStates.get(forwardEnd); - states.add(other); - } - state = closure.merge(merge, states); - current = merge; - continue; - } } - } - } else { - FixedNode firstSuccessor = (FixedNode) successors.next(); - if (!successors.hasNext()) { - current = firstSuccessor; - continue; } else { - while (successors.hasNext()) { - AbstractBeginNode successor = (AbstractBeginNode) successors.next(); - blockEndStates.put(successor, closure.afterSplit(successor, state)); - nodeQueue.add(successor); + FixedNode firstSuccessor = (FixedNode) successors.next(); + if (!successors.hasNext()) { + current = firstSuccessor; + continue; + } else { + while (successors.hasNext()) { + AbstractBeginNode successor = (AbstractBeginNode) successors.next(); + StateT successorState = closure.afterSplit(successor, state); + if (closure.continueIteration(successorState)) { + blockEndStates.put(successor, successorState); + nodeQueue.add(successor); + } + } + state = closure.afterSplit((AbstractBeginNode) firstSuccessor, state); + current = closure.continueIteration(state) ? firstSuccessor : null; + continue; } - state = closure.afterSplit((AbstractBeginNode) firstSuccessor, state); - current = firstSuccessor; - continue; } } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ScheduledNodeIterator.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ScheduledNodeIterator.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ScheduledNodeIterator.java Wed Oct 02 13:26:31 2013 +0200 @@ -26,6 +26,7 @@ import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.cfg.*; import com.oracle.graal.phases.schedule.*; /** @@ -41,11 +42,12 @@ private FixedWithNextNode reconnect; private ListIterator iterator; - public void processNodes(List nodes, FixedWithNextNode begin) { - assert begin != null; - lastFixed = begin; + public void processNodes(Block block, SchedulePhase shedule) { + lastFixed = block.getBeginNode(); + assert lastFixed != null; reconnect = null; - iterator = nodes.listIterator(); + iterator = shedule.nodesFor(block).listIterator(); + while (iterator.hasNext()) { Node node = iterator.next(); if (!node.isAlive()) { @@ -60,7 +62,10 @@ } processNode(node); } - assert reconnect == null; + if (reconnect != null) { + assert block.getSuccessorCount() == 1; + reconnect.setNext(block.getFirstSuccessor().getBeginNode()); + } } protected void insert(FixedNode start, FixedWithNextNode end) { diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java Wed Oct 02 13:26:31 2013 +0200 @@ -36,6 +36,7 @@ import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.cfg.*; import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.virtual.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.graph.*; @@ -785,7 +786,7 @@ if (!(usage instanceof FrameState)) { throw new SchedulingError(usage.toString()); } - if (!(unscheduledUsage instanceof StateSplit || unscheduledUsage instanceof DeoptimizingNode)) { + if (!(unscheduledUsage instanceof NodeWithState)) { throw new SchedulingError(unscheduledUsage.toString()); } // Otherwise: Put the input into the same block as the usage. diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/HighTierContext.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/HighTierContext.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/tiers/HighTierContext.java Wed Oct 02 13:26:31 2013 +0200 @@ -52,4 +52,8 @@ public OptimisticOptimizations getOptimisticOptimizations() { return optimisticOpts; } + + public HighTierContext replaceAssumptions(Assumptions newAssumptions) { + return new HighTierContext(getRuntime(), newAssumptions, getReplacements(), getGraphCache(), getPhasePlan(), getOptimisticOptimizations()); + } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/GraphOrder.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/GraphOrder.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/GraphOrder.java Wed Oct 02 13:26:31 2013 +0200 @@ -39,7 +39,7 @@ NodeBitMap visited = graph.createNodeBitMap(); - for (ControlSinkNode node : graph.getNodes(ControlSinkNode.class)) { + for (ControlSinkNode node : graph.getNodes().filter(ControlSinkNode.class)) { result.visitForward(visited, node); } return result; diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/Util.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/Util.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/Util.java Wed Oct 02 13:26:31 2013 +0200 @@ -26,9 +26,6 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.debug.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.calc.*; /** * The {@code Util} class contains a motley collection of utility methods used throughout the @@ -319,14 +316,6 @@ return (short) v; } - public static boolean isFixed(Node n) { - return n instanceof FixedNode; - } - - public static boolean isFloating(Node n) { - return n instanceof FloatingNode; - } - /** * Creates an array of integers of length "size", in which each number from 0 to (size - 1) * occurs exactly once. The integers are sorted using the given comparator. This can be used to diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.phases/src/com/oracle/graal/phases/verify/VerifyUsageWithEquals.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/verify/VerifyUsageWithEquals.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/verify/VerifyUsageWithEquals.java Wed Oct 02 13:26:31 2013 +0200 @@ -73,7 +73,7 @@ if (!isEqualsMethod(graph)) { // bail out if we compare an object of type klass with == or != (except null checks) assert !(checkUsage(cn.x(), cn.y(), context.getRuntime()) && checkUsage(cn.y(), cn.x(), context.getRuntime())) : "Verifcation of " + klass.getName() + " usage failed: Comparing " + - cn.x() + " and" + cn.y() + " in " + graph.method() + " must use .equals() for object equality, not '==' or '!='"; + cn.x() + " and " + cn.y() + " in " + graph.method() + " must use .equals() for object equality, not '==' or '!='"; } } return true; diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.printer/src/com/oracle/graal/printer/BinaryGraphPrinter.java --- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/BinaryGraphPrinter.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/BinaryGraphPrinter.java Wed Oct 02 13:26:31 2013 +0200 @@ -66,6 +66,7 @@ private static final int PROPERTY_TRUE = 0x05; private static final int PROPERTY_FALSE = 0x06; private static final int PROPERTY_ARRAY = 0x07; + private static final int PROPERTY_SUBGRAPH = 0x08; private static final int KLASS = 0x00; private static final int ENUM_KLASS = 0x01; @@ -115,6 +116,17 @@ } public void print(Graph graph, String title, SchedulePhase predefinedSchedule) throws IOException { + writeByte(BEGIN_GRAPH); + writePoolObject(title); + writeGraph(graph, predefinedSchedule); + flush(); + } + + private void writeGraph(Graph graph) throws IOException { + writeGraph(graph, null); + } + + private void writeGraph(Graph graph, SchedulePhase predefinedSchedule) throws IOException { SchedulePhase schedule = predefinedSchedule; if (schedule == null) { try { @@ -126,11 +138,8 @@ ControlFlowGraph cfg = schedule == null ? null : schedule.getCFG(); BlockMap> blockToNodes = schedule == null ? null : schedule.getBlockToNodesMap(); Block[] blocks = cfg == null ? null : cfg.getBlocks(); - writeByte(BEGIN_GRAPH); - writePoolObject(title); writeNodes(graph); writeBlocks(blocks, blockToNodes); - flush(); } private void flush() throws IOException { @@ -343,6 +352,9 @@ } else { writeByte(PROPERTY_FALSE); } + } else if (obj instanceof Graph) { + writeByte(PROPERTY_SUBGRAPH); + writeGraph((Graph) obj); } else if (obj != null && obj.getClass().isArray()) { Class componentType = obj.getClass().getComponentType(); if (componentType.isPrimitive()) { diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java --- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java Wed Oct 02 13:26:31 2013 +0200 @@ -243,12 +243,6 @@ out.println("HIR"); out.disableIndentation(); - if (block.getPredecessorCount() == 0) { - // Currently method parameters are not in the schedule, so print them separately here. - for (ValueNode param : block.getBeginNode().graph().getNodes(LocalNode.class)) { - printNode(param, false); - } - } if (block.getBeginNode() instanceof MergeNode) { // Currently phi functions are not in the schedule, so print them separately here. for (ValueNode phi : ((MergeNode) block.getBeginNode()).phis()) { diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.printer/src/com/oracle/graal/printer/DebugEnvironment.java --- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/DebugEnvironment.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/DebugEnvironment.java Wed Oct 02 13:26:31 2013 +0200 @@ -34,7 +34,10 @@ public class DebugEnvironment { public static void initialize(PrintStream log) { - Debug.enable(); + if (!Debug.isEnabled()) { + log.println("WARNING: Scope debugging needs to be enabled with -esa or -D" + Debug.Initialization.INITIALIZER_PROPERTY_NAME + "=true"); + return; + } List dumpHandlers = new ArrayList<>(); dumpHandlers.add(new GraphPrinterDumpHandler()); if (PrintCFG.getValue() || PrintBackendCFG.getValue()) { diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.ptx/src/com/oracle/graal/ptx/PTX.java --- a/graal/com.oracle.graal.ptx/src/com/oracle/graal/ptx/PTX.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.ptx/src/com/oracle/graal/ptx/PTX.java Wed Oct 02 13:26:31 2013 +0200 @@ -35,83 +35,167 @@ */ public class PTX extends Architecture { - public static final RegisterCategory CPU = new RegisterCategory("CPU"); - public static final RegisterCategory FPU = new RegisterCategory("FPU"); + public static final RegisterCategory REG = new RegisterCategory("REG"); + public static final RegisterCategory SREG = new RegisterCategory("SREG"); + public static final RegisterCategory PARAM = new RegisterCategory("PARAM"); + // @formatter:off /* * Register State Space * - * Registers (.reg state space) are fast storage locations. The number of - * registers is limited, and will vary from platform to platform. When the - * limit is exceeded, register variables will be spilled to memory, causing - * changes in performance. For each architecture, there is a recommended - * maximum number of registers to use (see the "CUDA Programming Guide" for - * details). + * Registers (.reg state space) are fast storage locations. The + * number of GPU architectural registers is limited, and will vary + * from platform to platform. When the limit is exceeded, register + * variables will be spilled to memory, causing changes in + * performance. For each architecture, there is a recommended + * maximum number of registers to use (see the "CUDA Programming + * Guide" for details). + * + * TODD: XXX + * + * However, PTX supports virtual registers. So, the generated PTX + * code does not need to use a specified number of registers. Till + * we figure out how to model a virtual register set in Graal, we + * will pretend that we can use only 16 registers. */ - // General purpose registers - public static final Register r0 = new Register(0, 0, "r0", CPU); - public static final Register r1 = new Register(1, 1, "r1", CPU); - public static final Register r2 = new Register(2, 2, "r2", CPU); - public static final Register r3 = new Register(3, 3, "r3", CPU); - public static final Register r4 = new Register(4, 4, "r4", CPU); - public static final Register r5 = new Register(5, 5, "r5", CPU); - public static final Register r6 = new Register(6, 6, "r6", CPU); - public static final Register r7 = new Register(7, 7, "r7", CPU); + public static final Register r0 = new Register(0, 0, "r0", REG); + public static final Register r1 = new Register(1, 1, "r1", REG); + public static final Register r2 = new Register(2, 2, "r2", REG); + public static final Register r3 = new Register(3, 3, "r3", REG); + public static final Register r4 = new Register(4, 4, "r4", REG); + public static final Register r5 = new Register(5, 5, "r5", REG); + public static final Register r6 = new Register(6, 6, "r6", REG); + public static final Register r7 = new Register(7, 7, "r7", REG); - public static final Register r8 = new Register(8, 8, "r8", CPU); - public static final Register r9 = new Register(9, 9, "r9", CPU); - public static final Register r10 = new Register(10, 10, "r10", CPU); - public static final Register r11 = new Register(11, 11, "r11", CPU); - public static final Register r12 = new Register(12, 12, "r12", CPU); - public static final Register r13 = new Register(13, 13, "r13", CPU); - public static final Register r14 = new Register(14, 14, "r14", CPU); - public static final Register r15 = new Register(15, 15, "r15", CPU); + public static final Register r8 = new Register(8, 8, "r8", REG); + public static final Register r9 = new Register(9, 9, "r9", REG); + public static final Register r10 = new Register(10, 10, "r10", REG); + public static final Register r11 = new Register(11, 11, "r11", REG); + public static final Register r12 = new Register(12, 12, "r12", REG); + public static final Register r13 = new Register(13, 13, "r13", REG); + public static final Register r14 = new Register(14, 14, "r14", REG); + public static final Register r15 = new Register(15, 15, "r15", REG); public static final Register[] gprRegisters = { r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15 }; - // Floating point registers - public static final Register f0 = new Register(16, 0, "f0", FPU); - public static final Register f1 = new Register(17, 1, "f1", FPU); - public static final Register f2 = new Register(18, 2, "f2", FPU); - public static final Register f3 = new Register(19, 3, "f3", FPU); - public static final Register f4 = new Register(20, 4, "f4", FPU); - public static final Register f5 = new Register(21, 5, "f5", FPU); - public static final Register f6 = new Register(22, 6, "f6", FPU); - public static final Register f7 = new Register(23, 7, "f7", FPU); + /* Parameter State Space + * + * The parameter (.param) state space is used (1) to pass input + * arguments from the host to the kernel, (2a) to declare formal + * input and return parameters for device functions called from + * within kernel execution, and (2b) to declare locally-scoped + * byte array variables that serve as function call arguments, + * typically for passing large structures by value to a function. + * + * TODO: XXX + * The parameters are virtual symbols - just like registers. Bit, + * Till we figure out how to model a virtual register set in Graal, + * we will pretend that we can use only 8 parameters. + */ + + public static final Register param0 = new Register(16, 16, "param0", PARAM); + public static final Register param1 = new Register(17, 17, "param1", PARAM); + public static final Register param2 = new Register(18, 18, "param2", PARAM); + public static final Register param3 = new Register(19, 19, "param3", PARAM); + public static final Register param4 = new Register(20, 20, "param4", PARAM); + public static final Register param5 = new Register(21, 21, "param5", PARAM); + public static final Register param6 = new Register(22, 22, "param6", PARAM); + public static final Register param7 = new Register(23, 23, "param7", PARAM); + + public static final Register[] paramRegisters = { + param0, param1, param2, param3, param4, param5, param6, param7 + }; + + // Define a virtual register that holds return value + public static final Register retReg = new Register(24, 24, "retReg", REG); + + // PTX ISA Manual: Section 9:. Special Registers - public static final Register f8 = new Register(24, 8, "f8", FPU); - public static final Register f9 = new Register(25, 9, "f9", FPU); - public static final Register f10 = new Register(26, 10, "f10", FPU); - public static final Register f11 = new Register(27, 11, "f11", FPU); - public static final Register f12 = new Register(28, 12, "f12", FPU); - public static final Register f13 = new Register(29, 13, "f13", FPU); - public static final Register f14 = new Register(30, 14, "f14", FPU); - public static final Register f15 = new Register(31, 15, "f15", FPU); + // PTX includes a number of predefined, read-only variables, which + // are visible as special registers and accessed through mov or + // cvt instructions. + // Thread identifier within a Co-operative Thread Array (CTA) - %tid + public static final Register tid = new Register(100, 100, "tid", SREG); + // Number of thread IDs per CTA - %ntid + public static final Register ntid = new Register(101, 101, "ntid", SREG); + // Lane identifier + public static final Register laneid = new Register(102, 102, "laneid", SREG); + // Warp identifier + public static final Register warpid = new Register(103, 103, "warid", SREG); + // Number of warp IDs + public static final Register nwarpid = new Register(104, 104, "nwarpid", SREG); + // CTA identifier + public static final Register ctaid = new Register(105, 105, "ctaid", SREG); + // Number of CTA IDs per grid + public static final Register nctaid = new Register(106, 106, "nctaid", SREG); + // Single Multiprocessor (SM) ID + public static final Register smid = new Register(107, 107, "smid", SREG); + // Number of SM IDs + public static final Register nsmid = new Register(108, 108, "nsmid", SREG); + // Grid ID + public static final Register gridid = new Register(109, 109, "gridid", SREG); + // 32-bit mask with bit set in position equal to thread's lane number in the warp + public static final Register lanemask_eq = new Register(110, 110, "lanemask_eq", SREG); + // 32-bit mask with bits set in positions less than or equal to thread's lane number in the warp + public static final Register lanemask_le = new Register(111, 111, "lanemask_le", SREG); + // 32-bit mask with bits set in positions less than thread's lane number in the warp + public static final Register lanemask_lt = new Register(112, 112, "lanemask_lt", SREG); + // 32-bit mask with bits set in positions greater than or equal to thread's lane number in the warp + public static final Register lanemask_ge = new Register(113, 113, "lanemask_ge", SREG); + // 32-bit mask with bits set in positions greater than thread's lane number in the warp + public static final Register lanemask_gt = new Register(114, 114, "lanemask_gt", SREG); + // A predefined, read-only 32-bit unsigned 32-bit unsigned cycle counter + public static final Register clock = new Register(114, 114, "clock", SREG); + // A predefined, read-only 64-bit unsigned 32-bit unsigned cycle counter + public static final Register clock64 = new Register(115, 115, "clock64", SREG); + // Performance monitoring registers + public static final Register pm0 = new Register(116, 116, "pm0", SREG); + public static final Register pm1 = new Register(117, 117, "pm1", SREG); + public static final Register pm2 = new Register(118, 118, "pm2", SREG); + public static final Register pm3 = new Register(119, 119, "pm3", SREG); + public static final Register pm4 = new Register(120, 120, "pm4", SREG); + public static final Register pm5 = new Register(121, 121, "pm5", SREG); + public static final Register pm6 = new Register(122, 122, "pm6", SREG); + public static final Register pm7 = new Register(123, 123, "pm7", SREG); + // TODO: Add Driver-defined read-only %envreg<32> + // and %globaltimer, %globaltimer_lo and %globaltimer_hi - public static final Register[] fpuRegisters = { - f0, f1, f2, f3, f4, f5, f6, f7, - f8, f9, f10, f11, f12, f13, f14, f15 + public static final Register[] specialRegisters = { + tid, ntid, laneid, warpid, nwarpid, ctaid, + nctaid, smid, nsmid, gridid, + lanemask_eq, lanemask_le, lanemask_lt, lanemask_ge, lanemask_gt, + clock, clock64, + pm0, pm1, pm2, pm3, pm4, pm5, pm6, pm7 }; public static final Register[] allRegisters = { - // GPR + // Parameter State Space + param0, param1, param2, param3, + param4, param5, param6, param7, + // Register State Space r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15, - // FPU - f0, f1, f2, f3, f4, f5, f6, f7, - f8, f9, f10, f11, f12, f13, f14, f15 + // return register + retReg, + // Special Register State Space - SREG + tid, ntid, laneid, warpid, nwarpid, ctaid, + nctaid, smid, nsmid, gridid, + lanemask_eq, lanemask_le, lanemask_lt, lanemask_ge, lanemask_gt, + clock, clock64, + pm0, pm1, pm2, pm3, pm4, pm5, pm6, pm7 }; // @formatter:on public PTX() { - super("PTX", 8, ByteOrder.LITTLE_ENDIAN, false, allRegisters, LOAD_STORE | STORE_STORE, 0, r15.encoding + 1, 8); + super("PTX", 8, ByteOrder.LITTLE_ENDIAN, false, allRegisters, + LOAD_STORE | STORE_STORE, 0, r15.encoding + 1, 8); } @Override @@ -121,7 +205,7 @@ } Kind kind = (Kind) platformKind; - if (category == CPU) { + if (category == REG) { switch (kind) { case Boolean: case Byte: @@ -130,10 +214,6 @@ case Int: case Long: case Object: - return true; - } - } else if (category == FPU) { - switch (kind) { case Float: case Double: return true; @@ -145,12 +225,12 @@ @Override public PlatformKind getLargestStorableKind(RegisterCategory category) { - if (category == CPU) { - return Kind.Long; - } else if (category == FPU) { + if (category == REG) { return Kind.Double; } else { return Kind.Illegal; } } + + } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64ConvertNode.java --- a/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64ConvertNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64ConvertNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -22,17 +22,17 @@ */ package com.oracle.graal.replacements.amd64; +import com.oracle.graal.api.meta.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.calc.ConvertNode.Op; -import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; /** * This node has the semantics of the AMD64 conversions. It is used in the lowering of the - * ConvertNode which, on AMD64 needs a AMD64ConvertNode plus some fixup code that handles the corner - * cases that differ between AMD64 and Java. - * + * {@link ConvertNode} which, on AMD64 needs a {@link AMD64ConvertNode} plus some fixup code that + * handles the corner cases that differ between AMD64 and Java. */ public class AMD64ConvertNode extends FloatingNode implements ArithmeticLIRLowerable { @@ -45,6 +45,12 @@ this.value = value; } + public Constant evalConst(Constant... inputs) { + // this node should never have been created if its input is constant + assert false; + return null; + } + public void generate(ArithmeticLIRGenerator gen) { gen.setResult(this, gen.emitConvert(opcode, gen.operand(value))); } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64ConvertSnippets.java --- a/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64ConvertSnippets.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64ConvertSnippets.java Wed Oct 02 13:26:31 2013 +0200 @@ -172,15 +172,16 @@ // Convert node are replaced by the placeholder which in turn is replaced by the // snippet. - LocalNode replacee = graph.add(new LocalNode(Integer.MAX_VALUE, convert.stamp())); + LocalNode replacee = graph.addWithoutUnique(new LocalNode(Integer.MAX_VALUE, convert.stamp())); convert.replaceAtUsages(replacee); - Arguments args = new Arguments(key); + Arguments args = new Arguments(key, graph.getGuardsStage()); args.add("input", convert.value()); args.add("result", convert.graph().unique(new AMD64ConvertNode(convert.opcode, convert.value()))); SnippetTemplate template = template(args); Debug.log("Lowering %s in %s: node=%s, template=%s, arguments=%s", convert.opcode, graph, convert, template, args); template.instantiate(runtime, replacee, DEFAULT_REPLACER, tool, args); + graph.removeFloating(convert); } } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/CheckCastTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/CheckCastTest.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/CheckCastTest.java Wed Oct 02 13:26:31 2013 +0200 @@ -34,7 +34,7 @@ @Override protected void replaceProfile(StructuredGraph graph, JavaTypeProfile profile) { - CheckCastNode ccn = graph.getNodes(CheckCastNode.class).first(); + CheckCastNode ccn = graph.getNodes().filter(CheckCastNode.class).first(); if (ccn != null) { CheckCastNode ccnNew = graph.add(new CheckCastNode(ccn.type(), ccn.object(), profile, false)); graph.replaceFixedWithFixed(ccn, ccnNew); diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/InstanceOfTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/InstanceOfTest.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/InstanceOfTest.java Wed Oct 02 13:26:31 2013 +0200 @@ -49,7 +49,7 @@ protected void replaceProfile(StructuredGraph graph, JavaTypeProfile profile) { InstanceOfNode ion = graph.getNodes().filter(InstanceOfNode.class).first(); if (ion != null) { - InstanceOfNode ionNew = graph.add(new InstanceOfNode(ion.type(), ion.object(), profile)); + InstanceOfNode ionNew = graph.unique(new InstanceOfNode(ion.type(), ion.object(), profile)); graph.replaceFloating(ion, ionNew); } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/MethodSubstitutionTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/MethodSubstitutionTest.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/MethodSubstitutionTest.java Wed Oct 02 13:26:31 2013 +0200 @@ -53,7 +53,7 @@ Assumptions assumptions = new Assumptions(true); HighTierContext context = new HighTierContext(runtime(), assumptions, replacements, null, phasePlan, OptimisticOptimizations.ALL); Debug.dump(graph, "Graph"); - new InliningPhase().apply(graph, context); + new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context); Debug.dump(graph, "Graph"); new CanonicalizerPhase(true).apply(graph, context); new DeadCodeEliminationPhase().apply(graph); diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/MonitorTest.java diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ObjectAccessTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ObjectAccessTest.java Wed Oct 02 13:26:31 2013 +0200 @@ -0,0 +1,390 @@ +/* + * 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.replacements.test; + +import java.lang.reflect.*; + +import org.junit.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.runtime.*; +import com.oracle.graal.compiler.test.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.replacements.*; +import com.oracle.graal.replacements.Snippet.SnippetInliningPolicy; +import com.oracle.graal.word.*; + +/** + * Tests for the {@link Pointer} read and write operations. + */ +public class ObjectAccessTest extends GraalCompilerTest implements Snippets { + + private static final LocationIdentity ID = new NamedLocationIdentity("ID"); + private static final Kind[] KINDS = new Kind[]{Kind.Byte, Kind.Char, Kind.Short, Kind.Int, Kind.Long, Kind.Float, Kind.Double, Kind.Object}; + private final TargetDescription target; + private final ReplacementsImpl installer; + + public ObjectAccessTest() { + target = Graal.getRequiredCapability(CodeCacheProvider.class).getTarget(); + installer = new ReplacementsImpl(runtime, new Assumptions(false), target); + } + + private static final ThreadLocal inliningPolicy = new ThreadLocal<>(); + + @Override + protected StructuredGraph parse(Method m) { + ResolvedJavaMethod resolvedMethod = runtime.lookupJavaMethod(m); + return installer.makeGraph(resolvedMethod, null, inliningPolicy.get()); + } + + @Test + public void testRead1() { + for (Kind kind : KINDS) { + assertRead(parse("read" + kind.name() + "1"), kind, false, ID); + } + } + + @Test + public void testRead2() { + for (Kind kind : KINDS) { + assertRead(parse("read" + kind.name() + "2"), kind, true, ID); + } + } + + @Test + public void testRead3() { + for (Kind kind : KINDS) { + assertRead(parse("read" + kind.name() + "3"), kind, false, LocationIdentity.ANY_LOCATION); + } + } + + @Test + public void testWrite1() { + for (Kind kind : KINDS) { + assertWrite(parse("write" + kind.name() + "1"), kind, false, ID); + } + } + + @Test + public void testWrite2() { + for (Kind kind : KINDS) { + assertWrite(parse("write" + kind.name() + "2"), kind, true, ID); + } + } + + @Test + public void testWrite3() { + for (Kind kind : KINDS) { + assertWrite(parse("write" + kind.name() + "3"), kind, false, LocationIdentity.ANY_LOCATION); + } + } + + private static void assertRead(StructuredGraph graph, Kind kind, boolean indexConvert, LocationIdentity locationIdentity) { + ReadNode read = (ReadNode) graph.start().next(); + Assert.assertEquals(kind.getStackKind(), read.kind()); + Assert.assertEquals(graph.getLocal(0), read.object()); + + IndexedLocationNode location = (IndexedLocationNode) read.location(); + Assert.assertEquals(kind, location.getValueKind()); + Assert.assertEquals(locationIdentity, location.getLocationIdentity()); + Assert.assertEquals(1, location.getIndexScaling()); + + if (indexConvert) { + ConvertNode convert = (ConvertNode) location.getIndex(); + Assert.assertEquals(ConvertNode.Op.I2L, convert.opcode); + Assert.assertEquals(graph.getLocal(1), convert.value()); + } else { + Assert.assertEquals(graph.getLocal(1), location.getIndex()); + } + + ReturnNode ret = (ReturnNode) read.next(); + Assert.assertEquals(read, ret.result()); + } + + private static void assertWrite(StructuredGraph graph, Kind kind, boolean indexConvert, LocationIdentity locationIdentity) { + WriteNode write = (WriteNode) graph.start().next(); + Assert.assertEquals(graph.getLocal(2), write.value()); + Assert.assertEquals(graph.getLocal(0), write.object()); + Assert.assertEquals(Kind.Void, write.kind()); + Assert.assertEquals(FrameState.AFTER_BCI, write.stateAfter().bci); + + IndexedLocationNode location = (IndexedLocationNode) write.location(); + Assert.assertEquals(kind, location.getValueKind()); + Assert.assertEquals(locationIdentity, location.getLocationIdentity()); + Assert.assertEquals(1, location.getIndexScaling()); + + if (indexConvert) { + ConvertNode convert = (ConvertNode) location.getIndex(); + Assert.assertEquals(ConvertNode.Op.I2L, convert.opcode); + Assert.assertEquals(graph.getLocal(1), convert.value()); + } else { + Assert.assertEquals(graph.getLocal(1), location.getIndex()); + } + + ReturnNode ret = (ReturnNode) write.next(); + Assert.assertEquals(null, ret.result()); + } + + @Snippet + public static byte readByte1(Object o, int offset) { + return ObjectAccess.readByte(o, offset, ID); + } + + @Snippet + public static byte readByte2(Object o, int offset) { + return ObjectAccess.readByte(o, Word.signed(offset), ID); + } + + @Snippet + public static byte readByte3(Object o, int offset) { + return ObjectAccess.readByte(o, offset); + } + + @Snippet + public static void writeByte1(Object o, int offset, byte value) { + ObjectAccess.writeByte(o, offset, value, ID); + } + + @Snippet + public static void writeByte2(Object o, int offset, byte value) { + ObjectAccess.writeByte(o, Word.signed(offset), value, ID); + } + + @Snippet + public static void writeByte3(Object o, int offset, byte value) { + ObjectAccess.writeByte(o, offset, value); + } + + @Snippet + public static char readChar1(Object o, int offset) { + return ObjectAccess.readChar(o, offset, ID); + } + + @Snippet + public static char readChar2(Object o, int offset) { + return ObjectAccess.readChar(o, Word.signed(offset), ID); + } + + @Snippet + public static char readChar3(Object o, int offset) { + return ObjectAccess.readChar(o, offset); + } + + @Snippet + public static void writeChar1(Object o, int offset, char value) { + ObjectAccess.writeChar(o, offset, value, ID); + } + + @Snippet + public static void writeChar2(Object o, int offset, char value) { + ObjectAccess.writeChar(o, Word.signed(offset), value, ID); + } + + @Snippet + public static void writeChar3(Object o, int offset, char value) { + ObjectAccess.writeChar(o, offset, value); + } + + @Snippet + public static short readShort1(Object o, int offset) { + return ObjectAccess.readShort(o, offset, ID); + } + + @Snippet + public static short readShort2(Object o, int offset) { + return ObjectAccess.readShort(o, Word.signed(offset), ID); + } + + @Snippet + public static short readShort3(Object o, int offset) { + return ObjectAccess.readShort(o, offset); + } + + @Snippet + public static void writeShort1(Object o, int offset, short value) { + ObjectAccess.writeShort(o, offset, value, ID); + } + + @Snippet + public static void writeShort2(Object o, int offset, short value) { + ObjectAccess.writeShort(o, Word.signed(offset), value, ID); + } + + @Snippet + public static void writeShort3(Object o, int offset, short value) { + ObjectAccess.writeShort(o, offset, value); + } + + @Snippet + public static int readInt1(Object o, int offset) { + return ObjectAccess.readInt(o, offset, ID); + } + + @Snippet + public static int readInt2(Object o, int offset) { + return ObjectAccess.readInt(o, Word.signed(offset), ID); + } + + @Snippet + public static int readInt3(Object o, int offset) { + return ObjectAccess.readInt(o, offset); + } + + @Snippet + public static void writeInt1(Object o, int offset, int value) { + ObjectAccess.writeInt(o, offset, value, ID); + } + + @Snippet + public static void writeInt2(Object o, int offset, int value) { + ObjectAccess.writeInt(o, Word.signed(offset), value, ID); + } + + @Snippet + public static void writeInt3(Object o, int offset, int value) { + ObjectAccess.writeInt(o, offset, value); + } + + @Snippet + public static long readLong1(Object o, int offset) { + return ObjectAccess.readLong(o, offset, ID); + } + + @Snippet + public static long readLong2(Object o, int offset) { + return ObjectAccess.readLong(o, Word.signed(offset), ID); + } + + @Snippet + public static long readLong3(Object o, int offset) { + return ObjectAccess.readLong(o, offset); + } + + @Snippet + public static void writeLong1(Object o, int offset, long value) { + ObjectAccess.writeLong(o, offset, value, ID); + } + + @Snippet + public static void writeLong2(Object o, int offset, long value) { + ObjectAccess.writeLong(o, Word.signed(offset), value, ID); + } + + @Snippet + public static void writeLong3(Object o, int offset, long value) { + ObjectAccess.writeLong(o, offset, value); + } + + @Snippet + public static float readFloat1(Object o, int offset) { + return ObjectAccess.readFloat(o, offset, ID); + } + + @Snippet + public static float readFloat2(Object o, int offset) { + return ObjectAccess.readFloat(o, Word.signed(offset), ID); + } + + @Snippet + public static float readFloat3(Object o, int offset) { + return ObjectAccess.readFloat(o, offset); + } + + @Snippet + public static void writeFloat1(Object o, int offset, float value) { + ObjectAccess.writeFloat(o, offset, value, ID); + } + + @Snippet + public static void writeFloat2(Object o, int offset, float value) { + ObjectAccess.writeFloat(o, Word.signed(offset), value, ID); + } + + @Snippet + public static void writeFloat3(Object o, int offset, float value) { + ObjectAccess.writeFloat(o, offset, value); + } + + @Snippet + public static double readDouble1(Object o, int offset) { + return ObjectAccess.readDouble(o, offset, ID); + } + + @Snippet + public static double readDouble2(Object o, int offset) { + return ObjectAccess.readDouble(o, Word.signed(offset), ID); + } + + @Snippet + public static double readDouble3(Object o, int offset) { + return ObjectAccess.readDouble(o, offset); + } + + @Snippet + public static void writeDouble1(Object o, int offset, double value) { + ObjectAccess.writeDouble(o, offset, value, ID); + } + + @Snippet + public static void writeDouble2(Object o, int offset, double value) { + ObjectAccess.writeDouble(o, Word.signed(offset), value, ID); + } + + @Snippet + public static void writeDouble3(Object o, int offset, double value) { + ObjectAccess.writeDouble(o, offset, value); + } + + @Snippet + public static Object readObject1(Object o, int offset) { + return ObjectAccess.readObject(o, offset, ID); + } + + @Snippet + public static Object readObject2(Object o, int offset) { + return ObjectAccess.readObject(o, Word.signed(offset), ID); + } + + @Snippet + public static Object readObject3(Object o, int offset) { + return ObjectAccess.readObject(o, offset); + } + + @Snippet + public static void writeObject1(Object o, int offset, Object value) { + ObjectAccess.writeObject(o, offset, value, ID); + } + + @Snippet + public static void writeObject2(Object o, int offset, Object value) { + ObjectAccess.writeObject(o, Word.signed(offset), value, ID); + } + + @Snippet + public static void writeObject3(Object o, int offset, Object value) { + ObjectAccess.writeObject(o, offset, value); + } +} diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/PointerTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/PointerTest.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/PointerTest.java Wed Oct 02 13:26:31 2013 +0200 @@ -33,9 +33,13 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.phases.*; +import com.oracle.graal.phases.common.*; +import com.oracle.graal.phases.tiers.*; import com.oracle.graal.replacements.*; -import com.oracle.graal.replacements.Snippet.*; +import com.oracle.graal.replacements.Snippet.SnippetInliningPolicy; import com.oracle.graal.word.*; +import com.oracle.graal.word.nodes.*; /** * Tests for the {@link Pointer} read and write operations. @@ -103,11 +107,13 @@ } private void assertRead(StructuredGraph graph, Kind kind, boolean indexConvert, LocationIdentity locationIdentity) { - ReadNode read = (ReadNode) graph.start().next(); + WordCastNode cast = (WordCastNode) graph.start().next(); + + ReadNode read = (ReadNode) cast.next(); Assert.assertEquals(kind.getStackKind(), read.kind()); - UnsafeCastNode cast = (UnsafeCastNode) read.object(); - Assert.assertEquals(graph.getLocal(0), cast.object()); + Assert.assertEquals(cast, read.object()); + Assert.assertEquals(graph.getLocal(0), cast.getInput()); Assert.assertEquals(target.wordKind, cast.kind()); IndexedLocationNode location = (IndexedLocationNode) read.location(); @@ -128,13 +134,15 @@ } private void assertWrite(StructuredGraph graph, Kind kind, boolean indexConvert, LocationIdentity locationIdentity) { - WriteNode write = (WriteNode) graph.start().next(); + WordCastNode cast = (WordCastNode) graph.start().next(); + + WriteNode write = (WriteNode) cast.next(); Assert.assertEquals(graph.getLocal(2), write.value()); Assert.assertEquals(Kind.Void, write.kind()); - Assert.assertEquals(FrameState.INVALID_FRAMESTATE_BCI, write.stateAfter().bci); + Assert.assertEquals(FrameState.AFTER_BCI, write.stateAfter().bci); - UnsafeCastNode cast = (UnsafeCastNode) write.object(); - Assert.assertEquals(graph.getLocal(0), cast.object()); + Assert.assertEquals(cast, write.object()); + Assert.assertEquals(graph.getLocal(0), cast.getInput()); Assert.assertEquals(target.wordKind, cast.kind()); IndexedLocationNode location = (IndexedLocationNode) write.location(); @@ -150,10 +158,7 @@ Assert.assertEquals(graph.getLocal(1), location.getIndex()); } - AbstractStateSplit stateSplit = (AbstractStateSplit) write.next(); - Assert.assertEquals(FrameState.AFTER_BCI, stateSplit.stateAfter().bci); - - ReturnNode ret = (ReturnNode) stateSplit.next(); + ReturnNode ret = (ReturnNode) write.next(); Assert.assertEquals(null, ret.result()); } @@ -397,4 +402,62 @@ Word.fromObject(o).writeObject(offset, value); } + private void assertNumWordCasts(String snippetName, int expectedWordCasts) { + Assumptions assumptions = new Assumptions(true); + HighTierContext context = new HighTierContext(runtime(), assumptions, replacements, null, null, OptimisticOptimizations.ALL); + + StructuredGraph graph = parse(snippetName); + new CanonicalizerPhase(false).apply(graph, context); + Assert.assertEquals(expectedWordCasts, graph.getNodes().filter(WordCastNode.class).count()); + } + + @Test + public void testUnusedFromObject() { + assertNumWordCasts("unusedFromObject", 0); + } + + @Snippet + public static void unusedFromObject(Object o) { + Word.fromObject(o); + } + + @Test + public void testUnusedRawValue() { + assertNumWordCasts("unusedRawValue", 0); + } + + @Snippet + public static void unusedRawValue(Object o) { + Word.fromObject(o).rawValue(); + } + + @Test + public void testUsedRawValue() { + assertNumWordCasts("usedRawValue", 1); + } + + @Snippet + public static long usedRawValue(Object o) { + return Word.fromObject(o).rawValue(); + } + + @Test + public void testUnusedToObject() { + assertNumWordCasts("unusedToObject", 0); + } + + @Snippet + public static void unusedToObject(Word w) { + w.toObject(); + } + + @Test + public void testUsedToObject() { + assertNumWordCasts("usedToObject", 1); + } + + @Snippet + public static Object usedToObject(Word w) { + return w.toObject(); + } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/BoxingSnippets.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/BoxingSnippets.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/BoxingSnippets.java Wed Oct 02 13:26:31 2013 +0200 @@ -79,49 +79,49 @@ @Snippet(inlining = BoxingSnippetInliningPolicy.class) public static Boolean booleanValueOf(boolean value) { valueOfCounter.inc(); - return UnsafeCastNode.unsafeCast(Boolean.valueOf(value), StampFactory.forNodeIntrinsic()); + return PiNode.piCast(Boolean.valueOf(value), StampFactory.forNodeIntrinsic()); } @Snippet(inlining = BoxingSnippetInliningPolicy.class) public static Byte byteValueOf(byte value) { valueOfCounter.inc(); - return UnsafeCastNode.unsafeCast(Byte.valueOf(value), StampFactory.forNodeIntrinsic()); + return PiNode.piCast(Byte.valueOf(value), StampFactory.forNodeIntrinsic()); } @Snippet(inlining = BoxingSnippetInliningPolicy.class) public static Character charValueOf(char value) { valueOfCounter.inc(); - return UnsafeCastNode.unsafeCast(Character.valueOf(value), StampFactory.forNodeIntrinsic()); + return PiNode.piCast(Character.valueOf(value), StampFactory.forNodeIntrinsic()); } @Snippet(inlining = BoxingSnippetInliningPolicy.class) public static Double doubleValueOf(double value) { valueOfCounter.inc(); - return UnsafeCastNode.unsafeCast(Double.valueOf(value), StampFactory.forNodeIntrinsic()); + return PiNode.piCast(Double.valueOf(value), StampFactory.forNodeIntrinsic()); } @Snippet(inlining = BoxingSnippetInliningPolicy.class) public static Float floatValueOf(float value) { valueOfCounter.inc(); - return UnsafeCastNode.unsafeCast(Float.valueOf(value), StampFactory.forNodeIntrinsic()); + return PiNode.piCast(Float.valueOf(value), StampFactory.forNodeIntrinsic()); } @Snippet(inlining = BoxingSnippetInliningPolicy.class) public static Integer intValueOf(int value) { valueOfCounter.inc(); - return UnsafeCastNode.unsafeCast(Integer.valueOf(value), StampFactory.forNodeIntrinsic()); + return PiNode.piCast(Integer.valueOf(value), StampFactory.forNodeIntrinsic()); } @Snippet(inlining = BoxingSnippetInliningPolicy.class) public static Long longValueOf(long value) { valueOfCounter.inc(); - return UnsafeCastNode.unsafeCast(Long.valueOf(value), StampFactory.forNodeIntrinsic()); + return PiNode.piCast(Long.valueOf(value), StampFactory.forNodeIntrinsic()); } @Snippet(inlining = BoxingSnippetInliningPolicy.class) public static Short shortValueOf(short value) { valueOfCounter.inc(); - return UnsafeCastNode.unsafeCast(Short.valueOf(value), StampFactory.forNodeIntrinsic()); + return PiNode.piCast(Short.valueOf(value), StampFactory.forNodeIntrinsic()); } @Snippet(inlining = BoxingSnippetInliningPolicy.class) @@ -220,7 +220,7 @@ if (canonical != null && !AOTCompilation.getValue()) { box.graph().replaceFloating(box, canonical); } else { - Arguments args = new Arguments(boxSnippets.get(box.getBoxingKind())); + Arguments args = new Arguments(boxSnippets.get(box.getBoxingKind()), box.graph().getGuardsStage()); args.add("value", box.getValue()); SnippetTemplate template = template(args); @@ -231,7 +231,7 @@ } public void lower(UnboxNode unbox, LoweringTool tool) { - Arguments args = new Arguments(unboxSnippets.get(unbox.getBoxingKind())); + Arguments args = new Arguments(unboxSnippets.get(unbox.getBoxingKind()), unbox.graph().getGuardsStage()); args.add("value", unbox.getValue()); SnippetTemplate template = template(args); diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/InstanceOfSnippetsTemplates.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/InstanceOfSnippetsTemplates.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/InstanceOfSnippetsTemplates.java Wed Oct 02 13:26:31 2013 +0200 @@ -93,7 +93,7 @@ */ protected InstanceOfUsageReplacer createReplacer(FloatingNode instanceOf, Instantiation instantiation, Node usage, final StructuredGraph graph) { InstanceOfUsageReplacer replacer; - if (usage instanceof IfNode || usage instanceof FixedGuardNode || usage instanceof ShortCircuitBooleanNode || usage instanceof GuardingPiNode) { + if (usage instanceof IfNode || usage instanceof FixedGuardNode || usage instanceof ShortCircuitOrNode || usage instanceof GuardingPiNode) { replacer = new NonMaterializationUsageReplacer(instantiation, ConstantNode.forInt(1, graph), ConstantNode.forInt(0, graph), instanceOf, usage); } else { assert usage instanceof ConditionalNode : "unexpected usage of " + instanceOf + ": " + usage; @@ -206,7 +206,7 @@ } @Override - public void replace(ValueNode oldNode, ValueNode newNode) { + public void replace(ValueNode oldNode, ValueNode newNode, MemoryMapNode mmap) { assert newNode instanceof PhiNode; assert oldNode == instanceOf; newNode.inferStamp(); @@ -238,7 +238,7 @@ } @Override - public void replace(ValueNode oldNode, ValueNode newNode) { + public void replace(ValueNode oldNode, ValueNode newNode, MemoryMapNode mmap) { assert newNode instanceof PhiNode; assert oldNode == instanceOf; newNode.inferStamp(); diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeClassSubstitutions.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeClassSubstitutions.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeClassSubstitutions.java Wed Oct 02 13:26:31 2013 +0200 @@ -36,8 +36,8 @@ * Substitutions for improving the performance of some critical methods in {@link NodeClass} * methods. These substitutions improve the performance by forcing the relevant methods to be * inlined (intrinsification being a special form of inlining) and removing a checked cast. The - * latter cannot be done directly in Java code as {@link UnsafeCastNode} is not available to the - * project containing {@link NodeClass}. + * latter cannot be done directly in Java code as {@link PiNode} is not available to the project + * containing {@link NodeClass}. */ @ClassSubstitution(NodeClass.class) public class NodeClassSubstitutions { @@ -64,12 +64,12 @@ @MethodSubstitution private static Node getNode(Node node, long offset) { - return UnsafeCastNode.unsafeCast(UnsafeLoadNode.load(node, 0, offset, Kind.Object), Node.class, false, false); + return PiNode.piCast(UnsafeLoadNode.load(node, 0, offset, Kind.Object), Node.class, false, false); } @MethodSubstitution private static NodeList getNodeList(Node node, long offset) { - return UnsafeCastNode.unsafeCast(UnsafeLoadNode.load(node, 0, offset, Kind.Object), NodeList.class, false, false); + return PiNode.piCast(UnsafeLoadNode.load(node, 0, offset, Kind.Object), NodeList.class, false, false); } @MethodSubstitution diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationPhase.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationPhase.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationPhase.java Wed Oct 02 13:26:31 2013 +0200 @@ -67,7 +67,7 @@ } } - private boolean tryIntrinsify(MethodCallTargetNode methodCallTargetNode, List cleanUpReturnList) { + protected boolean tryIntrinsify(MethodCallTargetNode methodCallTargetNode, List cleanUpReturnList) { ResolvedJavaMethod target = methodCallTargetNode.targetMethod(); NodeIntrinsic intrinsic = target.getAnnotation(Node.NodeIntrinsic.class); ResolvedJavaType declaringClass = target.getDeclaringClass(); @@ -76,7 +76,6 @@ assert Modifier.isStatic(target.getModifiers()) : "node intrinsic must be static: " + target; ResolvedJavaType[] parameterTypes = MetaUtil.resolveJavaTypes(MetaUtil.signatureToTypes(target), declaringClass); - ResolvedJavaType returnType = target.getSignature().getReturnType(declaringClass).resolve(declaringClass); // Prepare the arguments for the reflective constructor call on the node class. Constant[] nodeConstructorArguments = prepareArguments(methodCallTargetNode, parameterTypes, target, false); @@ -86,15 +85,15 @@ // Create the new node instance. ResolvedJavaType c = getNodeClass(target, intrinsic); - Node newInstance = createNodeInstance(c, parameterTypes, returnType, intrinsic.setStampFromReturnType(), nodeConstructorArguments); + Node newInstance = createNodeInstance(c, parameterTypes, methodCallTargetNode.invoke().asNode().stamp(), intrinsic.setStampFromReturnType(), nodeConstructorArguments); // Replace the invoke with the new node. - methodCallTargetNode.graph().add(newInstance); + newInstance = methodCallTargetNode.graph().addOrUnique(newInstance); methodCallTargetNode.invoke().intrinsify(newInstance); // Clean up checkcast instructions inserted by javac if the return type is generic. cleanUpReturnList.add(newInstance); - } else if (target.getAnnotation(Fold.class) != null) { + } else if (isFoldable(target)) { ResolvedJavaType[] parameterTypes = MetaUtil.resolveJavaTypes(MetaUtil.signatureToTypes(target), declaringClass); // Prepare the arguments for the reflective method call @@ -128,6 +127,13 @@ } /** + * Permits a subclass to override the default definition of "foldable". + */ + protected boolean isFoldable(ResolvedJavaMethod method) { + return method.getAnnotation(Fold.class) != null; + } + + /** * Converts the arguments of an invoke node to object values suitable for use as the arguments * to a reflective invocation of a Java constructor or method. * @@ -187,7 +193,7 @@ return result; } - private Node createNodeInstance(ResolvedJavaType nodeClass, ResolvedJavaType[] parameterTypes, ResolvedJavaType returnType, boolean setStampFromReturnType, Constant[] nodeConstructorArguments) { + private Node createNodeInstance(ResolvedJavaType nodeClass, ResolvedJavaType[] parameterTypes, Stamp invokeStamp, boolean setStampFromReturnType, Constant[] nodeConstructorArguments) { ResolvedJavaMethod constructor = null; Constant[] arguments = null; @@ -211,11 +217,7 @@ ValueNode intrinsicNode = (ValueNode) constructor.newInstance(arguments).asObject(); if (setStampFromReturnType) { - if (returnType.getKind() == Kind.Object) { - intrinsicNode.setStamp(StampFactory.declared(returnType)); - } else { - intrinsicNode.setStamp(StampFactory.forKind(returnType.getKind())); - } + intrinsicNode.setStamp(invokeStamp); } return intrinsicNode; } catch (Exception e) { @@ -300,7 +302,7 @@ private static void checkCheckCastUsage(StructuredGraph graph, Node intrinsifiedNode, Node input, Node usage) { if (usage instanceof ValueAnchorNode) { ValueAnchorNode valueAnchorNode = (ValueAnchorNode) usage; - valueAnchorNode.removeAnchoredNode((ValueNode) input); + valueAnchorNode.removeAnchoredNode(); Debug.log("%s: Removed a ValueAnchor input", Debug.contextSnapshot(JavaMethod.class)); } else if (usage instanceof UnboxNode) { UnboxNode unbox = (UnboxNode) usage; diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java Wed Oct 02 13:26:31 2013 +0200 @@ -44,6 +44,7 @@ import com.oracle.graal.nodes.spi.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.common.*; +import com.oracle.graal.phases.tiers.*; import com.oracle.graal.replacements.Snippet.DefaultSnippetInliningPolicy; import com.oracle.graal.replacements.Snippet.SnippetInliningPolicy; import com.oracle.graal.word.phases.*; @@ -291,11 +292,8 @@ if (original == null) { new SnippetFrameStateCleanupPhase().apply(graph); - new DeadCodeEliminationPhase().apply(graph); - new InsertStateAfterPlaceholderPhase().apply(graph); - } else { - new DeadCodeEliminationPhase().apply(graph); } + new DeadCodeEliminationPhase().apply(graph); } private StructuredGraph parseGraph(final ResolvedJavaMethod methodToParse, final SnippetInliningPolicy policy) { @@ -324,30 +322,32 @@ @Override public void run() { - GraphBuilderConfiguration config = GraphBuilderConfiguration.getSnippetDefault(); - GraphBuilderPhase graphBuilder = new GraphBuilderPhase(runtime, config, OptimisticOptimizations.NONE); - graphBuilder.apply(graph); + new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getSnippetDefault(), OptimisticOptimizations.NONE).apply(graph); + new WordTypeVerificationPhase(runtime, target.wordKind).apply(graph); + new WordTypeRewriterPhase(runtime, target.wordKind).apply(graph); - new WordTypeVerificationPhase(runtime, target.wordKind).apply(graph); if (OptCanonicalizer.getValue()) { - new WordTypeRewriterPhase(runtime, target.wordKind).apply(graph); - new CanonicalizerPhase.Instance(runtime, assumptions, true).apply(graph); + new CanonicalizerPhase(true).apply(graph, new PhaseContext(runtime, assumptions, ReplacementsImpl.this)); } } }); return graph; } + protected Object beforeInline(@SuppressWarnings("unused") MethodCallTargetNode callTarget, @SuppressWarnings("unused") StructuredGraph callee) { + return null; + } + /** * Called after a graph is inlined. * * @param caller the graph into which {@code callee} was inlined * @param callee the graph that was inlined into {@code caller} + * @param beforeInlineData value returned by {@link #beforeInline}. */ - protected void afterInline(StructuredGraph caller, StructuredGraph callee) { + protected void afterInline(StructuredGraph caller, StructuredGraph callee, Object beforeInlineData) { if (OptCanonicalizer.getValue()) { - new WordTypeRewriterPhase(runtime, target.wordKind).apply(caller); - new CanonicalizerPhase.Instance(runtime, assumptions, true).apply(caller); + new CanonicalizerPhase(true).apply(caller, new PhaseContext(runtime, assumptions, ReplacementsImpl.this)); } } @@ -356,12 +356,9 @@ */ protected void afterInlining(StructuredGraph graph) { new NodeIntrinsificationPhase(runtime).apply(graph); - - new WordTypeRewriterPhase(runtime, target.wordKind).apply(graph); - new DeadCodeEliminationPhase().apply(graph); if (OptCanonicalizer.getValue()) { - new CanonicalizerPhase.Instance(runtime, assumptions, true).apply(graph); + new CanonicalizerPhase(true).apply(graph, new PhaseContext(runtime, assumptions, ReplacementsImpl.this)); } } @@ -377,10 +374,13 @@ if (callee == method) { final StructuredGraph originalGraph = new StructuredGraph(original); new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getSnippetDefault(), OptimisticOptimizations.NONE).apply(originalGraph); + new WordTypeVerificationPhase(runtime, target.wordKind).apply(graph); + new WordTypeRewriterPhase(runtime, target.wordKind).apply(graph); + InliningUtil.inline(callTarget.invoke(), originalGraph, true); Debug.dump(graph, "after inlining %s", callee); - afterInline(graph, originalGraph); + afterInline(graph, originalGraph, null); substituteCallsOriginal = true; } else { StructuredGraph intrinsicGraph = InliningUtil.getIntrinsicGraph(ReplacementsImpl.this, callee); @@ -397,9 +397,10 @@ } targetGraph = parseGraph(callee, policy); } + Object beforeInlineData = beforeInline(callTarget, targetGraph); InliningUtil.inline(callTarget.invoke(), targetGraph, true); Debug.dump(graph, "after inlining %s", callee); - afterInline(graph, targetGraph); + afterInline(graph, targetGraph, beforeInlineData); } } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetFrameStateCleanupPhase.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetFrameStateCleanupPhase.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetFrameStateCleanupPhase.java Wed Oct 02 13:26:31 2013 +0200 @@ -45,24 +45,24 @@ @Override protected void run(StructuredGraph graph) { - ReentrantNodeIterator.apply(new SnippetFrameStateCleanupClosure(), graph.start(), false, null); + ReentrantNodeIterator.apply(new SnippetFrameStateCleanupClosure(), graph.start(), null, null); } - /** - * A proper (loop-aware) iteration over the graph is used to detect loops that contain invalid - * frame states, so that they can be marked with an invalid frame state. - */ - private static class SnippetFrameStateCleanupClosure extends NodeIteratorClosure { + private static class SnippetFrameStateCleanupClosure extends NodeIteratorClosure { @Override - protected Boolean processNode(FixedNode node, Boolean currentState) { + protected StateSplit processNode(FixedNode node, StateSplit currentState) { + StateSplit state = currentState; if (node instanceof StateSplit) { StateSplit stateSplit = (StateSplit) node; FrameState frameState = stateSplit.stateAfter(); if (frameState != null) { - if (stateSplit.hasSideEffect()) { - stateSplit.setStateAfter(node.graph().add(new FrameState(FrameState.INVALID_FRAMESTATE_BCI))); - return true; + // the stateSplit == currentState case comes from merge handling + if (stateSplit.hasSideEffect() || stateSplit == currentState) { + stateSplit.setStateAfter(createInvalidFrameState(node)); + state = stateSplit; + } else if (hasInvalidState(state)) { + stateSplit.setStateAfter(createInvalidFrameState(node)); } else { stateSplit.setStateAfter(null); } @@ -71,41 +71,57 @@ } } } - return currentState; + if (node instanceof ControlSinkNode && state != null) { + state.setStateAfter(node.graph().add(new FrameState(FrameState.AFTER_BCI))); + } + return state; } @Override - protected Boolean merge(MergeNode merge, List states) { - for (boolean state : states) { - if (state) { - return true; + protected StateSplit merge(MergeNode merge, List states) { + boolean invalid = false; + for (StateSplit state : states) { + if (state != null && state.stateAfter() != null && state.stateAfter().bci == FrameState.INVALID_FRAMESTATE_BCI) { + invalid = true; + state.setStateAfter(merge.graph().add(new FrameState(FrameState.AFTER_BCI))); } } - return false; + if (invalid) { + // at the next processNode call, stateSplit == currentState == merge + return merge; + } else { + return null; + } } @Override - protected Boolean afterSplit(AbstractBeginNode node, Boolean oldState) { + protected StateSplit afterSplit(AbstractBeginNode node, StateSplit oldState) { return oldState; } @Override - protected Map processLoop(LoopBeginNode loop, Boolean initialState) { - LoopInfo info = ReentrantNodeIterator.processLoop(this, loop, false); - boolean containsFrameState = false; - for (Boolean state : info.endStates.values()) { - containsFrameState |= state; - } - if (containsFrameState) { - loop.setStateAfter(loop.graph().add(new FrameState(FrameState.INVALID_FRAMESTATE_BCI))); - } - if (containsFrameState || initialState) { - for (Map.Entry entry : info.exitStates.entrySet()) { - entry.setValue(true); + protected Map processLoop(LoopBeginNode loop, StateSplit initialState) { + LoopInfo info = ReentrantNodeIterator.processLoop(this, loop, initialState); + if (!hasInvalidState(initialState)) { + boolean isNowInvalid = false; + for (StateSplit endState : info.endStates.values()) { + isNowInvalid |= hasInvalidState(endState); + } + if (isNowInvalid) { + loop.setStateAfter(createInvalidFrameState(loop)); + info = ReentrantNodeIterator.processLoop(this, loop, loop); } } return info.exitStates; } + private static boolean hasInvalidState(StateSplit state) { + assert state == null || (state.stateAfter() != null && state.stateAfter().bci == FrameState.INVALID_FRAMESTATE_BCI) : state + " " + state.stateAfter(); + return state != null; + } + + private static FrameState createInvalidFrameState(FixedNode node) { + return node.graph().add(new FrameState(FrameState.INVALID_FRAMESTATE_BCI)); + } } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java Wed Oct 02 13:26:31 2013 +0200 @@ -22,6 +22,8 @@ */ package com.oracle.graal.replacements; +import static com.oracle.graal.api.meta.LocationIdentity.*; + import java.lang.reflect.*; import java.util.*; import java.util.concurrent.*; @@ -32,8 +34,10 @@ import com.oracle.graal.debug.*; import com.oracle.graal.debug.internal.*; import com.oracle.graal.graph.*; +import com.oracle.graal.graph.iterators.*; import com.oracle.graal.loop.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.StructuredGraph.GuardsStage; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; @@ -41,11 +45,12 @@ import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.util.*; import com.oracle.graal.phases.common.*; +import com.oracle.graal.phases.common.FloatingReadPhase.MemoryMapImpl; +import com.oracle.graal.phases.tiers.*; import com.oracle.graal.replacements.Snippet.ConstantParameter; import com.oracle.graal.replacements.Snippet.VarargsParameter; import com.oracle.graal.replacements.nodes.*; import com.oracle.graal.word.*; -import com.oracle.graal.word.phases.*; /** * A snippet template is a graph created by parsing a snippet method and then specialized by binding @@ -58,7 +63,7 @@ /** * Holds the {@link ResolvedJavaMethod} of the snippet, together with some information about the * method that needs to be computed only once. The {@link SnippetInfo} should be created once - * per snippet an then cached. + * per snippet and then cached. */ public static class SnippetInfo { @@ -149,9 +154,9 @@ protected int nextParamIdx; - public Arguments(SnippetInfo info) { + public Arguments(SnippetInfo info, GuardsStage guardsStage) { this.info = info; - this.cacheKey = new CacheKey(info); + this.cacheKey = new CacheKey(info, guardsStage); this.values = new Object[info.getParameterCount()]; } @@ -268,10 +273,12 @@ private final ResolvedJavaMethod method; private final Object[] values; + private final GuardsStage guardsStage; private int hash; - protected CacheKey(SnippetInfo info) { + protected CacheKey(SnippetInfo info, GuardsStage guardsStage) { this.method = info.method; + this.guardsStage = guardsStage; this.values = new Object[info.getParameterCount()]; this.hash = info.method.hashCode(); } @@ -290,6 +297,9 @@ if (method != other.method) { return false; } + if (guardsStage != other.guardsStage) { + return false; + } for (int i = 0; i < values.length; i++) { if (values[i] != null && !values[i].equals(other.values[i])) { return false; @@ -351,7 +361,7 @@ @Override public SnippetTemplate call() throws Exception { - return new SnippetTemplate(runtime, replacements, target, args); + return new SnippetTemplate(runtime, replacements, args); } }); templates.put(args.cacheKey, template); @@ -382,14 +392,16 @@ /** * Creates a snippet template. */ - protected SnippetTemplate(MetaAccessProvider runtime, Replacements replacements, TargetDescription target, Arguments args) { + protected SnippetTemplate(final MetaAccessProvider runtime, final Replacements replacements, Arguments args) { StructuredGraph snippetGraph = replacements.getSnippet(args.info.method); ResolvedJavaMethod method = snippetGraph.method(); Signature signature = method.getSignature(); + PhaseContext context = new PhaseContext(runtime, replacements.getAssumptions(), replacements); + // Copy snippet graph, replacing constant parameters with given arguments - StructuredGraph snippetCopy = new StructuredGraph(snippetGraph.name, snippetGraph.method()); + final StructuredGraph snippetCopy = new StructuredGraph(snippetGraph.name, snippetGraph.method()); IdentityHashMap nodeReplacements = new IdentityHashMap<>(); nodeReplacements.put(snippetGraph.start(), snippetCopy.start()); @@ -417,15 +429,13 @@ placeholders[i] = placeholder; } } - snippetCopy.addDuplicates(snippetGraph.getNodes(), nodeReplacements); + snippetCopy.addDuplicates(snippetGraph.getNodes(), snippetGraph, snippetGraph.getNodeCount(), nodeReplacements); Debug.dump(snippetCopy, "Before specialization"); if (!nodeReplacements.isEmpty()) { // Do deferred intrinsification of node intrinsics new NodeIntrinsificationPhase(runtime).apply(snippetCopy); - new WordTypeRewriterPhase(runtime, target.wordKind).apply(snippetCopy); - - new CanonicalizerPhase.Instance(runtime, replacements.getAssumptions(), true, 0, null).apply(snippetCopy); + new CanonicalizerPhase(true).apply(snippetCopy, context); } NodeIntrinsificationVerificationPhase.verify(snippetCopy); @@ -481,8 +491,8 @@ if (loopBegin != null) { LoopEx loop = new LoopsData(snippetCopy).loop(loopBegin); int mark = snippetCopy.getMark(); - LoopTransformations.fullUnroll(loop, runtime, replacements.getAssumptions(), true); - new CanonicalizerPhase.Instance(runtime, replacements.getAssumptions(), true, mark, null).apply(snippetCopy); + LoopTransformations.fullUnroll(loop, context, new CanonicalizerPhase(true)); + new CanonicalizerPhase(true).applyIncremental(snippetCopy, context, mark); } FixedNode explodeLoopNext = explodeLoop.next(); explodeLoop.clearSuccessors(); @@ -493,7 +503,17 @@ } } while (exploded); - // Remove all frame states from inlined snippet graph. Snippets must be atomic (i.e. free + // Perform lowering on the snippet + snippetCopy.setGuardsStage(args.cacheKey.guardsStage); + Debug.scope("LoweringSnippetTemplate", snippetCopy, new Runnable() { + + public void run() { + PhaseContext c = new PhaseContext(runtime, new Assumptions(false), replacements); + new LoweringPhase(new CanonicalizerPhase(true)).apply(snippetCopy, c); + } + }); + + // Remove all frame states from snippet graph. Snippets must be atomic (i.e. free // of side-effects that prevent deoptimizing to a point before the snippet). ArrayList curSideEffectNodes = new ArrayList<>(); ArrayList curDeoptNodes = new ArrayList<>(); @@ -524,11 +544,15 @@ assert checkAllVarargPlaceholdersAreDeleted(parameterCount, placeholders); + new FloatingReadPhase(FloatingReadPhase.ExecutionMode.ANALYSIS_ONLY).apply(snippetCopy); + this.memoryMap = null; + this.snippet = snippetCopy; ReturnNode retNode = null; StartNode entryPointNode = snippet.start(); - nodes = new ArrayList<>(snippet.getNodeCount()); + boolean seenReturn = false; + boolean containsMemoryMap = false; for (Node node : snippet.getNodes()) { if (node == entryPointNode || node == entryPointNode.stateAfter()) { // Do nothing. @@ -536,9 +560,20 @@ nodes.add(node); if (node instanceof ReturnNode) { retNode = (ReturnNode) node; + NodeIterable memstates = retNode.inputs().filter(MemoryMapNode.class); + assert memstates.count() == 1; + memoryMap = memstates.first(); + retNode.replaceFirstInput(memoryMap, null); + memoryMap.safeDelete(); + + assert !seenReturn : "can handle only one ReturnNode"; + seenReturn = true; + } else if (node instanceof MemoryMapNode) { + containsMemoryMap = true; } } } + assert !containsMemoryMap; this.sideEffectNodes = curSideEffectNodes; this.deoptNodes = curDeoptNodes; @@ -622,6 +657,11 @@ private final ArrayList nodes; /** + * map of killing locations to memory checkpoints (nodes). + */ + private MemoryMapNode memoryMap; + + /** * Gets the instantiation-time bindings to this template's parameters. * * @return the map that will be used to bind arguments to parameters when inlining this template @@ -713,7 +753,7 @@ /** * Replaces all usages of {@code oldNode} with direct or indirect usages of {@code newNode}. */ - void replace(ValueNode oldNode, ValueNode newNode); + void replace(ValueNode oldNode, ValueNode newNode, MemoryMapNode mmap); } /** @@ -723,11 +763,96 @@ public static final UsageReplacer DEFAULT_REPLACER = new UsageReplacer() { @Override - public void replace(ValueNode oldNode, ValueNode newNode) { + public void replace(ValueNode oldNode, ValueNode newNode, MemoryMapNode mmap) { oldNode.replaceAtUsages(newNode); + if (mmap == null || newNode == null) { + return; + } + for (Node usage : newNode.usages().snapshot()) { + if (usage instanceof FloatingReadNode && ((FloatingReadNode) usage).lastLocationAccess() == newNode) { + assert newNode.graph().isAfterFloatingReadPhase(); + + // lastLocationAccess points into the snippet graph. find a proper + // MemoryCheckPoint inside the snippet graph + FloatingReadNode read = (FloatingReadNode) usage; + Node lastAccess = mmap.getLastLocationAccess(read.location().getLocationIdentity()); + + assert lastAccess != null : "no mapping found for lowerable node " + oldNode + ". (No node in the snippet kill the same location as the lowerable node?)"; + read.setLastLocationAccess(lastAccess); + } + } } }; + private boolean checkSnippetKills(ScheduledNode replacee) { + if (!replacee.graph().isAfterFloatingReadPhase()) { + // no floating reads yet, ignore locations created while lowering + return true; + } + if (memoryMap == null || ((MemoryMapImpl) memoryMap).isEmpty()) { + // there're no kills in the snippet graph + return true; + } + + Set kills = new HashSet<>(((MemoryMapImpl) memoryMap).getLocations()); + + if (replacee instanceof MemoryCheckpoint.Single) { + // check if some node in snippet graph also kills the same location + LocationIdentity locationIdentity = ((MemoryCheckpoint.Single) replacee).getLocationIdentity(); + if (locationIdentity == ANY_LOCATION) { + assert !(memoryMap.getLastLocationAccess(ANY_LOCATION) instanceof StartNode); + } + assert kills.contains(locationIdentity) : replacee + " kills " + locationIdentity + ", but snippet doesn't contain a kill to this location"; + return true; + } + assert !(replacee instanceof MemoryCheckpoint.Multi) : replacee + " multi not supported (yet)"; + + Debug.log("WARNING: %s is not a MemoryCheckpoint, but the snippet graph contains kills (%s). You might want %s to be a MemoryCheckpoint", replacee, kills, replacee); + + // remove ANY_LOCATION if it's just a kill by the start node + if (memoryMap.getLastLocationAccess(ANY_LOCATION) instanceof StartNode) { + kills.remove(ANY_LOCATION); + } + + // node can only lower to a ANY_LOCATION kill if the replacee also kills ANY_LOCATION + assert !kills.contains(ANY_LOCATION) : "snippet graph contains a kill to ANY_LOCATION, but replacee (" + replacee + ") doesn't kill ANY_LOCATION. kills: " + kills; + + /* + * kills to other locations than ANY_LOCATION can be still inserted if there aren't any + * floating reads accessing this locations. Example: In HotSpot, InstanceOfNode is lowered + * to a snippet containing a write to SECONDARY_SUPER_CACHE_LOCATION. This is runtime + * specific, so the runtime independent InstanceOfNode can not kill this location. However, + * if no FloatingReadNode is reading from this location, the kill to this location is fine. + */ + for (FloatingReadNode frn : replacee.graph().getNodes(FloatingReadNode.class)) { + assert !(kills.contains(frn.location().getLocationIdentity())) : frn + " reads from " + frn.location().getLocationIdentity() + " but " + replacee + " does not kill this location"; + } + return true; + } + + private class DuplicateMapper extends MemoryMapNode { + + Map duplicates; + StartNode replaceeStart; + + public DuplicateMapper(Map duplicates, StartNode replaceeStart) { + this.duplicates = duplicates; + this.replaceeStart = replaceeStart; + } + + @Override + public Node getLastLocationAccess(LocationIdentity locationIdentity) { + assert memoryMap != null : "no memory map stored for this snippet graph (snippet doesn't have a ReturnNode?)"; + Node lastLocationAccess = memoryMap.getLastLocationAccess(locationIdentity); + assert lastLocationAccess != null; + if (lastLocationAccess instanceof StartNode) { + return replaceeStart; + } else { + return duplicates.get(lastLocationAccess); + } + } + } + /** * Replaces a given fixed node with this specialized snippet. * @@ -738,17 +863,17 @@ * @return the map of duplicated nodes (original -> duplicate) */ public Map instantiate(MetaAccessProvider runtime, FixedNode replacee, UsageReplacer replacer, Arguments args) { + assert checkSnippetKills(replacee); try (TimerCloseable a = instantiationTimer.start()) { instantiationCounter.increment(); // Inline the snippet nodes, replacing parameters with the given args in the process - String name = snippet.name == null ? "{copy}" : snippet.name + "{copy}"; - StructuredGraph snippetCopy = new StructuredGraph(name, snippet.method()); StartNode entryPointNode = snippet.start(); FixedNode firstCFGNode = entryPointNode.next(); StructuredGraph replaceeGraph = replacee.graph(); IdentityHashMap replacements = bind(replaceeGraph, runtime, args); - Map duplicates = replaceeGraph.addDuplicates(nodes, replacements); - Debug.dump(replaceeGraph, "After inlining snippet %s", snippetCopy.method()); + replacements.put(entryPointNode, replaceeGraph.start()); + Map duplicates = replaceeGraph.addDuplicates(nodes, snippet, snippet.getNodeCount(), replacements); + Debug.dump(replaceeGraph, "After inlining snippet %s", snippet.method()); // Re-wire the control flow graph around the replacee FixedNode firstCFGNodeDuplicate = (FixedNode) duplicates.get(firstCFGNode); @@ -788,16 +913,16 @@ if (returnNode != null) { if (returnNode.result() instanceof LocalNode) { returnValue = (ValueNode) replacements.get(returnNode.result()); - } else { + } else if (returnNode.result() != null) { returnValue = (ValueNode) duplicates.get(returnNode.result()); } Node returnDuplicate = duplicates.get(returnNode); + MemoryMapNode mmap = new DuplicateMapper(duplicates, replaceeGraph.start()); if (returnValue == null && replacee.usages().isNotEmpty() && replacee instanceof MemoryCheckpoint) { - replacer.replace(replacee, (ValueNode) returnDuplicate.predecessor()); + replacer.replace(replacee, (ValueNode) returnDuplicate.predecessor(), mmap); } else { assert returnValue != null || replacee.usages().isEmpty() : this + " " + returnValue + " " + returnNode + " " + replacee.usages(); - replacer.replace(replacee, returnValue); - + replacer.replace(replacee, returnValue, mmap); } if (returnDuplicate.isAlive()) { returnDuplicate.clearInputs(); @@ -831,6 +956,7 @@ * @param args the arguments to be bound to the flattened positional parameters of the snippet */ public void instantiate(MetaAccessProvider runtime, FloatingNode replacee, UsageReplacer replacer, LoweringTool tool, Arguments args) { + assert checkSnippetKills(replacee); try (TimerCloseable a = instantiationTimer.start()) { instantiationCounter.increment(); @@ -841,7 +967,8 @@ FixedNode firstCFGNode = entryPointNode.next(); StructuredGraph replaceeGraph = replacee.graph(); IdentityHashMap replacements = bind(replaceeGraph, runtime, args); - Map duplicates = replaceeGraph.addDuplicates(nodes, replacements); + replacements.put(entryPointNode, replaceeGraph.start()); + Map duplicates = replaceeGraph.addDuplicates(nodes, snippet, snippet.getNodeCount(), replacements); Debug.dump(replaceeGraph, "After inlining snippet %s", snippetCopy.method()); FixedWithNextNode lastFixedNode = tool.lastFixedNode(); @@ -872,7 +999,7 @@ returnValue = (ValueNode) duplicates.get(returnNode.result()); } assert returnValue != null || replacee.usages().isEmpty(); - replacer.replace(replacee, returnValue); + replacer.replace(replacee, returnValue, new DuplicateMapper(duplicates, replaceeGraph.start())); Node returnDuplicate = duplicates.get(returnNode); if (returnDuplicate.isAlive()) { diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectObjectStoreNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectObjectStoreNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DirectObjectStoreNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -64,7 +64,7 @@ public static native void storeInt(Object obj, @ConstantNodeParameter int displacement, long offset, int value); @Override - public void lower(LoweringTool tool, LoweringType loweringType) { + public void lower(LoweringTool tool) { IndexedLocationNode location = IndexedLocationNode.create(ANY_LOCATION, value.kind(), displacement, offset, graph(), 1); WriteNode write = graph().add(new WriteNode(object, value, location, BarrierType.NONE, value.kind() == Kind.Object)); graph().replaceFixedWithFixed(this, write); diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -22,9 +22,12 @@ */ package com.oracle.graal.replacements.nodes; +import static java.lang.reflect.Modifier.*; + import java.lang.reflect.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; @@ -32,6 +35,7 @@ import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.phases.common.*; +import com.oracle.graal.phases.tiers.*; public class MacroNode extends AbstractStateSplit implements Lowerable, MemoryCheckpoint.Single { @@ -63,35 +67,68 @@ } /** - * Gets a snippet to be used for lowering this macro node. + * Gets a snippet to be used for lowering this macro node. The returned graph (if non-null) must + * have been {@linkplain #lowerReplacement(StructuredGraph, LoweringTool) lowered}. */ @SuppressWarnings("unused") - protected StructuredGraph getSnippetGraph(LoweringTool tool) { + protected StructuredGraph getLoweredSnippetGraph(LoweringTool tool) { return null; } /** * Gets a normal method substitution to be used for lowering this macro node. This is only - * called if {@link #getSnippetGraph(LoweringTool)} return nulls. + * called if {@link #getLoweredSnippetGraph(LoweringTool)} returns null. The returned graph (if + * non-null) must have been {@linkplain #lowerReplacement(StructuredGraph, LoweringTool) + * lowered}. */ - protected StructuredGraph getSubstitutionGraph(LoweringTool tool) { - return tool.getReplacements().getMethodSubstitution(getTargetMethod()); + protected StructuredGraph getLoweredSubstitutionGraph(LoweringTool tool) { + StructuredGraph methodSubstitution = tool.getReplacements().getMethodSubstitution(getTargetMethod()); + if (methodSubstitution != null) { + return lowerReplacement(methodSubstitution.copy(), tool); + } + return null; + } + + /** + * Applies {@linkplain LoweringPhase lowering} to a replacement graph. + * + * @param replacementGraph a replacement (i.e., snippet or method substitution) graph + */ + protected StructuredGraph lowerReplacement(final StructuredGraph replacementGraph, LoweringTool tool) { + replacementGraph.setGuardsStage(graph().getGuardsStage()); + final PhaseContext c = new PhaseContext(tool.getRuntime(), tool.assumptions(), tool.getReplacements()); + Debug.scope("LoweringReplacement", replacementGraph, new Runnable() { + + public void run() { + new LoweringPhase(new CanonicalizerPhase(true)).apply(replacementGraph, c); + } + }); + return replacementGraph; } @Override - public void lower(LoweringTool tool, LoweringType loweringType) { - boolean nullCheck = false; - StructuredGraph replacementGraph = getSnippetGraph(tool); + public void lower(LoweringTool tool) { + StructuredGraph replacementGraph = getLoweredSnippetGraph(tool); if (replacementGraph == null) { - replacementGraph = getSubstitutionGraph(tool); - nullCheck = true; + replacementGraph = getLoweredSubstitutionGraph(tool); } InvokeNode invoke = replaceWithInvoke(); assert invoke.verify(); if (replacementGraph != null) { - InliningUtil.inline(invoke, replacementGraph, nullCheck); + // Pull out the receiver null check so that a replaced + // receiver can be lowered if necessary + if (!isStatic(targetMethod.getModifiers())) { + ValueNode nonNullReceiver = InliningUtil.nonNullReceiver(invoke); + if (nonNullReceiver instanceof Lowerable) { + ((Lowerable) nonNullReceiver).lower(tool); + } + } + InliningUtil.inline(invoke, replacementGraph, false); + Debug.dump(graph(), "After inlining replacement %s", replacementGraph); + } else { + invoke.lower(tool); } } @@ -110,17 +147,16 @@ } protected void replaceSnippetInvokes(StructuredGraph snippetGraph) { - for (InvokeNode invoke : snippetGraph.getNodes(InvokeNode.class)) { - if (((MethodCallTargetNode) invoke.callTarget()).targetMethod() != getTargetMethod()) { + for (MethodCallTargetNode call : snippetGraph.getNodes(MethodCallTargetNode.class)) { + Invoke invoke = call.invoke(); + if (call.targetMethod() != getTargetMethod()) { throw new GraalInternalError("unexpected invoke %s in snippet", getClass().getSimpleName()); } - if (invoke.stateAfter().bci == FrameState.INVALID_FRAMESTATE_BCI) { - InvokeNode newInvoke = snippetGraph.add(new InvokeNode(invoke.callTarget(), getBci())); - newInvoke.setStateAfter(snippetGraph.add(new FrameState(FrameState.AFTER_BCI))); - snippetGraph.replaceFixedWithFixed(invoke, newInvoke); - } else { - assert invoke.stateAfter().bci == FrameState.AFTER_BCI : invoke; - } + assert invoke.stateAfter().bci == FrameState.AFTER_BCI; + // Here we need to fix the bci of the invoke + InvokeNode newInvoke = snippetGraph.add(new InvokeNode(invoke.callTarget(), getBci())); + newInvoke.setStateAfter(invoke.stateAfter()); + snippetGraph.replaceFixedWithFixed((InvokeNode) invoke.asNode(), newInvoke); } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MathIntrinsicNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MathIntrinsicNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MathIntrinsicNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -85,28 +85,15 @@ gen.setResult(this, result); } + public Constant evalConst(Constant... inputs) { + assert inputs.length == 1; + return Constant.forDouble(compute(inputs[0].asDouble(), operation())); + } + @Override public ValueNode canonical(CanonicalizerTool tool) { if (x().isConstant()) { - double value = x().asConstant().asDouble(); - switch (operation()) { - case ABS: - return ConstantNode.forDouble(Math.abs(value), graph()); - case SQRT: - return ConstantNode.forDouble(Math.sqrt(value), graph()); - case LOG: - return ConstantNode.forDouble(Math.log(value), graph()); - case LOG10: - return ConstantNode.forDouble(Math.log10(value), graph()); - case SIN: - return ConstantNode.forDouble(Math.sin(value), graph()); - case COS: - return ConstantNode.forDouble(Math.cos(value), graph()); - case TAN: - return ConstantNode.forDouble(Math.tan(value), graph()); - default: - throw GraalInternalError.shouldNotReachHere(); - } + return ConstantNode.forPrimitive(evalConst(x().asConstant()), graph()); } return this; } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/PartialEvaluationTest.java --- a/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/PartialEvaluationTest.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/PartialEvaluationTest.java Wed Oct 02 13:26:31 2013 +0200 @@ -36,7 +36,6 @@ import com.oracle.graal.loop.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.java.*; -import com.oracle.graal.nodes.spi.Lowerable.LoweringType; import com.oracle.graal.phases.*; import com.oracle.graal.phases.PhasePlan.PhasePosition; import com.oracle.graal.phases.common.*; @@ -118,7 +117,7 @@ if (ex.counted().isConstantMaxTripCount()) { long constant = ex.counted().constantMaxTripCount(); if (constant <= UNROLL_LIMIT) { - LoopTransformations.fullUnroll(ex, runtime, assumptions, canonicalizeReads); + LoopTransformations.fullUnroll(ex, context, canonicalizer); Debug.dump(resultGraph, "After loop unrolling %d times", constant); canonicalizer.apply(resultGraph, context); @@ -131,7 +130,7 @@ } new DeadCodeEliminationPhase().apply(resultGraph); - new PartialEscapePhase(true).apply(resultGraph, context); + new PartialEscapePhase(true, canonicalizer).apply(resultGraph, context); if (TruffleInlinePrinter.getValue()) { InlinePrinterProcessor.printTree(); @@ -161,7 +160,7 @@ frameState.replaceAtUsages(null); frameState.safeDelete(); } - new CanonicalizerPhase.Instance(runtime, new Assumptions(false), true).apply(graph); + new CanonicalizerPhase(true).apply(graph, new PhaseContext(runtime, new Assumptions(false), replacements)); new DeadCodeEliminationPhase().apply(graph); } @@ -169,34 +168,36 @@ StructuredGraph graphResult = Debug.scope("Truffle", new DebugDumpScope("Comparison: " + methodName), new Callable() { + @SuppressWarnings("deprecation") public StructuredGraph call() { Assumptions assumptions = new Assumptions(false); StructuredGraph graph = parse(methodName); - CanonicalizerPhase.Instance canonicalizerPhase = new CanonicalizerPhase.Instance(runtime, assumptions, true); - canonicalizerPhase.apply(graph); + PhaseContext context = new PhaseContext(runtime, assumptions, replacements); + CanonicalizerPhase canonicalizer = new CanonicalizerPhase(true); + canonicalizer.apply(graph, context); // Additional inlining. final PhasePlan plan = new PhasePlan(); GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getEagerDefault(), TruffleCompilerImpl.Optimizations); plan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase); - plan.addPhase(PhasePosition.AFTER_PARSING, canonicalizerPhase); + canonicalizer.addToPhasePlan(plan, context); plan.addPhase(PhasePosition.AFTER_PARSING, new DeadCodeEliminationPhase()); new ConvertDeoptimizeToGuardPhase().apply(graph); - canonicalizerPhase.apply(graph); + canonicalizer.apply(graph, context); new DeadCodeEliminationPhase().apply(graph); - HighTierContext context = new HighTierContext(runtime, assumptions, replacements, null, plan, OptimisticOptimizations.NONE); - InliningPhase inliningPhase = new InliningPhase(); - inliningPhase.apply(graph, context); + HighTierContext highTierContext = new HighTierContext(runtime, assumptions, replacements, null, plan, OptimisticOptimizations.NONE); + InliningPhase inliningPhase = new InliningPhase(canonicalizer); + inliningPhase.apply(graph, highTierContext); removeFrameStates(graph); new ConvertDeoptimizeToGuardPhase().apply(graph); - canonicalizerPhase.apply(graph); + canonicalizer.apply(graph, context); new DeadCodeEliminationPhase().apply(graph); - new LoweringPhase(LoweringType.BEFORE_GUARDS).apply(graph, context); - canonicalizerPhase.apply(graph); + new LoweringPhase(new CanonicalizerPhase(true)).apply(graph, context); + canonicalizer.apply(graph, context); new DeadCodeEliminationPhase().apply(graph); return graph; } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/CompilationPolicy.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/CompilationPolicy.java Wed Oct 02 13:26:31 2013 +0200 @@ -0,0 +1,109 @@ +/* + * 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.truffle; + +import static com.oracle.graal.truffle.TruffleCompilerOptions.*; + +public class CompilationPolicy { + + private int invokeCounter; + private int originalInvokeCounter; + private int loopAndInvokeCounter; + private long prevTimestamp; + + private final int initialInvokeCounter; + private final int compilationThreshold; + + public CompilationPolicy(final int compilationThreshold, final int initialInvokeCounter) { + this.invokeCounter = initialInvokeCounter; + this.loopAndInvokeCounter = compilationThreshold; + this.originalInvokeCounter = compilationThreshold; + this.prevTimestamp = System.currentTimeMillis(); + + this.compilationThreshold = compilationThreshold; + this.initialInvokeCounter = initialInvokeCounter; + } + + public int getInvokeCounter() { + return invokeCounter; + } + + public int getOriginalInvokeCounter() { + return originalInvokeCounter; + } + + public int getLoopAndInvokeCounter() { + return loopAndInvokeCounter; + } + + public void compilationInvalidated() { + int invalidationReprofileCount = TruffleInvalidationReprofileCount.getValue(); + invokeCounter = invalidationReprofileCount; + if (TruffleFunctionInlining.getValue()) { + originalInvokeCounter += invalidationReprofileCount; + } + } + + public void countInterpreterCall() { + invokeCounter--; + loopAndInvokeCounter--; + } + + public void inlined(int minInvokesAfterInlining) { + invokeCounter = minInvokesAfterInlining; + int inliningReprofileCount = TruffleInliningReprofileCount.getValue(); + loopAndInvokeCounter = inliningReprofileCount; + originalInvokeCounter = inliningReprofileCount; + } + + public void reportLoopCount(int count) { + loopAndInvokeCounter = Math.max(0, loopAndInvokeCounter - count); + } + + public void nodeReplaced() { + // delay compilation until tree is deemed stable enough + int replaceBackoff = TruffleReplaceReprofileCount.getValue(); + if (loopAndInvokeCounter < replaceBackoff) { + loopAndInvokeCounter = replaceBackoff; + } + } + + public boolean compileOrInline() { + if (invokeCounter <= 0 && loopAndInvokeCounter <= 0) { + if (TruffleUseTimeForCompilationDecision.getValue()) { + long timestamp = System.currentTimeMillis(); + if ((timestamp - prevTimestamp) < TruffleCompilationDecisionTime.getValue()) { + return true; + } + this.invokeCounter = initialInvokeCounter; + this.loopAndInvokeCounter = compilationThreshold; + this.originalInvokeCounter = compilationThreshold; + this.prevTimestamp = timestamp; + } else { + return true; + } + } + return false; + } + +} diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/FrameWithoutBoxing.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/FrameWithoutBoxing.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/FrameWithoutBoxing.java Wed Oct 02 13:26:31 2013 +0200 @@ -50,6 +50,7 @@ this.caller = caller; this.arguments = arguments; this.locals = new Object[descriptor.getSize()]; + Arrays.fill(locals, descriptor.getTypeConversion().getDefaultValue()); this.primitiveLocals = new long[descriptor.getSize()]; this.tags = new byte[descriptor.getSize()]; } @@ -90,8 +91,8 @@ } @Override - public void setObject(FrameSlot slot, Object value) throws FrameSlotTypeException { - verifySet(slot, FrameSlotKind.Object); + public void setObject(FrameSlot slot, Object value) { + verifySetObject(slot); setObjectUnsafe(slot, value); } @@ -242,43 +243,50 @@ tags[slotIndex] = (byte) accessKind.ordinal(); } - private void verifyGet(FrameSlot slot, FrameSlotKind accessKind) throws FrameSlotTypeException { - FrameSlotKind slotKind = slot.getKind(); - if (slotKind != accessKind) { + private void verifySetObject(FrameSlot slot) { + if (slot.getKind() != FrameSlotKind.Object) { CompilerDirectives.transferToInterpreter(); - if (slotKind == FrameSlotKind.Illegal && accessKind == FrameSlotKind.Object) { - slot.setKind(FrameSlotKind.Object); - this.setObject(slot, descriptor.getTypeConversion().getDefaultValue()); - } else { - throw new FrameSlotTypeException(); - } + slot.setKind(FrameSlotKind.Object); } int slotIndex = slot.getIndex(); if (slotIndex >= tags.length) { CompilerDirectives.transferToInterpreter(); resize(); } - if (tags[slotIndex] != accessKind.ordinal()) { + tags[slotIndex] = (byte) FrameSlotKind.Object.ordinal(); + } + + private void verifyGet(FrameSlot slot, FrameSlotKind accessKind) throws FrameSlotTypeException { + int slotIndex = slot.getIndex(); + if (slotIndex >= tags.length) { CompilerDirectives.transferToInterpreter(); - descriptor.getTypeConversion().updateFrameSlot(this, slot, getValue(slot)); - if (tags[slotIndex] != accessKind.ordinal()) { - throw new FrameSlotTypeException(); + resize(); + } + byte tag = tags[slotIndex]; + if (accessKind == FrameSlotKind.Object ? (tag & 0xfe) != 0 : tag != accessKind.ordinal()) { + CompilerDirectives.transferToInterpreter(); + if (slot.getKind() == accessKind || tag == 0) { + descriptor.getTypeConversion().updateFrameSlot(this, slot, getValue(slot)); + if (tags[slotIndex] == accessKind.ordinal()) { + return; + } } + throw new FrameSlotTypeException(); } } @Override public Object getValue(FrameSlot slot) { - int index = slot.getIndex(); - if (index >= tags.length) { - assert index >= 0 && index < descriptor.getSize(); - return descriptor.getTypeConversion().getDefaultValue(); + int slotIndex = slot.getIndex(); + if (slotIndex >= tags.length) { + CompilerDirectives.transferToInterpreter(); + resize(); } - byte tag = tags[index]; - if (tag == FrameSlotKind.Illegal.ordinal()) { - return descriptor.getTypeConversion().getDefaultValue(); - } else if (tag == FrameSlotKind.Boolean.ordinal()) { + byte tag = tags[slotIndex]; + if (tag == FrameSlotKind.Boolean.ordinal()) { return getBooleanUnsafe(slot); + } else if (tag == FrameSlotKind.Byte.ordinal()) { + return getByteUnsafe(slot); } else if (tag == FrameSlotKind.Int.ordinal()) { return getIntUnsafe(slot); } else if (tag == FrameSlotKind.Double.ordinal()) { @@ -288,14 +296,17 @@ } else if (tag == FrameSlotKind.Float.ordinal()) { return getFloatUnsafe(slot); } else { + assert tag == FrameSlotKind.Object.ordinal() || tag == FrameSlotKind.Illegal.ordinal(); return getObjectUnsafe(slot); } } private void resize() { + int oldSize = tags.length; int newSize = descriptor.getSize(); - if (newSize > tags.length) { + if (newSize > oldSize) { locals = Arrays.copyOf(locals, newSize); + Arrays.fill(locals, oldSize, newSize, descriptor.getTypeConversion().getDefaultValue()); primitiveLocals = Arrays.copyOf(primitiveLocals, newSize); tags = Arrays.copyOf(tags, newSize); } @@ -303,14 +314,11 @@ @Override public boolean isInitialized(FrameSlot slot) { - try { - return tags[slot.getIndex()] != 0; - } catch (ArrayIndexOutOfBoundsException ex) { + int slotIndex = slot.getIndex(); + if (slotIndex >= tags.length) { CompilerDirectives.transferToInterpreter(); - if (slot.getIndex() >= 0 && slot.getIndex() < descriptor.getSize()) { - return false; - } - throw ex; + resize(); } + return tags[slotIndex] != 0; } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/GraalTruffleRuntime.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/GraalTruffleRuntime.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/GraalTruffleRuntime.java Wed Oct 02 13:26:31 2013 +0200 @@ -65,7 +65,7 @@ if (truffleCompiler == null) { truffleCompiler = new TruffleCompilerImpl(); } - return new OptimizedCallTarget(rootNode, frameDescriptor, truffleCompiler, TruffleCompilationThreshold.getValue()); + return new OptimizedCallTarget(rootNode, frameDescriptor, truffleCompiler, TruffleMinInvokeThreshold.getValue(), TruffleCompilationThreshold.getValue()); } @Override diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java Wed Oct 02 13:26:31 2013 +0200 @@ -43,12 +43,10 @@ private static final PrintStream OUT = TTY.out().out(); private static final int MIN_INVOKES_AFTER_INLINING = 2; - protected OptimizedCallTarget(RootNode rootNode, FrameDescriptor descriptor, TruffleCompiler compiler, int compilationThreshold) { + protected OptimizedCallTarget(RootNode rootNode, FrameDescriptor descriptor, TruffleCompiler compiler, int invokeCounter, int compilationThreshold) { super(rootNode, descriptor); this.compiler = compiler; - this.invokeCounter = compilationThreshold >> 7; - this.loopAndInvokeCounter = compilationThreshold; - this.originalInvokeCounter = compilationThreshold; + this.compilationPolicy = new CompilationPolicy(compilationThreshold, invokeCounter); this.rootNode.setCallTarget(this); if (TruffleCallTargetProfiling.getValue()) { @@ -58,10 +56,8 @@ private HotSpotNmethod compiledMethod; private final TruffleCompiler compiler; + private final CompilationPolicy compilationPolicy; - private int invokeCounter; - private int originalInvokeCounter; - private int loopAndInvokeCounter; private boolean disableCompilation; private int callCount; @@ -76,6 +72,10 @@ @Override public Object call(PackedFrame caller, Arguments args) { + return callHelper(caller, args); + } + + private Object callHelper(PackedFrame caller, Arguments args) { if (TruffleCallTargetProfiling.getValue()) { callCount++; } @@ -93,12 +93,8 @@ private Object compiledCodeInvalidated(PackedFrame caller, Arguments args) { CompilerAsserts.neverPartOfCompilation(); compiledMethod = null; - int invalidationReprofileCount = TruffleInvalidationReprofileCount.getValue(); - invokeCounter = invalidationReprofileCount; invalidationCount++; - if (TruffleFunctionInlining.getValue()) { - originalInvokeCounter += invalidationReprofileCount; - } + compilationPolicy.compilationInvalidated(); if (TraceTruffleCompilation.getValue()) { OUT.printf("[truffle] invalidated %-48s |Alive %5.0fms |Inv# %d |Replace# %d\n", rootNode, (System.nanoTime() - timeCompilationFinished) / 1e6, invalidationCount, replaceCount); @@ -108,9 +104,8 @@ private Object interpreterCall(PackedFrame caller, Arguments args) { CompilerAsserts.neverPartOfCompilation(); - invokeCounter--; - loopAndInvokeCounter--; - if (disableCompilation || loopAndInvokeCounter > 0 || invokeCounter > 0) { + compilationPolicy.countInterpreterCall(); + if (disableCompilation || !compilationPolicy.compileOrInline()) { return executeHelper(caller, args); } else { compileOrInline(); @@ -120,10 +115,7 @@ private void compileOrInline() { if (TruffleFunctionInlining.getValue() && inline()) { - invokeCounter = MIN_INVOKES_AFTER_INLINING; - int inliningReprofileCount = TruffleInliningReprofileCount.getValue(); - loopAndInvokeCounter = inliningReprofileCount; - originalInvokeCounter = inliningReprofileCount; + compilationPolicy.inlined(MIN_INVOKES_AFTER_INLINING); } else { compile(); } @@ -185,18 +177,13 @@ @Override public void reportLoopCount(int count) { - loopAndInvokeCounter -= count; + compilationPolicy.reportLoopCount(count); } @Override public void nodeReplaced() { replaceCount++; - - // delay compilation until tree is deemed stable enough - int replaceBackoff = TruffleReplaceReprofileCount.getValue(); - if (loopAndInvokeCounter < replaceBackoff) { - loopAndInvokeCounter = replaceBackoff; - } + compilationPolicy.nodeReplaced(); } private static class InliningHelper { @@ -276,7 +263,7 @@ public InliningPolicy(OptimizedCallTarget caller) { this.callerNodeCount = NodeUtil.countNodes(caller.getRootNode()); - this.callerInvocationCount = caller.originalInvokeCounter; + this.callerInvocationCount = caller.compilationPolicy.getOriginalInvokeCounter(); } public boolean continueInlining() { diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java Wed Oct 02 13:26:31 2013 +0200 @@ -26,11 +26,13 @@ import static com.oracle.graal.phases.GraalOptions.*; import static com.oracle.graal.truffle.TruffleCompilerOptions.*; +import java.lang.reflect.*; import java.util.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.debug.*; +import com.oracle.graal.debug.internal.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.Node; import com.oracle.graal.hotspot.*; @@ -44,7 +46,6 @@ import com.oracle.graal.nodes.util.*; import com.oracle.graal.nodes.virtual.*; import com.oracle.graal.phases.*; -import com.oracle.graal.phases.PhasePlan.PhasePosition; import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.common.CanonicalizerPhase.CustomCanonicalizer; import com.oracle.graal.phases.tiers.*; @@ -65,9 +66,8 @@ public class PartialEvaluator { private final MetaAccessProvider metaAccessProvider; - private final ResolvedJavaType nodeClass; private final ResolvedJavaMethod executeHelperMethod; - private final CustomCanonicalizer customCanonicalizer; + private final CanonicalizerPhase canonicalizer; private final ResolvedJavaType[] skippedExceptionTypes; private final Replacements replacements; private Set constantReceivers; @@ -76,8 +76,8 @@ public PartialEvaluator(MetaAccessProvider metaAccessProvider, Replacements replacements, TruffleCache truffleCache) { this.metaAccessProvider = metaAccessProvider; - this.nodeClass = metaAccessProvider.lookupJavaType(com.oracle.truffle.api.nodes.Node.class); - this.customCanonicalizer = new PartialEvaluatorCanonicalizer(metaAccessProvider, nodeClass); + CustomCanonicalizer customCanonicalizer = new PartialEvaluatorCanonicalizer(metaAccessProvider); + this.canonicalizer = new CanonicalizerPhase(!AOTCompilation.getValue(), customCanonicalizer); this.skippedExceptionTypes = TruffleCompilerImpl.getSkippedExceptionTypes(metaAccessProvider); this.replacements = replacements; this.cache = HotSpotGraalRuntime.graalRuntime().getCache(); @@ -122,8 +122,8 @@ thisNode.replaceAndDelete(ConstantNode.forObject(node, metaAccessProvider, graph)); // Canonicalize / constant propagate. - CanonicalizerPhase.Instance canonicalizerPhase = new CanonicalizerPhase.Instance(metaAccessProvider, assumptions, !AOTCompilation.getValue(), null, customCanonicalizer); - canonicalizerPhase.apply(graph); + PhaseContext baseContext = new PhaseContext(metaAccessProvider, assumptions, replacements); + canonicalizer.apply(graph, baseContext); // Intrinsify methods. new ReplaceIntrinsicsPhase(replacements).apply(graph); @@ -136,7 +136,9 @@ Debug.dump(graph, "Before inlining"); // Make sure frame does not escape. - expandTree(config, graph, newFrameNode, assumptions); + expandTree(graph, assumptions); + + new VerifyFrameDoesNotEscapePhase().apply(graph, false); if (TruffleInlinePrinter.getValue()) { InlinePrinterProcessor.printTree(); @@ -148,29 +150,13 @@ for (Constant c : constantReceivers) { histogram.add(c.asObject().getClass().getSimpleName()); } - histogram.print(TTY.out().out()); + new DebugHistogramAsciiPrinter(TTY.out().out()).print(histogram); } // Additional inlining. final PhasePlan plan = new PhasePlan(); - GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(metaAccessProvider, config, TruffleCompilerImpl.Optimizations); - plan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase); - plan.addPhase(PhasePosition.AFTER_PARSING, canonicalizerPhase); - plan.addPhase(PhasePosition.AFTER_PARSING, new ReplaceIntrinsicsPhase(replacements)); - - new ConvertDeoptimizeToGuardPhase().apply(graph); - canonicalizerPhase.apply(graph); - new DeadCodeEliminationPhase().apply(graph); - + canonicalizer.apply(graph, baseContext); HighTierContext context = new HighTierContext(metaAccessProvider, assumptions, replacements, cache, plan, OptimisticOptimizations.NONE); - InliningPhase inliningPhase = new InliningPhase(customCanonicalizer); - inliningPhase.apply(graph, context); - - // Convert deopt to guards. - new ConvertDeoptimizeToGuardPhase().apply(graph); - - // Canonicalize / constant propagate. - canonicalizerPhase.apply(graph); for (NeverPartOfCompilationNode neverPartOfCompilationNode : graph.getNodes(NeverPartOfCompilationNode.class)) { Throwable exception = new VerificationError(neverPartOfCompilationNode.getMessage()); @@ -178,8 +164,7 @@ } // EA frame and clean up. - new VerifyFrameDoesNotEscapePhase().apply(graph, false); - new PartialEscapePhase(false).apply(graph, context); + new PartialEscapePhase(false, canonicalizer).apply(graph, context); new VerifyNoIntrinsicsLeftPhase().apply(graph, false); for (MaterializeFrameNode materializeNode : graph.getNodes(MaterializeFrameNode.class).snapshot()) { materializeNode.replaceAtUsages(materializeNode.getFrame()); @@ -197,55 +182,53 @@ } } } - - // Convert deopt to guards. - new ConvertDeoptimizeToGuardPhase().apply(graph); - - // Canonicalize / constant propagate. - canonicalizerPhase.apply(graph); } }); return graph; } - private void expandTree(GraphBuilderConfiguration config, StructuredGraph graph, NewFrameNode newFrameNode, Assumptions assumptions) { + private void expandTree(StructuredGraph graph, Assumptions assumptions) { + PhaseContext context = new PhaseContext(metaAccessProvider, assumptions, replacements); boolean changed; do { changed = false; - for (Node usage : newFrameNode.usages().snapshot()) { - if (usage instanceof MethodCallTargetNode && !usage.isDeleted()) { - MethodCallTargetNode methodCallTargetNode = (MethodCallTargetNode) usage; - InvokeKind kind = methodCallTargetNode.invokeKind(); - if (kind == InvokeKind.Special || kind == InvokeKind.Static) { - if (TruffleInlinePrinter.getValue()) { - InlinePrinterProcessor.addInlining(MethodHolder.getNewTruffleExecuteMethod(methodCallTargetNode)); + for (MethodCallTargetNode methodCallTargetNode : graph.getNodes(MethodCallTargetNode.class)) { + InvokeKind kind = methodCallTargetNode.invokeKind(); + if (kind == InvokeKind.Static || (kind == InvokeKind.Special && (methodCallTargetNode.receiver().isConstant() || methodCallTargetNode.receiver() instanceof NewFrameNode))) { + if (TruffleInlinePrinter.getValue()) { + InlinePrinterProcessor.addInlining(MethodHolder.getNewTruffleExecuteMethod(methodCallTargetNode)); + } + if (TraceTruffleCompilationDetails.getValue() && kind == InvokeKind.Special) { + ConstantNode constantNode = (ConstantNode) methodCallTargetNode.arguments().first(); + constantReceivers.add(constantNode.asConstant()); + } + StructuredGraph inlineGraph = replacements.getMethodSubstitution(methodCallTargetNode.targetMethod()); + + if (inlineGraph == null) { + Class macroSubstitution = replacements.getMacroSubstitution(methodCallTargetNode.targetMethod()); + if (macroSubstitution != null) { + InliningUtil.inlineMacroNode(methodCallTargetNode.invoke(), methodCallTargetNode.targetMethod(), methodCallTargetNode.graph(), macroSubstitution); + changed = true; + continue; } - if (TraceTruffleCompilationDetails.getValue() && kind == InvokeKind.Special && methodCallTargetNode.arguments().first() instanceof ConstantNode) { - ConstantNode constantNode = (ConstantNode) methodCallTargetNode.arguments().first(); - constantReceivers.add(constantNode.asConstant()); - } - StructuredGraph inlineGraph = replacements.getMethodSubstitution(methodCallTargetNode.targetMethod()); - NewFrameNode otherNewFrame = null; - if (inlineGraph == null) { - inlineGraph = parseGraph(methodCallTargetNode.targetMethod(), methodCallTargetNode.arguments(), assumptions, !AOTCompilation.getValue()); - otherNewFrame = inlineGraph.getNodes(NewFrameNode.class).first(); - } + } + if (inlineGraph == null && !Modifier.isNative(methodCallTargetNode.targetMethod().getModifiers()) && + methodCallTargetNode.targetMethod().getAnnotation(CompilerDirectives.SlowPath.class) == null) { + inlineGraph = parseGraph(methodCallTargetNode.targetMethod(), methodCallTargetNode.arguments(), assumptions, context); + } + + if (inlineGraph != null) { int nodeCountBefore = graph.getNodeCount(); - Map mapping = InliningUtil.inline(methodCallTargetNode.invoke(), inlineGraph, false); + int mark = graph.getMark(); + InliningUtil.inline(methodCallTargetNode.invoke(), inlineGraph, false); if (Debug.isDumpEnabled()) { int nodeCountAfter = graph.getNodeCount(); Debug.dump(graph, "After inlining %s %+d (%d)", methodCallTargetNode.targetMethod().toString(), nodeCountAfter - nodeCountBefore, nodeCountAfter); } + canonicalizer.applyIncremental(graph, context, mark); changed = true; - - if (otherNewFrame != null) { - otherNewFrame = (NewFrameNode) mapping.get(otherNewFrame); - if (otherNewFrame.isAlive() && otherNewFrame.usages().isNotEmpty()) { - expandTree(config, graph, otherNewFrame, assumptions); - } - } } } @@ -253,64 +236,68 @@ throw new BailoutException("Truffle compilation is exceeding maximum node count: " + graph.getNodeCount()); } } - } while (changed && newFrameNode.isAlive() && newFrameNode.usages().isNotEmpty()); + } while (changed); } - private StructuredGraph parseGraph(final ResolvedJavaMethod targetMethod, final NodeInputList arguments, final Assumptions assumptions, final boolean canonicalizeReads) { - - final StructuredGraph graph = truffleCache.lookup(targetMethod, arguments, assumptions); - Debug.scope("parseGraph", targetMethod, new Runnable() { + private StructuredGraph parseGraph(final ResolvedJavaMethod targetMethod, final NodeInputList arguments, final Assumptions assumptions, final PhaseContext context) { - @Override - public void run() { - - // Canonicalize / constant propagate. - new CanonicalizerPhase.Instance(metaAccessProvider, assumptions, canonicalizeReads, null, customCanonicalizer).apply(graph); + StructuredGraph graph = truffleCache.lookup(targetMethod, arguments, assumptions, canonicalizer); - // Intrinsify methods. - new ReplaceIntrinsicsPhase(replacements).apply(graph); + if (targetMethod.getAnnotation(ExplodeLoop.class) != null) { + assert graph.hasLoops(); + final StructuredGraph graphCopy = graph.copy(); + final List modifiedNodes = new ArrayList<>(); + for (LocalNode local : graphCopy.getNodes(LocalNode.class)) { + ValueNode arg = arguments.get(local.index()); + if (arg.isConstant()) { + Constant constant = arg.asConstant(); + ConstantNode constantNode = ConstantNode.forConstant(constant, metaAccessProvider, graphCopy); + local.replaceAndDelete(constantNode); + for (Node usage : constantNode.usages()) { + if (usage instanceof Canonicalizable) { + modifiedNodes.add(usage); + } + } + } + } + Debug.scope("TruffleUnrollLoop", targetMethod, new Runnable() { - // Inline trivial getter methods - new InlineTrivialGettersPhase(metaAccessProvider, assumptions, customCanonicalizer).apply(graph); + @Override + public void run() { - // Convert deopt to guards. - new ConvertDeoptimizeToGuardPhase().apply(graph); - - if (graph.hasLoops()) { + canonicalizer.applyIncremental(graphCopy, context, modifiedNodes); boolean unrolled; do { unrolled = false; - LoopsData loopsData = new LoopsData(graph); + LoopsData loopsData = new LoopsData(graphCopy); loopsData.detectedCountedLoops(); for (LoopEx ex : innerLoopsFirst(loopsData.countedLoops())) { if (ex.counted().isConstantMaxTripCount()) { long constant = ex.counted().constantMaxTripCount(); - if (constant <= TruffleConstantUnrollLimit.getValue() || targetMethod.getAnnotation(ExplodeLoop.class) != null) { - LoopTransformations.fullUnroll(ex, metaAccessProvider, assumptions, canonicalizeReads); - Debug.dump(graph, "After loop unrolling %d times", constant); - new CanonicalizerPhase.Instance(metaAccessProvider, assumptions, canonicalizeReads, null, customCanonicalizer).apply(graph); - unrolled = true; - break; - } + LoopTransformations.fullUnroll(ex, context, canonicalizer); + Debug.dump(graphCopy, "After loop unrolling %d times", constant); + unrolled = true; + break; } } } while (unrolled); } - } - private List innerLoopsFirst(Collection loops) { - ArrayList sortedLoops = new ArrayList<>(loops); - Collections.sort(sortedLoops, new Comparator() { + private List innerLoopsFirst(Collection loops) { + ArrayList sortedLoops = new ArrayList<>(loops); + Collections.sort(sortedLoops, new Comparator() { - @Override - public int compare(LoopEx o1, LoopEx o2) { - return o2.lirLoop().depth - o1.lirLoop().depth; - } - }); - return sortedLoops; - } - }); - - return graph; + @Override + public int compare(LoopEx o1, LoopEx o2) { + return o2.lirLoop().depth - o1.lirLoop().depth; + } + }); + return sortedLoops; + } + }); + return graphCopy; + } else { + return graph; + } } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluatorCanonicalizer.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluatorCanonicalizer.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluatorCanonicalizer.java Wed Oct 02 13:26:31 2013 +0200 @@ -24,10 +24,11 @@ import java.lang.reflect.*; +import sun.misc.*; + import com.oracle.graal.api.meta.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.java.*; -import com.oracle.graal.nodes.type.*; import com.oracle.graal.phases.common.*; import com.oracle.truffle.api.*; import com.oracle.truffle.api.nodes.Node.Child; @@ -35,40 +36,43 @@ final class PartialEvaluatorCanonicalizer implements CanonicalizerPhase.CustomCanonicalizer { private final MetaAccessProvider metaAccessProvider; - private final ResolvedJavaType nodeClass; - PartialEvaluatorCanonicalizer(MetaAccessProvider metaAccessProvider, ResolvedJavaType nodeClass) { + PartialEvaluatorCanonicalizer(MetaAccessProvider metaAccessProvider) { this.metaAccessProvider = metaAccessProvider; - this.nodeClass = nodeClass; } @Override public ValueNode canonicalize(ValueNode node) { if (node instanceof LoadFieldNode) { LoadFieldNode loadFieldNode = (LoadFieldNode) node; - if (!loadFieldNode.isStatic() && - loadFieldNode.object().isConstant() && - !loadFieldNode.object().isNullConstant() && - ((loadFieldNode.kind() == Kind.Object && loadFieldNode.field().getAnnotation(Child.class) != null) || Modifier.isFinal(loadFieldNode.field().getModifiers()) || loadFieldNode.field().getAnnotation( - CompilerDirectives.CompilationFinal.class) != null)) { - Constant constant = loadFieldNode.field().readValue(loadFieldNode.object().asConstant()); - return ConstantNode.forConstant(constant, metaAccessProvider, node.graph()); + if (!loadFieldNode.isStatic() && loadFieldNode.object().isConstant() && !loadFieldNode.object().isNullConstant()) { + if (Modifier.isFinal(loadFieldNode.field().getModifiers()) || (loadFieldNode.kind() == Kind.Object && loadFieldNode.field().getAnnotation(Child.class) != null) || + loadFieldNode.field().getAnnotation(CompilerDirectives.CompilationFinal.class) != null) { + Constant constant = loadFieldNode.field().readValue(loadFieldNode.object().asConstant()); + assert verifyFieldValue(loadFieldNode.field(), constant); + return ConstantNode.forConstant(constant, metaAccessProvider, node.graph()); + } } } else if (node instanceof LoadIndexedNode) { LoadIndexedNode loadIndexedNode = (LoadIndexedNode) node; - Stamp stamp = loadIndexedNode.array().stamp(); - if (stamp.kind() == Kind.Object && loadIndexedNode.array().isConstant() && !loadIndexedNode.array().isNullConstant() && loadIndexedNode.index().isConstant()) { - ObjectStamp objectStamp = (ObjectStamp) stamp; - ResolvedJavaType type = objectStamp.type(); - if (type != null && type.isArray() && this.nodeClass.isAssignableFrom(type.getComponentType())) { - Object array = loadIndexedNode.array().asConstant().asObject(); - int index = loadIndexedNode.index().asConstant().asInt(); - Object value = Array.get(array, index); - return ConstantNode.forObject(value, metaAccessProvider, node.graph()); + if (loadIndexedNode.array().isConstant() && !loadIndexedNode.array().isNullConstant() && loadIndexedNode.index().isConstant()) { + Object array = loadIndexedNode.array().asConstant().asObject(); + long index = loadIndexedNode.index().asConstant().asLong(); + if (index >= 0 && index < Array.getLength(array)) { + int arrayBaseOffset = Unsafe.getUnsafe().arrayBaseOffset(array.getClass()); + int arrayIndexScale = Unsafe.getUnsafe().arrayIndexScale(array.getClass()); + Constant constant = metaAccessProvider.readUnsafeConstant(loadIndexedNode.elementKind(), array, arrayBaseOffset + index * arrayIndexScale, + loadIndexedNode.elementKind() == Kind.Object); + return ConstantNode.forConstant(constant, metaAccessProvider, loadIndexedNode.graph()); } } } - return node; } + + private static boolean verifyFieldValue(ResolvedJavaField field, Constant constant) { + assert field.getAnnotation(Child.class) == null || constant.isNull() || constant.asObject() instanceof com.oracle.truffle.api.nodes.Node : "@Child field value must be a Node: " + field + + ", but was: " + constant.asObject(); + return true; + } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCache.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCache.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCache.java Wed Oct 02 13:26:31 2013 +0200 @@ -31,16 +31,15 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.debug.*; -import com.oracle.graal.debug.internal.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.Node; import com.oracle.graal.java.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; +import com.oracle.graal.nodes.util.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.tiers.*; @@ -59,264 +58,168 @@ private final OptimisticOptimizations optimisticOptimizations; private final Replacements replacements; - private final HashMap cache = new HashMap<>(); + private final HashMap, StructuredGraph> cache = new HashMap<>(); + private final StructuredGraph markerGraph = new StructuredGraph(); + private final ResolvedJavaType stringBuilderClass; public TruffleCache(MetaAccessProvider metaAccessProvider, GraphBuilderConfiguration config, OptimisticOptimizations optimisticOptimizations, Replacements replacements) { this.metaAccessProvider = metaAccessProvider; this.config = config; this.optimisticOptimizations = optimisticOptimizations; this.replacements = replacements; + this.stringBuilderClass = metaAccessProvider.lookupJavaType(StringBuilder.class); } - public StructuredGraph lookup(final ResolvedJavaMethod method, final NodeInputList arguments, final Assumptions assumptions) { + @SuppressWarnings("unused") + public StructuredGraph lookup(final ResolvedJavaMethod method, final NodeInputList arguments, final Assumptions assumptions, final CanonicalizerPhase finalCanonicalizer) { - StructuredGraph resultGraph = null; - if (cache.containsKey(method)) { - StructuredGraph graph = cache.get(method); - if (checkArgumentStamps(graph, arguments)) { - resultGraph = graph; + List key = new ArrayList<>(arguments.size() + 1); + key.add(method); + for (ValueNode v : arguments) { + if (v.kind() == Kind.Object) { + key.add(v.stamp()); } } + StructuredGraph resultGraph = cache.get(key); + if (resultGraph != null) { + return resultGraph; + } + + if (resultGraph == markerGraph) { + // Avoid recursive inline. + return null; + } - if (resultGraph == null) { - resultGraph = Debug.sandbox("TruffleCache", new Object[]{metaAccessProvider, method}, DebugScope.getConfig(), new Callable() { + cache.put(key, markerGraph); + resultGraph = Debug.scope("TruffleCache", new Object[]{metaAccessProvider, method}, new Callable() { + + public StructuredGraph call() { + + final StructuredGraph graph = new StructuredGraph(method); + PhaseContext context = new PhaseContext(metaAccessProvider, new Assumptions(false), replacements); + new GraphBuilderPhase(metaAccessProvider, config, optimisticOptimizations).apply(graph); + + for (LocalNode l : graph.getNodes(LocalNode.class)) { + if (l.kind() == Kind.Object) { + ValueNode actualArgument = arguments.get(l.index()); + l.setStamp(l.stamp().join(actualArgument.stamp())); + } + } - public StructuredGraph call() { - StructuredGraph newGraph = parseGraph(method); + // Intrinsify methods. + new ReplaceIntrinsicsPhase(replacements).apply(graph); + + // Convert deopt to guards. + new ConvertDeoptimizeToGuardPhase().apply(graph); + + CanonicalizerPhase canonicalizerPhase = new CanonicalizerPhase(!AOTCompilation.getValue()); + PartialEscapePhase partialEscapePhase = new PartialEscapePhase(false, canonicalizerPhase); + + int mark = 0; + while (true) { + + partialEscapePhase.apply(graph, context); + + // Conditional elimination. + ConditionalEliminationPhase conditionalEliminationPhase = new ConditionalEliminationPhase(metaAccessProvider); + conditionalEliminationPhase.apply(graph); + + // Canonicalize / constant propagate. + canonicalizerPhase.apply(graph, context); - // Get stamps from actual arguments. - List stamps = new ArrayList<>(); - for (ValueNode arg : arguments) { - stamps.add(arg.stamp()); - } - - if (cache.containsKey(method)) { - // Make sure stamps are generalized based on previous stamps. - StructuredGraph graph = cache.get(method); - for (LocalNode localNode : graph.getNodes(LocalNode.class)) { - int index = localNode.index(); - Stamp stamp = stamps.get(index); - stamps.set(index, stamp.meet(localNode.stamp())); + boolean inliningProgress = false; + for (MethodCallTargetNode methodCallTarget : graph.getNodes(MethodCallTargetNode.class)) { + if (graph.getMark() != mark) { + // Make sure macro substitutions such as + // CompilerDirectives.transferToInterpreter get processed first. + for (Node newNode : graph.getNewNodes(mark)) { + if (newNode instanceof MethodCallTargetNode) { + MethodCallTargetNode methodCallTargetNode = (MethodCallTargetNode) newNode; + Class macroSubstitution = replacements.getMacroSubstitution(methodCallTargetNode.targetMethod()); + if (macroSubstitution != null) { + InliningUtil.inlineMacroNode(methodCallTargetNode.invoke(), methodCallTargetNode.targetMethod(), methodCallTargetNode.graph(), macroSubstitution); + } else { + tryCutOffRuntimeExceptions(methodCallTargetNode); + } + } + } + mark = graph.getMark(); + } + if (methodCallTarget.isAlive() && methodCallTarget.invoke() != null && shouldInline(methodCallTarget)) { + inliningProgress = true; + List canonicalizerUsages = new ArrayList(); + for (Node n : methodCallTarget.invoke().asNode().usages()) { + if (n instanceof Canonicalizable) { + canonicalizerUsages.add(n); + } + } + List argumentSnapshot = methodCallTarget.arguments().snapshot(); + int beforeInvokeMark = graph.getMark(); + expandInvoke(methodCallTarget); + for (Node arg : argumentSnapshot) { + if (arg != null) { + for (Node argUsage : arg.usages()) { + if (graph.isNew(beforeInvokeMark, argUsage) && argUsage instanceof Canonicalizable) { + canonicalizerUsages.add(argUsage); + } + } + } + } + canonicalizerPhase.applyIncremental(graph, context, canonicalizerUsages); } } - // Set stamps into graph before optimizing. - for (LocalNode localNode : newGraph.getNodes(LocalNode.class)) { - int index = localNode.index(); - Stamp stamp = stamps.get(index); - localNode.setStamp(stamp); - } - - Assumptions tmpAssumptions = new Assumptions(false); - - optimizeGraph(newGraph, tmpAssumptions); - - PhaseContext context = new PhaseContext(metaAccessProvider, tmpAssumptions, replacements); - PartialEscapePhase partialEscapePhase = new PartialEscapePhase(false); - partialEscapePhase.apply(newGraph, context); + // Convert deopt to guards. + new ConvertDeoptimizeToGuardPhase().apply(graph); - cache.put(method, newGraph); - if (TruffleCompilerOptions.TraceTruffleCacheDetails.getValue()) { - TTY.println(String.format("[truffle] added to graph cache method %s with %d nodes.", method, newGraph.getNodeCount())); - } - return newGraph; - } - }); - } - - final StructuredGraph clonedResultGraph = resultGraph.copy(); - - Debug.sandbox("TruffleCacheConstants", new Object[]{metaAccessProvider, method}, DebugScope.getConfig(), new Runnable() { - - public void run() { - - Debug.dump(clonedResultGraph, "before applying constants"); - // Pass on constant arguments. - for (LocalNode local : clonedResultGraph.getNodes(LocalNode.class)) { - ValueNode arg = arguments.get(local.index()); - if (arg.isConstant()) { - Constant constant = arg.asConstant(); - local.replaceAndDelete(ConstantNode.forConstant(constant, metaAccessProvider, clonedResultGraph)); - } else { - local.setStamp(arg.stamp()); + if (!inliningProgress) { + break; } } - Debug.dump(clonedResultGraph, "after applying constants"); - optimizeGraph(clonedResultGraph, assumptions); + + if (TruffleCompilerOptions.TraceTruffleCacheDetails.getValue()) { + TTY.println(String.format("[truffle] added to graph cache method %s with %d nodes.", method, graph.getNodeCount())); + } + return graph; } }); - return clonedResultGraph; - } - - private void optimizeGraph(StructuredGraph newGraph, Assumptions assumptions) { - PhaseContext context = new PhaseContext(metaAccessProvider, assumptions, replacements); - ConditionalEliminationPhase conditionalEliminationPhase = new ConditionalEliminationPhase(metaAccessProvider); - ConvertDeoptimizeToGuardPhase convertDeoptimizeToGuardPhase = new ConvertDeoptimizeToGuardPhase(); - CanonicalizerPhase canonicalizerPhase = new CanonicalizerPhase(!AOTCompilation.getValue()); - EarlyReadEliminationPhase readEliminationPhase = new EarlyReadEliminationPhase(); - - int maxNodes = TruffleCompilerOptions.TruffleOperationCacheMaxNodes.getValue(); - - contractGraph(newGraph, conditionalEliminationPhase, convertDeoptimizeToGuardPhase, canonicalizerPhase, readEliminationPhase, context); - - while (newGraph.getNodeCount() <= maxNodes) { - - int mark = newGraph.getMark(); - - expandGraph(newGraph, maxNodes); - - if (newGraph.getNewNodes(mark).count() == 0) { - // No progress => exit iterative optimization. - break; - } - - contractGraph(newGraph, conditionalEliminationPhase, convertDeoptimizeToGuardPhase, canonicalizerPhase, readEliminationPhase, context); - } - - if (newGraph.getNodeCount() > maxNodes && (TruffleCompilerOptions.TraceTruffleCacheDetails.getValue() || TruffleCompilerOptions.TraceTrufflePerformanceWarnings.getValue())) { - TTY.println(String.format("[truffle] PERFORMANCE WARNING: method %s got too large with %d nodes.", newGraph.method(), newGraph.getNodeCount())); - } + cache.put(key, resultGraph); + return resultGraph; } - private static void contractGraph(StructuredGraph newGraph, ConditionalEliminationPhase conditionalEliminationPhase, ConvertDeoptimizeToGuardPhase convertDeoptimizeToGuardPhase, - CanonicalizerPhase canonicalizerPhase, EarlyReadEliminationPhase readEliminationPhase, PhaseContext context) { - // Canonicalize / constant propagate. - canonicalizerPhase.apply(newGraph, context); - - // Early read eliminiation - readEliminationPhase.apply(newGraph, context); - - // Convert deopt to guards. - convertDeoptimizeToGuardPhase.apply(newGraph); - - // Conditional elimination. - conditionalEliminationPhase.apply(newGraph); - } - - private void expandGraph(StructuredGraph newGraph, int maxNodes) { - NodeBitMap visitedNodes = newGraph.createNodeBitMap(true); - Queue workQueue = new LinkedList<>(); - workQueue.add(newGraph.start()); - - while (!workQueue.isEmpty() && newGraph.getNodeCount() <= maxNodes) { - AbstractBeginNode start = workQueue.poll(); - expandPath(newGraph, maxNodes, visitedNodes, start, workQueue); + private void expandInvoke(MethodCallTargetNode methodCallTargetNode) { + StructuredGraph inlineGraph = replacements.getMethodSubstitution(methodCallTargetNode.targetMethod()); + if (inlineGraph == null) { + inlineGraph = TruffleCache.this.lookup(methodCallTargetNode.targetMethod(), methodCallTargetNode.arguments(), null, null); } + if (inlineGraph == this.markerGraph) { + // Can happen for recursive calls. + throw GraphUtil.approxSourceException(methodCallTargetNode, new IllegalStateException("Found illegal recursive call to " + methodCallTargetNode.targetMethod() + + ", must annotate such calls with @CompilerDirectives.SlowPath!")); + } + Invoke invoke = methodCallTargetNode.invoke(); + InliningUtil.inline(invoke, inlineGraph, true); } - private void expandPath(StructuredGraph newGraph, int maxNodes, NodeBitMap visitedNodes, AbstractBeginNode start, Queue workQueue) { - if (start.isDeleted()) { - return; - } - - FixedNode next = start; - while (!visitedNodes.isMarked(next)) { - visitedNodes.mark(next); - if (next instanceof Invoke) { - Invoke invoke = (Invoke) next; - next = expandInvoke(invoke); - if (newGraph.getNodeCount() > maxNodes) { - return; - } - } - - if (next instanceof InvokeWithExceptionNode) { - InvokeWithExceptionNode invokeWithExceptionNode = (InvokeWithExceptionNode) next; - next = invokeWithExceptionNode.next(); - } else if (next instanceof IfNode && isAssertionsEnabledCondition(((IfNode) next).condition())) { - next = ((IfNode) next).falseSuccessor(); - } else if (next instanceof ControlSplitNode) { - ControlSplitNode controlSplitNode = (ControlSplitNode) next; - AbstractBeginNode maxProbNode = null; - for (Node succ : controlSplitNode.cfgSuccessors()) { - AbstractBeginNode successor = (AbstractBeginNode) succ; - if (maxProbNode == null || controlSplitNode.probability(successor) > controlSplitNode.probability(maxProbNode)) { - maxProbNode = successor; - } - } - for (Node succ : controlSplitNode.cfgSuccessors()) { - AbstractBeginNode successor = (AbstractBeginNode) succ; - if (successor != maxProbNode) { - workQueue.add(successor); - } - } - next = maxProbNode; - } else if (next instanceof EndNode) { - EndNode endNode = (EndNode) next; - next = endNode.merge(); - } else if (next instanceof ControlSinkNode) { - return; - } else if (next instanceof FixedWithNextNode) { - FixedWithNextNode fixedWithNextNode = (FixedWithNextNode) next; - next = fixedWithNextNode.next(); - } - } - } - - private static boolean isAssertionsEnabledCondition(LogicNode condition) { - if (condition instanceof IntegerEqualsNode) { - IntegerEqualsNode equalsNode = (IntegerEqualsNode) condition; - if (equalsNode.x() instanceof LoadFieldNode && equalsNode.y().isConstant()) { - LoadFieldNode loadFieldNode = (LoadFieldNode) equalsNode.x(); - if (loadFieldNode.isStatic() && loadFieldNode.field().getName().equals("$assertionsDisabled") && loadFieldNode.field().isSynthetic()) { - return ((ConstantNode) equalsNode.y()).value.equals(Constant.INT_0); - } + private boolean tryCutOffRuntimeExceptions(MethodCallTargetNode methodCallTargetNode) { + if (methodCallTargetNode.targetMethod().isConstructor()) { + ResolvedJavaType runtimeException = metaAccessProvider.lookupJavaType(RuntimeException.class); + ResolvedJavaType controlFlowException = metaAccessProvider.lookupJavaType(ControlFlowException.class); + ResolvedJavaType exceptionType = Objects.requireNonNull(ObjectStamp.typeOrNull(methodCallTargetNode.receiver().stamp())); + if (runtimeException.isAssignableFrom(methodCallTargetNode.targetMethod().getDeclaringClass()) && !controlFlowException.isAssignableFrom(exceptionType)) { + DeoptimizeNode deoptNode = methodCallTargetNode.graph().add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.UnreachedCode)); + FixedNode invokeNode = methodCallTargetNode.invoke().asNode(); + invokeNode.replaceAtPredecessor(deoptNode); + GraphUtil.killCFG(invokeNode); + return true; } } return false; } - private FixedNode expandInvoke(Invoke invoke) { - if (invoke.callTarget() instanceof MethodCallTargetNode) { - final MethodCallTargetNode methodCallTargetNode = (MethodCallTargetNode) invoke.callTarget(); - - if ((methodCallTargetNode.invokeKind() == InvokeKind.Special || methodCallTargetNode.invokeKind() == InvokeKind.Static) && - !Modifier.isNative(methodCallTargetNode.targetMethod().getModifiers()) && methodCallTargetNode.targetMethod().getAnnotation(ExplodeLoop.class) == null && - methodCallTargetNode.targetMethod().getAnnotation(CompilerDirectives.SlowPath.class) == null) { - Class macroSubstitution = replacements.getMacroSubstitution(methodCallTargetNode.targetMethod()); - if (macroSubstitution != null) { - return InliningUtil.inlineMacroNode(invoke, methodCallTargetNode.targetMethod(), methodCallTargetNode.graph(), macroSubstitution); - } else { - StructuredGraph inlinedGraph = Debug.scope("ExpandInvoke", methodCallTargetNode.targetMethod(), new Callable() { - - public StructuredGraph call() { - StructuredGraph inlineGraph = replacements.getMethodSubstitution(methodCallTargetNode.targetMethod()); - if (inlineGraph == null) { - inlineGraph = parseGraph(methodCallTargetNode.targetMethod()); - } - return inlineGraph; - } - }); - FixedNode fixedNode = (FixedNode) invoke.predecessor(); - InliningUtil.inline(invoke, inlinedGraph, true); - return fixedNode; - } - } - } - return invoke.asNode(); - } - - private StructuredGraph parseGraph(ResolvedJavaMethod method) { - StructuredGraph graph = new StructuredGraph(method); - new GraphBuilderPhase(metaAccessProvider, config, optimisticOptimizations).apply(graph); - // Intrinsify methods. - new ReplaceIntrinsicsPhase(replacements).apply(graph); - return graph; - } - - private static boolean checkArgumentStamps(StructuredGraph graph, NodeInputList arguments) { - assert graph.getNodes(LocalNode.class).count() <= arguments.count(); - for (LocalNode localNode : graph.getNodes(LocalNode.class)) { - Stamp newStamp = localNode.stamp().meet(arguments.get(localNode.index()).stamp()); - if (!newStamp.equals(localNode.stamp())) { - if (TruffleCompilerOptions.TraceTruffleCacheDetails.getValue()) { - TTY.println(String.format("[truffle] graph cache entry too specific for method %s argument %s previous stamp %s new stamp %s.", graph.method(), localNode, localNode.stamp(), - newStamp)); - } - return false; - } - } - - return true; + private boolean shouldInline(final MethodCallTargetNode methodCallTargetNode) { + return (methodCallTargetNode.invokeKind() == InvokeKind.Special || methodCallTargetNode.invokeKind() == InvokeKind.Static) && + !Modifier.isNative(methodCallTargetNode.targetMethod().getModifiers()) && methodCallTargetNode.targetMethod().getAnnotation(ExplodeLoop.class) == null && + methodCallTargetNode.targetMethod().getAnnotation(CompilerDirectives.SlowPath.class) == null && methodCallTargetNode.targetMethod().getDeclaringClass() != stringBuilderClass; } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java Wed Oct 02 13:26:31 2013 +0200 @@ -23,7 +23,6 @@ package com.oracle.graal.truffle; import static com.oracle.graal.api.code.CodeUtil.*; -import static com.oracle.graal.compiler.GraalDebugConfig.*; import java.util.*; import java.util.concurrent.*; @@ -78,13 +77,13 @@ this.graalRuntime = HotSpotGraalRuntime.graalRuntime(); this.skippedExceptionTypes = getSkippedExceptionTypes(metaAccessProvider); - final GraphBuilderConfiguration config = GraphBuilderConfiguration.getDefault(); + final GraphBuilderConfiguration config = GraphBuilderConfiguration.getEagerDefault(); config.setSkippedExceptionTypes(skippedExceptionTypes); this.truffleCache = new TruffleCache(this.runtime, config, TruffleCompilerImpl.Optimizations, this.replacements); this.partialEvaluator = new PartialEvaluator(metaAccessProvider, replacements, truffleCache); - if (DebugEnabled.getValue()) { + if (Debug.isEnabled()) { DebugEnvironment.initialize(System.out); } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java Wed Oct 02 13:26:31 2013 +0200 @@ -46,6 +46,8 @@ @Option(help = "") public static final OptionValue TruffleCompilationThreshold = new OptionValue<>(1000); @Option(help = "") + public static final OptionValue TruffleMinInvokeThreshold = new OptionValue<>(3); + @Option(help = "") public static final OptionValue TruffleInvalidationReprofileCount = new OptionValue<>(3); @Option(help = "") public static final OptionValue TruffleReplaceReprofileCount = new OptionValue<>(10); @@ -69,7 +71,10 @@ public static final OptionValue TruffleInliningTrivialSize = new OptionValue<>(10); @Option(help = "") public static final OptionValue TruffleInliningMinFrequency = new OptionValue<>(0.3); - + @Option(help = "") + public static final OptionValue TruffleUseTimeForCompilationDecision = new OptionValue<>(false); + @Option(help = "") + public static final OptionValue TruffleCompilationDecisionTime = new OptionValue<>(100); // tracing @Option(help = "") public static final OptionValue TraceTruffleCompilation = new OptionValue<>(true); diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleReplacements.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleReplacements.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleReplacements.java Wed Oct 02 13:26:31 2013 +0200 @@ -56,7 +56,6 @@ truffleReplacements.registerSubstitutions(CompilerDirectivesSubstitutions.class); truffleReplacements.registerSubstitutions(ExactMathSubstitutions.class); truffleReplacements.registerSubstitutions(UnexpectedResultExceptionSubstitutions.class); - truffleReplacements.registerSubstitutions(SlowPathExceptionSubstitutions.class); truffleReplacements.registerSubstitutions(FrameWithoutBoxingSubstitutions.class); truffleReplacements.registerSubstitutions(OptimizedAssumptionSubstitutions.class); truffleReplacements.registerSubstitutions(OptimizedCallTargetSubstitutions.class); diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/AssumptionNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/AssumptionNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/AssumptionNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -22,14 +22,13 @@ */ package com.oracle.graal.truffle.nodes; -import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.replacements.nodes.*; import com.oracle.graal.truffle.*; -public class AssumptionNode extends MacroNode implements com.oracle.graal.graph.Node.IterableNodeType, Simplifiable { +public class AssumptionNode extends MacroNode implements com.oracle.graal.graph.IterableNodeType, Simplifiable { public AssumptionNode(Invoke invoke) { super(invoke); diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/BailoutNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/BailoutNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/BailoutNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -27,7 +27,7 @@ import com.oracle.graal.nodes.spi.*; import com.oracle.graal.replacements.nodes.*; -public class BailoutNode extends MacroNode implements com.oracle.graal.graph.Node.IterableNodeType, Canonicalizable { +public class BailoutNode extends MacroNode implements Canonicalizable { public BailoutNode(Invoke invoke) { super(invoke); diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/LoadIndexedFinalNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/LoadIndexedFinalNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -0,0 +1,86 @@ +/* + * 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.truffle.nodes; + +import java.lang.reflect.*; + +import sun.misc.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.java.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; + +/** + * @see LoadIndexedNode + */ +public final class LoadIndexedFinalNode extends AccessIndexedNode implements Canonicalizable { + + /** + * Creates a new {@link LoadIndexedFinalNode}. + * + * @param array the instruction producing the array + * @param index the instruction producing the index + * @param elementKind the element type + */ + public LoadIndexedFinalNode(ValueNode array, ValueNode index, Kind elementKind) { + super(createStamp(array, elementKind), array, index, elementKind); + } + + @Override + public ValueNode canonical(CanonicalizerTool tool) { + if (array().isConstant() && !array().isNullConstant() && index().isConstant()) { + Object array = array().asConstant().asObject(); + long index = index().asConstant().asLong(); + if (index >= 0 && index < Array.getLength(array)) { + int arrayBaseOffset = Unsafe.getUnsafe().arrayBaseOffset(array.getClass()); + int arrayIndexScale = Unsafe.getUnsafe().arrayIndexScale(array.getClass()); + Constant constant = tool.runtime().readUnsafeConstant(elementKind(), array, arrayBaseOffset + index * arrayIndexScale, elementKind() == Kind.Object); + return ConstantNode.forConstant(constant, tool.runtime(), graph()); + } + } + return this; + } + + private static Stamp createStamp(ValueNode array, Kind kind) { + ResolvedJavaType type = ObjectStamp.typeOrNull(array); + if (kind == Kind.Object && type != null) { + return StampFactory.declared(type.getComponentType()); + } else { + return StampFactory.forKind(kind); + } + } + + @Override + public boolean inferStamp() { + return updateStamp(createStamp(array(), elementKind())); + } + + @Override + public void lower(LoweringTool tool) { + LoadIndexedNode loadIndexedNode = graph().add(new LoadIndexedNode(array(), index(), elementKind())); + graph().replaceFixedWithFixed(this, loadIndexedNode); + loadIndexedNode.lower(tool); + } +} diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerAddExactNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerAddExactNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerAddExactNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -77,7 +77,7 @@ } @Override - public void lower(LoweringTool tool, LoweringType loweringType) { + public void lower(LoweringTool tool) { IntegerExactArithmeticSplitNode.lower(tool, this); } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerExactArithmeticNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerExactArithmeticNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerExactArithmeticNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -26,7 +26,7 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; -interface IntegerExactArithmeticNode extends Lowerable, Node.IterableNodeType { +interface IntegerExactArithmeticNode extends Lowerable, IterableNodeType { IntegerExactArithmeticSplitNode createSplit(AbstractBeginNode next, AbstractBeginNode deopt); } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerExactArithmeticSplitNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerExactArithmeticSplitNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerExactArithmeticSplitNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -22,14 +22,12 @@ */ package com.oracle.graal.truffle.nodes.arithmetic; -import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.gen.*; import com.oracle.graal.compiler.target.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.spi.Lowerable.*; import com.oracle.graal.nodes.type.*; public abstract class IntegerExactArithmeticSplitNode extends ControlSplitNode implements LIRGenLowerable { @@ -82,7 +80,7 @@ protected abstract Value generateArithmetic(LIRGeneratorTool generator); static void lower(LoweringTool tool, IntegerExactArithmeticNode node) { - if (tool.getLoweringType() == LoweringType.AFTER_GUARDS) { + if (node.asNode().graph().getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS) { FloatingNode floatingNode = (FloatingNode) node; FixedWithNextNode previous = tool.lastFixedNode(); FixedNode next = previous.next(); diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerMulExactNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerMulExactNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerMulExactNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -73,7 +73,7 @@ } @Override - public void lower(LoweringTool tool, LoweringType loweringType) { + public void lower(LoweringTool tool) { IntegerExactArithmeticSplitNode.lower(tool, this); } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerSubExactNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerSubExactNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerSubExactNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -77,7 +77,7 @@ } @Override - public void lower(LoweringTool tool, LoweringType loweringType) { + public void lower(LoweringTool tool) { IntegerExactArithmeticSplitNode.lower(tool, this); } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/asserts/NeverInlineMacroNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/asserts/NeverInlineMacroNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/asserts/NeverInlineMacroNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -26,16 +26,17 @@ import com.oracle.graal.nodes.spi.*; import com.oracle.graal.replacements.nodes.*; -public class NeverInlineMacroNode extends MacroNode implements com.oracle.graal.graph.Node.IterableNodeType { +public class NeverInlineMacroNode extends MacroNode implements com.oracle.graal.graph.IterableNodeType { public NeverInlineMacroNode(Invoke invoke) { super(invoke); } @Override - public void lower(LoweringTool tool, LoweringType loweringType) { + public void lower(LoweringTool tool) { InvokeNode invoke = createInvoke(); graph().replaceFixedWithFixed(this, invoke); invoke.setUseForInlining(false); + invoke.lower(tool); } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/asserts/NeverPartOfCompilationNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/asserts/NeverPartOfCompilationNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/asserts/NeverPartOfCompilationNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -25,7 +25,7 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.replacements.nodes.*; -public class NeverPartOfCompilationNode extends MacroNode implements com.oracle.graal.graph.Node.IterableNodeType { +public class NeverPartOfCompilationNode extends MacroNode implements com.oracle.graal.graph.IterableNodeType { private final String message; diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/FrameAccessNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/FrameAccessNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/FrameAccessNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -25,7 +25,6 @@ import java.lang.reflect.*; import java.util.*; -import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; @@ -89,7 +88,7 @@ @Override public String toString(Verbosity verbosity) { if (verbosity == Verbosity.Name) { - return super.toString(verbosity) + getSlotKind().name() + (isConstantFrameSlot() ? " " + getConstantFrameSlot() : ""); + return super.toString(verbosity) + getSlotKind().name() + (slot != null && isConstantFrameSlot() ? " " + getConstantFrameSlot() : ""); } else { return super.toString(verbosity); } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/FrameGetNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/FrameGetNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/FrameGetNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -25,7 +25,6 @@ import sun.misc.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.Node.IterableNodeType; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; @@ -71,7 +70,7 @@ } @Override - public void lower(LoweringTool tool, LoweringType loweringType) { + public void lower(LoweringTool tool) { assert !(getFrame() instanceof NewFrameNode); StructuredGraph structuredGraph = graph(); @@ -89,6 +88,8 @@ loadNode = graph().add(new UnsafeLoadNode(loadFieldNode, Unsafe.ARRAY_LONG_BASE_OFFSET, slotOffset, getSlotKind())); } structuredGraph.replaceFixedWithFixed(this, loadNode); + loadFieldNode.lower(tool); + ((Lowerable) loadNode).lower(tool); } @NodeIntrinsic diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/FrameSetNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/FrameSetNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/FrameSetNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -23,7 +23,6 @@ package com.oracle.graal.truffle.nodes.frame; import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.Node.IterableNodeType; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.java.*; @@ -71,7 +70,7 @@ } @Override - public void lower(LoweringTool tool, LoweringType loweringType) { + public void lower(LoweringTool tool) { assert !(getFrame() instanceof NewFrameNode); StructuredGraph structuredGraph = graph(); @@ -87,6 +86,8 @@ storeNode = graph().add(new StoreIndexedNode(loadFieldNode, slotIndex, Kind.Long, value)); } structuredGraph.replaceFixedWithFixed(this, storeNode); + loadFieldNode.lower(tool); + ((Lowerable) storeNode).lower(tool); } @NodeIntrinsic diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/MaterializeFrameNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/MaterializeFrameNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/MaterializeFrameNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -22,7 +22,6 @@ */ package com.oracle.graal.truffle.nodes.frame; -import com.oracle.graal.graph.Node.IterableNodeType; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.truffle.*; diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/NewFrameNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/NewFrameNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/NewFrameNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -27,7 +27,6 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.api.runtime.*; import com.oracle.graal.graph.*; -import com.oracle.graal.graph.Node.IterableNodeType; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; @@ -59,7 +58,7 @@ } public NewFrameNode(ValueNode descriptor, ValueNode caller, ValueNode arguments) { - this(StampFactory.declaredNonNull(FRAME_TYPE), descriptor, caller, arguments); + this(StampFactory.exactNonNull(FRAME_TYPE), descriptor, caller, arguments); } public ValueNode getDescriptor() { diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomTypeCheckNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomTypeCheckNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomTypeCheckNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -26,7 +26,7 @@ import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; -public final class CustomTypeCheckNode extends LogicNode implements Lowerable, Virtualizable, com.oracle.graal.graph.Node.IterableNodeType { +public final class CustomTypeCheckNode extends LogicNode implements Lowerable, Virtualizable, com.oracle.graal.graph.IterableNodeType { @Input private ValueNode condition; @Input private ValueNode object; @@ -50,8 +50,8 @@ return customType; } - public void lower(LoweringTool tool, LoweringType loweringType) { - if (loweringType == LoweringType.BEFORE_GUARDS) { + public void lower(LoweringTool tool) { + if (graph().getGuardsStage() == StructuredGraph.GuardsStage.FLOATING_GUARDS) { this.replaceAtUsages(graph().unique(new IntegerEqualsNode(condition, ConstantNode.forInt(1, graph())))); this.safeDelete(); } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/TypeCastNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/TypeCastNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/TypeCastNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -28,7 +28,7 @@ import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; -public final class TypeCastNode extends FixedWithNextNode implements Lowerable, com.oracle.graal.graph.Node.IterableNodeType, ValueProxy, Virtualizable { +public final class TypeCastNode extends FixedWithNextNode implements Lowerable, com.oracle.graal.graph.IterableNodeType, ValueProxy, Virtualizable { @Input private ValueNode receiver; @Input private ValueNode object; @@ -59,11 +59,11 @@ return customType; } - public void lower(LoweringTool tool, LoweringType loweringType) { - if (loweringType == LoweringType.BEFORE_GUARDS) { - ValueAnchorNode valueAnchorNode = graph().add(new ValueAnchorNode()); - UnsafeCastNode unsafeCast = graph().unique(new UnsafeCastNode(object, this.stamp(), (GuardingNode) valueAnchorNode)); - this.replaceAtUsages(unsafeCast); + public void lower(LoweringTool tool) { + if (graph().getGuardsStage() == StructuredGraph.GuardsStage.FLOATING_GUARDS) { + ValueAnchorNode valueAnchorNode = graph().add(new ValueAnchorNode(null)); + PiNode piCast = graph().unique(new PiNode(object, this.stamp(), valueAnchorNode)); + this.replaceAtUsages(piCast); graph().replaceFixedWithFixed(this, valueAnchorNode); } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/UnsafeCustomizationNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/UnsafeCustomizationNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/UnsafeCustomizationNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -27,7 +27,7 @@ import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; -public final class UnsafeCustomizationNode extends FloatingNode implements LIRLowerable, com.oracle.graal.graph.Node.IterableNodeType { +public final class UnsafeCustomizationNode extends FloatingNode implements LIRLowerable, com.oracle.graal.graph.IterableNodeType { @Input private ValueNode receiver; private final Object customType; diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/phases/InlineTrivialGettersPhase.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/phases/InlineTrivialGettersPhase.java Fri Sep 06 21:37:50 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,76 +0,0 @@ -/* - * 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.truffle.phases; - -import static com.oracle.graal.phases.GraalOptions.*; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.debug.*; -import com.oracle.graal.java.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.java.*; -import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind; -import com.oracle.graal.phases.*; -import com.oracle.graal.phases.common.*; -import com.oracle.graal.phases.common.CanonicalizerPhase.CustomCanonicalizer; -import com.oracle.graal.truffle.*; - -/** - * Inline all trivial getters (i.e. simple field loads). - */ -public class InlineTrivialGettersPhase extends Phase { - - private static final int TRIVIAL_GETTER_SIZE = 5; - private final MetaAccessProvider metaAccessProvider; - private final Assumptions assumptions; - private final CustomCanonicalizer customCanonicalizer; - - public InlineTrivialGettersPhase(MetaAccessProvider metaAccessProvider, Assumptions assumptions, CustomCanonicalizer customCanonicalizer) { - this.metaAccessProvider = metaAccessProvider; - this.assumptions = assumptions; - this.customCanonicalizer = customCanonicalizer; - } - - @Override - protected void run(StructuredGraph graph) { - for (MethodCallTargetNode methodCallTarget : graph.getNodes(MethodCallTargetNode.class)) { - if (methodCallTarget.isAlive()) { - InvokeKind invokeKind = methodCallTarget.invokeKind(); - if (invokeKind == InvokeKind.Special) { - ResolvedJavaMethod targetMethod = methodCallTarget.targetMethod(); - if (methodCallTarget.receiver().isConstant() && !methodCallTarget.receiver().isNullConstant()) { - if (targetMethod.getCodeSize() == TRIVIAL_GETTER_SIZE && targetMethod.getDeclaringClass().isInitialized() && targetMethod.getName().startsWith("get")) { - StructuredGraph inlineGraph = new StructuredGraph(targetMethod); - new GraphBuilderPhase(metaAccessProvider, GraphBuilderConfiguration.getDefault(), TruffleCompilerImpl.Optimizations).apply(inlineGraph); - int mark = graph.getMark(); - InliningUtil.inline(methodCallTarget.invoke(), inlineGraph, false); - Debug.dump(graph, "After inlining trivial getter %s", targetMethod.toString()); - new CanonicalizerPhase.Instance(metaAccessProvider, assumptions, !AOTCompilation.getValue(), mark, customCanonicalizer).apply(graph); - } - } - } - } - } - } -} diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/phases/ReplaceLoadFinalPhase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/phases/ReplaceLoadFinalPhase.java Wed Oct 02 13:26:31 2013 +0200 @@ -0,0 +1,55 @@ +/* + * 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.truffle.phases; + +import java.lang.reflect.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.java.*; +import com.oracle.graal.phases.*; +import com.oracle.graal.truffle.nodes.*; +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.nodes.Node.Children; + +public class ReplaceLoadFinalPhase extends Phase { + + @Override + protected void run(StructuredGraph graph) { + for (LoadIndexedNode loadIndexedNode : graph.getNodes(LoadIndexedNode.class)) { + if (loadIndexedNode.array() instanceof LoadFieldNode) { + LoadFieldNode loadFieldNode = (LoadFieldNode) loadIndexedNode.array(); + if (!loadFieldNode.isStatic() && isCompilationFinal(loadFieldNode.field())) { + graph.replaceFixedWithFixed(loadIndexedNode, graph.add(new LoadIndexedFinalNode(loadIndexedNode.array(), loadIndexedNode.index(), loadIndexedNode.elementKind()))); + } + } else if (loadIndexedNode.array() instanceof ConstantNode) { + graph.replaceFixedWithFixed(loadIndexedNode, graph.add(new LoadIndexedFinalNode(loadIndexedNode.array(), loadIndexedNode.index(), loadIndexedNode.elementKind()))); + } + } + } + + private static boolean isCompilationFinal(ResolvedJavaField field) { + assert (field.getAnnotation(Children.class) == null && field.getAnnotation(CompilerDirectives.CompilationFinal.class) == null) || Modifier.isFinal(field.getModifiers()) : "field needs to be declared as final"; + return Modifier.isFinal(field.getModifiers()) && (field.getAnnotation(Children.class) != null || field.getAnnotation(CompilerDirectives.CompilationFinal.class) != null); + } +} diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/phases/VerifyNoIntrinsicsLeftPhase.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/phases/VerifyNoIntrinsicsLeftPhase.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/phases/VerifyNoIntrinsicsLeftPhase.java Wed Oct 02 13:26:31 2013 +0200 @@ -23,7 +23,6 @@ package com.oracle.graal.truffle.phases; import com.oracle.graal.graph.*; -import com.oracle.graal.graph.Node.IterableNodeType; import com.oracle.graal.nodes.*; import com.oracle.graal.phases.*; import com.oracle.graal.truffle.*; diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/CompilerDirectivesSubstitutions.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/CompilerDirectivesSubstitutions.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/CompilerDirectivesSubstitutions.java Wed Oct 02 13:26:31 2013 +0200 @@ -24,7 +24,6 @@ import java.util.concurrent.*; -import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.api.replacements.*; import com.oracle.graal.nodes.*; diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/FrameWithoutBoxingSubstitutions.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/FrameWithoutBoxingSubstitutions.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/FrameWithoutBoxingSubstitutions.java Wed Oct 02 13:26:31 2013 +0200 @@ -22,7 +22,6 @@ */ package com.oracle.graal.truffle.substitutions; -import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.api.replacements.*; import com.oracle.graal.api.runtime.*; @@ -214,7 +213,8 @@ } private static void verifyGet(FrameWithoutBoxing frame, FrameSlot slot, FrameSlotKind accessType) { - if (getTag(frame, slot) != (byte) accessType.ordinal()) { + byte tag = getTag(frame, slot); + if (accessType == FrameSlotKind.Object ? (tag & 0xfe) != 0 : tag != (byte) accessType.ordinal()) { DeoptimizeNode.deopt(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.UnreachedCode); } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/OptimizedCallTargetSubstitutions.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/OptimizedCallTargetSubstitutions.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/OptimizedCallTargetSubstitutions.java Wed Oct 02 13:26:31 2013 +0200 @@ -34,6 +34,9 @@ public class OptimizedCallTargetSubstitutions { @MacroSubstitution(macro = NeverInlineMacroNode.class, isStatic = false) + public static native Object callHelper(OptimizedCallTarget target, PackedFrame caller, Arguments args); + + @MacroSubstitution(macro = NeverInlineMacroNode.class, isStatic = false) public static native Object interpreterCall(OptimizedCallTarget target, PackedFrame caller, Arguments args); @MacroSubstitution(macro = NeverInlineMacroNode.class, isStatic = false) diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/SlowPathExceptionSubstitutions.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/SlowPathExceptionSubstitutions.java Fri Sep 06 21:37:50 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,59 +0,0 @@ -/* - * 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.truffle.substitutions; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.api.replacements.*; -import com.oracle.graal.nodes.*; -import com.oracle.truffle.api.nodes.*; - -/** - * Deoptimize on creation of a new SlowPathException instance. - */ -@ClassSubstitution(SlowPathException.class) -public class SlowPathExceptionSubstitutions { - - @MethodSubstitution(value = "") - public static void init() { - DeoptimizeNode.deopt(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.UnreachedCode); - } - - @SuppressWarnings("unused") - @MethodSubstitution(value = "") - public static void init(String result, Throwable cause) { - DeoptimizeNode.deopt(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.UnreachedCode); - } - - @SuppressWarnings("unused") - @MethodSubstitution(value = "") - public static void init(String result) { - DeoptimizeNode.deopt(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.UnreachedCode); - } - - @SuppressWarnings("unused") - @MethodSubstitution(value = "") - public static void init(Throwable cause) { - DeoptimizeNode.deopt(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.UnreachedCode); - } -} diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/UnexpectedResultExceptionSubstitutions.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/UnexpectedResultExceptionSubstitutions.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/UnexpectedResultExceptionSubstitutions.java Wed Oct 02 13:26:31 2013 +0200 @@ -22,7 +22,6 @@ */ package com.oracle.graal.truffle.substitutions; -import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.api.replacements.*; import com.oracle.graal.nodes.*; diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/nodes/MaterializedObjectState.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/nodes/MaterializedObjectState.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/nodes/MaterializedObjectState.java Wed Oct 02 13:26:31 2013 +0200 @@ -29,7 +29,7 @@ /** * This class encapsulated the materialized state of an escape analyzed object. */ -public final class MaterializedObjectState extends EscapeObjectState implements Node.IterableNodeType, Node.ValueNumberable { +public final class MaterializedObjectState extends EscapeObjectState implements IterableNodeType, Node.ValueNumberable { @Input private ValueNode materializedValue; @@ -44,7 +44,7 @@ @Override public MaterializedObjectState duplicateWithVirtualState() { - return graph().add(new MaterializedObjectState(object(), materializedValue)); + return graph().addWithoutUnique(new MaterializedObjectState(object(), materializedValue)); } @Override diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/nodes/VirtualObjectState.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/nodes/VirtualObjectState.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/nodes/VirtualObjectState.java Wed Oct 02 13:26:31 2013 +0200 @@ -31,7 +31,7 @@ /** * This class encapsulated the virtual state of an escape analyzed object. */ -public final class VirtualObjectState extends EscapeObjectState implements Node.IterableNodeType, Node.ValueNumberable { +public final class VirtualObjectState extends EscapeObjectState implements IterableNodeType, Node.ValueNumberable { @Input private final NodeInputList fieldValues; @@ -53,7 +53,7 @@ @Override public VirtualObjectState duplicateWithVirtualState() { - return graph().add(new VirtualObjectState(object(), fieldValues)); + return graph().addWithoutUnique(new VirtualObjectState(object(), fieldValues)); } @Override diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EarlyReadEliminationPhase.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EarlyReadEliminationPhase.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EarlyReadEliminationPhase.java Wed Oct 02 13:26:31 2013 +0200 @@ -25,13 +25,14 @@ import static com.oracle.graal.phases.GraalOptions.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.schedule.*; import com.oracle.graal.phases.tiers.*; public class EarlyReadEliminationPhase extends EffectsPhase { - public EarlyReadEliminationPhase() { - super(1); + public EarlyReadEliminationPhase(CanonicalizerPhase canonicalizer) { + super(1, canonicalizer); } @Override diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsPhase.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsPhase.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsPhase.java Wed Oct 02 13:26:31 2013 +0200 @@ -22,8 +22,6 @@ */ package com.oracle.graal.virtual.phases.ea; -import static com.oracle.graal.phases.GraalOptions.*; - import java.util.concurrent.*; import com.oracle.graal.debug.*; @@ -47,9 +45,11 @@ } private final int maxIterations; + private final CanonicalizerPhase canonicalizer; - public EffectsPhase(int maxIterations) { + public EffectsPhase(int maxIterations, CanonicalizerPhase canonicalizer) { this.maxIterations = maxIterations; + this.canonicalizer = canonicalizer; } @Override @@ -90,7 +90,7 @@ listener.getChangedNodes().add(node); } } - new CanonicalizerPhase.Instance(context.getRuntime(), context.getAssumptions(), !AOTCompilation.getValue(), listener.getChangedNodes(), null).apply(graph); + canonicalizer.applyIncremental(graph, context, listener.getChangedNodes()); return true; } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/GraphEffectList.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/GraphEffectList.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/GraphEffectList.java Wed Oct 02 13:26:31 2013 +0200 @@ -113,7 +113,7 @@ @Override public void apply(StructuredGraph graph, ArrayList obsoleteNodes) { assert !node.isAlive() && !node.isDeleted() : node + " " + cause; - graph.add(node); + graph.addWithoutUnique(node); } }); } @@ -187,7 +187,7 @@ stateAfter.virtualObjectMappings().remove(i); } } - stateAfter.addVirtualObjectMapping(graph.add(state)); + stateAfter.addVirtualObjectMapping(graph.addWithoutUnique(state)); } @Override @@ -328,7 +328,7 @@ @Override public void apply(StructuredGraph graph, ArrayList obsoleteNodes) { for (ValueNode otherAllocation : otherAllocations) { - graph.add(otherAllocation); + graph.addWithoutUnique(otherAllocation); if (otherAllocation instanceof FixedWithNextNode) { graph.addBeforeFixed(position, (FixedWithNextNode) otherAllocation); } else { @@ -344,7 +344,7 @@ graph.addBeforeFixed(position, commit); } for (AllocatedObjectNode obj : objects) { - graph.add(obj); + graph.addWithoutUnique(obj); commit.getVirtualObjects().add(obj.getVirtualObject()); obj.setCommit(commit); } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/IterativeInliningPhase.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/IterativeInliningPhase.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/IterativeInliningPhase.java Wed Oct 02 13:26:31 2013 +0200 @@ -60,13 +60,13 @@ @Override public Boolean call() { boolean progress = false; - PartialEscapePhase ea = new PartialEscapePhase(false); + PartialEscapePhase ea = new PartialEscapePhase(false, canonicalizer); boolean eaResult = ea.runAnalysis(graph, context); progress |= eaResult; Map hints = PEAInliningHints.getValue() ? PartialEscapePhase.getHints(graph) : null; - InliningPhase inlining = new InliningPhase(hints); + InliningPhase inlining = new InliningPhase(hints, new CanonicalizerPhase(true)); inlining.setMaxMethodsPerInlining(simple ? 1 : Integer.MAX_VALUE); inlining.apply(graph, context); progress |= inlining.getInliningCount() > 0; @@ -75,7 +75,7 @@ if (ConditionalElimination.getValue() && OptCanonicalizer.getValue()) { canonicalizer.apply(graph, context); - new IterativeConditionalEliminationPhase().apply(graph, context); + new IterativeConditionalEliminationPhase(canonicalizer).apply(graph, context); } return progress; diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java Wed Oct 02 13:26:31 2013 +0200 @@ -111,13 +111,18 @@ return !(node instanceof CommitAllocationNode || node instanceof AllocatedObjectNode); } if (isMarked) { - if (node instanceof StateSplit) { - StateSplit split = (StateSplit) node; - FrameState stateAfter = split.stateAfter(); + if (node instanceof NodeWithState) { + NodeWithState nodeWithState = (NodeWithState) node; + FrameState stateAfter = nodeWithState.getState(); if (stateAfter != null) { if (stateAfter.usages().count() > 1) { - stateAfter = (FrameState) stateAfter.copyWithInputs(); - split.setStateAfter(stateAfter); + if (nodeWithState instanceof StateSplit) { + StateSplit split = (StateSplit) nodeWithState; + stateAfter = (FrameState) stateAfter.copyWithInputs(); + split.setStateAfter(stateAfter); + } else { + throw GraalInternalError.shouldNotReachHere(); + } } final HashSet virtual = new HashSet<>(); stateAfter.applyToNonVirtual(new NodeClosure() { diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapePhase.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapePhase.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapePhase.java Wed Oct 02 13:26:31 2013 +0200 @@ -23,6 +23,7 @@ package com.oracle.graal.virtual.phases.ea; import static com.oracle.graal.phases.GraalOptions.*; +import static com.oracle.graal.virtual.phases.ea.PartialEscapePhase.Options.*; import java.util.*; @@ -33,25 +34,29 @@ import com.oracle.graal.nodes.util.*; import com.oracle.graal.nodes.virtual.*; import com.oracle.graal.options.*; +import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.graph.*; import com.oracle.graal.phases.schedule.*; import com.oracle.graal.phases.tiers.*; public class PartialEscapePhase extends EffectsPhase { - //@formatter:off - @Option(help = "") - public static final OptionValue OptEarlyReadElimination = new OptionValue<>(true); - //@formatter:on + static class Options { + + //@formatter:off + @Option(help = "") + public static final OptionValue OptEarlyReadElimination = new OptionValue<>(true); + //@formatter:on + } private final boolean readElimination; - public PartialEscapePhase(boolean iterative) { - this(iterative, OptEarlyReadElimination.getValue()); + public PartialEscapePhase(boolean iterative, CanonicalizerPhase canonicalizer) { + this(iterative, OptEarlyReadElimination.getValue(), canonicalizer); } - public PartialEscapePhase(boolean iterative, boolean readElimination) { - super(iterative ? EscapeAnalysisIterations.getValue() : 1); + public PartialEscapePhase(boolean iterative, boolean readElimination, CanonicalizerPhase canonicalizer) { + super(iterative ? EscapeAnalysisIterations.getValue() : 1, canonicalizer); this.readElimination = readElimination; } @@ -76,7 +81,7 @@ public static Map getHints(StructuredGraph graph) { NodesToDoubles probabilities = new ComputeProbabilityClosure(graph).apply(); Map hints = null; - for (CommitAllocationNode commit : graph.getNodes(CommitAllocationNode.class)) { + for (CommitAllocationNode commit : graph.getNodes().filter(CommitAllocationNode.class)) { double sum = 0; double invokeSum = 0; for (Node commitUsage : commit.usages()) { diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.word/src/com/oracle/graal/word/ObjectAccess.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/ObjectAccess.java Wed Oct 02 13:26:31 2013 +0200 @@ -0,0 +1,936 @@ +/* + * Copyright (c) 2013, 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.word; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.word.Word.Opcode; +import com.oracle.graal.word.Word.Operation; + +/** + * Low-level memory access for Objects. Similarly to the readXxx and writeXxx methods defined for + * {@link Pointer}, these methods access the raw memory without any null checks, read- or write + * barriers. + */ +public final class ObjectAccess { + + /** + * Reads the memory at address {@code (object + offset)}. The offset is in bytes. + *

+ * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the read (see {@link LocationNode}) + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ) + public static native byte readByte(Object object, WordBase offset, LocationIdentity locationIdentity); + + /** + * Reads the memory at address {@code (object + offset)}. The offset is in bytes. + *

+ * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the read (see {@link LocationNode}) + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ) + public static native char readChar(Object object, WordBase offset, LocationIdentity locationIdentity); + + /** + * Reads the memory at address {@code (object + offset)}. The offset is in bytes. + *

+ * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the read (see {@link LocationNode}) + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ) + public static native short readShort(Object object, WordBase offset, LocationIdentity locationIdentity); + + /** + * Reads the memory at address {@code (object + offset)}. The offset is in bytes. + *

+ * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the read (see {@link LocationNode}) + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ) + public static native int readInt(Object object, WordBase offset, LocationIdentity locationIdentity); + + /** + * Reads the memory at address {@code (object + offset)}. The offset is in bytes. + *

+ * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the read (see {@link LocationNode}) + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ) + public static native long readLong(Object object, WordBase offset, LocationIdentity locationIdentity); + + /** + * Reads the memory at address {@code (object + offset)}. The offset is in bytes. + *

+ * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the read (see {@link LocationNode}) + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ) + public static native float readFloat(Object object, WordBase offset, LocationIdentity locationIdentity); + + /** + * Reads the memory at address {@code (object + offset)}. The offset is in bytes. + *

+ * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the read (see {@link LocationNode}) + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ) + public static native double readDouble(Object object, WordBase offset, LocationIdentity locationIdentity); + + /** + * Reads the memory at address {@code (object + offset)}. The offset is in bytes. + *

+ * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the read (see {@link LocationNode}) + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ) + public static native Word readWord(Object object, WordBase offset, LocationIdentity locationIdentity); + + /** + * Reads the memory at address {@code (object + offset)}. The offset is in bytes. + *

+ * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the read (see {@link LocationNode}) + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ) + public static native Object readObject(Object object, WordBase offset, LocationIdentity locationIdentity); + + /** + * Reads the memory at address {@code (object + offset)}. The offset is in bytes. + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the read (see {@link LocationNode}) + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ) + public static native byte readByte(Object object, int offset, LocationIdentity locationIdentity); + + /** + * Reads the memory at address {@code (object + offset)}. The offset is in bytes. + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the read (see {@link LocationNode}) + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ) + public static native char readChar(Object object, int offset, LocationIdentity locationIdentity); + + /** + * Reads the memory at address {@code (object + offset)}. The offset is in bytes. + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the read (see {@link LocationNode}) + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ) + public static native short readShort(Object object, int offset, LocationIdentity locationIdentity); + + /** + * Reads the memory at address {@code (object + offset)}. The offset is in bytes. + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the read (see {@link LocationNode}) + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ) + public static native int readInt(Object object, int offset, LocationIdentity locationIdentity); + + /** + * Reads the memory at address {@code (object + offset)}. The offset is in bytes. + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the read (see {@link LocationNode}) + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ) + public static native long readLong(Object object, int offset, LocationIdentity locationIdentity); + + /** + * Reads the memory at address {@code (object + offset)}. The offset is in bytes. + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the read (see {@link LocationNode}) + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ) + public static native float readFloat(Object object, int offset, LocationIdentity locationIdentity); + + /** + * Reads the memory at address {@code (object + offset)}. The offset is in bytes. + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the read (see {@link LocationNode}) + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ) + public static native double readDouble(Object object, int offset, LocationIdentity locationIdentity); + + /** + * Reads the memory at address {@code (object + offset)}. The offset is in bytes. + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the read (see {@link LocationNode}) + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ) + public static native Word readWord(Object object, int offset, LocationIdentity locationIdentity); + + /** + * Reads the memory at address {@code (object + offset)}. The offset is in bytes. + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the read (see {@link LocationNode}) + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ) + public static native Object readObject(Object object, int offset, LocationIdentity locationIdentity); + + /** + * Writes the memory at address {@code (object + offset)}. The offset is in bytes. + *

+ * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the write (see {@link LocationNode}) + * @param val the value to be written to memory + */ + @Operation(opcode = Opcode.WRITE) + public static native void writeByte(Object object, WordBase offset, byte val, LocationIdentity locationIdentity); + + /** + * Writes the memory at address {@code (object + offset)}. The offset is in bytes. + *

+ * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the write (see {@link LocationNode}) + * @param val the value to be written to memory + */ + @Operation(opcode = Opcode.WRITE) + public static native void writeChar(Object object, WordBase offset, char val, LocationIdentity locationIdentity); + + /** + * Writes the memory at address {@code (object + offset)}. The offset is in bytes. + *

+ * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the write (see {@link LocationNode}) + * @param val the value to be written to memory + */ + @Operation(opcode = Opcode.WRITE) + public static native void writeShort(Object object, WordBase offset, short val, LocationIdentity locationIdentity); + + /** + * Writes the memory at address {@code (object + offset)}. The offset is in bytes. + *

+ * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the write (see {@link LocationNode}) + * @param val the value to be written to memory + */ + @Operation(opcode = Opcode.WRITE) + public static native void writeInt(Object object, WordBase offset, int val, LocationIdentity locationIdentity); + + /** + * Writes the memory at address {@code (object + offset)}. The offset is in bytes. + *

+ * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the write (see {@link LocationNode}) + * @param val the value to be written to memory + */ + @Operation(opcode = Opcode.WRITE) + public static native void writeLong(Object object, WordBase offset, long val, LocationIdentity locationIdentity); + + /** + * Writes the memory at address {@code (object + offset)}. The offset is in bytes. + *

+ * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the write (see {@link LocationNode}) + * @param val the value to be written to memory + */ + @Operation(opcode = Opcode.WRITE) + public static native void writeFloat(Object object, WordBase offset, float val, LocationIdentity locationIdentity); + + /** + * Writes the memory at address {@code (object + offset)}. The offset is in bytes. + *

+ * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the write (see {@link LocationNode}) + * @param val the value to be written to memory + */ + @Operation(opcode = Opcode.WRITE) + public static native void writeDouble(Object object, WordBase offset, double val, LocationIdentity locationIdentity); + + /** + * Writes the memory at address {@code (object + offset)}. The offset is in bytes. + *

+ * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the write (see {@link LocationNode}) + * @param val the value to be written to memory + */ + @Operation(opcode = Opcode.WRITE) + public static native void writeWord(Object object, WordBase offset, WordBase val, LocationIdentity locationIdentity); + + /** + * Writes the memory at address {@code (object + offset)}. The offset is in bytes. + *

+ * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the write (see {@link LocationNode}) + * @param val the value to be written to memory + */ + @Operation(opcode = Opcode.WRITE) + public static native void writeObject(Object object, WordBase offset, Object val, LocationIdentity locationIdentity); + + /** + * Writes the memory at address {@code (object + offset)}. The offset is in bytes. + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the write (see {@link LocationNode}) + * @param val the value to be written to memory + */ + @Operation(opcode = Opcode.WRITE) + public static native void writeByte(Object object, int offset, byte val, LocationIdentity locationIdentity); + + /** + * Writes the memory at address {@code (object + offset)}. The offset is in bytes. + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the write (see {@link LocationNode}) + * @param val the value to be written to memory + */ + @Operation(opcode = Opcode.WRITE) + public static native void writeChar(Object object, int offset, char val, LocationIdentity locationIdentity); + + /** + * Writes the memory at address {@code (object + offset)}. The offset is in bytes. + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the write (see {@link LocationNode}) + * @param val the value to be written to memory + */ + @Operation(opcode = Opcode.WRITE) + public static native void writeShort(Object object, int offset, short val, LocationIdentity locationIdentity); + + /** + * Writes the memory at address {@code (object + offset)}. The offset is in bytes. + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the write (see {@link LocationNode}) + * @param val the value to be written to memory + */ + @Operation(opcode = Opcode.WRITE) + public static native void writeInt(Object object, int offset, int val, LocationIdentity locationIdentity); + + /** + * Writes the memory at address {@code (object + offset)}. The offset is in bytes. + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the write (see {@link LocationNode}) + * @param val the value to be written to memory + */ + @Operation(opcode = Opcode.WRITE) + public static native void writeLong(Object object, int offset, long val, LocationIdentity locationIdentity); + + /** + * Writes the memory at address {@code (object + offset)}. The offset is in bytes. + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the write (see {@link LocationNode}) + * @param val the value to be written to memory + */ + @Operation(opcode = Opcode.WRITE) + public static native void writeFloat(Object object, int offset, float val, LocationIdentity locationIdentity); + + /** + * Writes the memory at address {@code (object + offset)}. The offset is in bytes. + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the write (see {@link LocationNode}) + * @param val the value to be written to memory + */ + @Operation(opcode = Opcode.WRITE) + public static native void writeDouble(Object object, int offset, double val, LocationIdentity locationIdentity); + + /** + * Writes the memory at address {@code (object + offset)}. The offset is in bytes. + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the write (see {@link LocationNode}) + * @param val the value to be written to memory + */ + @Operation(opcode = Opcode.WRITE) + public static native void writeWord(Object object, int offset, WordBase val, LocationIdentity locationIdentity); + + /** + * Writes the memory at address {@code (object + offset)}. The offset is in bytes. + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param locationIdentity the identity of the write (see {@link LocationNode}) + * @param val the value to be written to memory + */ + @Operation(opcode = Opcode.WRITE) + public static native void writeObject(Object object, int offset, Object val, LocationIdentity locationIdentity); + + /** + * Reads the memory at address {@code (object + offset)}. The offset is in bytes. + *

+ * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ) + public static native byte readByte(Object object, WordBase offset); + + /** + * Reads the memory at address {@code (object + offset)}. The offset is in bytes. + *

+ * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ) + public static native char readChar(Object object, WordBase offset); + + /** + * Reads the memory at address {@code (object + offset)}. The offset is in bytes. + *

+ * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ) + public static native short readShort(Object object, WordBase offset); + + /** + * Reads the memory at address {@code (object + offset)}. The offset is in bytes. + *

+ * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ) + public static native int readInt(Object object, WordBase offset); + + /** + * Reads the memory at address {@code (object + offset)}. The offset is in bytes. + *

+ * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ) + public static native long readLong(Object object, WordBase offset); + + /** + * Reads the memory at address {@code (object + offset)}. The offset is in bytes. + *

+ * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ) + public static native float readFloat(Object object, WordBase offset); + + /** + * Reads the memory at address {@code (object + offset)}. The offset is in bytes. + *

+ * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ) + public static native double readDouble(Object object, WordBase offset); + + /** + * Reads the memory at address {@code (object + offset)}. The offset is in bytes. + *

+ * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ) + public static native Word readWord(Object object, WordBase offset); + + /** + * Reads the memory at address {@code (object + offset)}. The offset is in bytes. + *

+ * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ) + public static native Object readObject(Object object, WordBase offset); + + /** + * Reads the memory at address {@code (object + offset)}. The offset is in bytes. + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ) + public static native byte readByte(Object object, int offset); + + /** + * Reads the memory at address {@code (object + offset)}. The offset is in bytes. + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ) + public static native char readChar(Object object, int offset); + + /** + * Reads the memory at address {@code (object + offset)}. The offset is in bytes. + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ) + public static native short readShort(Object object, int offset); + + /** + * Reads the memory at address {@code (object + offset)}. The offset is in bytes. + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ) + public static native int readInt(Object object, int offset); + + /** + * Reads the memory at address {@code (object + offset)}. The offset is in bytes. + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ) + public static native long readLong(Object object, int offset); + + /** + * Reads the memory at address {@code (object + offset)}. The offset is in bytes. + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ) + public static native float readFloat(Object object, int offset); + + /** + * Reads the memory at address {@code (object + offset)}. The offset is in bytes. + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ) + public static native double readDouble(Object object, int offset); + + /** + * Reads the memory at address {@code (object + offset)}. The offset is in bytes. + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ) + public static native Word readWord(Object object, int offset); + + /** + * Reads the memory at address {@code (object + offset)}. The offset is in bytes. + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @return the result of the memory access + */ + @Operation(opcode = Opcode.READ) + public static native Object readObject(Object object, int offset); + + /** + * Writes the memory at address {@code (object + offset)}. The offset is in bytes. + *

+ * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param val the value to be written to memory + */ + @Operation(opcode = Opcode.WRITE) + public static native void writeByte(Object object, WordBase offset, byte val); + + /** + * Writes the memory at address {@code (object + offset)}. The offset is in bytes. + *

+ * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param val the value to be written to memory + */ + @Operation(opcode = Opcode.WRITE) + public static native void writeChar(Object object, WordBase offset, char val); + + /** + * Writes the memory at address {@code (object + offset)}. The offset is in bytes. + *

+ * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param val the value to be written to memory + */ + @Operation(opcode = Opcode.WRITE) + public static native void writeShort(Object object, WordBase offset, short val); + + /** + * Writes the memory at address {@code (object + offset)}. The offset is in bytes. + *

+ * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param val the value to be written to memory + */ + @Operation(opcode = Opcode.WRITE) + public static native void writeInt(Object object, WordBase offset, int val); + + /** + * Writes the memory at address {@code (object + offset)}. The offset is in bytes. + *

+ * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param val the value to be written to memory + */ + @Operation(opcode = Opcode.WRITE) + public static native void writeLong(Object object, WordBase offset, long val); + + /** + * Writes the memory at address {@code (object + offset)}. The offset is in bytes. + *

+ * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param val the value to be written to memory + */ + @Operation(opcode = Opcode.WRITE) + public static native void writeFloat(Object object, WordBase offset, float val); + + /** + * Writes the memory at address {@code (object + offset)}. The offset is in bytes. + *

+ * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param val the value to be written to memory + */ + @Operation(opcode = Opcode.WRITE) + public static native void writeDouble(Object object, WordBase offset, double val); + + /** + * Writes the memory at address {@code (object + offset)}. The offset is in bytes. + *

+ * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param val the value to be written to memory + */ + @Operation(opcode = Opcode.WRITE) + public static native void writeWord(Object object, WordBase offset, WordBase val); + + /** + * Writes the memory at address {@code (object + offset)}. The offset is in bytes. + *

+ * The offset is always treated as a {@link Signed} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller + * knows that the highest-order bit of the unsigned value is never used). + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param val the value to be written to memory + */ + @Operation(opcode = Opcode.WRITE) + public static native void writeObject(Object object, WordBase offset, Object val); + + /** + * Writes the memory at address {@code (object + offset)}. The offset is in bytes. + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param val the value to be written to memory + */ + @Operation(opcode = Opcode.WRITE) + public static native void writeByte(Object object, int offset, byte val); + + /** + * Writes the memory at address {@code (object + offset)}. The offset is in bytes. + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param val the value to be written to memory + */ + @Operation(opcode = Opcode.WRITE) + public static native void writeChar(Object object, int offset, char val); + + /** + * Writes the memory at address {@code (object + offset)}. The offset is in bytes. + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param val the value to be written to memory + */ + @Operation(opcode = Opcode.WRITE) + public static native void writeShort(Object object, int offset, short val); + + /** + * Writes the memory at address {@code (object + offset)}. The offset is in bytes. + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param val the value to be written to memory + */ + @Operation(opcode = Opcode.WRITE) + public static native void writeInt(Object object, int offset, int val); + + /** + * Writes the memory at address {@code (object + offset)}. The offset is in bytes. + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param val the value to be written to memory + */ + @Operation(opcode = Opcode.WRITE) + public static native void writeLong(Object object, int offset, long val); + + /** + * Writes the memory at address {@code (object + offset)}. The offset is in bytes. + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param val the value to be written to memory + */ + @Operation(opcode = Opcode.WRITE) + public static native void writeFloat(Object object, int offset, float val); + + /** + * Writes the memory at address {@code (object + offset)}. The offset is in bytes. + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param val the value to be written to memory + */ + @Operation(opcode = Opcode.WRITE) + public static native void writeDouble(Object object, int offset, double val); + + /** + * Writes the memory at address {@code (object + offset)}. The offset is in bytes. + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param val the value to be written to memory + */ + @Operation(opcode = Opcode.WRITE) + public static native void writeWord(Object object, int offset, WordBase val); + + /** + * Writes the memory at address {@code (object + offset)}. The offset is in bytes. + * + * @param object the base object for the memory access + * @param offset the signed offset for the memory access + * @param val the value to be written to memory + */ + @Operation(opcode = Opcode.WRITE) + public static native void writeObject(Object object, int offset, Object val); +} diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.word/src/com/oracle/graal/word/nodes/WordCastNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/nodes/WordCastNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2013, 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.word.nodes; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; +import com.oracle.graal.word.phases.*; + +/** + * Cast between Word and Object that is introduced by the {@link WordTypeRewriterPhase}. It has an + * impact on the pointer maps for the GC, so it must not be scheduled or optimized away. + */ +public final class WordCastNode extends FixedWithNextNode implements LIRLowerable, Canonicalizable { + + public static WordCastNode wordToObject(ValueNode input, Kind wordKind) { + assert input.kind() == wordKind; + return new WordCastNode(StampFactory.object(), input); + } + + public static WordCastNode objectToWord(ValueNode input, Kind wordKind) { + assert input.kind() == Kind.Object; + return new WordCastNode(StampFactory.forKind(wordKind), input); + } + + @Input private ValueNode input; + + private WordCastNode(Stamp stamp, ValueNode input) { + super(stamp); + this.input = input; + } + + public ValueNode getInput() { + return input; + } + + public ValueNode canonical(CanonicalizerTool tool) { + if (usages().count() == 0) { + /* If the cast is unused, it can be eliminated. */ + return input; + } + return this; + } + + @Override + public void generate(LIRGeneratorTool generator) { + assert kind() != input.kind(); + assert generator.target().arch.getSizeInBytes(kind()) == generator.target().arch.getSizeInBytes(input.kind()); + + AllocatableValue result = generator.newVariable(kind()); + generator.emitMove(result, generator.operand(input)); + generator.setResult(this, result); + } +} diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java --- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java Wed Oct 02 13:26:31 2013 +0200 @@ -36,10 +36,10 @@ import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.util.*; import com.oracle.graal.phases.*; -import com.oracle.graal.phases.util.*; import com.oracle.graal.word.*; import com.oracle.graal.word.Word.Opcode; import com.oracle.graal.word.Word.Operation; +import com.oracle.graal.word.nodes.*; /** * Transforms all uses of the {@link Word} class into unsigned operations on {@code int} or @@ -47,210 +47,271 @@ */ public class WordTypeRewriterPhase extends Phase { - private final MetaAccessProvider metaAccess; - private final ResolvedJavaType wordBaseType; - private final ResolvedJavaType wordImplType; - private final Kind wordKind; + protected final MetaAccessProvider metaAccess; + protected final ResolvedJavaType wordBaseType; + protected final ResolvedJavaType wordImplType; + protected final ResolvedJavaType objectAccessType; + protected final Kind wordKind; public WordTypeRewriterPhase(MetaAccessProvider metaAccess, Kind wordKind) { this.metaAccess = metaAccess; this.wordKind = wordKind; this.wordBaseType = metaAccess.lookupJavaType(WordBase.class); this.wordImplType = metaAccess.lookupJavaType(Word.class); - } - - public ResolvedJavaType getWordBaseType() { - return wordBaseType; - } - - public ResolvedJavaType getWordImplType() { - return wordImplType; + this.objectAccessType = metaAccess.lookupJavaType(ObjectAccess.class); } @Override protected void run(StructuredGraph graph) { - for (Node n : GraphOrder.forwardGraph(graph)) { - if (n instanceof ValueNode && !(n instanceof PhiNode && ((PhiNode) n).isLoopPhi())) { - ValueNode valueNode = (ValueNode) n; - if (isWord(valueNode)) { - changeToWord(valueNode); - } - } - } - for (PhiNode phi : graph.getNodes(PhiNode.class)) { - if (phi.isLoopPhi() && isWord(phi)) { - changeToWord(phi); - } - } - - // Remove casts between different word types (which by now no longer have kind Object) - for (CheckCastNode checkCastNode : graph.getNodes().filter(CheckCastNode.class).snapshot()) { - if (!checkCastNode.isDeleted() && checkCastNode.kind() == wordKind) { - checkCastNode.replaceAtUsages(checkCastNode.object()); - graph.removeFixed(checkCastNode); - } - } - - // Remove unnecessary/redundant unsafe casts - for (UnsafeCastNode unsafeCastNode : graph.getNodes().filter(UnsafeCastNode.class).snapshot()) { - if (!unsafeCastNode.isDeleted() && unsafeCastNode.object().stamp() == unsafeCastNode.stamp()) { - graph.replaceFloating(unsafeCastNode, unsafeCastNode.object()); - } - } - - // Fold constant field reads (e.g. enum constants) - for (LoadFieldNode load : graph.getNodes(LoadFieldNode.class).snapshot()) { - ConstantNode constant = load.asConstant(metaAccess); - if (constant != null) { - graph.replaceFixedWithFloating(load, constant); - } - } + inferStamps(graph); - // Replace ObjectEqualsNodes with IntegerEqualsNodes where the values being compared are - // words - for (ObjectEqualsNode objectEqualsNode : graph.getNodes().filter(ObjectEqualsNode.class).snapshot()) { - ValueNode x = objectEqualsNode.x(); - ValueNode y = objectEqualsNode.y(); - if (x.kind() == wordKind || y.kind() == wordKind) { - assert x.kind() == wordKind; - assert y.kind() == wordKind; - - // TODO Remove the whole iteration of ObjectEqualsNodes when we are sure that there - // is no more code where this triggers. - throw GraalInternalError.shouldNotReachHere("Comparison of words with == and != is no longer supported"); - } - } - - for (AccessIndexedNode node : graph.getNodes().filter(AccessIndexedNode.class).snapshot()) { - ValueNode array = node.array(); - ResolvedJavaType arrayType = ObjectStamp.typeOrNull(array); - if (arrayType == null) { - // There are cases where the array does not have a known type yet. Assume it is not - // a word type. - continue; - } - assert arrayType.isArray(); - if (isWord(arrayType.getComponentType())) { - /* - * The elementKind of the node is a final field, and other information such as the - * stamp depends on elementKind. Therefore, just create a new node and replace the - * old one. - */ - if (node instanceof LoadIndexedNode) { - graph.replaceFixedWithFixed(node, graph.add(new LoadIndexedNode(node.array(), node.index(), wordKind))); - } else if (node instanceof StoreIndexedNode) { - graph.replaceFixedWithFixed(node, graph.add(new StoreIndexedNode(node.array(), node.index(), wordKind, ((StoreIndexedNode) node).value()))); - } else { - throw GraalInternalError.shouldNotReachHere(); - } + for (Node n : graph.getNodes()) { + if (n instanceof ValueNode) { + changeToWord(graph, (ValueNode) n); } } - for (MethodCallTargetNode callTargetNode : graph.getNodes(MethodCallTargetNode.class).snapshot()) { - ResolvedJavaMethod targetMethod = callTargetNode.targetMethod(); - if (!callTargetNode.isStatic() && (callTargetNode.receiver().kind() == wordKind || isWord(callTargetNode.receiver()))) { - targetMethod = getWordImplType().resolveMethod(targetMethod); - } - Operation operation = targetMethod.getAnnotation(Word.Operation.class); - if (operation != null) { - NodeInputList arguments = callTargetNode.arguments(); - Invoke invoke = (Invoke) callTargetNode.usages().first(); - assert invoke != null : callTargetNode.targetMethod(); - - switch (operation.opcode()) { - case NODE_CLASS: - assert arguments.size() == 2; - ValueNode left = arguments.get(0); - ValueNode right = operation.rightOperandIsInt() ? toUnsigned(graph, arguments.get(1), Kind.Int) : fromSigned(graph, arguments.get(1)); - replace(invoke, nodeClassOp(graph, operation.node(), left, right, invoke)); - break; - - case COMPARISON: - assert arguments.size() == 2; - replace(invoke, comparisonOp(graph, operation.condition(), arguments.get(0), fromSigned(graph, arguments.get(1)))); - break; + for (Node node : graph.getNodes()) { + rewriteNode(graph, node); + } + } - case NOT: - assert arguments.size() == 1; - replace(invoke, graph.unique(new XorNode(wordKind, arguments.get(0), ConstantNode.forIntegerKind(wordKind, -1, graph)))); - break; - - case READ: { - assert arguments.size() == 2 || arguments.size() == 3; - Kind readKind = asKind(callTargetNode.returnType()); - LocationNode location; - if (arguments.size() == 2) { - location = makeLocation(graph, arguments.get(1), readKind, ANY_LOCATION); - } else { - location = makeLocation(graph, arguments.get(1), readKind, arguments.get(2)); - } - replace(invoke, readOp(graph, arguments.get(0), invoke, location, BarrierType.NONE, false)); - break; - } - case READ_HEAP: { - assert arguments.size() == 4; - Kind readKind = asKind(callTargetNode.returnType()); - LocationNode location = makeLocation(graph, arguments.get(1), readKind, ANY_LOCATION); - BarrierType barrierType = (BarrierType) arguments.get(2).asConstant().asObject(); - replace(invoke, readOp(graph, arguments.get(0), invoke, location, barrierType, arguments.get(3).asConstant().asInt() == 0 ? false : true)); - break; + /** + * Infer the stamps for all Object nodes in the graph, to make the stamps as precise as + * possible. For example, this propagates the word-type through phi functions. To handle phi + * functions at loop headers, the stamp inference is called until a fix point is reached. + *

+ * Note that we cannot rely on the normal canonicalizer to propagate stamps: The word type + * rewriting must run before the first run of the canonicalizer because many nodes are not + * prepared to see the word type during canonicalization. + */ + protected void inferStamps(StructuredGraph graph) { + boolean stampChanged; + do { + stampChanged = false; + /* + * We could use GraphOrder.forwardGraph() to process the nodes in a defined order and + * propagate long def-use chains in fewer iterations. However, measurements showed that + * we have few iterations anyway, and the overhead of computing the order is much higher + * than the benefit. + */ + for (Node n : graph.getNodes()) { + if (n instanceof ValueNode) { + ValueNode node = (ValueNode) n; + if (node.kind() == Kind.Object) { + stampChanged |= node.inferStamp(); } - case WRITE: - case INITIALIZE: { - assert arguments.size() == 3 || arguments.size() == 4; - Kind writeKind = asKind(targetMethod.getSignature().getParameterType(1, targetMethod.getDeclaringClass())); - LocationNode location; - if (arguments.size() == 3) { - location = makeLocation(graph, arguments.get(1), writeKind, LocationIdentity.ANY_LOCATION); - } else { - location = makeLocation(graph, arguments.get(1), writeKind, arguments.get(3)); - } - replace(invoke, writeOp(graph, arguments.get(0), arguments.get(2), invoke, location, operation.opcode())); - break; - } - case ZERO: - assert arguments.size() == 0; - replace(invoke, ConstantNode.forIntegerKind(wordKind, 0L, graph)); - break; + } + } + } while (stampChanged); + } + + /** + * Change the stamp for word nodes from the object stamp ({@link WordBase} or anything extending + * or implementing that interface) to the primitive word stamp. + */ + protected void changeToWord(StructuredGraph graph, ValueNode node) { + if (isWord(node)) { + if (node.isConstant()) { + ConstantNode oldConstant = (ConstantNode) node; + assert oldConstant.value.getKind() == Kind.Object; + WordBase value = (WordBase) oldConstant.value.asObject(); + ConstantNode newConstant = ConstantNode.forIntegerKind(wordKind, value.rawValue(), node.graph()); + graph.replaceFloating(oldConstant, newConstant); - case FROM_UNSIGNED: - assert arguments.size() == 1; - replace(invoke, fromUnsigned(graph, arguments.get(0))); - break; + } else { + node.setStamp(StampFactory.forKind(wordKind)); + } + } + } + + /** + * Clean up nodes that are no longer necessary or valid after the stamp change, and perform + * intrinsification of all methods called on word types. + */ + protected void rewriteNode(StructuredGraph graph, Node node) { + if (node instanceof CheckCastNode) { + rewriteCheckCast(graph, (CheckCastNode) node); + } else if (node instanceof LoadFieldNode) { + rewriteLoadField(graph, (LoadFieldNode) node); + } else if (node instanceof AccessIndexedNode) { + rewriteAccessIndexed(graph, (AccessIndexedNode) node); + } else if (node instanceof MethodCallTargetNode) { + rewriteInvoke(graph, (MethodCallTargetNode) node); + } + } - case FROM_SIGNED: - assert arguments.size() == 1; - replace(invoke, fromSigned(graph, arguments.get(0))); - break; + /** + * Remove casts between word types (which by now no longer have kind Object). + */ + protected void rewriteCheckCast(StructuredGraph graph, CheckCastNode node) { + if (node.kind() == wordKind) { + node.replaceAtUsages(node.object()); + graph.removeFixed(node); + } + } - case TO_RAW_VALUE: - assert arguments.size() == 1; - replace(invoke, toUnsigned(graph, arguments.get(0), Kind.Long)); - break; + /** + * Fold constant field reads, e.g. enum constants. + */ + protected void rewriteLoadField(StructuredGraph graph, LoadFieldNode node) { + ConstantNode constant = node.asConstant(metaAccess); + if (constant != null) { + node.replaceAtUsages(constant); + graph.removeFixed(node); + } + } - case FROM_OBJECT: - assert arguments.size() == 1; - replace(invoke, graph.unique(new UnsafeCastNode(arguments.get(0), StampFactory.forKind(wordKind)))); - break; - - case FROM_ARRAY: - assert arguments.size() == 2; - replace(invoke, graph.unique(new ComputeAddressNode(arguments.get(0), arguments.get(1), StampFactory.forKind(wordKind)))); - break; - - case TO_OBJECT: - assert arguments.size() == 1; - replace(invoke, graph.unique(new UnsafeCastNode(arguments.get(0), invoke.asNode().stamp()))); - break; - - default: - throw new GraalInternalError("Unknown opcode: %s", operation.opcode()); - } + /** + * Change loads and stores of word-arrays. Since the element kind is managed by the node on its + * own and not in the stamp, {@link #changeToWord} does not perform all necessary changes. + */ + protected void rewriteAccessIndexed(StructuredGraph graph, AccessIndexedNode node) { + ResolvedJavaType arrayType = ObjectStamp.typeOrNull(node.array()); + /* + * There are cases where the array does not have a known type yet, i.e., the type is null. + * In that case we assume it is not a word type. + */ + if (arrayType != null && isWord(arrayType.getComponentType()) && node.elementKind() != wordKind) { + /* + * The elementKind of the node is a final field, and other information such as the stamp + * depends on elementKind. Therefore, just create a new node and replace the old one. + */ + if (node instanceof LoadIndexedNode) { + graph.replaceFixedWithFixed(node, graph.add(new LoadIndexedNode(node.array(), node.index(), wordKind))); + } else if (node instanceof StoreIndexedNode) { + graph.replaceFixedWithFixed(node, graph.add(new StoreIndexedNode(node.array(), node.index(), wordKind, ((StoreIndexedNode) node).value()))); + } else { + throw GraalInternalError.shouldNotReachHere(); } } } - private ValueNode fromUnsigned(StructuredGraph graph, ValueNode value) { + /** + * Intrinsification of methods defined on the {@link Word} class that are annotated with + * {@link Operation}. + */ + protected void rewriteInvoke(StructuredGraph graph, MethodCallTargetNode callTargetNode) { + ResolvedJavaMethod targetMethod = callTargetNode.targetMethod(); + if (!wordBaseType.isAssignableFrom(targetMethod.getDeclaringClass()) && !objectAccessType.equals(targetMethod.getDeclaringClass())) { + /* + * Not a method defined on WordBase or a subclass / subinterface, and not on + * ObjectAccess, so nothing to rewrite. + */ + return; + } + + if (!callTargetNode.isStatic()) { + assert callTargetNode.receiver().kind() == wordKind : "changeToWord() missed the receiver"; + targetMethod = wordImplType.resolveMethod(targetMethod); + } + Operation operation = targetMethod.getAnnotation(Word.Operation.class); + assert operation != null : targetMethod; + + NodeInputList arguments = callTargetNode.arguments(); + Invoke invoke = callTargetNode.invoke(); + + switch (operation.opcode()) { + case NODE_CLASS: + assert arguments.size() == 2; + ValueNode left = arguments.get(0); + ValueNode right = operation.rightOperandIsInt() ? toUnsigned(graph, arguments.get(1), Kind.Int) : fromSigned(graph, arguments.get(1)); + + ValueNode replacement = graph.addOrUnique(createBinaryNodeInstance(operation.node(), wordKind, left, right)); + if (replacement instanceof FixedWithNextNode) { + graph.addBeforeFixed(invoke.asNode(), (FixedWithNextNode) replacement); + } + replace(invoke, replacement); + break; + + case COMPARISON: + assert arguments.size() == 2; + replace(invoke, comparisonOp(graph, operation.condition(), arguments.get(0), fromSigned(graph, arguments.get(1)))); + break; + + case NOT: + assert arguments.size() == 1; + replace(invoke, graph.unique(new XorNode(wordKind, arguments.get(0), ConstantNode.forIntegerKind(wordKind, -1, graph)))); + break; + + case READ: { + assert arguments.size() == 2 || arguments.size() == 3; + Kind readKind = asKind(callTargetNode.returnType()); + LocationNode location; + if (arguments.size() == 2) { + location = makeLocation(graph, arguments.get(1), readKind, ANY_LOCATION); + } else { + location = makeLocation(graph, arguments.get(1), readKind, arguments.get(2)); + } + replace(invoke, readOp(graph, arguments.get(0), invoke, location, BarrierType.NONE, false)); + break; + } + case READ_HEAP: { + assert arguments.size() == 4; + Kind readKind = asKind(callTargetNode.returnType()); + LocationNode location = makeLocation(graph, arguments.get(1), readKind, ANY_LOCATION); + BarrierType barrierType = (BarrierType) arguments.get(2).asConstant().asObject(); + replace(invoke, readOp(graph, arguments.get(0), invoke, location, barrierType, arguments.get(3).asConstant().asInt() == 0 ? false : true)); + break; + } + case WRITE: + case INITIALIZE: { + assert arguments.size() == 3 || arguments.size() == 4; + Kind writeKind = asKind(targetMethod.getSignature().getParameterType(Modifier.isStatic(targetMethod.getModifiers()) ? 2 : 1, targetMethod.getDeclaringClass())); + LocationNode location; + if (arguments.size() == 3) { + location = makeLocation(graph, arguments.get(1), writeKind, LocationIdentity.ANY_LOCATION); + } else { + location = makeLocation(graph, arguments.get(1), writeKind, arguments.get(3)); + } + replace(invoke, writeOp(graph, arguments.get(0), arguments.get(2), invoke, location, operation.opcode())); + break; + } + case ZERO: + assert arguments.size() == 0; + replace(invoke, ConstantNode.forIntegerKind(wordKind, 0L, graph)); + break; + + case FROM_UNSIGNED: + assert arguments.size() == 1; + replace(invoke, fromUnsigned(graph, arguments.get(0))); + break; + + case FROM_SIGNED: + assert arguments.size() == 1; + replace(invoke, fromSigned(graph, arguments.get(0))); + break; + + case TO_RAW_VALUE: + assert arguments.size() == 1; + replace(invoke, toUnsigned(graph, arguments.get(0), Kind.Long)); + break; + + case FROM_OBJECT: + assert arguments.size() == 1; + WordCastNode objectToWord = graph.add(WordCastNode.objectToWord(arguments.get(0), wordKind)); + graph.addBeforeFixed(invoke.asNode(), objectToWord); + replace(invoke, objectToWord); + break; + + case FROM_ARRAY: + assert arguments.size() == 2; + replace(invoke, graph.unique(new ComputeAddressNode(arguments.get(0), arguments.get(1), StampFactory.forKind(wordKind)))); + break; + + case TO_OBJECT: + assert arguments.size() == 1; + WordCastNode wordToObject = graph.add(WordCastNode.wordToObject(arguments.get(0), wordKind)); + graph.addBeforeFixed(invoke.asNode(), wordToObject); + replace(invoke, wordToObject); + break; + + default: + throw new GraalInternalError("Unknown opcode: %s", operation.opcode()); + } + } + + protected ValueNode fromUnsigned(StructuredGraph graph, ValueNode value) { return convert(graph, value, wordKind, ConvertNode.Op.L2I, ConvertNode.Op.UNSIGNED_I2L); } @@ -258,7 +319,7 @@ return convert(graph, value, wordKind, ConvertNode.Op.L2I, ConvertNode.Op.I2L); } - private static ValueNode toUnsigned(StructuredGraph graph, ValueNode value, Kind toKind) { + protected ValueNode toUnsigned(StructuredGraph graph, ValueNode value, Kind toKind) { return convert(graph, value, toKind, ConvertNode.Op.L2I, ConvertNode.Op.UNSIGNED_I2L); } @@ -279,14 +340,15 @@ } } - private ValueNode nodeClassOp(StructuredGraph graph, Class nodeClass, ValueNode left, ValueNode right, Invoke invoke) { + /** + * Create an instance of a binary node which is used to lower Word operations. This method is + * called for all Word operations which are annotated with @Operation(node = ...) and + * encapsulates the reflective allocation of the node. + */ + private static ValueNode createBinaryNodeInstance(Class nodeClass, Kind kind, ValueNode left, ValueNode right) { try { Constructor constructor = nodeClass.getConstructor(Kind.class, ValueNode.class, ValueNode.class); - ValueNode result = graph.add(constructor.newInstance(wordKind, left, right)); - if (result instanceof FixedWithNextNode) { - graph.addBeforeFixed(invoke.asNode(), (FixedWithNextNode) result); - } - return result; + return constructor.newInstance(kind, left, right); } catch (Throwable ex) { throw new GraalInternalError(ex).addContext(nodeClass.getName()); } @@ -329,20 +391,22 @@ return SnippetLocationNode.create(locationIdentity, ConstantNode.forObject(readKind, metaAccess, graph), ConstantNode.forLong(0, graph), offset, ConstantNode.forInt(1, graph), graph); } - private static LocationNode makeLocation(StructuredGraph graph, ValueNode offset, Kind readKind, LocationIdentity locationIdentity) { + protected LocationNode makeLocation(StructuredGraph graph, ValueNode offset, Kind readKind, LocationIdentity locationIdentity) { return IndexedLocationNode.create(locationIdentity, readKind, 0, offset, graph, 1); } - private static ValueNode readOp(StructuredGraph graph, ValueNode base, Invoke invoke, LocationNode location, BarrierType barrierType, boolean compressible) { + protected ValueNode readOp(StructuredGraph graph, ValueNode base, Invoke invoke, LocationNode location, BarrierType barrierType, boolean compressible) { ReadNode read = graph.add(new ReadNode(base, location, invoke.asNode().stamp(), barrierType, compressible)); graph.addBeforeFixed(invoke.asNode(), read); - // The read must not float outside its block otherwise it may float above an explicit zero - // check on its base address + /* + * The read must not float outside its block otherwise it may float above an explicit zero + * check on its base address. + */ read.setGuard(AbstractBeginNode.prevBegin(invoke.asNode())); return read; } - private static ValueNode writeOp(StructuredGraph graph, ValueNode base, ValueNode value, Invoke invoke, LocationNode location, Opcode op) { + protected ValueNode writeOp(StructuredGraph graph, ValueNode base, ValueNode value, Invoke invoke, LocationNode location, Opcode op) { assert op == Opcode.WRITE || op == Opcode.INITIALIZE; WriteNode write = graph.add(new WriteNode(base, value, location, BarrierType.NONE, false, op == Opcode.INITIALIZE)); write.setStateAfter(invoke.stateAfter()); @@ -350,7 +414,7 @@ return write; } - private static void replace(Invoke invoke, ValueNode value) { + protected void replace(Invoke invoke, ValueNode value) { FixedNode next = invoke.next(); invoke.setNext(null); invoke.asNode().replaceAtPredecessor(next); @@ -358,52 +422,19 @@ GraphUtil.killCFG(invoke.asNode()); } - public boolean isWord(ValueNode node) { - /* - * If we already know that we have a word type, we do not need to infer the stamp. This - * avoids exceptions in inferStamp when the inputs have already been rewritten to word, - * i.e., when the expected input is no longer an object. - */ - if (isWord0(node)) { - return true; - } - node.inferStamp(); - return isWord0(node); - } - - private boolean isWord0(ValueNode node) { - if (node.stamp() == StampFactory.forWord()) { - return true; - } - if (node.stamp() instanceof ObjectStamp) { - return isWord(((ObjectStamp) node.stamp()).type()); - } - return false; + protected boolean isWord(ValueNode node) { + return isWord(ObjectStamp.typeOrNull(node)); } - public boolean isWord(ResolvedJavaType type) { - if (type != null && wordBaseType.isAssignableFrom(type)) { - return true; - } - return false; + protected boolean isWord(ResolvedJavaType type) { + return type != null && wordBaseType.isAssignableFrom(type); } - public Kind asKind(JavaType type) { - if (type instanceof ResolvedJavaType) { - return isWord((ResolvedJavaType) type) ? wordKind : type.getKind(); + protected Kind asKind(JavaType type) { + if (type instanceof ResolvedJavaType && isWord((ResolvedJavaType) type)) { + return wordKind; } else { - return Kind.Object; - } - } - - private void changeToWord(ValueNode valueNode) { - if (valueNode.isConstant() && valueNode.asConstant().getKind() == Kind.Object) { - WordBase value = (WordBase) valueNode.asConstant().asObject(); - ConstantNode newConstant = ConstantNode.forIntegerKind(wordKind, value.rawValue(), valueNode.graph()); - valueNode.graph().replaceFloating((ConstantNode) valueNode, newConstant); - } else { - assert !(valueNode instanceof ConstantNode) : "boxed Word constants should not appear in a snippet graph: " + valueNode + ", stamp: " + valueNode.stamp(); - valueNode.setStamp(StampFactory.forKind(wordKind)); + return type.getKind(); } } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeVerificationPhase.java --- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeVerificationPhase.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeVerificationPhase.java Wed Oct 02 13:26:31 2013 +0200 @@ -36,8 +36,8 @@ import com.oracle.graal.word.Word.Operation; /** - * Verifies invariants that must hold for snippet code above and beyond normal bytecode - * verification. + * Verifies invariants that must hold for code that uses the {@link WordBase word type} above and + * beyond normal bytecode verification. */ public class WordTypeVerificationPhase extends Phase { @@ -49,6 +49,17 @@ @Override protected void run(StructuredGraph graph) { + assert verify(graph); + } + + protected boolean verify(StructuredGraph inputGraph) { + /* + * This is a verification phase, so we do not want to have side effects. Since inferStamps() + * modifies the stamp of nodes, we copy the graph before running the verification. + */ + StructuredGraph graph = inputGraph.copy(); + wordAccess.inferStamps(graph); + for (ValueNode node : graph.getNodes().filter(ValueNode.class)) { for (Node usage : node.usages()) { if (usage instanceof AccessMonitorNode) { @@ -70,32 +81,7 @@ verify(!isWord(node) || ((StoreIndexedNode) usage).value() != node, node, usage, "cannot store word value to array"); } else if (usage instanceof MethodCallTargetNode) { MethodCallTargetNode callTarget = (MethodCallTargetNode) usage; - ResolvedJavaMethod method = callTarget.targetMethod(); - if (method.getAnnotation(NodeIntrinsic.class) == null) { - Invoke invoke = (Invoke) callTarget.usages().first(); - NodeInputList arguments = callTarget.arguments(); - boolean isStatic = Modifier.isStatic(method.getModifiers()); - int argc = 0; - if (!isStatic) { - ValueNode receiver = arguments.get(argc); - if (receiver == node && isWord(node)) { - ResolvedJavaMethod resolvedMethod = wordAccess.getWordImplType().resolveMethod(method); - verify(resolvedMethod != null, node, invoke.asNode(), "cannot resolve method on Word class: " + MetaUtil.format("%H.%n(%P) %r", method)); - Operation operation = resolvedMethod.getAnnotation(Word.Operation.class); - verify(operation != null, node, invoke.asNode(), "cannot dispatch on word value to non @Operation annotated method " + resolvedMethod); - } - argc++; - } - Signature signature = method.getSignature(); - for (int i = 0; i < signature.getParameterCount(false); i++) { - ValueNode argument = arguments.get(argc); - if (argument == node) { - ResolvedJavaType type = (ResolvedJavaType) signature.getParameterType(i, method.getDeclaringClass()); - verify(isWord(type) == isWord(argument), node, invoke.asNode(), "cannot pass word value to non-word parameter " + i + " or vice-versa"); - } - argc++; - } - } + verifyInvoke(node, callTarget); } else if (usage instanceof ObjectEqualsNode) { verify(!isWord(node) || ((ObjectEqualsNode) usage).x() != node, node, usage, "cannot use word type in comparison"); verify(!isWord(node) || ((ObjectEqualsNode) usage).y() != node, node, usage, "cannot use word type in comparison"); @@ -111,19 +97,39 @@ } } } + return true; + } + + protected void verifyInvoke(ValueNode node, MethodCallTargetNode callTarget) { + ResolvedJavaMethod method = callTarget.targetMethod(); + if (method.getAnnotation(NodeIntrinsic.class) == null) { + Invoke invoke = (Invoke) callTarget.usages().first(); + NodeInputList arguments = callTarget.arguments(); + boolean isStatic = Modifier.isStatic(method.getModifiers()); + int argc = 0; + if (!isStatic) { + ValueNode receiver = arguments.get(argc); + if (receiver == node && isWord(node)) { + ResolvedJavaMethod resolvedMethod = wordAccess.wordImplType.resolveMethod(method); + verify(resolvedMethod != null, node, invoke.asNode(), "cannot resolve method on Word class: " + MetaUtil.format("%H.%n(%P) %r", method)); + Operation operation = resolvedMethod.getAnnotation(Word.Operation.class); + verify(operation != null, node, invoke.asNode(), "cannot dispatch on word value to non @Operation annotated method " + resolvedMethod); + } + argc++; + } + Signature signature = method.getSignature(); + for (int i = 0; i < signature.getParameterCount(false); i++) { + ValueNode argument = arguments.get(argc); + if (argument == node) { + ResolvedJavaType type = (ResolvedJavaType) signature.getParameterType(i, method.getDeclaringClass()); + verify(isWord(type) == isWord(argument), node, invoke.asNode(), "cannot pass word value to non-word parameter " + i + " or vice-versa"); + } + argc++; + } + } } private boolean isWord(ValueNode node) { - if (node instanceof ProxyNode) { - /* - * The proxy node will eventually get the same stamp as the value it is proxying. - * However, since we cannot guarantee the order in which isWord is called during the - * verification phase, the stamp assignment for the value might not have happened yet. - * Therefore, we check the proxied value directly instead of the proxy. - */ - return isWord(((ProxyNode) node).value()); - } - return wordAccess.isWord(node); } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/FrameSlotTypeSpecializationTest.java --- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/FrameSlotTypeSpecializationTest.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/FrameSlotTypeSpecializationTest.java Wed Oct 02 13:26:31 2013 +0200 @@ -116,7 +116,7 @@ // fall through } } - FrameUtil.setObjectSafe(frame, slot, o); + frame.setObject(slot, o); this.replace(new ObjectAssignLocal(slot, value)); return null; } @@ -134,11 +134,7 @@ @Override Object execute(VirtualFrame frame) { Object o = value.execute(frame); - try { - frame.setObject(slot, o); - } catch (FrameSlotTypeException e) { - FrameUtil.setObjectSafe(frame, slot, o); - } + frame.setObject(slot, o); return null; } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ReturnTypeSpecializationTest.java --- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ReturnTypeSpecializationTest.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/ReturnTypeSpecializationTest.java Wed Oct 02 13:26:31 2013 +0200 @@ -120,11 +120,11 @@ try { frame.setInt(slot, result); } catch (FrameSlotTypeException e) { - FrameUtil.setObjectSafe(frame, slot, result); + frame.setObject(slot, result); replace(new ObjectAssignLocal(slot, value)); } } catch (UnexpectedResultException e) { - FrameUtil.setObjectSafe(frame, slot, e.getResult()); + frame.setObject(slot, e.getResult()); replace(new ObjectAssignLocal(slot, value)); } return null; @@ -143,11 +143,7 @@ @Override Object execute(VirtualFrame frame) { Object o = value.execute(frame); - try { - frame.setObject(slot, o); - } catch (FrameSlotTypeException e) { - FrameUtil.setObjectSafe(frame, slot, o); - } + frame.setObject(slot, o); return null; } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.truffle.api/src/com/oracle/truffle/api/SourceSection.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/SourceSection.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/SourceSection.java Wed Oct 02 13:26:31 2013 +0200 @@ -25,75 +25,30 @@ package com.oracle.truffle.api; /** - * Represents a contiguous text section within the source code of a guest language program. + * Description of contiguous text section within the source code of a guest language program. */ -public class SourceSection { - - private final Source source; - private final String identifier; - private final int startLine; - private final int startColumn; - private final int charIndex; - private final int charLength; - - /** - * Creates a new object representing a contiguous text section within the source code of a guest - * language program. - *

- * The starting location of the section is specified using two different coordinate: - *

    - *
  • (row, column): rows and columns are 1-based, so the first character in a source - * file is at position {@code (1,1)}.
  • - *
  • character index: 0-based offset of the character from the beginning of the source, - * so the first character in a file is at index {@code 0}.
  • - *
- * The newline that terminates each line counts as a single character for the purpose of - * a character index. The (row,column) coordinates of a newline character should never appear in - * a text section. - *

- * - * @param source object representing the complete source program that contains this section - * @param identifier an identifier used when printing the section - * @param startLine the 1-based number of the start line of the section - * @param startColumn the 1-based number of the start column of the section - * @param charIndex the 0-based index of the first character of the section - * @param charLength the length of the section in number of characters - */ - public SourceSection(Source source, String identifier, int startLine, int startColumn, int charIndex, int charLength) { - this.source = source; - this.identifier = identifier; - this.startLine = startLine; - this.startColumn = startColumn; - this.charIndex = charIndex; - this.charLength = charLength; - } +public interface SourceSection { /** * Returns the object representing the source program that contains this section. * * @return the source object */ - public final Source getSource() { - return source; - } + Source getSource(); /** * Returns 1-based line number of the first character in this source section (inclusive). * * @return the starting line number */ - public final int getStartLine() { - return startLine; - } + int getStartLine(); /** * Returns the 1-based column number of the first character in this source section (inclusive). * * @return the starting column number */ - public final int getStartColumn() { - return startColumn; - } + int getStartColumn(); /** * Returns the 0-based index of the first character in this source section. @@ -103,9 +58,7 @@ * * @return the starting character index */ - public final int getCharIndex() { - return charIndex; - } + int getCharIndex(); /** * Returns the length of this source section in characters. @@ -115,85 +68,28 @@ * * @return the number of characters in the section */ - public final int getCharLength() { - return charLength; - } + int getCharLength(); + + /** + * Returns the index of the text position immediately following the last character in the + * section. + * + * @return the end position of the section + */ + int getCharEndIndex(); /** * Returns the identifier of this source section that is used for printing the section. * * @return the identifier of the section */ - public final String getIdentifier() { - return identifier; - } + String getIdentifier(); /** * Returns text of the code represented by this source section. * * @return the code as a String object */ - public final String getCode() { - return getSource().getCode().substring(charIndex, charIndex + charLength); - } - - @Override - public String toString() { - return String.format("%s:%d", source.getName(), startLine); - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + charIndex; - result = prime * result + charLength; - result = prime * result + ((identifier == null) ? 0 : identifier.hashCode()); - result = prime * result + ((source == null) ? 0 : source.hashCode()); - result = prime * result + startColumn; - result = prime * result + startLine; - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (!(obj instanceof SourceSection)) { - return false; - } - SourceSection other = (SourceSection) obj; - if (charIndex != other.charIndex) { - return false; - } - if (charLength != other.charLength) { - return false; - } - if (identifier == null) { - if (other.identifier != null) { - return false; - } - } else if (!identifier.equals(other.identifier)) { - return false; - } - if (source == null) { - if (other.source != null) { - return false; - } - } else if (!source.equals(other.source)) { - return false; - } - if (startColumn != other.startColumn) { - return false; - } - if (startLine != other.startLine) { - return false; - } - return true; - } + String getCode(); } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/Frame.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/Frame.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/Frame.java Wed Oct 02 13:26:31 2013 +0200 @@ -64,7 +64,7 @@ * @param slot the slot of the local variable * @param value the new value of the local variable */ - void setObject(FrameSlot slot, Object value) throws FrameSlotTypeException; + void setObject(FrameSlot slot, Object value); /** * Read access to a local variable of type byte. diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameDescriptor.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameDescriptor.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameDescriptor.java Wed Oct 02 13:26:31 2013 +0200 @@ -39,6 +39,7 @@ private final ArrayList slots; private final HashMap identifierToSlotMap; private Assumption version; + private HashMap identifierToNotInFrameAssumptionMap; public FrameDescriptor() { this(DefaultFrameTypeConversion.getInstance()); @@ -61,6 +62,7 @@ slots.add(slot); identifierToSlotMap.put(identifier, slot); updateVersion(); + invalidateNotInFrameAssumption(identifier); return slot; } @@ -93,7 +95,7 @@ } /** - * (db) to retrieve the list of all the identifiers associated with this frame descriptor. + * Retrieve the list of all the identifiers associated with this frame descriptor. * * @return the list of all the identifiers in this frame descriptor */ @@ -133,4 +135,32 @@ public FrameTypeConversion getTypeConversion() { return typeConversion; } + + public Assumption getNotInFrameAssumption(Object identifier) { + if (identifierToSlotMap.containsKey(identifier)) { + throw new IllegalArgumentException("Cannot get not-in-frame assumption for existing frame slot!"); + } + + if (identifierToNotInFrameAssumptionMap == null) { + identifierToNotInFrameAssumptionMap = new HashMap<>(); + } else { + Assumption assumption = identifierToNotInFrameAssumptionMap.get(identifier); + if (assumption != null) { + return assumption; + } + } + Assumption assumption = Truffle.getRuntime().createAssumption("not in frame: " + identifier); + identifierToNotInFrameAssumptionMap.put(identifier, assumption); + return assumption; + } + + private void invalidateNotInFrameAssumption(Object identifier) { + if (identifierToNotInFrameAssumptionMap != null) { + Assumption assumption = identifierToNotInFrameAssumptionMap.get(identifier); + if (assumption != null) { + assumption.invalidate(); + identifierToNotInFrameAssumptionMap.remove(identifier); + } + } + } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameSlotImpl.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameSlotImpl.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameSlotImpl.java Wed Oct 02 13:26:31 2013 +0200 @@ -51,9 +51,10 @@ } public void setKind(final FrameSlotKind kind) { - assert this.kind != kind; - this.kind = kind; - this.descriptor.updateVersion(); + if (this.kind != kind) { + this.kind = kind; + this.descriptor.updateVersion(); + } } @Override diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameUtil.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameUtil.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameUtil.java Wed Oct 02 13:26:31 2013 +0200 @@ -35,14 +35,7 @@ * @param value the new value of the local variable */ public static void setObjectSafe(Frame frame, FrameSlot slot, Object value) { - if (slot.getKind() != FrameSlotKind.Object) { - slot.setKind(FrameSlotKind.Object); - } - try { - frame.setObject(slot, value); - } catch (FrameSlotTypeException e) { - throw new IllegalStateException(); - } + frame.setObject(slot, value); } /** diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/AbstractAssumption.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/AbstractAssumption.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/AbstractAssumption.java Wed Oct 02 13:26:31 2013 +0200 @@ -43,6 +43,6 @@ @Override public String toString() { - return "Assumption: " + name; + return "Assumption(valid=" + isValid + "): " + name; } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultFrameTypeConversion.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultFrameTypeConversion.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultFrameTypeConversion.java Wed Oct 02 13:26:31 2013 +0200 @@ -40,7 +40,7 @@ @Override public void updateFrameSlot(Frame frame, FrameSlot slot, Object value) { - FrameUtil.setObjectSafe(frame, slot, value); + frame.setObject(slot, value); } public static DefaultFrameTypeConversion getInstance() { diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultMaterializedFrame.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultMaterializedFrame.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultMaterializedFrame.java Wed Oct 02 13:26:31 2013 +0200 @@ -46,7 +46,7 @@ } @Override - public void setObject(FrameSlot slot, Object value) throws FrameSlotTypeException { + public void setObject(FrameSlot slot, Object value) { wrapped.setObject(slot, value); } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultSourceSection.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultSourceSection.java Wed Oct 02 13:26:31 2013 +0200 @@ -0,0 +1,164 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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.truffle.api.impl; + +import com.oracle.truffle.api.*; + +/** + * Represents a contiguous text section within the source code of a guest language program. + */ +public class DefaultSourceSection implements SourceSection { + + private final Source source; + private final String identifier; + private final int startLine; + private final int startColumn; + private final int charIndex; + private final int charLength; + + /** + * Creates a new object representing a contiguous text section within the source code of a guest + * language program's text. + *

+ * The starting location of the section is specified using two different coordinate: + *

    + *
  • (row, column): rows and columns are 1-based, so the first character in a source + * file is at position {@code (1,1)}.
  • + *
  • character index: 0-based offset of the character from the beginning of the source, + * so the first character in a file is at index {@code 0}.
  • + *
+ * The newline that terminates each line counts as a single character for the purpose of + * a character index. The (row,column) coordinates of a newline character should never appear in + * a text section. + *

+ * + * @param source object representing the complete source program that contains this section + * @param identifier an identifier used when printing the section + * @param startLine the 1-based number of the start line of the section + * @param startColumn the 1-based number of the start column of the section + * @param charIndex the 0-based index of the first character of the section + * @param charLength the length of the section in number of characters + */ + public DefaultSourceSection(Source source, String identifier, int startLine, int startColumn, int charIndex, int charLength) { + this.source = source; + this.identifier = identifier; + this.startLine = startLine; + this.startColumn = startColumn; + this.charIndex = charIndex; + this.charLength = charLength; + } + + public final Source getSource() { + return source; + } + + public final int getStartLine() { + return startLine; + } + + public final int getStartColumn() { + return startColumn; + } + + public final int getCharIndex() { + return charIndex; + } + + public final int getCharLength() { + return charLength; + } + + public final int getCharEndIndex() { + return charIndex + charLength; + } + + public final String getIdentifier() { + return identifier; + } + + public final String getCode() { + return getSource().getCode().substring(charIndex, charIndex + charLength); + } + + @Override + public String toString() { + return String.format("%s:%d", source.getName(), startLine); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + charIndex; + result = prime * result + charLength; + result = prime * result + ((identifier == null) ? 0 : identifier.hashCode()); + result = prime * result + ((source == null) ? 0 : source.hashCode()); + result = prime * result + startColumn; + result = prime * result + startLine; + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (!(obj instanceof DefaultSourceSection)) { + return false; + } + DefaultSourceSection other = (DefaultSourceSection) obj; + if (charIndex != other.charIndex) { + return false; + } + if (charLength != other.charLength) { + return false; + } + if (identifier == null) { + if (other.identifier != null) { + return false; + } + } else if (!identifier.equals(other.identifier)) { + return false; + } + if (source == null) { + if (other.source != null) { + return false; + } + } else if (!source.equals(other.source)) { + return false; + } + if (startColumn != other.startColumn) { + return false; + } + if (startLine != other.startLine) { + return false; + } + return true; + } + +} diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultVirtualFrame.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultVirtualFrame.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultVirtualFrame.java Wed Oct 02 13:26:31 2013 +0200 @@ -42,6 +42,7 @@ this.caller = caller; this.arguments = arguments; this.locals = new Object[descriptor.getSize()]; + Arrays.fill(locals, descriptor.getTypeConversion().getDefaultValue()); this.tags = new byte[descriptor.getSize()]; } @@ -73,8 +74,8 @@ } @Override - public void setObject(FrameSlot slot, Object value) throws FrameSlotTypeException { - verifySet(slot, FrameSlotKind.Object); + public void setObject(FrameSlot slot, Object value) { + verifySetObject(slot); locals[slot.getIndex()] = value; } @@ -157,17 +158,11 @@ @Override public Object getValue(FrameSlot slot) { - int index = slot.getIndex(); - if (index >= tags.length) { - assert index >= 0 && index < descriptor.getSize(); - return descriptor.getTypeConversion().getDefaultValue(); + int slotIndex = slot.getIndex(); + if (slotIndex >= tags.length) { + resize(); } - byte tag = tags[index]; - if (tag == FrameSlotKind.Illegal.ordinal()) { - return descriptor.getTypeConversion().getDefaultValue(); - } else { - return locals[index]; - } + return locals[slotIndex]; } private void verifySet(FrameSlot slot, FrameSlotKind accessKind) throws FrameSlotTypeException { @@ -186,45 +181,50 @@ tags[slotIndex] = (byte) accessKind.ordinal(); } - private void verifyGet(FrameSlot slot, FrameSlotKind accessKind) throws FrameSlotTypeException { - FrameSlotKind slotKind = slot.getKind(); - if (slotKind != accessKind) { - if (slotKind == FrameSlotKind.Illegal && accessKind == FrameSlotKind.Object) { - slot.setKind(FrameSlotKind.Object); - this.setObject(slot, descriptor.getTypeConversion().getDefaultValue()); - } else { - throw new FrameSlotTypeException(); - } + private void verifySetObject(FrameSlot slot) { + if (slot.getKind() != FrameSlotKind.Object) { + slot.setKind(FrameSlotKind.Object); } int slotIndex = slot.getIndex(); if (slotIndex >= tags.length) { resize(); } - if (tags[slotIndex] != accessKind.ordinal()) { - descriptor.getTypeConversion().updateFrameSlot(this, slot, getValue(slot)); - if (tags[slotIndex] != accessKind.ordinal()) { - throw new FrameSlotTypeException(); + tags[slotIndex] = (byte) FrameSlotKind.Object.ordinal(); + } + + private void verifyGet(FrameSlot slot, FrameSlotKind accessKind) throws FrameSlotTypeException { + int slotIndex = slot.getIndex(); + if (slotIndex >= tags.length) { + resize(); + } + byte tag = tags[slotIndex]; + if (accessKind == FrameSlotKind.Object ? (tag & 0xfe) != 0 : tag != accessKind.ordinal()) { + if (slot.getKind() == accessKind || tag == 0) { + descriptor.getTypeConversion().updateFrameSlot(this, slot, getValue(slot)); + if (tags[slotIndex] == accessKind.ordinal()) { + return; + } } + throw new FrameSlotTypeException(); } } private void resize() { + int oldSize = tags.length; int newSize = descriptor.getSize(); - if (newSize > tags.length) { + if (newSize > oldSize) { locals = Arrays.copyOf(locals, newSize); + Arrays.fill(locals, oldSize, newSize, descriptor.getTypeConversion().getDefaultValue()); tags = Arrays.copyOf(tags, newSize); } } @Override public boolean isInitialized(FrameSlot slot) { - try { - return tags[slot.getIndex()] != 0; - } catch (ArrayIndexOutOfBoundsException ex) { - if (slot.getIndex() >= 0 && slot.getIndex() < descriptor.getSize()) { - return false; - } - throw ex; + int slotIndex = slot.getIndex(); + if (slotIndex >= tags.length) { + resize(); } + return tags[slotIndex] != 0; } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/GraphPrintVisitor.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/GraphPrintVisitor.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/GraphPrintVisitor.java Wed Oct 02 13:26:31 2013 +0200 @@ -218,8 +218,10 @@ } } setNodeProperty(node, "class", node.getClass().getSimpleName()); - readNodeProperties((Node) node); - copyDebugProperties(node); + if (node instanceof Node) { + readNodeProperties((Node) node); + copyDebugProperties((Node) node); + } } } @@ -252,12 +254,10 @@ propElem.setTextContent(String.valueOf(value)); } - private void copyDebugProperties(Object node) { - if (node instanceof Node) { - Map debugProperties = ((Node) node).getDebugProperties(); - for (Map.Entry property : debugProperties.entrySet()) { - setNodeProperty(node, property.getKey(), property.getValue()); - } + private void copyDebugProperties(Node node) { + Map debugProperties = node.getDebugProperties(); + for (Map.Entry property : debugProperties.entrySet()) { + setNodeProperty(node, property.getKey(), property.getValue()); } } @@ -274,7 +274,7 @@ } } - protected void connectNodes(Object a, Object b) { + protected void connectNodes(Object a, Object b, String label) { if (nodeMap.get(a) == null || nodeMap.get(b) == null) { return; } @@ -294,6 +294,9 @@ edgeElem.setAttribute("from", fromId); edgeElem.setAttribute("to", toId); edgeElem.setAttribute("index", String.valueOf(count)); + if (label != null) { + edgeElem.setAttribute("label", label); + } edgesElement.appendChild(edgeElem); edgeList.add(edgeElem); } @@ -304,45 +307,60 @@ } // if node is visited once again, skip - if (getElementByObject(node) == null || NodeUtil.findAnnotation(node.getClass(), GraphDuplicate.class) != null) { - visitAny(node); + if (getElementByObject(node) != null && NodeUtil.findAnnotation(node.getClass(), GraphDuplicate.class) == null) { + return this; + } + + // respect node's custom handler + if (NodeUtil.findAnnotation(node.getClass(), CustomGraphPrintHandler.class) != null) { + Class customHandlerClass = NodeUtil.findAnnotation(node.getClass(), CustomGraphPrintHandler.class).handler(); + try { + GraphPrintHandler customHandler = customHandlerClass.newInstance(); + customHandler.visit(node, new GraphPrintAdapter()); + } catch (InstantiationException | IllegalAccessException e) { + assert false : e; + } + } else if (NodeUtil.findAnnotation(node.getClass(), NullGraphPrintHandler.class) != null) { + // ignore + } else { + // default handler + createElementForNode(node); + + if (node instanceof Node) { + for (Map.Entry child : findNamedNodeChildren((Node) node).entrySet()) { + visit(child.getValue()); + connectNodes(node, child.getValue(), child.getKey()); + } + } } return this; } - private void visitAny(Object node) { - // respect node's custom handler - if (NodeUtil.findAnnotation(node.getClass(), NullGraphPrintHandler.class) != null) { - return; - } - if (NodeUtil.findAnnotation(node.getClass(), CustomGraphPrintHandler.class) != null) { - Class gpHandlerClass = NodeUtil.findAnnotation(node.getClass(), CustomGraphPrintHandler.class).handler(); - try { - GraphPrintHandler gpHandler = gpHandlerClass.newInstance(); - gpHandler.visit(node, new GraphPrintAdapter()); - } catch (InstantiationException e) { - assert false; - } catch (IllegalAccessException e) { - assert false; + private static LinkedHashMap findNamedNodeChildren(Node node) { + LinkedHashMap nodes = new LinkedHashMap<>(); + NodeClass nodeClass = NodeClass.get(node.getClass()); + + for (NodeField field : nodeClass.getFields()) { + NodeFieldKind kind = field.getKind(); + if (kind == NodeFieldKind.CHILD || kind == NodeFieldKind.CHILDREN) { + Object value = field.loadValue(node); + if (value != null) { + if (kind == NodeFieldKind.CHILD) { + nodes.put(field.getName(), (Node) value); + } else if (kind == NodeFieldKind.CHILDREN) { + Object[] children = (Object[]) value; + for (int i = 0; i < children.length; i++) { + if (children[i] != null) { + nodes.put(field.getName() + "[" + i + "]", (Node) children[i]); + } + } + } + } } - return; } - // default handler - createElementForNode(node); - - List children = NodeUtil.findNodeChildren((Node) node); - for (Object child : children) { - if (child == null) { - continue; - } else if (child instanceof Node) { - visit(child); - } else { - continue; - } - connectNodes(node, child); - } + return nodes; } public class GraphPrintAdapter { @@ -356,7 +374,7 @@ } public void connectNodes(Object node, Object child) { - GraphPrintVisitor.this.connectNodes(node, child); + GraphPrintVisitor.this.connectNodes(node, child, null); } public void setNodeProperty(Object node, String propertyName, Object value) { diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java Wed Oct 02 13:26:31 2013 +0200 @@ -71,7 +71,12 @@ */ public final void assignSourceSection(SourceSection section) { if (sourceSection != null) { - throw new IllegalStateException("Source section is already assigned."); + // Patch this test during the transition to constructor-based + // source attribution, which would otherwise trigger this + // exception. This method will eventually be deprecated. + if (getSourceSection() != section) { + throw new IllegalStateException("Source section is already assigned. Old: " + getSourceSection() + ", new: " + section); + } } this.sourceSection = section; } @@ -97,6 +102,7 @@ * * @return the assigned source code section */ + @CompilerDirectives.SlowPath public final SourceSection getEncapsulatingSourceSection() { if (sourceSection == null && getParent() != null) { return getParent().getEncapsulatingSourceSection(); @@ -169,7 +175,7 @@ if (this.getParent() == null) { throw new IllegalStateException("This node cannot be replaced, because it does not yet have a parent."); } - if (sourceSection != null) { + if (sourceSection != null && newNode.getSourceSection() == null) { // Pass on the source section to the new node. newNode.assignSourceSection(sourceSection); } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java Wed Oct 02 13:26:31 2013 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -31,13 +31,14 @@ import sun.misc.*; +import com.oracle.truffle.api.*; import com.oracle.truffle.api.nodes.Node.Child; import com.oracle.truffle.api.nodes.Node.Children; /** * Utility class that manages the special access methods for node instances. */ -public class NodeUtil { +public final class NodeUtil { /** * Interface that allows the customization of field offsets used for {@link Unsafe} field @@ -274,7 +275,7 @@ return array; } - protected static final Unsafe unsafe = getUnsafe(); + private static final Unsafe unsafe = getUnsafe(); private static Unsafe getUnsafe() { try { @@ -292,12 +293,8 @@ @SuppressWarnings("unchecked") public static T cloneNode(T orig) { - Class clazz = orig.getClass(); - NodeClass nodeClass = NodeClass.get(clazz); - Node clone = orig.copy(); - if (clone == null) { - return null; - } + final Node clone = orig.copy(); + NodeClass nodeClass = NodeClass.get(clone.getClass()); unsafe.putObject(clone, nodeClass.parentOffset, null); @@ -305,10 +302,6 @@ Node child = (Node) unsafe.getObject(orig, fieldOffset); if (child != null) { Node clonedChild = cloneNode(child); - if (clonedChild == null) { - return null; - } - unsafe.putObject(clonedChild, nodeClass.parentOffset, clone); unsafe.putObject(clone, fieldOffset, clonedChild); } @@ -316,16 +309,13 @@ for (long fieldOffset : nodeClass.childrenOffsets) { Node[] children = (Node[]) unsafe.getObject(orig, fieldOffset); if (children != null) { - Node[] clonedChildren = children.clone(); - Arrays.fill(clonedChildren, null); + Node[] clonedChildren = (Node[]) Array.newInstance(children.getClass().getComponentType(), children.length); for (int i = 0; i < children.length; i++) { - Node clonedChild = cloneNode(children[i]); - if (clonedChild == null) { - return null; + if (children[i] != null) { + Node clonedChild = cloneNode(children[i]); + clonedChildren[i] = clonedChild; + unsafe.putObject(clonedChild, nodeClass.parentOffset, clone); } - - clonedChildren[i] = clonedChild; - unsafe.putObject(clonedChild, nodeClass.parentOffset, clone); } unsafe.putObject(clone, fieldOffset, clonedChildren); } @@ -364,6 +354,7 @@ if (unsafe.getObject(parent, fieldOffset) == oldChild) { assert assertAssignable(nodeClass, fieldOffset, newChild); unsafe.putObject(parent, fieldOffset, newChild); + return; } } @@ -376,6 +367,7 @@ if (array[i] == oldChild) { assert assertAssignable(nodeClass, fieldOffset, newChild); array[i] = newChild; + return; } } } @@ -423,6 +415,24 @@ return result; } + /** + * Get the nth parent of a node, where the 0th parent is the node itself. Returns null if there + * are less than n ancestors. + */ + public static Node getNthParent(Node node, int n) { + Node parent = node; + + for (int i = 0; i < n; i++) { + parent = parent.getParent(); + + if (parent == null) { + return null; + } + } + + return parent; + } + /** find annotation in class/interface hierarchy. */ public static T findAnnotation(Class clazz, Class annotationClass) { if (clazz.getAnnotation(annotationClass) != null) { @@ -628,6 +638,66 @@ p.flush(); } + public static String printSourceAttributionTree(Node node) { + StringWriter out = new StringWriter(); + printSourceAttributionTree(new PrintWriter(out), null, node, 1); + return out.toString(); + } + + public static void printSourceAttributionTree(OutputStream out, Node node) { + printSourceAttributionTree(new PrintWriter(out), null, node, 1); + } + + private static void printSourceAttributionTree(PrintWriter p, Node parent, Node node, int level) { + if (node == null) { + return; + } + if (parent == null) { + // Add some preliminary information before starting with the root node + final SourceSection sourceSection = node.getSourceSection(); + if (sourceSection != null) { + final String txt = sourceSection.getSource().getCode(); + p.println("Full source len=(" + txt.length() + ") txt=___" + txt + "___"); + p.println("AST source attribution:"); + } + } + final StringBuilder sb = new StringBuilder(); + for (int i = 0; i < level; i++) { + sb.append("| "); + } + + if (parent != null) { + String childName = ""; + NodeField[] fields = NodeClass.get(parent.getClass()).fields; + for (NodeField field : fields) { + Object value = field.loadValue(parent); + if (value == node) { + childName = field.getName(); + break; + } else if (value instanceof Node[]) { + int index = 0; + for (Node arrayNode : (Node[]) value) { + if (arrayNode == node) { + childName = field.getName() + "[" + index + "]"; + break; + } + index++; + } + } + } + sb.append(childName); + } + + sb.append(" (" + node.getClass().getSimpleName() + ") "); + sb.append(displaySourceAttribution(node)); + p.println(sb.toString()); + + for (Node child : node.getChildren()) { + printSourceAttributionTree(p, node, child, level + 1); + } + p.flush(); + } + /** * Prints a human readable form of a {@link Node} AST to the given {@link PrintStream}. This * print method does not check for cycles in the node structure. @@ -715,4 +785,17 @@ private static String nodeName(Node node) { return node.getClass().getSimpleName(); } + + private static String displaySourceAttribution(Node node) { + final SourceSection section = node.getSourceSection(); + if (section != null) { + final String srcText = section.getCode(); + final StringBuilder sb = new StringBuilder(); + sb.append("source: len=" + srcText.length()); + sb.append(" (" + section.getCharIndex() + "," + (section.getCharEndIndex() - 1) + ")"); + sb.append(" txt=___" + srcText + "___"); + return sb.toString(); + } + return ""; + } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/UnexpectedResultException.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/UnexpectedResultException.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/UnexpectedResultException.java Wed Oct 02 13:26:31 2013 +0200 @@ -35,7 +35,7 @@ private final Object result; /** - * Creates the exception with the alternative result that cannot be respresented as a value of + * Creates the exception with the alternative result that cannot be represented as a value of * the return type. * * @param result the alternative result diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/TruffleTypes.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/TruffleTypes.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/TruffleTypes.java Wed Oct 02 13:26:31 2013 +0200 @@ -56,6 +56,7 @@ private final TypeMirror compilerDirectives; private final TypeMirror compilerAsserts; private final DeclaredType slowPath; + private final DeclaredType sourceSection; private final DeclaredType truffleOptions; private final TypeElement expectError; @@ -75,6 +76,7 @@ nodeInfoAnnotation = getRequired(context, NodeInfo.class); nodeInfoKind = getRequired(context, NodeInfo.Kind.class); slowPath = getRequired(context, SlowPath.class); + sourceSection = getRequired(context, SourceSection.class); truffleOptions = getRequired(context, TruffleOptions.class); expectError = (TypeElement) getRequired(context, ExpectError.class).asElement(); } @@ -158,4 +160,8 @@ public DeclaredType getSlowPath() { return slowPath; } + + public DeclaredType getSourceSection() { + return sourceSection; + } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java Wed Oct 02 13:26:31 2013 +0200 @@ -1102,15 +1102,19 @@ private void createConstructors(NodeData node, CodeTypeElement clazz) { List constructors = findUserConstructors(node.getNodeType()); + ExecutableElement sourceSectionConstructor = null; if (constructors.isEmpty()) { clazz.add(createUserConstructor(clazz, null)); } else { for (ExecutableElement constructor : constructors) { clazz.add(createUserConstructor(clazz, constructor)); + if (NodeParser.isSourceSectionConstructor(context, constructor)) { + sourceSectionConstructor = constructor; + } } } if (node.needsRewrites(getContext())) { - clazz.add(createCopyConstructor(clazz, findCopyConstructor(node.getNodeType()))); + clazz.add(createCopyConstructor(clazz, findCopyConstructor(node.getNodeType()), sourceSectionConstructor)); } } @@ -1181,31 +1185,15 @@ return builder.getRoot(); } - private CodeTree createCopyArray(CodeTreeBuilder parent, NodeChildData child, TypeMirror arrayType, CodeBlock accessElement) { - CodeTreeBuilder builder = parent.create(); - NodeData node = getModel().getNode(); - builder.string("new ").type(arrayType).string(" {"); - builder.startCommaGroup(); - for (ActualParameter parameter : getModel().getParameters()) { - NodeChildData foundChild = node.findChild(parameter.getSpecification().getName()); - if (foundChild == child) { - builder.startGroup(); - builder.tree(accessElement.create(builder, String.valueOf(parameter.getIndex()))); - builder.end(); - } - } - builder.end(); - builder.end().string("}"); - return builder.getRoot(); - } - - private CodeExecutableElement createCopyConstructor(CodeTypeElement type, ExecutableElement superConstructor) { + private CodeExecutableElement createCopyConstructor(CodeTypeElement type, ExecutableElement superConstructor, ExecutableElement sourceSectionConstructor) { CodeExecutableElement method = new CodeExecutableElement(null, type.getSimpleName().toString()); CodeTreeBuilder builder = method.createBuilder(); method.getParameters().add(new CodeVariableElement(type.asType(), "copy")); if (superConstructor != null) { builder.startStatement().startSuperCall().string("copy").end().end(); + } else if (sourceSectionConstructor != null) { + builder.startStatement().startSuperCall().string("copy.getSourceSection()").end().end(); } for (VariableElement var : type.getFields()) { @@ -1213,18 +1201,11 @@ final String varName = var.getSimpleName().toString(); final TypeMirror varType = var.asType(); - final String copyAccess = "copy." + varName; - CodeTree init = CodeTreeBuilder.singleString(copyAccess); - if (Utils.isAssignable(getContext(), var.asType(), getContext().getTruffleTypes().getNodeArray())) { - NodeChildData child = getModel().getNode().findChild(varName); - init = createCopyArray(builder, child, varType, new CodeBlock() { - - public CodeTree create(CodeTreeBuilder parent, String index) { - return CodeTreeBuilder.singleString(copyAccess + "[" + index + "]"); - } - }); + String copyAccess = "copy." + varName; + if (Utils.isAssignable(getContext(), varType, getContext().getTruffleTypes().getNodeArray())) { + copyAccess += ".clone()"; } - init = createAdoptChild(builder, varType, init); + CodeTree init = createAdoptChild(builder, varType, CodeTreeBuilder.singleString(copyAccess)); builder.startStatement().string("this.").string(varName).string(" = ").tree(init).end(); } if (getModel().getNode().isPolymorphic()) { @@ -1492,7 +1473,7 @@ guardsAnd = " && "; } - CodeTree cast = createCast(castBuilder, child, valueParam, typeGuard.getType(), minimumState); + CodeTree cast = createCast(castBuilder, child, valueParam, typeGuard.getType(), checkMinimumState); if (cast != null) { castBuilder.tree(cast); } @@ -1605,7 +1586,7 @@ return builder.getRoot(); } - private CodeTree createCast(CodeTreeBuilder parent, NodeChildData field, ActualParameter source, TypeData targetType, boolean minimumState) { + private CodeTree createCast(CodeTreeBuilder parent, NodeChildData field, ActualParameter source, TypeData targetType, boolean checkMinimumState) { NodeData node = field.getNodeData(); TypeData sourceType = source.getTypeSystemType(); @@ -1632,7 +1613,7 @@ CodeTreeBuilder builder = parent.create(); builder.tree(createLazyAssignment(parent, castValueName(source), targetType.getPrimitiveType(), condition, value)); - if (minimumState && types.size() > 1) { + if (checkMinimumState && types.size() > 1) { CodeTree castType = createCallTypeSystemMethod(context, parent, node, TypeSystemCodeGenerator.getImplicitClass(targetType), CodeTreeBuilder.singleString(valueName(source))); builder.tree(createLazyAssignment(builder, typeName(source), getContext().getType(Class.class), condition, castType)); } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeParser.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeParser.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeParser.java Wed Oct 02 13:26:31 2013 +0200 @@ -1052,7 +1052,7 @@ boolean parametersFound = false; for (ExecutableElement constructor : constructors) { - if (!constructor.getParameters().isEmpty()) { + if (!constructor.getParameters().isEmpty() && !isSourceSectionConstructor(context, constructor)) { parametersFound = true; } } @@ -1077,6 +1077,10 @@ nodeData.addError("Specialization constructor '%s(%s previousNode) { this(...); }' is required.", Utils.getSimpleName(type), Utils.getSimpleName(type)); } + static boolean isSourceSectionConstructor(ProcessorContext context, ExecutableElement constructor) { + return constructor.getParameters().size() == 1 && Utils.typeEquals(constructor.getParameters().get(0).asType(), context.getTruffleTypes().getSourceSection()); + } + private static boolean verifySpecializationParameters(NodeData nodeData) { boolean valid = true; int args = -1; diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeSystemParser.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeSystemParser.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/typesystem/TypeSystemParser.java Wed Oct 02 13:26:31 2013 +0200 @@ -108,7 +108,6 @@ cast.getTargetType().addTypeCast(cast); } - verifyImplicitCasts(typeSystem); verifyGenericTypeChecksAndCasts(typeSystem); verifyMethodSignatures(typeSystem); verifyNamesUnique(typeSystem); @@ -116,24 +115,6 @@ return typeSystem; } - private static void verifyImplicitCasts(TypeSystemData typeSystem) { - Set types = new HashSet<>(); - Set duplicateSourceTypes = new HashSet<>(); - for (ImplicitCastData cast : typeSystem.getImplicitCasts()) { - if (types.contains(cast.getSourceType())) { - duplicateSourceTypes.add(cast.getSourceType()); - } - types.add(cast.getSourceType()); - } - for (TypeData duplicateType : duplicateSourceTypes) { - for (ImplicitCastData cast : typeSystem.getImplicitCasts()) { - if (cast.getSourceType().equals(duplicateType)) { - cast.addError("Duplicate cast source type %s.", Utils.getSimpleName(duplicateType.getPrimitiveType()), ImplicitCast.class.getSimpleName()); - } - } - } - } - private static void verifyGenericTypeChecksAndCasts(TypeSystemData typeSystem) { for (TypeData type : typeSystem.getTypes()) { if (!type.getTypeChecks().isEmpty()) { diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/ReadLocalNode.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/ReadLocalNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/ReadLocalNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -50,7 +50,7 @@ try { return frame.getObject(slot); } catch (FrameSlotTypeException e) { - throw new RuntimeException("uninitialized variable " + slot.getIdentifier()); + throw new IllegalStateException(); } } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/WriteLocalNode.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/WriteLocalNode.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/WriteLocalNode.java Wed Oct 02 13:26:31 2013 +0200 @@ -50,11 +50,7 @@ @Specialization public Object writeGeneric(VirtualFrame frame, Object right) { - try { - frame.setObject(slot, right); - } catch (FrameSlotTypeException e) { - FrameUtil.setObjectSafe(frame, slot, right); - } + frame.setObject(slot, right); return right; } diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Parser.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Parser.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Parser.java Wed Oct 02 13:26:31 2013 +0200 @@ -32,11 +32,11 @@ // Checkstyle: stop // @formatter:off public class Parser { - public static final int _EOF = 0; - public static final int _identifier = 1; - public static final int _stringLiteral = 2; - public static final int _numericLiteral = 3; - public static final int maxT = 28; + public static final int _EOF = 0; + public static final int _identifier = 1; + public static final int _stringLiteral = 2; + public static final int _numericLiteral = 3; + public static final int maxT = 28; static final boolean T = true; static final boolean x = false; @@ -120,255 +120,255 @@ } } - void SimpleLanguage() { - Function(); - while (la.kind == 4) { - Function(); - } - } - - void Function() { - Expect(4); - factory.startFunction(); - Expect(1); - String name = t.val; - StatementNode body = Block(); - factory.createFunction(body, name); - } - - StatementNode Block() { - StatementNode result; - List statements = new ArrayList<>(); - Expect(5); - while (StartOf(1)) { - StatementNode statement = Statement(); - statements.add(statement); - } - Expect(6); - result = factory.createBlock(statements); - return result; - } - - StatementNode Statement() { - StatementNode result; - result = null; - if (la.kind == 7) { - result = WhileStatement(); - } else if (la.kind == 1) { - result = AssignmentStatement(); - } else if (la.kind == 12) { - result = OutputStatement(); - } else if (la.kind == 13) { - result = ReturnStatement(); - } else SynErr(29); - return result; - } - - StatementNode WhileStatement() { - StatementNode result; - Expect(7); - Expect(8); - ConditionNode condition = Expression(); - Expect(9); - StatementNode body = Block(); - result = factory.createWhile(condition, body); - return result; - } - - StatementNode AssignmentStatement() { - StatementNode result; - Expect(1); - String name = t.val; - Expect(10); - TypedNode rvalue = Expression(); - Expect(11); - result = factory.createAssignment(name, rvalue); - return result; - } - - StatementNode OutputStatement() { - StatementNode result; - List expressions = new ArrayList<>(); - Expect(12); - while (StartOf(2)) { - TypedNode value = Expression(); - expressions.add(value); - } - Expect(11); - result = factory.createPrint(expressions); - return result; - } - - StatementNode ReturnStatement() { - StatementNode result; - Expect(13); - TypedNode value = Expression(); - Expect(11); - result = factory.createReturn(value); - return result; - } - - TypedNode Expression() { - TypedNode result; - result = ValueExpression(); - if (StartOf(3)) { - switch (la.kind) { - case 14: { - Get(); - break; - } - case 15: { - Get(); - break; - } - case 16: { - Get(); - break; - } - case 17: { - Get(); - break; - } - case 18: { - Get(); - break; - } - case 19: { - Get(); - break; - } - } - String op = t.val; - TypedNode right = ValueExpression(); - result = factory.createBinary(op, result, right); - } - return result; - } - - TypedNode ValueExpression() { - TypedNode result; - result = Term(); - while (la.kind == 20 || la.kind == 21) { - if (la.kind == 20) { - Get(); - } else { - Get(); - } - String op = t.val; - TypedNode right = Term(); - result = factory.createBinary(op, result, right); - } - return result; - } - - TypedNode Term() { - TypedNode result; - result = Factor(); - while (la.kind == 22 || la.kind == 23) { - if (la.kind == 22) { - Get(); - } else { - Get(); - } - String op = t.val; - TypedNode right = Factor(); - result = factory.createBinary(op, result, right); - } - return result; - } - - TypedNode Factor() { - TypedNode result; - result = null; - switch (la.kind) { - case 27: { - result = TimeRef(); - break; - } - case 1: { - result = VariableRef(); - break; - } - case 2: { - result = StringLiteral(); - break; - } - case 3: { - result = NumericLiteral(); - break; - } - case 24: { - result = Ternary(); - break; - } - case 8: { - Get(); - result = Expression(); - Expect(9); - break; - } - default: SynErr(30); break; - } - return result; - } - - TypedNode TimeRef() { - TypedNode result; - Expect(27); - result = factory.createTime(); - return result; - } - - TypedNode VariableRef() { - TypedNode result; - Expect(1); - result = factory.createLocal(t.val); - return result; - } - - TypedNode StringLiteral() { - TypedNode result; - Expect(2); - result = factory.createStringLiteral(t.val.substring(1, t.val.length() - 1)); - return result; - } - - TypedNode NumericLiteral() { - TypedNode result; - Expect(3); - result = factory.createNumericLiteral(t.val); - return result; - } - - TypedNode Ternary() { - TypedNode result; - TypedNode condition, thenPart, elsePart; - Expect(24); - condition = Expression(); - Expect(25); - thenPart = Expression(); - Expect(26); - elsePart = Expression(); - result = factory.createTernary(condition, thenPart, elsePart); - return result; - } - + void SimpleLanguage() { + Function(); + while (la.kind == 4) { + Function(); + } + } + + void Function() { + Expect(4); + factory.startFunction(); + Expect(1); + String name = t.val; + StatementNode body = Block(); + factory.createFunction(body, name); + } + + StatementNode Block() { + StatementNode result; + List statements = new ArrayList<>(); + Expect(5); + while (StartOf(1)) { + StatementNode statement = Statement(); + statements.add(statement); + } + Expect(6); + result = factory.createBlock(statements); + return result; + } + + StatementNode Statement() { + StatementNode result; + result = null; + if (la.kind == 7) { + result = WhileStatement(); + } else if (la.kind == 1) { + result = AssignmentStatement(); + } else if (la.kind == 12) { + result = OutputStatement(); + } else if (la.kind == 13) { + result = ReturnStatement(); + } else SynErr(29); + return result; + } + + StatementNode WhileStatement() { + StatementNode result; + Expect(7); + Expect(8); + ConditionNode condition = Expression(); + Expect(9); + StatementNode body = Block(); + result = factory.createWhile(condition, body); + return result; + } + + StatementNode AssignmentStatement() { + StatementNode result; + Expect(1); + String name = t.val; + Expect(10); + TypedNode rvalue = Expression(); + Expect(11); + result = factory.createAssignment(name, rvalue); + return result; + } + + StatementNode OutputStatement() { + StatementNode result; + List expressions = new ArrayList<>(); + Expect(12); + while (StartOf(2)) { + TypedNode value = Expression(); + expressions.add(value); + } + Expect(11); + result = factory.createPrint(expressions); + return result; + } + + StatementNode ReturnStatement() { + StatementNode result; + Expect(13); + TypedNode value = Expression(); + Expect(11); + result = factory.createReturn(value); + return result; + } + + TypedNode Expression() { + TypedNode result; + result = ValueExpression(); + if (StartOf(3)) { + switch (la.kind) { + case 14: { + Get(); + break; + } + case 15: { + Get(); + break; + } + case 16: { + Get(); + break; + } + case 17: { + Get(); + break; + } + case 18: { + Get(); + break; + } + case 19: { + Get(); + break; + } + } + String op = t.val; + TypedNode right = ValueExpression(); + result = factory.createBinary(op, result, right); + } + return result; + } + + TypedNode ValueExpression() { + TypedNode result; + result = Term(); + while (la.kind == 20 || la.kind == 21) { + if (la.kind == 20) { + Get(); + } else { + Get(); + } + String op = t.val; + TypedNode right = Term(); + result = factory.createBinary(op, result, right); + } + return result; + } + + TypedNode Term() { + TypedNode result; + result = Factor(); + while (la.kind == 22 || la.kind == 23) { + if (la.kind == 22) { + Get(); + } else { + Get(); + } + String op = t.val; + TypedNode right = Factor(); + result = factory.createBinary(op, result, right); + } + return result; + } + + TypedNode Factor() { + TypedNode result; + result = null; + switch (la.kind) { + case 27: { + result = TimeRef(); + break; + } + case 1: { + result = VariableRef(); + break; + } + case 2: { + result = StringLiteral(); + break; + } + case 3: { + result = NumericLiteral(); + break; + } + case 24: { + result = Ternary(); + break; + } + case 8: { + Get(); + result = Expression(); + Expect(9); + break; + } + default: SynErr(30); break; + } + return result; + } + + TypedNode TimeRef() { + TypedNode result; + Expect(27); + result = factory.createTime(); + return result; + } + + TypedNode VariableRef() { + TypedNode result; + Expect(1); + result = factory.createLocal(t.val); + return result; + } + + TypedNode StringLiteral() { + TypedNode result; + Expect(2); + result = factory.createStringLiteral(t.val.substring(1, t.val.length() - 1)); + return result; + } + + TypedNode NumericLiteral() { + TypedNode result; + Expect(3); + result = factory.createNumericLiteral(t.val); + return result; + } + + TypedNode Ternary() { + TypedNode result; + TypedNode condition, thenPart, elsePart; + Expect(24); + condition = Expression(); + Expect(25); + thenPart = Expression(); + Expect(26); + elsePart = Expression(); + result = factory.createTernary(condition, thenPart, elsePart); + return result; + } + public void Parse() { la = new Token(); la.val = ""; Get(); - SimpleLanguage(); - Expect(0); + SimpleLanguage(); + Expect(0); } private static final boolean[][] set = { - {T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x}, - {x,T,x,x, x,x,x,T, x,x,x,x, T,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x}, - {x,T,T,T, x,x,x,x, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,x,x,T, x,x}, - {x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,T, T,T,T,T, x,x,x,x, x,x,x,x, x,x} + {T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x}, + {x,T,x,x, x,x,x,T, x,x,x,x, T,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x}, + {x,T,T,T, x,x,x,x, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,x,x,T, x,x}, + {x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,T, T,T,T,T, x,x,x,x, x,x,x,x, x,x} }; @@ -416,37 +416,37 @@ public void SynErr(int line, int col, int n) { String s; - switch (n) { - case 0: s = "EOF expected"; break; - case 1: s = "identifier expected"; break; - case 2: s = "stringLiteral expected"; break; - case 3: s = "numericLiteral expected"; break; - case 4: s = "\"function\" expected"; break; - case 5: s = "\"{\" expected"; break; - case 6: s = "\"}\" expected"; break; - case 7: s = "\"while\" expected"; break; - case 8: s = "\"(\" expected"; break; - case 9: s = "\")\" expected"; break; - case 10: s = "\"=\" expected"; break; - case 11: s = "\";\" expected"; break; - case 12: s = "\"print\" expected"; break; - case 13: s = "\"return\" expected"; break; - case 14: s = "\"<\" expected"; break; - case 15: s = "\">\" expected"; break; - case 16: s = "\"<=\" expected"; break; - case 17: s = "\">=\" expected"; break; - case 18: s = "\"==\" expected"; break; - case 19: s = "\"!=\" expected"; break; - case 20: s = "\"+\" expected"; break; - case 21: s = "\"-\" expected"; break; - case 22: s = "\"*\" expected"; break; - case 23: s = "\"/\" expected"; break; - case 24: s = "\"#\" expected"; break; - case 25: s = "\"?\" expected"; break; - case 26: s = "\":\" expected"; break; - case 27: s = "\"time\" expected"; break; - case 28: s = "??? expected"; break; - case 29: s = "invalid Statement"; break; + switch (n) { + case 0: s = "EOF expected"; break; + case 1: s = "identifier expected"; break; + case 2: s = "stringLiteral expected"; break; + case 3: s = "numericLiteral expected"; break; + case 4: s = "\"function\" expected"; break; + case 5: s = "\"{\" expected"; break; + case 6: s = "\"}\" expected"; break; + case 7: s = "\"while\" expected"; break; + case 8: s = "\"(\" expected"; break; + case 9: s = "\")\" expected"; break; + case 10: s = "\"=\" expected"; break; + case 11: s = "\";\" expected"; break; + case 12: s = "\"print\" expected"; break; + case 13: s = "\"return\" expected"; break; + case 14: s = "\"<\" expected"; break; + case 15: s = "\">\" expected"; break; + case 16: s = "\"<=\" expected"; break; + case 17: s = "\">=\" expected"; break; + case 18: s = "\"==\" expected"; break; + case 19: s = "\"!=\" expected"; break; + case 20: s = "\"+\" expected"; break; + case 21: s = "\"-\" expected"; break; + case 22: s = "\"*\" expected"; break; + case 23: s = "\"/\" expected"; break; + case 24: s = "\"#\" expected"; break; + case 25: s = "\"?\" expected"; break; + case 26: s = "\":\" expected"; break; + case 27: s = "\"time\" expected"; break; + case 28: s = "??? expected"; break; + case 29: s = "invalid Statement"; break; case 30: s = "invalid Factor"; break; default: s = "error " + n; diff -r 91dbb0b7dc8b -r aff825fef0fd graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Scanner.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Scanner.java Fri Sep 06 21:37:50 2013 +0200 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Scanner.java Wed Oct 02 13:26:31 2013 +0200 @@ -21,7 +21,7 @@ * questions. */ -// The content of this file is automatically generated. DO NOT EDIT. + // The content of this file is automatically generated. DO NOT EDIT. package com.oracle.truffle.sl.parser; @@ -518,66 +518,66 @@ } // NextCh already done case 1: recEnd = pos; recKind = 1; - if (ch >= '0' && ch <= '9' || ch >= 'A' && ch <= 'Z' || ch >= 'a' && ch <= 'z') {AddCh(); state = 1; break;} + if (ch >= '0' && ch <= '9' || ch >= 'A' && ch <= 'Z' || ch >= 'a' && ch <= 'z') {AddCh(); state = 1; break;} else {t.kind = 1; t.val = new String(tval, 0, tlen); CheckLiteral(); return t;} case 2: - if (ch <= 9 || ch >= 11 && ch <= 12 || ch >= 14 && ch <= '!' || ch >= '#' && ch <= '[' || ch >= ']' && ch <= 65535) {AddCh(); state = 2; break;} - else if (ch == '"') {AddCh(); state = 3; break;} + if (ch <= 9 || ch >= 11 && ch <= 12 || ch >= 14 && ch <= '!' || ch >= '#' && ch <= '[' || ch >= ']' && ch <= 65535) {AddCh(); state = 2; break;} + else if (ch == '"') {AddCh(); state = 3; break;} else {state = 0; break;} - case 3: + case 3: {t.kind = 2; break loop;} case 4: recEnd = pos; recKind = 3; - if (ch >= '0' && ch <= '9') {AddCh(); state = 4; break;} + if (ch >= '0' && ch <= '9') {AddCh(); state = 4; break;} else {t.kind = 3; break loop;} - case 5: + case 5: {t.kind = 3; break loop;} - case 6: + case 6: {t.kind = 5; break loop;} - case 7: + case 7: {t.kind = 6; break loop;} - case 8: + case 8: {t.kind = 8; break loop;} - case 9: + case 9: {t.kind = 9; break loop;} - case 10: + case 10: {t.kind = 11; break loop;} - case 11: + case 11: {t.kind = 16; break loop;} - case 12: + case 12: {t.kind = 17; break loop;} - case 13: + case 13: {t.kind = 18; break loop;} case 14: - if (ch == '=') {AddCh(); state = 15; break;} + if (ch == '=') {AddCh(); state = 15; break;} else {state = 0; break;} - case 15: + case 15: {t.kind = 19; break loop;} - case 16: + case 16: {t.kind = 20; break loop;} - case 17: + case 17: {t.kind = 21; break loop;} - case 18: + case 18: {t.kind = 22; break loop;} - case 19: + case 19: {t.kind = 23; break loop;} - case 20: + case 20: {t.kind = 24; break loop;} - case 21: + case 21: {t.kind = 25; break loop;} - case 22: + case 22: {t.kind = 26; break loop;} case 23: recEnd = pos; recKind = 10; - if (ch == '=') {AddCh(); state = 13; break;} + if (ch == '=') {AddCh(); state = 13; break;} else {t.kind = 10; break loop;} case 24: recEnd = pos; recKind = 14; - if (ch == '=') {AddCh(); state = 11; break;} + if (ch == '=') {AddCh(); state = 11; break;} else {t.kind = 14; break loop;} case 25: recEnd = pos; recKind = 15; - if (ch == '=') {AddCh(); state = 12; break;} + if (ch == '=') {AddCh(); state = 12; break;} else {t.kind = 15; break loop;} } diff -r 91dbb0b7dc8b -r aff825fef0fd mx/.pylintrc --- a/mx/.pylintrc Fri Sep 06 21:37:50 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,278 +0,0 @@ -[MASTER] - -# Specify a configuration file. -#rcfile= - -# Python code to execute, usually for sys.path manipulation such as -# pygtk.require(). -#init-hook= - -# Profiled execution. -profile=no - -# Add files or directories to the blacklist. They should be base names, not -# paths. -ignore=CVS - -# Pickle collected data for later comparisons. -persistent=no - -# List of plugins (as comma separated values of python modules names) to load, -# usually to register additional checkers. -load-plugins= - - -[MESSAGES CONTROL] - -# Enable the message, report, category or checker with the given id(s). You can -# either give multiple identifier separated by comma (,) or put this option -# multiple time. See also the "--disable" option for examples. -#enable= - -# Disable the message, report, category or checker with the given id(s). You -# can either give multiple identifiers separated by comma (,) or put this -# option multiple times (only on the command line, not in the configuration -# file where it should appear only once).You can also use "--disable=all" to -# disable everything first and then reenable specific checks. For example, if -# you want to run only the similarities checker, you can use "--disable=all -# --enable=similarities". If you want to run only the classes checker, but have -# no Warning level messages displayed, use"--disable=all --enable=classes -# --disable=W" -disable=attribute-defined-outside-init,arguments-differ, - bare-except,global-statement,protected-access,redefined-outer-name, - unused-argument,star-args,pointless-string-statement,old-style-class, - too-many-lines,missing-docstring,no-init,no-self-use,too-many-statements, - too-many-locals,too-few-public-methods,too-many-instance-attributes, - too-many-arguments,too-many-branches,too-many-public-methods, - abstract-method - -[REPORTS] - -# Set the output format. Available formats are text, parseable, colorized, msvs -# (visual studio) and html. You can also give a reporter class, eg -# mypackage.mymodule.MyReporterClass. -output-format=text - -# Put messages in a separate file for each module / package specified on the -# command line instead of printing them on stdout. Reports (if any) will be -# written in a file name "pylint_global.[txt|html]". -files-output=no - -# Tells whether to display a full report or only the messages -reports=no - -# Python expression which should return a note less than 10 (10 is the highest -# note). You have access to the variables errors warning, statement which -# respectively contain the number of errors / warnings messages and the total -# number of statements analyzed. This is used by the global evaluation report -# (RP0004). -evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10) - -# Add a comment according to your evaluation note. This is used by the global -# evaluation report (RP0004). -comment=no - -# Template used to display messages. This is a python new-style format string -# used to format the massage information. See doc for all details -#msg-template= - - -[BASIC] - -# Required attributes for module, separated by a comma -required-attributes= - -# List of builtins function names that should not be used, separated by a comma -bad-functions=filter,apply,input - -# Regular expression which should only match correct module names -module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ - -# Regular expression which should only match correct module level names -const-rgx=[a-zA-Z0-9_]{2,30}$ - -# Regular expression which should only match correct class names -class-rgx=[A-Z_][a-zA-Z0-9]+$ - -# Regular expression which should only match correct function names -function-rgx=[a-z_][a-zA-Z0-9_]{1,40}$ - -# Regular expression which should only match correct method names -method-rgx=[a-z_][a-zA-Z0-9_]{2,40}$ - -# Regular expression which should only match correct instance attribute names -attr-rgx=[a-z_][a-zA-Z0-9_]{1,30}$ - -# Regular expression which should only match correct argument names -argument-rgx=[a-z_][a-zA-Z0-9_]{0,30}$ - -# Regular expression which should only match correct variable names -variable-rgx=[a-z_][a-zA-Z0-9_]{0,30}$ - -# Regular expression which should only match correct attribute names in class -# bodies -class-attribute-rgx=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$ - -# Regular expression which should only match correct list comprehension / -# generator expression variable names -inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$ - -# Good variable names which should always be accepted, separated by a comma -good-names=i,j,k,ex,Run,_ - -# Bad variable names which should always be refused, separated by a comma -bad-names=foo,bar,baz,toto,tutu,tata - -# Regular expression which should only match function or class names that do -# not require a docstring. -no-docstring-rgx=.* - -# Minimum line length for functions/classes that require docstrings, shorter -# ones are exempt. -docstring-min-length=-1 - - -[FORMAT] - -# Maximum number of characters on a single line. -max-line-length=300 - -# Regexp for a line that is allowed to be longer than the limit. -ignore-long-lines=^\s*(# )??$ - -# Maximum number of lines in a module -max-module-lines=1000 - -# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1 -# tab). -indent-string=' ' - - -[MISCELLANEOUS] - -# List of note tags to take in consideration, separated by a comma. -notes=FIXME - - -[SIMILARITIES] - -# Minimum lines number of a similarity. -min-similarity-lines=4 - -# Ignore comments when computing similarities. -ignore-comments=yes - -# Ignore docstrings when computing similarities. -ignore-docstrings=yes - -# Ignore imports when computing similarities. -ignore-imports=no - - -[TYPECHECK] - -# Tells whether missing members accessed in mixin class should be ignored. A -# mixin class is detected if its name ends with "mixin" (case insensitive). -ignore-mixin-members=yes - -# List of classes names for which member attributes should not be checked -# (useful for classes with attributes dynamically set). -ignored-classes=SQLObject - -# When zope mode is activated, add a predefined set of Zope acquired attributes -# to generated-members. -zope=no - -# List of members which are set dynamically and missed by pylint inference -# system, and so shouldn't trigger E0201 when accessed. Python regular -# expressions are accepted. -generated-members=REQUEST,acl_users,aq_parent - - -[VARIABLES] - -# Tells whether we should check for unused import in __init__ files. -init-import=no - -# A regular expression matching the beginning of the name of dummy variables -# (i.e. not used). -dummy-variables-rgx=_$|dummy - -# List of additional names supposed to be defined in builtins. Remember that -# you should avoid to define new builtins when possible. -additional-builtins= - - -[CLASSES] - -# List of interface methods to ignore, separated by a comma. This is used for -# instance to not check methods defines in Zope's Interface base class. -ignore-iface-methods=isImplementedBy,deferred,extends,names,namesAndDescriptions,queryDescriptionFor,getBases,getDescriptionFor,getDoc,getName,getTaggedValue,getTaggedValueTags,isEqualOrExtendedBy,setTaggedValue,isImplementedByInstancesOf,adaptWith,is_implemented_by - -# List of method names used to declare (i.e. assign) instance attributes. -defining-attr-methods=__init__,__new__,setUp - -# List of valid names for the first argument in a class method. -valid-classmethod-first-arg=cls - -# List of valid names for the first argument in a metaclass class method. -valid-metaclass-classmethod-first-arg=mcs - - -[DESIGN] - -# Maximum number of arguments for function / method -max-args=5 - -# Argument names that match this expression will be ignored. Default to name -# with leading underscore -ignored-argument-names=_.* - -# Maximum number of locals for function / method body -max-locals=15 - -# Maximum number of return / yield for function / method body -max-returns=6 - -# Maximum number of branch for function / method body -max-branches=12 - -# Maximum number of statements in function / method body -max-statements=50 - -# Maximum number of parents for a class (see R0901). -max-parents=7 - -# Maximum number of attributes for a class (see R0902). -max-attributes=7 - -# Minimum number of public methods for a class (see R0903). -min-public-methods=2 - -# Maximum number of public methods for a class (see R0904). -max-public-methods=20 - - -[IMPORTS] - -# Deprecated modules which should not be used, separated by a comma -deprecated-modules=regsub,TERMIOS,Bastion,rexec - -# Create a graph of every (i.e. internal and external) dependencies in the -# given file (report RP0402 must not be disabled) -import-graph= - -# Create a graph of external dependencies in the given file (report RP0402 must -# not be disabled) -ext-import-graph= - -# Create a graph of internal dependencies in the given file (report RP0402 must -# not be disabled) -int-import-graph= - - -[EXCEPTIONS] - -# Exceptions that will emit a warning when being caught. Defaults to -# "Exception" -overgeneral-exceptions=Exception diff -r 91dbb0b7dc8b -r aff825fef0fd mx/commands.py --- a/mx/commands.py Fri Sep 06 21:37:50 2013 +0200 +++ b/mx/commands.py Wed Oct 02 13:26:31 2013 +0200 @@ -243,7 +243,7 @@ machine = platform.uname()[4] if machine in ['amd64', 'AMD64', 'x86_64', 'i86pc']: return 'amd64' - if machine in ['sun4v']: + if machine in ['sun4v', 'sun4u']: return 'sparc' if machine == 'i386' and mx.get_os() == 'darwin': try: @@ -345,8 +345,8 @@ pass else: if not exists(jdk): - if _installed_jdks and mx._opts.verbose: - mx.log("Could not find JDK directory at " + jdk) + if _installed_jdks: + mx.log("The selected JDK directory does not (yet) exist: " + jdk) _handle_missing_VM(build, vmToCheck if vmToCheck else 'graal') if installGraalJar: @@ -442,43 +442,14 @@ log.close() return ret -def pylint(args): - """run pylint (if available) over Python source files""" - rcfile = join(_graal_home, 'mx', '.pylintrc') - if not exists(rcfile): - mx.log('pylint configuration file does not exist: ' + rcfile) - return +def jdkhome(vm=None): + """return the JDK directory selected for the 'vm' command""" + build = _vmbuild if _vmSourcesAvailable else 'product' + return _jdk(build, installGraalJar=False) - try: - output = subprocess.check_output(['pylint', '--version'], stderr=subprocess.STDOUT) - m = re.match(r'.*pylint (\d+)\.(\d+)\.(\d+).*', output, re.DOTALL) - if not m: - mx.log('could not determine pylint version from ' + output) - return - major, minor, micro = (int(m.group(1)), int(m.group(2)), int(m.group(3))) - if major < 1: - mx.log('require pylint version >= 1 (got {0}.{1}.{2})'.format(major, minor, micro)) - return - except BaseException: - mx.log('pylint is not available') - return - - - env = os.environ.copy() - env['PYTHONPATH'] = dirname(mx.__file__) - - versioned = subprocess.check_output(['hg', 'locate', '-f'], stderr=subprocess.STDOUT).split(os.linesep) - for f in versioned: - if f.endswith('.py'): - pyfile = f - mx.log('Running pylint on ' + pyfile + '...') - mx.run(['pylint', '--reports=n', '--rcfile=' + rcfile, pyfile], env=env) - -def jdkhome(args, vm=None): +def print_jdkhome(args, vm=None): """print the JDK directory selected for the 'vm' command""" - - build = _vmbuild if _vmSourcesAvailable else 'product' - print _jdk(build, installGraalJar=False) + print jdkhome(vm) def buildvars(args): """describe the variables that can be set by the -D option to the 'mx build' commmand""" @@ -800,7 +771,7 @@ mx.abort('VM option ' + t + ' must precede ' + tests[0]) candidates = [] - for p in mx.projects(): + for p in mx.projects_opt_limit_to_suites(): if mx.java().javaCompliance < p.javaCompliance: continue candidates += _find_classes_with_annotations(p, None, annotations).keys() @@ -818,7 +789,7 @@ if not found: mx.log('warning: no tests matched by substring "' + t) - projectscp = mx.classpath([pcp.name for pcp in mx.projects() if pcp.javaCompliance <= mx.java().javaCompliance]) + projectscp = mx.classpath([pcp.name for pcp in mx.projects_opt_limit_to_suites() if pcp.javaCompliance <= mx.java().javaCompliance]) if len(classes) != 0: f_testfile = open(testfile, 'w') @@ -942,31 +913,103 @@ allDuration = datetime.timedelta(seconds=time.time() - allStart) mx.log('TOTAL TIME: ' + '[' + str(allDuration) + ']') -def gate(args): +class Task: + def __init__(self, title): + self.start = time.time() + self.title = title + self.end = None + self.duration = None + mx.log(time.strftime('gate: %d %b %Y %H:%M:%S: BEGIN: ') + title) + def stop(self): + self.end = time.time() + self.duration = datetime.timedelta(seconds=self.end - self.start) + mx.log(time.strftime('gate: %d %b %Y %H:%M:%S: END: ') + self.title + ' [' + str(self.duration) + ']') + return self + def abort(self, codeOrMessage): + self.end = time.time() + self.duration = datetime.timedelta(seconds=self.end - self.start) + mx.log(time.strftime('gate: %d %b %Y %H:%M:%S: ABORT: ') + self.title + ' [' + str(self.duration) + ']') + mx.abort(codeOrMessage) + return self + +def _basic_gate_body(args, tasks): + t = Task('BuildHotSpotGraal: fastdebug,product') + buildvms(['--vms', 'graal,server', '--builds', 'fastdebug,product']) + tasks.append(t.stop()) + + with VM('graal', 'fastdebug'): + t = Task('BootstrapWithSystemAssertions:fastdebug') + vm(['-esa', '-version']) + tasks.append(t.stop()) + + with VM('graal', 'product'): + t = Task('BootstrapWithGCVerification:product') + vm(['-XX:+UnlockDiagnosticVMOptions', '-XX:+VerifyBeforeGC', '-XX:+VerifyAfterGC', '-version']) + tasks.append(t.stop()) + + with VM('graal', 'product'): + t = Task('BootstrapWithG1GCVerification:product') + vm(['-XX:+UnlockDiagnosticVMOptions', '-XX:-UseSerialGC', '-XX:+UseG1GC', '-XX:+UseNewCode', '-XX:+VerifyBeforeGC', '-XX:+VerifyAfterGC', '-version']) + tasks.append(t.stop()) + + with VM('graal', 'product'): + t = Task('BootstrapWithRegisterPressure:product') + vm(['-G:RegisterPressure=rbx,r11,r10,r14,xmm3,xmm11,xmm14', '-esa', '-version']) + tasks.append(t.stop()) + + with VM('graal', 'product'): + t = Task('BootstrapWithAOTConfiguration:product') + vm(['-G:+AOTCompilation', '-G:+VerifyPhases', '-esa', '-version']) + tasks.append(t.stop()) + + with VM('server', 'product'): # hosted mode + t = Task('UnitTests:hosted-product') + unittest([]) + tasks.append(t.stop()) + + for vmbuild in ['fastdebug', 'product']: + for test in sanitycheck.getDacapos(level=sanitycheck.SanityCheckLevel.Gate, gateBuildLevel=vmbuild): + t = Task(str(test) + ':' + vmbuild) + if not test.test('graal'): + t.abort(test.name + ' Failed') + tasks.append(t.stop()) + + if args.jacocout is not None: + jacocoreport([args.jacocout]) + + global _jacoco + _jacoco = 'off' + + t = Task('CleanAndBuildGraalVisualizer') + mx.run(['ant', '-f', join(_graal_home, 'visualizer', 'build.xml'), '-q', 'clean', 'build']) + tasks.append(t.stop()) + + # Prevent Graal modifications from breaking the standard builds + if args.buildNonGraal: + t = Task('BuildHotSpotVarieties') + buildvms(['--vms', 'client,server', '--builds', 'fastdebug,product']) + buildvms(['--vms', 'server-nograal', '--builds', 'product']) + buildvms(['--vms', 'server-nograal', '--builds', 'optimized']) + tasks.append(t.stop()) + + for vmbuild in ['product', 'fastdebug']: + for theVm in ['client', 'server']: + with VM(theVm, vmbuild): + t = Task('DaCapo_pmd:' + theVm + ':' + vmbuild) + dacapo(['pmd']) + tasks.append(t.stop()) + + t = Task('UnitTests:' + theVm + ':' + vmbuild) + unittest(['-XX:CompileCommand=exclude,*::run*', 'graal.api']) + tasks.append(t.stop()) + + +def gate(args, gate_body=_basic_gate_body): """run the tests used to validate a push If this command exits with a 0 exit code, then the source code is in a state that would be accepted for integration into the main repository.""" - class Task: - def __init__(self, title): - self.start = time.time() - self.title = title - self.end = None - self.duration = None - mx.log(time.strftime('gate: %d %b %Y %H:%M:%S: BEGIN: ') + title) - def stop(self): - self.end = time.time() - self.duration = datetime.timedelta(seconds=self.end - self.start) - mx.log(time.strftime('gate: %d %b %Y %H:%M:%S: END: ') + self.title + ' [' + str(self.duration) + ']') - return self - def abort(self, codeOrMessage): - self.end = time.time() - self.duration = datetime.timedelta(seconds=self.end - self.start) - mx.log(time.strftime('gate: %d %b %Y %H:%M:%S: ABORT: ') + self.title + ' [' + str(self.duration) + ']') - mx.abort(codeOrMessage) - return self - parser = ArgumentParser(prog='mx gate') parser.add_argument('-j', '--omit-java-clean', action='store_false', dest='cleanJava', help='omit cleaning Java native code') parser.add_argument('-n', '--omit-native-clean', action='store_false', dest='cleanNative', help='omit cleaning and building native code') @@ -982,7 +1025,7 @@ try: t = Task('Pylint') - pylint([]) + mx.pylint([]) tasks.append(t.stop()) t = Task('Clean') @@ -1029,74 +1072,7 @@ else: _jacoco = 'off' - t = Task('BuildHotSpotGraal: fastdebug,product') - buildvms(['--vms', 'graal,server', '--builds', 'fastdebug,product']) - tasks.append(t.stop()) - - with VM('graal', 'fastdebug'): - t = Task('BootstrapWithSystemAssertions:fastdebug') - vm(['-esa', '-version']) - tasks.append(t.stop()) - - with VM('graal', 'product'): - t = Task('BootstrapWithGCVerification:product') - vm(['-XX:+UnlockDiagnosticVMOptions', '-XX:+VerifyBeforeGC', '-XX:+VerifyAfterGC', '-version']) - tasks.append(t.stop()) - - with VM('graal', 'product'): - t = Task('BootstrapWithG1GCVerification:product') - vm(['-XX:+UnlockDiagnosticVMOptions', '-XX:-UseSerialGC', '-XX:+UseG1GC', '-XX:+UseNewCode', '-XX:+VerifyBeforeGC', '-XX:+VerifyAfterGC', '-version']) - tasks.append(t.stop()) - - with VM('graal', 'product'): - t = Task('BootstrapWithRegisterPressure:product') - vm(['-G:RegisterPressure=rbx,r11,r10,r14,xmm3,xmm11,xmm14', '-esa', '-version']) - tasks.append(t.stop()) - - with VM('graal', 'product'): - t = Task('BootstrapWithAOTConfiguration:product') - vm(['-G:+AOTCompilation', '-G:+VerifyPhases', '-esa', '-version']) - tasks.append(t.stop()) - - with VM('server', 'product'): # hosted mode - t = Task('UnitTests:hosted-product') - unittest([]) - tasks.append(t.stop()) - - for vmbuild in ['fastdebug', 'product']: - for test in sanitycheck.getDacapos(level=sanitycheck.SanityCheckLevel.Gate, gateBuildLevel=vmbuild): - t = Task(str(test) + ':' + vmbuild) - if not test.test('graal'): - t.abort(test.name + ' Failed') - tasks.append(t.stop()) - - if args.jacocout is not None: - jacocoreport([args.jacocout]) - - _jacoco = 'off' - - t = Task('CleanAndBuildGraalVisualizer') - mx.run(['ant', '-f', join(_graal_home, 'visualizer', 'build.xml'), '-q', 'clean', 'build']) - tasks.append(t.stop()) - - # Prevent Graal modifications from breaking the standard builds - if args.buildNonGraal: - t = Task('BuildHotSpotVarieties') - buildvms(['--vms', 'client,server', '--builds', 'fastdebug,product']) - buildvms(['--vms', 'server-nograal', '--builds', 'product']) - buildvms(['--vms', 'server-nograal', '--builds', 'optimized']) - tasks.append(t.stop()) - - for vmbuild in ['product', 'fastdebug']: - for theVm in ['client', 'server']: - with VM(theVm, vmbuild): - t = Task('DaCapo_pmd:' + theVm + ':' + vmbuild) - dacapo(['pmd']) - tasks.append(t.stop()) - - t = Task('UnitTests:' + theVm + ':' + vmbuild) - unittest(['-XX:CompileCommand=exclude,*::run*', 'graal.api']) - tasks.append(t.stop()) + gate_body(args, tasks) except KeyboardInterrupt: total.abort(1) @@ -1358,7 +1334,7 @@ '--title', 'Graal OpenJDK Project Documentation', '--dot-output-base', 'projects'] + args) -def mx_init(): +def mx_init(suite): commands = { 'build': [build, ''], 'buildvars': [buildvars, ''], @@ -1367,8 +1343,7 @@ 'hsdis': [hsdis, '[att]'], 'hcfdis': [hcfdis, ''], 'igv' : [igv, ''], - 'jdkhome': [jdkhome, ''], - 'pylint': [pylint, ''], + 'jdkhome': [print_jdkhome, ''], 'dacapo': [dacapo, '[VM options] benchmarks...|"all" [DaCapo options]'], 'scaladacapo': [scaladacapo, '[VM options] benchmarks...|"all" [Scala DaCapo options]'], 'specjvm2008': [specjvm2008, '[VM options] benchmarks...|"all" [SPECjvm2008 options]'], @@ -1406,7 +1381,7 @@ 'export': [export, '[-options] [zipfile]'], }) - mx._commands.update(commands) + mx.update_commands(suite, commands) def mx_post_parse_cmd_line(opts): # # TODO _minVersion check could probably be part of a Suite in mx? diff -r 91dbb0b7dc8b -r aff825fef0fd mx/eclipse-settings/org.eclipse.jdt.core.prefs --- a/mx/eclipse-settings/org.eclipse.jdt.core.prefs Fri Sep 06 21:37:50 2013 +0200 +++ b/mx/eclipse-settings/org.eclipse.jdt.core.prefs Wed Oct 02 13:26:31 2013 +0200 @@ -157,7 +157,7 @@ org.eclipse.jdt.core.formatter.blank_lines_after_imports=1 org.eclipse.jdt.core.formatter.blank_lines_after_package=1 org.eclipse.jdt.core.formatter.blank_lines_before_field=0 -org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=1 +org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0 org.eclipse.jdt.core.formatter.blank_lines_before_imports=1 org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1 org.eclipse.jdt.core.formatter.blank_lines_before_method=1 diff -r 91dbb0b7dc8b -r aff825fef0fd mx/projects --- a/mx/projects Fri Sep 06 21:37:50 2013 +0200 +++ b/mx/projects Wed Oct 02 13:26:31 2013 +0200 @@ -28,7 +28,7 @@ library@OKRA@urls=http://cr.openjdk.java.net/~tdeneau/okra-1.2.jar distribution@GRAAL@path=graal.jar -distribution@GRAAL@dependencies=com.oracle.graal.hotspot.amd64,com.oracle.graal.truffle,com.oracle.graal.truffle.printer,com.oracle.graal.hotspot.sparc,com.oracle.graal.hotspot,com.oracle.graal.compiler.hsail +distribution@GRAAL@dependencies=com.oracle.graal.hotspot.amd64,com.oracle.graal.hotspot.ptx,com.oracle.graal.truffle,com.oracle.graal.truffle.printer,com.oracle.graal.hotspot.sparc,com.oracle.graal.hotspot,com.oracle.graal.compiler.hsail # graal.api.runtime project@com.oracle.graal.api.runtime@subDir=graal @@ -134,6 +134,15 @@ project@com.oracle.graal.hotspot.sparc@javaCompliance=1.7 project@com.oracle.graal.hotspot.sparc@workingSets=Graal,HotSpot,SPARC +# graal.hotspot.ptx +project@com.oracle.graal.hotspot.ptx@subDir=graal +project@com.oracle.graal.hotspot.ptx@sourceDirs=src +project@com.oracle.graal.hotspot.ptx@dependencies=com.oracle.graal.hotspot,com.oracle.graal.ptx +project@com.oracle.graal.hotspot.ptx@checkstyle=com.oracle.graal.graph +project@com.oracle.graal.hotspot.ptx@annotationProcessors=com.oracle.graal.service.processor +project@com.oracle.graal.hotspot.ptx@javaCompliance=1.7 +project@com.oracle.graal.hotspot.ptx@workingSets=Graal,HotSpot,PTX + # graal.hotspot.server project@com.oracle.graal.hotspot.server@subDir=graal project@com.oracle.graal.hotspot.server@sourceDirs=src @@ -177,7 +186,7 @@ # graal.graph project@com.oracle.graal.graph@subDir=graal project@com.oracle.graal.graph@sourceDirs=src -project@com.oracle.graal.graph@dependencies= +project@com.oracle.graal.graph@dependencies=com.oracle.graal.debug project@com.oracle.graal.graph@javaCompliance=1.7 project@com.oracle.graal.graph@workingSets=Graal,Graph @@ -223,7 +232,7 @@ # graal.lir.ptx project@com.oracle.graal.lir.ptx@subDir=graal project@com.oracle.graal.lir.ptx@sourceDirs=src -project@com.oracle.graal.lir.ptx@dependencies=com.oracle.graal.asm.ptx,com.oracle.graal.lir +project@com.oracle.graal.lir.ptx@dependencies=com.oracle.graal.asm.ptx project@com.oracle.graal.lir.ptx@checkstyle=com.oracle.graal.graph project@com.oracle.graal.lir.ptx@javaCompliance=1.7 project@com.oracle.graal.lir.ptx@workingSets=Graal,LIR,PTX @@ -288,7 +297,7 @@ # graal.nodes project@com.oracle.graal.nodes@subDir=graal project@com.oracle.graal.nodes@sourceDirs=src -project@com.oracle.graal.nodes@dependencies=com.oracle.graal.graph,com.oracle.graal.debug,com.oracle.graal.api.replacements,com.oracle.graal.api.code +project@com.oracle.graal.nodes@dependencies=com.oracle.graal.graph,com.oracle.graal.api.replacements,com.oracle.graal.api.code project@com.oracle.graal.nodes@checkstyle=com.oracle.graal.graph project@com.oracle.graal.nodes@javaCompliance=1.7 project@com.oracle.graal.nodes@workingSets=Graal,Graph @@ -369,7 +378,7 @@ # graal.compiler.ptx.test project@com.oracle.graal.compiler.ptx.test@subDir=graal project@com.oracle.graal.compiler.ptx.test@sourceDirs=src -project@com.oracle.graal.compiler.ptx.test@dependencies=com.oracle.graal.compiler.ptx,com.oracle.graal.compiler.test,com.oracle.graal.ptx +project@com.oracle.graal.compiler.ptx.test@dependencies=com.oracle.graal.hotspot.ptx,com.oracle.graal.compiler.ptx,com.oracle.graal.compiler.test project@com.oracle.graal.compiler.ptx.test@checkstyle=com.oracle.graal.graph project@com.oracle.graal.compiler.ptx.test@javaCompliance=1.7 project@com.oracle.graal.compiler.ptx.test@workingSets=Graal,PTX,Test @@ -531,7 +540,7 @@ # graal.asm.ptx project@com.oracle.graal.asm.ptx@subDir=graal project@com.oracle.graal.asm.ptx@sourceDirs=src -project@com.oracle.graal.asm.ptx@dependencies=com.oracle.graal.asm +project@com.oracle.graal.asm.ptx@dependencies=com.oracle.graal.lir project@com.oracle.graal.asm.ptx@checkstyle=com.oracle.graal.graph project@com.oracle.graal.asm.ptx@javaCompliance=1.7 project@com.oracle.graal.asm.ptx@workingSets=Graal,Assembler,PTX diff -r 91dbb0b7dc8b -r aff825fef0fd mx/sanitycheck.py --- a/mx/sanitycheck.py Fri Sep 06 21:37:50 2013 +0200 +++ b/mx/sanitycheck.py Wed Oct 02 13:26:31 2013 +0200 @@ -252,13 +252,15 @@ return Test("Scala-DaCapo-" + name, ['-jar', dacapo, name] + _noneAsEmptyList(dacapoArgs), [dacapoSuccess], [dacapoFail], [dacapoMatcher], ['-Xms2g', '-XX:+' + gc, '-XX:-UseCompressedOops']) def getBootstraps(): - time = re.compile(r"Bootstrapping Graal\.+ in (?P

predecessors; private List
successors; + private List subgraphs; private Color color; private int id; private String idString; @@ -177,6 +179,14 @@ successors.remove(f); } + public List getSubgraphs() { + return subgraphs; + } + + public void setSubgraphs(List subgraphs) { + this.subgraphs = subgraphs; + } + @Override public void setPosition(Point p) { this.position = p; diff -r 91dbb0b7dc8b -r aff825fef0fd src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/EditorTopComponent.java --- a/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/EditorTopComponent.java Fri Sep 06 21:37:50 2013 +0200 +++ b/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/EditorTopComponent.java Wed Oct 02 13:26:31 2013 +0200 @@ -69,7 +69,7 @@ import org.openide.windows.WindowManager; /** - * + * * @author Thomas Wuerthinger */ public final class EditorTopComponent extends TopComponent implements PropertyChangeListener { @@ -140,7 +140,7 @@ }; private ChangedEvent diagramChangedEvent = new ChangedEvent<>(diagramProvider); - + private void updateDisplayName() { setDisplayName(getDiagram().getName()); @@ -254,6 +254,11 @@ toolBar.add(Box.createHorizontalGlue()); Action action = Utilities.actionsForPath("QuickSearchShadow").get(0); Component quicksearch = ((Presenter.Toolbar) action).getToolbarPresenter(); + try { + // (aw) workaround for disappearing search bar due to reparenting one shared component instance. + quicksearch = (Component) quicksearch.getClass().getConstructor(KeyStroke.class).newInstance(new Object[]{null}); + } catch (ReflectiveOperationException | IllegalArgumentException | SecurityException e) { + } quicksearch.setMinimumSize(quicksearch.getPreferredSize()); // necessary for GTK LAF toolBar.add(quicksearch); @@ -420,7 +425,7 @@ graphContent.set(list, null); diagramProvider.getChangedEvent().fire(); } - + }; public boolean showPredSucc() { diff -r 91dbb0b7dc8b -r aff825fef0fd src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/widgets/FigureWidget.java --- a/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/widgets/FigureWidget.java Fri Sep 06 21:37:50 2013 +0200 +++ b/src/share/tools/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/widgets/FigureWidget.java Wed Oct 02 13:26:31 2013 +0200 @@ -23,16 +23,20 @@ */ package com.sun.hotspot.igv.view.widgets; +import com.sun.hotspot.igv.data.InputGraph; import com.sun.hotspot.igv.data.Properties; +import com.sun.hotspot.igv.data.services.GraphViewer; import com.sun.hotspot.igv.graph.Figure; import com.sun.hotspot.igv.util.DoubleClickAction; import com.sun.hotspot.igv.util.DoubleClickHandler; import com.sun.hotspot.igv.util.PropertiesSheet; import com.sun.hotspot.igv.view.DiagramScene; import java.awt.*; +import java.awt.event.ActionEvent; import java.util.ArrayList; import java.util.HashSet; import java.util.Set; +import javax.swing.AbstractAction; import javax.swing.Action; import javax.swing.BorderFactory; import javax.swing.JMenu; @@ -49,6 +53,7 @@ import org.openide.nodes.Children; import org.openide.nodes.Node; import org.openide.nodes.Sheet; +import org.openide.util.Lookup; /** * @@ -272,6 +277,27 @@ successors.addMenuListener(new NeighborMenuListener(successors, getFigure(), true)); menu.add(successors); + if (getFigure().getSubgraphs() != null) { + menu.addSeparator(); + JMenu subgraphs = new JMenu("Subgraphs"); + menu.add(subgraphs); + + final GraphViewer viewer = Lookup.getDefault().lookup(GraphViewer.class); + for(final InputGraph subgraph : getFigure().getSubgraphs()) { + Action a = new AbstractAction() { + + @Override + public void actionPerformed(ActionEvent e) { + viewer.view(subgraph, true); + } + }; + + a.setEnabled(true); + a.putValue(Action.NAME, subgraph.getName()); + subgraphs.add(a); + } + } + return menu; } diff -r 91dbb0b7dc8b -r aff825fef0fd src/share/vm/classfile/vmSymbols.hpp --- a/src/share/vm/classfile/vmSymbols.hpp Fri Sep 06 21:37:50 2013 +0200 +++ b/src/share/vm/classfile/vmSymbols.hpp Wed Oct 02 13:26:31 2013 +0200 @@ -311,6 +311,7 @@ template(com_oracle_graal_hotspot_meta_HotSpotResolvedObjectType, "com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType") \ template(com_oracle_graal_hotspot_meta_HotSpotMonitorValue, "com/oracle/graal/hotspot/meta/HotSpotMonitorValue") \ template(com_oracle_graal_hotspot_debug_LocalImpl, "com/oracle/graal/hotspot/debug/LocalImpl") \ + template(com_oracle_graal_hotspot_ptx_PTXHotSpotGraalRuntime, "com/oracle/graal/hotspot/ptx/PTXHotSpotGraalRuntime")\ AMD64_ONLY(template(com_oracle_graal_hotspot_amd64_AMD64HotSpotGraalRuntime,"com/oracle/graal/hotspot/amd64/AMD64HotSpotGraalRuntime"))\ SPARC_ONLY(template(com_oracle_graal_hotspot_sparc_SPARCHotSpotGraalRuntime,"com/oracle/graal/hotspot/sparc/SPARCHotSpotGraalRuntime"))\ /* graal.api.meta */ \ @@ -356,6 +357,7 @@ template(compileMethod_signature, "(JLcom/oracle/graal/hotspot/meta/HotSpotResolvedObjectType;IZ)V") \ template(setOption_name, "setOption") \ template(setOption_signature, "(Ljava/lang/String;)Z") \ + template(finalizeOptions_name, "finalizeOptions") \ template(createUnresolvedJavaMethod_name, "createUnresolvedJavaMethod") \ template(createUnresolvedJavaMethod_signature, "(Ljava/lang/String;Ljava/lang/String;Lcom/oracle/graal/api/meta/JavaType;)Lcom/oracle/graal/api/meta/JavaMethod;") \ template(createSignature_name, "createSignature") \ diff -r 91dbb0b7dc8b -r aff825fef0fd src/share/vm/graal/graalCodeInstaller.cpp --- a/src/share/vm/graal/graalCodeInstaller.cpp Fri Sep 06 21:37:50 2013 +0200 +++ b/src/share/vm/graal/graalCodeInstaller.cpp Wed Oct 02 13:26:31 2013 +0200 @@ -727,7 +727,7 @@ oop debug_info = CompilationResult_Call::debugInfo(site); - assert((hotspot_method ? 1 : 0) + (foreign_call ? 1 : 0) == 1, "Call site needs exactly one type"); + assert(!!hotspot_method ^ !!foreign_call, "Call site needs exactly one type"); NativeInstruction* inst = nativeInstruction_at(_instructions->start() + pc_offset); jint next_pc_offset = CodeInstaller::pd_next_offset(inst, pc_offset, hotspot_method); @@ -810,27 +810,11 @@ _next_call_type = (MarkId) id; _invoke_mark_pc = pc; break; - case MARK_POLL_NEAR: { - NativeInstruction* ni = nativeInstruction_at(pc); - int32_t* disp = (int32_t*) pd_locate_operand(pc); - // int32_t* disp = (int32_t*) Assembler::locate_operand(instruction, Assembler::disp32_operand); - int32_t offset = *disp; // The Java code installed the polling page offset into the disp32 operand - intptr_t new_disp = (intptr_t) (os::get_polling_page() + offset) - (intptr_t) ni; - *disp = (int32_t)new_disp; - } + case MARK_POLL_NEAR: case MARK_POLL_FAR: - _instructions->relocate(pc, relocInfo::poll_type); - break; - case MARK_POLL_RETURN_NEAR: { - NativeInstruction* ni = nativeInstruction_at(pc); - int32_t* disp = (int32_t*) pd_locate_operand(pc); - // int32_t* disp = (int32_t*) Assembler::locate_operand(instruction, Assembler::disp32_operand); - int32_t offset = *disp; // The Java code installed the polling page offset into the disp32 operand - intptr_t new_disp = (intptr_t) (os::get_polling_page() + offset) - (intptr_t) ni; - *disp = (int32_t)new_disp; - } + case MARK_POLL_RETURN_NEAR: case MARK_POLL_RETURN_FAR: - _instructions->relocate(pc, relocInfo::poll_return_type); + pd_relocate_poll(pc, id); break; default: ShouldNotReachHere(); diff -r 91dbb0b7dc8b -r aff825fef0fd src/share/vm/graal/graalCodeInstaller.hpp --- a/src/share/vm/graal/graalCodeInstaller.hpp Fri Sep 06 21:37:50 2013 +0200 +++ b/src/share/vm/graal/graalCodeInstaller.hpp Wed Oct 02 13:26:31 2013 +0200 @@ -80,7 +80,7 @@ void pd_relocate_CodeBlob(CodeBlob* cb, NativeInstruction* inst); void pd_relocate_ForeignCall(NativeInstruction* inst, jlong foreign_call_destination); void pd_relocate_JavaMethod(oop method, jint pc_offset); - int32_t* pd_locate_operand(address instruction); + void pd_relocate_poll(address pc, jint mark); public: diff -r 91dbb0b7dc8b -r aff825fef0fd src/share/vm/graal/graalCompiler.cpp --- a/src/share/vm/graal/graalCompiler.cpp Fri Sep 06 21:37:50 2013 +0200 +++ b/src/share/vm/graal/graalCompiler.cpp Wed Oct 02 13:26:31 2013 +0200 @@ -95,6 +95,8 @@ vm_abort(false); } } + VMToCompiler::finalizeOptions(CITime); + if (UseCompiler) { VMToCompiler::startCompiler(BootstrapGraal); _initialized = true; diff -r 91dbb0b7dc8b -r aff825fef0fd src/share/vm/graal/graalCompilerToGPU.cpp --- a/src/share/vm/graal/graalCompilerToGPU.cpp Fri Sep 06 21:37:50 2013 +0200 +++ b/src/share/vm/graal/graalCompilerToGPU.cpp Wed Oct 02 13:26:31 2013 +0200 @@ -28,7 +28,7 @@ #include "graal/graalJavaAccess.hpp" #include "runtime/gpu.hpp" #include "runtime/javaCalls.hpp" -# include "ptx/vm/kernelArguments.hpp" +# include "ptx/vm/ptxKernelArguments.hpp" // Entry to native method implementation that transitions current thread to '_thread_in_vm'. #define C2V_VMENTRY(result_type, name, signature) \ @@ -103,6 +103,45 @@ C2V_END +C2V_VMENTRY(jobject, executeParallelMethodVarargs, (JNIEnv *env, + jobject, + jint dimX, jint dimY, jint dimZ, + jobject args, jobject hotspotInstalledCode)) + ResourceMark rm; + HandleMark hm; + + if (gpu::is_available() == false || gpu::has_gpu_linkage() == false && gpu::is_initialized()) { + tty->print_cr("executeParallelMethodVarargs - not available / no linkage / not initialized"); + return NULL; + } + jlong nmethodValue = HotSpotInstalledCode::codeBlob(hotspotInstalledCode); + nmethod* nm = (nmethod*) (address) nmethodValue; + methodHandle mh = nm->method(); + Symbol* signature = mh->signature(); + + // start value is the kernel + jlong startValue = HotSpotInstalledCode::codeStart(hotspotInstalledCode); + + PTXKernelArguments ptxka(signature, (arrayOop) JNIHandles::resolve(args), mh->is_static()); + JavaValue result(ptxka.get_ret_type()); +if (!gpu::execute_warp(dimX, dimY, dimZ, (address)startValue, ptxka, result)) { + return NULL; + } + + if (ptxka.get_ret_type() == T_VOID) { + return NULL; + } else if (ptxka.get_ret_type() == T_OBJECT || ptxka.get_ret_type() == T_ARRAY) { + return JNIHandles::make_local((oop) result.get_jobject()); + } else { + oop o = java_lang_boxing_object::create(ptxka.get_ret_type(), (jvalue *) result.get_value_addr(), CHECK_NULL); + if (TraceGPUInteraction) { + tty->print_cr("GPU execution returned %d", result.get_jint()); + } + return JNIHandles::make_local(o); + } + +C2V_END + C2V_VMENTRY(jboolean, deviceInit, (JNIEnv *env, jobject)) if (gpu::is_available() == false || gpu::has_gpu_linkage() == false) { tty->print_cr("deviceInit - not available / no linkage"); @@ -116,6 +155,14 @@ return gpu::is_initialized(); C2V_END +C2V_VMENTRY(jint, availableProcessors, (JNIEnv *env, jobject)) + if (gpu::is_available() == false || gpu::has_gpu_linkage() == false) { + tty->print_cr("deviceInit - not available / no linkage"); + return false; + } + return gpu::available_processors(); +C2V_END + C2V_VMENTRY(jboolean, deviceDetach, (JNIEnv *env, jobject)) return true; C2V_END @@ -157,10 +204,12 @@ #define GPUSPACE_METHOD "J" JNINativeMethod CompilerToGPU_methods[] = { - {CC"generateKernel", CC"([B" STRING ")"GPUSPACE_METHOD, FN_PTR(generateKernel)}, - {CC"deviceInit", CC"()Z", FN_PTR(deviceInit)}, - {CC"deviceDetach", CC"()Z", FN_PTR(deviceDetach)}, - {CC"executeExternalMethodVarargs", CC"(["OBJECT HS_INSTALLED_CODE")"OBJECT, FN_PTR(executeExternalMethodVarargs)}, + {CC"generateKernel", CC"([B" STRING ")"GPUSPACE_METHOD, FN_PTR(generateKernel)}, + {CC"deviceInit", CC"()Z", FN_PTR(deviceInit)}, + {CC"deviceDetach", CC"()Z", FN_PTR(deviceDetach)}, + {CC"availableProcessors", CC"()I", FN_PTR(availableProcessors)}, + {CC"executeExternalMethodVarargs", CC"(["OBJECT HS_INSTALLED_CODE")"OBJECT, FN_PTR(executeExternalMethodVarargs)}, + {CC"executeParallelMethodVarargs", CC"(III["OBJECT HS_INSTALLED_CODE")"OBJECT, FN_PTR(executeParallelMethodVarargs)}, }; int CompilerToGPU_methods_count() { diff -r 91dbb0b7dc8b -r aff825fef0fd src/share/vm/graal/graalVMToCompiler.cpp --- a/src/share/vm/graal/graalVMToCompiler.cpp Fri Sep 06 21:37:50 2013 +0200 +++ b/src/share/vm/graal/graalVMToCompiler.cpp Wed Oct 02 13:26:31 2013 +0200 @@ -24,6 +24,7 @@ #include "precompiled.hpp" #include "classfile/systemDictionary.hpp" #include "graal/graalVMToCompiler.hpp" +#include "runtime/gpu.hpp" // this is a *global* handle jobject VMToCompiler::_graalRuntimePermObject = NULL; @@ -60,7 +61,16 @@ Handle VMToCompiler::graalRuntime() { if (JNIHandles::resolve(_graalRuntimePermObject) == NULL) { #ifdef AMD64 - Symbol* name = vmSymbols::com_oracle_graal_hotspot_amd64_AMD64HotSpotGraalRuntime(); + Symbol* name = NULL; + // Set name to PTXHotSpotRuntime if nVidia GPU was detected. + if (UseGPU && (gpu::get_target_il_type() == gpu::PTX) && + gpu::is_available() && gpu::has_gpu_linkage()) { + name = vmSymbols::com_oracle_graal_hotspot_ptx_PTXHotSpotGraalRuntime(); + } + + if (name == NULL) { + name = vmSymbols::com_oracle_graal_hotspot_amd64_AMD64HotSpotGraalRuntime(); + } #endif #ifdef SPARC Symbol* name = vmSymbols::com_oracle_graal_hotspot_sparc_SPARCHotSpotGraalRuntime(); @@ -90,23 +100,33 @@ } void VMToCompiler::initOptions() { - KlassHandle compilerKlass = loadClass(vmSymbols::com_oracle_graal_hotspot_HotSpotOptions()); + KlassHandle optionsKlass = loadClass(vmSymbols::com_oracle_graal_hotspot_HotSpotOptions()); Thread* THREAD = Thread::current(); - compilerKlass->initialize(THREAD); + optionsKlass->initialize(THREAD); check_pending_exception("Error while calling initOptions"); } jboolean VMToCompiler::setOption(Handle option) { assert(!option.is_null(), ""); - KlassHandle compilerKlass = loadClass(vmSymbols::com_oracle_graal_hotspot_HotSpotOptions()); + KlassHandle optionsKlass = loadClass(vmSymbols::com_oracle_graal_hotspot_HotSpotOptions()); Thread* THREAD = Thread::current(); JavaValue result(T_BOOLEAN); - JavaCalls::call_static(&result, compilerKlass, vmSymbols::setOption_name(), vmSymbols::setOption_signature(), option, THREAD); + JavaCalls::call_static(&result, optionsKlass, vmSymbols::setOption_name(), vmSymbols::setOption_signature(), option, THREAD); check_pending_exception("Error while calling setOption"); return result.get_jboolean(); } +void VMToCompiler::finalizeOptions(jboolean ciTime) { + KlassHandle optionsKlass = loadClass(vmSymbols::com_oracle_graal_hotspot_HotSpotOptions()); + Thread* THREAD = Thread::current(); + JavaValue result(T_VOID); + JavaCallArguments args; + args.push_int(ciTime); + JavaCalls::call_static(&result, optionsKlass, vmSymbols::finalizeOptions_name(), vmSymbols::bool_void_signature(), &args, THREAD); + check_pending_exception("Error while calling finalizeOptions"); +} + void VMToCompiler::compileMethod(Method* method, Handle holder, int entry_bci, jboolean blocking) { assert(method != NULL, "just checking"); assert(!holder.is_null(), "just checking"); diff -r 91dbb0b7dc8b -r aff825fef0fd src/share/vm/graal/graalVMToCompiler.hpp --- a/src/share/vm/graal/graalVMToCompiler.hpp Fri Sep 06 21:37:50 2013 +0200 +++ b/src/share/vm/graal/graalVMToCompiler.hpp Wed Oct 02 13:26:31 2013 +0200 @@ -57,6 +57,9 @@ // public static boolean HotSpotOptions.setOption(String option); static jboolean setOption(Handle option); + // public static void HotSpotOptions.finalizeOptions(boolean ciTime); + static void finalizeOptions(jboolean ciTime); + // public abstract boolean compileMethod(long vmId, String name, int entry_bci, boolean blocking); static void compileMethod(Method* method, Handle holder, int entry_bci, jboolean blocking); diff -r 91dbb0b7dc8b -r aff825fef0fd src/share/vm/runtime/globals.hpp --- a/src/share/vm/runtime/globals.hpp Fri Sep 06 21:37:50 2013 +0200 +++ b/src/share/vm/runtime/globals.hpp Wed Oct 02 13:26:31 2013 +0200 @@ -3717,8 +3717,11 @@ product(bool , AllowNonVirtualCalls, false, \ "Obey the ACC_SUPER flag and allow invokenonvirtual calls") \ \ - product(bool, TraceGPUInteraction, false, \ - "Trace external GPU warp loading") \ + product(bool, TraceGPUInteraction, false, \ + "Trace external GPU Interaction") \ + \ + product(bool, UseGPU, false, \ + "Run code on GPU") \ \ diagnostic(ccstr, SharedArchiveFile, NULL, \ "Override the default location of the CDS archive file") \ diff -r 91dbb0b7dc8b -r aff825fef0fd src/share/vm/runtime/gpu.cpp --- a/src/share/vm/runtime/gpu.cpp Fri Sep 06 21:37:50 2013 +0200 +++ b/src/share/vm/runtime/gpu.cpp Wed Oct 02 13:26:31 2013 +0200 @@ -25,14 +25,69 @@ #include "precompiled.hpp" #include "runtime/gpu.hpp" -bool gpu::_available = false; // does the hardware exist? -bool gpu::_gpu_linkage = false; // is the driver library to access the GPU installed -bool gpu::_initialized = false; // is the GPU device initialized +bool gpu::_available = false; // does the hardware exist? +bool gpu::_gpu_linkage = false; // is the driver library to access the GPU installed +bool gpu::_initialized = false; // is the GPU device initialized +gpu::TargetGPUIL gpu::_targetIL = gpu::NONE; // No GPU detected yet. void gpu::init() { #if defined(TARGET_OS_FAMILY_bsd) || defined(TARGET_OS_FAMILY_linux) gpu::probe_gpu(); + if (gpu::get_target_il_type() == gpu::PTX) { + set_gpu_linkage(gpu::Ptx::probe_linkage()); + } else { + set_gpu_linkage(false); + } #endif - // need multi-gpu TARGET ifdef - gpu::probe_linkage(); +} + +void gpu::initialize_gpu() { + if (gpu::has_gpu_linkage()) { + if (gpu::get_target_il_type() == gpu::PTX) { + set_initialized(gpu::Ptx::initialize_gpu()); + } + // Add initialization of other GPUs here + } +} + +void * gpu::generate_kernel(unsigned char *code, int code_len, const char *name) { + if (gpu::has_gpu_linkage()) { + if (gpu::get_target_il_type() == gpu::PTX) { + return (gpu::Ptx::generate_kernel(code, code_len, name)); + } + // Add kernel generation functionality of other GPUs here + } + return NULL; } + +bool gpu::execute_kernel(address kernel, PTXKernelArguments & ptxka, JavaValue& ret) { + if (gpu::has_gpu_linkage()) { + if (gpu::get_target_il_type() == gpu::PTX) { + return (gpu::Ptx::execute_kernel(kernel, ptxka, ret)); + } + // Add kernel execution functionality of other GPUs here + } + return false; +} + +bool gpu::execute_warp(int dimX, int dimY, int dimZ, + address kernel, PTXKernelArguments & ptxka, JavaValue& ret) { + if (gpu::has_gpu_linkage()) { + if (gpu::get_target_il_type() == gpu::PTX) { + return (gpu::Ptx::execute_warp(dimX, dimY, dimZ, kernel, ptxka, ret)); + } + // Add kernel execution functionality of other GPUs here + } + return false; +} + +int gpu::available_processors() { + if (gpu::has_gpu_linkage()) { + if (gpu::get_target_il_type() == gpu::PTX) { + return (gpu::Ptx::total_cores()); + } + // Add kernel execution functionality of other GPUs here + } + return 0; +} + diff -r 91dbb0b7dc8b -r aff825fef0fd src/share/vm/runtime/gpu.hpp --- a/src/share/vm/runtime/gpu.hpp Fri Sep 06 21:37:50 2013 +0200 +++ b/src/share/vm/runtime/gpu.hpp Wed Oct 02 13:26:31 2013 +0200 @@ -36,16 +36,21 @@ class gpu: AllStatic { public: + + enum TargetGPUIL { NONE = 0, PTX = 1, HSAIL = 2}; static void init(void); static void probe_gpu(); - static void probe_linkage(); - static void initialize_gpu(); + + static int available_processors(); static void * generate_kernel(unsigned char *code, int code_len, const char *name); + static bool execute_warp(int dimX, int dimY, int dimZ, + address kernel, PTXKernelArguments & ptxka, JavaValue & ret); + static bool execute_kernel(address kernel, PTXKernelArguments & ptxka, JavaValue & ret); static void set_available(bool value) { @@ -66,10 +71,19 @@ static bool has_gpu_linkage() { return _gpu_linkage; } + static void set_target_il_type(TargetGPUIL value) { + _targetIL = value; + } + + static enum gpu::TargetGPUIL get_target_il_type() { + return _targetIL; + } + protected: static bool _available; static bool _gpu_linkage; static bool _initialized; + static TargetGPUIL _targetIL; // Platform dependent stuff #ifdef TARGET_OS_FAMILY_linux