1 /* |
1 /* |
2 * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved. |
2 * Copyright (c) 2011, 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. |
41 import java.nio.ByteOrder; |
41 import java.nio.ByteOrder; |
42 import java.util.ArrayList; |
42 import java.util.ArrayList; |
43 import java.util.BitSet; |
43 import java.util.BitSet; |
44 import java.util.List; |
44 import java.util.List; |
45 |
45 |
|
46 import jdk.vm.ci.meta.JavaConstant; |
46 import org.graalvm.compiler.api.directives.GraalDirectives; |
47 import org.graalvm.compiler.api.directives.GraalDirectives; |
47 import org.graalvm.compiler.api.replacements.Snippet; |
48 import org.graalvm.compiler.api.replacements.Snippet; |
48 import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; |
49 import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; |
49 import org.graalvm.compiler.core.common.LIRKind; |
50 import org.graalvm.compiler.core.common.LIRKind; |
50 import org.graalvm.compiler.core.common.spi.ForeignCallsProvider; |
51 import org.graalvm.compiler.core.common.spi.ForeignCallsProvider; |
51 import org.graalvm.compiler.core.common.type.AbstractObjectStamp; |
52 import org.graalvm.compiler.core.common.type.AbstractPointerStamp; |
52 import org.graalvm.compiler.core.common.type.IntegerStamp; |
53 import org.graalvm.compiler.core.common.type.IntegerStamp; |
53 import org.graalvm.compiler.core.common.type.ObjectStamp; |
54 import org.graalvm.compiler.core.common.type.ObjectStamp; |
54 import org.graalvm.compiler.core.common.type.Stamp; |
55 import org.graalvm.compiler.core.common.type.Stamp; |
55 import org.graalvm.compiler.core.common.type.StampFactory; |
56 import org.graalvm.compiler.core.common.type.StampFactory; |
56 import org.graalvm.compiler.core.common.type.TypeReference; |
57 import org.graalvm.compiler.core.common.type.TypeReference; |
59 import org.graalvm.compiler.debug.GraalError; |
60 import org.graalvm.compiler.debug.GraalError; |
60 import org.graalvm.compiler.graph.Node; |
61 import org.graalvm.compiler.graph.Node; |
61 import org.graalvm.compiler.nodeinfo.InputType; |
62 import org.graalvm.compiler.nodeinfo.InputType; |
62 import org.graalvm.compiler.nodes.CompressionNode.CompressionOp; |
63 import org.graalvm.compiler.nodes.CompressionNode.CompressionOp; |
63 import org.graalvm.compiler.nodes.ConstantNode; |
64 import org.graalvm.compiler.nodes.ConstantNode; |
|
65 import org.graalvm.compiler.nodes.EndNode; |
64 import org.graalvm.compiler.nodes.FieldLocationIdentity; |
66 import org.graalvm.compiler.nodes.FieldLocationIdentity; |
65 import org.graalvm.compiler.nodes.FixedNode; |
67 import org.graalvm.compiler.nodes.FixedNode; |
|
68 import org.graalvm.compiler.nodes.FixedWithNextNode; |
|
69 import org.graalvm.compiler.nodes.IfNode; |
66 import org.graalvm.compiler.nodes.LogicNode; |
70 import org.graalvm.compiler.nodes.LogicNode; |
|
71 import org.graalvm.compiler.nodes.MergeNode; |
67 import org.graalvm.compiler.nodes.NamedLocationIdentity; |
72 import org.graalvm.compiler.nodes.NamedLocationIdentity; |
68 import org.graalvm.compiler.nodes.NodeView; |
73 import org.graalvm.compiler.nodes.NodeView; |
|
74 import org.graalvm.compiler.nodes.PhiNode; |
69 import org.graalvm.compiler.nodes.PiNode; |
75 import org.graalvm.compiler.nodes.PiNode; |
70 import org.graalvm.compiler.nodes.StructuredGraph; |
76 import org.graalvm.compiler.nodes.StructuredGraph; |
71 import org.graalvm.compiler.nodes.ValueNode; |
77 import org.graalvm.compiler.nodes.ValueNode; |
|
78 import org.graalvm.compiler.nodes.ValuePhiNode; |
72 import org.graalvm.compiler.nodes.calc.AddNode; |
79 import org.graalvm.compiler.nodes.calc.AddNode; |
73 import org.graalvm.compiler.nodes.calc.ConditionalNode; |
80 import org.graalvm.compiler.nodes.calc.ConditionalNode; |
74 import org.graalvm.compiler.nodes.calc.IntegerBelowNode; |
81 import org.graalvm.compiler.nodes.calc.IntegerBelowNode; |
75 import org.graalvm.compiler.nodes.calc.IntegerConvertNode; |
82 import org.graalvm.compiler.nodes.calc.IntegerConvertNode; |
76 import org.graalvm.compiler.nodes.calc.IntegerEqualsNode; |
83 import org.graalvm.compiler.nodes.calc.IntegerEqualsNode; |
90 import org.graalvm.compiler.nodes.extended.GuardingNode; |
97 import org.graalvm.compiler.nodes.extended.GuardingNode; |
91 import org.graalvm.compiler.nodes.extended.JavaReadNode; |
98 import org.graalvm.compiler.nodes.extended.JavaReadNode; |
92 import org.graalvm.compiler.nodes.extended.JavaWriteNode; |
99 import org.graalvm.compiler.nodes.extended.JavaWriteNode; |
93 import org.graalvm.compiler.nodes.extended.LoadArrayComponentHubNode; |
100 import org.graalvm.compiler.nodes.extended.LoadArrayComponentHubNode; |
94 import org.graalvm.compiler.nodes.extended.LoadHubNode; |
101 import org.graalvm.compiler.nodes.extended.LoadHubNode; |
|
102 import org.graalvm.compiler.nodes.extended.LoadHubOrNullNode; |
95 import org.graalvm.compiler.nodes.extended.MembarNode; |
103 import org.graalvm.compiler.nodes.extended.MembarNode; |
96 import org.graalvm.compiler.nodes.extended.RawLoadNode; |
104 import org.graalvm.compiler.nodes.extended.RawLoadNode; |
97 import org.graalvm.compiler.nodes.extended.RawStoreNode; |
105 import org.graalvm.compiler.nodes.extended.RawStoreNode; |
98 import org.graalvm.compiler.nodes.extended.UnboxNode; |
106 import org.graalvm.compiler.nodes.extended.UnboxNode; |
99 import org.graalvm.compiler.nodes.extended.UnsafeMemoryLoadNode; |
107 import org.graalvm.compiler.nodes.extended.UnsafeMemoryLoadNode; |
138 import org.graalvm.compiler.options.OptionValues; |
146 import org.graalvm.compiler.options.OptionValues; |
139 import org.graalvm.compiler.phases.util.Providers; |
147 import org.graalvm.compiler.phases.util.Providers; |
140 import org.graalvm.compiler.replacements.SnippetLowerableMemoryNode.SnippetLowering; |
148 import org.graalvm.compiler.replacements.SnippetLowerableMemoryNode.SnippetLowering; |
141 import org.graalvm.compiler.replacements.nodes.BinaryMathIntrinsicNode; |
149 import org.graalvm.compiler.replacements.nodes.BinaryMathIntrinsicNode; |
142 import org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode; |
150 import org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode; |
143 import org.graalvm.compiler.word.WordTypes; |
|
144 import jdk.internal.vm.compiler.word.LocationIdentity; |
151 import jdk.internal.vm.compiler.word.LocationIdentity; |
145 |
152 |
146 import jdk.vm.ci.code.CodeUtil; |
153 import jdk.vm.ci.code.CodeUtil; |
147 import jdk.vm.ci.code.MemoryBarriers; |
154 import jdk.vm.ci.code.MemoryBarriers; |
148 import jdk.vm.ci.code.TargetDescription; |
155 import jdk.vm.ci.code.TargetDescription; |
164 protected final MetaAccessProvider metaAccess; |
171 protected final MetaAccessProvider metaAccess; |
165 protected final ForeignCallsProvider foreignCalls; |
172 protected final ForeignCallsProvider foreignCalls; |
166 protected final TargetDescription target; |
173 protected final TargetDescription target; |
167 private final boolean useCompressedOops; |
174 private final boolean useCompressedOops; |
168 private final ResolvedJavaType objectArrayType; |
175 private final ResolvedJavaType objectArrayType; |
169 private final WordTypes wordTypes; |
|
170 |
176 |
171 private BoxingSnippets.Templates boxingSnippets; |
177 private BoxingSnippets.Templates boxingSnippets; |
172 private ConstantStringIndexOfSnippets.Templates indexOfSnippets; |
178 private ConstantStringIndexOfSnippets.Templates indexOfSnippets; |
173 |
179 |
174 public DefaultJavaLoweringProvider(MetaAccessProvider metaAccess, ForeignCallsProvider foreignCalls, TargetDescription target, boolean useCompressedOops) { |
180 public DefaultJavaLoweringProvider(MetaAccessProvider metaAccess, ForeignCallsProvider foreignCalls, TargetDescription target, boolean useCompressedOops) { |
175 this.metaAccess = metaAccess; |
181 this.metaAccess = metaAccess; |
176 this.foreignCalls = foreignCalls; |
182 this.foreignCalls = foreignCalls; |
177 this.target = target; |
183 this.target = target; |
178 this.useCompressedOops = useCompressedOops; |
184 this.useCompressedOops = useCompressedOops; |
179 this.objectArrayType = metaAccess.lookupJavaType(Object[].class); |
185 this.objectArrayType = metaAccess.lookupJavaType(Object[].class); |
180 this.wordTypes = new WordTypes(metaAccess, target.wordJavaKind); |
|
181 } |
186 } |
182 |
187 |
183 public void initialize(OptionValues options, Iterable<DebugHandlersFactory> factories, SnippetCounter.Group.Factory factory, Providers providers, SnippetReflectionProvider snippetReflection) { |
188 public void initialize(OptionValues options, Iterable<DebugHandlersFactory> factories, SnippetCounter.Group.Factory factory, Providers providers, SnippetReflectionProvider snippetReflection) { |
184 boxingSnippets = new BoxingSnippets.Templates(options, factories, factory, providers, snippetReflection, target); |
189 boxingSnippets = new BoxingSnippets.Templates(options, factories, factory, providers, snippetReflection, target); |
185 indexOfSnippets = new ConstantStringIndexOfSnippets.Templates(options, factories, providers, snippetReflection, target); |
190 indexOfSnippets = new ConstantStringIndexOfSnippets.Templates(options, factories, providers, snippetReflection, target); |
212 lowerIndexAddressNode((IndexAddressNode) n); |
217 lowerIndexAddressNode((IndexAddressNode) n); |
213 } else if (n instanceof ArrayLengthNode) { |
218 } else if (n instanceof ArrayLengthNode) { |
214 lowerArrayLengthNode((ArrayLengthNode) n, tool); |
219 lowerArrayLengthNode((ArrayLengthNode) n, tool); |
215 } else if (n instanceof LoadHubNode) { |
220 } else if (n instanceof LoadHubNode) { |
216 lowerLoadHubNode((LoadHubNode) n, tool); |
221 lowerLoadHubNode((LoadHubNode) n, tool); |
|
222 } else if (n instanceof LoadHubOrNullNode) { |
|
223 lowerLoadHubOrNullNode((LoadHubOrNullNode) n, tool); |
217 } else if (n instanceof LoadArrayComponentHubNode) { |
224 } else if (n instanceof LoadArrayComponentHubNode) { |
218 lowerLoadArrayComponentHubNode((LoadArrayComponentHubNode) n); |
225 lowerLoadArrayComponentHubNode((LoadArrayComponentHubNode) n); |
219 } else if (n instanceof MonitorEnterNode) { |
226 } else if (n instanceof MonitorEnterNode) { |
220 lowerMonitorEnterNode((MonitorEnterNode) n, tool, graph); |
227 lowerMonitorEnterNode((MonitorEnterNode) n, tool, graph); |
221 } else if (n instanceof UnsafeCompareAndSwapNode) { |
228 } else if (n instanceof UnsafeCompareAndSwapNode) { |
434 ValueNode positiveIndex = graph.maybeAddOrUnique(PiNode.create(index, POSITIVE_ARRAY_INDEX_STAMP, boundsCheck != null ? boundsCheck.asNode() : null)); |
441 ValueNode positiveIndex = graph.maybeAddOrUnique(PiNode.create(index, POSITIVE_ARRAY_INDEX_STAMP, boundsCheck != null ? boundsCheck.asNode() : null)); |
435 return createArrayAddress(graph, array, elementKind, positiveIndex); |
442 return createArrayAddress(graph, array, elementKind, positiveIndex); |
436 } |
443 } |
437 |
444 |
438 public AddressNode createArrayAddress(StructuredGraph graph, ValueNode array, JavaKind elementKind, ValueNode index) { |
445 public AddressNode createArrayAddress(StructuredGraph graph, ValueNode array, JavaKind elementKind, ValueNode index) { |
|
446 return createArrayAddress(graph, array, elementKind, elementKind, index); |
|
447 } |
|
448 |
|
449 public AddressNode createArrayAddress(StructuredGraph graph, ValueNode array, JavaKind arrayKind, JavaKind elementKind, ValueNode index) { |
439 ValueNode wordIndex; |
450 ValueNode wordIndex; |
440 if (target.wordSize > 4) { |
451 if (target.wordSize > 4) { |
441 wordIndex = graph.unique(new SignExtendNode(index, target.wordSize * 8)); |
452 wordIndex = graph.unique(new SignExtendNode(index, target.wordSize * 8)); |
442 } else { |
453 } else { |
443 assert target.wordSize == 4 : "unsupported word size"; |
454 assert target.wordSize == 4 : "unsupported word size"; |
445 } |
456 } |
446 |
457 |
447 int shift = CodeUtil.log2(metaAccess.getArrayIndexScale(elementKind)); |
458 int shift = CodeUtil.log2(metaAccess.getArrayIndexScale(elementKind)); |
448 ValueNode scaledIndex = graph.unique(new LeftShiftNode(wordIndex, ConstantNode.forInt(shift, graph))); |
459 ValueNode scaledIndex = graph.unique(new LeftShiftNode(wordIndex, ConstantNode.forInt(shift, graph))); |
449 |
460 |
450 int base = metaAccess.getArrayBaseOffset(elementKind); |
461 int base = metaAccess.getArrayBaseOffset(arrayKind); |
451 ValueNode offset = graph.unique(new AddNode(scaledIndex, ConstantNode.forIntegerKind(target.wordJavaKind, base, graph))); |
462 ValueNode offset = graph.unique(new AddNode(scaledIndex, ConstantNode.forIntegerKind(target.wordJavaKind, base, graph))); |
452 |
463 |
453 return graph.unique(new OffsetAddressNode(array, offset)); |
464 return graph.unique(new OffsetAddressNode(array, offset)); |
454 } |
465 } |
455 |
466 |
456 protected void lowerIndexAddressNode(IndexAddressNode indexAddress) { |
467 protected void lowerIndexAddressNode(IndexAddressNode indexAddress) { |
457 AddressNode lowered = createArrayAddress(indexAddress.graph(), indexAddress.getArray(), indexAddress.getElementKind(), indexAddress.getIndex()); |
468 AddressNode lowered = createArrayAddress(indexAddress.graph(), indexAddress.getArray(), indexAddress.getArrayKind(), indexAddress.getElementKind(), indexAddress.getIndex()); |
458 indexAddress.replaceAndDelete(lowered); |
469 indexAddress.replaceAndDelete(lowered); |
459 } |
470 } |
460 |
471 |
461 protected void lowerLoadIndexedNode(LoadIndexedNode loadIndexed, LoweringTool tool) { |
472 protected void lowerLoadIndexedNode(LoadIndexedNode loadIndexed, LoweringTool tool) { |
462 StructuredGraph graph = loadIndexed.graph(); |
473 StructuredGraph graph = loadIndexed.graph(); |
515 } |
526 } |
516 } |
527 } |
517 |
528 |
518 AddressNode address = createArrayIndexAddress(graph, array, elementKind, storeIndexed.index(), boundsCheck); |
529 AddressNode address = createArrayIndexAddress(graph, array, elementKind, storeIndexed.index(), boundsCheck); |
519 WriteNode memoryWrite = graph.add(new WriteNode(address, NamedLocationIdentity.getArrayLocation(elementKind), implicitStoreConvert(graph, elementKind, value), |
530 WriteNode memoryWrite = graph.add(new WriteNode(address, NamedLocationIdentity.getArrayLocation(elementKind), implicitStoreConvert(graph, elementKind, value), |
520 arrayStoreBarrierType(array, storeIndexed.elementKind()))); |
531 arrayStoreBarrierType(storeIndexed.elementKind()))); |
521 memoryWrite.setGuard(boundsCheck); |
532 memoryWrite.setGuard(boundsCheck); |
522 if (condition != null) { |
533 if (condition != null) { |
523 tool.createGuard(storeIndexed, condition, DeoptimizationReason.ArrayStoreException, DeoptimizationAction.InvalidateReprofile); |
534 tool.createGuard(storeIndexed, condition, DeoptimizationReason.ArrayStoreException, DeoptimizationAction.InvalidateReprofile); |
524 } |
535 } |
525 memoryWrite.setStateAfter(storeIndexed.stateAfter()); |
536 memoryWrite.setStateAfter(storeIndexed.stateAfter()); |
554 if (graph.getGuardsStage().allowsFloatingGuards()) { |
565 if (graph.getGuardsStage().allowsFloatingGuards()) { |
555 return; |
566 return; |
556 } |
567 } |
557 ValueNode hub = createReadHub(graph, loadHub.getValue(), tool); |
568 ValueNode hub = createReadHub(graph, loadHub.getValue(), tool); |
558 loadHub.replaceAtUsagesAndDelete(hub); |
569 loadHub.replaceAtUsagesAndDelete(hub); |
|
570 } |
|
571 |
|
572 protected void lowerLoadHubOrNullNode(LoadHubOrNullNode loadHubOrNullNode, LoweringTool tool) { |
|
573 StructuredGraph graph = loadHubOrNullNode.graph(); |
|
574 if (tool.getLoweringStage() != LoweringTool.StandardLoweringStage.LOW_TIER) { |
|
575 return; |
|
576 } |
|
577 if (graph.getGuardsStage().allowsFloatingGuards()) { |
|
578 return; |
|
579 } |
|
580 final FixedWithNextNode predecessor = tool.lastFixedNode(); |
|
581 final ValueNode value = loadHubOrNullNode.getValue(); |
|
582 AbstractPointerStamp stamp = (AbstractPointerStamp) value.stamp(NodeView.DEFAULT); |
|
583 final LogicNode isNull = graph.addOrUniqueWithInputs(IsNullNode.create(value)); |
|
584 final EndNode trueEnd = graph.add(new EndNode()); |
|
585 final EndNode falseEnd = graph.add(new EndNode()); |
|
586 final IfNode ifNode = graph.add(new IfNode(isNull, trueEnd, falseEnd, 0.5)); |
|
587 final MergeNode merge = graph.add(new MergeNode()); |
|
588 merge.addForwardEnd(trueEnd); |
|
589 merge.addForwardEnd(falseEnd); |
|
590 final AbstractPointerStamp hubStamp = (AbstractPointerStamp) loadHubOrNullNode.stamp(NodeView.DEFAULT); |
|
591 ValueNode nullHub = ConstantNode.forConstant(hubStamp.asAlwaysNull(), JavaConstant.NULL_POINTER, tool.getMetaAccess(), graph); |
|
592 final ValueNode nonNullValue = graph.addOrUniqueWithInputs(PiNode.create(value, stamp.asNonNull(), ifNode.falseSuccessor())); |
|
593 ValueNode hub = createReadHub(graph, nonNullValue, tool); |
|
594 ValueNode[] values = new ValueNode[]{nullHub, hub}; |
|
595 final PhiNode hubPhi = graph.unique(new ValuePhiNode(hubStamp, merge, values)); |
|
596 final FixedNode oldNext = predecessor.next(); |
|
597 predecessor.setNext(ifNode); |
|
598 merge.setNext(oldNext); |
|
599 loadHubOrNullNode.replaceAtUsagesAndDelete(hubPhi); |
559 } |
600 } |
560 |
601 |
561 protected void lowerLoadArrayComponentHubNode(LoadArrayComponentHubNode loadHub) { |
602 protected void lowerLoadArrayComponentHubNode(LoadArrayComponentHubNode loadHub) { |
562 StructuredGraph graph = loadHub.graph(); |
603 StructuredGraph graph = loadHub.graph(); |
563 ValueNode hub = createReadArrayComponentHub(graph, loadHub.getValue(), loadHub); |
604 ValueNode hub = createReadArrayComponentHub(graph, loadHub.getValue(), loadHub); |
764 if (virtual instanceof VirtualInstanceNode) { |
805 if (virtual instanceof VirtualInstanceNode) { |
765 newObject = graph.add(createNewInstanceFromVirtual(virtual)); |
806 newObject = graph.add(createNewInstanceFromVirtual(virtual)); |
766 } else { |
807 } else { |
767 newObject = graph.add(createNewArrayFromVirtual(virtual, ConstantNode.forInt(entryCount, graph))); |
808 newObject = graph.add(createNewArrayFromVirtual(virtual, ConstantNode.forInt(entryCount, graph))); |
768 } |
809 } |
|
810 // The final STORE_STORE barrier will be emitted by finishAllocatedObjects |
|
811 newObject.clearEmitMemoryBarrier(); |
769 |
812 |
770 recursiveLowerings.add(newObject); |
813 recursiveLowerings.add(newObject); |
771 graph.addBeforeFixed(commit, newObject); |
814 graph.addBeforeFixed(commit, newObject); |
772 allocations[objIndex] = newObject; |
815 allocations[objIndex] = newObject; |
773 for (int i = 0; i < entryCount; i++) { |
816 for (int i = 0; i < entryCount; i++) { |
790 if (virtual instanceof VirtualInstanceNode) { |
833 if (virtual instanceof VirtualInstanceNode) { |
791 ResolvedJavaField field = ((VirtualInstanceNode) virtual).field(i); |
834 ResolvedJavaField field = ((VirtualInstanceNode) virtual).field(i); |
792 long offset = fieldOffset(field); |
835 long offset = fieldOffset(field); |
793 if (offset >= 0) { |
836 if (offset >= 0) { |
794 address = createOffsetAddress(graph, newObject, offset); |
837 address = createOffsetAddress(graph, newObject, offset); |
795 barrierType = fieldInitializationBarrier(field); |
838 barrierType = fieldInitializationBarrier(entryKind); |
796 } |
839 } |
797 } else { |
840 } else { |
798 address = createOffsetAddress(graph, newObject, metaAccess.getArrayBaseOffset(entryKind) + i * metaAccess.getArrayIndexScale(entryKind)); |
841 address = createOffsetAddress(graph, newObject, metaAccess.getArrayBaseOffset(entryKind) + i * metaAccess.getArrayIndexScale(entryKind)); |
799 barrierType = arrayInitializationBarrier(newObject, entryKind); |
842 barrierType = arrayInitializationBarrier(entryKind); |
800 } |
843 } |
801 if (address != null) { |
844 if (address != null) { |
802 WriteNode write = new WriteNode(address, LocationIdentity.init(), implicitStoreConvert(graph, entryKind, value), barrierType); |
845 WriteNode write = new WriteNode(address, LocationIdentity.init(), implicitStoreConvert(graph, entryKind, value), barrierType); |
803 graph.addAfterFixed(newObject, graph.add(write)); |
846 graph.addAfterFixed(newObject, graph.add(write)); |
804 } |
847 } |
827 VirtualInstanceNode virtualInstance = (VirtualInstanceNode) virtual; |
870 VirtualInstanceNode virtualInstance = (VirtualInstanceNode) virtual; |
828 address = createFieldAddress(graph, newObject, virtualInstance.field(i)); |
871 address = createFieldAddress(graph, newObject, virtualInstance.field(i)); |
829 barrierType = fieldStoreBarrierType(virtualInstance.field(i)); |
872 barrierType = fieldStoreBarrierType(virtualInstance.field(i)); |
830 } else { |
873 } else { |
831 address = createArrayAddress(graph, newObject, virtual.entryKind(i), ConstantNode.forInt(i, graph)); |
874 address = createArrayAddress(graph, newObject, virtual.entryKind(i), ConstantNode.forInt(i, graph)); |
832 barrierType = arrayStoreBarrierType(newObject, virtual.entryKind(i)); |
875 barrierType = arrayStoreBarrierType(virtual.entryKind(i)); |
833 } |
876 } |
834 if (address != null) { |
877 if (address != null) { |
835 WriteNode write = new WriteNode(address, LocationIdentity.init(), implicitStoreConvert(graph, JavaKind.Object, allocValue), barrierType); |
878 WriteNode write = new WriteNode(address, LocationIdentity.init(), implicitStoreConvert(graph, JavaKind.Object, allocValue), barrierType); |
836 graph.addBeforeFixed(commit, graph.add(write)); |
879 graph.addBeforeFixed(commit, graph.add(write)); |
837 } |
880 } |
941 protected BarrierType fieldLoadBarrierType(ResolvedJavaField field) { |
984 protected BarrierType fieldLoadBarrierType(ResolvedJavaField field) { |
942 return BarrierType.NONE; |
985 return BarrierType.NONE; |
943 } |
986 } |
944 |
987 |
945 protected BarrierType fieldStoreBarrierType(ResolvedJavaField field) { |
988 protected BarrierType fieldStoreBarrierType(ResolvedJavaField field) { |
946 JavaKind fieldKind = wordTypes.asKind(field.getType()); |
989 if (getStorageKind(field) == JavaKind.Object) { |
947 if (fieldKind == JavaKind.Object) { |
|
948 return BarrierType.FIELD; |
990 return BarrierType.FIELD; |
949 } |
991 } |
950 return BarrierType.NONE; |
992 return BarrierType.NONE; |
951 } |
993 } |
952 |
994 |
953 /** |
995 protected BarrierType arrayStoreBarrierType(JavaKind elementKind) { |
954 * If the given value is indeed an array, and its elements are of a word type, return the |
996 if (elementKind == JavaKind.Object) { |
955 * correct word kind; in all other cases, return the defaultElementKind. This is needed for |
|
956 * determining the correct write barrier type. |
|
957 * |
|
958 * @param array a value that is expected to have an array stamp |
|
959 * @param defaultElementKind the array's element kind without taking word types into account |
|
960 * @return the element kind of the array taking word types into account |
|
961 */ |
|
962 protected JavaKind maybeWordArrayElementKind(ValueNode array, JavaKind defaultElementKind) { |
|
963 JavaKind elementKind = defaultElementKind; |
|
964 Stamp arrayStamp = array.stamp(NodeView.DEFAULT); |
|
965 if (arrayStamp instanceof AbstractObjectStamp && arrayStamp.hasValues()) { |
|
966 ResolvedJavaType arrayType = ((AbstractObjectStamp) arrayStamp).type(); |
|
967 if (arrayType != null && arrayType.getComponentType() != null) { |
|
968 elementKind = wordTypes.asKind(arrayType.getComponentType()); |
|
969 } |
|
970 } |
|
971 return elementKind; |
|
972 } |
|
973 |
|
974 protected BarrierType arrayStoreBarrierType(ValueNode array, JavaKind elementKind) { |
|
975 JavaKind kind = maybeWordArrayElementKind(array, elementKind); |
|
976 if (kind == JavaKind.Object) { |
|
977 return BarrierType.ARRAY; |
997 return BarrierType.ARRAY; |
978 } |
998 } |
979 return BarrierType.NONE; |
999 return BarrierType.NONE; |
980 } |
1000 } |
981 |
1001 |
982 public BarrierType fieldInitializationBarrier(ResolvedJavaField field) { |
1002 public BarrierType fieldInitializationBarrier(JavaKind entryKind) { |
983 JavaKind fieldKind = wordTypes.asKind(field.getType()); |
1003 return entryKind == JavaKind.Object ? BarrierType.FIELD : BarrierType.NONE; |
984 return fieldKind == JavaKind.Object ? BarrierType.FIELD : BarrierType.NONE; |
1004 } |
985 } |
1005 |
986 |
1006 public BarrierType arrayInitializationBarrier(JavaKind entryKind) { |
987 public BarrierType arrayInitializationBarrier(ValueNode array, JavaKind entryKind) { |
1007 return entryKind == JavaKind.Object ? BarrierType.ARRAY : BarrierType.NONE; |
988 JavaKind kind = maybeWordArrayElementKind(array, entryKind); |
|
989 return kind == JavaKind.Object ? BarrierType.ARRAY : BarrierType.NONE; |
|
990 } |
1008 } |
991 |
1009 |
992 private BarrierType unsafeStoreBarrierType(RawStoreNode store) { |
1010 private BarrierType unsafeStoreBarrierType(RawStoreNode store) { |
993 if (!store.needsBarrier()) { |
1011 if (!store.needsBarrier()) { |
994 return BarrierType.NONE; |
1012 return BarrierType.NONE; |
1000 if (value.getStackKind() == JavaKind.Object && object.getStackKind() == JavaKind.Object) { |
1018 if (value.getStackKind() == JavaKind.Object && object.getStackKind() == JavaKind.Object) { |
1001 ResolvedJavaType type = StampTool.typeOrNull(object); |
1019 ResolvedJavaType type = StampTool.typeOrNull(object); |
1002 // Array types must use a precise barrier, so if the type is unknown or is a supertype |
1020 // Array types must use a precise barrier, so if the type is unknown or is a supertype |
1003 // of Object[] then treat it as an array. |
1021 // of Object[] then treat it as an array. |
1004 if (type != null && type.isArray()) { |
1022 if (type != null && type.isArray()) { |
1005 return arrayStoreBarrierType(object, JavaKind.Object); |
1023 return BarrierType.ARRAY; |
1006 } else if (type != null && wordTypes.isWord(type)) { |
|
1007 return BarrierType.NONE; |
|
1008 } else if (type == null || type.isAssignableFrom(objectArrayType)) { |
1024 } else if (type == null || type.isAssignableFrom(objectArrayType)) { |
1009 return BarrierType.UNKNOWN; |
1025 return BarrierType.UNKNOWN; |
1010 } else { |
1026 } else { |
1011 return BarrierType.FIELD; |
1027 return BarrierType.FIELD; |
1012 } |
1028 } |