Skip to content

Commit e2821cb

Browse files
committed
Eliminate relocation entries for base layer vtables with RelativeCodePointers.
1 parent cafeed1 commit e2821cb

File tree

21 files changed

+417
-153
lines changed

21 files changed

+417
-153
lines changed

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/nodes/CountTrailingZerosNode.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,4 +98,7 @@ public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) {
9898
public void generate(NodeLIRBuilderTool builder, ArithmeticLIRGeneratorTool gen) {
9999
builder.setResult(this, gen.emitCountTrailingZeros(builder.operand(getValue())));
100100
}
101+
102+
@NodeIntrinsic
103+
public static native int countLongTrailingZeros(long value);
101104
}

substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/linux/LinuxImageHeapProvider.java

Lines changed: 79 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import static com.oracle.svm.core.Isolates.IMAGE_HEAP_WRITABLE_END;
3434
import static com.oracle.svm.core.Isolates.IMAGE_HEAP_WRITABLE_PATCHED_BEGIN;
3535
import static com.oracle.svm.core.Isolates.IMAGE_HEAP_WRITABLE_PATCHED_END;
36+
import static com.oracle.svm.core.imagelayer.ImageLayerSection.SectionEntries.CODE_START;
3637
import static com.oracle.svm.core.imagelayer.ImageLayerSection.SectionEntries.HEAP_BEGIN;
3738
import static com.oracle.svm.core.imagelayer.ImageLayerSection.SectionEntries.HEAP_END;
3839
import static com.oracle.svm.core.imagelayer.ImageLayerSection.SectionEntries.HEAP_RELOCATABLE_BEGIN;
@@ -42,11 +43,13 @@
4243
import static com.oracle.svm.core.imagelayer.ImageLayerSection.SectionEntries.HEAP_WRITEABLE_PATCHED_BEGIN;
4344
import static com.oracle.svm.core.imagelayer.ImageLayerSection.SectionEntries.HEAP_WRITEABLE_PATCHED_END;
4445
import static com.oracle.svm.core.imagelayer.ImageLayerSection.SectionEntries.NEXT_SECTION;
46+
import static com.oracle.svm.core.imagelayer.ImageLayerSection.SectionEntries.VARIABLY_SIZED_DATA;
4547
import static com.oracle.svm.core.posix.linux.ProcFSSupport.findMapping;
4648
import static com.oracle.svm.core.util.PointerUtils.roundDown;
4749
import static com.oracle.svm.core.util.UnsignedUtils.isAMultiple;
4850
import static com.oracle.svm.core.util.UnsignedUtils.roundUp;
4951
import static jdk.graal.compiler.word.Word.signed;
52+
import static jdk.graal.compiler.word.Word.unsigned;
5053

5154
import java.util.concurrent.ThreadLocalRandom;
5255

@@ -84,6 +87,7 @@
8487

8588
import jdk.graal.compiler.nodes.NamedLocationIdentity;
8689
import jdk.graal.compiler.nodes.PauseNode;
90+
import jdk.graal.compiler.replacements.nodes.CountTrailingZerosNode;
8791
import jdk.graal.compiler.word.Word;
8892

