Skip to content

Commit

Permalink
Export the Truffle packages explicitly, since TruffleJDKServices clas…
Browse files Browse the repository at this point in the history
…s was removed.
  • Loading branch information
entlicher committed Feb 24, 2022
1 parent aad1b8f commit 7fe5a90
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -118,9 +118,7 @@ private boolean isStepInto() {

void newPolyglotEngineInstance(ObjectReference engine, JPDAThreadImpl thread) {
LOG.log(Level.FINE, "Engine created breakpoint hit: engine = {0} in thread = {1}", new Object[] { engine, thread.getThreadReference()});
if (inited.compareAndSet(false, true)) {
initDebuggerRemoteService(thread);
}
assert inited.get(): "The remote services should have been initialized already from a Truffle class.";
if (accessorClass == null) {
// No accessor
return ;
Expand Down Expand Up @@ -163,7 +161,13 @@ void newPolyglotEngineInstance(ObjectReference engine, JPDAThreadImpl thread) {
}
}

private void initDebuggerRemoteService(JPDAThread thread) {
void initDebuggerRemoteService(JPDAThread thread) {
if (inited.compareAndSet(false, true)) {
doInitDebuggerRemoteService(thread);
}
}

private void doInitDebuggerRemoteService(JPDAThread thread) {
if (LOG.isLoggable(Level.FINE)) {
LOG.log(Level.FINE, "initDebuggerRemoteService({0})", thread);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,9 +98,13 @@ public final class RemoteServices {
static final String REMOTE_CLASSES_ZIPFILE = "/org/netbeans/modules/debugger/jpda/truffle/resources/JPDATruffleBackend.jar"; // NOI18N

private static final String TRUFFLE_CLASS = "com.oracle.truffle.api.Truffle"; // NOI18N
private static final String EXPORT_TRUFFLE_CLASS = "com.oracle.truffle.api.impl.TruffleJDKServices"; // NOI18N
private static final String EXPORT_TRUFFLE_METHOD = "exportTo"; // NOI18N
private static final String EXPORT_TRUFFLE_SIGNAT = "(Ljava/lang/ClassLoader;Ljava/lang/String;)V"; // NOI18N
private static final String[] TRUFFLE_PACKAGES = {
"com.oracle.truffle.api", // NOI18N
"com.oracle.truffle.api.debug", // NOI18N
"com.oracle.truffle.api.frame", // NOI18N
"com.oracle.truffle.api.instrumentation", // NOI18N
"com.oracle.truffle.api.nodes", // NOI18N
"com.oracle.truffle.api.source" }; // NOI18N

private static final Map<JPDADebugger, ClassObjectReference> remoteServiceClasses = new WeakHashMap<>();
private static final Map<JPDADebugger, ThreadReference> remoteServiceAccess = new WeakHashMap<>();
Expand Down Expand Up @@ -269,17 +273,20 @@ private static ClassObjectReference doUpload(VirtualMachine vm, ThreadReference

// We have an agent class loader that we'll use to define Truffle backend debugging classes.
// We need to export the agent class loader to Truffle so that we can upload classes that access Truffle APIs.
ClassType languageLoader = getClass(vm, EXPORT_TRUFFLE_CLASS);
if (languageLoader == null) {
Exceptions.printStackTrace(new IllegalStateException("Class " + EXPORT_TRUFFLE_CLASS + " not found in the debuggee."));
return null;
// We need to export packages from Truffle to our unnamed module.
// We must call the Modeule.addExports() method from the Truffle module, we must be suspended in a Truffle class.
Method getModule = ClassTypeWrapper.concreteMethodByName(theClass, "getModule", "()Ljava/lang/Module;");
// truffleModule = Truffle.class.getModule()
ObjectReference truffleModule = (ObjectReference) ObjectReferenceWrapper.invokeMethod(ReferenceTypeWrapper.classObject(truffleLocatorClass), tawt, getModule, Collections.emptyList(), ObjectReference.INVOKE_SINGLE_THREADED);
ClassType newClassLoaderClass = (ClassType) ObjectReferenceWrapper.referenceType(classLoader);
Method getUnnamedModule = ClassTypeWrapper.concreteMethodByName(newClassLoaderClass, "getUnnamedModule", "()Ljava/lang/Module;");
// unnamedModule = newInstanceOfClassLoader.getUnnamedModule()
ObjectReference unnamedModule = (ObjectReference) ObjectReferenceWrapper.invokeMethod(classLoader, tawt, getUnnamedModule, Collections.emptyList(), ObjectReference.INVOKE_SINGLE_THREADED);
Method addExports = ClassTypeWrapper.concreteMethodByName((ClassType) ObjectReferenceWrapper.referenceType(truffleModule), "addExports", "(Ljava/lang/String;Ljava/lang/Module;)Ljava/lang/Module;");
for (String tPackage : TRUFFLE_PACKAGES) {
// Add exports: truffleModule.addExports(package, unnamedModule)
ObjectReferenceWrapper.invokeMethod(truffleModule, tawt, addExports, Arrays.asList(values.mirrorOf(tPackage), unnamedModule), ObjectReference.INVOKE_SINGLE_THREADED);
}
Method exportTruffle = ClassTypeWrapper.concreteMethodByName(languageLoader, EXPORT_TRUFFLE_METHOD, EXPORT_TRUFFLE_SIGNAT);
if (exportTruffle == null) {
Exceptions.printStackTrace(new IllegalStateException("Method " + EXPORT_TRUFFLE_METHOD + " was not found in " + EXPORT_TRUFFLE_CLASS +" in the debuggee."));
return null;
}
ClassTypeWrapper.invokeMethod(languageLoader, tawt, exportTruffle, Arrays.asList(classLoader, null), ObjectReference.INVOKE_SINGLE_THREADED);
} else {
ObjectReference cl;
cl = getTruffleClassLoader(tawt, vm);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,12 +62,15 @@ public class TruffleDebugManager extends DebuggerManagerAdapter {

private static final Logger LOG = Logger.getLogger(TruffleDebugManager.class.getName());

private static final String ENGINE_CLASS = "org.graalvm.polyglot.Engine";
private static final String ENGINE_BUILDER_CLASS = "org.graalvm.polyglot.Engine$Builder";
private static final String ENGINE_CLASS = "org.graalvm.polyglot.Engine"; // NOI18N
private static final String ENGINE_BUILDER_CLASS = "org.graalvm.polyglot.Engine$Builder"; // NOI18N
private static final String REMOTE_SERVICES_TRIGGER_CLASS = "com.oracle.truffle.api.Truffle"; // NOI18N
private static final String REMOTE_SERVICES_TRIGGER_METHOD = "getRuntime"; // NOI18N
// Breakpoint on this class triggers search of existing engines
private static final String EXISTING_ENGINES_TRIGGER = "com.oracle.truffle.api.frame.Frame";
private static final String EXISTING_ENGINES_TRIGGER = "com.oracle.truffle.api.frame.Frame"; // NOI18N

private JPDABreakpoint debugManagerLoadBP;
private Map<JPDADebugger, JPDABreakpoint> initServiceBPs = new HashMap<>();
private static final Map<JPDADebugger, Boolean> haveExistingEnginesTrigger = new WeakHashMap<>();
private static final Map<JPDADebugger, DebugManagerHandler> dmHandlers = new HashMap<>();
private static final Map<JPDADebugger, JPDABreakpointListener> debugBPListeners = new HashMap<>();
Expand Down Expand Up @@ -110,9 +113,12 @@ public void sessionAdded(Session session) {
}
}
initLoadBP();
JPDABreakpoint bpService = addRemoteServiceInitBP(debugger);
DebuggerManager.getDebuggerManager().addBreakpoint(bpService);
JPDABreakpointListener bpl = addPolyglotEngineCreationBP(debugger);
LOG.log(Level.FINE, "TruffleDebugManager.sessionAdded({0}), adding BP listener to {1}", new Object[]{session, debugManagerLoadBP});
synchronized (debugBPListeners) {
initServiceBPs.put(debugger, bpService);
debugBPListeners.put(debugger, bpl);
}
}
Expand All @@ -123,10 +129,15 @@ public void sessionRemoved(Session session) {
if (debugger == null) {
return ;
}
JPDABreakpoint bpService;
JPDABreakpointListener bpl;
synchronized (debugBPListeners) {
bpService = initServiceBPs.remove(debugger);
bpl = debugBPListeners.remove(debugger);
}
if (bpService != null) {
DebuggerManager.getDebuggerManager().removeBreakpoint(bpService);
}
if (bpl != null) {
LOG.log(Level.FINE, "TruffleDebugManager.engineRemoved({0}), removing BP listener from {1}", new Object[]{session, debugManagerLoadBP});
debugManagerLoadBP.removeJPDABreakpointListener(bpl);
Expand All @@ -141,6 +152,30 @@ public void sessionRemoved(Session session) {
}
}

private JPDABreakpoint addRemoteServiceInitBP(final JPDADebugger debugger) {
MethodBreakpoint bp = MethodBreakpoint.create(REMOTE_SERVICES_TRIGGER_CLASS, REMOTE_SERVICES_TRIGGER_METHOD);
bp.setBreakpointType(MethodBreakpoint.TYPE_METHOD_ENTRY);
bp.setHidden(true);
bp.setSession(debugger);

JPDABreakpointListener bpl = new JPDABreakpointListener() {
@Override
public void breakpointReached(JPDABreakpointEvent event) {
try {
if (event.getDebugger() == debugger) {
DebugManagerHandler dmh = getDebugManagerHandler(debugger);
dmh.initDebuggerRemoteService(event.getThread());
DebuggerManager.getDebuggerManager().removeBreakpoint(bp);
}
} finally {
event.resume();
}
}
};
bp.addJPDABreakpointListener(bpl);
return bp;
}

private JPDABreakpointListener addPolyglotEngineCreationBP(final JPDADebugger debugger) {
JPDABreakpointListener bpl = new JPDABreakpointListener() {
@Override
Expand Down Expand Up @@ -249,7 +284,7 @@ private void submitExistingEnginesProbe(final JPDADebugger debugger, List<JPDACl
DebuggerManager.getDebuggerManager().addBreakpoint(execTrigger);
}

private void haveNewPE(JPDADebugger debugger, JPDAThreadImpl thread, ObjectReference engine) {
private DebugManagerHandler getDebugManagerHandler(JPDADebugger debugger) {
DebugManagerHandler dmh;
synchronized (dmHandlers) {
dmh = dmHandlers.get(debugger);
Expand All @@ -258,6 +293,11 @@ private void haveNewPE(JPDADebugger debugger, JPDAThreadImpl thread, ObjectRefer
dmHandlers.put(debugger, dmh);
}
}
return dmh;
}

private void haveNewPE(JPDADebugger debugger, JPDAThreadImpl thread, ObjectReference engine) {
DebugManagerHandler dmh = getDebugManagerHandler(debugger);
dmh.newPolyglotEngineInstance(engine, thread);
}

Expand Down

0 comments on commit 7fe5a90

Please sign in to comment.