/*
 * Copyright (c) 2015, 2016, 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 org.graalvm.compiler.hotspot.test;

import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG;
import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.STACK;
import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_IGNORED;
import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_IGNORED;

import java.util.function.Consumer;

import org.junit.Test;

import org.graalvm.compiler.code.CompilationResult;
import org.graalvm.compiler.core.common.LIRKind;
import org.graalvm.compiler.core.common.type.StampFactory;
import org.graalvm.compiler.core.test.GraalCompilerTest;
import org.graalvm.compiler.debug.Debug;
import org.graalvm.compiler.debug.DebugConfigScope;
import org.graalvm.compiler.graph.NodeClass;
import org.graalvm.compiler.hotspot.HotSpotCompiledCodeBuilder;
import org.graalvm.compiler.lir.FullInfopointOp;
import org.graalvm.compiler.lir.LIRFrameState;
import org.graalvm.compiler.lir.LIRInstruction;
import org.graalvm.compiler.lir.LIRInstructionClass;
import org.graalvm.compiler.lir.Variable;
import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
import org.graalvm.compiler.lir.gen.LIRGeneratorTool;
import org.graalvm.compiler.nodeinfo.NodeInfo;
import org.graalvm.compiler.nodes.DeoptimizingFixedWithNextNode;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.spi.LIRLowerable;
import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;

import jdk.vm.ci.code.BytecodeFrame;
import jdk.vm.ci.code.VirtualObject;
import jdk.vm.ci.code.site.InfopointReason;
import jdk.vm.ci.common.JVMCIError;
import jdk.vm.ci.hotspot.HotSpotCompiledCode;
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.PlatformKind;
import jdk.vm.ci.meta.ResolvedJavaMethod;
import jdk.vm.ci.meta.ResolvedJavaType;
import jdk.vm.ci.meta.Value;

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;

        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;

        ValueUse(AllocatableValue value) {
            super(TYPE);
            this.value = value;
        }

        @Override
        public void emitCode(CompilationResultBuilder crb) {
        }
    }

    @NodeInfo(cycles = CYCLES_IGNORED, size = SIZE_IGNORED)
    private static class TestNode extends DeoptimizingFixedWithNextNode implements LIRLowerable {
        private static final NodeClass<TestNode> TYPE = NodeClass.create(TestNode.class);

        private final TestSpec spec;

        protected TestNode(TestSpec spec) {
            super(TYPE, StampFactory.forVoid());
            this.spec = spec;
        }

        @Override
        public boolean canDeoptimize() {
            return true;
        }

        @Override
        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);
        HotSpotCompiledCode compiledCode = HotSpotCompiledCodeBuilder.createCompiledCode(method, null, compResult);
        getCodeCache().addCode(method, compiledCode, 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(LIRKind.fromJavaKind(tool.target().arch, 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(LIRKind.fromJavaKind(tool.target().arch, 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 GraalError, 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 GraalError, 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);
        });
    }
}