8993
/**
@@ -241,28 +245,91 @@ public static void patchLayeredImageHeap() {
241245
return;
242246
}
243247

244-
Pointer currentSection = ImageLayerSection.getInitialLayerSection().get();
245-
Word heapBegin = currentSection.readWord(ImageLayerSection.getEntryOffset(HEAP_BEGIN));
248+
Pointer layerSection = ImageLayerSection.getInitialLayerSection().get();
249+
Pointer initialLayerImageHeap = layerSection.readWord(ImageLayerSection.getEntryOffset(HEAP_BEGIN));
250+
Pointer codeBase = layerSection.readWord(ImageLayerSection.getEntryOffset(CODE_START));
251+
252+
int referenceSize = ConfigurationValues.getObjectLayout().getReferenceSize();
253+
while (layerSection.isNonNull()) {
254+
Pointer data = layerSection.add(ImageLayerSection.getEntryOffset(VARIABLY_SIZED_DATA));
255+
int offset = 0;
256+
257+
// Skip singletons table
258+
long singletonTableEntryCount = data.readLong(offset);
259+
UnsignedWord singletonTableAlignedSize = roundUp(unsigned(singletonTableEntryCount * referenceSize), unsigned(Long.BYTES));
260+
offset += Long.BYTES + (int) singletonTableAlignedSize.rawValue();
261+
262+
Pointer layerHeapRelocs = layerSection.readWord(ImageLayerSection.getEntryOffset(HEAP_RELOCATABLE_BEGIN));
263+
Pointer layerCode = layerSection.readWord(ImageLayerSection.getEntryOffset(CODE_START));
264+
Word layerCodeOffsetToBase = (Word) layerCode.subtract(codeBase);
265+
offset = applyLayerCodePointerPatches(data, offset, layerHeapRelocs, layerCodeOffsetToBase);
266+
267+
Word negativeCodeBase = Word.<Word> zero().subtract(codeBase);
268+
offset = applyLayerCodePointerPatches(data, offset, layerHeapRelocs, negativeCodeBase);
269+
270+
applyLayerImageHeapRefPatches(data.add(offset), initialLayerImageHeap);
271+
272+
layerSection = layerSection.readWord(ImageLayerSection.getEntryOffset(NEXT_SECTION));
273+
}
274+
275+
heapPatchStateAddr.writeWordVolatile(0, ImageHeapPatchingState.SUCCESSFUL);
276+
}
246277

247-
Word patches = ImageLayerSection.getHeapRelativeRelocationsStart().get();
248-
int endOffset = Integer.BYTES + (patches.readInt(0) * Integer.BYTES);
278+
@Uninterruptible(reason = "Thread state not yet set up.")
279+
private static int applyLayerCodePointerPatches(Pointer data, int startOffset, Pointer layerHeapRelocs, Word addend) {
280+
int wordSize = ConfigurationValues.getTarget().wordSize;
281+
282+
int offset = startOffset;
283+
int bitmapWordCount = (int) data.readLong(offset);
284+
offset += Long.BYTES;
285+
if (addend.equal(0)) {
286+
offset += bitmapWordCount * Long.BYTES;
287+
return offset;
288+
}
249289

290+
for (int i = 0; i < bitmapWordCount; i++) {
291+
long bits = data.readLong(offset);
292+
offset += Long.BYTES;
293+
int j = 0; // index of a 1-bit
294+
while (bits != 0) {
295+
int ntz = CountTrailingZerosNode.countLongTrailingZeros(bits);
296+
j += ntz;
297+
298+
int at = (i * 64 + j) * wordSize;
299+
Word w = layerHeapRelocs.readWord(at);
300+
w = w.add(addend);
301+
layerHeapRelocs.writeWord(at, w);
302+
303+
/*
304+
* Note that we must not shift by ntz+1 here because it can be 64, and according to
305+
* the Java Language Specification, 15.19. Shift Operators: If the promoted type of
306+
* the left-hand operand is long, then only the six lowest-order bits of the
307+
* right-hand operand are used as the shift distance. [..] The shift distance
308+
* actually used is therefore always in the range 0 to 63, inclusive.
309+
*/
310+
bits = (bits >>> ntz) >>> 1;
311+
j++;
312+
}
313+
}
314+
return offset;
315+
}
316+
317+
@Uninterruptible(reason = "Thread state not yet set up.")
318+
private static void applyLayerImageHeapRefPatches(Pointer patches, Pointer layerImageHeap) {
250319
int referenceSize = ConfigurationValues.getObjectLayout().getReferenceSize();
251-
int offset = Integer.BYTES;
320+
int count = (int) patches.readLong(0);
321+
int offset = Long.BYTES;
322+
int endOffset = offset + count * Integer.BYTES;
252323
while (offset < endOffset) {
253324
int heapOffset = patches.readInt(offset);
254325
int referenceEncoding = patches.readInt(offset + Integer.BYTES);
255-
326+
offset += 2 * Integer.BYTES;
256327
if (referenceSize == 4) {
257-
heapBegin.writeInt(heapOffset, referenceEncoding);
328+
layerImageHeap.writeInt(heapOffset, referenceEncoding);
258329
} else {
259-
heapBegin.writeLong(heapOffset, referenceEncoding);
330+
layerImageHeap.writeLong(heapOffset, referenceEncoding);
260331
}
261-
262-
offset += 2 * Integer.BYTES;
263332
}
264-
265-
heapPatchStateAddr.writeWordVolatile(0, ImageHeapPatchingState.SUCCESSFUL);
266333
}
267334

