Skip to content

Commit 0465567

Browse files
committed
[GR-60068] Crema: Inject interpreter execution via vTable stubs
PullRequest: graal/20165
2 parents cc2f0ca + 6711d81 commit 0465567

File tree

8 files changed

+151
-52
lines changed

8 files changed

+151
-52
lines changed

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/CremaSupport.java

+4
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,12 @@
2424
*/
2525
package com.oracle.svm.core.hub;
2626

27+
import org.graalvm.nativeimage.Platform;
28+
import org.graalvm.nativeimage.Platforms;
29+
2730
import jdk.vm.ci.meta.ResolvedJavaType;
2831

2932
public interface CremaSupport {
33+
@Platforms(Platform.HOSTED_ONLY.class)
3034
ResolvedJavaType createInterpreterType(DynamicHub hub, ResolvedJavaType analysisType);
3135
}

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/analysis/DynamicHubInitializer.java

+4-1
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@
6262
import jdk.vm.ci.meta.ConstantReflectionProvider;
6363
import jdk.vm.ci.meta.JavaKind;
6464
import jdk.vm.ci.meta.ResolvedJavaField;
65+
import jdk.vm.ci.meta.ResolvedJavaType;
6566

6667
public class DynamicHubInitializer {
6768

@@ -150,8 +151,10 @@ public void initializeMetaData(ImageHeapScanner heapScanner, AnalysisType type)
150151
}
151152

152153
if (RuntimeClassLoading.isSupported()) {
153-
hub.setInterpreterType(RuntimeClassLoading.createInterpreterType(hub, type));
154+
ResolvedJavaType interpreterType = RuntimeClassLoading.createInterpreterType(hub, type);
155+
hub.setInterpreterType(interpreterType);
154156
heapScanner.rescanField(hub.getCompanion(), hubCompanionInterpreterType);
157+
heapScanner.rescanObject(interpreterType.getDeclaredMethods());
155158
}
156159
}
157160

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

+21-12
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,17 @@
3131

3232
import java.util.Collection;
3333

34+
import org.graalvm.nativeimage.Platform;
35+
import org.graalvm.nativeimage.Platforms;
36+
3437
import com.oracle.objectfile.ObjectFile;
38+
import com.oracle.svm.core.SubstrateControlFlowIntegrity;
39+
import com.oracle.svm.core.aarch64.SubstrateAArch64MacroAssembler;
3540
import com.oracle.svm.core.config.ConfigurationValues;
3641
import com.oracle.svm.core.graal.aarch64.AArch64InterpreterStubs;
3742
import com.oracle.svm.core.graal.aarch64.SubstrateAArch64RegisterConfig;
38-
import com.oracle.svm.core.graal.meta.KnownOffsets;
3943
import com.oracle.svm.core.graal.meta.SubstrateRegisterConfig;
4044
import com.oracle.svm.core.util.VMError;
41-
import com.oracle.svm.core.aarch64.SubstrateAArch64MacroAssembler;
4245
import com.oracle.svm.hosted.image.NativeImage;
4346
import com.oracle.svm.interpreter.metadata.InterpreterResolvedJavaMethod;
4447

