# HG changeset patch # User Thomas Wuerthinger # Date 1363546186 -3600 # Node ID 70dd2a8e170cdd341890bf882ad9ea9e40b8d1e3 # Parent 330b455f18be12648974150c95b88a568c62b7cf Add test case for deoptimizing out of a synchronized method. Made guard lowering phase use earliest schedule. diff -r 330b455f18be -r 70dd2a8e170c graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CompiledMethodTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CompiledMethodTest.java Sun Mar 17 19:39:28 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,199 +0,0 @@ -/* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.compiler.test; - -import java.lang.reflect.*; - -import org.junit.*; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.code.InstalledCode.*; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.java.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.phases.*; -import com.oracle.graal.phases.common.*; - -/** - * In the following tests, the usages of local variable "a" are replaced with the integer constant - * 0. Then canonicalization is applied and it is verified that the resulting graph is equal to the - * graph of the method that just has a "return 1" statement in it. - */ -public class CompiledMethodTest extends GraalCompilerTest { - - public static Object testMethod(Object arg1, Object arg2, Object arg3) { - return arg1 + " " + arg2 + " " + arg3; - } - - Object f1; - - public Object testMethodVirtual(Object arg1, Object arg2, Object arg3) { - return f1 + " " + arg1 + " " + arg2 + " " + arg3; - } - - @Test - public void test1() { - Method method = getMethod("testMethod"); - final StructuredGraph graph = parse(method); - new CanonicalizerPhase(runtime(), new Assumptions(false)).apply(graph); - new DeadCodeEliminationPhase().apply(graph); - - for (Node node : graph.getNodes()) { - if (node instanceof ConstantNode) { - ConstantNode constant = (ConstantNode) node; - if (constant.kind() == Kind.Object && " ".equals(constant.value.asObject())) { - graph.replaceFloating(constant, ConstantNode.forObject("-", runtime, graph)); - } - } - } - - final ResolvedJavaMethod javaMethod = runtime.lookupJavaMethod(method); - InstalledCode compiledMethod = getCode(javaMethod, graph); - try { - Object result = compiledMethod.execute("1", "2", "3"); - Assert.assertEquals("1-2-3", result); - } catch (MethodInvalidatedException t) { - Assert.fail("method invalidated"); - } - } - - @Test - public void test3() { - Method method = getMethod("testMethod"); - final StructuredGraph graph = parse(method); - final ResolvedJavaMethod javaMethod = runtime.lookupJavaMethod(method); - InstalledCode compiledMethod = getCode(javaMethod, graph); - try { - Object result = compiledMethod.executeVarargs("1", "2", "3"); - Assert.assertEquals("1 2 3", result); - } catch (MethodInvalidatedException t) { - Assert.fail("method invalidated"); - } - } - - @Test - public void test4() { - Method method = getMethod("testMethodVirtual"); - final StructuredGraph graph = parse(method); - final ResolvedJavaMethod javaMethod = runtime.lookupJavaMethod(method); - InstalledCode compiledMethod = getCode(javaMethod, graph); - try { - f1 = "0"; - Object result = compiledMethod.executeVarargs(this, "1", "2", "3"); - Assert.assertEquals("0 1 2 3", result); - } catch (MethodInvalidatedException t) { - Assert.fail("method invalidated"); - } - } - - @Test - public void test2() throws NoSuchMethodException, SecurityException { - Method method = CompilableObjectImpl.class.getDeclaredMethod("executeHelper", ObjectCompiler.class, String.class); - ResolvedJavaMethod javaMethod = runtime.lookupJavaMethod(method); - StructuredGraph graph = new StructuredGraph(javaMethod); - new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getEagerDefault(), OptimisticOptimizations.NONE).apply(graph); - new CanonicalizerPhase(runtime, new Assumptions(false)).apply(graph); - new DeadCodeEliminationPhase().apply(graph); - - for (Node node : graph.getNodes()) { - if (node instanceof ConstantNode) { - ConstantNode constant = (ConstantNode) node; - if (constant.kind() == Kind.Object && "1 ".equals(constant.value.asObject())) { - graph.replaceFloating(constant, ConstantNode.forObject("1-", runtime, graph)); - } - } - } - - InstalledCode compiledMethod = getCode(javaMethod, graph); - final CompilableObject compilableObject = new CompilableObjectImpl(0); - - Object result; - result = compilableObject.execute(new ObjectCompilerImpl(compiledMethod), "3"); - Assert.assertEquals("1-3", result); - } - - public abstract class CompilableObject { - - private CompiledObject compiledObject; - private final int compileThreshold; - private int counter; - - public CompilableObject(int compileThreshold) { - this.compileThreshold = compileThreshold; - } - - public final Object execute(ObjectCompiler compiler, String args) { - if (counter++ < compileThreshold || compiler == null) { - return executeHelper(compiler, args); - } else { - compiledObject = compiler.compile(this); - return compiledObject.execute(compiler, args); - } - } - - protected abstract Object executeHelper(ObjectCompiler context, String args); - } - - private final class CompilableObjectImpl extends CompilableObject { - - private CompilableObjectImpl(int compileThreshold) { - super(compileThreshold); - } - - @Override - protected Object executeHelper(ObjectCompiler compiler, String args) { - return "1 " + args; - } - } - - public interface CompiledObject { - - Object execute(ObjectCompiler context, String args); - } - - public interface ObjectCompiler { - - CompiledObject compile(CompilableObject node); - } - - private final class ObjectCompilerImpl implements ObjectCompiler { - - private final InstalledCode compiledMethod; - - private ObjectCompilerImpl(InstalledCode compiledMethod) { - this.compiledMethod = compiledMethod; - } - - @Override - public CompiledObject compile(final CompilableObject node) { - return new CompiledObject() { - - @Override - public Object execute(ObjectCompiler compiler, String args) { - return compiledMethod.execute(node, compiler, args); - } - }; - } - } -} diff -r 330b455f18be -r 70dd2a8e170c graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/CompiledMethodTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/CompiledMethodTest.java Sun Mar 17 19:49:46 2013 +0100 @@ -0,0 +1,200 @@ +/* + * 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.compiler.test.deopt; + +import java.lang.reflect.*; + +import org.junit.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.code.InstalledCode.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.test.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.java.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.phases.*; +import com.oracle.graal.phases.common.*; + +/** + * In the following tests, the usages of local variable "a" are replaced with the integer constant + * 0. Then canonicalization is applied and it is verified that the resulting graph is equal to the + * graph of the method that just has a "return 1" statement in it. + */ +public class CompiledMethodTest extends GraalCompilerTest { + + public static Object testMethod(Object arg1, Object arg2, Object arg3) { + return arg1 + " " + arg2 + " " + arg3; + } + + Object f1; + + public Object testMethodVirtual(Object arg1, Object arg2, Object arg3) { + return f1 + " " + arg1 + " " + arg2 + " " + arg3; + } + + @Test + public void test1() { + Method method = getMethod("testMethod"); + final StructuredGraph graph = parse(method); + new CanonicalizerPhase(runtime(), new Assumptions(false)).apply(graph); + new DeadCodeEliminationPhase().apply(graph); + + for (Node node : graph.getNodes()) { + if (node instanceof ConstantNode) { + ConstantNode constant = (ConstantNode) node; + if (constant.kind() == Kind.Object && " ".equals(constant.value.asObject())) { + graph.replaceFloating(constant, ConstantNode.forObject("-", runtime, graph)); + } + } + } + + final ResolvedJavaMethod javaMethod = runtime.lookupJavaMethod(method); + InstalledCode compiledMethod = getCode(javaMethod, graph); + try { + Object result = compiledMethod.execute("1", "2", "3"); + Assert.assertEquals("1-2-3", result); + } catch (MethodInvalidatedException t) { + Assert.fail("method invalidated"); + } + } + + @Test + public void test3() { + Method method = getMethod("testMethod"); + final StructuredGraph graph = parse(method); + final ResolvedJavaMethod javaMethod = runtime.lookupJavaMethod(method); + InstalledCode compiledMethod = getCode(javaMethod, graph); + try { + Object result = compiledMethod.executeVarargs("1", "2", "3"); + Assert.assertEquals("1 2 3", result); + } catch (MethodInvalidatedException t) { + Assert.fail("method invalidated"); + } + } + + @Test + public void test4() { + Method method = getMethod("testMethodVirtual"); + final StructuredGraph graph = parse(method); + final ResolvedJavaMethod javaMethod = runtime.lookupJavaMethod(method); + InstalledCode compiledMethod = getCode(javaMethod, graph); + try { + f1 = "0"; + Object result = compiledMethod.executeVarargs(this, "1", "2", "3"); + Assert.assertEquals("0 1 2 3", result); + } catch (MethodInvalidatedException t) { + Assert.fail("method invalidated"); + } + } + + @Test + public void test2() throws NoSuchMethodException, SecurityException { + Method method = CompilableObjectImpl.class.getDeclaredMethod("executeHelper", ObjectCompiler.class, String.class); + ResolvedJavaMethod javaMethod = runtime.lookupJavaMethod(method); + StructuredGraph graph = new StructuredGraph(javaMethod); + new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getEagerDefault(), OptimisticOptimizations.NONE).apply(graph); + new CanonicalizerPhase(runtime, new Assumptions(false)).apply(graph); + new DeadCodeEliminationPhase().apply(graph); + + for (Node node : graph.getNodes()) { + if (node instanceof ConstantNode) { + ConstantNode constant = (ConstantNode) node; + if (constant.kind() == Kind.Object && "1 ".equals(constant.value.asObject())) { + graph.replaceFloating(constant, ConstantNode.forObject("1-", runtime, graph)); + } + } + } + + InstalledCode compiledMethod = getCode(javaMethod, graph); + final CompilableObject compilableObject = new CompilableObjectImpl(0); + + Object result; + result = compilableObject.execute(new ObjectCompilerImpl(compiledMethod), "3"); + Assert.assertEquals("1-3", result); + } + + public abstract class CompilableObject { + + private CompiledObject compiledObject; + private final int compileThreshold; + private int counter; + + public CompilableObject(int compileThreshold) { + this.compileThreshold = compileThreshold; + } + + public final Object execute(ObjectCompiler compiler, String args) { + if (counter++ < compileThreshold || compiler == null) { + return executeHelper(compiler, args); + } else { + compiledObject = compiler.compile(this); + return compiledObject.execute(compiler, args); + } + } + + protected abstract Object executeHelper(ObjectCompiler context, String args); + } + + private final class CompilableObjectImpl extends CompilableObject { + + private CompilableObjectImpl(int compileThreshold) { + super(compileThreshold); + } + + @Override + protected Object executeHelper(ObjectCompiler compiler, String args) { + return "1 " + args; + } + } + + public interface CompiledObject { + + Object execute(ObjectCompiler context, String args); + } + + public interface ObjectCompiler { + + CompiledObject compile(CompilableObject node); + } + + private final class ObjectCompilerImpl implements ObjectCompiler { + + private final InstalledCode compiledMethod; + + private ObjectCompilerImpl(InstalledCode compiledMethod) { + this.compiledMethod = compiledMethod; + } + + @Override + public CompiledObject compile(final CompilableObject node) { + return new CompiledObject() { + + @Override + public Object execute(ObjectCompiler compiler, String args) { + return compiledMethod.execute(node, compiler, args); + } + }; + } + } +} diff -r 330b455f18be -r 70dd2a8e170c graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/SynchronizedMethodDeoptimizationTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/SynchronizedMethodDeoptimizationTest.java Sun Mar 17 19:49:46 2013 +0100 @@ -0,0 +1,74 @@ +/* + * 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.compiler.test.deopt; + +import java.lang.reflect.*; + +import org.junit.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.code.InstalledCode.MethodInvalidatedException; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.test.*; +import com.oracle.graal.nodes.*; + +/** + * In the following tests, we try to deoptimize out of synchronized methods. + */ +public class SynchronizedMethodDeoptimizationTest extends GraalCompilerTest { + + public static final int N = 15000; + + public static synchronized Object testMethodSynchronized(Object o) { + if (o == null) { + return null; + } + return o; + } + + @Test + public void test1() { + Method method = getMethod("testMethodSynchronized"); + String testString = "test"; + for (int i = 0; i < N; ++i) { + Assert.assertEquals(testString, testMethodSynchronized(testString)); + } + final StructuredGraph graph = parseProfiled(method); + final ResolvedJavaMethod javaMethod = runtime.lookupJavaMethod(method); + InstalledCode compiledMethod = getCode(javaMethod, graph); + try { + Object result = compiledMethod.executeVarargs(testString); + Assert.assertEquals(testString, result); + } catch (MethodInvalidatedException t) { + Assert.fail("method invalidated"); + } + + try { + Object result = compiledMethod.executeVarargs(new Object[]{null}); + Assert.assertEquals(null, result); + Assert.assertFalse(compiledMethod.isValid()); + } catch (MethodInvalidatedException t) { + Assert.fail("method invalidated"); + } + } +} diff -r 330b455f18be -r 70dd2a8e170c graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java Sun Mar 17 19:39:28 2013 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java Sun Mar 17 19:49:46 2013 +0100 @@ -45,7 +45,7 @@ @Override protected void run(StructuredGraph graph) { - SchedulePhase schedule = new SchedulePhase(); + SchedulePhase schedule = new SchedulePhase(SchedulePhase.SchedulingStrategy.EARLIEST); schedule.apply(graph); for (Block block : schedule.getCFG().getBlocks()) {