Skip to content

Commit e1751e9

Browse files
committed
[GR-68888] Handle multiple contexts.
PullRequest: graal/21916
2 parents 4eb430d + 42a9d17 commit e1751e9

File tree

4 files changed

+123
-68
lines changed

4 files changed

+123
-68
lines changed

espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/DebuggerController.java

Lines changed: 9 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@
4444
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
4545
import com.oracle.truffle.api.RootCallTarget;
4646
import com.oracle.truffle.api.Truffle;
47-
import com.oracle.truffle.api.TruffleContext;
4847
import com.oracle.truffle.api.TruffleLogger;
4948
import com.oracle.truffle.api.debug.Breakpoint;
5049
import com.oracle.truffle.api.debug.DebugStackFrame;
@@ -58,8 +57,6 @@
5857
import com.oracle.truffle.api.debug.SuspensionFilter;
5958
import com.oracle.truffle.api.frame.Frame;
6059
import com.oracle.truffle.api.frame.FrameInstance;
61-
import com.oracle.truffle.api.instrumentation.ContextsListener;
62-
import com.oracle.truffle.api.nodes.LanguageInfo;
6360
import com.oracle.truffle.api.nodes.Node;
6461
import com.oracle.truffle.api.nodes.RootNode;
6562
import com.oracle.truffle.espresso.jdwp.api.CallFrame;
@@ -71,7 +68,7 @@
7168
import com.oracle.truffle.espresso.jdwp.api.MethodVersionRef;
7269
import com.oracle.truffle.espresso.jdwp.api.VMEventListener;
7370

