src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/LateMembarInsertionTest.java
changeset 58877 aec7bf35d6f5
equal deleted inserted replaced
58876:1a8d65e71a66 58877:aec7bf35d6f5
       
     1 /*
       
     2  * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
       
     3  * Copyright (c) 2019, Red Hat Inc. All rights reserved.
       
     4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     5  *
       
     6  * This code is free software; you can redistribute it and/or modify it
       
     7  * under the terms of the GNU General Public License version 2 only, as
       
     8  * published by the Free Software Foundation.
       
     9  *
       
    10  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    13  * version 2 for more details (a copy is included in the LICENSE file that
       
    14  * accompanied this code).
       
    15  *
       
    16  * You should have received a copy of the GNU General Public License version
       
    17  * 2 along with this work; if not, write to the Free Software Foundation,
       
    18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    19  *
       
    20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    21  * or visit www.oracle.com if you need additional information or have any
       
    22  * questions.
       
    23  */
       
    24 
       
    25 
       
    26 
       
    27 package org.graalvm.compiler.core.test;
       
    28 
       
    29 import jdk.vm.ci.meta.ConstantReflectionProvider;
       
    30 import jdk.vm.ci.meta.MetaAccessProvider;
       
    31 import jdk.vm.ci.meta.ResolvedJavaType;
       
    32 import jdk.internal.vm.compiler.collections.EconomicMap;
       
    33 import org.graalvm.compiler.core.common.type.Stamp;
       
    34 import org.graalvm.compiler.nodes.ConstantNode;
       
    35 import org.graalvm.compiler.nodes.NodeView;
       
    36 import org.graalvm.compiler.nodes.StructuredGraph;
       
    37 import org.graalvm.compiler.nodes.ValueNode;
       
    38 import org.graalvm.compiler.nodes.cfg.Block;
       
    39 import org.graalvm.compiler.nodes.cfg.ControlFlowGraph;
       
    40 import org.graalvm.compiler.nodes.memory.FixedAccessNode;
       
    41 import org.graalvm.compiler.nodes.memory.MemoryAccess;
       
    42 import org.graalvm.compiler.nodes.memory.ReadNode;
       
    43 import org.graalvm.compiler.nodes.memory.address.AddressNode;
       
    44 import org.graalvm.compiler.options.OptionKey;
       
    45 import org.graalvm.compiler.options.OptionValues;
       
    46 import org.junit.Assert;
       
    47 import org.junit.Test;
       
    48 
       
    49 import java.util.Arrays;
       
    50 import java.util.List;
       
    51 import java.util.stream.Collectors;
       
    52 
       
    53 import static org.graalvm.compiler.core.common.GraalOptions.StressTestEarlyReads;
       
    54 
       
    55 public class LateMembarInsertionTest extends GraalCompilerTest {
       
    56 
       
    57     private final ResolvedJavaType volatileAccessType = getMetaAccess().lookupJavaType(VolatileAccess.class);
       
    58     private final ResolvedJavaType regularAccessField = getMetaAccess().lookupJavaType(RegularAccess.class);
       
    59     private final ResolvedJavaType volatileAccess2Type = getMetaAccess().lookupJavaType(VolatileAccess2.class);
       
    60 
       
    61     static class VolatileAccess {
       
    62         static volatile int field;
       
    63     }
       
    64 
       
    65     static class VolatileAccess2 {
       
    66         static volatile int field;
       
    67     }
       
    68 
       
    69     static class RegularAccess {
       
    70         static int field;
       
    71     }
       
    72 
       
    73     public static int volatileFieldLoadFieldLoad() {
       
    74         int v1 = VolatileAccess.field;
       
    75         int v2 = RegularAccess.field;
       
    76         return v1 + v2;
       
    77     }
       
    78 
       
    79     @Test
       
    80     public void test01() {
       
    81         List<TypePair> accesses = compile("volatileFieldLoadFieldLoad", stressTestEarlyReads());
       
    82 
       
    83         Assert.assertEquals(accesses.size(), 2);
       
    84         Assert.assertEquals(accesses.get(0).getType(), volatileAccessType);
       
    85         Assert.assertEquals(accesses.get(1).getType(), regularAccessField);
       
    86         Assert.assertTrue(accesses.get(0).isRead());
       
    87         Assert.assertTrue(accesses.get(1).isRead());
       
    88     }
       
    89 
       
    90     public static int volatileFieldLoadVolatileFieldLoad() {
       
    91         int v1 = VolatileAccess.field;
       
    92         int v2 = VolatileAccess2.field;
       
    93         return v1 + v2;
       
    94     }
       
    95 
       
    96     @Test
       
    97     public void test02() {
       
    98         List<TypePair> accesses = compile("volatileFieldLoadVolatileFieldLoad", stressTestEarlyReads());
       
    99 
       
   100         Assert.assertEquals(accesses.size(), 2);
       
   101         Assert.assertEquals(accesses.get(0).getType(), volatileAccessType);
       
   102         Assert.assertEquals(accesses.get(1).getType(), volatileAccess2Type);
       
   103         Assert.assertTrue(accesses.get(0).isRead());
       
   104         Assert.assertTrue(accesses.get(1).isRead());
       
   105     }
       
   106 
       
   107     public static int volatileFieldLoadVolatileFieldStore(int v2) {
       
   108         int v1 = VolatileAccess.field;
       
   109         VolatileAccess2.field = v2;
       
   110         return v1;
       
   111     }
       
   112 
       
   113     @Test
       
   114     public void test03() {
       
   115         List<TypePair> accesses = compile("volatileFieldLoadVolatileFieldStore");
       
   116 
       
   117         Assert.assertEquals(accesses.size(), 2);
       
   118         Assert.assertEquals(accesses.get(0).getType(), volatileAccessType);
       
   119         Assert.assertEquals(accesses.get(1).getType(), volatileAccess2Type);
       
   120         Assert.assertTrue(accesses.get(0).isRead());
       
   121         Assert.assertTrue(accesses.get(1).isWrite());
       
   122     }
       
   123 
       
   124     public static int volatileFieldStoreVolatileFieldLoad(int v2) {
       
   125         VolatileAccess.field = v2;
       
   126         return VolatileAccess2.field;
       
   127     }
       
   128 
       
   129     @Test
       
   130     public void test04() {
       
   131         List<TypePair> accesses = compile("volatileFieldStoreVolatileFieldLoad", stressTestEarlyReads());
       
   132 
       
   133         Assert.assertEquals(accesses.size(), 2);
       
   134         Assert.assertEquals(accesses.get(0).getType(), volatileAccessType);
       
   135         Assert.assertEquals(accesses.get(1).getType(), volatileAccess2Type);
       
   136         Assert.assertTrue(accesses.get(0).isWrite());
       
   137         Assert.assertTrue(accesses.get(1).isRead());
       
   138     }
       
   139 
       
   140     public static int fieldLoadVolatileFieldStore(int v2) {
       
   141         int v1 = RegularAccess.field;
       
   142         VolatileAccess2.field = v2;
       
   143         return v1;
       
   144     }
       
   145 
       
   146     @Test
       
   147     public void test05() {
       
   148         List<TypePair> accesses = compile("fieldLoadVolatileFieldStore");
       
   149 
       
   150         Assert.assertEquals(accesses.size(), 2);
       
   151         Assert.assertEquals(accesses.get(0).getType(), regularAccessField);
       
   152         Assert.assertEquals(accesses.get(1).getType(), volatileAccess2Type);
       
   153         Assert.assertTrue(accesses.get(0).isRead());
       
   154         Assert.assertTrue(accesses.get(1).isWrite());
       
   155     }
       
   156 
       
   157     public static void volatileFieldStoreVolatileFieldStore(int v1, int v2) {
       
   158         VolatileAccess.field = v1;
       
   159         VolatileAccess2.field = v2;
       
   160     }
       
   161 
       
   162     @Test
       
   163     public void test06() {
       
   164         List<TypePair> accesses = compile("volatileFieldStoreVolatileFieldStore");
       
   165 
       
   166         Assert.assertEquals(accesses.size(), 2);
       
   167         Assert.assertEquals(accesses.get(0).getType(), volatileAccessType);
       
   168         Assert.assertEquals(accesses.get(1).getType(), volatileAccess2Type);
       
   169         Assert.assertTrue(accesses.get(0).isWrite());
       
   170         Assert.assertTrue(accesses.get(1).isWrite());
       
   171     }
       
   172 
       
   173     private static OptionValues stressTestEarlyReads() {
       
   174         EconomicMap<OptionKey<?>, Object> overrides = OptionValues.newOptionMap();
       
   175         overrides.put(StressTestEarlyReads, true);
       
   176         return new OptionValues(getInitialOptions(), overrides);
       
   177     }
       
   178 
       
   179     static class TypePair {
       
   180         private boolean isRead;
       
   181         private ResolvedJavaType type;
       
   182 
       
   183         TypePair(boolean isRead, ResolvedJavaType type) {
       
   184             this.isRead = isRead;
       
   185             this.type = type;
       
   186         }
       
   187 
       
   188         public boolean isRead() {
       
   189             return isRead;
       
   190         }
       
   191 
       
   192         public boolean isWrite() {
       
   193             return !isRead;
       
   194         }
       
   195 
       
   196         public ResolvedJavaType getType() {
       
   197             return type;
       
   198         }
       
   199     }
       
   200 
       
   201     private List<TypePair> compile(String test, OptionValues options) {
       
   202         StructuredGraph graph = getFinalGraph(getResolvedJavaMethod(test), options);
       
   203         return getAccesses(graph);
       
   204     }
       
   205 
       
   206     private List<TypePair> getAccesses(StructuredGraph graph) {
       
   207         StructuredGraph.ScheduleResult schedule = graph.getLastSchedule();
       
   208         ControlFlowGraph cfg = schedule.getCFG();
       
   209         Block[] blocks = cfg.getBlocks();
       
   210 
       
   211         return Arrays.stream(blocks).flatMap(b -> schedule.nodesFor(b).stream()).filter(n -> n instanceof MemoryAccess).map(
       
   212                         n -> new TypePair(n instanceof ReadNode, classForAccess((FixedAccessNode) n))).collect(Collectors.toList());
       
   213     }
       
   214 
       
   215     private List<TypePair> compile(String test) {
       
   216         StructuredGraph graph = getFinalGraph(getResolvedJavaMethod(test));
       
   217         return getAccesses(graph);
       
   218     }
       
   219 
       
   220     private ResolvedJavaType classForAccess(FixedAccessNode n) {
       
   221         AddressNode address = n.getAddress();
       
   222         ValueNode base = address.getBase();
       
   223         Stamp stamp = base.stamp(NodeView.DEFAULT);
       
   224         MetaAccessProvider metaAccess = getMetaAccess();
       
   225         ResolvedJavaType javaType = stamp.javaType(metaAccess);
       
   226         if (javaType == metaAccess.lookupJavaType(Class.class) && base instanceof ConstantNode) {
       
   227             ConstantReflectionProvider constantReflection = getConstantReflection();
       
   228             javaType = constantReflection.asJavaType(base.asConstant());
       
   229         }
       
   230         return javaType;
       
   231     }
       
   232 
       
   233 }