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.replacements;
26
27 import static jdk.vm.ci.code.MemoryBarriers.JMM_POST_VOLATILE_READ;
28 import static jdk.vm.ci.code.MemoryBarriers.JMM_POST_VOLATILE_WRITE;
29 import static jdk.vm.ci.code.MemoryBarriers.JMM_PRE_VOLATILE_READ;
30 import static jdk.vm.ci.code.MemoryBarriers.JMM_PRE_VOLATILE_WRITE;
31 import static jdk.vm.ci.meta.DeoptimizationAction.InvalidateReprofile;
32 import static jdk.vm.ci.meta.DeoptimizationReason.BoundsCheckException;
33 import static jdk.vm.ci.meta.DeoptimizationReason.NullCheckException;
34 import static org.graalvm.compiler.nodes.NamedLocationIdentity.ARRAY_LENGTH_LOCATION;
35 import static org.graalvm.compiler.nodes.java.ArrayLengthNode.readArrayLength;
36 import static org.graalvm.compiler.nodes.util.GraphUtil.skipPiWhileNonNull;
37
38 import java.nio.ByteOrder;
39 import java.util.ArrayList;
40 import java.util.BitSet;
41 import java.util.List;
42
43 import org.graalvm.compiler.api.directives.GraalDirectives;
44 import org.graalvm.compiler.api.replacements.Snippet;
45 import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
46 import org.graalvm.compiler.core.common.LIRKind;
47 import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
48 import org.graalvm.compiler.core.common.spi.ForeignCallsProvider;
49 import org.graalvm.compiler.core.common.type.IntegerStamp;
50 import org.graalvm.compiler.core.common.type.ObjectStamp;
51 import org.graalvm.compiler.core.common.type.Stamp;
52 import org.graalvm.compiler.core.common.type.StampFactory;
53 import org.graalvm.compiler.core.common.type.TypeReference;
54 import org.graalvm.compiler.debug.DebugCloseable;
168 private ConstantStringIndexOfSnippets.Templates indexOfSnippets;
169
170 public DefaultJavaLoweringProvider(MetaAccessProvider metaAccess, ForeignCallsProvider foreignCalls, TargetDescription target, boolean useCompressedOops) {
171 this.metaAccess = metaAccess;
172 this.foreignCalls = foreignCalls;
173 this.target = target;
174 this.useCompressedOops = useCompressedOops;
175 this.objectArrayType = metaAccess.lookupJavaType(Object[].class);
176 }
177
178 public void initialize(OptionValues options, Iterable<DebugHandlersFactory> factories, SnippetCounter.Group.Factory factory, Providers providers, SnippetReflectionProvider snippetReflection) {
179 boxingSnippets = new BoxingSnippets.Templates(options, factories, factory, providers, snippetReflection, target);
180 indexOfSnippets = new ConstantStringIndexOfSnippets.Templates(options, factories, providers, snippetReflection, target);
181 providers.getReplacements().registerSnippetTemplateCache(new SnippetCounterNode.SnippetCounterSnippets.Templates(options, factories, providers, snippetReflection, target));
182 }
183
184 public final TargetDescription getTarget() {
185 return target;
186 }
187
188 @Override
189 @SuppressWarnings("try")
190 public void lower(Node n, LoweringTool tool) {
191 assert n instanceof Lowerable;
192 StructuredGraph graph = (StructuredGraph) n.graph();
193 try (DebugCloseable context = n.withNodeSourcePosition()) {
194 if (n instanceof LoadFieldNode) {
195 lowerLoadFieldNode((LoadFieldNode) n, tool);
196 } else if (n instanceof StoreFieldNode) {
197 lowerStoreFieldNode((StoreFieldNode) n, tool);
198 } else if (n instanceof LoadIndexedNode) {
199 lowerLoadIndexedNode((LoadIndexedNode) n, tool);
200 } else if (n instanceof StoreIndexedNode) {
201 lowerStoreIndexedNode((StoreIndexedNode) n, tool);
202 } else if (n instanceof ArrayLengthNode) {
203 lowerArrayLengthNode((ArrayLengthNode) n, tool);
204 } else if (n instanceof LoadHubNode) {
205 lowerLoadHubNode((LoadHubNode) n, tool);
206 } else if (n instanceof LoadArrayComponentHubNode) {
207 lowerLoadArrayComponentHubNode((LoadArrayComponentHubNode) n);
423 StructuredGraph graph = storeField.graph();
424 ResolvedJavaField field = storeField.field();
425 ValueNode object = storeField.isStatic() ? staticFieldBase(graph, field) : storeField.object();
426 object = createNullCheckedValue(object, storeField, tool);
427 ValueNode value = implicitStoreConvert(graph, getStorageKind(storeField.field()), storeField.value());
428 AddressNode address = createFieldAddress(graph, object, field);
429 assert address != null;
430
431 WriteNode memoryWrite = graph.add(new WriteNode(address, fieldLocationIdentity(field), value, fieldStoreBarrierType(storeField.field())));
432 memoryWrite.setStateAfter(storeField.stateAfter());
433 graph.replaceFixedWithFixed(storeField, memoryWrite);
434
435 if (storeField.isVolatile()) {
436 MembarNode preMembar = graph.add(new MembarNode(JMM_PRE_VOLATILE_WRITE));
437 graph.addBeforeFixed(memoryWrite, preMembar);
438 MembarNode postMembar = graph.add(new MembarNode(JMM_POST_VOLATILE_WRITE));
439 graph.addAfterFixed(memoryWrite, postMembar);
440 }
441 }
442
443 /**
444 * Create a PiNode on the index proving that the index is positive. On some platforms this is
445 * important to allow the index to be used as an int in the address mode.
446 */
447 public AddressNode createArrayIndexAddress(StructuredGraph graph, ValueNode array, JavaKind elementKind, ValueNode index, GuardingNode boundsCheck) {
448 IntegerStamp indexStamp = StampFactory.forInteger(32, 0, Integer.MAX_VALUE - 1);
449 ValueNode positiveIndex = graph.maybeAddOrUnique(PiNode.create(index, indexStamp, boundsCheck != null ? boundsCheck.asNode() : null));
450 return createArrayAddress(graph, array, elementKind, positiveIndex);
451 }
452
453 public AddressNode createArrayAddress(StructuredGraph graph, ValueNode array, JavaKind elementKind, ValueNode index) {
454 ValueNode wordIndex;
455 if (target.wordSize > 4) {
456 wordIndex = graph.unique(new SignExtendNode(index, target.wordSize * 8));
457 } else {
458 assert target.wordSize == 4 : "unsupported word size";
459 wordIndex = index;
460 }
461
462 int shift = CodeUtil.log2(arrayScalingFactor(elementKind));
463 ValueNode scaledIndex = graph.unique(new LeftShiftNode(wordIndex, ConstantNode.forInt(shift, graph)));
464
465 int base = arrayBaseOffset(elementKind);
466 ValueNode offset = graph.unique(new AddNode(scaledIndex, ConstantNode.forIntegerKind(target.wordJavaKind, base, graph)));
467
468 return graph.unique(new OffsetAddressNode(array, offset));
469 }
470
471 protected void lowerLoadIndexedNode(LoadIndexedNode loadIndexed, LoweringTool tool) {
472 StructuredGraph graph = loadIndexed.graph();
473 ValueNode array = loadIndexed.array();
474 array = createNullCheckedValue(array, loadIndexed, tool);
475 JavaKind elementKind = loadIndexed.elementKind();
476 Stamp loadStamp = loadStamp(loadIndexed.stamp(NodeView.DEFAULT), elementKind);
477
478 GuardingNode boundsCheck = getBoundsCheck(loadIndexed, array, tool);
479 AddressNode address = createArrayIndexAddress(graph, array, elementKind, loadIndexed.index(), boundsCheck);
480 ReadNode memoryRead = graph.add(new ReadNode(address, NamedLocationIdentity.getArrayLocation(elementKind), loadStamp, BarrierType.NONE));
481 memoryRead.setGuard(boundsCheck);
482 ValueNode readValue = implicitLoadConvert(graph, elementKind, memoryRead);
483
484 loadIndexed.replaceAtUsages(readValue);
485 graph.replaceFixed(loadIndexed, memoryRead);
486 }
487
488 protected void lowerStoreIndexedNode(StoreIndexedNode storeIndexed, LoweringTool tool) {
489 StructuredGraph graph = storeIndexed.graph();
490
491 ValueNode value = storeIndexed.value();
492 ValueNode array = storeIndexed.array();
493
494 array = this.createNullCheckedValue(array, storeIndexed, tool);
495
496 GuardingNode boundsCheck = getBoundsCheck(storeIndexed, array, tool);
497
498 JavaKind elementKind = storeIndexed.elementKind();
499
783 if (value == null) {
784 omittedValues.set(valuePos);
785 } else if (!(value.isConstant() && value.asConstant().isDefaultForKind())) {
786 // Constant.illegal is always the defaultForKind, so it is skipped
787 JavaKind valueKind = value.getStackKind();
788 JavaKind entryKind = virtual.entryKind(i);
789
790 // Truffle requires some leniency in terms of what can be put where:
791 assert valueKind.getStackKind() == entryKind.getStackKind() ||
792 (valueKind == JavaKind.Long || valueKind == JavaKind.Double || (valueKind == JavaKind.Int && virtual instanceof VirtualArrayNode));
793 AddressNode address = null;
794 BarrierType barrierType = null;
795 if (virtual instanceof VirtualInstanceNode) {
796 ResolvedJavaField field = ((VirtualInstanceNode) virtual).field(i);
797 long offset = fieldOffset(field);
798 if (offset >= 0) {
799 address = createOffsetAddress(graph, newObject, offset);
800 barrierType = fieldInitializationBarrier(entryKind);
801 }
802 } else {
803 address = createOffsetAddress(graph, newObject, arrayBaseOffset(entryKind) + i * arrayScalingFactor(entryKind));
804 barrierType = arrayInitializationBarrier(entryKind);
805 }
806 if (address != null) {
807 WriteNode write = new WriteNode(address, LocationIdentity.init(), implicitStoreConvert(graph, entryKind, value), barrierType);
808 graph.addAfterFixed(newObject, graph.add(write));
809 }
810 }
811 valuePos++;
812 }
813 }
814 }
815 valuePos = 0;
816
817 for (int objIndex = 0; objIndex < commit.getVirtualObjects().size(); objIndex++) {
818 VirtualObjectNode virtual = commit.getVirtualObjects().get(objIndex);
819 try (DebugCloseable nsp = graph.withNodeSourcePosition(virtual)) {
820 int entryCount = virtual.entryCount();
821 ValueNode newObject = allocations[objIndex];
822 for (int i = 0; i < entryCount; i++) {
823 if (omittedValues.get(valuePos)) {
983 // of Object[] then treat it as an array.
984 if (type == null || type.isArray() || type.isAssignableFrom(objectArrayType)) {
985 return BarrierType.PRECISE;
986 } else {
987 return BarrierType.IMPRECISE;
988 }
989 }
990 return BarrierType.NONE;
991 }
992
993 public abstract int fieldOffset(ResolvedJavaField field);
994
995 public FieldLocationIdentity fieldLocationIdentity(ResolvedJavaField field) {
996 return new FieldLocationIdentity(field);
997 }
998
999 public abstract ValueNode staticFieldBase(StructuredGraph graph, ResolvedJavaField field);
1000
1001 public abstract int arrayLengthOffset();
1002
1003 @Override
1004 public int arrayScalingFactor(JavaKind elementKind) {
1005 return target.arch.getPlatformKind(elementKind).getSizeInBytes();
1006 }
1007
1008 public Stamp loadStamp(Stamp stamp, JavaKind kind) {
1009 return loadStamp(stamp, kind, true);
1010 }
1011
1012 private boolean useCompressedOops(JavaKind kind, boolean compressible) {
1013 return kind == JavaKind.Object && compressible && useCompressedOops;
1014 }
1015
1016 protected abstract Stamp loadCompressedStamp(ObjectStamp stamp);
1017
1018 /**
1019 * @param compressible whether the stamp should be compressible
1020 */
1021 protected Stamp loadStamp(Stamp stamp, JavaKind kind, boolean compressible) {
1022 if (useCompressedOops(kind, compressible)) {
1023 return loadCompressedStamp((ObjectStamp) stamp);
1024 }
1025
1026 switch (kind) {
1027 case Boolean:
1093 protected ValueNode implicitStoreConvert(JavaKind kind, ValueNode value, boolean compressible) {
1094 if (useCompressedOops(kind, compressible)) {
1095 return newCompressionNode(CompressionOp.Compress, value);
1096 }
1097
1098 switch (kind) {
1099 case Boolean:
1100 case Byte:
1101 return new NarrowNode(value, 8);
1102 case Char:
1103 case Short:
1104 return new NarrowNode(value, 16);
1105 }
1106 return value;
1107 }
1108
1109 protected abstract ValueNode createReadHub(StructuredGraph graph, ValueNode object, LoweringTool tool);
1110
1111 protected abstract ValueNode createReadArrayComponentHub(StructuredGraph graph, ValueNode arrayHub, FixedNode anchor);
1112
1113 protected GuardingNode getBoundsCheck(AccessIndexedNode n, ValueNode array, LoweringTool tool) {
1114 if (n.getBoundsCheck() != null) {
1115 return n.getBoundsCheck();
1116 }
1117
1118 StructuredGraph graph = n.graph();
1119 ValueNode arrayLength = readArrayLength(array, tool.getConstantReflection());
1120 if (arrayLength == null) {
1121 arrayLength = createReadArrayLength(array, n, tool);
1122 } else {
1123 arrayLength = arrayLength.isAlive() ? arrayLength : graph.addOrUniqueWithInputs(arrayLength);
1124 }
1125
1126 LogicNode boundsCheck = IntegerBelowNode.create(n.index(), arrayLength, NodeView.DEFAULT);
1127 if (boundsCheck.isTautology()) {
1128 return null;
1129 }
1130 return tool.createGuard(n, graph.addOrUniqueWithInputs(boundsCheck), BoundsCheckException, InvalidateReprofile);
1131 }
1132
1133 protected GuardingNode createNullCheck(ValueNode object, FixedNode before, LoweringTool tool) {
1134 if (StampTool.isPointerNonNull(object)) {
1135 return null;
1136 }
1137 return tool.createGuard(before, before.graph().unique(IsNullNode.create(object)), NullCheckException, InvalidateReprofile, SpeculationLog.NO_SPECULATION, true, null);
1138 }
1139
1140 protected ValueNode createNullCheckedValue(ValueNode object, FixedNode before, LoweringTool tool) {
1141 GuardingNode nullCheck = createNullCheck(object, before, tool);
1142 if (nullCheck == null) {
1143 return object;
1144 }
1145 return before.graph().maybeAddOrUnique(PiNode.create(object, (object.stamp(NodeView.DEFAULT)).join(StampFactory.objectNonNull()), (ValueNode) nullCheck));
1146 }
1147
1148 @Override
1149 public ValueNode reconstructArrayIndex(JavaKind elementKind, AddressNode address) {
1150 StructuredGraph graph = address.graph();
1151 ValueNode offset = ((OffsetAddressNode) address).getOffset();
1152
1153 int base = arrayBaseOffset(elementKind);
1154 ValueNode scaledIndex = graph.unique(new SubNode(offset, ConstantNode.forIntegerStamp(offset.stamp(NodeView.DEFAULT), base, graph)));
1155
1156 int shift = CodeUtil.log2(arrayScalingFactor(elementKind));
1157 ValueNode ret = graph.unique(new RightShiftNode(scaledIndex, ConstantNode.forInt(shift, graph)));
1158 return IntegerConvertNode.convert(ret, StampFactory.forKind(JavaKind.Int), graph, NodeView.DEFAULT);
1159 }
1160 }
|
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.replacements;
26
27 import static jdk.vm.ci.code.MemoryBarriers.JMM_POST_VOLATILE_READ;
28 import static jdk.vm.ci.code.MemoryBarriers.JMM_POST_VOLATILE_WRITE;
29 import static jdk.vm.ci.code.MemoryBarriers.JMM_PRE_VOLATILE_READ;
30 import static jdk.vm.ci.code.MemoryBarriers.JMM_PRE_VOLATILE_WRITE;
31 import static jdk.vm.ci.meta.DeoptimizationAction.InvalidateReprofile;
32 import static jdk.vm.ci.meta.DeoptimizationReason.BoundsCheckException;
33 import static jdk.vm.ci.meta.DeoptimizationReason.NullCheckException;
34 import static org.graalvm.compiler.core.common.SpeculativeExecutionAttacksMitigations.Options.UseIndexMasking;
35 import static org.graalvm.compiler.nodes.NamedLocationIdentity.ARRAY_LENGTH_LOCATION;
36 import static org.graalvm.compiler.nodes.calc.BinaryArithmeticNode.branchlessMax;
37 import static org.graalvm.compiler.nodes.calc.BinaryArithmeticNode.branchlessMin;
38 import static org.graalvm.compiler.nodes.java.ArrayLengthNode.readArrayLength;
39 import static org.graalvm.compiler.nodes.util.GraphUtil.skipPiWhileNonNull;
40
41 import java.nio.ByteOrder;
42 import java.util.ArrayList;
43 import java.util.BitSet;
44 import java.util.List;
45
46 import org.graalvm.compiler.api.directives.GraalDirectives;
47 import org.graalvm.compiler.api.replacements.Snippet;
48 import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
49 import org.graalvm.compiler.core.common.LIRKind;
50 import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
51 import org.graalvm.compiler.core.common.spi.ForeignCallsProvider;
52 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.Stamp;
55 import org.graalvm.compiler.core.common.type.StampFactory;
56 import org.graalvm.compiler.core.common.type.TypeReference;
57 import org.graalvm.compiler.debug.DebugCloseable;
171 private ConstantStringIndexOfSnippets.Templates indexOfSnippets;
172
173 public DefaultJavaLoweringProvider(MetaAccessProvider metaAccess, ForeignCallsProvider foreignCalls, TargetDescription target, boolean useCompressedOops) {
174 this.metaAccess = metaAccess;
175 this.foreignCalls = foreignCalls;
176 this.target = target;
177 this.useCompressedOops = useCompressedOops;
178 this.objectArrayType = metaAccess.lookupJavaType(Object[].class);
179 }
180
181 public void initialize(OptionValues options, Iterable<DebugHandlersFactory> factories, SnippetCounter.Group.Factory factory, Providers providers, SnippetReflectionProvider snippetReflection) {
182 boxingSnippets = new BoxingSnippets.Templates(options, factories, factory, providers, snippetReflection, target);
183 indexOfSnippets = new ConstantStringIndexOfSnippets.Templates(options, factories, providers, snippetReflection, target);
184 providers.getReplacements().registerSnippetTemplateCache(new SnippetCounterNode.SnippetCounterSnippets.Templates(options, factories, providers, snippetReflection, target));
185 }
186
187 public final TargetDescription getTarget() {
188 return target;
189 }
190
191 public MetaAccessProvider getMetaAccess() {
192 return metaAccess;
193 }
194
195 @Override
196 @SuppressWarnings("try")
197 public void lower(Node n, LoweringTool tool) {
198 assert n instanceof Lowerable;
199 StructuredGraph graph = (StructuredGraph) n.graph();
200 try (DebugCloseable context = n.withNodeSourcePosition()) {
201 if (n instanceof LoadFieldNode) {
202 lowerLoadFieldNode((LoadFieldNode) n, tool);
203 } else if (n instanceof StoreFieldNode) {
204 lowerStoreFieldNode((StoreFieldNode) n, tool);
205 } else if (n instanceof LoadIndexedNode) {
206 lowerLoadIndexedNode((LoadIndexedNode) n, tool);
207 } else if (n instanceof StoreIndexedNode) {
208 lowerStoreIndexedNode((StoreIndexedNode) n, tool);
209 } else if (n instanceof ArrayLengthNode) {
210 lowerArrayLengthNode((ArrayLengthNode) n, tool);
211 } else if (n instanceof LoadHubNode) {
212 lowerLoadHubNode((LoadHubNode) n, tool);
213 } else if (n instanceof LoadArrayComponentHubNode) {
214 lowerLoadArrayComponentHubNode((LoadArrayComponentHubNode) n);
430 StructuredGraph graph = storeField.graph();
431 ResolvedJavaField field = storeField.field();
432 ValueNode object = storeField.isStatic() ? staticFieldBase(graph, field) : storeField.object();
433 object = createNullCheckedValue(object, storeField, tool);
434 ValueNode value = implicitStoreConvert(graph, getStorageKind(storeField.field()), storeField.value());
435 AddressNode address = createFieldAddress(graph, object, field);
436 assert address != null;
437
438 WriteNode memoryWrite = graph.add(new WriteNode(address, fieldLocationIdentity(field), value, fieldStoreBarrierType(storeField.field())));
439 memoryWrite.setStateAfter(storeField.stateAfter());
440 graph.replaceFixedWithFixed(storeField, memoryWrite);
441
442 if (storeField.isVolatile()) {
443 MembarNode preMembar = graph.add(new MembarNode(JMM_PRE_VOLATILE_WRITE));
444 graph.addBeforeFixed(memoryWrite, preMembar);
445 MembarNode postMembar = graph.add(new MembarNode(JMM_POST_VOLATILE_WRITE));
446 graph.addAfterFixed(memoryWrite, postMembar);
447 }
448 }
449
450 public static final IntegerStamp POSITIVE_ARRAY_INDEX_STAMP = StampFactory.forInteger(32, 0, Integer.MAX_VALUE - 1);
451
452 /**
453 * Create a PiNode on the index proving that the index is positive. On some platforms this is
454 * important to allow the index to be used as an int in the address mode.
455 */
456 public AddressNode createArrayIndexAddress(StructuredGraph graph, ValueNode array, JavaKind elementKind, ValueNode index, GuardingNode boundsCheck) {
457 ValueNode positiveIndex = graph.maybeAddOrUnique(PiNode.create(index, POSITIVE_ARRAY_INDEX_STAMP, boundsCheck != null ? boundsCheck.asNode() : null));
458 return createArrayAddress(graph, array, elementKind, positiveIndex);
459 }
460
461 public AddressNode createArrayAddress(StructuredGraph graph, ValueNode array, JavaKind elementKind, ValueNode index) {
462 ValueNode wordIndex;
463 if (target.wordSize > 4) {
464 wordIndex = graph.unique(new SignExtendNode(index, target.wordSize * 8));
465 } else {
466 assert target.wordSize == 4 : "unsupported word size";
467 wordIndex = index;
468 }
469
470 int shift = CodeUtil.log2(metaAccess.getArrayIndexScale(elementKind));
471 ValueNode scaledIndex = graph.unique(new LeftShiftNode(wordIndex, ConstantNode.forInt(shift, graph)));
472
473 int base = metaAccess.getArrayBaseOffset(elementKind);
474 ValueNode offset = graph.unique(new AddNode(scaledIndex, ConstantNode.forIntegerKind(target.wordJavaKind, base, graph)));
475
476 return graph.unique(new OffsetAddressNode(array, offset));
477 }
478
479 protected void lowerLoadIndexedNode(LoadIndexedNode loadIndexed, LoweringTool tool) {
480 StructuredGraph graph = loadIndexed.graph();
481 ValueNode array = loadIndexed.array();
482 array = createNullCheckedValue(array, loadIndexed, tool);
483 JavaKind elementKind = loadIndexed.elementKind();
484 Stamp loadStamp = loadStamp(loadIndexed.stamp(NodeView.DEFAULT), elementKind);
485
486 GuardingNode boundsCheck = getBoundsCheck(loadIndexed, array, tool);
487 ValueNode index = loadIndexed.index();
488 if (UseIndexMasking.getValue(graph.getOptions())) {
489 index = proxyIndex(loadIndexed, index, array, tool);
490 }
491 AddressNode address = createArrayIndexAddress(graph, array, elementKind, index, boundsCheck);
492
493 ReadNode memoryRead = graph.add(new ReadNode(address, NamedLocationIdentity.getArrayLocation(elementKind), loadStamp, BarrierType.NONE));
494 memoryRead.setGuard(boundsCheck);
495 ValueNode readValue = implicitLoadConvert(graph, elementKind, memoryRead);
496
497 loadIndexed.replaceAtUsages(readValue);
498 graph.replaceFixed(loadIndexed, memoryRead);
499 }
500
501 protected void lowerStoreIndexedNode(StoreIndexedNode storeIndexed, LoweringTool tool) {
502 StructuredGraph graph = storeIndexed.graph();
503
504 ValueNode value = storeIndexed.value();
505 ValueNode array = storeIndexed.array();
506
507 array = this.createNullCheckedValue(array, storeIndexed, tool);
508
509 GuardingNode boundsCheck = getBoundsCheck(storeIndexed, array, tool);
510
511 JavaKind elementKind = storeIndexed.elementKind();
512
796 if (value == null) {
797 omittedValues.set(valuePos);
798 } else if (!(value.isConstant() && value.asConstant().isDefaultForKind())) {
799 // Constant.illegal is always the defaultForKind, so it is skipped
800 JavaKind valueKind = value.getStackKind();
801 JavaKind entryKind = virtual.entryKind(i);
802
803 // Truffle requires some leniency in terms of what can be put where:
804 assert valueKind.getStackKind() == entryKind.getStackKind() ||
805 (valueKind == JavaKind.Long || valueKind == JavaKind.Double || (valueKind == JavaKind.Int && virtual instanceof VirtualArrayNode));
806 AddressNode address = null;
807 BarrierType barrierType = null;
808 if (virtual instanceof VirtualInstanceNode) {
809 ResolvedJavaField field = ((VirtualInstanceNode) virtual).field(i);
810 long offset = fieldOffset(field);
811 if (offset >= 0) {
812 address = createOffsetAddress(graph, newObject, offset);
813 barrierType = fieldInitializationBarrier(entryKind);
814 }
815 } else {
816 address = createOffsetAddress(graph, newObject, metaAccess.getArrayBaseOffset(entryKind) + i * metaAccess.getArrayIndexScale(entryKind));
817 barrierType = arrayInitializationBarrier(entryKind);
818 }
819 if (address != null) {
820 WriteNode write = new WriteNode(address, LocationIdentity.init(), implicitStoreConvert(graph, entryKind, value), barrierType);
821 graph.addAfterFixed(newObject, graph.add(write));
822 }
823 }
824 valuePos++;
825 }
826 }
827 }
828 valuePos = 0;
829
830 for (int objIndex = 0; objIndex < commit.getVirtualObjects().size(); objIndex++) {
831 VirtualObjectNode virtual = commit.getVirtualObjects().get(objIndex);
832 try (DebugCloseable nsp = graph.withNodeSourcePosition(virtual)) {
833 int entryCount = virtual.entryCount();
834 ValueNode newObject = allocations[objIndex];
835 for (int i = 0; i < entryCount; i++) {
836 if (omittedValues.get(valuePos)) {
996 // of Object[] then treat it as an array.
997 if (type == null || type.isArray() || type.isAssignableFrom(objectArrayType)) {
998 return BarrierType.PRECISE;
999 } else {
1000 return BarrierType.IMPRECISE;
1001 }
1002 }
1003 return BarrierType.NONE;
1004 }
1005
1006 public abstract int fieldOffset(ResolvedJavaField field);
1007
1008 public FieldLocationIdentity fieldLocationIdentity(ResolvedJavaField field) {
1009 return new FieldLocationIdentity(field);
1010 }
1011
1012 public abstract ValueNode staticFieldBase(StructuredGraph graph, ResolvedJavaField field);
1013
1014 public abstract int arrayLengthOffset();
1015
1016 public Stamp loadStamp(Stamp stamp, JavaKind kind) {
1017 return loadStamp(stamp, kind, true);
1018 }
1019
1020 private boolean useCompressedOops(JavaKind kind, boolean compressible) {
1021 return kind == JavaKind.Object && compressible && useCompressedOops;
1022 }
1023
1024 protected abstract Stamp loadCompressedStamp(ObjectStamp stamp);
1025
1026 /**
1027 * @param compressible whether the stamp should be compressible
1028 */
1029 protected Stamp loadStamp(Stamp stamp, JavaKind kind, boolean compressible) {
1030 if (useCompressedOops(kind, compressible)) {
1031 return loadCompressedStamp((ObjectStamp) stamp);
1032 }
1033
1034 switch (kind) {
1035 case Boolean:
1101 protected ValueNode implicitStoreConvert(JavaKind kind, ValueNode value, boolean compressible) {
1102 if (useCompressedOops(kind, compressible)) {
1103 return newCompressionNode(CompressionOp.Compress, value);
1104 }
1105
1106 switch (kind) {
1107 case Boolean:
1108 case Byte:
1109 return new NarrowNode(value, 8);
1110 case Char:
1111 case Short:
1112 return new NarrowNode(value, 16);
1113 }
1114 return value;
1115 }
1116
1117 protected abstract ValueNode createReadHub(StructuredGraph graph, ValueNode object, LoweringTool tool);
1118
1119 protected abstract ValueNode createReadArrayComponentHub(StructuredGraph graph, ValueNode arrayHub, FixedNode anchor);
1120
1121 protected ValueNode proxyIndex(AccessIndexedNode n, ValueNode index, ValueNode array, LoweringTool tool) {
1122 StructuredGraph graph = index.graph();
1123 ValueNode arrayLength = readOrCreateArrayLength(n, array, tool, graph);
1124 ValueNode lengthMinusOne = SubNode.create(arrayLength, ConstantNode.forInt(1), NodeView.DEFAULT);
1125 return branchlessMax(branchlessMin(index, lengthMinusOne, NodeView.DEFAULT), ConstantNode.forInt(0), NodeView.DEFAULT);
1126 }
1127
1128 protected GuardingNode getBoundsCheck(AccessIndexedNode n, ValueNode array, LoweringTool tool) {
1129 if (n.getBoundsCheck() != null) {
1130 return n.getBoundsCheck();
1131 }
1132
1133 StructuredGraph graph = n.graph();
1134 ValueNode arrayLength = readOrCreateArrayLength(n, array, tool, graph);
1135
1136 LogicNode boundsCheck = IntegerBelowNode.create(n.index(), arrayLength, NodeView.DEFAULT);
1137 if (boundsCheck.isTautology()) {
1138 return null;
1139 }
1140 return tool.createGuard(n, graph.addOrUniqueWithInputs(boundsCheck), BoundsCheckException, InvalidateReprofile);
1141 }
1142
1143 private ValueNode readOrCreateArrayLength(AccessIndexedNode n, ValueNode array, LoweringTool tool, StructuredGraph graph) {
1144 ValueNode arrayLength = readArrayLength(array, tool.getConstantReflection());
1145 if (arrayLength == null) {
1146 arrayLength = createReadArrayLength(array, n, tool);
1147 } else {
1148 arrayLength = arrayLength.isAlive() ? arrayLength : graph.addOrUniqueWithInputs(arrayLength);
1149 }
1150 return arrayLength;
1151 }
1152
1153 protected GuardingNode createNullCheck(ValueNode object, FixedNode before, LoweringTool tool) {
1154 if (StampTool.isPointerNonNull(object)) {
1155 return null;
1156 }
1157 return tool.createGuard(before, before.graph().unique(IsNullNode.create(object)), NullCheckException, InvalidateReprofile, SpeculationLog.NO_SPECULATION, true, null);
1158 }
1159
1160 protected ValueNode createNullCheckedValue(ValueNode object, FixedNode before, LoweringTool tool) {
1161 GuardingNode nullCheck = createNullCheck(object, before, tool);
1162 if (nullCheck == null) {
1163 return object;
1164 }
1165 return before.graph().maybeAddOrUnique(PiNode.create(object, (object.stamp(NodeView.DEFAULT)).join(StampFactory.objectNonNull()), (ValueNode) nullCheck));
1166 }
1167
1168 @Override
1169 public ValueNode reconstructArrayIndex(JavaKind elementKind, AddressNode address) {
1170 StructuredGraph graph = address.graph();
1171 ValueNode offset = ((OffsetAddressNode) address).getOffset();
1172
1173 int base = metaAccess.getArrayBaseOffset(elementKind);
1174 ValueNode scaledIndex = graph.unique(new SubNode(offset, ConstantNode.forIntegerStamp(offset.stamp(NodeView.DEFAULT), base, graph)));
1175
1176 int shift = CodeUtil.log2(metaAccess.getArrayIndexScale(elementKind));
1177 ValueNode ret = graph.unique(new RightShiftNode(scaledIndex, ConstantNode.forInt(shift, graph)));
1178 return IntegerConvertNode.convert(ret, StampFactory.forKind(JavaKind.Int), graph, NodeView.DEFAULT);
1179 }
1180 }
|