Skip to content

Commit ce73657

Browse files
author
Elia Trachsel
committed
[GR-67928] No-Native-Espresso
PullRequest: graal/21575
2 parents 6de4fd7 + 750f82d commit ce73657

34 files changed

+1229
-44
lines changed

espresso/src/com.oracle.truffle.espresso.processor/src/com/oracle/truffle/espresso/processor/EspressoProcessor.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,9 @@ abstract FieldBuilder generateFactoryConstructor(FieldBuilder factoryBuilder, St
215215
TypeElement truffleNode;
216216
private static final String TRUFFLE_NODE = "com.oracle.truffle.api.nodes.Node";
217217

218+
TypeElement truffleObject;
219+
private static final String TRUFFLE_OBJECT = "com.oracle.truffle.api.interop.TruffleObject";
220+
218221
// Global constants
219222
protected static final String FACTORY = "Factory";
220223
protected static final String FACTORY_FIELD_NAME = "FACTORY";
@@ -228,7 +231,7 @@ abstract FieldBuilder generateFactoryConstructor(FieldBuilder factoryBuilder, St
228231

229232
static final String IMPORT_INTEROP_LIBRARY = "com.oracle.truffle.api.interop.InteropLibrary";
230233
static final String IMPORT_STATIC_OBJECT = STATIC_OBJECT;
231-
static final String IMPORT_TRUFFLE_OBJECT = "com.oracle.truffle.api.interop.TruffleObject";
234+
static final String IMPORT_TRUFFLE_OBJECT = TRUFFLE_OBJECT;
232235
static final String IMPORT_ESPRESSO_LANGUAGE = ESPRESSO_LANGUAGE;
233236
static final String IMPORT_META = "com.oracle.truffle.espresso.meta.Meta";
234237
static final String IMPORT_ESPRESSO_CONTEXT = ESPRESSO_CONTEXT;
@@ -342,6 +345,7 @@ public boolean doProcess(Set<? extends TypeElement> annotations, RoundEnvironmen
342345
espressoContext = getTypeElement(ESPRESSO_CONTEXT);
343346
substitutionProfiler = getTypeElement(SUBSTITUTION_PROFILER);
344347
truffleNode = getTypeElement(TRUFFLE_NODE);
348+
truffleObject = getTypeElement(TRUFFLE_OBJECT);
345349

346350
processImpl(roundEnv);
347351
done = true;

espresso/src/com.oracle.truffle.espresso.processor/src/com/oracle/truffle/espresso/processor/SubstitutionFlag.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,18 @@ public final class SubstitutionFlag {
5353
*/
5454
public static final byte InlineInBytecode = 0b00000010;
5555

56+
/**
57+
* Whether the given library entry implementation needs to have its method signature mangled for
58+
* registration. This can happen if a class has overloaded native methods.
59+
*/
60+
public static final byte needsSignatureMangle = 0b00000100;
61+
62+
/**
63+
* Whether to relax type checks in the substitution processor to allow for @Pointer
64+
* TruffleObject. Used for substitutions in libnespresso.
65+
*/
66+
public static final byte allowPointerType = 0b00001000;
67+
5668
private SubstitutionFlag() {
5769
}
5870
}

espresso/src/com.oracle.truffle.espresso.processor/src/com/oracle/truffle/espresso/processor/SubstitutionProcessor.java

Lines changed: 27 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -206,15 +206,23 @@ private void processElement(Element substitution) {
206206
}
207207
}
208208

209-
private void checkParameterOrReturnType(String headerMessage, TypeMirror typeMirror, Element element) {
209+
private void checkParameterOrReturnType(String headerMessage, TypeMirror typeMirror, Element element, boolean allowPointerType) {
210210
if (typeMirror.getKind().isPrimitive()) {
211211
if (getAnnotation(typeMirror, javaType) != null) {
212212
processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,
213213
headerMessage + " (primitive type) cannot be annotated with @JavaType", element);
214214
}
215215
} else if (typeMirror.getKind() != TypeKind.VOID) {
216-
// Reference type.
217-
if (!processingEnv.getTypeUtils().isSameType(typeMirror, staticObject.asType())) {
216+
boolean isStaticObject = processingEnv.getTypeUtils().isSameType(typeMirror, staticObject.asType());
217+
if (allowPointerType) {
218+
// used in EspressoLibs where @Pointer TruffleObjects are allowed.
219+
boolean isPointer = processingEnv.getTypeUtils().isSameType(typeMirror, truffleObject.asType());
220+
if (!(isStaticObject || isPointer)) {
221+
processingEnv.getMessager().printMessage(Diagnostic.Kind.WARNING,
222+
headerMessage + " is not of type StaticObject or TruffleObject", element);
223+
}
224+
} else if (!isStaticObject) {
225+
// only StaticObject is allowed when typec checks are not relaxed
218226
processingEnv.getMessager().printMessage(Diagnostic.Kind.WARNING,
219227
headerMessage + " is not of type StaticObject", element);
220228
}
@@ -230,18 +238,18 @@ private void checkInjectedParameter(String headerMessage, TypeMirror typeMirror,
230238
}
231239
}
232240

233-
private void checkTargetMethod(ExecutableElement targetElement) {
241+
private void checkTargetMethod(ExecutableElement targetElement, boolean allowPointerType) {
234242
for (VariableElement param : targetElement.getParameters()) {
235243
if (isActualParameter(param)) {
236-
checkParameterOrReturnType("Substitution parameter", param.asType(), param);
244+
checkParameterOrReturnType("Substitution parameter", param.asType(), param, allowPointerType);
237245
} else {
238246
checkInjectedParameter("Substitution parameter", param.asType(), param);
239247
}
240248
}
241-
checkParameterOrReturnType("Substitution return type", targetElement.getReturnType(), targetElement);
249+
checkParameterOrReturnType("Substitution return type", targetElement.getReturnType(), targetElement, allowPointerType);
242250
}
243251

244-
private void checkSubstitutionElement(Element element) {
252+
private void checkSubstitutionElement(Element element, boolean allowPointerType) {
245253
if (element.getKind() == ElementKind.METHOD) {
246254
ExecutableElement methodElement = (ExecutableElement) element;
247255
Set<Modifier> modifiers = methodElement.getModifiers();
@@ -251,7 +259,7 @@ private void checkSubstitutionElement(Element element) {
251259
if (!modifiers.contains(Modifier.STATIC)) {
252260
processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "Substitution method must be static", element);
253261
}
254-
checkTargetMethod(methodElement);
262+
checkTargetMethod(methodElement, allowPointerType);
255263
}
256264
if (element.getKind() == ElementKind.CLASS) {
257265
TypeElement typeElement = (TypeElement) element;
@@ -261,7 +269,7 @@ private void checkSubstitutionElement(Element element) {
261269
}
262270
ExecutableElement targetMethod = findNodeExecute(typeElement);
263271
if (targetMethod != null) {
264-
checkTargetMethod(targetMethod);
272+
checkTargetMethod(targetMethod, allowPointerType);
265273
}
266274
}
267275
}
@@ -313,9 +321,12 @@ void processSubstitution(Element element, String className, TypeMirror defaultNa
313321
// Find the methods annotated with @Substitution.
314322
AnnotationMirror subst = getAnnotation(element, substitutionAnnotation);
315323
if (subst != null) {
316-
317-
// Sanity check.
318-
checkSubstitutionElement(element);
324+
List<Byte> flagsList = getAnnotationValueList(subst, "flags", Byte.class);
325+
byte flags = 0;
326+
for (Byte flag : flagsList) {
327+
flags |= flag;
328+
}
329+
checkSubstitutionElement(element, isFlag(flags, SubstitutionFlag.allowPointerType));
319330

320331
// Obtain the name of the element to be substituted in.
321332
String targetMethodName = getSubstutitutedMethodName(element);
@@ -347,12 +358,6 @@ void processSubstitution(Element element, String className, TypeMirror defaultNa
347358

348359
TypeMirror languageFilter = getLanguageFilter(subst);
349360

350-
List<Byte> flagsList = getAnnotationValueList(subst, "flags", Byte.class);
351-
byte flags = 0;
352-
for (Byte flag : flagsList) {
353-
flags |= flag;
354-
}
355-
356361
TypeMirror encodedInlineGuard = getInlineValue(classWideInline, element);
357362
boolean inlineInBytecode = encodedInlineGuard != null ||
358363
// Implicit inlining of trivial substitutions.
@@ -474,7 +479,7 @@ static boolean isValidInternalType(String internalName) {
474479
/**
475480
* @param annotation @JavaType annotation
476481
* @param element element containing the @JavaType annotation for error reporting
477-
*
482+
*
478483
* @return the fully qualified internal name of the guest class.
479484
*/
480485
private String getClassFromJavaType(AnnotationMirror annotation, Element element) {
@@ -626,6 +631,9 @@ List<String> expectedImports(String className, String targetMethodName, List<Str
626631
if (parameterTypeName.contains("StaticObject") || h.returnType.equals("V")) {
627632
expectedImports.add(IMPORT_STATIC_OBJECT);
628633
}
634+
if (parameterTypeName.contains("TruffleObject")) {
635+
expectedImports.add(IMPORT_TRUFFLE_OBJECT);
636+
}
629637
if (helper.isNodeTarget()) {
630638
expectedImports.add(helper.getNodeTarget().getQualifiedName().toString());
631639
}

espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/EspressoLanguage.java

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@
6868
import com.oracle.truffle.espresso.classfile.descriptors.TypeSymbols;
6969
import com.oracle.truffle.espresso.classfile.descriptors.Utf8Symbols;
7070
import com.oracle.truffle.espresso.descriptors.EspressoSymbols;
71+
import com.oracle.truffle.espresso.ffi.NoNativeAccess;
7172
import com.oracle.truffle.espresso.ffi.nfi.NFIIsolatedNativeAccess;
7273
import com.oracle.truffle.espresso.ffi.nfi.NFINativeAccess;
7374
import com.oracle.truffle.espresso.ffi.nfi.NFISulongNativeAccess;
@@ -328,10 +329,17 @@ private void extractDataFrom(EspressoLanguage other) {
328329
}
329330

330331
private static String setNativeBackendId(final TruffleLanguage.Env env) {
331-
String nativeBackend;
332+
boolean isAllowed = env.isNativeAccessAllowed();
333+
// if the Env allows, this might be overwritten.
334+
String nativeBackend = NoNativeAccess.Provider.ID;
332335
if (env.getOptions().hasBeenSet(EspressoOptions.NativeBackend)) {
333-
nativeBackend = env.getOptions().get(EspressoOptions.NativeBackend);
334-
} else {
336+
String userNativeBackend = env.getOptions().get(EspressoOptions.NativeBackend);
337+
if (!isAllowed && !userNativeBackend.equals(nativeBackend)) {
338+
throw EspressoError.fatal("trying to set NativeBackend even though NativeAccess is disabled");
339+
}
340+
return userNativeBackend;
341+
342+
} else if (isAllowed) {
335343
// Pick a sane "default" native backend depending on the platform.
336344
boolean isInPreInit = (boolean) env.getConfig().getOrDefault("preinit", false);
337345
if (isInPreInit || !EspressoOptions.RUNNING_ON_SVM) {
@@ -631,6 +639,10 @@ public String nativeBackendId() {
631639
return nativeBackendId;
632640
}
633641

642+
public boolean isNativeAvailable() {
643+
return !nativeBackendId.equals("no-native");
644+
}
645+
634646
public boolean isContinuumEnabled() {
635647
return continuum;
636648
}

espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/blocking/BlockingSupport.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@ public void sleep(long nanos, Node location) throws GuestInterruptedException {
153153
*/
154154
public void guestInterrupt(Thread t, T guest) {
155155
guestInterrupter.guestInterrupt(t, guest);
156+
156157
if (t != null) { // Make sure thread is initialized
157158
t.interrupt(); // Host interrupt to wake up the thread.
158159
}

espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/descriptors/EspressoSymbols.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,10 @@ public static void ensureInitialized() {
190190
// libnio
191191
public static final Symbol<Type> sun_nio_fs_TruffleFilteredDirectoryStream$ForeignDirectoryStream = SYMBOLS.putType("Lsun/nio/fs/TruffleFilteredDirectoryStream$ForeignDirectoryStream;");
192192
public static final Symbol<Type> sun_nio_fs_TruffleFilteredDirectoryStream$ForeignIterator = SYMBOLS.putType("Lsun/nio/fs/TruffleFilteredDirectoryStream$ForeignIterator;");
193+
// libextnet
194+
public static final Symbol<Type> jdk_net_ExtendedSocketOptions$PlatformSocketOptions = SYMBOLS.putType("Ljdk/net/ExtendedSocketOptions$PlatformSocketOptions;");
195+
// libmanagement
196+
public static final Symbol<Type> sun_management_VMManagementImpl = SYMBOLS.putType("Lsun/management/VMManagementImpl;");
193197
// URL class loader
194198
public static final Symbol<Type> java_net_URLClassLoader = SYMBOLS.putType("Ljava/net/URLClassLoader;");
195199
public static final Symbol<Type> java_net_URL = SYMBOLS.putType("Ljava/net/URL;");
@@ -835,6 +839,15 @@ public static class Names {
835839
public static final Symbol<Name> totalTime = SYMBOLS.putName("totalTime");
836840
public static final Symbol<Name> user = SYMBOLS.putName("user");
837841
public static final Symbol<Name> initialized = SYMBOLS.putName("initialized");
842+
// java.management
843+
public static final Symbol<Name> compTimeMonitoringSupport = SYMBOLS.putName("compTimeMonitoringSupport");
844+
public static final Symbol<Name> threadContentionMonitoringSupport = SYMBOLS.putName("threadContentionMonitoringSupport");
845+
public static final Symbol<Name> currentThreadCpuTimeSupport = SYMBOLS.putName("currentThreadCpuTimeSupport");
846+
public static final Symbol<Name> otherThreadCpuTimeSupport = SYMBOLS.putName("otherThreadCpuTimeSupport");
847+
public static final Symbol<Name> threadAllocatedMemorySupport = SYMBOLS.putName("threadAllocatedMemorySupport");
848+
public static final Symbol<Name> remoteDiagnosticCommandsSupport = SYMBOLS.putName("remoteDiagnosticCommandsSupport");
849+
public static final Symbol<Name> objectMonitorUsageSupport = SYMBOLS.putName("objectMonitorUsageSupport");
850+
public static final Symbol<Name> synchronizerUsageSupport = SYMBOLS.putName("synchronizerUsageSupport");
838851
// java.lang.invoke.*
839852
// CallSite
840853
public static final Symbol<Name> target = SYMBOLS.putName("target");

espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/ffi/EspressoLibsNativeAccess.java

Lines changed: 46 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,11 @@
2424

2525
import java.nio.file.Path;
2626

27+
import com.oracle.truffle.api.CompilerDirectives;
2728
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
2829
import com.oracle.truffle.api.TruffleLogger;
2930
import com.oracle.truffle.api.interop.ArityException;
31+
import com.oracle.truffle.api.interop.InteropLibrary;
3032
import com.oracle.truffle.api.interop.TruffleObject;
3133
import com.oracle.truffle.api.interop.UnsupportedMessageException;
3234
import com.oracle.truffle.api.interop.UnsupportedTypeException;
@@ -35,7 +37,11 @@
3537
import com.oracle.truffle.espresso.libs.Lib;
3638
import com.oracle.truffle.espresso.libs.Libs;
3739
import com.oracle.truffle.espresso.libs.SubstitutionFactoryWrapper;
40+
import com.oracle.truffle.espresso.meta.EspressoError;
3841
import com.oracle.truffle.espresso.runtime.EspressoContext;
42+
import com.oracle.truffle.espresso.vm.UnsafeAccess;
43+
44+
import sun.misc.Unsafe;
3945

4046
/**
4147
* Uses Espresso's implementation of standard JDK libraries, falling back to a delegate if the
@@ -50,6 +56,11 @@
5056
public class EspressoLibsNativeAccess extends ContextAccessImpl implements NativeAccess {
5157

5258
private static final TruffleLogger logger = TruffleLogger.getLogger(EspressoLanguage.ID, EspressoLibsNativeAccess.class);
59+
/*
60+
* Temporarily used for off-heap memory access. Will be removed with the memory virtualization
61+
* (GR-70643)
62+
*/
63+
private static final Unsafe UNSAFE = UnsafeAccess.get();
5364

5465
private static TruffleLogger getLogger() {
5566
return logger;
@@ -61,7 +72,7 @@ private static TruffleLogger getLogger() {
6172
public EspressoLibsNativeAccess(EspressoContext ctx, NativeAccess delegate) {
6273
super(ctx);
6374
this.delegate = delegate;
64-
this.libs = new Libs();
75+
this.libs = new Libs(ctx.getLanguage());
6576
}
6677

6778
@Override
@@ -166,17 +177,48 @@ public SignatureCallNode createSignatureCall(NativeSignature nativeSignature) {
166177

167178
@Override
168179
public @Buffer TruffleObject allocateMemory(long size) {
169-
return delegate.allocateMemory(size);
180+
// Will be removed with the memory virtualization (GR-70643)
181+
long address = 0L;
182+
try {
183+
address = UNSAFE.allocateMemory(size);
184+
} catch (OutOfMemoryError e) {
185+
return null;
186+
}
187+
return TruffleByteBuffer.wrap(RawPointer.create(address), Math.toIntExact(size));
170188
}
171189

172190
@Override
173191
public @Buffer TruffleObject reallocateMemory(@Pointer TruffleObject buffer, long newSize) {
174-
return delegate.reallocateMemory(buffer, newSize);
192+
// Will be removed with the memory virtualization (GR-70643)
193+
assert InteropLibrary.getUncached().isPointer(buffer);
194+
long oldAddress = 0L;
195+
try {
196+
oldAddress = InteropLibrary.getUncached().asPointer(buffer);
197+
} catch (UnsupportedMessageException e) {
198+
CompilerDirectives.transferToInterpreterAndInvalidate();
199+
throw EspressoError.shouldNotReachHere(e);
200+
}
201+
long newAddress = 0L;
202+
try {
203+
newAddress = UNSAFE.reallocateMemory(oldAddress, newSize);
204+
} catch (OutOfMemoryError e) {
205+
return null;
206+
}
207+
return TruffleByteBuffer.wrap(RawPointer.create(newAddress), Math.toIntExact(newSize));
175208
}
176209

177210
@Override
178211
public void freeMemory(@Pointer TruffleObject buffer) {
179-
delegate.freeMemory(buffer);
212+
// Will be removed with the memory virtualization (GR-70643)
213+
assert InteropLibrary.getUncached().isPointer(buffer);
214+
long address = 0L;
215+
try {
216+
address = InteropLibrary.getUncached().asPointer(buffer);
217+
} catch (UnsupportedMessageException e) {
218+
CompilerDirectives.transferToInterpreterAndInvalidate();
219+
throw EspressoError.shouldNotReachHere(e);
220+
}
221+
UNSAFE.freeMemory(address);
180222
}
181223

182224
@Override

espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/ffi/NoNativeAccess.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import com.oracle.truffle.api.interop.UnsupportedTypeException;
3434
import com.oracle.truffle.espresso.EspressoLanguage;
3535
import com.oracle.truffle.espresso.meta.EspressoError;
36+
import com.oracle.truffle.espresso.runtime.EspressoContext;
3637
import com.oracle.truffle.espresso.substitutions.Collect;
3738

3839
public class NoNativeAccess implements NativeAccess {
@@ -119,8 +120,10 @@ public void freeMemory(@Pointer TruffleObject buffer) {
119120

120121
@Override
121122
public @Pointer TruffleObject createNativeClosure(TruffleObject executable, NativeSignature nativeSignature) {
122-
getLogger().warning(() -> "Attempting to create native closure without native access.");
123-
return null;
123+
if (EspressoContext.get(null).isInitialized()) {
124+
getLogger().warning(() -> "Attempting to create native closure without native access.");
125+
}
126+
return RawPointer.nullInstance();
124127
}
125128

126129
@Override

espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/jni/JniEnv.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,8 @@ private JniEnv(EspressoContext context, NativeAccess nativeAccess) {
190190
popObject = nativeAccess.lookupAndBindSymbol(nespressoLibrary, "pop_object", NativeSignature.create(NativeType.OBJECT, NativeType.POINTER));
191191

192192
jniEnvPtr = initializeAndGetEnv(initializeNativeContext);
193-
assert jniEnvPtr != null && !getUncached().isNull(jniEnvPtr);
193+
assert jniEnvPtr != null;
194+
assert !getUncached().isNull(jniEnvPtr) || !getLanguage().isNativeAvailable();
194195
assert getUncached().isPointer(jniEnvPtr);
195196
}
196197

0 commit comments

Comments
 (0)