268335
@Override

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateOptions.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1523,6 +1523,7 @@ public static boolean printClosedArenaUponThrow() {
15231523
}
15241524

15251525
@Option(help = "Avoid linker relocations for code and instead emit address computations.", type = OptionType.Expert) //
1526+
@LayerVerifiedOption(severity = Severity.Error, kind = Kind.Changed, positional = false) //
15261527
public static final HostedOptionKey<Boolean> RelativeCodePointers = new HostedOptionKey<>(false, SubstrateOptions::validateRelativeCodePointers);
15271528

15281529
@Fold

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

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,9 +83,10 @@
8383
import com.oracle.svm.core.heap.ReferenceHandlerThread;
8484
import com.oracle.svm.core.heap.ReferenceInternals;
8585
import com.oracle.svm.core.heap.RestrictHeapAccess;
86+
import com.oracle.svm.core.imagelayer.ImageLayerBuildingSupport;
87+
import com.oracle.svm.core.imagelayer.ImageLayerSection;
8688
import com.oracle.svm.core.jdk.PlatformNativeLibrarySupport;
8789
import com.oracle.svm.core.jdk.RuntimeSupport;
88-
import com.oracle.svm.core.layeredimagesingleton.MultiLayeredImageSingleton;
8990
import com.oracle.svm.core.log.Log;
9091
import com.oracle.svm.core.option.RuntimeOptionParser;
9192
import com.oracle.svm.core.os.CommittedMemoryProvider;
@@ -208,8 +209,16 @@ private static void setHeapBase(PointerBase heapBase) {
208209
@Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE)
209210
@NeverInline("Heap base register is set in caller, prevent reads from floating before that.")
210211
private static void initCodeBase() {
211-
ImageCodeInfo imageCodeInfo = MultiLayeredImageSingleton.getForLayer(ImageCodeInfo.class, MultiLayeredImageSingleton.INITIAL_LAYER_NUMBER);
212-
CodePointer codeBase = imageCodeInfo.getCodeStart();
212+
CodePointer codeBase;
213+
if (ImageLayerBuildingSupport.buildingImageLayer()) {
214+
/* Layered ImageSingleton handling is not ready yet at this point. */
215+
Pointer initialLayerSection = ImageLayerSection.getInitialLayerSection().get();
216+
int codeStartEntry = ImageLayerSection.getEntryOffset(ImageLayerSection.SectionEntries.CODE_START);
217+
codeBase = initialLayerSection.readWord(codeStartEntry);
218+
} else {
219+
ImageCodeInfo imageCodeInfo = ImageSingletons.lookup(ImageCodeInfo.class);
220+
codeBase = imageCodeInfo.getCodeStart();
221+
}
213222
writeCurrentVMCodeBase(codeBase);
214223
}
215224

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/imagelayer/ImageLayerSection.java

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -32,24 +32,20 @@
3232
import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingleton;
3333

3434
import jdk.graal.compiler.api.replacements.Fold;
35-
import jdk.graal.compiler.word.Word;
3635

