Skip to content

Commit 73282d7

Browse files
committed
[GR-60075] Allow using different LocationIdentities with ObjectHeader.initializeObjectHeader
PullRequest: graal/19444
2 parents 3f05705 + 031a192 commit 73282d7

File tree

4 files changed

+139
-18
lines changed

4 files changed

+139
-18
lines changed

substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/ObjectHeaderImpl.java

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2013, 2024, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -26,7 +26,6 @@
2626

2727
import org.graalvm.nativeimage.Platform;
2828
import org.graalvm.nativeimage.Platforms;
29-
import org.graalvm.word.LocationIdentity;
3029
import org.graalvm.word.Pointer;
3130
import org.graalvm.word.UnsignedWord;
3231
import org.graalvm.word.WordBase;
@@ -48,7 +47,6 @@
4847

4948
import jdk.graal.compiler.api.directives.GraalDirectives;
5049
import jdk.graal.compiler.api.replacements.Fold;
51-
import jdk.graal.compiler.nodes.extended.MembarNode;
5250
import jdk.graal.compiler.replacements.ReplacementsUtil;
5351
import jdk.graal.compiler.word.ObjectAccess;
5452
import jdk.graal.compiler.word.Word;
@@ -137,26 +135,26 @@ public Word encodeAsUnmanagedObjectHeader(DynamicHub hub) {
137135
}
138136

