Skip to content

Commit 8867b8e

Browse files
Add SymbolsSupport and SymbolsFeature
1 parent b098b68 commit 8867b8e

File tree

8 files changed

+164
-39
lines changed

8 files changed

+164
-39
lines changed

espresso-shared/src/com.oracle.truffle.espresso.classfile/src/com/oracle/truffle/espresso/classfile/descriptors/SignatureSymbols.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ public TypeSymbols getTypes() {
140140
* @return Array of Type symbols representing parameter types followed by return type
141141
*/
142142
public Symbol<Type>[] parsed(Symbol<Signature> signature) {
143-
return parse(SignatureSymbols.this.getTypes(), signature, 0);
143+
return parse(SignatureSymbols.this.getTypes(), signature);
144144
}
145145

146146
/**
@@ -186,12 +186,12 @@ private static Symbol<Type> toBasic(Symbol<Type> type) {
186186
* @throws ParserException.ClassFormatError if {the signature is not well-formed
187187
*/
188188
@SuppressWarnings({"rawtypes", "unchecked"})
189-
static Symbol<Type>[] parse(TypeSymbols typeSymbols, Symbol<Signature> signature, int startIndex) throws ParserException.ClassFormatError {
190-
if ((startIndex > signature.length() - 3) || signature.byteAt(startIndex) != '(') {
189+
public static Symbol<Type>[] parse(TypeSymbols typeSymbols, Symbol<Signature> signature) throws ParserException.ClassFormatError {
190+
if ((signature.length() < 3) || signature.byteAt(0) != '(') {
191191
throw new ParserException.ClassFormatError("Invalid method signature: " + signature);
192192
}
193193
final List<Symbol<Type>> buf = new ArrayList<>();
194-
int i = startIndex + 1;
194+
int i = 1;
195195
while (signature.byteAt(i) != ')') {
196196
final Symbol<Type> descriptor = typeSymbols.parse(signature, i, true);
197197
buf.add(descriptor);

substratevm/mx.substratevm/mx_substratevm.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1626,7 +1626,7 @@ def prevent_build_path_in_libgraal():
16261626
use_modules='image',
16271627
jar_distributions=['substratevm:SVM_JDWP_SERVER'],
16281628
build_args=libsvmjdwp_build_args + [
1629-
'--features=com.oracle.svm.jdwp.server.ServerJDWPFeature',
1629+
'--features=com.oracle.svm.jdwp.server.ServerJDWPFeature,com.oracle.svm.hosted.SymbolsFeature',
16301630
],
16311631
headers=False,
16321632
)

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/registry/AbstractClassRegistry.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ public final Class<?> findLoadedClass(Symbol<Type> name) {
8888
@Platforms(Platform.HOSTED_ONLY.class)
8989
public final void addAOTType(Class<?> cls) {
9090
assert !cls.isArray() && !cls.isPrimitive();
91-
TypeSymbols types = ClassRegistries.singleton().getTypes();
91+
TypeSymbols types = SymbolsSupport.getTypes();
9292
ByteSequence typeBytes = ByteSequence.createTypeFromName(cls.getName());
9393
Symbol<Type> key = types.getOrCreateValidType(typeBytes, true);
9494
assert key != null : typeBytes;

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/registry/ClassRegistries.java

Lines changed: 6 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -53,13 +53,9 @@
5353
import com.oracle.svm.espresso.classfile.descriptors.ByteSequence;
5454
import com.oracle.svm.espresso.classfile.descriptors.ModifiedUTF8;
5555
import com.oracle.svm.espresso.classfile.descriptors.Name;
56-
import com.oracle.svm.espresso.classfile.descriptors.NameSymbols;
57-
import com.oracle.svm.espresso.classfile.descriptors.ParserSymbols;
5856
import com.oracle.svm.espresso.classfile.descriptors.Symbol;
59-
import com.oracle.svm.espresso.classfile.descriptors.Symbols;
6057
import com.oracle.svm.espresso.classfile.descriptors.Type;
6158
import com.oracle.svm.espresso.classfile.descriptors.TypeSymbols;
62-
import com.oracle.svm.espresso.classfile.descriptors.Utf8Symbols;
6359
import com.oracle.svm.espresso.classfile.perf.TimerCollection;
6460
import com.oracle.svm.util.ReflectionUtil;
6561

@@ -92,9 +88,6 @@ public final class ClassRegistries implements ParsingContext {
9288
@Platforms(Platform.HOSTED_ONLY.class)//
9389
private final ConcurrentHashMap<ClassLoader, AbstractClassRegistry> buildTimeRegistries;
9490

95-
private final Utf8Symbols utf8;
96-
private final NameSymbols names;
97-
private final TypeSymbols types;
9891
private final AbstractClassRegistry bootRegistry;
9992
private final EconomicMap<String, String> bootPackageToModule;
10093

@@ -105,13 +98,6 @@ public ClassRegistries() {
10598
} else {
10699
bootRegistry = new AOTClassRegistry(null);
107100
}
108-
ParserSymbols.ensureInitialized();
109-
int initialSymbolTableCapacity = 4 * 1024;
110-
Symbols symbols = Symbols.fromExisting(ParserSymbols.SYMBOLS.freeze(), initialSymbolTableCapacity, 0);
111-
// let this resize when first used at runtime
112-
utf8 = new Utf8Symbols(symbols);
113-
names = new NameSymbols(symbols);
114-
types = new TypeSymbols(symbols);
115101
buildTimeRegistries = new ConcurrentHashMap<>();
116102
bootPackageToModule = computeBootPackageToModuleMap();
117103
}
@@ -149,10 +135,6 @@ public static String[] getSystemPackageNames() {
149135
return result;
150136
}
151137

152-
TypeSymbols getTypes() {
153-
return types;
154-
}
155-
156138
public static Class<?> findBootstrapClass(String name) {
157139
try {
158140
return singleton().resolve(name, null);
@@ -167,7 +149,7 @@ public static Class<?> findLoadedClass(String name, ClassLoader loader) {
167149
return null;
168150
}
169151
ByteSequence typeBytes = ByteSequence.createTypeFromName(name);
170-
Symbol<Type> type = singleton().getTypes().lookupValidType(typeBytes);
152+
Symbol<Type> type = SymbolsSupport.getTypes().lookupValidType(typeBytes);
171153
Class<?> result = null;
172154
if (type != null) {
173155
result = singleton().getRegistry(loader).findLoadedClass(type);
@@ -285,7 +267,7 @@ private Class<?> resolveInstanceType(String name, ClassLoader loader) throws Cla
285267
}
286268

287269
private Class<?> resolveInstanceType(ClassLoader loader, ByteSequence elementalType) throws ClassNotFoundException {
288-
Symbol<Type> type = getTypes().getOrCreateValidType(elementalType);
270+
Symbol<Type> type = SymbolsSupport.getTypes().getOrCreateValidType(elementalType);
289271
if (type == null) {
290272
return null;
291273
}
@@ -321,7 +303,7 @@ public static Class<?> defineClass(ClassLoader loader, String name, byte[] b, in
321303
throw sneakyThrow(new ClassNotFoundException(name));
322304
}
323305
ByteSequence typeBytes = ByteSequence.createTypeFromName(name);
324-
Symbol<Type> type = singleton().getTypes().getOrCreateValidType(typeBytes);
306+
Symbol<Type> type = SymbolsSupport.getTypes().getOrCreateValidType(typeBytes);
325307
if (type == null) {
326308
throw new NoClassDefFoundError(name);
327309
}
@@ -439,17 +421,17 @@ public Logger getLogger() {
439421

440422
@Override
441423
public Symbol<Name> getOrCreateName(ByteSequence byteSequence) {
442-
return ClassRegistries.singleton().names.getOrCreate(byteSequence);
424+
return SymbolsSupport.getNames().getOrCreate(byteSequence);
443425
}
444426

445427
@Override
446428
public Symbol<Type> getOrCreateTypeFromName(ByteSequence byteSequence) {
447-
return ClassRegistries.singleton().getTypes().getOrCreateValidType(TypeSymbols.nameToType(byteSequence));
429+
return SymbolsSupport.getTypes().getOrCreateValidType(TypeSymbols.nameToType(byteSequence));
448430
}
449431

450432
@Override
451433
public Symbol<? extends ModifiedUTF8> getOrCreateUtf8(ByteSequence byteSequence) {
452434
// Note: all symbols are strong for now
453-
return ClassRegistries.singleton().utf8.getOrCreateValidUtf8(byteSequence, true);
435+
return SymbolsSupport.getUtf8().getOrCreateValidUtf8(byteSequence, true);
454436
}
455437
}
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
/*
2+
* Copyright (c) 2025, 2025, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation. Oracle designates this
8+
* particular file as subject to the "Classpath" exception as provided
9+
* by Oracle in the LICENSE file that accompanied this code.
10+
*
11+
* This code is distributed in the hope that it will be useful, but WITHOUT
12+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
* version 2 for more details (a copy is included in the LICENSE file that
15+
* accompanied this code).
16+
*
17+
* You should have received a copy of the GNU General Public License version
18+
* 2 along with this work; if not, write to the Free Software Foundation,
19+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+
*
21+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+
* or visit www.oracle.com if you need additional information or have any
23+
* questions.
24+
*/
25+
package com.oracle.svm.core.hub.registry;
26+
27+
import org.graalvm.nativeimage.ImageInfo;
28+
import org.graalvm.nativeimage.ImageSingletons;
29+
import org.graalvm.nativeimage.Platform;
30+
import org.graalvm.nativeimage.Platforms;
31+
32+
import com.oracle.svm.espresso.classfile.descriptors.NameSymbols;
33+
import com.oracle.svm.espresso.classfile.descriptors.ParserSymbols;
34+
import com.oracle.svm.espresso.classfile.descriptors.SignatureSymbols;
35+
import com.oracle.svm.espresso.classfile.descriptors.Symbols;
36+
import com.oracle.svm.espresso.classfile.descriptors.TypeSymbols;
37+
import com.oracle.svm.espresso.classfile.descriptors.Utf8Symbols;
38+
39+
import jdk.graal.compiler.api.replacements.Fold;
40+
41+
public final class SymbolsSupport {
42+
@Platforms(Platform.HOSTED_ONLY.class) //
43+
private static final SymbolsSupport TEST_SINGLETON = ImageInfo.inImageCode() ? null : new SymbolsSupport();
44+
45+
private final Utf8Symbols utf8;
46+
private final NameSymbols names;
47+
private final TypeSymbols types;
48+
private final SignatureSymbols signatures;
49+
50+
@Platforms(Platform.HOSTED_ONLY.class)
51+
public SymbolsSupport() {
52+
ParserSymbols.ensureInitialized();
53+
int initialSymbolTableCapacity = 4 * 1024;
54+
Symbols symbols = Symbols.fromExisting(ParserSymbols.SYMBOLS.freeze(), initialSymbolTableCapacity, 0);
55+
// let this resize when first used at runtime
56+
utf8 = new Utf8Symbols(symbols);
57+
names = new NameSymbols(symbols);
58+
types = new TypeSymbols(symbols);
59+
signatures = new SignatureSymbols(symbols, types);
60+
}
61+
62+
public static TypeSymbols getTypes() {
63+
return singleton().types;
64+
}
65+
66+
public static SignatureSymbols getSignatures() {
67+
return singleton().signatures;
68+
}
69+
70+
public static NameSymbols getNames() {
71+
return singleton().names;
72+
}
73+
74+
public static Utf8Symbols getUtf8() {
75+
return singleton().utf8;
76+
}
77+
78+
@Fold
79+
public static SymbolsSupport singleton() {
80+
if (TEST_SINGLETON != null) {
81+
/*
82+
* Some unit tests use com.oracle.svm.interpreter.metadata outside the context of
83+
* native-image.
84+
*/
85+
assert !ImageInfo.inImageCode();
86+
return TEST_SINGLETON;
87+
}
88+
return ImageSingletons.lookup(SymbolsSupport.class);
89+
}
90+
}

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ClassRegistryFeature.java

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,14 @@
2424
*/
2525
package com.oracle.svm.hosted;
2626

27-
import java.lang.reflect.Field;
27+
import java.util.List;
2828

2929
import org.graalvm.nativeimage.ImageSingletons;
30+
import org.graalvm.nativeimage.hosted.Feature;
3031
import org.graalvm.nativeimage.impl.RuntimeClassInitializationSupport;
3132

3233
import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature;
3334
import com.oracle.svm.core.feature.InternalFeature;
34-
import com.oracle.svm.core.fieldvaluetransformer.NewInstanceFieldValueTransformer;
3535
import com.oracle.svm.core.hub.ClassForNameSupport;
3636
import com.oracle.svm.core.hub.RuntimeClassLoading;
3737
import com.oracle.svm.core.hub.registry.ClassRegistries;
@@ -43,6 +43,11 @@ public boolean isInConfiguration(IsInConfigurationAccess access) {
4343
return ClassForNameSupport.respectClassLoader();
4444
}
4545

46+
@Override
47+
public List<Class<? extends Feature>> getRequiredFeatures() {
48+
return List.of(SymbolsFeature.class);
49+
}
50+
4651
@Override
4752
public void afterRegistration(AfterRegistrationAccess access) {
4853
ImageSingletons.lookup(RuntimeClassInitializationSupport.class).initializeAtBuildTime("com.oracle.svm.espresso.classfile",
@@ -53,12 +58,6 @@ public void afterRegistration(AfterRegistrationAccess access) {
5358
public void beforeAnalysis(BeforeAnalysisAccess a) {
5459
FeatureImpl.BeforeAnalysisAccessImpl access = (FeatureImpl.BeforeAnalysisAccessImpl) a;
5560
access.registerSubtypeReachabilityHandler((unused, cls) -> onTypeReachable(cls), Object.class);
56-
/*
57-
* This works around issues when analysis concurrently scans the readWriteLock in
58-
* SymbolsImpl and might add a Thread to the image heap. It could be generalized (GR-62530).
59-
*/
60-
Field readWriteLockField = access.findField("com.oracle.svm.espresso.classfile.descriptors.SymbolsImpl", "readWriteLock");
61-
access.registerFieldValueTransformer(readWriteLockField, new NewInstanceFieldValueTransformer());
6261
}
6362

6463
private static void onTypeReachable(Class<?> cls) {
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
* Copyright (c) 2025, 2025, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation. Oracle designates this
8+
* particular file as subject to the "Classpath" exception as provided
9+
* by Oracle in the LICENSE file that accompanied this code.
10+
*
11+
* This code is distributed in the hope that it will be useful, but WITHOUT
12+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
* version 2 for more details (a copy is included in the LICENSE file that
15+
* accompanied this code).
16+
*
17+
* You should have received a copy of the GNU General Public License version
18+
* 2 along with this work; if not, write to the Free Software Foundation,
19+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+
*
21+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+
* or visit www.oracle.com if you need additional information or have any
23+
* questions.
24+
*/
25+
package com.oracle.svm.hosted;
26+
27+
import java.lang.reflect.Field;
28+
29+
import org.graalvm.nativeimage.ImageSingletons;
30+
31+
import com.oracle.svm.core.feature.InternalFeature;
32+
import com.oracle.svm.core.fieldvaluetransformer.NewInstanceFieldValueTransformer;
33+
import com.oracle.svm.core.hub.registry.SymbolsSupport;
34+
35+
public class SymbolsFeature implements InternalFeature {
36+
37+
@Override
38+
public void afterRegistration(AfterRegistrationAccess access) {
39+
ImageSingletons.add(SymbolsSupport.class, new SymbolsSupport());
40+
}
41+
42+
@Override
43+
public void beforeAnalysis(BeforeAnalysisAccess a) {
44+
FeatureImpl.BeforeAnalysisAccessImpl access = (FeatureImpl.BeforeAnalysisAccessImpl) a;
45+
/*
46+
* This works around issues when analysis concurrently scans the readWriteLock in
47+
* SymbolsImpl and might add a Thread to the image heap. It could be generalized (GR-62530).
48+
*/
49+
Field readWriteLockField = access.findField("com.oracle.svm.espresso.classfile.descriptors.SymbolsImpl", "readWriteLock");
50+
access.registerFieldValueTransformer(readWriteLockField, new NewInstanceFieldValueTransformer());
51+
}
52+
}

substratevm/src/com.oracle.svm.interpreter/src/com/oracle/svm/interpreter/DebuggerFeature.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@
7777
import com.oracle.svm.graal.hosted.DeoptimizationFeature;
7878
import com.oracle.svm.hosted.FeatureImpl;
7979
import com.oracle.svm.hosted.NativeImageGenerator;
80+
import com.oracle.svm.hosted.SymbolsFeature;
8081
import com.oracle.svm.hosted.code.CompileQueue;
8182
import com.oracle.svm.hosted.code.SubstrateCompilationDirectives;
8283
import com.oracle.svm.hosted.image.NativeImageHeap;
@@ -151,7 +152,8 @@ public List<Class<? extends Feature>> getRequiredFeatures() {
151152
return Arrays.asList(
152153
DeoptimizationFeature.class,
153154
InterpreterFeature.class,
154-
IdentityMethodAddressResolverFeature.class);
155+
IdentityMethodAddressResolverFeature.class,
156+
SymbolsFeature.class);
155157
}
156158

157159
private static Class<?> getArgumentClass(GraphBuilderContext b, ResolvedJavaMethod targetMethod, int parameterIndex, ValueNode arg) {

0 commit comments

Comments
 (0)