Skip to content

Commit 08cbe52

Browse files
committed
[GR-51550] Added callback for method exit and use suspendHere() to suspend immediately.
PullRequest: graal/21733
2 parents 7681e87 + b66c04f commit 08cbe52

File tree

5 files changed

+57
-42
lines changed

5 files changed

+57
-42
lines changed

espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/api/VMEventListenerImpl.java

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import com.oracle.truffle.api.interop.InvalidArrayIndexException;
3737
import com.oracle.truffle.api.interop.UnknownIdentifierException;
3838
import com.oracle.truffle.api.interop.UnsupportedMessageException;
39+
import com.oracle.truffle.api.nodes.Node;
3940
import com.oracle.truffle.espresso.jdwp.impl.BreakpointInfo;
4041
import com.oracle.truffle.espresso.jdwp.impl.ClassPrepareRequest;
4142
import com.oracle.truffle.espresso.jdwp.impl.DebuggerController;
@@ -161,13 +162,13 @@ public void clearAllBreakpointRequests() {
161162

162163
@Override
163164
@TruffleBoundary
164-
public boolean onFieldModification(FieldRef field, Object receiver, Object value) {
165+
public boolean onFieldModification(FieldRef field, Node node, Object receiver, Object value) {
165166
boolean active = false;
166167
for (FieldBreakpoint info : field.getFieldBreakpointInfos()) {
167168
if (info.isModificationBreakpoint()) {
168169
// OK, tell the Debug API to suspend the thread now
169170
debuggerController.prepareFieldBreakpoint(new FieldBreakpointEvent((FieldBreakpointInfo) info, receiver, value));
170-
debuggerController.suspend(context.asGuestThread(Thread.currentThread()));
171+
debuggerController.suspendHere(node);
171172
active = true;
172173
}
173174
}
@@ -176,13 +177,13 @@ public boolean onFieldModification(FieldRef field, Object receiver, Object value
176177

177178
@Override
178179
@TruffleBoundary
179-
public boolean onFieldAccess(FieldRef field, Object receiver) {
180+
public boolean onFieldAccess(FieldRef field, Node node, Object receiver) {
180181
boolean active = false;
181182
for (FieldBreakpoint info : field.getFieldBreakpointInfos()) {
182183
if (info.isAccessBreakpoint()) {
183184
// OK, tell the Debug API to suspend the thread now
184185
debuggerController.prepareFieldBreakpoint(new FieldBreakpointEvent((FieldBreakpointInfo) info, receiver));
185-
debuggerController.suspend(context.asGuestThread(Thread.currentThread()));
186+
debuggerController.suspendHere(node);
186187
active = true;
187188
}
188189
}
@@ -191,7 +192,7 @@ public boolean onFieldAccess(FieldRef field, Object receiver) {
191192

192193
@Override
193194
@TruffleBoundary
194-
public boolean onMethodEntry(MethodRef method, Object scope) {
195+
public boolean onMethodEntry(MethodRef method, Node node, Object scope) {
195196
boolean active = false;
196197
// collect variable information from scope
197198
List<MethodVariable> variables = new ArrayList<>(1);
@@ -216,7 +217,7 @@ public boolean onMethodEntry(MethodRef method, Object scope) {
216217
if (hook.onMethodEnter(method, variables.toArray(new MethodVariable[variables.size()]))) {
217218
// OK, tell the Debug API to suspend the thread now
218219
debuggerController.prepareMethodBreakpoint(new MethodBreakpointEvent((MethodBreakpointInfo) hook, null));
219-
debuggerController.suspend(context.asGuestThread(Thread.currentThread()));
220+
debuggerController.suspendHere(node);
220221
active = true;
221222

222223
switch (hook.getKind()) {
@@ -236,13 +237,13 @@ public boolean onMethodEntry(MethodRef method, Object scope) {
236237

237238
@Override
238239
@TruffleBoundary
239-
public boolean onMethodReturn(MethodRef method, Object returnValue) {
240+
public boolean onMethodReturn(MethodRef method, Node node, Object returnValue) {
240241
boolean active = false;
241242
for (MethodHook hook : method.getMethodHooks()) {
242243
if (hook.onMethodExit(method, returnValue)) {
243244
// OK, tell the Debug API to suspend the thread now
244245
debuggerController.prepareMethodBreakpoint(new MethodBreakpointEvent((MethodBreakpointInfo) hook, returnValue));
245-
debuggerController.suspend(context.asGuestThread(Thread.currentThread()));
246+
debuggerController.suspendHere(node);
246247
active = true;
247248

248249
switch (hook.getKind()) {

espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/api/VMListener.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
*/
2323
package com.oracle.truffle.espresso.jdwp.api;
2424

25+
import com.oracle.truffle.api.nodes.Node;
26+
2527
public interface VMListener {
2628

2729
void vmStarted(boolean suspend);
@@ -57,7 +59,7 @@ public interface VMListener {
5759
* @param value the new field value
5860
* @return true if a breakpoint should be hit due to the modification
5961
*/
60-
boolean onFieldModification(FieldRef field, Object receiver, Object value);
62+
boolean onFieldModification(FieldRef field, Node node, Object receiver, Object value);
6163

6264
/**
6365
* This method will be called when a field is about to be accessed. The method will determine if
@@ -67,7 +69,7 @@ public interface VMListener {
6769
* @param receiver owner of the field
6870
* @return true if a breakpoint should be hit due to the modification
6971
*/
70-
boolean onFieldAccess(FieldRef field, Object receiver);
72+
boolean onFieldAccess(FieldRef field, Node node, Object receiver);
7173

7274
/**
7375
* This method will be called when a method is entered iff there is an active
@@ -79,7 +81,7 @@ public interface VMListener {
7981
* local variables in scope
8082
* @return true a breakpoint should be hit on method entry
8183
*/
82-
boolean onMethodEntry(MethodRef method, Object scope);
84+
boolean onMethodEntry(MethodRef method, Node node, Object scope);
8385

8486
/**
8587
* This method will be called when a method is about to return iff there is an active
@@ -90,7 +92,7 @@ public interface VMListener {
9092
* @param returnValue the return value
9193
* @return true if a breakpoint should be hit on method exit
9294
*/
93-
boolean onMethodReturn(MethodRef method, Object returnValue);
95+
boolean onMethodReturn(MethodRef method, Node node, Object returnValue);
9496

9597
/**
9698
* This method should be called when when the monitor wait(timeout) method is invoked in the

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -547,6 +547,11 @@ public void resumeAll() {
547547
}
548548
}
549549

550+
public void suspendHere(Node node) {
551+
boolean success = debuggerSession.suspendHere(node);
552+
assert success : "Immediate suspend was not successful, must be called on language execution thread";
553+
}
554+
550555
public void suspend(Object guestThread) {
551556
SimpleLock suspendLock = getSuspendLock(guestThread);
552557
synchronized (suspendLock) {

espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/nodes/BytecodeNode.java

Lines changed: 29 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1279,7 +1279,8 @@ private Object executeBodyFromBCI(VirtualFrame frame, int startBCI, int startTop
12791279
}
12801280
Object returnValue = getReturnValueAsObject(frame, top);
12811281
if (instrument != null) {
1282-
instrument.exitAt(frame, statementIndex, returnValue);
1282+
instrument.notifyExit(frame, this, returnValue);
1283+
instrument.notifyStatementExit(frame, statementIndex, returnValue);
12831284
}
12841285

12851286
// This branch must not be a loop exit.
@@ -2739,64 +2740,64 @@ private int putField(VirtualFrame frame, int top, Field field, int curBCI, int o
27392740
case 'Z':
27402741
boolean booleanValue = stackIntToBoolean(popInt(frame, top - 1));
27412742
if (instrumentation != null) {
2742-
instrumentation.notifyFieldModification(frame, statementIndex, field, receiver, booleanValue);
2743+
instrumentation.notifyFieldModification(frame, statementIndex, field, this, receiver, booleanValue);
27432744
}
27442745
InterpreterToVM.setFieldBoolean(booleanValue, receiver, field);
27452746
break;
27462747
case 'B':
27472748
byte byteValue = (byte) popInt(frame, top - 1);
27482749
if (instrumentation != null) {
2749-
instrumentation.notifyFieldModification(frame, statementIndex, field, receiver, byteValue);
2750+
instrumentation.notifyFieldModification(frame, statementIndex, field, this, receiver, byteValue);
27502751
}
27512752
InterpreterToVM.setFieldByte(byteValue, receiver, field);
27522753
break;
27532754
case 'C':
27542755
char charValue = (char) popInt(frame, top - 1);
27552756
if (instrumentation != null) {
2756-
instrumentation.notifyFieldModification(frame, statementIndex, field, receiver, charValue);
2757+
instrumentation.notifyFieldModification(frame, statementIndex, field, this, receiver, charValue);
27572758
}
27582759
InterpreterToVM.setFieldChar(charValue, receiver, field);
27592760
break;
27602761
case 'S':
27612762
short shortValue = (short) popInt(frame, top - 1);
27622763
if (instrumentation != null) {
2763-
instrumentation.notifyFieldModification(frame, statementIndex, field, receiver, shortValue);
2764+
instrumentation.notifyFieldModification(frame, statementIndex, field, this, receiver, shortValue);
27642765
}
27652766
InterpreterToVM.setFieldShort(shortValue, receiver, field);
27662767
break;
27672768
case 'I':
27682769
int intValue = popInt(frame, top - 1);
27692770
if (instrumentation != null) {
2770-
instrumentation.notifyFieldModification(frame, statementIndex, field, receiver, intValue);
2771+
instrumentation.notifyFieldModification(frame, statementIndex, field, this, receiver, intValue);
27712772
}
27722773
InterpreterToVM.setFieldInt(intValue, receiver, field);
27732774
break;
27742775
case 'D':
27752776
double doubleValue = popDouble(frame, top - 1);
27762777
if (instrumentation != null) {
2777-
instrumentation.notifyFieldModification(frame, statementIndex, field, receiver, doubleValue);
2778+
instrumentation.notifyFieldModification(frame, statementIndex, field, this, receiver, doubleValue);
27782779
}
27792780
InterpreterToVM.setFieldDouble(doubleValue, receiver, field);
27802781
break;
27812782
case 'F':
27822783
float floatValue = popFloat(frame, top - 1);
27832784
if (instrumentation != null) {
2784-
instrumentation.notifyFieldModification(frame, statementIndex, field, receiver, floatValue);
2785+
instrumentation.notifyFieldModification(frame, statementIndex, field, this, receiver, floatValue);
27852786
}
27862787
InterpreterToVM.setFieldFloat(floatValue, receiver, field);
27872788
break;
27882789
case 'J':
27892790
long longValue = popLong(frame, top - 1);
27902791
if (instrumentation != null) {
2791-
instrumentation.notifyFieldModification(frame, statementIndex, field, receiver, longValue);
2792+
instrumentation.notifyFieldModification(frame, statementIndex, field, this, receiver, longValue);
27922793
}
27932794
InterpreterToVM.setFieldLong(longValue, receiver, field);
27942795
break;
27952796
case '[': // fall through
27962797
case 'L':
27972798
StaticObject value = popObject(frame, top - 1);
27982799
if (instrumentation != null) {
2799-
instrumentation.notifyFieldModification(frame, statementIndex, field, receiver, value);
2800+
instrumentation.notifyFieldModification(frame, statementIndex, field, this, receiver, value);
28002801
}
28012802
InterpreterToVM.setFieldObject(value, receiver, field);
28022803
break;
@@ -2847,7 +2848,7 @@ private int getField(VirtualFrame frame, int top, Field field, int curBCI, int o
28472848
}
28482849

28492850
if (instrumentation != null) {
2850-
instrumentation.notifyFieldAccess(frame, statementIndex, field, receiver);
2851+
instrumentation.notifyFieldAccess(frame, statementIndex, field, this, receiver);
28512852
}
28522853

28532854
int resultAt = mode.isStatic() ? top : (top - 1);
@@ -2901,14 +2902,14 @@ public String toString() {
29012902
public void notifyFieldModification(VirtualFrame frame, int index, Field field, StaticObject receiver, Object value) {
29022903
// Notifications are only for Espresso objects
29032904
if (instrumentation != null && (noForeignObjects.isValid() || receiver.isEspressoObject())) {
2904-
instrumentation.notifyFieldModification(frame, index, field, receiver, value);
2905+
instrumentation.notifyFieldModification(frame, index, field, this, receiver, value);
29052906
}
29062907
}
29072908

29082909
public void notifyFieldAccess(VirtualFrame frame, int index, Field field, StaticObject receiver) {
29092910
// Notifications are only for Espresso objects
29102911
if (instrumentation != null && (noForeignObjects.isValid() || receiver.isEspressoObject())) {
2911-
instrumentation.notifyFieldAccess(frame, index, field, receiver);
2912+
instrumentation.notifyFieldAccess(frame, index, field, this, receiver);
29122913
}
29132914
}
29142915

@@ -2980,7 +2981,7 @@ private static boolean assertionsEnabled() {
29802981
*/
29812982
void notifyStatementChange(VirtualFrame frame, int statementIndex, int nextStatementIndex, int targetBci) {
29822983
assert statementIndex != nextStatementIndex;
2983-
notifyStatementExit(frame, statementIndex);
2984+
notifyStatementExit(frame, statementIndex, StaticObject.NULL);
29842985
setBCI(frame, targetBci);
29852986
notifyStatementEnter(frame, nextStatementIndex);
29862987
}
@@ -2995,20 +2996,26 @@ void notifyStatementResume(VirtualFrame frame, int statementIndex) {
29952996
resumeAt(frame, statementIndex);
29962997
}
29972998

2998-
void notifyStatementExit(VirtualFrame frame, int statementIndex) {
2999+
void notifyStatementExit(VirtualFrame frame, int statementIndex, Object returnValue) {
29993000
CompilerAsserts.partialEvaluationConstant(statementIndex);
3000-
exitAt(frame, statementIndex, StaticObject.NULL);
3001+
exitAt(frame, statementIndex, returnValue);
30013002
}
30023003

30033004
public void notifyEntry(VirtualFrame frame, AbstractInstrumentableBytecodeNode instrumentableNode) {
30043005
if (context.shouldReportVMEvents() && method.getMethod().hasActiveHook()) {
3005-
context.reportOnMethodEntry(method, instrumentableNode.getScope(frame, true));
3006+
context.reportOnMethodEntry(method, instrumentableNode, instrumentableNode.getScope(frame, true));
30063007
}
30073008
}
30083009

30093010
public void notifyResume(VirtualFrame frame, AbstractInstrumentableBytecodeNode instrumentableNode) {
30103011
if (context.shouldReportVMEvents() && method.getMethod().hasActiveHook()) {
3011-
context.reportOnMethodEntry(method, instrumentableNode.getScope(frame, true));
3012+
context.reportOnMethodEntry(method, instrumentableNode, instrumentableNode.getScope(frame, true));
3013+
}
3014+
}
3015+
3016+
public void notifyExit(@SuppressWarnings("unused") VirtualFrame frame, AbstractInstrumentableBytecodeNode instrumentableNode, Object returnValue) {
3017+
if (context.shouldReportVMEvents() && method.getMethod().hasActiveHook()) {
3018+
context.reportOnMethodReturn(method, instrumentableNode, returnValue);
30123019
}
30133020
}
30143021

@@ -3028,17 +3035,17 @@ void notifyYieldAt(VirtualFrame frame, Object o, int statementIndex) {
30283035
probeNode.onYield(frame, o);
30293036
}
30303037

3031-
public void notifyFieldModification(VirtualFrame frame, int index, Field field, StaticObject receiver, Object value) {
3038+
public void notifyFieldModification(VirtualFrame frame, int index, Field field, AbstractInstrumentableBytecodeNode instrumentableNode, StaticObject receiver, Object value) {
30323039
if (context.shouldReportVMEvents() && field.hasActiveBreakpoint()) {
3033-
if (context.reportOnFieldModification(field, receiver, value)) {
3040+
if (context.reportOnFieldModification(field, instrumentableNode, receiver, value)) {
30343041
enterAt(frame, index);
30353042
}
30363043
}
30373044
}
30383045

3039-
public void notifyFieldAccess(VirtualFrame frame, int index, Field field, StaticObject receiver) {
3046+
public void notifyFieldAccess(VirtualFrame frame, int index, Field field, AbstractInstrumentableBytecodeNode instrumentableNode, StaticObject receiver) {
30403047
if (context.shouldReportVMEvents() && field.hasActiveBreakpoint()) {
3041-
if (context.reportOnFieldAccess(field, receiver)) {
3048+
if (context.reportOnFieldAccess(field, instrumentableNode, receiver)) {
30423049
enterAt(frame, index);
30433050
}
30443051
}

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

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1250,24 +1250,24 @@ public void reportOnContendedMonitorEntered(StaticObject obj) {
12501250
espressoEnv.getEventListener().onContendedMonitorEntered(obj);
12511251
}
12521252

1253-
public boolean reportOnMethodEntry(Method.MethodVersion methodVersion, Object scope) {
1253+
public boolean reportOnMethodEntry(Method.MethodVersion methodVersion, Node node, Object scope) {
12541254
assert shouldReportVMEvents();
1255-
return espressoEnv.getEventListener().onMethodEntry(methodVersion.getMethod(), scope);
1255+
return espressoEnv.getEventListener().onMethodEntry(methodVersion.getMethod(), node, scope);
12561256
}
12571257

1258-
public boolean reportOnMethodReturn(Method.MethodVersion methodVersion, Object returnValue) {
1258+
public boolean reportOnMethodReturn(Method.MethodVersion methodVersion, Node node, Object returnValue) {
12591259
assert shouldReportVMEvents();
1260-
return espressoEnv.getEventListener().onMethodReturn(methodVersion.getMethod(), returnValue);
1260+
return espressoEnv.getEventListener().onMethodReturn(methodVersion.getMethod(), node, returnValue);
12611261
}
12621262

1263-
public boolean reportOnFieldModification(Field field, StaticObject receiver, Object value) {
1263+
public boolean reportOnFieldModification(Field field, Node node, StaticObject receiver, Object value) {
12641264
assert shouldReportVMEvents();
1265-
return espressoEnv.getEventListener().onFieldModification(field, receiver, value);
1265+
return espressoEnv.getEventListener().onFieldModification(field, node, receiver, value);
12661266
}
12671267

1268-
public boolean reportOnFieldAccess(Field field, StaticObject receiver) {
1268+
public boolean reportOnFieldAccess(Field field, Node node, StaticObject receiver) {
12691269
assert shouldReportVMEvents();
1270-
return espressoEnv.getEventListener().onFieldAccess(field, receiver);
1270+
return espressoEnv.getEventListener().onFieldAccess(field, node, receiver);
12711271
}
12721272
// endregion VM event reporting
12731273

0 commit comments

Comments
 (0)