Skip to content

Commit 3800481

Browse files
committed
[GR-59071] Make CGlobals layer-aware.
PullRequest: graal/21612
2 parents 2c57cba + fa98487 commit 3800481

25 files changed

+1084
-78
lines changed

substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/ObjectFile.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1805,7 +1805,7 @@ public interface Symbol {
18051805

18061806
public abstract Symbol createDefinedSymbol(String name, Element baseSection, long position, int size, boolean isCode, boolean isGlobal);
18071807

1808-
public abstract Symbol createUndefinedSymbol(String name, int size, boolean isCode);
1808+
public abstract Symbol createUndefinedSymbol(String name, boolean isCode);
18091809

18101810
protected abstract SymbolTable createSymbolTable();
18111811

substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/elf/ELFObjectFile.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ public Symbol createDefinedSymbol(String name, Element baseSection, long positio
190190
}
191191

192192
@Override
193-
public Symbol createUndefinedSymbol(String name, int size, boolean isCode) {
193+
public Symbol createUndefinedSymbol(String name, boolean isCode) {
194194
ELFSymtab symtab = createSymbolTable();
195195
return symtab.newUndefinedEntry(name, isCode);
196196
}

substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/macho/MachOObjectFile.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ public Symbol createDefinedSymbol(String name, Element baseSection, long positio
180180
}
181181

182182
@Override
183-
public Symbol createUndefinedSymbol(String name, int size, boolean isCode) {
183+
public Symbol createUndefinedSymbol(String name, boolean isCode) {
184184
MachOSymtab symtab = (MachOSymtab) getOrCreateSymbolTable();
185185
return symtab.newUndefinedEntry(name, isCode);
186186
}

substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/pecoff/PECoffObjectFile.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ public Symbol createDefinedSymbol(String name, Element baseSection, long positio
114114
}
115115

116116
@Override
117-
public Symbol createUndefinedSymbol(String name, int size, boolean isCode) {
117+
public Symbol createUndefinedSymbol(String name, boolean isCode) {
118118
PECoffSymtab st = createSymbolTable();
119119
return st.newUndefinedEntry(name, isCode);
120120
}

substratevm/src/com.oracle.svm.core.graal.llvm/src/com/oracle/svm/core/graal/llvm/LLVMNativeImageCodeCache.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,7 @@ public void patchMethods(DebugContext debug, RelocatableBuffer relocs, ObjectFil
293293
CGlobalDataInfo info = ((CGlobalDataReference) dataPatch.reference).getDataInfo();
294294
CGlobalDataImpl<?> data = info.getData();
295295
if (info.isSymbolReference() && objectFile.getOrCreateSymbolTable().getSymbol(data.symbolName) == null) {
296-
objectFile.createUndefinedSymbol(data.symbolName, 0, true);
296+
objectFile.createUndefinedSymbol(data.symbolName, true);
297297
}
298298

299299
String symbolName = (String) dataPatch.note;
@@ -319,7 +319,7 @@ public NativeTextSectionImpl getTextSectionImpl(RelocatableBuffer buffer, Object
319319
return new NativeTextSectionImpl(buffer, objectFile, codeCache) {
320320
@Override
321321
protected void defineMethodSymbol(String name, boolean global, Element section, HostedMethod method, CompilationResult result) {
322-
ObjectFile.Symbol symbol = objectFile.createUndefinedSymbol(name, 0, true);
322+
ObjectFile.Symbol symbol = objectFile.createUndefinedSymbol(name, true);
323323
if (global) {
324324
globalSymbols.add(symbol);
325325
}

substratevm/src/com.oracle.svm.core.graal.llvm/src/com/oracle/svm/core/graal/llvm/objectfile/LLVMObjectFile.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ public Symbol createDefinedSymbol(String name, Element baseSection, long positio
165165
}
166166

167167
@Override
168-
public Symbol createUndefinedSymbol(String name, int size, boolean isCode) {
168+
public Symbol createUndefinedSymbol(String name, boolean isCode) {
169169
SymbolTable symtab = getOrCreateSymbolTable();
170170
return symtab.newUndefinedEntry(name, isCode);
171171
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
/**
3232
* An object of this class represents a chunk of static global data that is located outside the heap
3333
* and can be accessed directly {@linkplain PointerBase by address}. No
34-
* {@linkplain CEntryPointOptions#prologue()} Java execution context} is required.
34+
* {@linkplain CEntryPointOptions#prologue() Java execution context} is required.
3535
*/
3636
public abstract class CGlobalData<T extends PointerBase> {
3737
/**

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

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,21 +24,38 @@
2424
*/
2525
package com.oracle.svm.core.c;
2626

27+
import java.util.EnumSet;
28+
import java.util.Optional;
2729
import java.util.function.IntSupplier;
2830
import java.util.function.Supplier;
2931

3032
import org.graalvm.nativeimage.Platform;
3133
import org.graalvm.nativeimage.Platforms;
3234
import org.graalvm.word.PointerBase;
3335

36+
import com.oracle.svm.core.graal.code.CGlobalDataInfo;
37+
38+
/**
39+
* Stores static information about a CGlobal. Build-specific information is stored in
40+
* {@link CGlobalDataInfo}. This separation of data is used to facilitate storing
41+
* {@link CGlobalDataImpl} within static fields.
42+
*/
3443
public final class CGlobalDataImpl<T extends PointerBase> extends CGlobalData<T> {
44+
3545
/**
3646
* The name of the symbol to create for this data (or null to create no symbol), or if the other
3747
* fields are null, the name of the symbol to be referenced by this instance.
3848
*/
3949
@Platforms(Platform.HOSTED_ONLY.class) //
4050
public final String symbolName;
4151

52+
/**
53+
* When a CGlobal does not have a {@link #symbolName}, when building layered images,
54+
* {@link #computeCodeLocation} is used as a unique key.
55+
*/
56+
@Platforms(Platform.HOSTED_ONLY.class) //
57+
public final StackWalker.StackFrame codeLocation;
58+
4259
@Platforms(Platform.HOSTED_ONLY.class) //
4360
public final Supplier<byte[]> bytesSupplier;
4461
@Platforms(Platform.HOSTED_ONLY.class) //
@@ -74,12 +91,38 @@ public final class CGlobalDataImpl<T extends PointerBase> extends CGlobalData<T>
7491
this(symbolName, null, null, nonConstant);
7592
}
7693

94+
@Platforms(Platform.HOSTED_ONLY.class)
95+
public boolean isSymbolReference() {
96+
return bytesSupplier == null && sizeSupplier == null;
97+
}
98+
7799
@Platforms(Platform.HOSTED_ONLY.class)
78100
private CGlobalDataImpl(String symbolName, Supplier<byte[]> bytesSupplier, IntSupplier sizeSupplier, boolean nonConstant) {
79101
assert !(bytesSupplier != null && sizeSupplier != null);
80102
this.symbolName = symbolName;
81103
this.bytesSupplier = bytesSupplier;
82104
this.sizeSupplier = sizeSupplier;
83105
this.nonConstant = nonConstant;
106+
/*
107+
* Note the uniqueness of code locations is checked in
108+
* CGlobalDataFeature#createCGlobalDataInfo.
109+
*/
110+
this.codeLocation = this.symbolName == null ? computeCodeLocation() : null;
111+
}
112+
113+
/**
114+
* A CGlobal's code location is defined to be the caller of the {@link CGlobalDataFactory} used
115+
* to create the instance.
116+
*/
117+
@Platforms(Platform.HOSTED_ONLY.class)
118+
private static StackWalker.StackFrame computeCodeLocation() {
119+
var walker = StackWalker.getInstance(EnumSet.of(StackWalker.Option.RETAIN_CLASS_REFERENCE));
120+
return walker.walk((stackStream) -> {
121+
Optional<StackWalker.StackFrame> result = stackStream.filter(stackFrame -> {
122+
var declaringClass = stackFrame.getDeclaringClass();
123+
return declaringClass != CGlobalDataImpl.class && declaringClass != CGlobalDataFactory.class;
124+
}).findFirst();
125+
return result.get();
126+
});
84127
}
85128
}

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

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,6 @@
2424
*/
2525
package com.oracle.svm.core.c;
2626

27-
import java.util.concurrent.locks.Lock;
28-
import java.util.concurrent.locks.ReentrantLock;
29-
3027
import org.graalvm.collections.EconomicMap;
3128
import org.graalvm.collections.Equivalence;
3229
import org.graalvm.nativeimage.Platform;
@@ -45,9 +42,6 @@ public class CGlobalDataNonConstantRegistry {
4542

4643
private final EconomicMap<CGlobalDataImpl<?>, CGlobalDataInfo> cGlobalDataInfos = ImageHeapMap.create(Equivalence.IDENTITY, "cGlobalDataInfos");
4744

48-
@Platforms(Platform.HOSTED_ONLY.class) //
49-
private final Lock lock = new ReentrantLock();
50-
5145
/**
5246
* Invoked at runtime via com.oracle.svm.hosted.c.CGlobalDataFeature#getCGlobalDataInfoMethod.
5347
*/
@@ -62,11 +56,10 @@ public CGlobalDataInfo getCGlobalDataInfo(CGlobalDataImpl<?> cGlobalData) {
6256

6357
@Platforms(Platform.HOSTED_ONLY.class)
6458
public void registerNonConstantSymbol(CGlobalDataInfo cGlobalDataInfo) {
65-
lock.lock();
66-
try {
67-
cGlobalDataInfos.put(cGlobalDataInfo.getData(), cGlobalDataInfo);
68-
} finally {
69-
lock.unlock();
70-
}
59+
/*
60+
* Note at build time ImageHeapMaps are backed by a concurrent hash map, so this code is
61+
* thread safe.
62+
*/
63+
cGlobalDataInfos.put(cGlobalDataInfo.getData(), cGlobalDataInfo);
7164
}
7265
}

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/code/CGlobalDataInfo.java

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,11 @@
3737
import com.oracle.svm.core.heap.UnknownPrimitiveField;
3838
import com.oracle.svm.core.util.VMError;
3939

40+
/**
41+
* Stores build-specific information about a CGlobal. Static information is stored in
42+
* {@link CGlobalDataImpl}. This separation of data is used to facilitate storing
43+
* {@link CGlobalDataImpl} within static fields.
44+
*/
4045
public final class CGlobalDataInfo {
4146
/**
4247
* Image heap object storing the base address of CGlobalData memory using a relocation. Before
@@ -47,7 +52,15 @@ public final class CGlobalDataInfo {
4752
private final CGlobalDataImpl<?> data;
4853
private final boolean isSymbolReference;
4954

55+
/**
56+
* Denotes whether this CGlobal has been defined as a global in a prior layer. This also implies
57+
* in a prior layer that the CGlobal was not a symbol reference.
58+
*/
59+
@Platforms(Platform.HOSTED_ONLY.class) private final boolean definedAsGlobalInPriorLayer;
60+
61+
/** See CGlobalDataFeature#registerWithGlobalSymbol. */
5062
@UnknownPrimitiveField(availability = AfterHostedUniverse.class) private boolean isGlobalSymbol;
63+
/** See CGlobalDataFeature#registerWithGlobalHiddenSymbol. */
5164
@UnknownPrimitiveField(availability = AfterHostedUniverse.class) private boolean isHiddenSymbol;
5265
@UnknownPrimitiveField(availability = AfterHeapLayout.class) private int offset = -1;
5366
@UnknownPrimitiveField(availability = AfterHeapLayout.class) private int size = -1;
@@ -56,11 +69,12 @@ public final class CGlobalDataInfo {
5669
@Platforms(HOSTED_ONLY.class) private byte[] bytes;
5770

5871
@Platforms(Platform.HOSTED_ONLY.class)
59-
public CGlobalDataInfo(CGlobalDataImpl<?> data) {
72+
public CGlobalDataInfo(CGlobalDataImpl<?> data, boolean definedAsGlobalInPriorLayer) {
6073
assert data != null;
6174
this.data = data;
62-
this.isSymbolReference = (data.bytesSupplier == null && data.sizeSupplier == null);
75+
this.isSymbolReference = data.isSymbolReference();
6376
assert !this.isSymbolReference || data.symbolName != null;
77+
this.definedAsGlobalInPriorLayer = definedAsGlobalInPriorLayer;
6478
}
6579

6680
public CGlobalDataImpl<?> getData() {
@@ -100,7 +114,16 @@ public int getSize() {
100114
}
101115

102116
public void makeGlobalSymbol() {
103-
VMError.guarantee(!isSymbolReference && data.symbolName != null, "Cannot change the local/global status of a symbol reference");
117+
if (isSymbolReference) {
118+
/*
119+
* Only CGlobals assigned to global data chunks allocated by native image can be defined
120+
* as global symbols. If the symbol was defined as a global symbol in a prior layer,
121+
* this request is a no-op.
122+
*/
123+
VMError.guarantee(definedAsGlobalInPriorLayer, "Cannot change the local/global status of a symbol reference %s", data.symbolName);
124+
return;
125+
}
126+
VMError.guarantee(data.symbolName != null, "No symbol name associated with data reference");
104127
isGlobalSymbol = true;
105128
}
106129

0 commit comments

Comments
 (0)