@@ -60,6 +63,10 @@ public AArch64InterpreterStubSection() {
6063
protected byte[] generateEnterStubs(Collection<InterpreterResolvedJavaMethod> methods) {
6164
AArch64MacroAssembler masm = new SubstrateAArch64MacroAssembler(target);
6265

66+
if (SubstrateControlFlowIntegrity.enabled()) {
67+
VMError.unimplemented("GR-63035: Add CFI support for interpreter stubs");
68+
}
69+
6370
Label interpEnterStub = new Label();
6471
masm.bind(interpEnterStub);
6572

@@ -96,9 +103,13 @@ public int getVTableStubSize() {
96103
}
97104

98105
@Override
99-
protected byte[] generateVtableEnterStubs(int maxVtableIndex) {
106+
protected byte[] generateVTableEnterStubs(int maxVTableIndex) {
100107
AArch64MacroAssembler masm = new SubstrateAArch64MacroAssembler(target);
101108

109+
if (SubstrateControlFlowIntegrity.enabled()) {
110+
VMError.unimplemented("GR-63035: Add CFI support for interpreter stubs");
111+
}
112+
102113
Label interpEnterStub = new Label();
103114
masm.bind(interpEnterStub);
104115

@@ -115,21 +126,18 @@ protected byte[] generateVtableEnterStubs(int maxVtableIndex) {
115126
}
116127

117128
masm.align(getVTableStubSize());
129+
recordVTableStubBaseOffset(masm.position());
118130

119-
int vTableEntrySize = KnownOffsets.singleton().getVTableEntrySize();
120-
for (int index = 0; index < maxVtableIndex; index++) {
121-
int stubStart = masm.position();
122-
int stubEnd = stubStart + getVTableStubSize();
123-
124-
int offset = index * vTableEntrySize;
131+
for (int vTableIndex = 0; vTableIndex < maxVTableIndex; vTableIndex++) {
132+
int expectedStubEnd = masm.position() + getVTableStubSize();
125133

126-
/* pass current vtable offset as hidden argument */
127-
masm.mov(AArch64InterpreterStubs.TRAMPOLINE_ARGUMENT, offset);
134+
/* pass current vTable index as hidden argument */
135+
masm.mov(AArch64InterpreterStubs.TRAMPOLINE_ARGUMENT, vTableIndex);
128136

129137
masm.jmp(interpEnterStub);
130138

131139
masm.align(getVTableStubSize());
132-
assert masm.position() == stubEnd;
140+
assert masm.position() == expectedStubEnd;
133141
}
134142

135143
return masm.close(true);
@@ -149,6 +157,7 @@ private void recordEnterStubForPatching(Assembler.CodeAnnotation a) {
149157
resolverPatchOffset = annotation.instructionPosition;
150158
}
151159

160+
@Platforms(Platform.HOSTED_ONLY.class)
152161
@Override
153162
protected void markEnterStubPatch(ObjectFile.ProgbitsSectionImpl pltBuffer, ResolvedJavaMethod enterStub) {
154163
pltBuffer.markRelocationSite(resolverPatchOffset, AARCH64_R_AARCH64_ADR_PREL_PG_HI21, NativeImage.localSymbolNameForMethod(enterStub), 0);

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

+28-15
Original file line numberDiff line numberDiff line change
@@ -25,27 +25,31 @@
2525

2626
package com.oracle.svm.interpreter;
2727

28+
import static com.oracle.svm.interpreter.metadata.InterpreterResolvedJavaMethod.EST_NO_ENTRY;
29+
2830
import java.util.Collection;
2931

32+
import org.graalvm.nativeimage.Platform;
33+
import org.graalvm.nativeimage.Platforms;
34+
3035
import com.oracle.objectfile.ObjectFile;
36+
import com.oracle.svm.core.SubstrateControlFlowIntegrity;
3137
import com.oracle.svm.core.config.ConfigurationValues;
3238
import com.oracle.svm.core.graal.amd64.AMD64InterpreterStubs;
3339
import com.oracle.svm.core.graal.amd64.SubstrateAMD64RegisterConfig;
34-
import com.oracle.svm.core.graal.meta.KnownOffsets;
3540
import com.oracle.svm.core.graal.meta.SubstrateRegisterConfig;
3641
import com.oracle.svm.core.util.VMError;
37-
import com.oracle.svm.interpreter.metadata.InterpreterResolvedJavaMethod;
3842
import com.oracle.svm.hosted.image.NativeImage;
43+
import com.oracle.svm.interpreter.metadata.InterpreterResolvedJavaMethod;
3944

4045
import jdk.graal.compiler.asm.Assembler;
4146
import jdk.graal.compiler.asm.Label;
4247
import jdk.graal.compiler.asm.amd64.AMD64BaseAssembler;
4348
import jdk.graal.compiler.asm.amd64.AMD64MacroAssembler;
4449
import jdk.graal.compiler.core.common.LIRKind;
50+
import jdk.graal.compiler.core.common.NumUtil;
4551
import jdk.vm.ci.meta.ResolvedJavaMethod;
4652

47-
import static com.oracle.svm.interpreter.metadata.InterpreterResolvedJavaMethod.EST_NO_ENTRY;
48-
4953
public class AMD64InterpreterStubSection extends InterpreterStubSection {
5054
public AMD64InterpreterStubSection() {
5155
this.target = ConfigurationValues.getTarget();
@@ -57,6 +61,10 @@ public AMD64InterpreterStubSection() {
5761
protected byte[] generateEnterStubs(Collection<InterpreterResolvedJavaMethod> methods) {
5862
AMD64MacroAssembler masm = new AMD64MacroAssembler(target);
5963

64+
if (SubstrateControlFlowIntegrity.enabled()) {
65+
VMError.unimplemented("GR-63035: Add CFI support for interpreter stubs");
66+
}
67+
6068
Label interpEnterStub = new Label();
6169
masm.bind(interpEnterStub);
6270

@@ -80,35 +88,39 @@ protected byte[] generateEnterStubs(Collection<InterpreterResolvedJavaMethod> me
8088

8189
@Override
8290
public int getVTableStubSize() {
83-
return 16;
91+
int branchTargetAlignment = ConfigurationValues.getTarget().wordSize * 2;
92+
int stubSize = 10;
93+
94+
return NumUtil.roundUp(stubSize, branchTargetAlignment);
8495
}
8596

8697
@Override
87-
protected byte[] generateVtableEnterStubs(int maxVtableIndex) {
98+
protected byte[] generateVTableEnterStubs(int maxVTableIndex) {
8899
AMD64MacroAssembler masm = new AMD64MacroAssembler(target);
89100

101+
if (SubstrateControlFlowIntegrity.enabled()) {
102+
VMError.unimplemented("GR-63035: Add CFI support for interpreter stubs");
103+
}
104+
90105
Label interpEnterStub = new Label();
91106
masm.bind(interpEnterStub);
92107

93108
masm.setCodePatchingAnnotationConsumer(this::recordEnterStubForPatching);
94109
masm.jmp();
95110

96111
masm.align(getVTableStubSize());
112+
recordVTableStubBaseOffset(masm.position());
97113

98-
int vTableEntrySize = KnownOffsets.singleton().getVTableEntrySize();
99-
for (int index = 0; index < maxVtableIndex; index++) {
100-
int stubStart = masm.position();
101-
int stubEnd = stubStart + getVTableStubSize();
102-
103-
int offset = index * vTableEntrySize;
114+
for (int vTableIndex = 0; vTableIndex < maxVTableIndex; vTableIndex++) {
115+
int expectedStubEnd = masm.position() + getVTableStubSize();
104116

105-
/* pass current vtable offset as hidden argument */
106-
masm.movq(AMD64InterpreterStubs.TRAMPOLINE_ARGUMENT, offset);
117+
/* pass current vTable index as hidden argument */
118+
masm.moveInt(AMD64InterpreterStubs.TRAMPOLINE_ARGUMENT, vTableIndex);
107119

108120
masm.jmp(interpEnterStub);
109121

110122
masm.align(getVTableStubSize());
111-
assert masm.position() == stubEnd;
123+
assert masm.position() == expectedStubEnd;
112124
}
113125

114126
return masm.close(true);
@@ -130,6 +142,7 @@ private void recordEnterStubForPatching(Assembler.CodeAnnotation a) {
130142
resolverPatchRelocationKind = ObjectFile.RelocationKind.getPCRelative(annotation.operandSize);
131143
}
132144

145+
@Platforms(Platform.HOSTED_ONLY.class)
133146
@Override
134147
protected void markEnterStubPatch(ObjectFile.ProgbitsSectionImpl pltBuffer, ResolvedJavaMethod enterStub) {
135148
pltBuffer.markRelocationSite(resolverPatchOffset, resolverPatchRelocationKind, NativeImage.localSymbolNameForMethod(enterStub), resolverKindAddend);

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

+23-3
Original file line numberDiff line numberDiff line change
@@ -25,20 +25,23 @@
2525
package com.oracle.svm.interpreter;
2626

2727
import java.lang.reflect.Field;
28+
import java.lang.reflect.Method;
2829
import java.util.Arrays;
2930
import java.util.List;
3031

3132
import org.graalvm.nativeimage.ImageSingletons;
3233
import org.graalvm.nativeimage.Platform;
3334
import org.graalvm.nativeimage.Platforms;
3435
import org.graalvm.nativeimage.hosted.Feature;
36+
import org.graalvm.word.Pointer;
3537

3638
import com.oracle.graal.pointsto.meta.AnalysisType;
3739
import com.oracle.graal.pointsto.meta.AnalysisUniverse;
3840
import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature;
3941
import com.oracle.svm.core.feature.InternalFeature;
4042
import com.oracle.svm.core.hub.CremaSupport;
4143
import com.oracle.svm.core.hub.RuntimeClassLoading;
44+
import com.oracle.svm.core.util.VMError;
4245
import com.oracle.svm.hosted.FeatureImpl;
4346
import com.oracle.svm.hosted.meta.HostedType;
4447
import com.oracle.svm.hosted.meta.HostedUniverse;
@@ -53,6 +56,7 @@
5356
@Platforms(Platform.HOSTED_ONLY.class)
5457
@AutomaticallyRegisteredFeature
5558
public class CremaFeature implements InternalFeature {
59+
private Method enterVTableInterpreterStub;
5660

5761
@Override
5862
public boolean isInConfiguration(IsInConfigurationAccess access) {
@@ -75,6 +79,17 @@ private static boolean assertionsEnabled() {
7579
return enabled;
7680
}
7781

82+
@Override
83+
public void beforeAnalysis(BeforeAnalysisAccess access) {
84+
FeatureImpl.BeforeAnalysisAccessImpl accessImpl = (FeatureImpl.BeforeAnalysisAccessImpl) access;
85+
try {
86+
enterVTableInterpreterStub = InterpreterStubSection.class.getMethod("enterVTableInterpreterStub", int.class, Pointer.class);
87+
accessImpl.registerAsRoot(enterVTableInterpreterStub, true, "stub for interpreter");
88+
} catch (NoSuchMethodException e) {
89+
throw VMError.shouldNotReachHere(e);
90+
}
91+
}
92+
7893
@Override
7994
public void afterAnalysis(AfterAnalysisAccess access) {
8095
AnalysisUniverse aUniverse = ((FeatureImpl.AfterAnalysisAccessImpl) access).getUniverse();
@@ -106,9 +121,14 @@ public void beforeCompilation(BeforeCompilationAccess access) {
106121
public void afterAbstractImageCreation(AfterAbstractImageCreationAccess access) {
107122
FeatureImpl.AfterAbstractImageCreationAccessImpl accessImpl = ((FeatureImpl.AfterAbstractImageCreationAccessImpl) access);
108123

109-
/* create vtable enter stubs */
110-
int maxVtableIndex = 0x100;
111124
InterpreterStubSection stubSection = ImageSingletons.lookup(InterpreterStubSection.class);
112-
stubSection.createInterpreterVtableEnterStubSection(accessImpl.getImage(), maxVtableIndex);
125+
stubSection.createInterpreterVTableEnterStubSection(accessImpl.getImage());
126+
}
127+
128+
@Override
129+
public void beforeImageWrite(BeforeImageWriteAccess access) {
130+
FeatureImpl.BeforeImageWriteAccessImpl accessImpl = (FeatureImpl.BeforeImageWriteAccessImpl) access;
131+
InterpreterStubSection stubSection = ImageSingletons.lookup(InterpreterStubSection.class);
132+
stubSection.markEnterStubPatch(accessImpl.getHostedMetaAccess().lookupJavaMethod(enterVTableInterpreterStub));
113133
}
114134
}

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

+4
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@
2727
import java.util.ArrayList;
2828
import java.util.List;
2929

30+
import org.graalvm.nativeimage.Platform;
31+
import org.graalvm.nativeimage.Platforms;
32+
3033
import com.oracle.graal.pointsto.meta.AnalysisMethod;
3134
import com.oracle.graal.pointsto.meta.AnalysisType;
3235
import com.oracle.graal.pointsto.meta.AnalysisUniverse;
@@ -43,6 +46,7 @@
4346

4447
public class CremaSupportImpl implements CremaSupport {
4548

49+
@Platforms(Platform.HOSTED_ONLY.class)
4650
@Override
4751
public ResolvedJavaType createInterpreterType(DynamicHub hub, ResolvedJavaType type) {
4852
BuildTimeInterpreterUniverse btiUniverse = BuildTimeInterpreterUniverse.singleton();

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

+4-4
Original file line numberDiff line numberDiff line change
@@ -189,8 +189,8 @@ public void beforeAnalysis(BeforeAnalysisAccess access) {
189189
FeatureImpl.BeforeAnalysisAccessImpl accessImpl = (FeatureImpl.BeforeAnalysisAccessImpl) access;
190190

191191
try {
192-
enterInterpreterMethod = InterpreterStubSection.class.getMethod("enterInterpreterStub", int.class, Pointer.class);
193-
accessImpl.registerAsRoot(enterInterpreterMethod, false, "stub for interpreter");
192+
enterInterpreterMethod = InterpreterStubSection.class.getMethod("enterMethodInterpreterStub", int.class, Pointer.class);
193+
accessImpl.registerAsRoot(enterInterpreterMethod, true, "stub for interpreter");
194194

195195
// Holds references that must be kept alive in the image heap.
196196
access.registerAsAccessed(DebuggerSupport.class.getDeclaredField("referencesInImage"));
@@ -199,7 +199,7 @@ public void beforeAnalysis(BeforeAnalysisAccess access) {
199199
accessImpl.registerAsRoot(System.class.getDeclaredMethod("arraycopy", Object.class, int.class, Object.class, int.class, int.class), true,
200200
"Allow interpreting methods that call System.arraycopy");
201201
} catch (NoSuchMethodException | NoSuchFieldException e) {
202-
throw VMError.shouldNotReachHereAtRuntime();
202+
throw VMError.shouldNotReachHere(e);
203203
}
204204

205205
registerStringConcatenation(accessImpl);
@@ -212,7 +212,7 @@ public void beforeAnalysis(BeforeAnalysisAccess access) {
212212
// is inlined, therefore it's not needed. Still needed for interpreter execution.
213213
access.registerAsAccessed(Integer.class.getField("TYPE"));
214214
} catch (NoSuchFieldException e) {
215-
throw VMError.shouldNotReachHereAtRuntime();
215+
throw VMError.shouldNotReachHere(e);
216216
}
217217

218218
methodsProcessedDuringAnalysis = new HashSet<>();

0 commit comments

Comments
 (0)