/* * Copyright (c) 2019, 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.junit.Assert.assertNotEquals; import org.graalvm.compiler.api.directives.GraalDirectives; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.hotspot.nodes.KlassBeingInitializedCheckNode; import org.graalvm.compiler.nodes.DeoptimizeNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.java.LoadFieldNode; import org.graalvm.compiler.nodes.java.NewInstanceNode; import org.junit.Assert; import org.junit.Assume; import org.junit.Before; import org.junit.Test; import jdk.vm.ci.code.InstalledCode; import jdk.vm.ci.code.InvalidInstalledCodeException; import jdk.vm.ci.meta.DeoptimizationReason; import jdk.vm.ci.meta.ResolvedJavaMethod; public class HotSpotClassInitializationTest extends HotSpotGraalCompilerTest { static HotSpotClassInitializationTest instance; static class InvokeStatic { static { instance.test(InvokeStatic.class, "m"); } static boolean m() { double value = 123; doOtherWork(value); return GraalDirectives.inCompiledCode(); } static double doOtherWork(double value) { return value; } static int field; } static class GetStatic { static class Inner { static int N = 5000; static { instance.test(GetStatic.class, "m", LoadFieldNode.class); } } static { @SuppressWarnings("unused") int n = Inner.N; } @SuppressWarnings("unused") static boolean m() { double value = 123 * Inner.N; return GraalDirectives.inCompiledCode(); } static double field; } static class NewInstance { static { instance.test(NewInstance.class, "m", NewInstanceNode.class); } @SuppressWarnings("unused") static boolean m() { Object o = new NewInstance(); return GraalDirectives.inCompiledCode(); } static double field; } @Before public void checkAssumptions() { // cannot be BeforeClass because we need a runtime and BeforeClass must be static Assume.assumeTrue("init_thread field must be visible", runtime().getVMConfig().instanceKlassInitThreadOffset != -1); } @SafeVarargs final void test(Class testClass, String methodName, Class... nodeTypes) { ResolvedJavaMethod method = getResolvedJavaMethod(testClass, methodName); StructuredGraph graph = parseProfiled(method, StructuredGraph.AllowAssumptions.NO); for (DeoptimizeNode d : graph.getNodes().filter(DeoptimizeNode.class)) { assertNotEquals("No unresolved deopts expected", d.getReason(), DeoptimizationReason.Unresolved); } assertTrue("A dynamic check should have been emitted", graph.getNodes().filter(KlassBeingInitializedCheckNode.class).count() == 1); // Ensure that all expected nodes exist. for (Class nodeType : nodeTypes) { assertTrue("expected node of type " + nodeType, graph.getNodes().filter(nodeType).count() == 1); } // Ensure that execution remains in the compiled code to the return point InstalledCode code = instance.getCode(method, graph); try { boolean result = (boolean) code.executeVarargs(); Assert.assertEquals("should have completed in compiled code", result, true); } catch (InvalidInstalledCodeException e) { e.printStackTrace(); } } @Test public void testInvokeStatic() { GraalDirectives.inCompiledCode(); instance = this; InvokeStatic.field = 0; instance = null; } @Test public void testGetStatic() { GraalDirectives.inCompiledCode(); instance = this; GetStatic.field = 0; instance = null; } @Test public void testNewInstance() { GraalDirectives.inCompiledCode(); instance = this; NewInstance.field = 0; instance = null; } }