changeset 22902:76a4f40ed8d1

Unit test for error conditions in JVMCI code installer.
author Roland Schatz <roland.schatz@oracle.com>
date Thu, 29 Oct 2015 16:29:42 +0100
parents 666ddd927480
children 217a942e3603
files graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/JVMCIErrorTest.java graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/JVMCIInfopointErrorTest.java mx.graal/suite.py
diffstat 3 files changed, 511 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/JVMCIErrorTest.java	Thu Oct 29 16:29:42 2015 +0100
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.test;
+
+import java.util.function.Consumer;
+
+import jdk.vm.ci.code.CompilationResult;
+import jdk.vm.ci.code.CompilationResult.ConstantReference;
+import jdk.vm.ci.code.CompilationResult.DataPatch;
+import jdk.vm.ci.code.CompilationResult.DataSectionReference;
+import jdk.vm.ci.code.CompilationResult.Infopoint;
+import jdk.vm.ci.code.CompilationResult.Reference;
+import jdk.vm.ci.code.DataSection.Data;
+import jdk.vm.ci.code.DataSection.DataBuilder;
+import jdk.vm.ci.code.InfopointReason;
+import jdk.vm.ci.common.JVMCIError;
+import jdk.vm.ci.hotspot.HotSpotConstant;
+import jdk.vm.ci.meta.Assumptions.Assumption;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.VMConstant;
+
+import org.junit.Test;
+
+import com.oracle.graal.compiler.test.GraalCompilerTest;
+
+public class JVMCIErrorTest extends GraalCompilerTest {
+
+    public static void testMethod() {
+    }
+
+    private void test(Consumer<CompilationResult> modify) {
+        ResolvedJavaMethod method = getResolvedJavaMethod("testMethod");
+        CompilationResult compResult = compile(method, null);
+
+        modify.accept(compResult);
+
+        getCodeCache().addCode(method, compResult, null, null);
+    }
+
+    @Test(expected = JVMCIError.class)
+    public void testInvalidAssumption() {
+        test(r -> r.setAssumptions(new Assumption[]{new InvalidAssumption()}));
+    }
+
+    private static class InvalidAssumption extends Assumption {
+    }
+
+    @Test(expected = JVMCIError.class)
+    public void testInvalidAlignment() {
+        test(r -> r.getDataSection().insertData(new Data(7, 1, DataBuilder.zero(1))));
+    }
+
+    @Test(expected = JVMCIError.class)
+    public void testInvalidDataSectionReference() {
+        test(r -> {
+            DataSectionReference ref = r.getDataSection().insertData(new Data(1, 1, DataBuilder.zero(1)));
+            Data data = new Data(1, 1, (buffer, patch) -> {
+                patch.accept(new DataPatch(buffer.position(), ref));
+                buffer.put((byte) 0);
+            });
+            r.getDataSection().insertData(data);
+        });
+    }
+
+    @Test(expected = JVMCIError.class)
+    public void testInvalidNarrowMethodInDataSection() {
+        test(r -> {
+            ResolvedJavaMethod method = getResolvedJavaMethod("testMethod");
+            HotSpotConstant c = (HotSpotConstant) method.getEncoding();
+            Data data = new Data(4, 4, (buffer, patch) -> {
+                patch.accept(new DataPatch(buffer.position(), new ConstantReference((VMConstant) c.compress())));
+                buffer.putInt(0);
+            });
+            r.getDataSection().insertData(data);
+        });
+    }
+
+    @Test(expected = JVMCIError.class)
+    public void testInvalidConstantInDataSection() {
+        test(r -> {
+            Data data = new Data(1, 1, (buffer, patch) -> {
+                patch.accept(new DataPatch(buffer.position(), new ConstantReference(new InvalidVMConstant())));
+            });
+            r.getDataSection().insertData(data);
+        });
+    }
+
+    @Test(expected = JVMCIError.class)
+    public void testInvalidConstantInCode() {
+        test(r -> r.recordDataPatch(0, new ConstantReference(new InvalidVMConstant())));
+    }
+
+    private static class InvalidVMConstant implements VMConstant {
+
+        public boolean isDefaultForKind() {
+            return false;
+        }
+
+        public String toValueString() {
+            return null;
+        }
+    }
+
+    @Test(expected = JVMCIError.class)
+    public void testInvalidReference() {
+        test(r -> r.recordDataPatch(0, new InvalidReference()));
+    }
+
+    private static class InvalidReference extends Reference {
+
+        @Override
+        public int hashCode() {
+            return 0;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            return false;
+        }
+    }
+
+    @Test(expected = JVMCIError.class)
+    public void testOutOfBoundsDataSectionReference() {
+        test(r -> {
+            DataSectionReference ref = new DataSectionReference();
+            ref.setOffset(0x1000);
+            r.recordDataPatch(0, ref);
+        });
+    }
+
+    @Test(expected = JVMCIError.class)
+    public void testInvalidMark() {
+        test(r -> r.recordMark(0, new Object()));
+    }
+
+    @Test(expected = JVMCIError.class)
+    public void testInvalidMarkInt() {
+        test(r -> r.recordMark(0, -1));
+    }
+
+    @Test(expected = JVMCIError.class)
+    public void testUnknownInfopointReason() {
+        test(r -> r.addInfopoint(new Infopoint(0, null, InfopointReason.UNKNOWN)));
+    }
+
+    @Test(expected = JVMCIError.class)
+    public void testInfopointMissingDebugInfo() {
+        test(r -> r.addInfopoint(new Infopoint(0, null, InfopointReason.METHOD_START)));
+    }
+
+    @Test(expected = JVMCIError.class)
+    public void testSafepointMissingDebugInfo() {
+        test(r -> r.addInfopoint(new Infopoint(0, null, InfopointReason.SAFEPOINT)));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/JVMCIInfopointErrorTest.java	Thu Oct 29 16:29:42 2015 +0100
@@ -0,0 +1,335 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.test;
+
+import static com.oracle.graal.lir.LIRInstruction.OperandFlag.REG;
+import static com.oracle.graal.lir.LIRInstruction.OperandFlag.STACK;
+
+import java.util.function.Consumer;
+
+import jdk.vm.ci.code.BytecodeFrame;
+import jdk.vm.ci.code.CompilationResult;
+import jdk.vm.ci.code.InfopointReason;
+import jdk.vm.ci.code.VirtualObject;
+import jdk.vm.ci.common.JVMCIError;
+import jdk.vm.ci.meta.AllocatableValue;
+import jdk.vm.ci.meta.JavaConstant;
+import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.JavaValue;
+import jdk.vm.ci.meta.LIRKind;
+import jdk.vm.ci.meta.PlatformKind;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.ResolvedJavaType;
+import jdk.vm.ci.meta.Value;
+
+import org.junit.Test;
+
+import com.oracle.graal.compiler.common.type.StampFactory;
+import com.oracle.graal.compiler.test.GraalCompilerTest;
+import com.oracle.graal.debug.Debug;
+import com.oracle.graal.debug.DebugConfigScope;
+import com.oracle.graal.graph.NodeClass;
+import com.oracle.graal.lir.FullInfopointOp;
+import com.oracle.graal.lir.LIRFrameState;
+import com.oracle.graal.lir.LIRInstruction;
+import com.oracle.graal.lir.LIRInstructionClass;
+import com.oracle.graal.lir.Variable;
+import com.oracle.graal.lir.asm.CompilationResultBuilder;
+import com.oracle.graal.lir.gen.LIRGeneratorTool;
+import com.oracle.graal.nodeinfo.NodeInfo;
+import com.oracle.graal.nodes.DeoptimizingFixedWithNextNode;
+import com.oracle.graal.nodes.StructuredGraph;
+import com.oracle.graal.nodes.spi.LIRLowerable;
+import com.oracle.graal.nodes.spi.NodeLIRBuilderTool;
+
+public class JVMCIInfopointErrorTest extends GraalCompilerTest {
+
+    private static class ValueDef extends LIRInstruction {
+        private static final LIRInstructionClass<ValueDef> TYPE = LIRInstructionClass.create(ValueDef.class);
+
+        @Def({REG, STACK}) AllocatableValue value;
+
+        public ValueDef(AllocatableValue value) {
+            super(TYPE);
+            this.value = value;
+        }
+
+        @Override
+        public void emitCode(CompilationResultBuilder crb) {
+        }
+    }
+
+    private static class ValueUse extends LIRInstruction {
+        private static final LIRInstructionClass<ValueUse> TYPE = LIRInstructionClass.create(ValueUse.class);
+
+        @Use({REG, STACK}) AllocatableValue value;
+
+        public ValueUse(AllocatableValue value) {
+            super(TYPE);
+            this.value = value;
+        }
+
+        @Override
+        public void emitCode(CompilationResultBuilder crb) {
+        }
+    }
+
+    @NodeInfo
+    private static class TestNode extends DeoptimizingFixedWithNextNode implements LIRLowerable {
+        private static final NodeClass<TestNode> TYPE = NodeClass.create(TestNode.class);
+
+        private final TestSpec spec;
+
+        public TestNode(TestSpec spec) {
+            super(TYPE, StampFactory.forVoid());
+            this.spec = spec;
+        }
+
+        public boolean canDeoptimize() {
+            return true;
+        }
+
+        public void generate(NodeLIRBuilderTool gen) {
+            LIRGeneratorTool tool = gen.getLIRGeneratorTool();
+            LIRFrameState state = gen.state(this);
+            spec.spec(tool, state, st -> {
+                tool.append(new FullInfopointOp(st, InfopointReason.SAFEPOINT));
+            });
+        }
+    }
+
+    @FunctionalInterface
+    private interface TestSpec {
+        void spec(LIRGeneratorTool tool, LIRFrameState state, Consumer<LIRFrameState> safepoint);
+    }
+
+    public static void testMethod() {
+    }
+
+    private void test(TestSpec spec) {
+        ResolvedJavaMethod method = getResolvedJavaMethod("testMethod");
+
+        StructuredGraph graph = parseForCompile(method);
+        TestNode test = graph.add(new TestNode(spec));
+        graph.addAfterFixed(graph.start(), test);
+
+        CompilationResult compResult = compile(method, graph);
+        getCodeCache().addCode(method, compResult, null, null);
+    }
+
+    @Test(expected = JVMCIError.class)
+    public void testInvalidShortOop() {
+        test((tool, state, safepoint) -> {
+            PlatformKind kind = tool.target().arch.getPlatformKind(JavaKind.Short);
+            LIRKind lirKind = LIRKind.reference(kind);
+
+            Variable var = tool.newVariable(lirKind);
+            tool.append(new ValueDef(var));
+            safepoint.accept(state);
+            tool.append(new ValueUse(var));
+        });
+    }
+
+    @Test(expected = JVMCIError.class)
+    public void testInvalidShortDerivedOop() {
+        test((tool, state, safepoint) -> {
+            Variable baseOop = tool.newVariable(tool.target().getLIRKind(JavaKind.Object));
+            tool.append(new ValueDef(baseOop));
+
+            PlatformKind kind = tool.target().arch.getPlatformKind(JavaKind.Short);
+            LIRKind lirKind = LIRKind.derivedReference(kind, baseOop);
+
+            Variable var = tool.newVariable(lirKind);
+            tool.append(new ValueDef(var));
+            safepoint.accept(state);
+            tool.append(new ValueUse(var));
+        });
+    }
+
+    private static LIRFrameState modifyTopFrame(LIRFrameState state, JavaValue[] values, JavaKind[] slotKinds, int locals, int stack, int locks) {
+        return modifyTopFrame(state, null, values, slotKinds, locals, stack, locks);
+    }
+
+    private static LIRFrameState modifyTopFrame(LIRFrameState state, VirtualObject[] vobj, JavaValue[] values, JavaKind[] slotKinds, int locals, int stack, int locks) {
+        BytecodeFrame top = state.topFrame;
+        top = new BytecodeFrame(top.caller(), top.getMethod(), top.getBCI(), top.rethrowException, top.duringCall, values, slotKinds, locals, stack, locks);
+        return new LIRFrameState(top, vobj, state.exceptionEdge);
+    }
+
+    @Test(expected = JVMCIError.class)
+    public void testUnexpectedScopeValuesLength() {
+        test((tool, state, safepoint) -> {
+            LIRFrameState newState = modifyTopFrame(state, new JavaValue[]{JavaConstant.FALSE}, new JavaKind[0], 0, 0, 0);
+            safepoint.accept(newState);
+        });
+    }
+
+    @Test(expected = JVMCIError.class)
+    public void testUnexpectedScopeSlotKindsLength() {
+        test((tool, state, safepoint) -> {
+            LIRFrameState newState = modifyTopFrame(state, new JavaValue[0], new JavaKind[]{JavaKind.Boolean}, 0, 0, 0);
+            safepoint.accept(newState);
+        });
+    }
+
+    @Test(expected = JVMCIError.class)
+    public void testWrongMonitorType() {
+        test((tool, state, safepoint) -> {
+            LIRFrameState newState = modifyTopFrame(state, new JavaValue[]{JavaConstant.INT_0}, new JavaKind[]{}, 0, 0, 1);
+            safepoint.accept(newState);
+        });
+    }
+
+    @Test(expected = JVMCIError.class)
+    public void testUnexpectedIllegalValue() {
+        test((tool, state, safepoint) -> {
+            LIRFrameState newState = modifyTopFrame(state, new JavaValue[]{Value.ILLEGAL}, new JavaKind[]{JavaKind.Int}, 1, 0, 0);
+            safepoint.accept(newState);
+        });
+    }
+
+    @Test(expected = JVMCIError.class)
+    public void testUnexpectedTypeInRegister() {
+        test((tool, state, safepoint) -> {
+            Variable var = tool.newVariable(tool.target().getLIRKind(JavaKind.Int));
+            tool.append(new ValueDef(var));
+            LIRFrameState newState = modifyTopFrame(state, new JavaValue[]{var}, new JavaKind[]{JavaKind.Illegal}, 1, 0, 0);
+            safepoint.accept(newState);
+        });
+    }
+
+    @Test(expected = JVMCIError.class)
+    public void testWrongConstantType() {
+        test((tool, state, safepoint) -> {
+            LIRFrameState newState = modifyTopFrame(state, new JavaValue[]{JavaConstant.INT_0}, new JavaKind[]{JavaKind.Object}, 1, 0, 0);
+            safepoint.accept(newState);
+        });
+    }
+
+    @Test(expected = JVMCIError.class)
+    public void testUnsupportedConstantType() {
+        test((tool, state, safepoint) -> {
+            LIRFrameState newState = modifyTopFrame(state, new JavaValue[]{JavaConstant.forShort((short) 0)}, new JavaKind[]{JavaKind.Short}, 1, 0, 0);
+            safepoint.accept(newState);
+        });
+    }
+
+    @Test(expected = JVMCIError.class)
+    public void testUnexpectedNull() {
+        test((tool, state, safepoint) -> {
+            LIRFrameState newState = modifyTopFrame(state, new JavaValue[]{JavaConstant.NULL_POINTER}, new JavaKind[]{JavaKind.Int}, 1, 0, 0);
+            safepoint.accept(newState);
+        });
+    }
+
+    @Test(expected = JVMCIError.class)
+    public void testUnexpectedObject() {
+        JavaValue wrapped = getSnippetReflection().forObject(this);
+        test((tool, state, safepoint) -> {
+            LIRFrameState newState = modifyTopFrame(state, new JavaValue[]{wrapped}, new JavaKind[]{JavaKind.Int}, 1, 0, 0);
+            safepoint.accept(newState);
+        });
+    }
+
+    private static class UnknownJavaValue implements JavaValue {
+    }
+
+    @SuppressWarnings("try")
+    @Test(expected = Error.class)
+    public void testUnknownJavaValue() {
+        try (DebugConfigScope s = Debug.setConfig(Debug.silentConfig())) {
+            /*
+             * Expected: either AssertionError or JVMCIError, depending on whether the unit test run
+             * is with assertions enabled or disabled.
+             */
+            test((tool, state, safepoint) -> {
+                LIRFrameState newState = modifyTopFrame(state, new JavaValue[]{new UnknownJavaValue()}, new JavaKind[]{JavaKind.Int}, 1, 0, 0);
+                safepoint.accept(newState);
+            });
+        }
+    }
+
+    @Test(expected = Error.class)
+    public void testMissingIllegalAfterDouble() {
+        /*
+         * Expected: either AssertionError or JVMCIError, depending on whether the unit test run is
+         * with assertions enabled or disabled.
+         */
+        test((tool, state, safepoint) -> {
+            LIRFrameState newState = modifyTopFrame(state, new JavaValue[]{JavaConstant.DOUBLE_0, JavaConstant.INT_0}, new JavaKind[]{JavaKind.Double, JavaKind.Int}, 2, 0, 0);
+            safepoint.accept(newState);
+        });
+    }
+
+    @Test(expected = JVMCIError.class)
+    public void testInvalidVirtualObjectId() {
+        ResolvedJavaType obj = getMetaAccess().lookupJavaType(Object.class);
+        test((tool, state, safepoint) -> {
+            VirtualObject o = VirtualObject.get(obj, 5);
+            o.setValues(new JavaValue[0], new JavaKind[0]);
+
+            safepoint.accept(new LIRFrameState(state.topFrame, new VirtualObject[]{o}, state.exceptionEdge));
+        });
+    }
+
+    @Test(expected = JVMCIError.class)
+    public void testDuplicateVirtualObject() {
+        ResolvedJavaType obj = getMetaAccess().lookupJavaType(Object.class);
+        test((tool, state, safepoint) -> {
+            VirtualObject o1 = VirtualObject.get(obj, 0);
+            o1.setValues(new JavaValue[0], new JavaKind[0]);
+
+            VirtualObject o2 = VirtualObject.get(obj, 0);
+            o2.setValues(new JavaValue[0], new JavaKind[0]);
+
+            safepoint.accept(new LIRFrameState(state.topFrame, new VirtualObject[]{o1, o2}, state.exceptionEdge));
+        });
+    }
+
+    @Test(expected = JVMCIError.class)
+    public void testUnexpectedVirtualObject() {
+        ResolvedJavaType obj = getMetaAccess().lookupJavaType(Object.class);
+        test((tool, state, safepoint) -> {
+            VirtualObject o = VirtualObject.get(obj, 0);
+            o.setValues(new JavaValue[0], new JavaKind[0]);
+
+            LIRFrameState newState = modifyTopFrame(state, new VirtualObject[]{o}, new JavaValue[]{o}, new JavaKind[]{JavaKind.Int}, 1, 0, 0);
+            safepoint.accept(newState);
+        });
+    }
+
+    @Test(expected = JVMCIError.class)
+    public void testUndefinedVirtualObject() {
+        ResolvedJavaType obj = getMetaAccess().lookupJavaType(Object.class);
+        test((tool, state, safepoint) -> {
+            VirtualObject o0 = VirtualObject.get(obj, 0);
+            o0.setValues(new JavaValue[0], new JavaKind[0]);
+
+            VirtualObject o1 = VirtualObject.get(obj, 1);
+            o1.setValues(new JavaValue[0], new JavaKind[0]);
+
+            LIRFrameState newState = modifyTopFrame(state, new VirtualObject[]{o0}, new JavaValue[]{o1}, new JavaKind[]{JavaKind.Object}, 1, 0, 0);
+            safepoint.accept(newState);
+        });
+    }
+}
--- a/mx.graal/suite.py	Thu Oct 29 13:32:53 2015 +0100
+++ b/mx.graal/suite.py	Thu Oct 29 16:29:42 2015 +0100
@@ -22,7 +22,7 @@
             {
                "name" : "jvmci",
                "optional" : "true",
-               "version" : "7e7573382a23216db2c177811ae083383af62e90",
+               "version" : "316e768645c07309a10dc9c150b4b968d06b66cc",
                "urls" : [
                     {"url" : "http://lafo.ssw.uni-linz.ac.at/hg/graal-jvmci-8", "kind" : "hg"},
                     {"url" : "https://curio.ssw.jku.at/nexus/content/repositories/snapshots", "kind" : "binary"},