src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/UnsafeAccessNode.java
changeset 58877 aec7bf35d6f5
parent 52910 583fd71c47d6
equal deleted inserted replaced
58876:1a8d65e71a66 58877:aec7bf35d6f5
     1 /*
     1 /*
     2  * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     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
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.
     7  * published by the Free Software Foundation.
    25 package org.graalvm.compiler.nodes.extended;
    25 package org.graalvm.compiler.nodes.extended;
    26 
    26 
    27 import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_2;
    27 import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_2;
    28 import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1;
    28 import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1;
    29 
    29 
       
    30 import java.nio.ByteOrder;
       
    31 
    30 import org.graalvm.compiler.core.common.type.Stamp;
    32 import org.graalvm.compiler.core.common.type.Stamp;
    31 import org.graalvm.compiler.graph.Node;
    33 import org.graalvm.compiler.graph.Node;
    32 import org.graalvm.compiler.graph.NodeClass;
    34 import org.graalvm.compiler.graph.NodeClass;
    33 import org.graalvm.compiler.graph.spi.Canonicalizable;
    35 import org.graalvm.compiler.graph.spi.Canonicalizable;
    34 import org.graalvm.compiler.graph.spi.CanonicalizerTool;
    36 import org.graalvm.compiler.graph.spi.CanonicalizerTool;
    38 import org.graalvm.compiler.nodes.ValueNode;
    40 import org.graalvm.compiler.nodes.ValueNode;
    39 import org.graalvm.compiler.nodes.type.StampTool;
    41 import org.graalvm.compiler.nodes.type.StampTool;
    40 import jdk.internal.vm.compiler.word.LocationIdentity;
    42 import jdk.internal.vm.compiler.word.LocationIdentity;
    41 
    43 
    42 import jdk.vm.ci.meta.Assumptions;
    44 import jdk.vm.ci.meta.Assumptions;
       
    45 import jdk.vm.ci.meta.ConstantReflectionProvider;
       
    46 import jdk.vm.ci.meta.JavaConstant;
    43 import jdk.vm.ci.meta.JavaKind;
    47 import jdk.vm.ci.meta.JavaKind;
    44 import jdk.vm.ci.meta.ResolvedJavaField;
    48 import jdk.vm.ci.meta.ResolvedJavaField;
    45 import jdk.vm.ci.meta.ResolvedJavaType;
    49 import jdk.vm.ci.meta.ResolvedJavaType;
    46 
    50 
    47 @NodeInfo(cycles = CYCLES_2, size = SIZE_1)
    51 @NodeInfo(cycles = CYCLES_2, size = SIZE_1)
    93                 long constantOffset = offset().asJavaConstant().asLong();
    97                 long constantOffset = offset().asJavaConstant().asLong();
    94 
    98 
    95                 // Try to canonicalize to a field access.
    99                 // Try to canonicalize to a field access.
    96                 ResolvedJavaType receiverType = StampTool.typeOrNull(object());
   100                 ResolvedJavaType receiverType = StampTool.typeOrNull(object());
    97                 if (receiverType != null) {
   101                 if (receiverType != null) {
    98                     ResolvedJavaField field = receiverType.findInstanceFieldWithOffset(constantOffset, accessKind());
   102                     ResolvedJavaField field = getStaticFieldUnsafeAccess(tool.getConstantReflection());
    99                     // No need for checking that the receiver is non-null. The field access includes
   103                     if (field == null) {
   100                     // the null check and if a field is found, the offset is so small that this is
   104                         field = receiverType.findInstanceFieldWithOffset(constantOffset, accessKind());
   101                     // never a valid access of an arbitrary address.
   105                     }
       
   106 
       
   107                     // No need for checking that the receiver is non-null. The field access
       
   108                     // includes the null check and if a field is found, the offset is so small that
       
   109                     // this is never a valid access of an arbitrary address.
   102                     if (field != null && field.getJavaKind() == this.accessKind()) {
   110                     if (field != null && field.getJavaKind() == this.accessKind()) {
   103                         assert !graph().isAfterFloatingReadPhase() : "cannot add more precise memory location after floating read phase";
   111                         assert !graph().isAfterFloatingReadPhase() : "cannot add more precise memory location after floating read phase";
   104                         // Unsafe accesses never have volatile semantics.
   112                         // Unsafe accesses never have volatile semantics.
   105                         // Memory barriers are placed around such an unsafe access at construction
   113                         // Memory barriers are placed around such an unsafe access at construction
   106                         // time if necessary, unlike AccessFieldNodes which encapsulate their
   114                         // time if necessary, unlike AccessFieldNodes which encapsulate their
   126     }
   134     }
   127 
   135 
   128     protected abstract ValueNode cloneAsFieldAccess(Assumptions assumptions, ResolvedJavaField field, boolean volatileAccess);
   136     protected abstract ValueNode cloneAsFieldAccess(Assumptions assumptions, ResolvedJavaField field, boolean volatileAccess);
   129 
   137 
   130     protected abstract ValueNode cloneAsArrayAccess(ValueNode location, LocationIdentity identity);
   138     protected abstract ValueNode cloneAsArrayAccess(ValueNode location, LocationIdentity identity);
       
   139 
       
   140     /**
       
   141      * In this method we check if the unsafe access is to a static field. This is the case when
       
   142      * {@code object} is a constant of type {@link Class} (static field's declaring class) and
       
   143      * {@code offset} is a constant (HotSpot-specific field offset from the declaring class).
       
   144      *
       
   145      * @return the static field, if any, that this node is reading
       
   146      */
       
   147     private ResolvedJavaField getStaticFieldUnsafeAccess(ConstantReflectionProvider constantReflection) {
       
   148         if (!object().isJavaConstant() || !offset().isJavaConstant() ||
       
   149                         object().isNullConstant() || offset().isNullConstant()) {
       
   150             return null;
       
   151         }
       
   152         JavaConstant objectConstant = object().asJavaConstant();
       
   153         JavaConstant offsetConstant = offset().asJavaConstant();
       
   154         assert objectConstant != null && offsetConstant != null : "Verified by the check at the beginning.";
       
   155         ResolvedJavaType staticReceiverType = constantReflection.asJavaType(objectConstant);
       
   156         if (staticReceiverType == null) {
       
   157             // object is not of type Class so it is not a static field
       
   158             return null;
       
   159         }
       
   160         return findStaticFieldWithOffset(staticReceiverType, offsetConstant.asLong(), accessKind);
       
   161     }
       
   162 
       
   163     private static ResolvedJavaField findStaticFieldWithOffset(ResolvedJavaType type, long offset, JavaKind expectedEntryKind) {
       
   164         try {
       
   165             ResolvedJavaField[] declaredFields = type.getStaticFields();
       
   166             return findFieldWithOffset(offset, expectedEntryKind, declaredFields);
       
   167         } catch (UnsupportedOperationException e) {
       
   168             return null;
       
   169         }
       
   170     }
       
   171 
       
   172     /**
       
   173      * NOTE GR-18873: this is a copy-paste implementation derived from
       
   174      * {@code jdk.vm.ci.hotspot.HotSpotResolvedObjectTypeImpl#findStaticFieldWithOffset}.
       
   175      */
       
   176     private static ResolvedJavaField findFieldWithOffset(long offset, JavaKind expectedEntryKind, ResolvedJavaField[] declaredFields) {
       
   177         for (ResolvedJavaField field : declaredFields) {
       
   178             long resolvedFieldOffset = field.getOffset();
       
   179             if (ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN &&
       
   180                             expectedEntryKind.isPrimitive() &&
       
   181                             !expectedEntryKind.equals(JavaKind.Void) &&
       
   182                             field.getJavaKind().isPrimitive()) {
       
   183                 resolvedFieldOffset += field.getJavaKind().getByteCount() -
       
   184                                 Math.min(field.getJavaKind().getByteCount(), 4 + expectedEntryKind.getByteCount());
       
   185             }
       
   186             if (resolvedFieldOffset == offset) {
       
   187                 return field;
       
   188             }
       
   189         }
       
   190         return null;
       
   191     }
       
   192 
   131 }
   193 }