74-
public final class DebuggerController implements ContextsListener {
71+
public final class DebuggerController {
7572

7673
private static final StepConfig STEP_CONFIG = StepConfig.newBuilder().suspendAnchors(SourceElement.ROOT, SuspendAnchor.AFTER).build();
7774

@@ -91,15 +88,14 @@ public final class DebuggerController implements ContextsListener {
9188
private volatile HandshakeController hsController = null;
9289
private final Lock resetting = new ReentrantLock();
9390
private volatile boolean isClosing;
94-
private JDWPOptions options;
95-
private DebuggerSession debuggerSession;
96-
private Ids<Object> ids;
97-
private Debugger debugger;
91+
private final JDWPOptions options;
92+
private final DebuggerSession debuggerSession;
93+
private final Ids<Object> ids;
94+
private final Debugger debugger;
9895
private final GCPrevention gcPrevention;
9996
private final ThreadSuspension threadSuspension;
10097
private final EventFilters eventFilters;
101-
private VMEventListener eventListener;
102-
private TruffleContext truffleContext;
98+
private final VMEventListener eventListener;
10399
private Object initialThread;
104100
private final TruffleLogger jdwpLogger;
105101
private DebuggerConnection connection;
@@ -110,14 +106,11 @@ public final class DebuggerController implements ContextsListener {
110106
// itself, it must check this field and exit the context if set.
111107
private volatile Throwable lateStartupError;
112108

113-
public DebuggerController(TruffleLogger logger) {
109+
public DebuggerController(TruffleLogger logger, Debugger debug, JDWPOptions jdwpOptions, JDWPContext jdwpContext, Object thread, VMEventListener vmEventListener) {
114110
this.gcPrevention = new GCPrevention();
115111
this.threadSuspension = new ThreadSuspension();
116112
this.eventFilters = new EventFilters();
117113
this.jdwpLogger = logger;
118-
}
119-
120-
public void initialize(Debugger debug, JDWPOptions jdwpOptions, JDWPContext jdwpContext, Object thread, VMEventListener vmEventListener) {
121114
this.debugger = debug;
122115
this.options = jdwpOptions;
123116
this.context = jdwpContext;
@@ -154,9 +147,7 @@ public void init(JDWPContext jdwpContext) {
154147

155148
public void reInitialize() {
156149
// create a new DebuggerController instance
157-
DebuggerController newController = new DebuggerController(jdwpLogger);
158-
newController.truffleContext = truffleContext;
159-
newController.initialize(debugger, options, context, initialThread, eventListener);
150+
DebuggerController newController = new DebuggerController(jdwpLogger, debugger, options, context, initialThread, eventListener);
160151
context.replaceController(newController);
161152
assert newController.setupState != null;
162153

@@ -683,23 +674,7 @@ public VMEventListener getEventListener() {
683674
return eventListener;
684675
}
685676

686-
public Object enterTruffleContext() {
687-
assert truffleContext != null;
688-
return truffleContext.enter(null);
689-
}
690-
691-
public void leaveTruffleContext(Object previous) {
692-
assert truffleContext != null;
693-
truffleContext.leave(null, previous);
694-
}
695-
696-
@Override
697-
public void onLanguageContextInitialized(TruffleContext con, @SuppressWarnings("unused") LanguageInfo language) {
698-
if (!"java".equals(language.getId())) {
699-
return;
700-
}
701-
truffleContext = con;
702-
677+
public void onLanguageContextInitialized() {
703678
// With the Espresso context initialized, we can now complete the JDWP setup and establish
704679
// the connection.
705680
assert setupState != null;
@@ -1282,29 +1257,4 @@ public void severe(String message, Throwable error) {
12821257
jdwpLogger.log(Level.SEVERE, message, error);
12831258
}
12841259

1285-
@Override
1286-
public void onContextCreated(@SuppressWarnings("unused") TruffleContext con) {
1287-
1288-
}
1289-
1290-
@Override
1291-
public void onLanguageContextCreated(@SuppressWarnings("unused") TruffleContext con, @SuppressWarnings("unused") LanguageInfo language) {
1292-
1293-
}
1294-
1295-
@Override
1296-
public void onLanguageContextFinalized(@SuppressWarnings("unused") TruffleContext con, @SuppressWarnings("unused") LanguageInfo language) {
1297-
1298-
}
1299-
1300-
@Override
1301-
public void onLanguageContextDisposed(@SuppressWarnings("unused") TruffleContext con, @SuppressWarnings("unused") LanguageInfo language) {
1302-
1303-
}
1304-
1305-
@Override
1306-
public void onContextClosed(@SuppressWarnings("unused") TruffleContext con) {
1307-
1308-
}
1309-
13101260
}
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
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.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
package com.oracle.truffle.espresso.jdwp.impl;
24+
25+
import java.util.Map;
26+
import java.util.concurrent.ConcurrentHashMap;
27+
28+
import com.oracle.truffle.api.TruffleContext;
29+
import com.oracle.truffle.api.TruffleLogger;
30+
import com.oracle.truffle.api.debug.Debugger;
31+
import com.oracle.truffle.api.instrumentation.ContextsListener;
32+
import com.oracle.truffle.api.nodes.LanguageInfo;
33+
import com.oracle.truffle.espresso.jdwp.api.JDWPContext;
34+
import com.oracle.truffle.espresso.jdwp.api.JDWPOptions;
35+
import com.oracle.truffle.espresso.jdwp.api.VMEventListener;
36+
37+
/**
38+
* Controller bound to the JDWP instrument that manages controllers for individual contexts.
39+
*/
40+
public final class DebuggerInstrumentController implements ContextsListener {
41+
42+
private final TruffleLogger jdwpLogger;
43+
private final Map<TruffleContext, DebuggerController> controllers = new ConcurrentHashMap<>();
44+
45+
public DebuggerInstrumentController(TruffleLogger logger) {
46+
this.jdwpLogger = logger;
47+
}
48+
49+
public DebuggerController createContextController(Debugger debug, JDWPOptions jdwpOptions, TruffleContext truffleContext, JDWPContext jdwpContext, Object thread, VMEventListener vmEventListener) {
50+
DebuggerController controller = new DebuggerController(jdwpLogger, debug, jdwpOptions, jdwpContext, thread, vmEventListener);
51+
controllers.put(truffleContext, controller);
52+
return controller;
53+
}
54+
55+
public void disposeController(TruffleContext context) {
56+
DebuggerController controller = controllers.remove(context);
57+
if (controller != null) {
58+
controller.disposeDebugger(false);
59+
}
60+
}
61+
62+
public void replaceController(TruffleContext context, DebuggerController newController) {
63+
controllers.put(context, newController);
64+
}
65+
66+
@Override
67+
public void onLanguageContextInitialized(TruffleContext context, LanguageInfo language) {
68+
if (!"java".equals(language.getId())) {
69+
return;
70+
}
71+
DebuggerController controller = controllers.get(context);
72+
if (controller != null) {
73+
controller.onLanguageContextInitialized();
74+
}
75+
}
76+
77+
@Override
78+
public void onContextCreated(TruffleContext context) {
79+
}
80+
81+
@Override
82+
public void onLanguageContextCreated(TruffleContext context, LanguageInfo language) {
83+
}
84+
85+
@Override
86+
public void onLanguageContextFinalized(TruffleContext context, LanguageInfo language) {
87+
}
88+
89+
@Override
90+
public void onLanguageContextDisposed(TruffleContext context, LanguageInfo language) {
91+
}
92+
93+
@Override
94+
public void onContextClosed(TruffleContext context) {
95+
}
96+
97+
}

espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/JDWPInstrument.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -25,17 +25,17 @@
2525
import com.oracle.truffle.api.instrumentation.TruffleInstrument;
2626
import com.oracle.truffle.api.instrumentation.TruffleInstrument.Registration;
2727

28-
@Registration(id = JDWPInstrument.ID, name = "Java debug wire protocol", services = DebuggerController.class)
28+
@Registration(id = JDWPInstrument.ID, name = "Java debug wire protocol", services = DebuggerInstrumentController.class)
2929
public final class JDWPInstrument extends TruffleInstrument {
3030

3131
public static final String ID = "jdwp";
3232

3333
@Override
3434
protected void onCreate(Env instrumentEnv) {
35-
// It is the DebuggerController that handles the complete lifecycle of a JDWP session. Here
36-
// we simply create a new controller instance, provide it as a service for lookup and
37-
// attaches a context listener to assist in setup and shutdown hooks.
38-
DebuggerController controller = new DebuggerController(instrumentEnv.getLogger(ID));
35+
// It is the DebuggerInstrumentController that handles the complete lifecycle of a JDWP
36+
// session. Here we simply create a new controller instance, provide it as a service for
37+
// lookup and attaches a context listener to assist in setup and shutdown hooks.
38+
DebuggerInstrumentController controller = new DebuggerInstrumentController(instrumentEnv.getLogger(ID));
3939
instrumentEnv.registerService(controller);
4040
instrumentEnv.getInstrumenter().attachContextsListener(controller, false);
4141
}

espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/runtime/JDWPContextImpl.java

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@
6868
import com.oracle.truffle.espresso.jdwp.api.TagConstants;
6969
import com.oracle.truffle.espresso.jdwp.api.VMEventListenerImpl;
7070
import com.oracle.truffle.espresso.jdwp.impl.DebuggerController;
71+
import com.oracle.truffle.espresso.jdwp.impl.DebuggerInstrumentController;
7172
import com.oracle.truffle.espresso.jdwp.impl.JDWPInstrument;
7273
import com.oracle.truffle.espresso.jdwp.impl.TypeTag;
7374
import com.oracle.truffle.espresso.meta.EspressoError;
@@ -98,18 +99,23 @@ public JDWPContextImpl(EspressoContext context) {
9899
this.ids = new Ids<>(StaticObject.NULL);
99100
}
100101

102+
private static DebuggerInstrumentController getInstrumentController(TruffleLanguage.Env env) {
103+
return env.lookup(env.getInstruments().get(JDWPInstrument.ID), DebuggerInstrumentController.class);
104+
}
105+
101106
public void jdwpInit(TruffleLanguage.Env env, Object mainThread, VMEventListenerImpl eventListener) {
102107
Debugger debugger = env.lookup(env.getInstruments().get("debugger"), Debugger.class);
103-
this.controller = env.lookup(env.getInstruments().get(JDWPInstrument.ID), DebuggerController.class);
108+
DebuggerInstrumentController instrumentController = getInstrumentController(env);
109+
this.controller = instrumentController.createContextController(debugger, context.getEspressoEnv().JDWPOptions, env.getContext(), this, mainThread, eventListener);
104110
vmEventListener = eventListener;
105111
eventListener.activate(mainThread, controller, this);
106-
controller.initialize(debugger, context.getEspressoEnv().JDWPOptions, this, mainThread, eventListener);
107112
}
108113

109114
public void finalizeContext() {
110115
if (context.getEspressoEnv().JDWPOptions != null) {
111116
if (controller != null) { // in case we exited before initializing the controller field
112-
controller.disposeDebugger(false);
117+
TruffleLanguage.Env env = context.getEnv();
118+
getInstrumentController(env).disposeController(env.getContext());
113119
}
114120
}
115121
}
@@ -118,6 +124,8 @@ public void finalizeContext() {
118124
public void replaceController(DebuggerController newController) {
119125
this.controller = newController;
120126
vmEventListener.replaceController(newController);
127+
TruffleLanguage.Env env = context.getEnv();
128+
getInstrumentController(env).replaceController(env.getContext(), newController);
121129
}
122130

123131
@Override

0 commit comments

Comments
 (0)