< prev index next >

src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/DefaultJavaLoweringProvider.java

Print this page

        

@@ -46,10 +46,11 @@
 import org.graalvm.compiler.api.directives.GraalDirectives;
 import org.graalvm.compiler.api.replacements.Snippet;
 import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
 import org.graalvm.compiler.core.common.LIRKind;
 import org.graalvm.compiler.core.common.spi.ForeignCallsProvider;
+import org.graalvm.compiler.core.common.type.AbstractObjectStamp;
 import org.graalvm.compiler.core.common.type.IntegerStamp;
 import org.graalvm.compiler.core.common.type.ObjectStamp;
 import org.graalvm.compiler.core.common.type.Stamp;
 import org.graalvm.compiler.core.common.type.StampFactory;
 import org.graalvm.compiler.core.common.type.TypeReference;

@@ -137,10 +138,11 @@
 import org.graalvm.compiler.options.OptionValues;
 import org.graalvm.compiler.phases.util.Providers;
 import org.graalvm.compiler.replacements.SnippetLowerableMemoryNode.SnippetLowering;
 import org.graalvm.compiler.replacements.nodes.BinaryMathIntrinsicNode;
 import org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode;
+import org.graalvm.compiler.word.WordTypes;
 import jdk.internal.vm.compiler.word.LocationIdentity;
 
 import jdk.vm.ci.code.CodeUtil;
 import jdk.vm.ci.code.MemoryBarriers;
 import jdk.vm.ci.code.TargetDescription;

@@ -162,20 +164,22 @@
     protected final MetaAccessProvider metaAccess;
     protected final ForeignCallsProvider foreignCalls;
     protected final TargetDescription target;
     private final boolean useCompressedOops;
     private final ResolvedJavaType objectArrayType;
+    private final WordTypes wordTypes;
 
     private BoxingSnippets.Templates boxingSnippets;
     private ConstantStringIndexOfSnippets.Templates indexOfSnippets;
 
     public DefaultJavaLoweringProvider(MetaAccessProvider metaAccess, ForeignCallsProvider foreignCalls, TargetDescription target, boolean useCompressedOops) {
         this.metaAccess = metaAccess;
         this.foreignCalls = foreignCalls;
         this.target = target;
         this.useCompressedOops = useCompressedOops;
         this.objectArrayType = metaAccess.lookupJavaType(Object[].class);
+        this.wordTypes = new WordTypes(metaAccess, target.wordJavaKind);
     }
 
     public void initialize(OptionValues options, Iterable<DebugHandlersFactory> factories, SnippetCounter.Group.Factory factory, Providers providers, SnippetReflectionProvider snippetReflection) {
         boxingSnippets = new BoxingSnippets.Templates(options, factories, factory, providers, snippetReflection, target);
         indexOfSnippets = new ConstantStringIndexOfSnippets.Templates(options, factories, providers, snippetReflection, target);

@@ -511,11 +515,11 @@
             }
         }
 
         AddressNode address = createArrayIndexAddress(graph, array, elementKind, storeIndexed.index(), boundsCheck);
         WriteNode memoryWrite = graph.add(new WriteNode(address, NamedLocationIdentity.getArrayLocation(elementKind), implicitStoreConvert(graph, elementKind, value),
-                        arrayStoreBarrierType(storeIndexed.elementKind())));
+                        arrayStoreBarrierType(array, storeIndexed.elementKind())));
         memoryWrite.setGuard(boundsCheck);
         if (condition != null) {
             tool.createGuard(storeIndexed, condition, DeoptimizationReason.ArrayStoreException, DeoptimizationAction.InvalidateReprofile);
         }
         memoryWrite.setStateAfter(storeIndexed.stateAfter());

@@ -786,15 +790,15 @@
                             if (virtual instanceof VirtualInstanceNode) {
                                 ResolvedJavaField field = ((VirtualInstanceNode) virtual).field(i);
                                 long offset = fieldOffset(field);
                                 if (offset >= 0) {
                                     address = createOffsetAddress(graph, newObject, offset);
-                                    barrierType = fieldInitializationBarrier(entryKind);
+                                    barrierType = fieldInitializationBarrier(field);
                                 }
                             } else {
                                 address = createOffsetAddress(graph, newObject, metaAccess.getArrayBaseOffset(entryKind) + i * metaAccess.getArrayIndexScale(entryKind));
-                                barrierType = arrayInitializationBarrier(entryKind);
+                                barrierType = arrayInitializationBarrier(newObject, entryKind);
                             }
                             if (address != null) {
                                 WriteNode write = new WriteNode(address, LocationIdentity.init(), implicitStoreConvert(graph, entryKind, value), barrierType);
                                 graph.addAfterFixed(newObject, graph.add(write));
                             }