139137
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
138+
@AlwaysInline(INLINE_INITIALIZE_HEADER_INIT_REASON)
140139
@Override
141-
public void initializeHeaderOfNewObject(Pointer objectPointer, Word encodedHub, boolean isArrayLike) {
140+
protected void initializeObjectHeader(Pointer objectPointer, Word encodedHub, boolean isArrayLike, MemWriter writer) {
142141
ObjectLayout ol = ConfigurationValues.getObjectLayout();
143142
boolean isIdentityHashFieldInObjectHeader = ol.isIdentityHashFieldInObjectHeader() || ol.isIdentityHashFieldAtTypeSpecificOffset() && isArrayLike;
144143
if (getReferenceSize() == Integer.BYTES) {
145144
dynamicAssert(encodedHub.and(WordFactory.unsigned(0xFFFFFFFF00000000L)).isNull(), "hub can only use 32 bits");
146145
if (isIdentityHashFieldInObjectHeader) {
147146
/* Use a single 64-bit write to initialize the hub and the identity hashcode. */
148147
dynamicAssert(ol.getObjectHeaderIdentityHashOffset() == getHubOffset() + 4, "assumed layout to optimize initializing write");
149-
objectPointer.writeLong(getHubOffset(), encodedHub.rawValue(), LocationIdentity.INIT_LOCATION);
148+
writer.writeLong(objectPointer, getHubOffset(), encodedHub.rawValue());
150149
} else {
151-
objectPointer.writeInt(getHubOffset(), (int) encodedHub.rawValue(), LocationIdentity.INIT_LOCATION);
150+
writer.writeInt(objectPointer, getHubOffset(), (int) encodedHub.rawValue());
152151
}
153152
} else {
154-
objectPointer.writeWord(getHubOffset(), encodedHub, LocationIdentity.INIT_LOCATION);
153+
writer.writeWord(objectPointer, getHubOffset(), encodedHub);
155154
if (isIdentityHashFieldInObjectHeader) {
156-
objectPointer.writeInt(ol.getObjectHeaderIdentityHashOffset(), 0, LocationIdentity.INIT_LOCATION);
155+
writer.writeInt(objectPointer, ol.getObjectHeaderIdentityHashOffset(), 0);
157156
}
158157
}
159-
MembarNode.memoryBarrier(MembarNode.FenceKind.ALLOCATION_INIT, LocationIdentity.INIT_LOCATION);
160158
}
161159

162160
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/c/NonmovableArrays.java

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -31,7 +31,6 @@
3131
import org.graalvm.nativeimage.Platform;
3232
import org.graalvm.nativeimage.Platforms;
3333
import org.graalvm.nativeimage.c.type.CTypeConversion;
34-
import org.graalvm.word.LocationIdentity;
3534
import org.graalvm.word.Pointer;
3635
import org.graalvm.word.PointerBase;
3736
import org.graalvm.word.UnsignedWord;
@@ -55,7 +54,7 @@
5554
import com.oracle.svm.core.snippets.KnownIntrinsics;
5655
import com.oracle.svm.core.util.VMError;
5756

58-
import jdk.graal.compiler.nodes.extended.MembarNode;
57+
import jdk.graal.compiler.nodes.NamedLocationIdentity;
5958
import jdk.graal.compiler.nodes.java.ArrayLengthNode;
6059
import jdk.graal.compiler.word.Word;
6160

@@ -102,9 +101,8 @@ private static <T extends NonmovableArray<?>> T createArray(int length, Class<?>
102101

103102
ObjectHeader header = Heap.getHeap().getObjectHeader();
104103
Word encodedHeader = header.encodeAsUnmanagedObjectHeader(hub);
105-
header.initializeHeaderOfNewObject(array, encodedHeader, true);
106-
array.writeInt(ConfigurationValues.getObjectLayout().getArrayLengthOffset(), length, LocationIdentity.INIT_LOCATION);
107-
MembarNode.memoryBarrier(MembarNode.FenceKind.ALLOCATION_INIT, LocationIdentity.INIT_LOCATION);
104+
header.initializeHeaderOfNewObjectOffHeap(array, encodedHeader, true);
105+
array.writeInt(ConfigurationValues.getObjectLayout().getArrayLengthOffset(), length, NamedLocationIdentity.OFF_HEAP_LOCATION);
108106
// already zero-initialized thanks to calloc()
109107
trackUnmanagedArray((NonmovableArray<?>) array);
110108
return (T) array;

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/SubstrateAllocationSnippets.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -529,7 +529,7 @@ protected final Object callNewMultiArrayStub(Word objectHeader, int rank, Word d
529529

530530
@Override
531531
public void initializeObjectHeader(Word memory, Word objectHeader, boolean isArrayLike) {
532-
Heap.getHeap().getObjectHeader().initializeHeaderOfNewObject(memory, objectHeader, isArrayLike);
532+
Heap.getHeap().getObjectHeader().initializeHeaderOfNewObjectInit(memory, objectHeader, isArrayLike);
533533
}
534534

535535
@Override

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/ObjectHeader.java

Lines changed: 127 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2013, 2024, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -26,18 +26,22 @@
2626

2727
import org.graalvm.nativeimage.Platform;
2828
import org.graalvm.nativeimage.Platforms;
29+
import org.graalvm.word.LocationIdentity;
2930
import org.graalvm.word.Pointer;
3031
import org.graalvm.word.WordFactory;
3132

33+
import com.oracle.svm.core.AlwaysInline;
3234
import com.oracle.svm.core.Uninterruptible;
3335
import com.oracle.svm.core.config.ConfigurationValues;
3436
import com.oracle.svm.core.hub.DynamicHub;
3537
import com.oracle.svm.core.image.ImageHeapObject;
3638
import com.oracle.svm.core.snippets.KnownIntrinsics;
3739

3840
import jdk.graal.compiler.api.replacements.Fold;
41+
import jdk.graal.compiler.nodes.NamedLocationIdentity;
3942
import jdk.graal.compiler.word.ObjectAccess;
4043
import jdk.graal.compiler.word.Word;
44+
import jdk.graal.compiler.word.WordOperationPlugin;
4145

4246
/**
4347
* An object header is a reference-sized collection of bits in each object instance. The object
@@ -49,6 +53,8 @@
4953
* of this instance if the object has been moved by the collector.
5054
*/
5155
public abstract class ObjectHeader {
56+
protected static final String INLINE_INITIALIZE_HEADER_INIT_REASON = "Methods that write to INIT_LOCATION must be inlined into a caller that emits an ALLOCATION_INIT barrier.";
57+
5258
@Platforms(Platform.HOSTED_ONLY.class)
5359
protected ObjectHeader() {
5460
}
@@ -107,8 +113,37 @@ public Pointer readPotentialDynamicHubFromPointer(Pointer ptr) {
107113
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
108114
public abstract Pointer extractPotentialDynamicHubFromHeader(Word header);
109115

116+
/**
117+
* Initializes the header of a newly allocated heap object (i.e. writing to
118+
* {@link LocationIdentity#INIT_LOCATION})
119+
*/
120+
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
121+
@AlwaysInline(INLINE_INITIALIZE_HEADER_INIT_REASON)
122+
public final void initializeHeaderOfNewObjectInit(Pointer ptr, Word header, boolean isArrayLike) {
123+
initializeObjectHeader(ptr, header, isArrayLike, InitLocationMemWriter.INSTANCE);
124+
}
125+
126+
/**
127+
* Initializes the header of a newly allocated object located anywhere in memory (i.e. writing
128+
* to {@link LocationIdentity#ANY_LOCATION})
129+
*/
110130
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
111-
public abstract void initializeHeaderOfNewObject(Pointer ptr, Word header, boolean isArrayLike);
131+
public final void initializeHeaderOfNewObjectAny(Pointer ptr, Word header, boolean isArrayLike) {
132+
initializeObjectHeader(ptr, header, isArrayLike, AnyLocationMemWriter.INSTANCE);
133+
}
134+
135+
/**
136+
* Initializes the header of a newly allocated object located off the heap (i.e. writing to
137+
* {@link NamedLocationIdentity#OFF_HEAP_LOCATION})
138+
*/
139+
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
140+
public final void initializeHeaderOfNewObjectOffHeap(Pointer ptr, Word header, boolean isArrayLike) {
141+
initializeObjectHeader(ptr, header, isArrayLike, OffHeapLocationMemWriter.INSTANCE);
142+
}
143+
144+
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
145+
@AlwaysInline(INLINE_INITIALIZE_HEADER_INIT_REASON)
146+
protected abstract void initializeObjectHeader(Pointer ptr, Word header, boolean isArrayLike, MemWriter writer);
112147

113148
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
114149
public boolean pointsToObjectHeader(Pointer ptr) {
@@ -149,4 +184,94 @@ protected static int getReferenceSize() {
149184
protected static int getHubOffset() {
150185
return ConfigurationValues.getObjectLayout().getHubOffset();
151186
}
187+
188+
/**
189+
* Helper interface to write to memory at an overridable {@link LocationIdentity}.
190+
* <p>
191+
* {@link #initializeObjectHeader} is used in multiple contexts which write to different memory
192+
* locations. LocationIdentity arguments to {@link WordOperationPlugin}s are required to be
193+
* constant at the time of bytecode parsing, meaning it's not possible to {@link Fold} a
194+
* location identity in any way, it must be a compile-time constant. To avoid duplicating
195+
* implementations of {@link #initializeObjectHeader}, we get around this by delegating the
196+
* writing to the MemWriter, whose implementations use different (constant) location identities.
197+
*/
198+
protected interface MemWriter {
199+
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
200+
void writeWord(Pointer ptr, int offset, Word word);
201+
202+
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
203+
void writeInt(Pointer ptr, int offset, int val);
204+
205+
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
206+
void writeLong(Pointer ptr, int offset, long val);
207+
}
208+
209+
private static final class AnyLocationMemWriter implements MemWriter {
210+
private static final AnyLocationMemWriter INSTANCE = new AnyLocationMemWriter();
211+
212+
@Override
213+
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
214+
public void writeWord(Pointer ptr, int offset, Word word) {
215+
ptr.writeWord(offset, word, LocationIdentity.ANY_LOCATION);
216+
}
217+
218+
@Override
219+
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
220+
public void writeInt(Pointer ptr, int offset, int val) {
221+
ptr.writeInt(offset, val, LocationIdentity.ANY_LOCATION);
222+
}
223+
224+
@Override
225+
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
226+
public void writeLong(Pointer ptr, int offset, long val) {
227+
ptr.writeLong(offset, val, LocationIdentity.ANY_LOCATION);
228+
}
229+
}
230+
231+
private static final class OffHeapLocationMemWriter implements MemWriter {
232+
private static final OffHeapLocationMemWriter INSTANCE = new OffHeapLocationMemWriter();
233+
234+
@Override
235+
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
236+
public void writeWord(Pointer ptr, int offset, Word word) {
237+
ptr.writeWord(offset, word, NamedLocationIdentity.OFF_HEAP_LOCATION);
238+
}
239+
240+
@Override
241+
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
242+
public void writeInt(Pointer ptr, int offset, int val) {
243+
ptr.writeInt(offset, val, NamedLocationIdentity.OFF_HEAP_LOCATION);
244+
}
245+
246+
@Override
247+
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
248+
public void writeLong(Pointer ptr, int offset, long val) {
249+
ptr.writeLong(offset, val, NamedLocationIdentity.OFF_HEAP_LOCATION);
250+
}
251+
}
252+
253+
private static final class InitLocationMemWriter implements MemWriter {
254+
private static final InitLocationMemWriter INSTANCE = new InitLocationMemWriter();
255+
256+
@Override
257+
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
258+
@AlwaysInline(INLINE_INITIALIZE_HEADER_INIT_REASON)
259+
public void writeWord(Pointer ptr, int offset, Word word) {
260+
ptr.writeWord(offset, word, LocationIdentity.INIT_LOCATION);
261+
}
262+
263+
@Override
264+
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
265+
@AlwaysInline(INLINE_INITIALIZE_HEADER_INIT_REASON)
266+
public void writeInt(Pointer ptr, int offset, int val) {
267+
ptr.writeInt(offset, val, LocationIdentity.INIT_LOCATION);
268+
}
269+
270+
@Override
271+
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
272+
@AlwaysInline(INLINE_INITIALIZE_HEADER_INIT_REASON)
273+
public void writeLong(Pointer ptr, int offset, long val) {
274+
ptr.writeLong(offset, val, LocationIdentity.INIT_LOCATION);
275+
}
276+
}
152277
}

0 commit comments

Comments
 (0)