Skip to content

Commit 299f246

Browse files
author
Christian Wimmer
committed
Optimize serial GC write barrier for non-array stores
1 parent 5b743d4 commit 299f246

File tree

1 file changed

+46
-8
lines changed
  • substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/graal

1 file changed

+46
-8
lines changed

substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/graal/BarrierSnippets.java

Lines changed: 46 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,11 @@
3131
import org.graalvm.compiler.api.replacements.Fold;
3232
import org.graalvm.compiler.api.replacements.Snippet;
3333
import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter;
34+
import org.graalvm.compiler.api.replacements.Snippet.NonNullParameter;
3435
import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
3536
import org.graalvm.compiler.debug.DebugHandlersFactory;
3637
import org.graalvm.compiler.graph.Node;
38+
import org.graalvm.compiler.nodes.BreakpointNode;
3739
import org.graalvm.compiler.nodes.NamedLocationIdentity;
3840
import org.graalvm.compiler.nodes.extended.BranchProbabilityNode;
3941
import org.graalvm.compiler.nodes.extended.FixedValueAnchorNode;
@@ -42,6 +44,7 @@
4244
import org.graalvm.compiler.nodes.gc.WriteBarrier;
4345
import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode;
4446
import org.graalvm.compiler.nodes.spi.LoweringTool;
47+
import org.graalvm.compiler.nodes.type.StampTool;
4548
import org.graalvm.compiler.options.Option;
4649
import org.graalvm.compiler.options.OptionValues;
4750
import org.graalvm.compiler.phases.util.Providers;
@@ -64,13 +67,18 @@
6467
import com.oracle.svm.core.util.Counter;
6568
import com.oracle.svm.core.util.CounterFeature;
6669

70+
import jdk.vm.ci.meta.ResolvedJavaType;
71+
6772
public class BarrierSnippets extends SubstrateTemplates implements Snippets {
6873
/** A LocationIdentity to distinguish card locations from other locations. */
6974
public static final LocationIdentity CARD_REMEMBERED_SET_LOCATION = NamedLocationIdentity.mutable("CardRememberedSet");
7075

7176
public static class Options {
7277
@Option(help = "Instrument write barriers with counters")//
7378
public static final HostedOptionKey<Boolean> CountWriteBarriers = new HostedOptionKey<>(false);
79+
80+
@Option(help = "Verify write barriers")//
81+
public static final HostedOptionKey<Boolean> VerifyWriteBarriers = new HostedOptionKey<>(true);
7482
}
7583

7684
@Fold
@@ -90,23 +98,40 @@ public void registerLowerings(Map<Class<? extends Node>, NodeLoweringProvider<?>
9098
}
9199

92100
@Snippet
93-
public static void postWriteBarrierSnippet(Object object, @ConstantParameter boolean verifyOnly) {
101+
public static void postWriteBarrierSnippet(@NonNullParameter Object object, @ConstantParameter boolean alwaysAlignedChunk, @ConstantParameter boolean verifyOnly) {
94102
counters().postWriteBarrier.inc();
95103

96104
Object fixedObject = FixedValueAnchorNode.getObject(object);
97105
UnsignedWord objectHeader = ObjectHeaderImpl.readHeaderFromObject(fixedObject);
106+
107+
if (Options.VerifyWriteBarriers.getValue() && alwaysAlignedChunk) {
108+
/*
109+
* In addition to verifying that the object is in an aligned chunk, we also verify that
110+
* it is not an array at all. Since most arrays are small and therefore in an aligned
111+
* chunk, this greatly increases the verification coverage. To increase verification
112+
* coverage, we also do the verification before checking if a barrier is needed at all.
113+
*/
114+
if (ObjectHeaderImpl.isUnalignedHeader(objectHeader) || object.getClass().isArray()) {
115+
BreakpointNode.breakpoint();
116+
}
117+
}
118+
98119
boolean needsBarrier = RememberedSet.get().hasRememberedSet(objectHeader);
99120
if (BranchProbabilityNode.probability(BranchProbabilityNode.FREQUENT_PROBABILITY, !needsBarrier)) {
100121
return;
101122
}
102-
boolean aligned = ObjectHeaderImpl.isAlignedHeader(objectHeader);
103-
if (BranchProbabilityNode.probability(BranchProbabilityNode.LIKELY_PROBABILITY, aligned)) {
104-
counters().postWriteBarrierAligned.inc();
105-
RememberedSet.get().dirtyCardForAlignedObject(fixedObject, verifyOnly);
106-
return;
123+
124+
if (!alwaysAlignedChunk) {
125+
boolean unaligned = ObjectHeaderImpl.isUnalignedHeader(objectHeader);
126+
if (BranchProbabilityNode.probability(BranchProbabilityNode.NOT_LIKELY_PROBABILITY, unaligned)) {
127+
counters().postWriteBarrierUnaligned.inc();
128+
RememberedSet.get().dirtyCardForUnalignedObject(fixedObject, verifyOnly);
129+
return;
130+
}
107131
}
108-
counters().postWriteBarrierUnaligned.inc();
109-
RememberedSet.get().dirtyCardForUnalignedObject(fixedObject, verifyOnly);
132+
133+
counters().postWriteBarrierAligned.inc();
134+
RememberedSet.get().dirtyCardForAlignedObject(fixedObject, verifyOnly);
110135
}
111136

112137
private class PostWriteBarrierLowering implements NodeLoweringProvider<WriteBarrier> {
@@ -116,7 +141,20 @@ private class PostWriteBarrierLowering implements NodeLoweringProvider<WriteBarr
116141
public void lower(WriteBarrier barrier, LoweringTool tool) {
117142
Arguments args = new Arguments(postWriteBarrierSnippet, barrier.graph().getGuardsStage(), tool.getLoweringStage());
118143
OffsetAddressNode address = (OffsetAddressNode) barrier.getAddress();
144+
145+
/*
146+
* We know that instances (in contrast to arrays) are always in aligned chunks. There is
147+
* no code anywhere that would allocate an instance into an unaligned chunk.
148+
*
149+
* Note that arrays can be assigned to values that have the type java.lang.Object, so
150+
* that case is excluded. Arrays can also implement some interfaces, like Serializable.
151+
* For simplicity, we exclude all interface types.
152+
*/
153+
ResolvedJavaType baseType = StampTool.typeOrNull(address.getBase());
154+
boolean alwaysAlignedChunk = baseType != null && !baseType.isArray() && !baseType.isJavaLangObject() && !baseType.isInterface();
155+
119156
args.add("object", address.getBase());
157+
args.addConst("alwaysAlignedChunk", alwaysAlignedChunk);
120158
args.addConst("verifyOnly", getVerifyOnly(barrier));
121159

122160
template(barrier, args).instantiate(providers.getMetaAccess(), barrier, SnippetTemplate.DEFAULT_REPLACER, args);

0 commit comments

Comments
 (0)