@@ -820,14 +824,14 @@
                                 AddressNode address;
                                 BarrierType barrierType;
                                 if (virtual instanceof VirtualInstanceNode) {
                                     VirtualInstanceNode virtualInstance = (VirtualInstanceNode) virtual;
                                     address = createFieldAddress(graph, newObject, virtualInstance.field(i));
-                                    barrierType = BarrierType.IMPRECISE;
+                                    barrierType = fieldStoreBarrierType(virtualInstance.field(i));
                                 } else {
                                     address = createArrayAddress(graph, newObject, virtual.entryKind(i), ConstantNode.forInt(i, graph));
-                                    barrierType = BarrierType.PRECISE;
+                                    barrierType = arrayStoreBarrierType(newObject, virtual.entryKind(i));
                                 }
                                 if (address != null) {
                                     WriteNode write = new WriteNode(address, LocationIdentity.init(), implicitStoreConvert(graph, JavaKind.Object, allocValue), barrierType);
                                     graph.addBeforeFixed(commit, graph.add(write));
                                 }

@@ -937,29 +941,54 @@
     protected BarrierType fieldLoadBarrierType(ResolvedJavaField field) {
         return BarrierType.NONE;
     }
 
     protected BarrierType fieldStoreBarrierType(ResolvedJavaField field) {
-        if (field.getJavaKind() == JavaKind.Object) {
-            return BarrierType.IMPRECISE;
+        JavaKind fieldKind = wordTypes.asKind(field.getType());
+        if (fieldKind == JavaKind.Object) {
+            return BarrierType.FIELD;
         }
         return BarrierType.NONE;
     }
 
-    protected BarrierType arrayStoreBarrierType(JavaKind elementKind) {
-        if (elementKind == JavaKind.Object) {
-            return BarrierType.PRECISE;
+    /**
+     * If the given value is indeed an array, and its elements are of a word type, return the
+     * correct word kind; in all other cases, return the defaultElementKind. This is needed for
+     * determining the correct write barrier type.
+     *
+     * @param array a value that is expected to have an array stamp
+     * @param defaultElementKind the array's element kind without taking word types into account
+     * @return the element kind of the array taking word types into account
+     */
+    protected JavaKind maybeWordArrayElementKind(ValueNode array, JavaKind defaultElementKind) {
+        JavaKind elementKind = defaultElementKind;
+        Stamp arrayStamp = array.stamp(NodeView.DEFAULT);
+        if (arrayStamp instanceof AbstractObjectStamp && arrayStamp.hasValues()) {
+            ResolvedJavaType arrayType = ((AbstractObjectStamp) arrayStamp).type();
+            if (arrayType != null && arrayType.getComponentType() != null) {
+                elementKind = wordTypes.asKind(arrayType.getComponentType());
+            }
+        }
+        return elementKind;
+    }
+
+    protected BarrierType arrayStoreBarrierType(ValueNode array, JavaKind elementKind) {
+        JavaKind kind = maybeWordArrayElementKind(array, elementKind);
+        if (kind == JavaKind.Object) {
+            return BarrierType.ARRAY;
         }
         return BarrierType.NONE;
     }
 
-    public BarrierType fieldInitializationBarrier(JavaKind entryKind) {
-        return entryKind == JavaKind.Object ? BarrierType.IMPRECISE : BarrierType.NONE;
+    public BarrierType fieldInitializationBarrier(ResolvedJavaField field) {
+        JavaKind fieldKind = wordTypes.asKind(field.getType());
+        return fieldKind == JavaKind.Object ? BarrierType.FIELD : BarrierType.NONE;
     }
 
-    public BarrierType arrayInitializationBarrier(JavaKind entryKind) {
-        return entryKind == JavaKind.Object ? BarrierType.PRECISE : BarrierType.NONE;
+    public BarrierType arrayInitializationBarrier(ValueNode array, JavaKind entryKind) {
+        JavaKind kind = maybeWordArrayElementKind(array, entryKind);
+        return kind == JavaKind.Object ? BarrierType.ARRAY : BarrierType.NONE;
     }
 
     private BarrierType unsafeStoreBarrierType(RawStoreNode store) {
         if (!store.needsBarrier()) {
             return BarrierType.NONE;

@@ -970,14 +999,18 @@
     private BarrierType guessStoreBarrierType(ValueNode object, ValueNode value) {
         if (value.getStackKind() == JavaKind.Object && object.getStackKind() == JavaKind.Object) {
             ResolvedJavaType type = StampTool.typeOrNull(object);
             // Array types must use a precise barrier, so if the type is unknown or is a supertype
             // of Object[] then treat it as an array.
-            if (type == null || type.isArray() || type.isAssignableFrom(objectArrayType)) {
-                return BarrierType.PRECISE;
+            if (type != null && type.isArray()) {
+                return arrayStoreBarrierType(object, JavaKind.Object);
+            } else if (type != null && wordTypes.isWord(type)) {
+                return BarrierType.NONE;
+            } else if (type == null || type.isAssignableFrom(objectArrayType)) {
+                return BarrierType.UNKNOWN;
             } else {
-                return BarrierType.IMPRECISE;
+                return BarrierType.FIELD;
             }
         }
         return BarrierType.NONE;
     }
 
< prev index next >