# HG changeset patch # User Christos Kotselidis # Date 1372062341 -7200 # Node ID 5db21405c6a49f63f33425f64be4977c6182ccc7 # Parent 0eeb9f8dab9b280bee938617674411c7ddde5188# Parent dcbdf71c450741cfce91dfd9265e359f593af34f Merge diff -r 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotNmethodTest.java --- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotNmethodTest.java Mon Jun 24 10:22:28 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotNmethodTest.java Mon Jun 24 10:25:41 2013 +0200 @@ -42,7 +42,7 @@ Assert.assertTrue(nmethod.isValid()); Object result; try { - result = nmethod.execute("a", "b", "c"); + result = nmethod.execute(null, "b", "c"); assertEquals(43, result); } catch (InvalidInstalledCodeException e) { Assert.fail("Code was invalidated"); @@ -59,6 +59,21 @@ } @Test + public void testInstallCodeInvalidationWhileRunning() { + final ResolvedJavaMethod testJavaMethod = runtime.lookupJavaMethod(getMethod("foo")); + final StructuredGraph graph = parse("otherFoo"); + final HotSpotNmethod nmethod = (HotSpotNmethod) getCode(testJavaMethod, graph); + Object result; + try { + result = nmethod.execute(nmethod, null, null); + assertEquals(43, result); + } catch (InvalidInstalledCodeException e) { + Assert.fail("Code was invalidated"); + } + Assert.assertFalse(nmethod.isValid()); + } + + @Test public void testInstalledCodeCalledFromCompiledCode() { final ResolvedJavaMethod testJavaMethod = runtime.lookupJavaMethod(getMethod("foo")); final StructuredGraph graph = parse("otherFoo"); @@ -66,7 +81,7 @@ Assert.assertTrue(nmethod.isValid()); try { for (int i = 0; i < ITERATION_COUNT; ++i) { - nmethod.execute("a", "b", "c"); + nmethod.execute(null, "b", "c"); } } catch (InvalidInstalledCodeException e) { Assert.fail("Code was invalidated"); @@ -74,12 +89,15 @@ } @SuppressWarnings("unused") - public static Object foo(Object a1, Object a2, Object a3) { + public static Object foo(HotSpotNmethod method, Object a2, Object a3) { return 42; } @SuppressWarnings("unused") - public static Object otherFoo(Object a1, Object a2, Object a3) { + public static Object otherFoo(HotSpotNmethod method, Object a2, Object a3) { + if (method != null) { + method.invalidate(); + } return 43; } } diff -r 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java Mon Jun 24 10:22:28 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java Mon Jun 24 10:25:41 2013 +0200 @@ -206,9 +206,9 @@ StackTraceElement getStackTraceElement(long metaspaceMethod, int bci); - Object executeCompiledMethod(Object arg1, Object arg2, Object arg3, long nmethod) throws InvalidInstalledCodeException; + Object executeCompiledMethod(Object arg1, Object arg2, Object arg3, HotSpotInstalledCode hotspotInstalledCode) throws InvalidInstalledCodeException; - Object executeCompiledMethodVarargs(Object[] args, long nmethod) throws InvalidInstalledCodeException; + Object executeCompiledMethodVarargs(Object[] args, HotSpotInstalledCode hotspotInstalledCode) throws InvalidInstalledCodeException; int getVtableEntryOffset(long metaspaceMethod); @@ -229,7 +229,5 @@ */ void reprofile(long metaspaceMethod); - void invalidateInstalledCode(long nativeMethod); - - boolean isInstalledCodeValid(long nativeMethod); + void invalidateInstalledCode(HotSpotInstalledCode hotspotInstalledCode); } diff -r 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java Mon Jun 24 10:22:28 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java Mon Jun 24 10:25:41 2013 +0200 @@ -143,7 +143,7 @@ public native StackTraceElement getStackTraceElement(long metaspaceMethod, int bci); @Override - public native Object executeCompiledMethodVarargs(Object[] args, long nmethod); + public native Object executeCompiledMethodVarargs(Object[] args, HotSpotInstalledCode hotspotInstalledCode); @Override public native int getVtableEntryOffset(long metaspaceMethod); @@ -170,14 +170,11 @@ public native Object lookupAppendixInPool(HotSpotResolvedObjectType pool, int cpi, byte opcode); @Override - public native void invalidateInstalledCode(long nativeMethod); + public native void invalidateInstalledCode(HotSpotInstalledCode hotspotInstalledCode); @Override - public native boolean isInstalledCodeValid(long nativeMethod); - - @Override - public Object executeCompiledMethod(Object arg1, Object arg2, Object arg3, long nmethod) throws InvalidInstalledCodeException { - return executeCompiledMethodIntrinsic(arg1, arg2, arg3, nmethod); + public Object executeCompiledMethod(Object arg1, Object arg2, Object arg3, HotSpotInstalledCode hotspotInstalledCode) throws InvalidInstalledCodeException { + return executeCompiledMethodIntrinsic(arg1, arg2, arg3, hotspotInstalledCode); } /** @@ -187,5 +184,5 @@ * stub that does the necessary argument shuffling and a tail call via an indirect jump to the * verified entry point of the given native method. */ - private static native Object executeCompiledMethodIntrinsic(Object arg1, Object arg2, Object arg3, long nmethod); + private static native Object executeCompiledMethodIntrinsic(Object arg1, Object arg2, Object arg3, HotSpotInstalledCode hotspotInstalledCode); } diff -r 0eeb9f8dab9b -r 5db21405c6a4 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 Mon Jun 24 10:22:28 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotNmethod.java Mon Jun 24 10:25:41 2013 +0200 @@ -68,12 +68,12 @@ @Override public boolean isValid() { - return graalRuntime().getCompilerToVM().isInstalledCodeValid(codeBlob); + return codeBlob != 0; } @Override public void invalidate() { - graalRuntime().getCompilerToVM().invalidateInstalledCode(codeBlob); + graalRuntime().getCompilerToVM().invalidateInstalledCode(this); } @Override @@ -87,7 +87,7 @@ assert method.getSignature().getParameterKind(0) == Kind.Object; assert method.getSignature().getParameterKind(1) == Kind.Object; assert !Modifier.isStatic(method.getModifiers()) || method.getSignature().getParameterKind(2) == Kind.Object; - return graalRuntime().getCompilerToVM().executeCompiledMethod(arg1, arg2, arg3, codeBlob); + return graalRuntime().getCompilerToVM().executeCompiledMethod(arg1, arg2, arg3, this); } private boolean checkArgs(Object... args) { @@ -107,7 +107,7 @@ @Override public Object executeVarargs(Object... args) throws InvalidInstalledCodeException { assert checkArgs(args); - return graalRuntime().getCompilerToVM().executeCompiledMethodVarargs(args, codeBlob); + return graalRuntime().getCompilerToVM().executeCompiledMethodVarargs(args, this); } @Override diff -r 0eeb9f8dab9b -r 5db21405c6a4 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 Mon Jun 24 10:22:28 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/WriteBarrierSnippets.java Mon Jun 24 10:25:41 2013 +0200 @@ -23,6 +23,7 @@ package com.oracle.graal.hotspot.replacements; import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*; +import static com.oracle.graal.phases.GraalOptions.*; import static com.oracle.graal.replacements.SnippetTemplate.*; import com.oracle.graal.api.code.*; @@ -40,14 +41,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"); + @Snippet public static void serialArrayWriteBarrier(Object obj, Object location, @ConstantParameter boolean usePrecise) { Object object = FixedValueAnchorNode.getObject(obj); Pointer oop; if (usePrecise) { oop = Word.fromArray(object, location); + serialArrayWriteBarrierCounter.inc(); } else { oop = Word.fromObject(object); + serialFieldWriteBarrierCounter.inc(); } Word base = (Word) oop.unsignedShiftRight(cardTableShift()); long startAddress = cardTableStart(); diff -r 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.graal.java.decompiler.test/src/com/oracle/graal/java/decompiler/test/BootstrapTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.java.decompiler.test/src/com/oracle/graal/java/decompiler/test/BootstrapTest.java Mon Jun 24 10:25:41 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.java.decompiler.test; + +public class BootstrapTest { + + public static void main(String[] args) { + + } +} diff -r 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.graal.java.decompiler.test/src/com/oracle/graal/java/decompiler/test/Test.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.java.decompiler.test/src/com/oracle/graal/java/decompiler/test/Test.java Mon Jun 24 10:25:41 2013 +0200 @@ -0,0 +1,47 @@ +/* + * 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.java.decompiler.test; + +import java.lang.reflect.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.runtime.*; +import com.oracle.graal.java.decompiler.test.example.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.printer.*; + +public class Test { + + /** + * @param args + * @throws SecurityException + * @throws NoSuchMethodException + */ + public static void main(String[] args) throws NoSuchMethodException, SecurityException { + DebugEnvironment.initialize(System.out); + GraalCodeCacheProvider runtime = Graal.getRequiredCapability(GraalCodeCacheProvider.class); + Method method = Example.class.getDeclaredMethod("loop7", new Class[]{int.class, int.class}); + final ResolvedJavaMethod javaMethod = runtime.lookupJavaMethod(method); + TestUtil.compileMethod(javaMethod); + } +} diff -r 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.graal.java.decompiler.test/src/com/oracle/graal/java/decompiler/test/TestUtil.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.java.decompiler.test/src/com/oracle/graal/java/decompiler/test/TestUtil.java Mon Jun 24 10:25:41 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.java.decompiler.test; + +import static com.oracle.graal.api.code.CodeUtil.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.code.CallingConvention.Type; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.runtime.*; +import com.oracle.graal.compiler.*; +import com.oracle.graal.compiler.target.*; +import com.oracle.graal.java.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.phases.*; +import com.oracle.graal.phases.PhasePlan.PhasePosition; +import com.oracle.graal.phases.tiers.*; + +public class TestUtil { + + public static void compileMethod(ResolvedJavaMethod method) { + GraalCodeCacheProvider runtime = Graal.getRequiredCapability(GraalCodeCacheProvider.class); + Replacements replacements = Graal.getRequiredCapability(Replacements.class); + Suites suites = Graal.getRequiredCapability(SuitesProvider.class).createSuites(); + StructuredGraph graph = new StructuredGraph(method); + new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getEagerDefault(), OptimisticOptimizations.ALL).apply(graph); + PhasePlan phasePlan = new PhasePlan(); + GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getDefault(), OptimisticOptimizations.ALL); + phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase); + CallingConvention cc = getCallingConvention(runtime, Type.JavaCallee, graph.method(), false); + Backend backend = Graal.getRequiredCapability(Backend.class); + GraalCompiler.compileGraph(graph, cc, method, runtime, replacements, backend, runtime.getTarget(), null, phasePlan, OptimisticOptimizations.ALL, new SpeculationLog(), suites); + } +} diff -r 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.graal.java.decompiler.test/src/com/oracle/graal/java/decompiler/test/example/Example.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.java.decompiler.test/src/com/oracle/graal/java/decompiler/test/example/Example.java Mon Jun 24 10:25:41 2013 +0200 @@ -0,0 +1,200 @@ +/* + * 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.java.decompiler.test.example; + +public class Example { + + static int if0(int a, int b) { + if (a > b) { + return a - b; + } + return 0; + + } + + static int if1(int a, int b) { + if (a > b) { + return a - b; + } else { + return a + b; + } + } + + static int if2(int a, int b) { + int c; + if (a > b) { + c = 1; + } else { + c = 2; + } + return c; + } + + static int if3(int a, int b) { + int c = 0; + int s = 3; + if (a > b) { + if (a == 4) { + c = 2 + b; + } else { + c = 4 + b; + } + s = a + b; + } else { + c = 2; + s = a - b; + } + return c + s; + } + + static int if4(int a, @SuppressWarnings("unused") int b) { + if (a > 10) { + if (a > 100) { + if (a > 1000) { + return 1; + } + return 2; + } + return 3; + } + return 4; + } + + static int loop(int a, int b) { + int i = 0; + int s = 0; + + while (i < a) { + s += b; + i++; + } + return s; + } + + static int loop2(int a, int b) { + int i = 0; + int s = 0; + + while (i < a) { + if (a > b) { + s += a; + } else { + s += b; + } + i++; + } + return s; + } + + static int loop3(int a, int b) { + int i = 0; + int s = 0; + + while (i < a) { + if (a > b) { + s += a; + } else { + s += b; + } + i++; + } + if (s > 1000) { + return -1; + } else { + return s; + } + } + + static int loop4(int a, int b) { + int s = 0; + + if (a < 1000) { + int i = 0; + while (i < 123) { + if (a > b) { + s += a; + } else { + s += b; + } + i = i + ret1(i); + } + return -1; + } else { + return s; + } + } + + static int ret1(int i) { + if (i % 2 == 0) { + return 1; + } else { + return 3; + } + } + + static int loop5(int a, int b) { + int i = 0; + int sum = 0; + while (i < 1000) { + if (a < b) { + sum = sum + a; + } + sum = sum + i; + if (sum < a) { + sum = sum + b; + } + i++; + } + if (sum < a + b) { + sum = sum * 2; + } + return sum; + } + + static int loop6(int a, int b) { + int s = 0; + for (int i = 0; i < a; i++) { + s += b; + } + return s; + } + + static int loop7(int a, int b) { + int s = 0; + for (int i = 0; i < a; i++) { + for (int j = 0; j < b; j++) { + if (a > 400) { + for (int k = 0; k < a + b; k++) { + s += if4(a, b); + } + } else { + for (int k = 0; k < a - b; k++) { + s += b; + } + } + } + s += b; + } + return s; + } +} diff -r 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/Decompiler.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/Decompiler.java Mon Jun 24 10:25:41 2013 +0200 @@ -0,0 +1,122 @@ +/* + * 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.java.decompiler; + +import java.io.*; +import java.util.*; + +import com.oracle.graal.java.decompiler.block.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.cfg.*; +import com.oracle.graal.phases.schedule.*; + +public class Decompiler { + + private List blocks = new ArrayList<>(); + private List cfgBlocks = new ArrayList<>(); + private SchedulePhase schedule; + private ControlFlowGraph cfg; + + private final PrintStream stream; + private final PrintStream infoStream; + + private static final String IDENT = " "; + private String curIdent = ""; + + public final String contexInformation; + + public Decompiler(StructuredGraph graph, SchedulePhase schedulePhase, PrintStream stream, PrintStream infoPrintStream, String contextInformation) { + this.stream = stream; + this.infoStream = infoPrintStream; + this.contexInformation = contextInformation; + schedule = schedulePhase; + if (schedule == null) { + try { + schedule = new SchedulePhase(); + schedule.apply(graph); + } catch (Throwable t) { + } + } + + cfg = schedule.getCFG(); + } + + public void decompile() { + + for (Block b : getCfg().getBlocks()) { + cfgBlocks.add(b); + } + + for (int i = 0; i < getCfg().getBlocks().length - 1; i++) { + if (cfg.getBlocks()[i].getId() >= cfg.getBlocks()[i + 1].getId()) { + throw new AssertionError(); + } + } + + blocks = new DecompilerLoopSimplify(this, infoStream).apply(cfgBlocks); + blocks = new DecompilerIfSimplify(this, infoStream).apply(blocks); + + DecompilerPhiRemover.apply(cfg, blocks); + + printDebugOutput(); + } + + private void printDebugOutput() { + for (int i = 0; i < blocks.size(); i++) { + if (i < blocks.size() - 1) { + blocks.get(i).printBlock(stream, blocks.get(i + 1).getBlock()); + } else { + blocks.get(i).printBlock(stream, null); + } + } + } + + public List getBlocks() { + return blocks; + } + + public void ident() { + curIdent += IDENT; + } + + public void undent() { + curIdent = curIdent.substring(0, curIdent.length() - IDENT.length()); + } + + public String getIdent() { + return curIdent; + } + + public List getCfgBlocks() { + return cfgBlocks; + } + + public SchedulePhase getSchedule() { + return schedule; + } + + public ControlFlowGraph getCfg() { + return cfg; + } + +} diff -r 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/DecompilerIfSimplify.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/DecompilerIfSimplify.java Mon Jun 24 10:25:41 2013 +0200 @@ -0,0 +1,124 @@ +/* + * 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.java.decompiler; + +import java.io.*; +import java.util.*; + +import com.oracle.graal.java.decompiler.block.*; +import com.oracle.graal.java.decompiler.lines.*; +import com.oracle.graal.nodes.cfg.*; + +public class DecompilerIfSimplify { + + private final Decompiler decompiler; + private final PrintStream infoStream; + + public DecompilerIfSimplify(Decompiler decompiler, PrintStream infoStream) { + this.decompiler = decompiler; + this.infoStream = infoStream; + } + + public List apply(List decompilerBlocks) { + return detectIfs(decompilerBlocks); + } + + private List detectIfs(List decompilerBlocks) { + List blocks = new ArrayList<>(); + while (!decompilerBlocks.isEmpty()) { + if (decompilerBlocks.get(0) instanceof DecompilerBasicBlock) { + DecompilerBasicBlock block = (DecompilerBasicBlock) decompilerBlocks.remove(0); + if (block.getSuccessorCount() <= 1) { + blocks.add(block); + } else if (block.getSuccessorCount() == 2 && block.getCode().get(block.getCode().size() - 1) instanceof DecompilerIfLine) { + Block firstThenBlock = block.getBlock().getSuccessors().get(0); + Block firstElseBlock = block.getBlock().getSuccessors().get(1); + List thenBlocks = getReachableDecompilerBlocks(firstThenBlock, decompilerBlocks); + List elseBlocks = getReachableDecompilerBlocks(firstElseBlock, decompilerBlocks); + removeIntersection(thenBlocks, elseBlocks); + if (thenBlocks.size() == 0 && elseBlocks.size() == 0) { + blocks.add(block); + } else { + for (DecompilerBlock b : thenBlocks) { + decompilerBlocks.remove(b); + } + for (DecompilerBlock b : elseBlocks) { + decompilerBlocks.remove(b); + } + // TODO(mg) + // thenBlocks and elseBlocks can be both empty --> causes an AssertionError + DecompilerIfBlock ifBlock = new DecompilerIfBlock(block.getBlock(), decompiler, thenBlocks, elseBlocks, infoStream); + if (thenBlocks.contains(block.getBlock()) || elseBlocks.contains(block.getBlock())) { + throw new AssertionError(); + } + blocks.add(ifBlock); + ifBlock.detectIfs(); + } + } else { + blocks.add(block); + } + } else { + if (decompilerBlocks.get(0) instanceof DecompilerLoopBlock) { + DecompilerLoopBlock loop = (DecompilerLoopBlock) decompilerBlocks.get(0); + loop.detectIfs(); + } + blocks.add(decompilerBlocks.remove(0)); + } + } + + return blocks; + } + + private static List getReachableDecompilerBlocks(Block b, List decompilerBlocks) { + List result = new ArrayList<>(); + for (DecompilerBlock block : decompilerBlocks) { + if (isReachable(b, block.getBlock(), new ArrayList())) { + result.add(block); + } + } + return result; + } + + private static boolean isReachable(Block from, Block to, ArrayList visited) { + if (from == to) { + return true; + } + for (Block b : from.getSuccessors()) { + if (b != from && visited.contains(b) == false && b.getId() > from.getId()) { + visited.add(b); + if (isReachable(b, to, visited)) { + return true; + } + } + } + return false; + } + + private static void removeIntersection(List list1, List list2) { + List list1Copy = new ArrayList<>(list1); + List list2Copy = new ArrayList<>(list2); + + list1.removeAll(list2Copy); + list2.removeAll(list1Copy); + } +} diff -r 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/DecompilerLoopSimplify.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/DecompilerLoopSimplify.java Mon Jun 24 10:25:41 2013 +0200 @@ -0,0 +1,82 @@ +/* + * 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.java.decompiler; + +import java.io.*; +import java.util.*; + +import com.oracle.graal.java.decompiler.block.*; +import com.oracle.graal.nodes.cfg.*; + +public class DecompilerLoopSimplify { + + private final Decompiler decompiler; + private final PrintStream infoStream; + + public DecompilerLoopSimplify(Decompiler decompiler, PrintStream infoStream) { + this.decompiler = decompiler; + this.infoStream = infoStream; + } + + public List apply(List cfgBlocks) { + List blocks = new ArrayList<>(); + + while (!cfgBlocks.isEmpty()) { + Block firstBlock = cfgBlocks.get(0); + cfgBlocks.remove(0); + if (firstBlock.isLoopHeader()) { + DecompilerLoopBlock loopBlock = new DecompilerLoopBlock(firstBlock, decompiler, decompiler.getSchedule(), infoStream); + Loop loop = firstBlock.getLoop(); + + for (int i = 0; i < cfgBlocks.size(); i++) { + if (loop.blocks.contains(cfgBlocks.get(i)) && cfgBlocks.get(i) != firstBlock) { + loopBlock.addBodyBlock(cfgBlocks.get(i)); + } + } + + // Asserting: + for (Block b : loopBlock.getBody()) { + if (!loop.blocks.contains(b)) { + throw new AssertionError(); + } + } + for (Block b : loop.blocks) { + if (b != firstBlock && !loopBlock.getBody().contains(b)) { + throw new AssertionError(); + } + } + + for (Block b : loopBlock.getBody()) { + cfgBlocks.remove(b); + } + + blocks.add(loopBlock); + loopBlock.detectLoops(); + } else { + DecompilerBasicBlock wrappedBlock = new DecompilerBasicBlock(firstBlock, decompiler, decompiler.getSchedule()); + blocks.add(wrappedBlock); + } + } + return blocks; + } +} diff -r 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/DecompilerPhiRemover.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/DecompilerPhiRemover.java Mon Jun 24 10:25:41 2013 +0200 @@ -0,0 +1,92 @@ +/* + * 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.java.decompiler; + +import java.util.*; + +import com.oracle.graal.graph.*; +import com.oracle.graal.java.decompiler.block.*; +import com.oracle.graal.java.decompiler.lines.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.cfg.*; + +public class DecompilerPhiRemover { + + public static void apply(ControlFlowGraph cfg, List decompilerBlocks) { + List blocks = collectAllBasicBlocks(decompilerBlocks); + for (DecompilerBasicBlock b : blocks) { + List removedLines = new ArrayList<>(); + Map addedLines = new HashMap<>(); + for (DecompilerSyntaxLine l : b.getCode()) { + if (l instanceof DecompilerPhiLine) { + DecompilerPhiLine phi = (DecompilerPhiLine) l; + removedLines.add(phi); + PhiNode phiNode = (PhiNode) phi.getNode(); + for (int i = 0; i < phiNode.merge().phiPredecessorCount(); i++) { + Node n = phiNode.merge().phiPredecessorAt(i); + DecompilerBasicBlock targetBlock = getBlock(n, cfg, blocks); + DecompilerPhiResolveLine assignment = new DecompilerPhiResolveLine(targetBlock, phiNode, n); + addedLines.put(assignment, targetBlock); + } + } + } + for (DecompilerSyntaxLine l : addedLines.keySet()) { + addAssignment(addedLines.get(l), l); + } + b.getCode().removeAll(removedLines); + } + } + + private static List collectAllBasicBlocks(List blocks) { + List allBasicBlocks = new ArrayList<>(); + for (DecompilerBlock b : blocks) { + allBasicBlocks.addAll(b.getAllBasicBlocks()); + } + return allBasicBlocks; + } + + private static DecompilerBasicBlock getBlock(Node n, ControlFlowGraph cfg, List blocks) { + Block b = cfg.blockFor(n); + for (DecompilerBasicBlock basicBlock : blocks) { + if (basicBlock.getBlock() == b) { + return basicBlock; + } + } + throw new IllegalStateException("Block not found"); + } + + private static void addAssignment(DecompilerBasicBlock block, DecompilerSyntaxLine line) { + if (block.getCode().isEmpty()) { + block.getCode().add(line); + return; + } + DecompilerSyntaxLine lastLine = block.getCode().get(block.getCode().size() - 1); + if (lastLine instanceof DecompilerIfLine || lastLine instanceof DecompilerControlSplitLine) { + block.getCode().remove(lastLine); + block.getCode().add(line); + block.getCode().add(lastLine); + } else { + block.getCode().add(line); + } + } +} diff -r 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/block/DecompilerBasicBlock.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/block/DecompilerBasicBlock.java Mon Jun 24 10:25:41 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.java.decompiler.block; + +import java.io.*; +import java.util.*; + +import com.oracle.graal.java.decompiler.*; +import com.oracle.graal.java.decompiler.lines.*; +import com.oracle.graal.nodes.cfg.*; +import com.oracle.graal.phases.schedule.*; + +public class DecompilerBasicBlock extends DecompilerBlock { + + public DecompilerBasicBlock(Block block, Decompiler decompiler, SchedulePhase schedule) { + super(block, decompiler); + initCode(schedule); + } + + @Override + public void printBlock(PrintStream stream, Block codeSuccessor) { + stream.println(decompiler.getIdent() + block); + for (DecompilerSyntaxLine l : code) { + if (l != null) { + String line = l.getAsString(); + stream.println(decompiler.getIdent() + line); + } + } + if (!(block.getSuccessorCount() == 0 || (block.getSuccessorCount() == 1 && block.getFirstSuccessor() == codeSuccessor))) { + stream.println(decompiler.getIdent() + "GOTO " + Arrays.toString(block.getSuccessors().toArray())); + } + } + + @Override + public String toString() { + return block.toString(); + } + + @Override + public int getSuccessorCount() { + return block.getSuccessorCount(); + } + + public List getSuccessors() { + return block.getSuccessors(); + } + + @Override + public boolean contains(Block b) { + return b == block; + } + + public List getCode() { + return code; + } + + @Override + public List getAllBasicBlocks() { + return Arrays.asList(new DecompilerBasicBlock[]{this}); + } +} diff -r 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/block/DecompilerBlock.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/block/DecompilerBlock.java Mon Jun 24 10:25:41 2013 +0200 @@ -0,0 +1,117 @@ +/* + * 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.java.decompiler.block; + +import java.io.*; +import java.util.*; + +import com.oracle.graal.graph.Node.Verbosity; +import com.oracle.graal.java.decompiler.*; +import com.oracle.graal.java.decompiler.lines.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.cfg.*; +import com.oracle.graal.phases.schedule.*; + +public abstract class DecompilerBlock { + + protected final Block block; + protected final Decompiler decompiler; + protected final List code; + + public DecompilerBlock(Block block, Decompiler decompiler) { + this.block = block; + this.decompiler = decompiler; + this.code = new ArrayList<>(); + } + + public Block getBlock() { + return block; + } + + public abstract void printBlock(PrintStream stream, Block codeSuccessor); + + public final int getPredecessorCount() { + return block.getPredecessorCount(); + } + + public abstract int getSuccessorCount(); + + public abstract boolean contains(Block b); + + public abstract List getAllBasicBlocks(); + + @Override + public abstract String toString(); + + protected void initCode(SchedulePhase schedule) { + List instructions = schedule.nodesFor(block); + for (ScheduledNode n : instructions) { + if (n instanceof MergeNode) { + MergeNode merge = (MergeNode) n; + for (PhiNode phi : merge.phis()) { + addLine(new DecompilerPhiLine(this, phi)); + } + } else if (n instanceof StartNode || n instanceof BeginNode || n instanceof EndNode || n instanceof LoopEndNode || n instanceof LoopExitNode) { + // do nothing + } else if (n instanceof ConstantNode) { + // do nothing + } else if (n instanceof IfNode) { + assert n.inputs().count() == 1; + addLine(new DecompilerIfLine(this, n, ((IfNode) n).condition())); + } else if (n instanceof ReturnNode) { + addLine(new DecompilerReturnLine(this, n.inputs().first())); + } else if (n instanceof ControlSplitNode) { + addLine(new DecompilerControlSplitLine(this, n)); + } else if (n instanceof ProxyNode) { + ProxyNode proxy = (ProxyNode) n; + addLine(new DecompilerProxyLine(this, proxy, proxy.value())); + } else if (n instanceof ValueNode) { + addLine(new DecompilerAssignmentLine(this, n)); + } else { + throw new IllegalStateException(n.toString(Verbosity.All) + " " + n.getClass()); + } + } + simplifyCode(); + } + + private void simplifyCode() { + for (int i = 0; i < code.size(); i++) { + if (code.get(i) instanceof DecompilerAssignmentLine) { + if (i + 1 < code.size()) { + if (code.get(i + 1) instanceof DecompilerIfLine) { + if (code.get(i).getNode().usages().count() == 1) { + if (((DecompilerIfLine) code.get(i + 1)).getCondition() == code.get(i).getNode()) { + ((DecompilerIfLine) code.get(i + 1)).setMergedCondition((DecompilerAssignmentLine) code.get(i)); + code.set(i, null); + } + } + } + } + } + } + } + + protected void addLine(DecompilerSyntaxLine line) { + code.add(line); + } +} diff -r 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/block/DecompilerIfBlock.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/block/DecompilerIfBlock.java Mon Jun 24 10:25:41 2013 +0200 @@ -0,0 +1,177 @@ +/* + * 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.java.decompiler.block; + +import java.io.*; +import java.util.*; + +import com.oracle.graal.java.decompiler.*; +import com.oracle.graal.java.decompiler.lines.*; +import com.oracle.graal.nodes.cfg.*; + +public class DecompilerIfBlock extends DecompilerBlock { + + private List thenBranch; + private List elseBranch; + private final DecompilerBasicBlock head; + private final PrintStream infoStream; + + public DecompilerIfBlock(Block block, Decompiler decompiler, List thenBranch, List elseBranch, PrintStream infoStream) { + super(block, decompiler); + this.thenBranch = thenBranch; + this.elseBranch = elseBranch; + this.infoStream = infoStream; + this.head = new DecompilerBasicBlock(block, decompiler, decompiler.getSchedule()); + + if (!(thenBranch.isEmpty() == false && head.getBlock().getSuccessors().contains(thenBranch.get(0).getBlock()) || (elseBranch.isEmpty() == false && head.getBlock().getSuccessors().contains( + elseBranch.get(0).getBlock())))) { + // first block of then / else MUST be a successor of the head! + throw new AssertionError(decompiler.contexInformation); + } + } + + @Override + public void printBlock(PrintStream stream, Block codeSuccessor) { + List lines = head.getCode(); + for (int i = 0; i < lines.size() - 1; i++) { + if (lines.get(i) != null) { + String line = lines.get(i).getAsString(); + stream.println(decompiler.getIdent() + line); + } + } + DecompilerIfLine ifLine = (DecompilerIfLine) lines.get(lines.size() - 1); + if (!thenBranch.isEmpty() && block.getSuccessors().contains(thenBranch.get(0).getBlock())) { + if (elseBranch.isEmpty()) { + // while break: + stream.println(decompiler.getIdent() + ifLine.getIfNegStatement()); + decompiler.ident(); + stream.println(decompiler.getIdent() + "BREAK TO " + block.getSuccessors().get(1)); + decompiler.undent(); + for (int i = 0; i < thenBranch.size(); i++) { + if (i < thenBranch.size() - 1) { + thenBranch.get(i).printBlock(stream, thenBranch.get(i + 1).getBlock()); + } else { + thenBranch.get(i).printBlock(stream, codeSuccessor); + } + } + } else { + stream.println(decompiler.getIdent() + ifLine.getIfStatement() + " {"); + decompiler.ident(); + for (int i = 0; i < thenBranch.size(); i++) { + if (i < thenBranch.size() - 1) { + thenBranch.get(i).printBlock(stream, thenBranch.get(i + 1).getBlock()); + } else { + thenBranch.get(i).printBlock(stream, codeSuccessor); + } + } + decompiler.undent(); + stream.println(decompiler.getIdent() + "} ELSE {"); + decompiler.ident(); + for (int i = 0; i < elseBranch.size(); i++) { + if (i < elseBranch.size() - 1) { + elseBranch.get(i).printBlock(stream, elseBranch.get(i + 1).getBlock()); + } else { + elseBranch.get(i).printBlock(stream, codeSuccessor); + } + } + decompiler.undent(); + stream.println(decompiler.getIdent() + "}"); + } + } else if (!elseBranch.isEmpty() && block.getSuccessors().contains(elseBranch.get(0).getBlock())) { + if (thenBranch.isEmpty()) { + // while break: + stream.println(decompiler.getIdent() + ifLine.getIfStatement()); + decompiler.ident(); + stream.println(decompiler.getIdent() + "BREAK TO " + block.getSuccessors().get(0)); + decompiler.undent(); + for (int i = 0; i < elseBranch.size(); i++) { + if (i < elseBranch.size() - 1) { + elseBranch.get(i).printBlock(stream, elseBranch.get(i + 1).getBlock()); + } else { + elseBranch.get(i).printBlock(stream, codeSuccessor); + } + } + } else { + stream.println(decompiler.getIdent() + ifLine.getIfNegStatement() + " {"); + decompiler.ident(); + for (int i = 0; i < elseBranch.size(); i++) { + if (i < elseBranch.size() - 1) { + elseBranch.get(i).printBlock(stream, elseBranch.get(i + 1).getBlock()); + } else { + elseBranch.get(i).printBlock(stream, codeSuccessor); + } + } + decompiler.undent(); + stream.println(decompiler.getIdent() + "} ELSE {"); + decompiler.ident(); + + for (int i = 0; i < thenBranch.size(); i++) { + if (i < thenBranch.size() - 1) { + thenBranch.get(i).printBlock(stream, thenBranch.get(i + 1).getBlock()); + } else { + thenBranch.get(i).printBlock(stream, codeSuccessor); + } + } + + decompiler.undent(); + stream.println(decompiler.getIdent() + "}"); + } + } else { + throw new AssertionError(); + } + } + + public void detectIfs() { + thenBranch = new DecompilerIfSimplify(decompiler, infoStream).apply(thenBranch); + elseBranch = new DecompilerIfSimplify(decompiler, infoStream).apply(elseBranch); + } + + @Override + public int getSuccessorCount() { + return 1; + } + + @Override + public String toString() { + return "IF" + block.toString(); + } + + @Override + public boolean contains(Block b) { + return b == block || thenBranch.contains(b) || elseBranch.contains(b); + } + + @Override + public List getAllBasicBlocks() { + List blocks = new ArrayList<>(); + blocks.add(head); + for (DecompilerBlock b : thenBranch) { + blocks.addAll(b.getAllBasicBlocks()); + } + for (DecompilerBlock b : elseBranch) { + blocks.addAll(b.getAllBasicBlocks()); + } + return blocks; + } + +} diff -r 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/block/DecompilerLoopBlock.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/block/DecompilerLoopBlock.java Mon Jun 24 10:25:41 2013 +0200 @@ -0,0 +1,110 @@ +/* + * 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.java.decompiler.block; + +import java.io.*; +import java.util.*; + +import com.oracle.graal.java.decompiler.*; +import com.oracle.graal.nodes.cfg.*; +import com.oracle.graal.phases.schedule.*; + +public class DecompilerLoopBlock extends DecompilerBlock { + + private final List body; + private List decompilerBlockBody; + private final PrintStream infoStream; + + public DecompilerLoopBlock(Block block, Decompiler decompiler, SchedulePhase schedule, PrintStream infoStream) { + super(block, decompiler); + this.infoStream = infoStream; + this.body = new ArrayList<>(); + decompilerBlockBody = new ArrayList<>(); + decompilerBlockBody.add(new DecompilerBasicBlock(block, decompiler, schedule)); + } + + public void addBodyBlock(Block bodyBlock) { + body.add(bodyBlock); + } + + public List getBody() { + return body; + } + + public void detectLoops() { + decompilerBlockBody.addAll(new DecompilerLoopSimplify(decompiler, infoStream).apply(body)); + } + + public void detectIfs() { + decompilerBlockBody = new DecompilerIfSimplify(decompiler, infoStream).apply(decompilerBlockBody); + } + + @Override + public void printBlock(PrintStream stream, Block codeSuccessor) { + stream.println(decompiler.getIdent() + block); + stream.println(decompiler.getIdent() + "while {"); + decompiler.ident(); + for (int i = 0; i < decompilerBlockBody.size(); i++) { + if (i < decompilerBlockBody.size() - 1) { + decompilerBlockBody.get(i).printBlock(stream, decompilerBlockBody.get(i + 1).getBlock()); + } else { + decompilerBlockBody.get(i).printBlock(stream, block); + } + } + decompiler.undent(); + stream.println(decompiler.getIdent() + "}"); + } + + @Override + public String toString() { + return "LOOP " + block.toString(); + } + + @Override + public int getSuccessorCount() { + return block.getLoop().exits.size(); + } + + @Override + public boolean contains(Block b) { + if (b == block) { + return true; + } + for (Block bodyBlock : body) { + if (bodyBlock == b) { + return true; + } + } + return false; + } + + @Override + public List getAllBasicBlocks() { + List blocks = new ArrayList<>(); + for (DecompilerBlock b : decompilerBlockBody) { + blocks.addAll(b.getAllBasicBlocks()); + } + return blocks; + } + +} diff -r 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/lines/DecompilerAssignmentLine.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/lines/DecompilerAssignmentLine.java Mon Jun 24 10:25:41 2013 +0200 @@ -0,0 +1,63 @@ +/* + * 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.java.decompiler.lines; + +import com.oracle.graal.graph.*; +import com.oracle.graal.graph.Node.Verbosity; +import com.oracle.graal.java.decompiler.block.*; +import com.oracle.graal.nodes.*; + +public class DecompilerAssignmentLine extends DecompilerSyntaxLine { + + private final NodeClassIterable inputs; + + public DecompilerAssignmentLine(DecompilerBlock block, Node node) { + super(block, node); + this.inputs = node.inputs(); + } + + @Override + public String getAsString() { + StringBuilder sb = new StringBuilder(); + sb.append(getStringRepresentation(node)); + sb.append(" = "); + sb.append(getStatement()); + return sb.toString(); + } + + public String getStatement() { + StringBuilder sb = new StringBuilder(); + if (node instanceof CallTargetNode) { + CallTargetNode callTarget = (CallTargetNode) node; + sb.append(callTarget.targetName()); + } else { + sb.append(node.toString(Verbosity.Name)); + sb.append(" "); + for (Node n : inputs) { + sb.append(getStringRepresentation(n)); + sb.append(", "); + } + } + return sb.toString(); + } +} diff -r 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/lines/DecompilerControlSplitLine.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/lines/DecompilerControlSplitLine.java Mon Jun 24 10:25:41 2013 +0200 @@ -0,0 +1,47 @@ +/* + * 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.java.decompiler.lines; + +import com.oracle.graal.graph.*; +import com.oracle.graal.graph.Node.Verbosity; +import com.oracle.graal.java.decompiler.block.*; +import com.oracle.graal.nodes.cfg.*; + +public class DecompilerControlSplitLine extends DecompilerSyntaxLine { + + public DecompilerControlSplitLine(DecompilerBlock block, Node node) { + super(block, node); + } + + @Override + public String getAsString() { + StringBuilder sb = new StringBuilder(); + sb.append(node.toString(Verbosity.Name)); + sb.append(": "); + for (Block b : block.getBlock().getSuccessors()) { + sb.append(b); + sb.append(" "); + } + return null; + } +} diff -r 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/lines/DecompilerIfLine.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/lines/DecompilerIfLine.java Mon Jun 24 10:25:41 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.java.decompiler.lines; + +import com.oracle.graal.graph.*; +import com.oracle.graal.java.decompiler.block.*; + +public class DecompilerIfLine extends DecompilerSyntaxLine { + + private final Node condition; + private DecompilerAssignmentLine mergedCondition; + + public DecompilerIfLine(DecompilerBlock block, Node node, Node condition) { + super(block, node); + this.condition = condition; + } + + public void setMergedCondition(DecompilerAssignmentLine mergedCondition) { + this.mergedCondition = mergedCondition; + } + + @Override + public String getAsString() { + if (mergedCondition == null) { + return "IF (" + getStringRepresentation(condition) + ") " + block.getBlock().getSuccessors().get(0) + ":" + block.getBlock().getSuccessors().get(1); + } else { + return "IF (" + mergedCondition.getStatement() + ") " + block.getBlock().getSuccessors().get(0) + ":" + block.getBlock().getSuccessors().get(1); + } + } + + public String getIfStatement() { + if (mergedCondition == null) { + return "IF (" + getStringRepresentation(condition) + ")"; + } else { + return "IF (" + mergedCondition.getStatement() + ")"; + } + + } + + public String getIfNegStatement() { + if (mergedCondition == null) { + return "IF (!(" + getStringRepresentation(condition) + "))"; + } else { + return "IF (!(" + mergedCondition.getStatement() + "))"; + } + } + + public Node getCondition() { + return condition; + } +} diff -r 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/lines/DecompilerPhiLine.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/lines/DecompilerPhiLine.java Mon Jun 24 10:25:41 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.java.decompiler.lines; + +import com.oracle.graal.graph.*; +import com.oracle.graal.java.decompiler.block.*; +import com.oracle.graal.nodes.*; + +public class DecompilerPhiLine extends DecompilerSyntaxLine { + + public DecompilerPhiLine(DecompilerBlock block, Node node) { + super(block, node); + } + + @Override + public String getAsString() { + PhiNode phi = (PhiNode) node; + StringBuilder sb = new StringBuilder(); + sb.append(getStringRepresentation(phi)); + sb.append(" = Phi {"); + for (Node n : phi.values()) { + sb.append(getStringRepresentation(n)); + sb.append(","); + } + sb.append("}"); + + return sb.toString(); + } +} diff -r 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/lines/DecompilerPhiResolveLine.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/lines/DecompilerPhiResolveLine.java Mon Jun 24 10:25:41 2013 +0200 @@ -0,0 +1,46 @@ +/* + * 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.java.decompiler.lines; + +import com.oracle.graal.graph.*; +import com.oracle.graal.java.decompiler.block.*; + +public class DecompilerPhiResolveLine extends DecompilerSyntaxLine { + + private final Node value; + + public DecompilerPhiResolveLine(DecompilerBlock block, Node node, Node value) { + super(block, node); + this.value = value; + } + + @Override + public String getAsString() { + StringBuilder sb = new StringBuilder(); + sb.append(getStringRepresentation(node)); + sb.append(" = "); + sb.append(getStringRepresentation(value)); + return sb.toString(); + } + +} diff -r 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/lines/DecompilerProxyLine.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/lines/DecompilerProxyLine.java Mon Jun 24 10:25:41 2013 +0200 @@ -0,0 +1,42 @@ +/* + * 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.java.decompiler.lines; + +import com.oracle.graal.graph.*; +import com.oracle.graal.java.decompiler.block.*; + +public class DecompilerProxyLine extends DecompilerSyntaxLine { + + private final Node proxy; + + public DecompilerProxyLine(DecompilerBlock block, Node node, Node proxy) { + super(block, node); + this.proxy = proxy; + } + + @Override + public String getAsString() { + return getVariable(node) + " = " + getStringRepresentation(proxy); + } + +} diff -r 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/lines/DecompilerReturnLine.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/lines/DecompilerReturnLine.java Mon Jun 24 10:25:41 2013 +0200 @@ -0,0 +1,39 @@ +/* + * 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.java.decompiler.lines; + +import com.oracle.graal.graph.*; +import com.oracle.graal.java.decompiler.block.*; + +public class DecompilerReturnLine extends DecompilerSyntaxLine { + + public DecompilerReturnLine(DecompilerBlock block, Node node) { + super(block, node); + } + + @Override + public String getAsString() { + return "return " + getStringRepresentation(node); + } + +} diff -r 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/lines/DecompilerSyntaxLine.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.java.decompiler/src/com/oracle/graal/java/decompiler/lines/DecompilerSyntaxLine.java Mon Jun 24 10:25:41 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.java.decompiler.lines; + +import com.oracle.graal.graph.*; +import com.oracle.graal.java.decompiler.block.*; +import com.oracle.graal.nodes.*; + +public abstract class DecompilerSyntaxLine { + + protected final Node node; + protected final DecompilerBlock block; + + protected DecompilerSyntaxLine(DecompilerBlock block, Node node) { + this.node = node; + this.block = block; + } + + public Node getNode() { + return node; + } + + public abstract String getAsString(); + + public DecompilerBlock getBlock() { + return block; + } + + protected static String getStringRepresentation(Node node) { + if (node instanceof ConstantNode) { + return String.valueOf(((ConstantNode) node).asConstant().asBoxedValue()); + } else if (node instanceof LocalNode) { + return "local_" + ((LocalNode) node).index(); + } else { + return getVariable(node); + } + } + + @SuppressWarnings("deprecation") + protected static String getVariable(Node node) { + if (node != null) { + return "var_" + node.getId(); + } else { + return "null"; + } + } + +} diff -r 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCAddressValue.java --- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCAddressValue.java Mon Jun 24 10:22:28 2013 +0200 +++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCAddressValue.java Mon Jun 24 10:25:41 2013 +0200 @@ -34,12 +34,10 @@ private static final long serialVersionUID = -3583286416638228207L; - @Component({ REG, OperandFlag.ILLEGAL }) - protected AllocatableValue base; + @Component({REG, OperandFlag.ILLEGAL}) protected AllocatableValue base; protected final int displacement; - public SPARCAddressValue(PlatformKind kind, AllocatableValue baseRegister, - int finalDisp) { + public SPARCAddressValue(PlatformKind kind, AllocatableValue baseRegister, int finalDisp) { super(kind); this.base = baseRegister; this.displacement = finalDisp; diff -r 0eeb9f8dab9b -r 5db21405c6a4 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 Mon Jun 24 10:22:28 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedWithNextNode.java Mon Jun 24 10:25:41 2013 +0200 @@ -30,13 +30,15 @@ */ public abstract class FixedWithNextNode extends FixedNode { + @Successor private FixedNode next; + public FixedNode next() { - assert scheduledNext() == null || scheduledNext() instanceof FixedNode : "next() cannot be used while the graph is scheduled"; - return (FixedNode) scheduledNext(); + return next; } public void setNext(FixedNode x) { - setScheduledNext(x); + updatePredecessor(next, x); + next = x; } public FixedWithNextNode(Stamp stamp) { diff -r 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ScheduledNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ScheduledNode.java Mon Jun 24 10:22:28 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ScheduledNode.java Mon Jun 24 10:25:41 2013 +0200 @@ -26,17 +26,6 @@ public abstract class ScheduledNode extends Node { - @Successor private ScheduledNode scheduledNext; // the immediate successor of the current node - - public ScheduledNode scheduledNext() { - return scheduledNext; - } - - public void setScheduledNext(ScheduledNode x) { - updatePredecessor(scheduledNext, x); - scheduledNext = x; - } - @Override public StructuredGraph graph() { return (StructuredGraph) super.graph(); diff -r 0eeb9f8dab9b -r 5db21405c6a4 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 Mon Jun 24 10:22:28 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/IntegerStamp.java Mon Jun 24 10:25:41 2013 +0200 @@ -131,13 +131,14 @@ IntegerStamp other = (IntegerStamp) otherStamp; if (lowerBound > other.upperBound || upperBound < other.lowerBound) { return true; - } else { - if ((mask & other.mask) == 0) { - // zero is the only common value if the masks don't overlap => check for non-zero - return lowerBound > 0 || upperBound < 0 || other.lowerBound > 0 || other.upperBound < 0; - } - return false; + } else if ((mask & other.mask) == 0 && (lowerBound > 0 || upperBound < 0 || other.lowerBound > 0 || other.upperBound < 0)) { + /* + * Zero is the only common value if the masks don't overlap. If one of the two values is + * less than or greater than zero, they are always distinct. + */ + return true; } + return false; } @Override diff -r 0eeb9f8dab9b -r 5db21405c6a4 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 Mon Jun 24 10:22:28 2013 +0200 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java Mon Jun 24 10:25:41 2013 +0200 @@ -183,6 +183,8 @@ public static final OptionValue ExitVMOnException = new OptionValue<>(true); @Option(help = "") public static final OptionValue PrintStackTraceOnException = new OptionValue<>(false); + @Option(help = "Sets a phase after which the decompiler dumps the graph, -G:Dump= required") + public static final OptionValue DecompileAfterPhase = new OptionValue<>(null); // HotSpot command line options @Option(help = "") @@ -308,6 +310,7 @@ public static final OptionValue IntrinsifyInstalledCodeMethods = new OptionValue<>(true); @Option(help = "") public static final OptionValue IntrinsifyCallSiteTarget = new OptionValue<>(true); + /** * Counts the various paths taken through snippets. */ diff -r 0eeb9f8dab9b -r 5db21405c6a4 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 Mon Jun 24 10:22:28 2013 +0200 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java Mon Jun 24 10:25:41 2013 +0200 @@ -209,25 +209,6 @@ sortNodesWithinBlocks(graph, selectedStrategy); } - /** - * Sets {@link ScheduledNode#scheduledNext} on all scheduled nodes in all blocks using the - * scheduling built by {@link #run(StructuredGraph)}. This method should thus only be called - * when run has been successfully executed. - */ - public void scheduleGraph() { - assert blockToNodesMap != null : "cannot set scheduledNext before run has been executed"; - for (Block block : cfg.getBlocks()) { - List nodeList = blockToNodesMap.get(block); - ScheduledNode last = null; - for (ScheduledNode node : nodeList) { - if (last != null) { - last.setScheduledNext(node); - } - last = node; - } - } - } - public ControlFlowGraph getCFG() { return cfg; } diff -r 0eeb9f8dab9b -r 5db21405c6a4 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 Mon Jun 24 10:22:28 2013 +0200 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/DebugEnvironment.java Mon Jun 24 10:25:41 2013 +0200 @@ -43,6 +43,9 @@ } dumpHandlers.add(new CFGPrinterObserver()); } + if (DecompileAfterPhase.getValue() != null) { + dumpHandlers.add(new DecompilerDebugDumpHandler()); + } GraalDebugConfig hotspotDebugConfig = new GraalDebugConfig(Log.getValue(), Meter.getValue(), Time.getValue(), Dump.getValue(), MethodFilter.getValue(), log, dumpHandlers); Debug.setConfig(hotspotDebugConfig); } diff -r 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.graal.printer/src/com/oracle/graal/printer/DecompilerDebugDumpHandler.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/DecompilerDebugDumpHandler.java Mon Jun 24 10:25:41 2013 +0200 @@ -0,0 +1,108 @@ +/* + * 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.printer; + +import java.io.*; +import java.util.concurrent.atomic.*; + +import static com.oracle.graal.phases.GraalOptions.*; + +import com.oracle.graal.debug.*; +import com.oracle.graal.java.decompiler.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.phases.schedule.*; + +public class DecompilerDebugDumpHandler implements DebugDumpHandler { + + private final PrintStream infoPrintStream = System.out; + private File file; + private FileOutputStream fos; + private PrintStream printStream; + private String fileName; + private static final AtomicInteger uniqueId = new AtomicInteger(); + + @Override + public void dump(Object object, final String message) { + if (object instanceof StructuredGraph) { + if (Debug.currentScope().contains("LowTier")) { + // no decompilation after high / mid tier + return; + } + final StructuredGraph graph = (StructuredGraph) object; + String filter = DecompileAfterPhase.getValue(); + if (filter.endsWith("Phase")) { + filter = filter.substring(0, filter.indexOf("Phase")); + } + + if (printStream == null) { + fileName = "decompilerDump_" + uniqueId.incrementAndGet() + "_" + System.currentTimeMillis() + ".txt"; + file = new File(fileName); + try { + fos = new FileOutputStream(file, true); + } catch (FileNotFoundException e) { + throw new IllegalStateException(e); + } + printStream = new PrintStream(fos); + infoPrintStream.println("Dump Decompiler Output to " + file.getAbsolutePath()); + } + + final String currentScope = Debug.currentScope(); + if (currentScope.endsWith(filter) && graph.method() != null) { + final String methodName = graph.method().getName(); + Debug.sandbox("Printing Decompiler Output", null, new Runnable() { + + @Override + public void run() { + printStream.println(); + printStream.println("Object: " + methodName); + printStream.println("Message: " + message); + new Decompiler(graph, getPredefinedSchedule(), printStream, infoPrintStream, currentScope).decompile(); + printStream.flush(); + } + }); + + } + } + } + + private static SchedulePhase getPredefinedSchedule() { + SchedulePhase result = null; + for (Object o : Debug.context()) { + if (o instanceof SchedulePhase) { + result = (SchedulePhase) o; + } + } + return result; + } + + @Override + public void close() { + try { + printStream.close(); + fos.close(); + } catch (IOException e) { + throw new IllegalStateException(e); + } + } + +} diff -r 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.graal.truffle.printer/src/com/oracle/graal/truffle/printer/InlinePrinterProcessor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle.printer/src/com/oracle/graal/truffle/printer/InlinePrinterProcessor.java Mon Jun 24 10:25:41 2013 +0200 @@ -0,0 +1,117 @@ +/* + * 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.printer; + +import java.util.*; + +import com.oracle.graal.debug.*; +import com.oracle.graal.truffle.printer.method.*; + +public final class InlinePrinterProcessor { + + private static final String IDENT = " "; + private static InlinePrinterProcessor instance; + + private final List inlineTree = new ArrayList<>(); + + public static void initialize() { + if (instance == null) { + instance = new InlinePrinterProcessor(); + } else { + throw new IllegalStateException(); + } + } + + public static void addInlining(MethodHolder methodHolder) { + instance.addExecuteInline(methodHolder); + } + + public static void printTree() { + instance.print(); + } + + public static void reset() { + instance = null; + } + + private void addExecuteInline(MethodHolder executeMethod) { + if (inlineTree.isEmpty()) { + inlineTree.add(new TruffleMethodNode(null, executeMethod)); + } else { + TruffleMethodNode newNode = null; + for (TruffleMethodNode node : inlineTree) { + newNode = node.addTruffleExecuteMethodNode(executeMethod); + if (newNode != null) { + break; + } + } + if (newNode == null) { + throw new AssertionError("Not able to add " + executeMethod.getMethod().toString() + " to the inlineing tree"); + } + inlineTree.add(newNode); + } + } + + private TruffleMethodNode getInlineTree() { + TruffleMethodNode root = inlineTree.get(0); + while (root.getParent() != null) { + root = root.getParent(); + } + + // asserting: + for (TruffleMethodNode node : inlineTree) { + TruffleMethodNode nodeRoot = node; + while (nodeRoot.getParent() != null) { + nodeRoot = nodeRoot.getParent(); + } + if (root != nodeRoot) { + throw new AssertionError("Different roots found"); + } + } + + return root; + } + + private void print() { + String curIndent = ""; + TruffleMethodNode root = getInlineTree(); + String name = root.getJavaMethod().getDeclaringClass().getName(); + TTY.print(name.substring(name.lastIndexOf('/') + 1, name.lastIndexOf(';')) + "::" + root.getJavaMethod().getName()); + TTY.println(); + recursivePrint(curIndent, root); + } + + private void recursivePrint(String curIdent, TruffleMethodNode node) { + Map> inlinings = node.getInlinings(); + for (int l : inlinings.keySet()) { + for (TruffleMethodNode n : inlinings.get(l)) { + TTY.print(curIdent); + TTY.print("L" + l + " "); + String name = n.getJavaMethod().getDeclaringClass().getName(); + TTY.print(name.substring(name.lastIndexOf('/') + 1, name.lastIndexOf(';')) + "::" + n.getJavaMethod().getName()); + TTY.println(); + recursivePrint(curIdent + IDENT, n); + } + } + } +} diff -r 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.graal.truffle.printer/src/com/oracle/graal/truffle/printer/method/CallStackElement.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle.printer/src/com/oracle/graal/truffle/printer/method/CallStackElement.java Mon Jun 24 10:25:41 2013 +0200 @@ -0,0 +1,66 @@ +/* + * 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.printer.method; + +import com.oracle.graal.api.meta.*; + +public class CallStackElement { + + private final int lineOfInvoke; + private final ResolvedJavaMethod callerMethod; + + public CallStackElement(ResolvedJavaMethod callerMethod, int lineOfInvoke) { + this.lineOfInvoke = lineOfInvoke; + this.callerMethod = callerMethod; + } + + public int getLineOfInvoke() { + return lineOfInvoke; + } + + @Override + public boolean equals(Object o) { + if (o instanceof CallStackElement) { + CallStackElement i = (CallStackElement) o; + if (i.getCallerMethod() == this.getCallerMethod()/* + * && i.lineOfInvoke == + * this.lineOfInvoke + */) { + return true; + } else { + return false; + } + } else { + return false; + } + } + + @Override + public int hashCode() { + return super.hashCode(); + } + + public ResolvedJavaMethod getCallerMethod() { + return callerMethod; + } +} diff -r 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.graal.truffle.printer/src/com/oracle/graal/truffle/printer/method/MethodHolder.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle.printer/src/com/oracle/graal/truffle/printer/method/MethodHolder.java Mon Jun 24 10:25:41 2013 +0200 @@ -0,0 +1,65 @@ +/* + * 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.printer.method; + +import java.util.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.java.*; + +public final class MethodHolder { + + private final List callStack; + private final ResolvedJavaMethod method; + + public static MethodHolder getNewTruffleExecuteMethod(MethodCallTargetNode targetNode) { + return new MethodHolder(getCallStack(targetNode), targetNode.targetMethod()); + } + + private MethodHolder(List callStack, ResolvedJavaMethod callee) { + this.callStack = callStack; + this.method = callee; + } + + public List getCallStack() { + return callStack; + } + + public ResolvedJavaMethod getMethod() { + return method; + } + + private static List getCallStack(MethodCallTargetNode targetNode) { + List callStack = new ArrayList<>(); + FrameState state = targetNode.invoke().stateAfter(); + while (state != null) { + ResolvedJavaMethod method = state.method(); + LineNumberTable table = method.getLineNumberTable(); + int lineNr = table.getLineNumber(state.bci - 1); + callStack.add(new CallStackElement(method, lineNr)); + state = state.outerFrameState(); + } + return callStack; + } +} diff -r 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.graal.truffle.printer/src/com/oracle/graal/truffle/printer/method/TruffleMethodNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle.printer/src/com/oracle/graal/truffle/printer/method/TruffleMethodNode.java Mon Jun 24 10:25:41 2013 +0200 @@ -0,0 +1,102 @@ +/* + * 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.printer.method; + +import java.util.*; + +import com.oracle.graal.api.meta.*; + +public final class TruffleMethodNode { + + private final TruffleMethodNode parent; + private final MethodHolder truffleExecuteMethod; + private final Map> inlinings; + + public TruffleMethodNode(TruffleMethodNode parent, MethodHolder truffleExecuteMethod) { + this.parent = parent; + this.truffleExecuteMethod = truffleExecuteMethod; + this.inlinings = new HashMap<>(); + } + + public TruffleMethodNode getParent() { + return parent; + } + + public ResolvedJavaMethod getJavaMethod() { + return truffleExecuteMethod.getMethod(); + } + + public Map> getInlinings() { + return inlinings; + } + + public void putInlineList(int lineOfInvoke, List list) { + inlinings.put(lineOfInvoke, list); + } + + public List getInliningsAtLine(int line) { + return inlinings.get(line); + } + + public MethodHolder getTruffleExecuteMethod() { + return truffleExecuteMethod; + } + + public TruffleMethodNode addTruffleExecuteMethodNode(MethodHolder newMethod) { + int lineOfInvoke = newMethod.getCallStack().get(0).getLineOfInvoke(); + + if (!callStackMatch(newMethod.getCallStack())) { + return null; + } else { + TruffleMethodNode node = new TruffleMethodNode(this, newMethod); + if (getInliningsAtLine(lineOfInvoke) == null) { + List list = new ArrayList<>(); + list.add(node); + putInlineList(lineOfInvoke, list); + } else { + getInliningsAtLine(lineOfInvoke).add(node); + } + return node; + } + } + + private boolean callStackMatch(List callStack) { + List curCallStack = truffleExecuteMethod.getCallStack(); + if (curCallStack.size() == callStack.size() - 1) { + if (curCallStack.size() >= 1) { + if (curCallStack.get(0).getCallerMethod() != callStack.get(1).getCallerMethod()) { + return false; + } + } + for (int i = 1; i < curCallStack.size(); i++) { + if (!curCallStack.get(i).equals(callStack.get(i + 1))) { + return false; + } + } + } else { + return false; + } + return true; + } + +} diff -r 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/AssumptionPartialEvaluationTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/AssumptionPartialEvaluationTest.java Mon Jun 24 10:25:41 2013 +0200 @@ -0,0 +1,73 @@ +/* + * 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.test; + +import org.junit.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.truffle.test.nodes.*; +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; + +@Ignore("Currently ignored due to problems with code coverage tools.") +public class AssumptionPartialEvaluationTest extends PartialEvaluationTest { + + public static Object constant42() { + return 42; + } + + @Test + public void constantValue() { + FrameDescriptor fd = new FrameDescriptor(); + Assumption assumption = Truffle.getRuntime().createAssumption(); + AbstractTestNode result = new ConstantWithAssumptionTestNode(assumption, 42); + RootTestNode rootNode = new RootTestNode("constantValue", result); + InstalledCode installedCode = assertPartialEvalEquals("constant42", rootNode, fd); + Assert.assertTrue(installedCode.isValid()); + try { + assertEquals(42, installedCode.execute(null, null, null)); + } catch (InvalidInstalledCodeException e) { + Assert.fail("Code must not have been invalidated."); + } + Assert.assertTrue(installedCode.isValid()); + try { + assumption.check(); + } catch (InvalidAssumptionException e) { + Assert.fail("Assumption must not have been invalidated."); + } + assumption.invalidate(); + try { + assumption.check(); + Assert.fail("Assumption must have been invalidated."); + } catch (InvalidAssumptionException e) { + } + Assert.assertFalse(installedCode.isValid()); + + try { + installedCode.execute(null, null, null); + Assert.fail("Code must have been invalidated."); + } catch (InvalidInstalledCodeException e) { + } + } +} diff -r 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/ExactMathTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/ExactMathTest.java Mon Jun 24 10:25:41 2013 +0200 @@ -0,0 +1,104 @@ +/* + * 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.test; + +import org.junit.*; + +import com.oracle.graal.api.runtime.*; +import com.oracle.graal.compiler.test.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.truffle.substitutions.*; +import com.oracle.truffle.api.*; + +public class ExactMathTest extends GraalCompilerTest { + + private static boolean substitutionsInstalled; + + public ExactMathTest() { + if (!substitutionsInstalled) { + Graal.getRequiredCapability(Replacements.class).registerSubstitutions(ExactMathSubstitutions.class); + substitutionsInstalled = true; + } + } + + @Test + public void testAdd() { + test("add", 1, 2); + test("add", Integer.MAX_VALUE, 2); + } + + @Test + public void testMul() { + test("mul", 1, 2); + test("mul", Integer.MAX_VALUE, 2); + } + + @Test + public void testSub() { + test("sub", 1, 2); + test("sub", Integer.MIN_VALUE, 2); + } + + @Test + public void testLongAdd() { + test("longAdd", (long) Integer.MAX_VALUE, 2L); + test("longAdd", Long.MAX_VALUE, 2L); + } + + @Test + public void testLongMul() { + test("longMul", (long) Integer.MAX_VALUE, 2L); + test("longMul", (long) Integer.MIN_VALUE, 2L); + test("longMul", Long.MAX_VALUE, 2L); + } + + @Test + public void testLongSub() { + test("longSub", (long) Integer.MIN_VALUE, 2L); + test("longSub", Long.MIN_VALUE, 2L); + } + + public static int add(int a, int b) { + return ExactMath.addExact(a, b); + } + + public static int mul(int a, int b) { + return ExactMath.multiplyExact(a, b); + } + + public static int sub(int a, int b) { + return ExactMath.subtractExact(a, b); + } + + public static long longAdd(long a, long b) { + return ExactMath.addExact(a, b); + } + + public static long longMul(long a, long b) { + return ExactMath.multiplyExact(a, b); + } + + public static long longSub(long a, long b) { + return ExactMath.subtractExact(a, b); + } +} diff -r 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/PartialEvaluationTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/PartialEvaluationTest.java Mon Jun 24 10:25:41 2013 +0200 @@ -0,0 +1,204 @@ +/* + * 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.test; + +import static com.oracle.graal.truffle.TruffleCompilerOptions.*; + +import java.util.*; +import java.util.concurrent.*; + +import org.junit.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.compiler.test.*; +import com.oracle.graal.debug.*; +import com.oracle.graal.java.*; +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.*; +import com.oracle.graal.phases.tiers.*; +import com.oracle.graal.printer.*; +import com.oracle.graal.truffle.*; +import com.oracle.graal.truffle.printer.*; +import com.oracle.graal.virtual.phases.ea.*; +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; + +public class PartialEvaluationTest extends GraalCompilerTest { + + private static final long UNROLL_LIMIT = 100; + private final PartialEvaluator nodeCompiler; + + public PartialEvaluationTest() { + // Make sure Truffle runtime is initialized. + Assert.assertTrue(Truffle.getRuntime() instanceof GraalTruffleRuntime); + this.nodeCompiler = new PartialEvaluator(runtime, runtime); + + DebugEnvironment.initialize(System.out); + } + + protected InstalledCode assertPartialEvalEquals(String methodName, RootNode root, FrameDescriptor descriptor) { + return assertPartialEvalEquals(methodName, root, descriptor, Arguments.EMPTY_ARGUMENTS); + } + + protected InstalledCode assertPartialEvalEquals(String methodName, RootNode root, FrameDescriptor descriptor, Arguments arguments) { + Assumptions assumptions = new Assumptions(true); + StructuredGraph actual = partialEval(root, descriptor, arguments, assumptions, true); + InstalledCode result = new TruffleCompilerImpl().compileMethodHelper(actual, GraphBuilderConfiguration.getDefault(), assumptions); + StructuredGraph expected = parseForComparison(methodName); + removeFrameStates(actual); + Assert.assertEquals(getCanonicalGraphString(expected, true), getCanonicalGraphString(actual, true)); + return result; + } + + protected void assertPartialEvalNoInvokes(RootNode root, FrameDescriptor descriptor) { + assertPartialEvalNoInvokes(root, descriptor, Arguments.EMPTY_ARGUMENTS); + } + + protected void assertPartialEvalNoInvokes(RootNode root, FrameDescriptor descriptor, Arguments arguments) { + Assumptions assumptions = new Assumptions(true); + StructuredGraph actual = partialEval(root, descriptor, arguments, assumptions, true); + removeFrameStates(actual); + for (MethodCallTargetNode node : actual.getNodes(MethodCallTargetNode.class)) { + Assert.fail("Found invalid method call target node: " + node); + } + } + + protected StructuredGraph partialEval(RootNode root, FrameDescriptor descriptor, Arguments arguments, final Assumptions assumptions, final boolean canonicalizeReads) { + final OptimizedCallTarget compilable = (OptimizedCallTarget) Truffle.getRuntime().createCallTarget(root, descriptor); + + // Executed AST so that all classes are loaded and initialized. + do { + compilable.call(null, arguments); + compilable.call(null, arguments); + compilable.call(null, arguments); + } while (compilable.inline()); + + StructuredGraph graph = Debug.scope("Truffle", new DebugDumpScope("Truffle: " + compilable), new Callable() { + + @Override + public StructuredGraph call() { + StructuredGraph resultGraph = nodeCompiler.createGraph(compilable, assumptions); + CanonicalizerPhase canonicalizer = new CanonicalizerPhase(canonicalizeReads); + HighTierContext context = new HighTierContext(runtime, assumptions, replacements); + + if (resultGraph.hasLoops()) { + boolean unrolled; + do { + unrolled = false; + LoopsData loopsData = new LoopsData(resultGraph); + loopsData.detectedCountedLoops(); + for (LoopEx ex : innerLoopsFirst(loopsData.countedLoops())) { + if (ex.counted().isConstantMaxTripCount()) { + long constant = ex.counted().constantMaxTripCount(); + if (constant <= UNROLL_LIMIT) { + LoopTransformations.fullUnroll(ex, runtime, assumptions, canonicalizeReads); + Debug.dump(resultGraph, "After loop unrolling %d times", constant); + + canonicalizer.apply(resultGraph, context); + unrolled = true; + break; + } + } + } + } while (unrolled); + } + + new DeadCodeEliminationPhase().apply(resultGraph); + new PartialEscapePhase(true, canonicalizer).apply(resultGraph, context); + + if (TruffleInlinePrinter.getValue()) { + InlinePrinterProcessor.printTree(); + } + + return resultGraph; + } + + 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; + } + + protected void removeFrameStates(StructuredGraph graph) { + for (FrameState frameState : graph.getNodes(FrameState.class)) { + frameState.replaceAtUsages(null); + frameState.safeDelete(); + } + new CanonicalizerPhase.Instance(runtime, new Assumptions(false), true).apply(graph); + new DeadCodeEliminationPhase().apply(graph); + } + + protected StructuredGraph parseForComparison(final String methodName) { + + StructuredGraph graphResult = Debug.scope("Truffle", new DebugDumpScope("Comparison: " + methodName), new Callable() { + + public StructuredGraph call() { + Assumptions assumptions = new Assumptions(false); + StructuredGraph graph = parse(methodName); + CanonicalizerPhase.Instance canonicalizerPhase = new CanonicalizerPhase.Instance(runtime, assumptions, true); + canonicalizerPhase.apply(graph); + + // 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); + plan.addPhase(PhasePosition.AFTER_PARSING, new DeadCodeEliminationPhase()); + + new ConvertDeoptimizeToGuardPhase().apply(graph); + canonicalizerPhase.apply(graph); + new DeadCodeEliminationPhase().apply(graph); + + InliningPhase inliningPhase = new InliningPhase(runtime, null, replacements, assumptions, null, plan, OptimisticOptimizations.NONE); + inliningPhase.apply(graph); + removeFrameStates(graph); + + new ConvertDeoptimizeToGuardPhase().apply(graph); + canonicalizerPhase.apply(graph); + new DeadCodeEliminationPhase().apply(graph); + + new LoweringPhase(LoweringType.BEFORE_GUARDS).apply(graph, new PhaseContext(runtime, assumptions, replacements)); + canonicalizerPhase.apply(graph); + new DeadCodeEliminationPhase().apply(graph); + return graph; + } + }); + return graphResult; + } +} diff -r 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/SimplePartialEvaluationTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/SimplePartialEvaluationTest.java Mon Jun 24 10:25:41 2013 +0200 @@ -0,0 +1,111 @@ +/* + * 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.test; + +import org.junit.*; + +import com.oracle.graal.truffle.test.nodes.*; +import com.oracle.truffle.api.frame.*; + +@Ignore("Currently ignored due to problems with code coverage tools.") +public class SimplePartialEvaluationTest extends PartialEvaluationTest { + + public static Object constant42() { + return 42; + } + + @Test + public void constantValue() { + FrameDescriptor fd = new FrameDescriptor(); + AbstractTestNode result = new ConstantTestNode(42); + assertPartialEvalEquals("constant42", new RootTestNode("constantValue", result), fd); + } + + @Test + public void addConstants() { + FrameDescriptor fd = new FrameDescriptor(); + AbstractTestNode result = new AddTestNode(new ConstantTestNode(40), new ConstantTestNode(2)); + assertPartialEvalEquals("constant42", new RootTestNode("addConstants", result), fd); + } + + @Test + public void sequenceConstants() { + FrameDescriptor fd = new FrameDescriptor(); + AbstractTestNode result = new BlockTestNode(new AbstractTestNode[]{new ConstantTestNode(40), new ConstantTestNode(42)}); + assertPartialEvalEquals("constant42", new RootTestNode("sequenceConstants", result), fd); + } + + @Test + public void localVariable() { + FrameDescriptor fd = new FrameDescriptor(); + AbstractTestNode result = new BlockTestNode(new AbstractTestNode[]{new StoreLocalTestNode("x", fd, new ConstantTestNode(42)), new LoadLocalTestNode("x", fd)}); + assertPartialEvalEquals("constant42", new RootTestNode("localVariable", result), fd); + } + + @Test + public void longSequenceConstants() { + FrameDescriptor fd = new FrameDescriptor(); + int length = 40; + AbstractTestNode[] children = new AbstractTestNode[length]; + for (int i = 0; i < children.length; ++i) { + children[i] = new ConstantTestNode(42); + } + + AbstractTestNode result = new BlockTestNode(children); + assertPartialEvalEquals("constant42", new RootTestNode("longSequenceConstants", result), fd); + } + + @Test + public void longAddConstants() { + FrameDescriptor fd = new FrameDescriptor(); + AbstractTestNode result = new ConstantTestNode(2); + for (int i = 0; i < 20; ++i) { + result = new AddTestNode(result, new ConstantTestNode(2)); + } + assertPartialEvalEquals("constant42", new RootTestNode("longAddConstants", result), fd); + } + + @Test + public void mixLocalAndAdd() { + FrameDescriptor fd = new FrameDescriptor(); + AbstractTestNode result = new BlockTestNode(new AbstractTestNode[]{new StoreLocalTestNode("x", fd, new ConstantTestNode(40)), + new StoreLocalTestNode("x", fd, new AddTestNode(new LoadLocalTestNode("x", fd), new ConstantTestNode(2))), new LoadLocalTestNode("x", fd)}); + assertPartialEvalEquals("constant42", new RootTestNode("mixLocalAndAdd", result), fd); + } + + @Test + public void loop() { + FrameDescriptor fd = new FrameDescriptor(); + AbstractTestNode result = new BlockTestNode(new AbstractTestNode[]{new StoreLocalTestNode("x", fd, new ConstantTestNode(0)), + new LoopTestNode(21, new StoreLocalTestNode("x", fd, new AddTestNode(new LoadLocalTestNode("x", fd), new ConstantTestNode(2))))}); + assertPartialEvalEquals("constant42", new RootTestNode("loop", result), fd); + } + + @Test + public void longLoop() { + FrameDescriptor fd = new FrameDescriptor(); + AbstractTestNode result = new BlockTestNode(new AbstractTestNode[]{new StoreLocalTestNode("x", fd, new ConstantTestNode(0)), + new LoopTestNode(42, new StoreLocalTestNode("x", fd, new AddTestNode(new LoadLocalTestNode("x", fd), new ConstantTestNode(1))))}); + assertPartialEvalNoInvokes(new RootTestNode("loop", result), fd); + } +} diff -r 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/TruffleRuntimeTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/TruffleRuntimeTest.java Mon Jun 24 10:25:41 2013 +0200 @@ -0,0 +1,51 @@ +/* + * 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.test; + +import static org.junit.Assert.*; + +import org.junit.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.runtime.*; +import com.oracle.graal.truffle.*; +import com.oracle.truffle.api.*; + +public class TruffleRuntimeTest { + + @Test + public void testGraalCapabilities() { + assertNotNull(Graal.getRuntime().getCapability(MetaAccessProvider.class)); + } + + @Test + public void testRuntimeAvailable() { + assertNotNull(Truffle.getRuntime()); + } + + @Test + public void testRuntimeIsGraalRuntime() { + TruffleRuntime runtime = Truffle.getRuntime(); + assertEquals(GraalTruffleRuntime.class, runtime.getClass()); + } +} diff -r 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/AbstractTestNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/AbstractTestNode.java Mon Jun 24 10:25:41 2013 +0200 @@ -0,0 +1,31 @@ +/* + * 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.test.nodes; + +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; + +public abstract class AbstractTestNode extends Node { + + public abstract int execute(VirtualFrame frame); +} diff -r 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/AddTestNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/AddTestNode.java Mon Jun 24 10:25:41 2013 +0200 @@ -0,0 +1,41 @@ +/* + * 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.test.nodes; + +import com.oracle.truffle.api.frame.*; + +public class AddTestNode extends AbstractTestNode { + + @Child private AbstractTestNode left; + @Child private AbstractTestNode right; + + public AddTestNode(AbstractTestNode left, AbstractTestNode right) { + this.left = adoptChild(left); + this.right = adoptChild(right); + } + + @Override + public int execute(VirtualFrame frame) { + return left.execute(frame) + right.execute(frame); + } +} diff -r 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/BlockTestNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/BlockTestNode.java Mon Jun 24 10:25:41 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.truffle.test.nodes; + +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; + +public class BlockTestNode extends AbstractTestNode { + + @Children private final AbstractTestNode[] statements; + + public BlockTestNode(AbstractTestNode[] statements) { + this.statements = adoptChildren(statements); + } + + @ExplodeLoop + @Override + public int execute(VirtualFrame frame) { + int result = 0; + for (AbstractTestNode statement : statements) { + result = statement.execute(frame); + } + return result; + } +} diff -r 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/ConstantTestNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/ConstantTestNode.java Mon Jun 24 10:25:41 2013 +0200 @@ -0,0 +1,39 @@ +/* + * 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.test.nodes; + +import com.oracle.truffle.api.frame.*; + +public class ConstantTestNode extends AbstractTestNode { + + private final int value; + + public ConstantTestNode(int value) { + this.value = value; + } + + @Override + public int execute(VirtualFrame frame) { + return value; + } +} diff -r 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/ConstantWithAssumptionTestNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/ConstantWithAssumptionTestNode.java Mon Jun 24 10:25:41 2013 +0200 @@ -0,0 +1,48 @@ +/* + * 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.test.nodes; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; + +public class ConstantWithAssumptionTestNode extends AbstractTestNode { + + private final int value; + private final Assumption assumption; + + public ConstantWithAssumptionTestNode(Assumption assumption, int value) { + this.value = value; + this.assumption = assumption; + } + + @Override + public int execute(VirtualFrame frame) { + try { + assumption.check(); + return value; + } catch (InvalidAssumptionException e) { + return this.replace(new ConstantTestNode(value + 1)).execute(frame); + } + } +} diff -r 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/LoadLocalTestNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/LoadLocalTestNode.java Mon Jun 24 10:25:41 2013 +0200 @@ -0,0 +1,43 @@ +/* + * 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.test.nodes; + +import com.oracle.truffle.api.frame.*; + +public class LoadLocalTestNode extends AbstractTestNode { + + private final FrameSlot slot; + + public LoadLocalTestNode(String name, FrameDescriptor frameDescriptor) { + slot = frameDescriptor.findOrAddFrameSlot(name); + } + + @Override + public int execute(VirtualFrame frame) { + try { + return frame.getInt(slot); + } catch (FrameSlotTypeException e) { + throw new IllegalStateException(e); + } + } +} diff -r 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/LoopTestNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/LoopTestNode.java Mon Jun 24 10:25:41 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.truffle.test.nodes; + +import com.oracle.truffle.api.frame.*; + +public class LoopTestNode extends AbstractTestNode { + + private final int numberOfIterations; + @Child private AbstractTestNode child; + + public LoopTestNode(int numberOfIterations, AbstractTestNode child) { + this.numberOfIterations = numberOfIterations; + this.child = adoptChild(child); + } + + @Override + public int execute(VirtualFrame frame) { + int lastValue = 0; + for (int i = 0; i < numberOfIterations; ++i) { + lastValue = child.execute(frame); + } + return lastValue; + } +} diff -r 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/RootTestNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/RootTestNode.java Mon Jun 24 10:25:41 2013 +0200 @@ -0,0 +1,47 @@ +/* + * 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.test.nodes; + +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; + +public class RootTestNode extends RootNode { + + private final String name; + @Child AbstractTestNode node; + + public RootTestNode(String name, AbstractTestNode node) { + this.name = name; + this.node = node; + } + + @Override + public Object execute(VirtualFrame frame) { + return node.execute(frame); + } + + @Override + public String toString() { + return name; + } +} diff -r 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/StoreLocalTestNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/StoreLocalTestNode.java Mon Jun 24 10:25:41 2013 +0200 @@ -0,0 +1,48 @@ +/* + * 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.test.nodes; + +import com.oracle.truffle.api.frame.*; + +public class StoreLocalTestNode extends AbstractTestNode { + + private final FrameSlot slot; + + @Child private AbstractTestNode valueNode; + + public StoreLocalTestNode(String name, FrameDescriptor frameDescriptor, AbstractTestNode valueNode) { + this.slot = frameDescriptor.findOrAddFrameSlot(name); + this.valueNode = valueNode; + } + + @Override + public int execute(VirtualFrame frame) { + int value = valueNode.execute(frame); + try { + frame.setInt(slot, value); + } catch (FrameSlotTypeException e) { + throw new IllegalStateException(e); + } + return value; + } +} diff -r 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/TestNodeFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/nodes/TestNodeFactory.java Mon Jun 24 10:25:41 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.truffle.test.nodes; + +public class TestNodeFactory { + + public AbstractTestNode createConstant(int value) { + return new ConstantTestNode(value); + } +} diff -r 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/FrameWithoutBoxing.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/FrameWithoutBoxing.java Mon Jun 24 10:25:41 2013 +0200 @@ -0,0 +1,288 @@ +/* + * 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 java.util.*; + +import sun.misc.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; + +/** + * More efficient implementation of the Truffle frame that has no safety checks for frame accesses + * and therefore is much faster. Should not be used during debugging as potential misuses of the + * frame object would show up very late and would be hard to identify. + */ +public final class FrameWithoutBoxing implements VirtualFrame, MaterializedFrame, PackedFrame { + + private static final Unsafe unsafe = Unsafe.getUnsafe(); + + private final FrameDescriptor descriptor; + private final PackedFrame caller; + private final Arguments arguments; + private Object[] locals; + private long[] primitiveLocals; + private byte[] tags; + + public FrameWithoutBoxing(FrameDescriptor descriptor, PackedFrame caller, Arguments arguments) { + this.descriptor = descriptor; + this.caller = caller; + this.arguments = arguments; + this.locals = new Object[descriptor.getSize()]; + this.primitiveLocals = new long[descriptor.getSize()]; + this.tags = new byte[descriptor.getSize()]; + } + + @SuppressWarnings("unchecked") + @Override + public T getArguments(Class clazz) { + return (T) unsafeCast(arguments, clazz); + } + + private static Object unsafeCast(Object value, @SuppressWarnings("unused") Class clazz) { + return value; + } + + @Override + public PackedFrame getCaller() { + return caller; + } + + @Override + public PackedFrame pack() { + return this; + } + + @Override + public MaterializedFrame materialize() { + return this; + } + + @Override + public VirtualFrame unpack() { + return this; + } + + @Override + public Object getObject(FrameSlot slot) throws FrameSlotTypeException { + verifyGet(slot, FrameSlotKind.Object); + return getObjectUnsafe(slot); + } + + private Object getObjectUnsafe(FrameSlot slot) { + return unsafe.getObject(locals, (long) slot.getIndex() * Unsafe.ARRAY_OBJECT_INDEX_SCALE + Unsafe.ARRAY_OBJECT_BASE_OFFSET); + } + + @Override + public void setObject(FrameSlot slot, Object value) throws FrameSlotTypeException { + verifySet(slot, FrameSlotKind.Object); + setObjectUnsafe(slot, value); + } + + private void setObjectUnsafe(FrameSlot slot, Object value) { + unsafe.putObject(locals, (long) slot.getIndex() * Unsafe.ARRAY_OBJECT_INDEX_SCALE + Unsafe.ARRAY_OBJECT_BASE_OFFSET, value); + } + + @Override + public boolean getBoolean(FrameSlot slot) throws FrameSlotTypeException { + verifyGet(slot, FrameSlotKind.Boolean); + return getBooleanUnsafe(slot); + } + + private boolean getBooleanUnsafe(FrameSlot slot) { + return unsafe.getBoolean(primitiveLocals, (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET); + } + + @Override + public void setBoolean(FrameSlot slot, boolean value) throws FrameSlotTypeException { + verifySet(slot, FrameSlotKind.Boolean); + setBooleanUnsafe(slot, value); + } + + private void setBooleanUnsafe(FrameSlot slot, boolean value) { + unsafe.putBoolean(primitiveLocals, (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET, value); + } + + @Override + public float getFloat(FrameSlot slot) throws FrameSlotTypeException { + verifyGet(slot, FrameSlotKind.Float); + return getFloatUnsafe(slot); + } + + private float getFloatUnsafe(FrameSlot slot) { + return unsafe.getFloat(primitiveLocals, (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET); + } + + @Override + public void setFloat(FrameSlot slot, float value) throws FrameSlotTypeException { + verifySet(slot, FrameSlotKind.Float); + setFloatUnsafe(slot, value); + } + + private void setFloatUnsafe(FrameSlot slot, float value) { + unsafe.putFloat(primitiveLocals, (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET, value); + } + + @Override + public long getLong(FrameSlot slot) throws FrameSlotTypeException { + verifyGet(slot, FrameSlotKind.Long); + return getLongUnsafe(slot); + } + + private long getLongUnsafe(FrameSlot slot) { + return unsafe.getLong(primitiveLocals, (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET); + } + + @Override + public void setLong(FrameSlot slot, long value) throws FrameSlotTypeException { + verifySet(slot, FrameSlotKind.Long); + setLongUnsafe(slot, value); + } + + private void setLongUnsafe(FrameSlot slot, long value) { + unsafe.putLong(primitiveLocals, (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET, value); + } + + @Override + public int getInt(FrameSlot slot) throws FrameSlotTypeException { + verifyGet(slot, FrameSlotKind.Int); + return getIntUnsafe(slot); + } + + private int getIntUnsafe(FrameSlot slot) { + return unsafe.getInt(primitiveLocals, (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET); + } + + @Override + public void setInt(FrameSlot slot, int value) throws FrameSlotTypeException { + verifySet(slot, FrameSlotKind.Int); + setIntUnsafe(slot, value); + } + + private void setIntUnsafe(FrameSlot slot, int value) { + unsafe.putInt(primitiveLocals, (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET, value); + } + + @Override + public double getDouble(FrameSlot slot) throws FrameSlotTypeException { + verifyGet(slot, FrameSlotKind.Double); + return getDoubleUnsafe(slot); + } + + private double getDoubleUnsafe(FrameSlot slot) { + return unsafe.getDouble(primitiveLocals, (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET); + } + + @Override + public void setDouble(FrameSlot slot, double value) throws FrameSlotTypeException { + verifySet(slot, FrameSlotKind.Double); + setDoubleUnsafe(slot, value); + } + + private void setDoubleUnsafe(FrameSlot slot, double value) { + unsafe.putDouble(primitiveLocals, (long) slot.getIndex() * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET, value); + } + + @Override + public FrameDescriptor getFrameDescriptor() { + return this.descriptor; + } + + private void verifySet(FrameSlot slot, FrameSlotKind accessKind) throws FrameSlotTypeException { + FrameSlotKind slotKind = slot.getKind(); + if (slotKind != accessKind) { + if (slotKind == FrameSlotKind.Illegal) { + slot.setKind(accessKind); + } else { + throw new FrameSlotTypeException(); + } + } + int slotIndex = slot.getIndex(); + if (slotIndex >= tags.length) { + resize(); + } + 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(); + } + } + 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(); + } + } + } + + @Override + public Object getValue(FrameSlot slot) { + int index = slot.getIndex(); + if (index >= tags.length) { + assert index >= 0 && index < descriptor.getSize(); + return descriptor.getTypeConversion().getDefaultValue(); + } + byte tag = tags[index]; + if (tag == FrameSlotKind.Illegal.ordinal()) { + return descriptor.getTypeConversion().getDefaultValue(); + } else if (tag == FrameSlotKind.Boolean.ordinal()) { + return getBooleanUnsafe(slot); + } else if (tag == FrameSlotKind.Int.ordinal()) { + return getIntUnsafe(slot); + } else if (tag == FrameSlotKind.Double.ordinal()) { + return getDoubleUnsafe(slot); + } else if (tag == FrameSlotKind.Long.ordinal()) { + return getLongUnsafe(slot); + } else if (tag == FrameSlotKind.Float.ordinal()) { + return getFloatUnsafe(slot); + } else { + return getObjectUnsafe(slot); + } + } + + private void resize() { + int newSize = descriptor.getSize(); + if (newSize > tags.length) { + locals = Arrays.copyOf(locals, newSize); + primitiveLocals = Arrays.copyOf(primitiveLocals, newSize); + tags = Arrays.copyOf(tags, newSize); + } + } + + @Override + public boolean isInitialized(FrameSlot slot) { + return !(this.tags[slot.getIndex()] == FrameSlotKind.Illegal.ordinal()); + } +} diff -r 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/GraalTruffleRuntime.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/GraalTruffleRuntime.java Mon Jun 24 10:25:41 2013 +0200 @@ -0,0 +1,141 @@ +/* + * 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.*; + +import java.util.*; + +import com.oracle.graal.api.runtime.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.truffle.substitutions.*; +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.impl.*; +import com.oracle.truffle.api.nodes.*; + +/** + * Implementation of the Truffle runtime when running on top of Graal. + */ +public final class GraalTruffleRuntime implements TruffleRuntime { + + public static GraalTruffleRuntime makeInstance() { + return new GraalTruffleRuntime(); + } + + private TruffleCompiler truffleCompiler; + private ArrayList includes; + private ArrayList excludes; + + private GraalTruffleRuntime() { + Replacements replacements = Graal.getRequiredCapability(Replacements.class); + replacements.registerSubstitutions(CompilerAssertsSubstitutions.class); + replacements.registerSubstitutions(CompilerDirectivesSubstitutions.class); + replacements.registerSubstitutions(ExactMathSubstitutions.class); + replacements.registerSubstitutions(UnexpectedResultExceptionSubstitutions.class); + replacements.registerSubstitutions(SlowPathExceptionSubstitutions.class); + replacements.registerSubstitutions(FrameWithoutBoxingSubstitutions.class); + replacements.registerSubstitutions(OptimizedAssumptionSubstitutions.class); + replacements.registerSubstitutions(OptimizedCallTargetSubstitutions.class); + replacements.registerSubstitutions(DefaultCallTargetSubstitutions.class); + } + + public String getName() { + return "Graal Truffle Runtime"; + } + + public CallTarget createCallTarget(RootNode rootNode) { + return createCallTarget(rootNode, new FrameDescriptor()); + } + + @Override + public CallTarget createCallTarget(RootNode rootNode, FrameDescriptor frameDescriptor) { + if (!acceptForCompilation(rootNode)) { + return new DefaultCallTarget(rootNode, frameDescriptor); + } + if (truffleCompiler == null) { + truffleCompiler = new TruffleCompilerImpl(); + } + return new OptimizedCallTarget(rootNode, frameDescriptor, truffleCompiler, TruffleCompilationThreshold.getValue(), TruffleInliningReprofileCount.getValue(), + TruffleInvalidationReprofileCount.getValue()); + } + + @Override + public MaterializedFrame createMaterializedFrame(Arguments arguments) { + return createMaterializedFrame(arguments); + } + + @Override + public MaterializedFrame createMaterializedFrame(Arguments arguments, FrameDescriptor frameDescriptor) { + return new FrameWithoutBoxing(frameDescriptor, null, arguments); + } + + @Override + public Assumption createAssumption() { + return createAssumption(null); + } + + @Override + public Assumption createAssumption(String name) { + return new OptimizedAssumption(name); + } + + private boolean acceptForCompilation(RootNode rootNode) { + if (TruffleCompileOnly.getValue() != null) { + if (includes == null) { + parseCompileOnly(); + } + + String name = rootNode.toString(); + boolean included = includes.isEmpty(); + for (int i = 0; !included && i < includes.size(); i++) { + if (name.contains(includes.get(i))) { + included = true; + } + } + if (!included) { + return false; + } + for (String exclude : excludes) { + if (name.contains(exclude)) { + return false; + } + } + } + return true; + } + + private void parseCompileOnly() { + includes = new ArrayList<>(); + excludes = new ArrayList<>(); + + String[] items = TruffleCompileOnly.getValue().split(","); + for (String item : items) { + if (item.startsWith("~")) { + excludes.add(item.substring(1)); + } else { + includes.add(item); + } + } + } +} diff -r 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedAssumption.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedAssumption.java Mon Jun 24 10:25:41 2013 +0200 @@ -0,0 +1,78 @@ +/* + * 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 java.lang.ref.*; +import java.util.*; + +import com.oracle.graal.api.code.*; +import com.oracle.truffle.api.impl.*; +import com.oracle.truffle.api.nodes.*; + +public final class OptimizedAssumption extends AbstractAssumption { + + List> dependentInstalledCode; + + public OptimizedAssumption(String name) { + super(name); + } + + @Override + public void check() throws InvalidAssumptionException { + if (!isValid) { + throw new InvalidAssumptionException(); + } + } + + @Override + public synchronized void invalidate() { + if (isValid) { + if (dependentInstalledCode != null) { + for (WeakReference installedCodeReference : dependentInstalledCode) { + InstalledCode installedCode = installedCodeReference.get(); + if (installedCode != null) { + installedCode.invalidate(); + } + } + dependentInstalledCode = null; + } + isValid = false; + } + } + + public synchronized void registerInstalledCode(InstalledCode installedCode) { + if (isValid) { + if (dependentInstalledCode == null) { + dependentInstalledCode = new ArrayList<>(); + } + dependentInstalledCode.add(new WeakReference<>(installedCode)); + } else { + installedCode.invalidate(); + } + } + + @Override + public boolean isValid() { + return isValid; + } +} diff -r 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java Mon Jun 24 10:25:41 2013 +0200 @@ -0,0 +1,276 @@ +/* + * 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.*; + +import java.io.*; +import java.util.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.debug.*; +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.impl.*; +import com.oracle.truffle.api.nodes.*; + +/** + * Call target that is optimized by Graal upon surpassing a specific invocation threshold. + */ +public final class OptimizedCallTarget extends DefaultCallTarget implements LoopCountReceiver, FrameFactory { + + private static final PrintStream OUT = TTY.out().out(); + + private final int inliningReprofileCount; + private final int invalidationReprofileCount; + + protected OptimizedCallTarget(RootNode rootNode, FrameDescriptor descriptor, TruffleCompiler compiler, int compilationThreshold, int inliningReprofileCount, int invalidationReprofileCount) { + super(rootNode, descriptor); + this.compiler = compiler; + this.invokeCounter = compilationThreshold >> 7; + this.loopAndInvokeCounter = compilationThreshold; + this.originalInvokeCounter = compilationThreshold; + this.rootNode.setCallTarget(this); + this.inliningReprofileCount = inliningReprofileCount; + this.invalidationReprofileCount = invalidationReprofileCount; + } + + private InstalledCode compiledMethod; + private final TruffleCompiler compiler; + private int invokeCounter; + private int originalInvokeCounter; + private int loopAndInvokeCounter; + private boolean disableCompilation; + + long timeCompilationStarted; + long timePartialEvaluationFinished; + long timeCompilationFinished; + int codeSize; + int nodeCountPartialEval; + int nodeCountLowered; + + @Override + public Object call(PackedFrame caller, Arguments args) { + for (;;) { + if (compiledMethod != null) { + try { + return compiledMethod.execute(this, caller, args); + } catch (InvalidInstalledCodeException ex) { + compiledMethod = null; + invokeCounter = invalidationReprofileCount; + if (TruffleFunctionInlining.getValue()) { + originalInvokeCounter += invalidationReprofileCount; + } + if (TraceTruffleCompilation.getValue()) { + OUT.printf("[truffle] invalidated %-48s |Alive %5.0fms\n", rootNode, (System.nanoTime() - timeCompilationFinished) / 1e6); + } + } + } else { + invokeCounter--; + loopAndInvokeCounter--; + if (disableCompilation || loopAndInvokeCounter > 0 || invokeCounter > 0) { + return executeHelper(caller, args); + } else { + if (TruffleFunctionInlining.getValue()) { + if (inline()) { + invokeCounter = 2; + loopAndInvokeCounter = inliningReprofileCount; + originalInvokeCounter = inliningReprofileCount; + continue; + } + } + compile(); + } + } + } + } + + public boolean inline() { + return new InliningHelper(this).inline(); + } + + public void compile() { + try { + compiledMethod = compiler.compile(this); + if (compiledMethod == null) { + throw new BailoutException(String.format("code installation failed (codeSize=%s)", codeSize)); + } else { + if (TraceTruffleCompilation.getValue()) { + int nodeCountTruffle = new InliningHelper.CallTargetProfile(rootNode).nodeCount; + OUT.printf("[truffle] optimized %-50s |Nodes %7d |Time %5.0f(%4.0f+%-4.0f)ms |Nodes %5d/%5d |CodeSize %d\n", rootNode, nodeCountTruffle, + (timeCompilationFinished - timeCompilationStarted) / 1e6, (timePartialEvaluationFinished - timeCompilationStarted) / 1e6, + (timeCompilationFinished - timePartialEvaluationFinished) / 1e6, nodeCountPartialEval, nodeCountLowered, codeSize); + } + } + } catch (Throwable e) { + disableCompilation = true; + if (TraceTruffleCompilation.getValue()) { + if (e instanceof BailoutException) { + OUT.printf("[truffle] opt bailout %-48s %s\n", rootNode, e.getMessage()); + } else { + OUT.printf("[truffle] opt failed %-49s %s\n", rootNode, e.toString()); + if (TraceTruffleCompilationExceptions.getValue()) { + e.printStackTrace(OUT); + } + if (TruffleCompilationExceptionsAreFatal.getValue()) { + System.exit(-1); + } + } + } + } + } + + public Object executeHelper(PackedFrame caller, Arguments args) { + VirtualFrame frame = createFrame(frameDescriptor, caller, args); + return rootNode.execute(frame); + } + + private static FrameWithoutBoxing createFrame(FrameDescriptor descriptor, PackedFrame caller, Arguments args) { + return new FrameWithoutBoxing(descriptor, caller, args); + } + + @Override + public VirtualFrame create(FrameDescriptor descriptor, PackedFrame caller, Arguments args) { + return createFrame(descriptor, caller, args); + } + + @Override + public String toString() { + return "CallTarget " + rootNode; + } + + @Override + public void reportLoopCount(int count) { + loopAndInvokeCounter -= count; + } + + private static class InliningHelper { + + private static final int MAX_SIZE = 300; + private static final int MAX_INLINE_SIZE = 62; + + private final OptimizedCallTarget target; + + public InliningHelper(OptimizedCallTarget target) { + this.target = target; + } + + public boolean inline() { + CallTargetProfile profile = new CallTargetProfile(target.getRootNode()); + + if (profile.inlinableCallSites.isEmpty()) { + return false; + } + + if (profile.nodeCount > MAX_SIZE) { + return false; + } + + double max = 0.0D; + ProfiledInlinableCallSite inliningDecision = null; + for (Node callNode : profile.inlinableCallSites) { + InlinableCallSite callSite = (InlinableCallSite) callNode; + Node inlineTree = callSite.getInlineTree(); + if (inlineTree == null) { + continue; + } + CallTargetProfile inlineProfile = new CallTargetProfile(inlineTree); + if (inlineProfile.nodeCount > MAX_INLINE_SIZE || inlineProfile.nodeCount + profile.nodeCount > MAX_SIZE) { + continue; + } + + ProfiledInlinableCallSite inlinable = new ProfiledInlinableCallSite(inlineProfile, callSite); + double metric = (inlinable.callCount / inlineProfile.nodeCount) + ((double) inlinable.callCount / (double) target.originalInvokeCounter); + if (metric >= max) { + inliningDecision = inlinable; + max = metric; + } + } + + for (Node callSite : profile.inlinableCallSites) { + ((InlinableCallSite) callSite).resetCallCount(); + } + + if (inliningDecision != null) { + if (inliningDecision.callSite.inline(target)) { + if (TraceTruffleCompilation.getValue()) { + + String calls = String.format("%4s/%4s", inliningDecision.callCount, target.originalInvokeCounter); + String nodes = String.format("%3s/%3s", inliningDecision.profile.nodeCount, profile.nodeCount); + + OUT.printf("[truffle] inlined %-50s |Nodes %6s |Calls %6s |into %s\n", inliningDecision.callSite, nodes, calls, target.getRootNode()); + } + return true; + } + } + return false; + } + + private static class ProfiledInlinableCallSite { + + final CallTargetProfile profile; + final InlinableCallSite callSite; + final int callCount; + + public ProfiledInlinableCallSite(CallTargetProfile profile, InlinableCallSite callSite) { + this.profile = profile; + this.callSite = callSite; + this.callCount = callSite.getCallCount(); + } + } + + private static class CallTargetProfile { + + final Node root; + final int nodeCount; + final List inlinableCallSites = new ArrayList<>(); + + public CallTargetProfile(Node rootNode) { + root = rootNode; + + VisitorImpl impl = new VisitorImpl(); + root.accept(impl); + + this.nodeCount = impl.visitedCount; + } + + private class VisitorImpl implements NodeVisitor { + + int visitedCount; + + @Override + public boolean visit(Node node) { + if (node instanceof RootNode && node != root) { + return false; + } + + if (node instanceof InlinableCallSite) { + inlinableCallSites.add(node); + } + visitedCount++; + return true; + } + } + } + } +} diff -r 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PackedFrameImpl.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PackedFrameImpl.java Mon Jun 24 10:25:41 2013 +0200 @@ -0,0 +1,42 @@ +/* + * 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 com.oracle.truffle.api.frame.*; + +/** + * Implementation of a packed frame that contains only a raw pointer to the native stack. This + * packed frame is only handed out by Truffle compiled methods. + * + */ +public class PackedFrameImpl implements PackedFrame { + + private long stackPointer; + + @Override + public VirtualFrame unpack() { + return unpackNative(); + } + + private native VirtualFrame unpackNative(); +} diff -r 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java Mon Jun 24 10:25:41 2013 +0200 @@ -0,0 +1,310 @@ +/* + * 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.compiler.GraalDebugConfig.*; +import static com.oracle.graal.phases.GraalOptions.*; +import static com.oracle.graal.truffle.TruffleCompilerOptions.*; + +import java.util.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.runtime.*; +import com.oracle.graal.debug.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.graph.Node; +import com.oracle.graal.hotspot.*; +import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.java.*; +import com.oracle.graal.loop.*; +import com.oracle.graal.nodes.*; +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.util.*; +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.*; +import com.oracle.graal.truffle.nodes.*; +import com.oracle.graal.truffle.nodes.NewFrameNode.VirtualOnlyInstanceNode; +import com.oracle.graal.truffle.phases.*; +import com.oracle.graal.truffle.printer.*; +import com.oracle.graal.truffle.printer.method.*; +import com.oracle.graal.virtual.phases.ea.*; +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; + +/** + * Class performing the partial evaluation starting from the root node of an AST. + */ +public class PartialEvaluator { + + private final MetaAccessProvider metaAccessProvider; + private final ResolvedJavaType nodeClass; + private final ResolvedJavaMethod executeHelperMethod; + private final CustomCanonicalizer customCanonicalizer; + private final ResolvedJavaType[] skippedExceptionTypes; + private final Replacements replacements; + private Set constantReceivers; + private final HotSpotGraphCache cache; + + public PartialEvaluator(GraalCodeCacheProvider runtime, MetaAccessProvider metaAccessProvider) { + this.metaAccessProvider = metaAccessProvider; + this.nodeClass = runtime.lookupJavaType(com.oracle.truffle.api.nodes.Node.class); + this.customCanonicalizer = new PartialEvaluatorCanonicalizer(runtime, nodeClass); + this.skippedExceptionTypes = TruffleCompilerImpl.getSkippedExceptionTypes(metaAccessProvider); + this.replacements = Graal.getRequiredCapability(Replacements.class); + this.cache = HotSpotGraalRuntime.graalRuntime().getCache(); + + try { + executeHelperMethod = runtime.lookupJavaMethod(OptimizedCallTarget.class.getDeclaredMethod("executeHelper", PackedFrame.class, Arguments.class)); + } catch (NoSuchMethodException ex) { + throw new RuntimeException(ex); + } + } + + public StructuredGraph createGraph(final OptimizedCallTarget node, final Assumptions assumptions) { + if (Dump.getValue() != null && Dump.getValue().contains("Truffle")) { + RootNode root = node.getRootNode(); + if (root != null) { + new GraphPrintVisitor().beginGroup("TruffleGraph").beginGraph(node.toString()).visit(root).printToNetwork(); + } + } + + if (TraceTruffleCompilationDetails.getValue()) { + constantReceivers = new HashSet<>(); + } + + final GraphBuilderConfiguration config = GraphBuilderConfiguration.getDefault(); + config.setSkippedExceptionTypes(skippedExceptionTypes); + + final StructuredGraph graph = new StructuredGraph(executeHelperMethod); + + if (TruffleInlinePrinter.getValue()) { + InlinePrinterProcessor.initialize(); + } + + Debug.scope("createGraph", graph, new Runnable() { + + @Override + public void run() { + new GraphBuilderPhase(metaAccessProvider, config, TruffleCompilerImpl.Optimizations).apply(graph); + + // Replace thisNode with constant. + LocalNode thisNode = graph.getLocal(0); + 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); + + // Intrinsify methods. + new ReplaceIntrinsicsPhase(replacements).apply(graph); + + NewFrameNode newFrameNode = graph.getNodes(NewFrameNode.class).first(); + if (newFrameNode == null) { + throw GraalInternalError.shouldNotReachHere("frame not found"); + } + + Debug.dump(graph, "Before inlining"); + + // Make sure frame does not escape. + expandTree(config, graph, newFrameNode, assumptions); + + if (TruffleInlinePrinter.getValue()) { + InlinePrinterProcessor.printTree(); + InlinePrinterProcessor.reset(); + } + + if (TraceTruffleCompilationDetails.getValue() && constantReceivers != null) { + DebugHistogram histogram = Debug.createHistogram("Expanded Truffle Nodes"); + for (Constant c : constantReceivers) { + histogram.add(c.asObject().getClass().getSimpleName()); + } + histogram.print(TTY.out().out()); + } + + // 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); + + InliningPhase inliningPhase = new InliningPhase(metaAccessProvider, null, replacements, assumptions, cache, plan, OptimisticOptimizations.NONE); + inliningPhase.setCustomCanonicalizer(customCanonicalizer); + inliningPhase.apply(graph); + + // 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()); + throw GraphUtil.approxSourceException(neverPartOfCompilationNode, exception); + } + + // EA frame and clean up. + new VerifyFrameDoesNotEscapePhase().apply(graph, false); + new PartialEscapePhase(false, new CanonicalizerPhase(!AOTCompilation.getValue())).apply(graph, new HighTierContext(metaAccessProvider, assumptions, replacements)); + new VerifyNoIntrinsicsLeftPhase().apply(graph, false); + for (MaterializeFrameNode materializeNode : graph.getNodes(MaterializeFrameNode.class).snapshot()) { + materializeNode.replaceAtUsages(materializeNode.getFrame()); + graph.removeFixed(materializeNode); + } + for (VirtualOnlyInstanceNode virtualOnlyNode : graph.getNodes(VirtualOnlyInstanceNode.class)) { + virtualOnlyNode.setAllowMaterialization(true); + } + + // 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) { + 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)); + } + 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(config, methodCallTargetNode.targetMethod(), methodCallTargetNode.arguments(), assumptions, !AOTCompilation.getValue()); + otherNewFrame = inlineGraph.getNodes(NewFrameNode.class).first(); + } + int nodeCountBefore = graph.getNodeCount(); + Map mapping = 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); + } + + if (newFrameNode.isAlive() && newFrameNode.usages().isNotEmpty()) { + expandTree(config, graph, newFrameNode, assumptions); + } + + if (otherNewFrame != null) { + otherNewFrame = (NewFrameNode) mapping.get(otherNewFrame); + if (otherNewFrame.isAlive() && otherNewFrame.usages().isNotEmpty()) { + expandTree(config, graph, otherNewFrame, assumptions); + } + } + } + } + } + } + + private StructuredGraph parseGraph(final GraphBuilderConfiguration config, final ResolvedJavaMethod targetMethod, final NodeInputList arguments, final Assumptions assumptions, + final boolean canonicalizeReads) { + + final StructuredGraph graph = new StructuredGraph(targetMethod); + Debug.scope("parseGraph", targetMethod, new Runnable() { + + @Override + public void run() { + new GraphBuilderPhase(metaAccessProvider, config, TruffleCompilerImpl.Optimizations).apply(graph); + // Pass on constant arguments. + for (LocalNode local : graph.getNodes(LocalNode.class)) { + ValueNode arg = arguments.get(local.index()); + if (arg instanceof NewFrameNode) { + local.setStamp(arg.stamp()); + } else if (arg.isConstant()) { + Constant constant = arg.asConstant(); + local.replaceAndDelete(ConstantNode.forConstant(constant, metaAccessProvider, graph)); + } + } + + // Canonicalize / constant propagate. + new CanonicalizerPhase.Instance(metaAccessProvider, assumptions, canonicalizeReads, null, customCanonicalizer).apply(graph); + + // Intrinsify methods. + new ReplaceIntrinsicsPhase(replacements).apply(graph); + + // Inline trivial getter methods + new InlineTrivialGettersPhase(metaAccessProvider, assumptions, customCanonicalizer).apply(graph); + + // Convert deopt to guards. + new ConvertDeoptimizeToGuardPhase().apply(graph); + + if (graph.hasLoops()) { + boolean unrolled; + do { + unrolled = false; + LoopsData loopsData = new LoopsData(graph); + 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; + } + } + } + } while (unrolled); + } + } + + 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; + } +} diff -r 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluatorCanonicalizer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluatorCanonicalizer.java Mon Jun 24 10:25:41 2013 +0200 @@ -0,0 +1,108 @@ +/* + * 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 java.lang.reflect.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.extended.*; +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; + +final class PartialEvaluatorCanonicalizer implements CanonicalizerPhase.CustomCanonicalizer { + + private final MetaAccessProvider runtime; + private final ResolvedJavaType nodeClass; + + PartialEvaluatorCanonicalizer(MetaAccessProvider runtime, ResolvedJavaType nodeClass) { + this.runtime = runtime; + 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, this.runtime, 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, this.runtime, node.graph()); + } + } + } else if (node instanceof UnsafeLoadNode) { + UnsafeLoadNode unsafeLoadNode = (UnsafeLoadNode) node; + if (unsafeLoadNode.offset().isConstant()) { + long offset = unsafeLoadNode.offset().asConstant().asLong() + unsafeLoadNode.displacement(); + ResolvedJavaType type = unsafeLoadNode.object().objectStamp().type(); + ResolvedJavaField field = recursiveFindFieldWithOffset(type, offset); + if (field != null) { + return node.graph().add(new LoadFieldNode(unsafeLoadNode.object(), field)); + } + } + } else if (node instanceof UnsafeStoreNode) { + UnsafeStoreNode unsafeStoreNode = (UnsafeStoreNode) node; + if (unsafeStoreNode.offset().isConstant()) { + long offset = unsafeStoreNode.offset().asConstant().asLong() + unsafeStoreNode.displacement(); + ResolvedJavaType type = unsafeStoreNode.object().objectStamp().type(); + ResolvedJavaField field = recursiveFindFieldWithOffset(type, offset); + if (field != null) { + StoreFieldNode storeFieldNode = node.graph().add(new StoreFieldNode(unsafeStoreNode.object(), field, unsafeStoreNode.value())); + storeFieldNode.setStateAfter(unsafeStoreNode.stateAfter()); + return storeFieldNode; + } + } + } + + return node; + } + + private ResolvedJavaField recursiveFindFieldWithOffset(ResolvedJavaType type, long offset) { + if (type != null) { + ResolvedJavaField field = type.findInstanceFieldWithOffset(offset); + if (field != null) { + return field; + } + return recursiveFindFieldWithOffset(type.getSuperclass(), offset); + } + return null; + } +} diff -r 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompiler.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompiler.java Mon Jun 24 10:25:41 2013 +0200 @@ -0,0 +1,34 @@ +/* + * 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 com.oracle.graal.api.code.*; + +/** + * Interface of the Truffle compiler producing an {@link InstalledCode} object from the partial + * evaluation starting with the AST represented by the given {@link OptimizedCallTarget} node. + */ +public interface TruffleCompiler { + + InstalledCode compile(OptimizedCallTarget node); +} diff -r 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java Mon Jun 24 10:25:41 2013 +0200 @@ -0,0 +1,206 @@ +/* + * 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.api.code.CodeUtil.*; +import static com.oracle.graal.compiler.GraalDebugConfig.*; + +import java.util.*; +import java.util.concurrent.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.code.Assumptions.Assumption; +import com.oracle.graal.api.code.CallingConvention.Type; +import com.oracle.graal.api.meta.*; +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.hotspot.*; +import com.oracle.graal.java.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.phases.*; +import com.oracle.graal.phases.PhasePlan.PhasePosition; +import com.oracle.graal.phases.tiers.*; +import com.oracle.graal.printer.*; +import com.oracle.graal.truffle.nodes.*; +import com.oracle.truffle.api.nodes.*; + +/** + * Implementation of the Truffle compiler using Graal. + */ +public class TruffleCompilerImpl implements TruffleCompiler { + + private final GraalCodeCacheProvider runtime; + private final Suites suites; + private final PartialEvaluator nodeCompiler; + private final MetaAccessProvider metaAccessProvider; + private final Replacements replacements; + private final Backend backend; + private final ResolvedJavaType[] skippedExceptionTypes; + private final HotSpotGraalRuntime graalRuntime; + + private static final Class[] SKIPPED_EXCEPTION_CLASSES = new Class[]{SlowPathException.class, UnexpectedResultException.class, ArithmeticException.class}; + + public static final OptimisticOptimizations Optimizations = OptimisticOptimizations.ALL.remove(OptimisticOptimizations.Optimization.UseExceptionProbability, + OptimisticOptimizations.Optimization.RemoveNeverExecutedCode); + + public TruffleCompilerImpl() { + this.runtime = Graal.getRequiredCapability(GraalCodeCacheProvider.class); + this.suites = Graal.getRequiredCapability(SuitesProvider.class).createSuites(); + this.metaAccessProvider = Graal.getRequiredCapability(MetaAccessProvider.class); + this.backend = Graal.getRequiredCapability(Backend.class); + this.replacements = Graal.getRequiredCapability(Replacements.class); + this.graalRuntime = HotSpotGraalRuntime.graalRuntime(); + + this.nodeCompiler = new PartialEvaluator(runtime, metaAccessProvider); + this.skippedExceptionTypes = getSkippedExceptionTypes(metaAccessProvider); + + if (DebugEnabled.getValue()) { + DebugEnvironment.initialize(System.out); + } + } + + static ResolvedJavaType[] getSkippedExceptionTypes(MetaAccessProvider metaAccessProvider) { + ResolvedJavaType[] skippedExceptionTypes = new ResolvedJavaType[SKIPPED_EXCEPTION_CLASSES.length]; + for (int i = 0; i < SKIPPED_EXCEPTION_CLASSES.length; i++) { + skippedExceptionTypes[i] = metaAccessProvider.lookupJavaType(SKIPPED_EXCEPTION_CLASSES[i]); + } + return skippedExceptionTypes; + } + + public InstalledCode compile(final OptimizedCallTarget compilable) { + Object[] debug = new Object[]{new DebugDumpScope("Truffle: " + compilable)}; + return Debug.scope("Truffle", debug, new Callable() { + + @Override + public InstalledCode call() throws Exception { + return compileMethodImpl(compilable); + } + }); + } + + private InstalledCode compileMethodImpl(final OptimizedCallTarget compilable) { + final StructuredGraph graph; + final GraphBuilderConfiguration config = GraphBuilderConfiguration.getDefault(); + config.setSkippedExceptionTypes(skippedExceptionTypes); + graalRuntime.evictDeoptedGraphs(); + + compilable.timeCompilationStarted = System.nanoTime(); + Assumptions assumptions = new Assumptions(true); + graph = nodeCompiler.createGraph(compilable, assumptions); + compilable.timePartialEvaluationFinished = System.nanoTime(); + compilable.nodeCountPartialEval = graph.getNodeCount(); + InstalledCode compiledMethod = compileMethodHelper(graph, config, compilable, assumptions); + compilable.timeCompilationFinished = System.nanoTime(); + compilable.nodeCountLowered = graph.getNodeCount(); + return compiledMethod; + } + + public InstalledCode compileMethodHelper(final StructuredGraph graph, final GraphBuilderConfiguration config, final Assumptions assumptions) { + return compileMethodHelper(graph, config, null, assumptions); + } + + public InstalledCode compileMethodHelper(final StructuredGraph graph, final GraphBuilderConfiguration config, final OptimizedCallTarget compilable, final Assumptions assumptions) { + final PhasePlan plan = createPhasePlan(config); + + Debug.scope("TruffleFinal", graph, new Runnable() { + + @Override + public void run() { + Debug.dump(graph, "After TruffleTier"); + } + }); + + final Graph graphCopy = graph.copy(); + + final CompilationResult result = Debug.scope("TruffleGraal", new Callable() { + + @Override + public CompilationResult call() { + CallingConvention cc = getCallingConvention(runtime, Type.JavaCallee, graph.method(), false); + return GraalCompiler.compileGraph(graph, cc, graph.method(), runtime, replacements, backend, runtime.getTarget(), null, plan, OptimisticOptimizations.ALL, new SpeculationLog(), suites); + } + }); + + List validAssumptions = new ArrayList<>(); + Assumptions newAssumptions = new Assumptions(true); + if (assumptions != null) { + for (Assumption assumption : assumptions.getAssumptions()) { + processAssumption(newAssumptions, assumption, validAssumptions); + } + } + + if (result.getAssumptions() != null) { + for (Assumption assumption : result.getAssumptions().getAssumptions()) { + processAssumption(newAssumptions, assumption, validAssumptions); + } + } + + result.setAssumptions(newAssumptions); + + InstalledCode compiledMethod = Debug.scope("CodeInstall", new Object[]{graph.method()}, new Callable() { + + @Override + public InstalledCode call() throws Exception { + InstalledCode installedCode = runtime.addMethod(graph.method(), result, graphCopy); + if (installedCode != null) { + Debug.dump(new Object[]{result, installedCode}, "After code installation"); + } + return installedCode; + } + }); + + for (AssumptionValidAssumption a : validAssumptions) { + a.getAssumption().registerInstalledCode(compiledMethod); + } + + if (Debug.isLogEnabled()) { + Debug.log(runtime.disassemble(result, compiledMethod)); + } + if (compilable != null) { + compilable.codeSize = result.getTargetCodeSize(); + } + return compiledMethod; + } + + private PhasePlan createPhasePlan(final GraphBuilderConfiguration config) { + final PhasePlan phasePlan = new PhasePlan(); + GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(metaAccessProvider, config, TruffleCompilerImpl.Optimizations); + phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase); + return phasePlan; + } + + public void processAssumption(Assumptions newAssumptions, Assumption assumption, List manual) { + if (assumption != null) { + if (assumption instanceof AssumptionValidAssumption) { + AssumptionValidAssumption assumptionValidAssumption = (AssumptionValidAssumption) assumption; + manual.add(assumptionValidAssumption); + } else { + newAssumptions.record(assumption); + } + } + } +} diff -r 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java Mon Jun 24 10:25:41 2013 +0200 @@ -0,0 +1,69 @@ +/* + * 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 com.oracle.graal.options.*; + +/** + * Options for the Truffle compiler. + */ +public class TruffleCompilerOptions { + + // @formatter:off + // configuration + /** + * Instructs the Truffle Compiler to compile call targets only if their name contains at least one element of a comma-separated list of includes. + * Excludes are prefixed with a tilde (~). + * + * The format in EBNF: + *
+     * CompileOnly = Element, { ',', Element } ;
+     * Element = Include | '~' Exclude ;
+     * 
+ */ + @Option(help = "") + public static final OptionValue TruffleCompileOnly = new OptionValue<>(null); + @Option(help = "") + public static final OptionValue TruffleCompilationThreshold = new OptionValue<>(1000); + @Option(help = "") + public static final OptionValue TruffleInvalidationReprofileCount = new OptionValue<>(3); + @Option(help = "") + public static final OptionValue TruffleInliningReprofileCount = new OptionValue<>(100); + @Option(help = "") + public static final OptionValue TruffleFunctionInlining = new OptionValue<>(true); + @Option(help = "") + public static final OptionValue TruffleConstantUnrollLimit = new OptionValue<>(32); + + // tracing + @Option(help = "") + public static final OptionValue TraceTruffleCompilation = new OptionValue<>(true); + @Option(help = "") + public static final OptionValue TraceTruffleCompilationDetails = new OptionValue<>(false); + @Option(help = "") + public static final OptionValue TruffleInlinePrinter = new OptionValue<>(false); + @Option(help = "") + public static final OptionValue TraceTruffleCompilationExceptions = new OptionValue<>(true); + @Option(help = "") + public static final OptionValue TruffleCompilationExceptionsAreFatal = new OptionValue<>(true); + // @formatter:on +} diff -r 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/AssumptionNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/AssumptionNode.java Mon Jun 24 10:25:41 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.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 AssumptionNode(Invoke invoke) { + super(invoke); + assert super.arguments.size() == 1; + } + + private ValueNode getAssumption() { + return arguments.first(); + } + + public void simplify(SimplifierTool tool) { + ValueNode assumption = getAssumption(); + if (tool.assumptions() != null && assumption.isConstant()) { + Constant c = assumption.asConstant(); + assert c.getKind() == Kind.Object; + Object object = c.asObject(); + OptimizedAssumption assumptionObject = (OptimizedAssumption) object; + StructuredGraph graph = graph(); + if (assumptionObject.isValid()) { + tool.assumptions().record(new AssumptionValidAssumption(assumptionObject)); + if (super.getReturnType().getKind() == Kind.Boolean) { + graph.replaceFixedWithFloating(this, ConstantNode.forBoolean(true, graph())); + } else { + graph.removeFixed(this); + } + } else { + if (super.getReturnType().getKind() == Kind.Boolean) { + graph.replaceFixedWithFloating(this, ConstantNode.forBoolean(false, graph())); + } else { + tool.deleteBranch(this.next()); + this.replaceAndDelete(graph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.None))); + } + } + } + } +} diff -r 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/AssumptionValidAssumption.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/AssumptionValidAssumption.java Mon Jun 24 10:25:41 2013 +0200 @@ -0,0 +1,41 @@ +/* + * 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 com.oracle.graal.api.code.*; +import com.oracle.graal.truffle.*; + +public class AssumptionValidAssumption extends Assumptions.Assumption { + + private static final long serialVersionUID = 2010244979610891262L; + + private OptimizedAssumption assumption; + + public AssumptionValidAssumption(OptimizedAssumption assumption) { + this.assumption = assumption; + } + + public OptimizedAssumption getAssumption() { + return assumption; + } +} diff -r 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/BailoutNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/BailoutNode.java Mon Jun 24 10:25:41 2013 +0200 @@ -0,0 +1,46 @@ +/* + * 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 com.oracle.graal.api.code.*; +import com.oracle.graal.nodes.*; +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 BailoutNode(Invoke invoke) { + super(invoke); + assert arguments.size() == 1; + } + + @Override + public ValueNode canonical(CanonicalizerTool tool) { + ValueNode arg = arguments.get(0); + String message = ""; + if (arg.isConstant()) { + message = (String) arg.asConstant().asObject(); + } + throw new BailoutException(message); + } +} diff -r 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/CompilationConstantNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/CompilationConstantNode.java Mon Jun 24 10:25:41 2013 +0200 @@ -0,0 +1,42 @@ +/* + * 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 com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; + +public class CompilationConstantNode extends NeverPartOfCompilationNode implements Canonicalizable { + + public CompilationConstantNode(Invoke invoke) { + super(invoke, "The value could not be reduced to a compile time constant."); + assert arguments.size() == 1; + } + + @Override + public ValueNode canonical(CanonicalizerTool tool) { + if (arguments.get(0).isConstant()) { + return arguments.get(0); + } + return this; + } +} diff -r 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/FrameAccessNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/FrameAccessNode.java Mon Jun 24 10:25:41 2013 +0200 @@ -0,0 +1,160 @@ +/* + * 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 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.*; +import com.oracle.graal.nodes.java.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; +import com.oracle.truffle.api.frame.*; + +/** + * Base node class for the intrinsic nodes for read and write access to a Truffle frame. + */ +public abstract class FrameAccessNode extends FixedWithNextNode implements Simplifiable { + + @Input private ValueNode frame; + @Input private ValueNode slot; + protected final ResolvedJavaField field; + protected final Kind slotKind; + + public FrameAccessNode(Stamp stamp, Kind slotKind, ValueNode frame, ValueNode slot, ResolvedJavaField field) { + super(stamp); + this.slotKind = slotKind; + this.frame = frame; + this.slot = slot; + this.field = field; + } + + public ValueNode getFrame() { + return frame; + } + + public ValueNode getSlot() { + return slot; + } + + public Kind getSlotKind() { + return slotKind; + } + + protected int getSlotIndex() { + return getFrameSlot().getIndex(); + } + + protected boolean isFrameSlotConstant() { + return slot.isConstant(); + } + + protected FrameSlot getFrameSlot() { + assert isFrameSlotConstant() : slot; + return (FrameSlot) slot.asConstant().asObject(); + } + + protected final void insertDeoptimization(VirtualizerTool tool) { + LogicNode contradiction = LogicConstantNode.contradiction(graph()); + FixedGuardNode fixedGuard = new FixedGuardNode(contradiction, DeoptimizationReason.UnreachedCode, DeoptimizationAction.InvalidateReprofile); + tool.addNode(fixedGuard); + } + + @Override + public String toString(Verbosity verbosity) { + if (verbosity == Verbosity.Name) { + return super.toString(verbosity) + getSlotKind().name() + (isFrameSlotConstant() ? " " + getFrameSlot() : ""); + } else { + return super.toString(verbosity); + } + } + + protected final ValueNode getSlotOffset(int scale, MetaAccessProvider metaAccessProvider) { + if (isFrameSlotConstant()) { + return ConstantNode.forInt(getSlotIndex() * scale, graph()); + } else { + LoadFieldNode loadFrameSlotIndex = graph().add(new LoadFieldNode(getSlot(), metaAccessProvider.lookupJavaField(getFrameSlotIndexField()))); + graph().addBeforeFixed(this, loadFrameSlotIndex); + return scale == 1 ? loadFrameSlotIndex : IntegerArithmeticNode.mul(loadFrameSlotIndex, ConstantNode.forInt(scale, graph())); + } + } + + private static Field getFrameSlotIndexField() { + try { + return FrameSlotImpl.class.getDeclaredField("index"); + } catch (NoSuchFieldException e) { + throw new RuntimeException(e); + } + } + + protected final boolean isValidAccessKind() { + if (getSlotKind() == Kind.Byte) { + // tag access + return true; + } + + return getSlotKind() == getGraalKind(getFrameSlot().getKind()); + } + + private static Kind getGraalKind(FrameSlotKind kind) { + switch (kind) { + case Object: + return Kind.Object; + case Long: + return Kind.Long; + case Int: + return Kind.Int; + case Double: + return Kind.Double; + case Float: + return Kind.Float; + case Boolean: + return Kind.Boolean; + case Illegal: + default: + return Kind.Illegal; + } + } + + @Override + public final void simplify(SimplifierTool tool) { + if (isFrameSlotConstant()) { + if (!isValidAccessKind()) { + tool.deleteBranch(this.next()); + this.replaceAndDelete(graph().add(new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.UnreachedCode))); + } + } + } + + @Override + public Map getDebugProperties(Map map) { + Map properties = super.getDebugProperties(map); + if (isFrameSlotConstant()) { + properties.put("frameSlot", getFrameSlot().toString()); + } + return properties; + } +} diff -r 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/FrameGetNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/FrameGetNode.java Mon Jun 24 10:25:41 2013 +0200 @@ -0,0 +1,96 @@ +/* + * 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 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.*; +import com.oracle.graal.nodes.java.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; +import com.oracle.graal.nodes.virtual.*; +import com.oracle.graal.truffle.*; +import com.oracle.truffle.api.frame.*; + +/** + * Intrinsic node for read access to a Truffle frame. + */ +@NodeInfo(nameTemplate = "FrameGet{p#slotKind/s}{p#frameSlot/s}") +public class FrameGetNode extends FrameAccessNode implements IterableNodeType, Virtualizable, Lowerable { + + public FrameGetNode(Kind kind, ValueNode frame, ValueNode slot, ResolvedJavaField field) { + super(StampFactory.forKind(kind), kind, frame, slot, field); + } + + @Override + public void virtualize(VirtualizerTool tool) { + if (!isFrameSlotConstant()) { + return; + } + assert isValidAccessKind(); + State virtualFrame = tool.getObjectState(getFrame()); + if (virtualFrame == null || virtualFrame.getState() != EscapeState.Virtual) { + return; + } + assert virtualFrame.getVirtualObject().type() == NewFrameNode.FRAME_TYPE : virtualFrame; + VirtualInstanceNode virtualFrameObject = (VirtualInstanceNode) virtualFrame.getVirtualObject(); + int arrayFieldIndex = virtualFrameObject.fieldIndex(field); + State virtualArray = tool.getObjectState(virtualFrame.getEntry(arrayFieldIndex)); + assert virtualArray != null; + ValueNode result = virtualArray.getEntry(getSlotIndex()); + State virtualResult = tool.getObjectState(result); + if (virtualResult != null) { + tool.replaceWithVirtual(virtualResult.getVirtualObject()); + } else { + tool.replaceWithValue(result); + } + } + + @Override + public void lower(LoweringTool tool, LoweringType loweringType) { + assert !(getFrame() instanceof NewFrameNode); + StructuredGraph structuredGraph = graph(); + + LoadFieldNode loadFieldNode = graph().add(new LoadFieldNode(getFrame(), field)); + structuredGraph.addBeforeFixed(this, loadFieldNode); + FixedWithNextNode loadNode; + if (!getSlotKind().isPrimitive()) { + ValueNode slotIndex = getSlotOffset(1, tool.getRuntime()); + loadNode = graph().add(new LoadIndexedNode(loadFieldNode, slotIndex, Kind.Object)); + } else if (getSlotKind() == Kind.Byte) { + ValueNode slotIndex = getSlotOffset(1, tool.getRuntime()); + loadNode = graph().add(new LoadIndexedNode(loadFieldNode, slotIndex, Kind.Byte)); + } else { + ValueNode slotOffset = getSlotOffset(Unsafe.ARRAY_LONG_INDEX_SCALE, tool.getRuntime()); + loadNode = graph().add(new UnsafeLoadNode(loadFieldNode, Unsafe.ARRAY_LONG_BASE_OFFSET, slotOffset, getSlotKind())); + } + structuredGraph.replaceFixedWithFixed(this, loadNode); + } + + @NodeIntrinsic + public static native T get(@ConstantNodeParameter Kind kind, FrameWithoutBoxing frame, FrameSlot slot, @ConstantNodeParameter ResolvedJavaField field); +} diff -r 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/FrameSetNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/FrameSetNode.java Mon Jun 24 10:25:41 2013 +0200 @@ -0,0 +1,117 @@ +/* + * 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 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.*; +import com.oracle.graal.nodes.java.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; +import com.oracle.graal.nodes.virtual.*; +import com.oracle.graal.truffle.*; +import com.oracle.truffle.api.frame.*; + +/** + * Intrinsic node for write access to a Truffle frame. + */ +@NodeInfo(nameTemplate = "FrameSet{p#slotKind/s}{p#frameSlot/s}") +public class FrameSetNode extends FrameAccessNode implements IterableNodeType, Virtualizable, Lowerable { + + @Input private ValueNode value; + + public FrameSetNode(Kind kind, ValueNode frame, ValueNode frameSlot, ValueNode value, ResolvedJavaField field) { + super(StampFactory.forVoid(), kind, frame, frameSlot, field); + this.value = value; + } + + public ValueNode getValue() { + return value; + } + + @Override + public void virtualize(VirtualizerTool tool) { + if (!isFrameSlotConstant()) { + return; + } + assert isValidAccessKind(); + State virtualFrame = tool.getObjectState(getFrame()); + if (virtualFrame == null || virtualFrame.getState() != EscapeState.Virtual) { + return; + } + assert virtualFrame.getVirtualObject().type() == NewFrameNode.FRAME_TYPE : virtualFrame; + VirtualInstanceNode virtualFrameObject = (VirtualInstanceNode) virtualFrame.getVirtualObject(); + int arrayFieldIndex = virtualFrameObject.fieldIndex(field); + State virtualArray = tool.getObjectState(virtualFrame.getEntry(arrayFieldIndex)); + assert virtualArray != null; + ValueNode storedValue = value; + tool.setVirtualEntry(virtualArray, getSlotIndex(), storedValue); + tool.delete(); + } + + @Override + public void lower(LoweringTool tool, LoweringType loweringType) { + assert !(getFrame() instanceof NewFrameNode); + StructuredGraph structuredGraph = graph(); + + LoadFieldNode loadFieldNode = graph().add(new LoadFieldNode(getFrame(), field)); + structuredGraph.addBeforeFixed(this, loadFieldNode); + FixedWithNextNode storeNode; + if (!getSlotKind().isPrimitive()) { + ValueNode slotIndex = getSlotOffset(1, tool.getRuntime()); + storeNode = graph().add(new StoreIndexedNode(loadFieldNode, slotIndex, Kind.Object, value)); + } else if (getSlotKind() == Kind.Byte) { + ValueNode slotIndex = getSlotOffset(1, tool.getRuntime()); + storeNode = graph().add(new StoreIndexedNode(loadFieldNode, slotIndex, Kind.Byte, value)); + } else { + ValueNode slotOffset = getSlotOffset(Unsafe.ARRAY_LONG_INDEX_SCALE, tool.getRuntime()); + storeNode = graph().add(new UnsafeStoreNode(loadFieldNode, Unsafe.ARRAY_LONG_BASE_OFFSET, slotOffset, value, getSlotKind())); + } + structuredGraph.replaceFixedWithFixed(this, storeNode); + } + + @NodeIntrinsic + public static native void set(@ConstantNodeParameter Kind kind, FrameWithoutBoxing frame, FrameSlot slot, Object value, @ConstantNodeParameter ResolvedJavaField field); + + @NodeIntrinsic + public static native void set(@ConstantNodeParameter Kind kind, FrameWithoutBoxing frame, FrameSlot slot, byte value, @ConstantNodeParameter ResolvedJavaField field); + + @NodeIntrinsic + public static native void set(@ConstantNodeParameter Kind kind, FrameWithoutBoxing frame, FrameSlot slot, boolean value, @ConstantNodeParameter ResolvedJavaField field); + + @NodeIntrinsic + public static native void set(@ConstantNodeParameter Kind kind, FrameWithoutBoxing frame, FrameSlot slot, int value, @ConstantNodeParameter ResolvedJavaField field); + + @NodeIntrinsic + public static native void set(@ConstantNodeParameter Kind kind, FrameWithoutBoxing frame, FrameSlot slot, long value, @ConstantNodeParameter ResolvedJavaField field); + + @NodeIntrinsic + public static native void set(@ConstantNodeParameter Kind kind, FrameWithoutBoxing frame, FrameSlot slot, double value, @ConstantNodeParameter ResolvedJavaField field); + + @NodeIntrinsic + public static native void set(@ConstantNodeParameter Kind kind, FrameWithoutBoxing frame, FrameSlot slot, float value, @ConstantNodeParameter ResolvedJavaField field); +} diff -r 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/IntegerAddExactNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/IntegerAddExactNode.java Mon Jun 24 10:25:41 2013 +0200 @@ -0,0 +1,89 @@ +/* + * 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 com.oracle.graal.api.meta.*; +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.truffle.api.*; + +/** + * Node representing an exact integer addition that will throw an {@link ArithmeticException} in + * case the addition would overflow the 32 bit range. + */ +public class IntegerAddExactNode extends IntegerAddNode implements Canonicalizable, IntegerExactArithmeticNode { + + public IntegerAddExactNode(ValueNode x, ValueNode y) { + super(x.kind(), x, y); + assert x.kind() == y.kind() && (x.kind() == Kind.Int || x.kind() == Kind.Long); + } + + @Override + public boolean inferStamp() { + // TODO Should probably use a specialised version which understands that it can't overflow + return updateStamp(StampTool.add(x().integerStamp(), y().integerStamp())); + } + + @Override + public ValueNode canonical(CanonicalizerTool tool) { + if (x().isConstant() && !y().isConstant()) { + return graph().unique(new IntegerAddExactNode(y(), x())); + } + if (x().isConstant()) { + try { + if (kind() == Kind.Int) { + return ConstantNode.forInt(ExactMath.addExact(x().asConstant().asInt(), y().asConstant().asInt()), graph()); + } else { + assert kind() == Kind.Long; + return ConstantNode.forLong(ExactMath.addExact(x().asConstant().asLong(), y().asConstant().asLong()), graph()); + } + } catch (ArithmeticException ex) { + // The operation will result in an overflow exception, so do not canonicalize. + } + } else if (y().isConstant()) { + long c = y().asConstant().asLong(); + if (c == 0) { + return x(); + } + } + return this; + } + + @Override + public IntegerExactArithmeticSplitNode createSplit(AbstractBeginNode next, AbstractBeginNode deopt) { + return graph().add(new IntegerAddExactSplitNode(stamp(), x(), y(), next, deopt)); + } + + @Override + public void lower(LoweringTool tool, LoweringType loweringType) { + IntegerExactArithmeticSplitNode.lower(tool, this); + } + + @NodeIntrinsic + public static native int addExact(int a, int b); + + @NodeIntrinsic + public static native long addExact(long a, long b); +} diff -r 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/IntegerAddExactSplitNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/IntegerAddExactSplitNode.java Mon Jun 24 10:25:41 2013 +0200 @@ -0,0 +1,40 @@ +/* + * 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 com.oracle.graal.api.meta.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; + +public class IntegerAddExactSplitNode extends IntegerExactArithmeticSplitNode { + + public IntegerAddExactSplitNode(Stamp stamp, ValueNode x, ValueNode y, AbstractBeginNode next, AbstractBeginNode overflowSuccessor) { + super(stamp, x, y, next, overflowSuccessor); + } + + @Override + protected Value generateArithmetic(LIRGeneratorTool gen) { + return gen.emitAdd(gen.operand(getX()), gen.operand(getY())); + } +} diff -r 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/IntegerExactArithmeticNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/IntegerExactArithmeticNode.java Mon Jun 24 10:25:41 2013 +0200 @@ -0,0 +1,31 @@ +/* + * 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 com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; + +interface IntegerExactArithmeticNode extends Lowerable { + + IntegerExactArithmeticSplitNode createSplit(AbstractBeginNode next, AbstractBeginNode deopt); +} diff -r 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/IntegerExactArithmeticSplitNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/IntegerExactArithmeticSplitNode.java Mon Jun 24 10:25:41 2013 +0200 @@ -0,0 +1,95 @@ +/* + * 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 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.type.*; + +public abstract class IntegerExactArithmeticSplitNode extends ControlSplitNode implements LIRGenLowerable { + + @Successor private AbstractBeginNode overflowSuccessor; + @Successor private AbstractBeginNode next; + @Input private ValueNode x; + @Input private ValueNode y; + + public IntegerExactArithmeticSplitNode(Stamp stamp, ValueNode x, ValueNode y, AbstractBeginNode next, AbstractBeginNode overflowSuccessor) { + super(stamp); + this.x = x; + this.y = y; + this.overflowSuccessor = overflowSuccessor; + this.next = next; + } + + @Override + public double probability(AbstractBeginNode successor) { + return successor == next ? 1 : 0; + } + + @Override + public void setProbability(AbstractBeginNode successor, double value) { + assert probability(successor) == value; + } + + public AbstractBeginNode getNext() { + return next; + } + + public AbstractBeginNode getOverflowSuccessor() { + return overflowSuccessor; + } + + public ValueNode getX() { + return x; + } + + public ValueNode getY() { + return y; + } + + @Override + public void generate(LIRGenerator generator) { + generator.setResult(this, generateArithmetic(generator)); + generator.emitOverflowCheckBranch(generator.getLIRBlock(getNext()), generator.getLIRBlock(getOverflowSuccessor())); + } + + protected abstract Value generateArithmetic(LIRGeneratorTool generator); + + static void lower(LoweringTool tool, IntegerExactArithmeticNode node) { + FloatingNode floatingNode = (FloatingNode) node; + FixedWithNextNode previous = tool.lastFixedNode(); + FixedNode next = previous.next(); + previous.setNext(null); + DeoptimizeNode deopt = floatingNode.graph().add(new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.ArithmeticException)); + BeginNode normalBegin = floatingNode.graph().add(new BeginNode()); + normalBegin.setNext(next); + IntegerExactArithmeticSplitNode split = node.createSplit(normalBegin, BeginNode.begin(deopt)); + previous.setNext(split); + floatingNode.replaceAndDelete(split); + } +} diff -r 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/IntegerMulExactNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/IntegerMulExactNode.java Mon Jun 24 10:25:41 2013 +0200 @@ -0,0 +1,85 @@ +/* + * 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 com.oracle.graal.api.meta.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.truffle.api.*; + +/** + * Node representing an exact integer multiplication that will throw an {@link ArithmeticException} + * in case the addition would overflow the 32 bit range. + */ +public class IntegerMulExactNode extends IntegerMulNode implements Canonicalizable, IntegerExactArithmeticNode { + + public IntegerMulExactNode(ValueNode x, ValueNode y) { + super(x.kind(), x, y); + assert x.kind() == y.kind() && (x.kind() == Kind.Int || x.kind() == Kind.Long); + } + + @Override + public ValueNode canonical(CanonicalizerTool tool) { + if (x().isConstant() && !y().isConstant()) { + return graph().unique(new IntegerMulExactNode(y(), x())); + } + if (x().isConstant()) { + try { + if (kind() == Kind.Int) { + return ConstantNode.forInt(ExactMath.multiplyExact(x().asConstant().asInt(), y().asConstant().asInt()), graph()); + } else { + assert kind() == Kind.Long; + return ConstantNode.forLong(ExactMath.multiplyExact(x().asConstant().asLong(), y().asConstant().asLong()), graph()); + } + } catch (ArithmeticException ex) { + // The operation will result in an overflow exception, so do not canonicalize. + } + } else if (y().isConstant()) { + long c = y().asConstant().asLong(); + if (c == 1) { + return x(); + } + if (c == 0) { + return ConstantNode.defaultForKind(kind(), graph()); + } + } + return this; + } + + @Override + public IntegerExactArithmeticSplitNode createSplit(AbstractBeginNode next, AbstractBeginNode deopt) { + return graph().add(new IntegerMulExactSplitNode(stamp(), x(), y(), next, deopt)); + } + + @Override + public void lower(LoweringTool tool, LoweringType loweringType) { + IntegerExactArithmeticSplitNode.lower(tool, this); + } + + @NodeIntrinsic + public static native int multiplyExact(int a, int b); + + @NodeIntrinsic + public static native long multiplyExact(long a, long b); +} diff -r 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/IntegerMulExactSplitNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/IntegerMulExactSplitNode.java Mon Jun 24 10:25:41 2013 +0200 @@ -0,0 +1,40 @@ +/* + * 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 com.oracle.graal.api.meta.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; + +public class IntegerMulExactSplitNode extends IntegerExactArithmeticSplitNode { + + public IntegerMulExactSplitNode(Stamp stamp, ValueNode x, ValueNode y, AbstractBeginNode next, AbstractBeginNode overflowSuccessor) { + super(stamp, x, y, next, overflowSuccessor); + } + + @Override + protected Value generateArithmetic(LIRGeneratorTool gen) { + return gen.emitMul(gen.operand(getX()), gen.operand(getY())); + } +} diff -r 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/IntegerSubExactNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/IntegerSubExactNode.java Mon Jun 24 10:25:41 2013 +0200 @@ -0,0 +1,89 @@ +/* + * 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 com.oracle.graal.api.meta.*; +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.truffle.api.*; + +/** + * Node representing an exact integer substraction that will throw an {@link ArithmeticException} in + * case the addition would overflow the 32 bit range. + */ +public class IntegerSubExactNode extends IntegerSubNode implements Canonicalizable, IntegerExactArithmeticNode { + + public IntegerSubExactNode(ValueNode x, ValueNode y) { + super(x.kind(), x, y); + assert x.kind() == y.kind() && (x.kind() == Kind.Int || x.kind() == Kind.Long); + } + + @Override + public boolean inferStamp() { + // TODO Should probably use a specialised version which understands that it can't overflow + return updateStamp(StampTool.sub(x().integerStamp(), y().integerStamp())); + } + + @Override + public ValueNode canonical(CanonicalizerTool tool) { + if (x() == y()) { + return ConstantNode.forIntegerKind(kind(), 0, graph()); + } + if (x().isConstant() && y().isConstant()) { + try { + if (kind() == Kind.Int) { + return ConstantNode.forInt(ExactMath.subtractExact(x().asConstant().asInt(), y().asConstant().asInt()), graph()); + } else { + assert kind() == Kind.Long; + return ConstantNode.forLong(ExactMath.subtractExact(x().asConstant().asLong(), y().asConstant().asLong()), graph()); + } + } catch (ArithmeticException ex) { + // The operation will result in an overflow exception, so do not canonicalize. + } + } else if (y().isConstant()) { + long c = y().asConstant().asLong(); + if (c == 0) { + return x(); + } + } + return this; + } + + @Override + public IntegerExactArithmeticSplitNode createSplit(AbstractBeginNode next, AbstractBeginNode deopt) { + return graph().add(new IntegerSubExactSplitNode(stamp(), x(), y(), next, deopt)); + } + + @Override + public void lower(LoweringTool tool, LoweringType loweringType) { + IntegerExactArithmeticSplitNode.lower(tool, this); + } + + @NodeIntrinsic + public static native int subtractExact(int a, int b); + + @NodeIntrinsic + public static native long subtractExact(long a, long b); +} diff -r 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/IntegerSubExactSplitNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/IntegerSubExactSplitNode.java Mon Jun 24 10:25:41 2013 +0200 @@ -0,0 +1,40 @@ +/* + * 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 com.oracle.graal.api.meta.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; + +public class IntegerSubExactSplitNode extends IntegerExactArithmeticSplitNode { + + public IntegerSubExactSplitNode(Stamp stamp, ValueNode x, ValueNode y, AbstractBeginNode next, AbstractBeginNode overflowSuccessor) { + super(stamp, x, y, next, overflowSuccessor); + } + + @Override + protected Value generateArithmetic(LIRGeneratorTool gen) { + return gen.emitSub(gen.operand(getX()), gen.operand(getY())); + } +} diff -r 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/MaterializeFrameNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/MaterializeFrameNode.java Mon Jun 24 10:25:41 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.truffle.nodes; + +import com.oracle.graal.graph.Node.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.truffle.*; + +/** + * Intrinsic node for materializing a Truffle frame. + */ +@NodeInfo(nameTemplate = "MaterializeFrame{p#frame/s}") +public class MaterializeFrameNode extends FixedWithNextNode implements IterableNodeType { + + @Input private ValueNode frame; + + public MaterializeFrameNode(ValueNode frame) { + super(frame.stamp()); + this.frame = frame; + } + + public ValueNode getFrame() { + return frame; + } + + @NodeIntrinsic + public static native T materialize(FrameWithoutBoxing frame); +} diff -r 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/NeverInlineMacroNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/NeverInlineMacroNode.java Mon Jun 24 10:25:41 2013 +0200 @@ -0,0 +1,41 @@ +/* + * 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 com.oracle.graal.nodes.*; +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 NeverInlineMacroNode(Invoke invoke) { + super(invoke); + } + + @Override + public void lower(LoweringTool tool, LoweringType loweringType) { + InvokeNode invoke = createInvoke(); + graph().replaceFixedWithFixed(this, invoke); + invoke.setUseForInlining(false); + } +} diff -r 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/NeverPartOfCompilationNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/NeverPartOfCompilationNode.java Mon Jun 24 10:25:41 2013 +0200 @@ -0,0 +1,44 @@ +/* + * 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 com.oracle.graal.nodes.*; +import com.oracle.graal.replacements.nodes.*; + +public class NeverPartOfCompilationNode extends MacroNode implements com.oracle.graal.graph.Node.IterableNodeType { + + private final String message; + + public NeverPartOfCompilationNode(Invoke invoke) { + this(invoke, "This code path should never be part of a compilation."); + } + + public NeverPartOfCompilationNode(Invoke invoke, String message) { + super(invoke); + this.message = message; + } + + public final String getMessage() { + return message; + } +} diff -r 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/NewFrameNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/NewFrameNode.java Mon Jun 24 10:25:41 2013 +0200 @@ -0,0 +1,218 @@ +/* + * 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.util.*; + +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.*; +import com.oracle.graal.nodes.type.*; +import com.oracle.graal.nodes.util.*; +import com.oracle.graal.nodes.virtual.*; +import com.oracle.graal.truffle.*; +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; + +/** + * Intrinsic node representing the call for creating a frame in the {@link OptimizedCallTarget} + * class. + */ +public class NewFrameNode extends FixedWithNextNode implements IterableNodeType, VirtualizableAllocation, Canonicalizable { + + static final ResolvedJavaType FRAME_TYPE = Graal.getRequiredCapability(MetaAccessProvider.class).lookupJavaType(FrameWithoutBoxing.class); + + @Input private ValueNode descriptor; + @Input private ValueNode caller; + @Input private ValueNode arguments; + + public NewFrameNode(Stamp stamp, ValueNode descriptor, ValueNode caller, ValueNode arguments) { + super(stamp); + this.descriptor = descriptor; + this.caller = caller; + this.arguments = arguments; + } + + public NewFrameNode(ValueNode descriptor, ValueNode caller, ValueNode arguments) { + this(StampFactory.declaredNonNull(FRAME_TYPE), descriptor, caller, arguments); + } + + public ValueNode getDescriptor() { + return descriptor; + } + + public ValueNode getCaller() { + return caller; + } + + public ValueNode getArguments() { + return arguments; + } + + private FrameDescriptor getConstantFrameDescriptor() { + assert descriptor.isConstant() && !descriptor.isNullConstant(); + return (FrameDescriptor) descriptor.asConstant().asObject(); + } + + private int getFrameSize() { + return getConstantFrameDescriptor().getSize(); + } + + private static ResolvedJavaField findField(ResolvedJavaField[] fields, String fieldName) { + for (ResolvedJavaField field : fields) { + if (field.getName().equals(fieldName)) { + return field; + } + } + throw new RuntimeException("Frame field not found: " + fieldName); + } + + public static class VirtualOnlyInstanceNode extends VirtualInstanceNode implements Node.IterableNodeType { + + private boolean allowMaterialization; + + public VirtualOnlyInstanceNode(ResolvedJavaType type, ResolvedJavaField[] fields) { + super(type, fields); + } + + @Override + public ValueNode getMaterializedRepresentation(FixedNode fixed, ValueNode[] entries, int[] locks) { + if (allowMaterialization) { + return super.getMaterializedRepresentation(fixed, entries, locks); + } + return getMaterializedRepresentationHelper(this, fixed); + } + + public void setAllowMaterialization(boolean b) { + this.allowMaterialization = b; + } + } + + public static ValueNode getMaterializedRepresentationHelper(VirtualObjectNode virtualNode, FixedNode fixed) { + if (fixed instanceof MaterializeFrameNode || fixed instanceof AbstractEndNode) { + // We need to conservatively assume that a materialization of a virtual frame can also + // happen at a merge point. + return new AllocatedObjectNode(virtualNode); + } + String escapeReason; + if (fixed instanceof StoreFieldNode) { + escapeReason = "Must not store virtual frame object into a field."; + } else if (fixed instanceof Invoke) { + escapeReason = "Must not pass virtual frame object into an invoke that cannot be inlined."; + } else { + escapeReason = "Must not let virtual frame object escape at node " + fixed + "."; + } + + Throwable exception = new GraalInternalError(escapeReason + + " Insert a call to VirtualFrame.materialize() to convert the instance to a materialized frame object (source position of following stack trace is approximate)"); + throw GraphUtil.approxSourceException(fixed, exception); + } + + @Override + public void virtualize(VirtualizerTool tool) { + int frameSize = getFrameSize(); + + ResolvedJavaType frameType = stamp().javaType(tool.getMetaAccessProvider()); + ResolvedJavaField[] frameFields = frameType.getInstanceFields(true); + + ResolvedJavaField descriptorField = findField(frameFields, "descriptor"); + ResolvedJavaField callerField = findField(frameFields, "caller"); + ResolvedJavaField argumentsField = findField(frameFields, "arguments"); + ResolvedJavaField localsField = findField(frameFields, "locals"); + ResolvedJavaField primitiveLocalsField = findField(frameFields, "primitiveLocals"); + ResolvedJavaField tagsField = findField(frameFields, "tags"); + + VirtualObjectNode virtualFrame = new VirtualOnlyInstanceNode(frameType, frameFields); + VirtualObjectNode virtualFrameObjectArray = new VirtualArrayNode((ResolvedJavaType) localsField.getType().getComponentType(), frameSize); + VirtualObjectNode virtualFramePrimitiveArray = new VirtualArrayNode((ResolvedJavaType) primitiveLocalsField.getType().getComponentType(), frameSize); + VirtualObjectNode virtualFrameTagArray = new VirtualArrayNode((ResolvedJavaType) tagsField.getType().getComponentType(), frameSize); + + ValueNode[] objectArrayEntryState = new ValueNode[frameSize]; + ValueNode[] primitiveArrayEntryState = new ValueNode[frameSize]; + ValueNode[] tagArrayEntryState = new ValueNode[frameSize]; + + if (frameSize > 0) { + FrameDescriptor frameDescriptor = getConstantFrameDescriptor(); + ConstantNode objectDefault = ConstantNode.forObject(frameDescriptor.getTypeConversion().getDefaultValue(), tool.getMetaAccessProvider(), graph()); + ConstantNode tagDefault = ConstantNode.forByte((byte) 0, graph()); + for (int i = 0; i < frameSize; i++) { + objectArrayEntryState[i] = objectDefault; + primitiveArrayEntryState[i] = initialValue(frameDescriptor.getSlots().get(i).getKind()); + tagArrayEntryState[i] = tagDefault; + } + tool.getAssumptions().record(new AssumptionValidAssumption((OptimizedAssumption) frameDescriptor.getVersion())); + } + + tool.createVirtualObject(virtualFrameObjectArray, objectArrayEntryState, null); + tool.createVirtualObject(virtualFramePrimitiveArray, primitiveArrayEntryState, null); + tool.createVirtualObject(virtualFrameTagArray, tagArrayEntryState, null); + + assert frameFields.length == 6; + ValueNode[] frameEntryState = new ValueNode[frameFields.length]; + List frameFieldList = Arrays.asList(frameFields); + frameEntryState[frameFieldList.indexOf(descriptorField)] = getDescriptor(); + frameEntryState[frameFieldList.indexOf(callerField)] = getCaller(); + frameEntryState[frameFieldList.indexOf(argumentsField)] = getArguments(); + frameEntryState[frameFieldList.indexOf(localsField)] = virtualFrameObjectArray; + frameEntryState[frameFieldList.indexOf(primitiveLocalsField)] = virtualFramePrimitiveArray; + frameEntryState[frameFieldList.indexOf(tagsField)] = virtualFrameTagArray; + tool.createVirtualObject(virtualFrame, frameEntryState, null); + tool.replaceWithVirtual(virtualFrame); + } + + private ValueNode initialValue(FrameSlotKind kind) { + Kind graalKind = Kind.Long; + switch (kind) { + case Int: + graalKind = Kind.Int; + break; + case Double: + graalKind = Kind.Double; + break; + case Float: + graalKind = Kind.Float; + break; + case Boolean: + graalKind = Kind.Boolean; + break; + } + + return ConstantNode.defaultForKind(graalKind, graph()); + } + + @Override + public ValueNode canonical(CanonicalizerTool tool) { + if (usages().isEmpty()) { + return null; + } else { + return this; + } + } + + @NodeIntrinsic + public static native FrameWithoutBoxing allocate(FrameDescriptor descriptor, PackedFrame caller, Arguments args); +} diff -r 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/UnsafeCastMacroNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/UnsafeCastMacroNode.java Mon Jun 24 10:25:41 2013 +0200 @@ -0,0 +1,48 @@ +/* + * 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 com.oracle.graal.api.meta.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; + +public class UnsafeCastMacroNode extends NeverPartOfCompilationNode implements Canonicalizable { + + public UnsafeCastMacroNode(Invoke invoke) { + super(invoke, "The class of the unsafe cast could not be reduced to a compile time constant."); + assert arguments.size() == 2; + } + + @Override + public ValueNode canonical(CanonicalizerTool tool) { + if (arguments.get(1).isConstant()) { + Class c = (Class) arguments.get(1).asConstant().asObject(); + ResolvedJavaType lookupJavaType = tool.runtime().lookupJavaType(c); + Stamp s = StampFactory.declaredNonNull(lookupJavaType); + return graph().unique(new UnsafeCastNode(arguments.get(0), s)); + } + return this; + } +} diff -r 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/phases/InlineTrivialGettersPhase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/phases/InlineTrivialGettersPhase.java Mon Jun 24 10:25:41 2013 +0200 @@ -0,0 +1,76 @@ +/* + * 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 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/phases/ReplaceIntrinsicsPhase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/phases/ReplaceIntrinsicsPhase.java Mon Jun 24 10:25:41 2013 +0200 @@ -0,0 +1,59 @@ +/* + * 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 com.oracle.graal.debug.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.java.*; +import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.phases.*; +import com.oracle.graal.phases.common.*; + +/** + * Compiler phase for intrinsifying the access to the Truffle virtual frame. + */ +public class ReplaceIntrinsicsPhase extends Phase { + + private final Replacements replacements; + + public ReplaceIntrinsicsPhase(Replacements replacements) { + this.replacements = replacements; + } + + @Override + protected void run(StructuredGraph graph) { + for (MethodCallTargetNode methodCallTarget : graph.getNodes(MethodCallTargetNode.class)) { + if (methodCallTarget.isAlive()) { + InvokeKind invokeKind = methodCallTarget.invokeKind(); + if (invokeKind == InvokeKind.Static || invokeKind == InvokeKind.Special) { + StructuredGraph inlineGraph = replacements.getMethodSubstitution(methodCallTarget.targetMethod()); + if (inlineGraph != null) { + InliningUtil.inline(methodCallTarget.invoke(), inlineGraph, false); + Debug.dump(graph, "After inlining %s", methodCallTarget.targetMethod().toString()); + } + } + } + } + } +} diff -r 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/phases/VerifyFrameDoesNotEscapePhase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/phases/VerifyFrameDoesNotEscapePhase.java Mon Jun 24 10:25:41 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.truffle.phases; + +import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.java.*; +import com.oracle.graal.nodes.util.*; +import com.oracle.graal.phases.*; +import com.oracle.graal.truffle.nodes.*; + +/** + * Compiler phase for verifying that the Truffle virtual frame does not escape and can therefore be + * escape analyzed. + */ +public class VerifyFrameDoesNotEscapePhase extends Phase { + + @Override + protected void run(StructuredGraph graph) { + NewFrameNode frame = graph.getNodes(NewFrameNode.class).first(); + if (frame != null) { + for (MethodCallTargetNode callTarget : frame.usages().filter(MethodCallTargetNode.class)) { + if (callTarget.invoke() != null) { + Throwable exception = new VerificationError("Frame escapes at: %s#%s", callTarget, callTarget.targetMethod()); + throw GraphUtil.approxSourceException(callTarget, exception); + } + } + } + } +} diff -r 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/phases/VerifyNoIntrinsicsLeftPhase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/phases/VerifyNoIntrinsicsLeftPhase.java Mon Jun 24 10:25:41 2013 +0200 @@ -0,0 +1,48 @@ +/* + * 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 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.*; +import com.oracle.graal.truffle.nodes.*; + +/** + * Verification phase for checking that no frame intrinsic nodes introduced by the + * {@link PartialEvaluator} are still in the graph. + */ +public class VerifyNoIntrinsicsLeftPhase extends Phase { + + @Override + protected void run(StructuredGraph graph) { + verifyNoInstanceLeft(graph, NewFrameNode.class); + } + + public static void verifyNoInstanceLeft(StructuredGraph graph, Class clazz) { + if (graph.getNodes(clazz).count() != 0) { + throw new VerificationError("Found unexpected node(s): %s", graph.getNodes(clazz)); + } + } +} diff -r 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/CompilerAssertsSubstitutions.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/CompilerAssertsSubstitutions.java Mon Jun 24 10:25:41 2013 +0200 @@ -0,0 +1,62 @@ +/* + * 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.replacements.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.truffle.nodes.*; +import com.oracle.truffle.api.*; + +@ClassSubstitution(CompilerAsserts.class) +public class CompilerAssertsSubstitutions { + + @MacroSubstitution(macro = NeverPartOfCompilationNode.class, isStatic = true) + public static native void neverPartOfCompilation(); + + @MacroSubstitution(macro = CompilationConstantNode.class, isStatic = true) + public static native boolean compilationConstant(boolean value); + + @MacroSubstitution(macro = CompilationConstantNode.class, isStatic = true) + public static native byte compilationConstant(byte value); + + @MacroSubstitution(macro = CompilationConstantNode.class, isStatic = true) + public static native char compilationConstant(char value); + + @MacroSubstitution(macro = CompilationConstantNode.class, isStatic = true) + public static native short compilationConstant(short value); + + @MacroSubstitution(macro = CompilationConstantNode.class, isStatic = true) + public static native int compilationConstant(int value); + + @MacroSubstitution(macro = CompilationConstantNode.class, isStatic = true) + public static native long compilationConstant(long value); + + @MacroSubstitution(macro = CompilationConstantNode.class, isStatic = true) + public static native float compilationConstant(float value); + + @MacroSubstitution(macro = CompilationConstantNode.class, isStatic = true) + public static native double compilationConstant(double value); + + @MacroSubstitution(macro = CompilationConstantNode.class, isStatic = true) + public static native Object compilationConstant(Object value); +} diff -r 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/CompilerDirectivesSubstitutions.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/CompilerDirectivesSubstitutions.java Mon Jun 24 10:25:41 2013 +0200 @@ -0,0 +1,60 @@ +/* + * 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 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.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.replacements.nodes.*; +import com.oracle.graal.truffle.nodes.*; +import com.oracle.truffle.api.*; + +@ClassSubstitution(CompilerDirectives.class) +public class CompilerDirectivesSubstitutions { + + @MethodSubstitution + public static void transferToInterpreter() { + DeoptimizeNode.deopt(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.UnreachedCode); + } + + @MethodSubstitution + public static void interpreterOnly(@SuppressWarnings("unused") Runnable runnable) { + } + + @MethodSubstitution + public static T interpreterOnly(@SuppressWarnings("unused") Callable callable) throws Exception { + return null; + } + + @MethodSubstitution + public static boolean injectBranchProbability(double probability, boolean condition) { + return BranchProbabilityNode.probability(probability, condition); + } + + @MacroSubstitution(macro = BailoutNode.class, isStatic = true) + public static native void bailout(String reason); +} diff -r 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/DefaultCallTargetSubstitutions.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/DefaultCallTargetSubstitutions.java Mon Jun 24 10:25:41 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.truffle.substitutions; + +import com.oracle.graal.api.replacements.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.truffle.nodes.*; +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.impl.*; + +@ClassSubstitution(DefaultCallTarget.class) +public class DefaultCallTargetSubstitutions { + + @MacroSubstitution(macro = NeverInlineMacroNode.class, isStatic = false) + public static native Object call(DefaultCallTarget target, PackedFrame caller, Arguments args); +} diff -r 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/ExactMathSubstitutions.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/ExactMathSubstitutions.java Mon Jun 24 10:25:41 2013 +0200 @@ -0,0 +1,65 @@ +/* + * 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.replacements.*; +import com.oracle.graal.truffle.nodes.*; +import com.oracle.truffle.api.*; + +/** + * Intrinsics for exact math operations that throw an exception in case the operation would overflow + * the allowed range. + */ +@ClassSubstitution(ExactMath.class) +public class ExactMathSubstitutions { + + @MethodSubstitution + public static int addExact(int x, int y) { + return IntegerAddExactNode.addExact(x, y); + } + + @MethodSubstitution + public static long addExact(long x, long y) { + return IntegerAddExactNode.addExact(x, y); + } + + @MethodSubstitution + public static int subtractExact(int x, int y) { + return IntegerSubExactNode.subtractExact(x, y); + } + + @MethodSubstitution + public static long subtractExact(long x, long y) { + return IntegerSubExactNode.subtractExact(x, y); + } + + @MethodSubstitution + public static int multiplyExact(int x, int y) { + return IntegerMulExactNode.multiplyExact(x, y); + } + + @MethodSubstitution + public static long multiplyExact(long x, long y) { + return IntegerMulExactNode.multiplyExact(x, y); + } +} diff -r 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/FrameWithoutBoxingSubstitutions.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/FrameWithoutBoxingSubstitutions.java Mon Jun 24 10:25:41 2013 +0200 @@ -0,0 +1,216 @@ +/* + * 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.api.runtime.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.truffle.*; +import com.oracle.graal.truffle.nodes.*; +import com.oracle.truffle.api.frame.*; + +@ClassSubstitution(FrameWithoutBoxing.class) +public class FrameWithoutBoxingSubstitutions { + + private static final ResolvedJavaField LOCALS_FIELD; + private static final ResolvedJavaField PRIMITIVELOCALS_FIELD; + private static final ResolvedJavaField TAGS_FIELD; + + static { + try { + MetaAccessProvider runtime = Graal.getRequiredCapability(MetaAccessProvider.class); + LOCALS_FIELD = runtime.lookupJavaField(FrameWithoutBoxing.class.getDeclaredField("locals")); + PRIMITIVELOCALS_FIELD = runtime.lookupJavaField(FrameWithoutBoxing.class.getDeclaredField("primitiveLocals")); + TAGS_FIELD = runtime.lookupJavaField(FrameWithoutBoxing.class.getDeclaredField("tags")); + } catch (NoSuchFieldException e) { + throw new RuntimeException(e); + } + } + + @MacroSubstitution(macro = UnsafeCastMacroNode.class, isStatic = true) + public static native Object unsafeCast(Object value, Class clazz); + + @SuppressWarnings("unused") + @MethodSubstitution(isStatic = false) + public static Object pack(FrameWithoutBoxing frame) { + return null; + } + + @MethodSubstitution(isStatic = false) + public static Object getObject(FrameWithoutBoxing frame, FrameSlot slot) { + verifyGet(frame, slot, FrameSlotKind.Object); + return getObjectUnsafe(frame, slot); + } + + @MethodSubstitution(isStatic = false) + public static void setObject(FrameWithoutBoxing frame, FrameSlot slot, Object value) { + verifySet(frame, slot, FrameSlotKind.Object); + setObjectUnsafe(frame, slot, value); + } + + @MethodSubstitution(isStatic = false) + public static boolean getBoolean(FrameWithoutBoxing frame, FrameSlot slot) { + verifyGet(frame, slot, FrameSlotKind.Boolean); + return getBooleanUnsafe(frame, slot); + } + + @MethodSubstitution(isStatic = false) + public static void setBoolean(FrameWithoutBoxing frame, FrameSlot slot, boolean value) { + verifySet(frame, slot, FrameSlotKind.Boolean); + setBooleanUnsafe(frame, slot, value); + } + + @MethodSubstitution(isStatic = false) + public static float getFloat(FrameWithoutBoxing frame, FrameSlot slot) { + verifyGet(frame, slot, FrameSlotKind.Float); + return getFloatUnsafe(frame, slot); + } + + @MethodSubstitution(isStatic = false) + public static void setFloat(FrameWithoutBoxing frame, FrameSlot slot, float value) { + verifySet(frame, slot, FrameSlotKind.Float); + setFloatUnsafe(frame, slot, value); + } + + @MethodSubstitution(isStatic = false) + public static long getLong(FrameWithoutBoxing frame, FrameSlot slot) { + verifyGet(frame, slot, FrameSlotKind.Long); + return getLongUnsafe(frame, slot); + } + + @MethodSubstitution(isStatic = false) + public static void setLong(FrameWithoutBoxing frame, FrameSlot slot, long value) { + verifySet(frame, slot, FrameSlotKind.Long); + setLongUnsafe(frame, slot, value); + } + + @MethodSubstitution(isStatic = false) + public static int getInt(FrameWithoutBoxing frame, FrameSlot slot) { + verifyGet(frame, slot, FrameSlotKind.Int); + return getIntUnsafe(frame, slot); + } + + @MethodSubstitution(isStatic = false) + public static void setInt(FrameWithoutBoxing frame, FrameSlot slot, int value) { + verifySet(frame, slot, FrameSlotKind.Int); + setIntUnsafe(frame, slot, value); + } + + @MethodSubstitution(isStatic = false) + public static double getDouble(FrameWithoutBoxing frame, FrameSlot slot) { + verifyGet(frame, slot, FrameSlotKind.Double); + return getDoubleUnsafe(frame, slot); + } + + @MethodSubstitution(isStatic = false) + public static void setDouble(FrameWithoutBoxing frame, FrameSlot slot, double value) { + verifySet(frame, slot, FrameSlotKind.Double); + setDoubleUnsafe(frame, slot, value); + } + + @MethodSubstitution(isStatic = false) + public static Object getObjectUnsafe(FrameWithoutBoxing frame, FrameSlot slot) { + return FrameGetNode.get(Kind.Object, frame, slot, LOCALS_FIELD); + } + + @MethodSubstitution(isStatic = false) + public static void setObjectUnsafe(FrameWithoutBoxing frame, FrameSlot slot, Object value) { + FrameSetNode.set(Kind.Object, frame, slot, value, LOCALS_FIELD); + } + + @MethodSubstitution(isStatic = false) + public static boolean getBooleanUnsafe(FrameWithoutBoxing frame, FrameSlot slot) { + return FrameGetNode.get(Kind.Boolean, frame, slot, PRIMITIVELOCALS_FIELD); + } + + @MethodSubstitution(isStatic = false) + public static void setBooleanUnsafe(FrameWithoutBoxing frame, FrameSlot slot, boolean value) { + FrameSetNode.set(Kind.Boolean, frame, slot, value, PRIMITIVELOCALS_FIELD); + } + + @MethodSubstitution(isStatic = false) + public static int getIntUnsafe(FrameWithoutBoxing frame, FrameSlot slot) { + return FrameGetNode.get(Kind.Int, frame, slot, PRIMITIVELOCALS_FIELD); + } + + @MethodSubstitution(isStatic = false) + public static void setIntUnsafe(FrameWithoutBoxing frame, FrameSlot slot, int value) { + FrameSetNode.set(Kind.Int, frame, slot, value, PRIMITIVELOCALS_FIELD); + } + + @MethodSubstitution(isStatic = false) + public static long getLongUnsafe(FrameWithoutBoxing frame, FrameSlot slot) { + return FrameGetNode.get(Kind.Long, frame, slot, PRIMITIVELOCALS_FIELD); + } + + @MethodSubstitution(isStatic = false) + public static void setLongUnsafe(FrameWithoutBoxing frame, FrameSlot slot, long value) { + FrameSetNode.set(Kind.Long, frame, slot, value, PRIMITIVELOCALS_FIELD); + } + + @MethodSubstitution(isStatic = false) + public static double getDoubleUnsafe(FrameWithoutBoxing frame, FrameSlot slot) { + return FrameGetNode.get(Kind.Double, frame, slot, PRIMITIVELOCALS_FIELD); + } + + @MethodSubstitution(isStatic = false) + public static void setDoubleUnsafe(FrameWithoutBoxing frame, FrameSlot slot, double value) { + FrameSetNode.set(Kind.Double, frame, slot, value, PRIMITIVELOCALS_FIELD); + } + + @MethodSubstitution(isStatic = false) + public static float getFloatUnsafe(FrameWithoutBoxing frame, FrameSlot slot) { + return FrameGetNode.get(Kind.Float, frame, slot, PRIMITIVELOCALS_FIELD); + } + + @MethodSubstitution(isStatic = false) + public static void setFloatUnsafe(FrameWithoutBoxing frame, FrameSlot slot, float value) { + FrameSetNode.set(Kind.Float, frame, slot, value, PRIMITIVELOCALS_FIELD); + } + + private static void verifySet(FrameWithoutBoxing frame, FrameSlot slot, FrameSlotKind accessType) { + setTag(frame, slot, (byte) accessType.ordinal()); + } + + private static void verifyGet(FrameWithoutBoxing frame, FrameSlot slot, FrameSlotKind accessType) { + if (getTag(frame, slot) != (byte) accessType.ordinal()) { + DeoptimizeNode.deopt(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.UnreachedCode); + } + } + + private static byte getTag(FrameWithoutBoxing frame, FrameSlot slot) { + return FrameGetNode.get(Kind.Byte, frame, slot, TAGS_FIELD); + } + + private static void setTag(FrameWithoutBoxing frame, FrameSlot slot, byte tag) { + FrameSetNode.set(Kind.Byte, frame, slot, tag, TAGS_FIELD); + } + + @MethodSubstitution(isStatic = false) + public static MaterializedFrame materialize(FrameWithoutBoxing frame) { + return MaterializeFrameNode.materialize(frame); + } +} diff -r 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/OptimizedAssumptionSubstitutions.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/OptimizedAssumptionSubstitutions.java Mon Jun 24 10:25:41 2013 +0200 @@ -0,0 +1,38 @@ +/* + * 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.replacements.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.truffle.*; +import com.oracle.graal.truffle.nodes.*; + +@ClassSubstitution(OptimizedAssumption.class) +public class OptimizedAssumptionSubstitutions { + + @MacroSubstitution(macro = AssumptionNode.class, isStatic = false, forced = true) + public static native void check(OptimizedAssumption assumption); + + @MacroSubstitution(macro = AssumptionNode.class, isStatic = false, forced = true) + public static native boolean isValid(OptimizedAssumption assumption); +} diff -r 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/OptimizedCallTargetSubstitutions.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/OptimizedCallTargetSubstitutions.java Mon Jun 24 10:25:41 2013 +0200 @@ -0,0 +1,48 @@ +/* + * 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.replacements.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.truffle.*; +import com.oracle.graal.truffle.nodes.*; +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; + +@ClassSubstitution(OptimizedCallTarget.class) +public class OptimizedCallTargetSubstitutions { + + @MacroSubstitution(macro = NeverInlineMacroNode.class, isStatic = false) + public static native Object call(OptimizedCallTarget target, PackedFrame caller, Arguments args); + + @MethodSubstitution + private static FrameWithoutBoxing createFrame(FrameDescriptor descriptor, PackedFrame caller, Arguments args) { + return NewFrameNode.allocate(descriptor, caller, args); + } + + @SuppressWarnings("unused") + @MethodSubstitution(isStatic = false) + private static VirtualFrame create(OptimizedCallTarget target, FrameDescriptor descriptor, PackedFrame caller, Arguments args) { + return createFrame(descriptor, caller, args); + } +} diff -r 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/SlowPathExceptionSubstitutions.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/SlowPathExceptionSubstitutions.java Mon Jun 24 10:25:41 2013 +0200 @@ -0,0 +1,59 @@ +/* + * 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 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/UnexpectedResultExceptionSubstitutions.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/UnexpectedResultExceptionSubstitutions.java Mon Jun 24 10:25:41 2013 +0200 @@ -0,0 +1,42 @@ +/* + * 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 UnexpectedResultException instance. + */ +@ClassSubstitution(UnexpectedResultException.class) +public class UnexpectedResultExceptionSubstitutions { + + @SuppressWarnings("unused") + @MethodSubstitution(value = "") + public static void init(Object result) { + DeoptimizeNode.deopt(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.UnreachedCode); + } +} diff -r 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/FrameFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/FrameFactory.java Mon Jun 24 10:25:41 2013 +0200 @@ -0,0 +1,32 @@ +/* + * 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.truffle.api.nodes; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; + +public interface FrameFactory { + + VirtualFrame create(FrameDescriptor descriptor, PackedFrame caller, Arguments args); + +} diff -r 0eeb9f8dab9b -r 5db21405c6a4 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 Mon Jun 24 10:22:28 2013 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/GraphPrintVisitor.java Mon Jun 24 10:25:41 2013 +0200 @@ -209,13 +209,15 @@ setNodeProperty(node, "name", node.getClass().getSimpleName().replaceFirst("Node$", "")); NodeInfo nodeInfo = node.getClass().getAnnotation(NodeInfo.class); - if (nodeInfo != null && !nodeInfo.shortName().isEmpty()) { - setNodeProperty(node, "shortName", nodeInfo.shortName()); + if (nodeInfo != null) { + setNodeProperty(node, "kind", nodeInfo.kind()); + if (!nodeInfo.shortName().isEmpty()) { + setNodeProperty(node, "shortName", nodeInfo.shortName()); + } } - setNodeProperty(node, "nodeType", (Node.class.isAssignableFrom(node.getClass()) ? Node.class.getSimpleName() : "other")); - setNodeProperty(node, "nodeClass", node.getClass().getSimpleName()); - copyDebugProperties(node); // TODO: may overwrite property "name"? (currently allowed) + setNodeProperty(node, "class", node.getClass().getSimpleName()); readNodeProperties((Node) node); + copyDebugProperties(node); } } diff -r 0eeb9f8dab9b -r 5db21405c6a4 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/InlinableCallSite.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/InlinableCallSite.java Mon Jun 24 10:25:41 2013 +0200 @@ -0,0 +1,35 @@ +/* + * 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.truffle.api.nodes; + +public interface InlinableCallSite { + + int getCallCount(); + + void resetCallCount(); + + Node getInlineTree(); + + boolean inline(FrameFactory factory); + +} diff -r 0eeb9f8dab9b -r 5db21405c6a4 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 Mon Jun 24 10:22:28 2013 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java Mon Jun 24 10:25:41 2013 +0200 @@ -57,6 +57,10 @@ public @interface Child { } + protected Node() { + CompilerAsserts.neverPartOfCompilation(); + } + /** * Assigns a link to a guest language source section to this node. * @@ -86,6 +90,18 @@ } /** + * Retrieves the guest language source code section that is currently assigned to this node. + * + * @return the assigned source code section + */ + public final SourceSection getEncapsulatingSourceSection() { + if (sourceSection == null && getParent() != null) { + return getParent().getEncapsulatingSourceSection(); + } + return sourceSection; + } + + /** * Method that updates the link to the parent in the array of specified new child nodes to this * node. * @@ -109,6 +125,9 @@ */ protected final T adoptChild(T newChild) { if (newChild != null) { + if (newChild == this) { + throw new IllegalStateException("The parent of a node can never be the node itself."); + } ((Node) newChild).parent = this; } return newChild; @@ -144,7 +163,9 @@ */ @SuppressWarnings({"unchecked"}) public final T replace(T newNode, String reason) { - assert this.getParent() != null; + if (this.getParent() == null) { + throw new IllegalStateException("This node cannot be replaced, because it does not yet have a parent."); + } if (sourceSection != null) { // Pass on the source section to the new node. newNode.assignSourceSection(sourceSection); diff -r 0eeb9f8dab9b -r 5db21405c6a4 mx/commands.py --- a/mx/commands.py Mon Jun 24 10:22:28 2013 +0200 +++ b/mx/commands.py Mon Jun 24 10:25:41 2013 +0200 @@ -937,6 +937,11 @@ vm(['-esa', '-version']) tasks.append(t.stop()) + _vmbuild = 'fastdebug' + t = Task('BootstrapWithGCVerification:fastdebug') + vm(['-XX:+VerifyBeforeGC', '-version']) + tasks.append(t.stop()) + _vmbuild = 'product' t = Task('BootstrapWithRegisterPressure:product') vm(['-G:RegisterPressure=rbx,r11,r10,r14,xmm3,xmm11,xmm14', '-esa', '-version']) diff -r 0eeb9f8dab9b -r 5db21405c6a4 mx/projects --- a/mx/projects Mon Jun 24 10:22:28 2013 +0200 +++ b/mx/projects Mon Jun 24 10:25:41 2013 +0200 @@ -25,7 +25,7 @@ library@DACAPO_SCALA@urls=http://repo.scalabench.org/snapshots/org/scalabench/benchmarks/scala-benchmark-suite/0.1.0-SNAPSHOT/scala-benchmark-suite-0.1.0-20120216.103539-3.jar distribution@GRAAL@path=graal.jar -distribution@GRAAL@dependencies=com.oracle.graal.hotspot.amd64,com.oracle.graal.hotspot.sparc,com.oracle.graal.hotspot +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 # graal.api.runtime project@com.oracle.graal.api.runtime@subDir=graal @@ -385,10 +385,26 @@ project@com.oracle.graal.java@javaCompliance=1.7 project@com.oracle.graal.java@workingSets=Graal,Java +# graal.java.decompiler +project@com.oracle.graal.java.decompiler@subDir=graal +project@com.oracle.graal.java.decompiler@sourceDirs=src +project@com.oracle.graal.java.decompiler@dependencies=com.oracle.graal.java +project@com.oracle.graal.java.decompiler@checkstyle=com.oracle.graal.graph +project@com.oracle.graal.java.decompiler@javaCompliance=1.7 +project@com.oracle.graal.java.decompiler@workingSets=Graal + +# graal.java.decompiler.test +project@com.oracle.graal.java.decompiler.test@subDir=graal +project@com.oracle.graal.java.decompiler.test@sourceDirs=src +project@com.oracle.graal.java.decompiler.test@dependencies=com.oracle.graal.printer +project@com.oracle.graal.java.decompiler.test@checkstyle=com.oracle.graal.graph +project@com.oracle.graal.java.decompiler.test@javaCompliance=1.7 +project@com.oracle.graal.java.decompiler.test@workingSets=Graal,Test + # graal.printer project@com.oracle.graal.printer@subDir=graal project@com.oracle.graal.printer@sourceDirs=src -project@com.oracle.graal.printer@dependencies=com.oracle.graal.java,com.oracle.graal.compiler +project@com.oracle.graal.printer@dependencies=com.oracle.graal.java.decompiler,com.oracle.graal.compiler project@com.oracle.graal.printer@checkstyle=com.oracle.graal.graph project@com.oracle.graal.printer@javaCompliance=1.7 project@com.oracle.graal.printer@workingSets=Graal,Graph @@ -523,5 +539,28 @@ project@com.oracle.truffle.sl.test@javaCompliance=1.7 project@com.oracle.truffle.sl.test@workingSets=Truffle,SimpleLanguage,Test +# graal.truffle +project@com.oracle.graal.truffle@subDir=graal +project@com.oracle.graal.truffle@sourceDirs=src +project@com.oracle.graal.truffle@dependencies=com.oracle.truffle.api,com.oracle.graal.truffle.printer,com.oracle.graal.hotspot +project@com.oracle.graal.truffle@checkstyle=com.oracle.graal.graph +project@com.oracle.graal.truffle@javaCompliance=1.7 +project@com.oracle.graal.truffle@workingSets=Graal,Truffle + +# graal.truffle.test +project@com.oracle.graal.truffle.test@subDir=graal +project@com.oracle.graal.truffle.test@sourceDirs=src +project@com.oracle.graal.truffle.test@dependencies=com.oracle.graal.truffle,com.oracle.graal.compiler.test +project@com.oracle.graal.truffle.test@checkstyle=com.oracle.graal.graph +project@com.oracle.graal.truffle.test@javaCompliance=1.7 +project@com.oracle.graal.truffle.test@workingSets=Graal,Truffle,Test + +# graal.truffle.printer +project@com.oracle.graal.truffle.printer@subDir=graal +project@com.oracle.graal.truffle.printer@sourceDirs=src +project@com.oracle.graal.truffle.printer@dependencies=com.oracle.graal.nodes +project@com.oracle.graal.truffle.printer@checkstyle=com.oracle.graal.graph +project@com.oracle.graal.truffle.printer@javaCompliance=1.7 +project@com.oracle.graal.truffle.printer@workingSets=Graal,Truffle diff -r 0eeb9f8dab9b -r 5db21405c6a4 src/cpu/sparc/vm/sharedRuntime_sparc.cpp --- a/src/cpu/sparc/vm/sharedRuntime_sparc.cpp Mon Jun 24 10:22:28 2013 +0200 +++ b/src/cpu/sparc/vm/sharedRuntime_sparc.cpp Mon Jun 24 10:25:41 2013 +0200 @@ -1826,20 +1826,6 @@ verify_oop_args(masm, method, sig_bt, regs); vmIntrinsics::ID iid = method->intrinsic_id(); - -#ifdef GRAAL - if (iid == vmIntrinsics::_CompilerToVMImpl_executeCompiledMethod) { - // We are called from compiled code here. The three object arguments - // are already in the correct registers (j_rarg0, jrarg1, jrarg2). The - // fourth argument (j_rarg3) is a raw pointer to the nmethod. Make a tail - // call to its verified entry point. - __ set(nmethod::verified_entry_point_offset(), O0); - __ JMP(O0, 0); - __ delayed()->nop(); - return; - } -#endif - // Now write the args into the outgoing interpreter space bool has_receiver = false; Register receiver_reg = noreg; diff -r 0eeb9f8dab9b -r 5db21405c6a4 src/cpu/sparc/vm/stubGenerator_sparc.cpp --- a/src/cpu/sparc/vm/stubGenerator_sparc.cpp Mon Jun 24 10:22:28 2013 +0200 +++ b/src/cpu/sparc/vm/stubGenerator_sparc.cpp Mon Jun 24 10:25:41 2013 +0200 @@ -3412,6 +3412,7 @@ // These entry points require SharedInfo::stack0 to be set up in non-core builds StubRoutines::_throw_AbstractMethodError_entry = generate_throw_exception("AbstractMethodError throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_AbstractMethodError)); StubRoutines::_throw_IncompatibleClassChangeError_entry= generate_throw_exception("IncompatibleClassChangeError throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_IncompatibleClassChangeError)); + StubRoutines::_throw_InvalidInstalledCodeException_entry= generate_throw_exception("InvalidInstalledCodeException throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_InvalidInstalledCodeException)); StubRoutines::_throw_NullPointerException_at_call_entry= generate_throw_exception("NullPointerException at call throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_NullPointerException_at_call)); StubRoutines::_handler_for_unsafe_access_entry = diff -r 0eeb9f8dab9b -r 5db21405c6a4 src/cpu/x86/vm/c2_globals_x86.hpp --- a/src/cpu/x86/vm/c2_globals_x86.hpp Mon Jun 24 10:22:28 2013 +0200 +++ b/src/cpu/x86/vm/c2_globals_x86.hpp Mon Jun 24 10:25:41 2013 +0200 @@ -86,7 +86,11 @@ define_pd_global(bool, OptoScheduling, false); define_pd_global(bool, OptoBundling, false); +#ifdef GRAAL +define_pd_global(intx, ReservedCodeCacheSize, 64*M); +#else define_pd_global(intx, ReservedCodeCacheSize, 48*M); +#endif define_pd_global(uintx,CodeCacheMinBlockLength, 4); // Heap related flags diff -r 0eeb9f8dab9b -r 5db21405c6a4 src/cpu/x86/vm/sharedRuntime_x86_64.cpp --- a/src/cpu/x86/vm/sharedRuntime_x86_64.cpp Mon Jun 24 10:22:28 2013 +0200 +++ b/src/cpu/x86/vm/sharedRuntime_x86_64.cpp Mon Jun 24 10:25:41 2013 +0200 @@ -40,6 +40,9 @@ #ifdef COMPILER2 #include "opto/runtime.hpp" #endif +#ifdef GRAAL +#include "graal/graalJavaAccess.hpp" +#endif #define __ masm-> @@ -1674,9 +1677,22 @@ if (iid == vmIntrinsics::_CompilerToVMImpl_executeCompiledMethod) { // We are called from compiled code here. The three object arguments // are already in the correct registers (j_rarg0, jrarg1, jrarg2). The - // fourth argument (j_rarg3) is a raw pointer to the nmethod. Make a tail - // call to its verified entry point. + // fourth argument (j_rarg3) is a pointer to the HotSpotInstalledCode object. + + // Load the nmethod pointer from the HotSpotInstalledCode object + __ movq(j_rarg3, Address(j_rarg3, sizeof(oopDesc))); + + // Check whether the nmethod was invalidated + __ testq(j_rarg3, j_rarg3); + Label invalid_nmethod; + __ jcc(Assembler::zero, invalid_nmethod); + + // Perform a tail call to the verified entry point of the nmethod. __ jmp(Address(j_rarg3, nmethod::verified_entry_point_offset())); + + __ bind(invalid_nmethod); + + __ jump(RuntimeAddress(StubRoutines::throw_InvalidInstalledCodeException_entry())); return; } #endif diff -r 0eeb9f8dab9b -r 5db21405c6a4 src/cpu/x86/vm/stubGenerator_x86_32.cpp --- a/src/cpu/x86/vm/stubGenerator_x86_32.cpp Mon Jun 24 10:22:28 2013 +0200 +++ b/src/cpu/x86/vm/stubGenerator_x86_32.cpp Mon Jun 24 10:25:41 2013 +0200 @@ -2897,6 +2897,7 @@ // and need to be relocatable, so they each fabricate a RuntimeStub internally. StubRoutines::_throw_AbstractMethodError_entry = generate_throw_exception("AbstractMethodError throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_AbstractMethodError)); StubRoutines::_throw_IncompatibleClassChangeError_entry= generate_throw_exception("IncompatibleClassChangeError throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_IncompatibleClassChangeError)); + StubRoutines::_throw_InvalidInstalledCodeException_entry = generate_throw_exception("InvalidInstalledCodeException throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_InvalidInstalledCodeException)); StubRoutines::_throw_NullPointerException_at_call_entry= generate_throw_exception("NullPointerException at call throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_NullPointerException_at_call)); //------------------------------------------------------------------------------------------------------------------------ diff -r 0eeb9f8dab9b -r 5db21405c6a4 src/cpu/x86/vm/stubGenerator_x86_64.cpp --- a/src/cpu/x86/vm/stubGenerator_x86_64.cpp Mon Jun 24 10:22:28 2013 +0200 +++ b/src/cpu/x86/vm/stubGenerator_x86_64.cpp Mon Jun 24 10:25:41 2013 +0200 @@ -3756,6 +3756,12 @@ SharedRuntime:: throw_IncompatibleClassChangeError)); + StubRoutines::_throw_InvalidInstalledCodeException_entry = + generate_throw_exception("InvalidInstalledCodeException throw_exception", + CAST_FROM_FN_PTR(address, + SharedRuntime:: + throw_InvalidInstalledCodeException)); + StubRoutines::_throw_NullPointerException_at_call_entry = generate_throw_exception("NullPointerException at call throw_exception", CAST_FROM_FN_PTR(address, diff -r 0eeb9f8dab9b -r 5db21405c6a4 src/cpu/x86/vm/templateInterpreter_x86_64.cpp --- a/src/cpu/x86/vm/templateInterpreter_x86_64.cpp Mon Jun 24 10:22:28 2013 +0200 +++ b/src/cpu/x86/vm/templateInterpreter_x86_64.cpp Mon Jun 24 10:25:41 2013 +0200 @@ -46,6 +46,9 @@ #include "runtime/vframeArray.hpp" #include "utilities/debug.hpp" #include "utilities/macros.hpp" +#ifdef GRAAL +#include "graal/graalJavaAccess.hpp" +#endif #define __ _masm-> @@ -908,20 +911,34 @@ // Move first object argument from interpreter calling convention to compiled // code calling convention. - __ movq(j_rarg0, Address(r11, Interpreter::stackElementSize*5)); + __ movq(j_rarg0, Address(r11, Interpreter::stackElementSize*4)); // Move second object argument. - __ movq(j_rarg1, Address(r11, Interpreter::stackElementSize*4)); + __ movq(j_rarg1, Address(r11, Interpreter::stackElementSize*3)); // Move third object argument. - __ movq(j_rarg2, Address(r11, Interpreter::stackElementSize*3)); + __ movq(j_rarg2, Address(r11, Interpreter::stackElementSize*2)); + + // Load the raw pointer to the HotSpotInstalledCode object. + __ movq(j_rarg3, Address(r11, Interpreter::stackElementSize)); - // Load the raw pointer to the nmethod. - __ movq(j_rarg3, Address(r11, Interpreter::stackElementSize)); + // Load the nmethod pointer from the HotSpotInstalledCode object + __ movq(j_rarg3, Address(j_rarg3, sizeof(oopDesc))); + + // Check whether the nmethod was invalidated + __ testq(j_rarg3, j_rarg3); + Label invalid_nmethod; + __ jcc(Assembler::zero, invalid_nmethod); // Perform a tail call to the verified entry point of the nmethod. __ jmp(Address(j_rarg3, nmethod::verified_entry_point_offset())); + __ bind(invalid_nmethod); + + __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_InvalidInstalledCodeException)); + // the call_VM checks for exception, so we should never return here. + __ should_not_reach_here(); + return entry_point; } diff -r 0eeb9f8dab9b -r 5db21405c6a4 src/share/vm/classfile/vmSymbols.hpp --- a/src/share/vm/classfile/vmSymbols.hpp Mon Jun 24 10:22:28 2013 +0200 +++ b/src/share/vm/classfile/vmSymbols.hpp Mon Jun 24 10:25:41 2013 +0200 @@ -348,6 +348,8 @@ template(com_oracle_graal_api_code_VirtualObject, "com/oracle/graal/api/code/VirtualObject") \ template(com_oracle_graal_api_code_RegisterSaveLayout, "com/oracle/graal/api/code/RegisterSaveLayout") \ template(com_oracle_graal_api_code_InvalidInstalledCodeException, "com/oracle/graal/api/code/InvalidInstalledCodeException") \ + /* graal.truffle */ \ + template(com_oracle_graal_truffle_GraalTruffleRuntime, "com/oracle/graal/truffle/GraalTruffleRuntime") \ template(startCompiler_name, "startCompiler") \ template(bootstrap_name, "bootstrap") \ template(shutdownCompiler_name, "shutdownCompiler") \ @@ -382,6 +384,7 @@ template(getVMToCompiler_name, "getVMToCompiler") \ template(getVMToCompiler_signature, "()Lcom/oracle/graal/hotspot/bridge/VMToCompiler;") \ template(getInstance_name, "getInstance") \ + template(getTruffleRuntimeInstance_signature, "()Lcom/oracle/graal/truffle/GraalTruffleRuntime;") \ template(makeInstance_name, "makeInstance") \ template(initialize_name, "initialize") \ template(getInstance_signature, "()Lcom/oracle/graal/hotspot/HotSpotGraalRuntime;") \ @@ -1145,7 +1148,7 @@ do_name( Double_valueOf_signature, "(D)Ljava/lang/Double;") \ \ do_intrinsic(_CompilerToVMImpl_executeCompiledMethod, com_oracle_graal_hotspot_bridge_CompilerToVMImpl, executeCompiledMethod_name, CompilerToVMImpl_executeCompiledMethod_signature, F_SN)\ - do_name( CompilerToVMImpl_executeCompiledMethod_signature, "(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;J)Ljava/lang/Object;") \ + do_name( CompilerToVMImpl_executeCompiledMethod_signature, "(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Lcom/oracle/graal/hotspot/meta/HotSpotInstalledCode;)Ljava/lang/Object;") \ do_name( executeCompiledMethod_name, "executeCompiledMethodIntrinsic") \ /*end*/ diff -r 0eeb9f8dab9b -r 5db21405c6a4 src/share/vm/code/nmethod.cpp --- a/src/share/vm/code/nmethod.cpp Mon Jun 24 10:22:28 2013 +0200 +++ b/src/share/vm/code/nmethod.cpp Mon Jun 24 10:25:41 2013 +0200 @@ -1397,9 +1397,10 @@ if (!is_osr_method() && !is_not_entrant()) { address stub = SharedRuntime::get_handle_wrong_method_stub(); #ifdef GRAAL - if (_graal_installed_code != NULL && !HotSpotNmethod::isDefault(_graal_installed_code)) { - // This was manually installed machine code. Patch entry with stub that throws an exception. - stub = SharedRuntime::get_deoptimized_installed_code_stub(); + if (_graal_installed_code != NULL) { + // Break the link between nmethod and HotSpotInstalledCode such that the nmethod can subsequently be flushed safely. + HotSpotInstalledCode::set_codeBlob(_graal_installed_code, 0); + _graal_installed_code = NULL; } #endif NativeJump::patch_verified_entry(entry_point(), verified_entry_point(), stub); diff -r 0eeb9f8dab9b -r 5db21405c6a4 src/share/vm/graal/graalCompilerToVM.cpp --- a/src/share/vm/graal/graalCompilerToVM.cpp Mon Jun 24 10:22:28 2013 +0200 +++ b/src/share/vm/graal/graalCompilerToVM.cpp Mon Jun 24 10:25:41 2013 +0200 @@ -1004,10 +1004,11 @@ return JNIHandles::make_local(element); C2V_END -C2V_VMENTRY(jobject, executeCompiledMethodVarargs, (JNIEnv *env, jobject, jobject args, jlong nmethodValue)) +C2V_VMENTRY(jobject, executeCompiledMethodVarargs, (JNIEnv *env, jobject, jobject args, jobject hotspotInstalledCode)) ResourceMark rm; HandleMark hm; + jlong nmethodValue = HotSpotInstalledCode::codeBlob(hotspotInstalledCode); nmethod* nm = (nmethod*) (address) nmethodValue; methodHandle mh = nm->method(); Symbol* signature = mh->signature(); @@ -1156,9 +1157,10 @@ C2V_END -C2V_VMENTRY(void, invalidateInstalledCode, (JNIEnv *env, jobject, jlong nativeMethod)) +C2V_VMENTRY(void, invalidateInstalledCode, (JNIEnv *env, jobject, jobject hotspotInstalledCode)) + jlong nativeMethod = HotSpotInstalledCode::codeBlob(hotspotInstalledCode); nmethod* m = (nmethod*)nativeMethod; - if (!m->is_not_entrant()) { + if (m != NULL && !m->is_not_entrant()) { m->mark_for_deoptimization(); VM_Deoptimize op; VMThread::execute(&op); @@ -1166,11 +1168,6 @@ C2V_END -C2V_VMENTRY(jboolean, isInstalledCodeValid, (JNIEnv *env, jobject, jlong nativeMethod)) - nmethod* m = (nmethod*)nativeMethod; - return m->is_alive() && !m->is_not_entrant(); -C2V_END - #define CC (char*) /*cast a literal from (const char*)*/ #define FN_PTR(f) CAST_FROM_FN_PTR(void*, &(c2v_ ## f)) @@ -1203,7 +1200,6 @@ #define METHOD_DATA "Lcom/oracle/graal/hotspot/meta/HotSpotMethodData;" #define METASPACE_METHOD "J" #define METASPACE_METHOD_DATA "J" -#define NMETHOD "J" JNINativeMethod CompilerToVM_methods[] = { {CC"initializeBytecode", CC"("METASPACE_METHOD"[B)[B", FN_PTR(initializeBytecode)}, @@ -1243,14 +1239,13 @@ {CC"installCode0", CC"("HS_COMPILED_CODE HS_INSTALLED_CODE"[Z)I", FN_PTR(installCode0)}, {CC"getCode", CC"(J)[B", FN_PTR(getCode)}, {CC"disassembleCodeBlob", CC"(J)"STRING, FN_PTR(disassembleCodeBlob)}, - {CC"executeCompiledMethodVarargs", CC"(["OBJECT NMETHOD")"OBJECT, FN_PTR(executeCompiledMethodVarargs)}, + {CC"executeCompiledMethodVarargs", CC"(["OBJECT HS_INSTALLED_CODE")"OBJECT, FN_PTR(executeCompiledMethodVarargs)}, {CC"getDeoptedLeafGraphIds", CC"()[J", FN_PTR(getDeoptedLeafGraphIds)}, {CC"getLineNumberTable", CC"("HS_RESOLVED_METHOD")[J", FN_PTR(getLineNumberTable)}, {CC"getLocalVariableTable", CC"("HS_RESOLVED_METHOD")["LOCAL, FN_PTR(getLocalVariableTable)}, {CC"getFileName", CC"("HS_RESOLVED_JAVA_TYPE")"STRING, FN_PTR(getFileName)}, {CC"reprofile", CC"("METASPACE_METHOD")V", FN_PTR(reprofile)}, - {CC"invalidateInstalledCode", CC"(J)V", FN_PTR(invalidateInstalledCode)}, - {CC"isInstalledCodeValid", CC"(J)Z", FN_PTR(isInstalledCodeValid)}, + {CC"invalidateInstalledCode", CC"("HS_INSTALLED_CODE")V", FN_PTR(invalidateInstalledCode)}, }; int CompilerToVM_methods_count() { diff -r 0eeb9f8dab9b -r 5db21405c6a4 src/share/vm/graal/graalJavaAccess.cpp --- a/src/share/vm/graal/graalJavaAccess.cpp Mon Jun 24 10:22:28 2013 +0200 +++ b/src/share/vm/graal/graalJavaAccess.cpp Mon Jun 24 10:25:41 2013 +0200 @@ -63,6 +63,7 @@ void graal_compute_offsets() { COMPILER_CLASSES_DO(START_CLASS, END_CLASS, CHAR_FIELD, INT_FIELD, BOOLEAN_FIELD, LONG_FIELD, FLOAT_FIELD, OOP_FIELD, STATIC_OOP_FIELD) + guarantee(HotSpotInstalledCode::_codeBlob_offset == sizeof(oopDesc), "codeBlob must be first field!"); } #define EMPTY0 diff -r 0eeb9f8dab9b -r 5db21405c6a4 src/share/vm/graal/graalRuntime.cpp --- a/src/share/vm/graal/graalRuntime.cpp Mon Jun 24 10:22:28 2013 +0200 +++ b/src/share/vm/graal/graalRuntime.cpp Mon Jun 24 10:25:41 2013 +0200 @@ -474,3 +474,8 @@ JVM_ENTRY(jobject, JVM_InitializeGraalRuntime(JNIEnv *env, jclass graalclass)) return VMToCompiler::graalRuntimePermObject(); JVM_END + +// JVM_InitializeTruffleRuntime +JVM_ENTRY(jobject, JVM_InitializeTruffleRuntime(JNIEnv *env, jclass graalclass)) + return JNIHandles::make_local(VMToCompiler::truffleRuntime()()); +JVM_END diff -r 0eeb9f8dab9b -r 5db21405c6a4 src/share/vm/graal/graalVMToCompiler.cpp --- a/src/share/vm/graal/graalVMToCompiler.cpp Mon Jun 24 10:22:28 2013 +0200 +++ b/src/share/vm/graal/graalVMToCompiler.cpp Mon Jun 24 10:25:41 2013 +0200 @@ -46,6 +46,16 @@ return _vmToCompilerPermKlass; } +Handle VMToCompiler::truffleRuntime() { + Symbol* name = vmSymbols::com_oracle_graal_truffle_GraalTruffleRuntime(); + KlassHandle klass = loadClass(name); + + JavaValue result(T_OBJECT); + JavaCalls::call_static(&result, klass, vmSymbols::makeInstance_name(), vmSymbols::getTruffleRuntimeInstance_signature(), Thread::current()); + check_pending_exception("Couldn't initialize GraalTruffleRuntime"); + return Handle((oop) result.get_jobject()); +} + Handle VMToCompiler::graalRuntime() { if (JNIHandles::resolve(_graalRuntimePermObject) == NULL) { #ifdef AMD64 @@ -292,3 +302,4 @@ } + diff -r 0eeb9f8dab9b -r 5db21405c6a4 src/share/vm/graal/graalVMToCompiler.hpp --- a/src/share/vm/graal/graalVMToCompiler.hpp Mon Jun 24 10:22:28 2013 +0200 +++ b/src/share/vm/graal/graalVMToCompiler.hpp Mon Jun 24 10:25:41 2013 +0200 @@ -44,6 +44,7 @@ public: static Handle graalRuntime(); + static Handle truffleRuntime(); static jobject graalRuntimePermObject() { graalRuntime(); diff -r 0eeb9f8dab9b -r 5db21405c6a4 src/share/vm/interpreter/interpreterRuntime.cpp --- a/src/share/vm/interpreter/interpreterRuntime.cpp Mon Jun 24 10:22:28 2013 +0200 +++ b/src/share/vm/interpreter/interpreterRuntime.cpp Mon Jun 24 10:25:41 2013 +0200 @@ -501,6 +501,10 @@ IRT_END +IRT_ENTRY(void, InterpreterRuntime::throw_InvalidInstalledCodeException(JavaThread* thread)) + THROW(vmSymbols::com_oracle_graal_api_code_InvalidInstalledCodeException()); +IRT_END + //------------------------------------------------------------------------------------------------------------------------ // Fields // diff -r 0eeb9f8dab9b -r 5db21405c6a4 src/share/vm/interpreter/interpreterRuntime.hpp --- a/src/share/vm/interpreter/interpreterRuntime.hpp Mon Jun 24 10:22:28 2013 +0200 +++ b/src/share/vm/interpreter/interpreterRuntime.hpp Mon Jun 24 10:25:41 2013 +0200 @@ -89,6 +89,7 @@ // Exceptions thrown by the interpreter static void throw_AbstractMethodError(JavaThread* thread); static void throw_IncompatibleClassChangeError(JavaThread* thread); + static void throw_InvalidInstalledCodeException(JavaThread* thread); static void throw_StackOverflowError(JavaThread* thread); static void throw_ArrayIndexOutOfBoundsException(JavaThread* thread, char* name, jint index); static void throw_ClassCastException(JavaThread* thread, oopDesc* obj); diff -r 0eeb9f8dab9b -r 5db21405c6a4 src/share/vm/prims/nativeLookup.cpp --- a/src/share/vm/prims/nativeLookup.cpp Mon Jun 24 10:22:28 2013 +0200 +++ b/src/share/vm/prims/nativeLookup.cpp Mon Jun 24 10:25:41 2013 +0200 @@ -125,6 +125,7 @@ void JNICALL JVM_RegisterWhiteBoxMethods(JNIEnv *env, jclass wbclass); #ifdef GRAAL jobject JNICALL JVM_InitializeGraalRuntime(JNIEnv *env, jclass graalclass); + jobject JNICALL JVM_InitializeTruffleRuntime(JNIEnv *env, jclass graalclass); #endif } @@ -142,6 +143,7 @@ { CC"Java_sun_hotspot_WhiteBox_registerNatives", NULL, FN_PTR(JVM_RegisterWhiteBoxMethods) }, #ifdef GRAAL { CC"Java_com_oracle_graal_api_runtime_Graal_initializeRuntime", NULL, FN_PTR(JVM_InitializeGraalRuntime) }, + { CC"Java_com_oracle_truffle_api_Truffle_initializeRuntime", NULL, FN_PTR(JVM_InitializeTruffleRuntime) }, #endif }; diff -r 0eeb9f8dab9b -r 5db21405c6a4 src/share/vm/runtime/sharedRuntime.cpp --- a/src/share/vm/runtime/sharedRuntime.cpp Mon Jun 24 10:22:28 2013 +0200 +++ b/src/share/vm/runtime/sharedRuntime.cpp Mon Jun 24 10:25:41 2013 +0200 @@ -752,6 +752,11 @@ throw_and_post_jvmti_exception(thread, vmSymbols::java_lang_IncompatibleClassChangeError(), "vtable stub"); JRT_END +JRT_ENTRY(void, SharedRuntime::throw_InvalidInstalledCodeException(JavaThread* thread)) + // These errors occur only at call sites + throw_and_post_jvmti_exception(thread, vmSymbols::com_oracle_graal_api_code_InvalidInstalledCodeException()); +JRT_END + JRT_ENTRY(void, SharedRuntime::throw_ArithmeticException(JavaThread* thread)) throw_and_post_jvmti_exception(thread, vmSymbols::java_lang_ArithmeticException(), "/ by zero"); JRT_END diff -r 0eeb9f8dab9b -r 5db21405c6a4 src/share/vm/runtime/sharedRuntime.hpp --- a/src/share/vm/runtime/sharedRuntime.hpp Mon Jun 24 10:22:28 2013 +0200 +++ b/src/share/vm/runtime/sharedRuntime.hpp Mon Jun 24 10:25:41 2013 +0200 @@ -186,6 +186,7 @@ }; static void throw_AbstractMethodError(JavaThread* thread); static void throw_IncompatibleClassChangeError(JavaThread* thread); + static void throw_InvalidInstalledCodeException(JavaThread* thread); static void throw_ArithmeticException(JavaThread* thread); static void throw_NullPointerException(JavaThread* thread); static void throw_NullPointerException_at_call(JavaThread* thread); diff -r 0eeb9f8dab9b -r 5db21405c6a4 src/share/vm/runtime/stubRoutines.cpp --- a/src/share/vm/runtime/stubRoutines.cpp Mon Jun 24 10:22:28 2013 +0200 +++ b/src/share/vm/runtime/stubRoutines.cpp Mon Jun 24 10:25:41 2013 +0200 @@ -51,6 +51,7 @@ address StubRoutines::_forward_exception_entry = NULL; address StubRoutines::_throw_AbstractMethodError_entry = NULL; address StubRoutines::_throw_IncompatibleClassChangeError_entry = NULL; +address StubRoutines::_throw_InvalidInstalledCodeException_entry = NULL; address StubRoutines::_throw_NullPointerException_at_call_entry = NULL; address StubRoutines::_throw_StackOverflowError_entry = NULL; address StubRoutines::_handler_for_unsafe_access_entry = NULL; diff -r 0eeb9f8dab9b -r 5db21405c6a4 src/share/vm/runtime/stubRoutines.hpp --- a/src/share/vm/runtime/stubRoutines.hpp Mon Jun 24 10:22:28 2013 +0200 +++ b/src/share/vm/runtime/stubRoutines.hpp Mon Jun 24 10:25:41 2013 +0200 @@ -128,6 +128,7 @@ static address _catch_exception_entry; static address _throw_AbstractMethodError_entry; static address _throw_IncompatibleClassChangeError_entry; + static address _throw_InvalidInstalledCodeException_entry; static address _throw_NullPointerException_at_call_entry; static address _throw_StackOverflowError_entry; static address _handler_for_unsafe_access_entry; @@ -261,6 +262,7 @@ // Implicit exceptions static address throw_AbstractMethodError_entry() { return _throw_AbstractMethodError_entry; } static address throw_IncompatibleClassChangeError_entry(){ return _throw_IncompatibleClassChangeError_entry; } + static address throw_InvalidInstalledCodeException_entry(){ return _throw_InvalidInstalledCodeException_entry; } static address throw_NullPointerException_at_call_entry(){ return _throw_NullPointerException_at_call_entry; } static address throw_StackOverflowError_entry() { return _throw_StackOverflowError_entry; }