1 /*
   2  * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 
  25 package org.graalvm.compiler.hotspot.test;
  26 
  27 import static org.junit.Assert.assertNotEquals;
  28 
  29 import org.graalvm.compiler.api.directives.GraalDirectives;
  30 import org.graalvm.compiler.graph.Node;
  31 import org.graalvm.compiler.hotspot.nodes.KlassBeingInitializedCheckNode;
  32 import org.graalvm.compiler.nodes.DeoptimizeNode;
  33 import org.graalvm.compiler.nodes.StructuredGraph;
  34 import org.graalvm.compiler.nodes.java.LoadFieldNode;
  35 import org.graalvm.compiler.nodes.java.NewInstanceNode;
  36 import org.junit.Assert;
  37 import org.junit.Assume;
  38 import org.junit.Before;
  39 import org.junit.Test;
  40 
  41 import jdk.vm.ci.code.InstalledCode;
  42 import jdk.vm.ci.code.InvalidInstalledCodeException;
  43 import jdk.vm.ci.meta.DeoptimizationReason;
  44 import jdk.vm.ci.meta.ResolvedJavaMethod;
  45 
  46 public class HotSpotClassInitializationTest extends HotSpotGraalCompilerTest {
  47 
  48     static HotSpotClassInitializationTest instance;
  49 
  50     static class InvokeStatic {
  51         static {
  52             instance.test(InvokeStatic.class, "m");
  53         }
  54 
  55         static boolean m() {
  56             double value = 123;
  57             doOtherWork(value);
  58             return GraalDirectives.inCompiledCode();
  59         }
  60 
  61         static double doOtherWork(double value) {
  62             return value;
  63         }
  64 
  65         static int field;
  66     }
  67 
  68     static class GetStatic {
  69         static class Inner {
  70             static int N = 5000;
  71 
  72             static {
  73                 instance.test(GetStatic.class, "m", LoadFieldNode.class);
  74             }
  75         }
  76 
  77         static {
  78             @SuppressWarnings("unused")
  79             int n = Inner.N;
  80         }
  81 
  82         @SuppressWarnings("unused")
  83         static boolean m() {
  84             double value = 123 * Inner.N;
  85             return GraalDirectives.inCompiledCode();
  86         }
  87 
  88         static double field;
  89     }
  90 
  91     static class NewInstance {
  92         static {
  93             instance.test(NewInstance.class, "m", NewInstanceNode.class);
  94         }
  95 
  96         @SuppressWarnings("unused")
  97         static boolean m() {
  98             Object o = new NewInstance();
  99             return GraalDirectives.inCompiledCode();
 100         }
 101 
 102         static double field;
 103     }
 104 
 105     @Before
 106     public void checkAssumptions() {
 107         // cannot be BeforeClass because we need a runtime and BeforeClass must be static
 108         Assume.assumeTrue("init_thread field must be visible", runtime().getVMConfig().instanceKlassInitThreadOffset != -1);
 109     }
 110 
 111     @SafeVarargs
 112     final void test(Class<?> testClass, String methodName, Class<? extends Node>... nodeTypes) {
 113         ResolvedJavaMethod method = getResolvedJavaMethod(testClass, methodName);
 114         StructuredGraph graph = parseProfiled(method, StructuredGraph.AllowAssumptions.NO);
 115         for (DeoptimizeNode d : graph.getNodes().filter(DeoptimizeNode.class)) {
 116             assertNotEquals("No unresolved deopts expected", d.getReason(), DeoptimizationReason.Unresolved);
 117         }
 118         assertTrue("A dynamic check should have been emitted", graph.getNodes().filter(KlassBeingInitializedCheckNode.class).count() == 1);
 119 
 120         // Ensure that all expected nodes exist.
 121         for (Class<? extends Node> nodeType : nodeTypes) {
 122             assertTrue("expected node of type " + nodeType, graph.getNodes().filter(nodeType).count() == 1);
 123         }
 124 
 125         // Ensure that execution remains in the compiled code to the return point
 126         InstalledCode code = instance.getCode(method, graph);
 127         try {
 128             boolean result = (boolean) code.executeVarargs();
 129             Assert.assertEquals("should have completed in compiled code", result, true);
 130         } catch (InvalidInstalledCodeException e) {
 131             e.printStackTrace();
 132         }
 133     }
 134 
 135     @Test
 136     public void testInvokeStatic() {
 137         GraalDirectives.inCompiledCode();
 138         instance = this;
 139         InvokeStatic.field = 0;
 140         instance = null;
 141     }
 142 
 143     @Test
 144     public void testGetStatic() {
 145         GraalDirectives.inCompiledCode();
 146         instance = this;
 147         GetStatic.field = 0;
 148         instance = null;
 149     }
 150 
 151     @Test
 152     public void testNewInstance() {
 153         GraalDirectives.inCompiledCode();
 154         instance = this;
 155         NewInstance.field = 0;
 156         instance = null;
 157     }
 158 
 159 }