3736
public abstract class ImageLayerSection implements LayeredImageSingleton {
3837

3938
protected final CGlobalData<Pointer> initialSectionStart;
4039
protected final CGlobalData<WordPointer> cachedImageFDs;
4140
protected final CGlobalData<WordPointer> cachedImageHeapOffsets;
4241
protected final CGlobalData<WordPointer> cachedImageHeapRelocations;
43-
protected final CGlobalData<Word> heapRelativeRelocations;
4442

4543
protected ImageLayerSection(CGlobalData<Pointer> initialSectionStart, CGlobalData<WordPointer> cachedImageFDs, CGlobalData<WordPointer> cachedImageHeapOffsets,
46-
CGlobalData<WordPointer> cachedImageHeapRelocations,
47-
CGlobalData<Word> heapRelativeRelocations) {
44+
CGlobalData<WordPointer> cachedImageHeapRelocations) {
4845
this.initialSectionStart = initialSectionStart;
4946
this.cachedImageFDs = cachedImageFDs;
5047
this.cachedImageHeapOffsets = cachedImageHeapOffsets;
5148
this.cachedImageHeapRelocations = cachedImageHeapRelocations;
52-
this.heapRelativeRelocations = heapRelativeRelocations;
5349
}
5450

5551
public enum SectionEntries {
@@ -61,7 +57,10 @@ public enum SectionEntries {
6157
HEAP_WRITEABLE_END,
6258
HEAP_WRITEABLE_PATCHED_BEGIN,
6359
HEAP_WRITEABLE_PATCHED_END,
64-
NEXT_SECTION
60+
CODE_START,
61+
NEXT_SECTION,
62+
VARIABLY_SIZED_DATA,
63+
FIRST_SINGLETON,
6564
}
6665

6766
private static ImageLayerSection singleton() {
@@ -93,11 +92,6 @@ public static CGlobalData<WordPointer> getCachedImageHeapRelocations() {
9392
return singleton().cachedImageHeapRelocations;
9493
}
9594

96-
@Fold
97-
public static CGlobalData<Word> getHeapRelativeRelocationsStart() {
98-
return singleton().heapRelativeRelocations;
99-
}
100-
10195
protected abstract int getEntryOffsetInternal(SectionEntries entry);
10296

10397
}

substratevm/src/com.oracle.svm.hosted/resources/SharedLayerSnapshotCapnProtoSchema.capnp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,7 @@ struct ConstantReference {
168168
}
169169
cEntryPointLiteralCodePointer @5 :CEntryPointLiteralReference;
170170
cGlobalDataBasePointer @6 :Void;
171+
methodOffset @7 :Void;
171172
}
172173
}
173174

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/MethodPointerRelocationProvider.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,9 @@
3030
import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature;
3131
import com.oracle.svm.core.feature.InternalFeature;
3232
import com.oracle.svm.core.imagelayer.ImageLayerBuildingSupport;
33+
import com.oracle.svm.core.meta.MethodOffset;
3334
import com.oracle.svm.core.meta.MethodPointer;
35+
import com.oracle.svm.core.util.VMError;
3436
import com.oracle.svm.hosted.imagelayer.LayeredDispatchTableFeature;
3537
import com.oracle.svm.hosted.meta.HostedMethod;
3638

@@ -52,6 +54,20 @@ public void markMethodPointerRelocation(ObjectFile.ProgbitsSectionImpl section,
5254
}
5355
section.markRelocationSite(offset, relocationKind, symbolName, addend);
5456
}
57+
58+
public void markMethodOffsetRelocation(ObjectFile.ProgbitsSectionImpl section, int offset, ObjectFile.RelocationKind relocationKind, HostedMethod target,
59+
long addend, MethodOffset methodOffset, boolean isInjectedNotCompiled) {
60+
if (!imageLayer || !isInjectedNotCompiled) {
61+
throw VMError.shouldNotReachHere("must be written to image heap without relocation");
62+
}
63+
64+
/*
65+
* Add a relocation entry that will be resolved to the absolute address for the symbol. At
66+
* runtime, we recompute this address ourselves to become relative to the code base.
67+
*/
68+
String symbolName = LayeredDispatchTableFeature.singleton().getSymbolName(methodOffset, target, isInjectedNotCompiled);
69+
section.markRelocationSite(offset, relocationKind, symbolName, addend);
70+
}
5571
}
5672

5773
@AutomaticallyRegisteredFeature

0 commit comments

Comments
 (0)