Skip to content

Commit 0e81c54

Browse files
committed
* Make sure we don't use the Truffle logger before we have the TruffleContext instance
* Avoid class init in InvokeEspressoNode specialization which can lead to deadlocks in the debugger
1 parent fc54c35 commit 0e81c54

File tree

17 files changed

+283
-240
lines changed

17 files changed

+283
-240
lines changed

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

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2019, 2022, 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
@@ -34,6 +34,7 @@
3434
import com.oracle.truffle.api.interop.UnsupportedMessageException;
3535
import com.oracle.truffle.api.nodes.Node;
3636
import com.oracle.truffle.api.nodes.RootNode;
37+
import com.oracle.truffle.espresso.jdwp.impl.DebuggerController;
3738
import com.oracle.truffle.espresso.jdwp.impl.JDWP;
3839

3940
public final class CallFrame {
@@ -53,10 +54,11 @@ public final class CallFrame {
5354
private final DebugStackFrame debugStackFrame;
5455
private final DebugScope debugScope;
5556
private final JDWPContext context;
57+
private final DebuggerController controller;
5658
private Object scope;
5759

5860
public CallFrame(long threadId, byte typeTag, long classId, MethodRef method, long methodId, long codeIndex, Frame frame, Node currentNode, RootNode rootNode,
59-
DebugStackFrame debugStackFrame, JDWPContext context) {
61+
DebugStackFrame debugStackFrame, JDWPContext context, DebuggerController controller) {
6062
this.threadId = threadId;
6163
this.typeTag = typeTag;
6264
this.classId = classId;
@@ -69,10 +71,11 @@ public CallFrame(long threadId, byte typeTag, long classId, MethodRef method, lo
6971
this.debugStackFrame = debugStackFrame;
7072
this.debugScope = debugStackFrame != null ? debugStackFrame.getScope() : null;
7173
this.context = context;
74+
this.controller = controller;
7275
}
7376

7477
public CallFrame(long threadId, byte typeTag, long classId, long methodId, long codeIndex) {
75-
this(threadId, typeTag, classId, null, methodId, codeIndex, null, null, null, null, null);
78+
this(threadId, typeTag, classId, null, methodId, codeIndex, null, null, null, null, null, null);
7679
}
7780

7881
public byte getTypeTag() {
@@ -115,7 +118,9 @@ public Object getThisValue() {
115118
try {
116119
return theScope != null ? INTEROP.readMember(theScope, "this") : null;
117120
} catch (UnsupportedMessageException | UnknownIdentifierException e) {
118-
JDWP.LOGGER.warning(() -> "Unable to read 'this' value from method: " + getMethod() + " with currentNode: " + currentNode.getClass());
121+
if (controller != null) {
122+
controller.warning(() -> "Unable to read 'this' value from method: " + getMethod() + " with currentNode: " + currentNode.getClass());
123+
}
119124
return INVALID_VALUE;
120125
}
121126
}
@@ -133,7 +138,9 @@ public void setVariable(Object value, String identifier) {
133138
try {
134139
INTEROP.writeMember(theScope, identifier, value);
135140
} catch (Exception e) {
136-
JDWP.LOGGER.warning(() -> "Unable to write member " + identifier + " from variables");
141+
if (controller != null) {
142+
controller.warning(() -> "Unable to write member " + identifier + " from variables");
143+
}
137144
}
138145
}
139146

@@ -151,10 +158,14 @@ private Object getScope() {
151158
try {
152159
scope = NodeLibrary.getUncached().getScope(node, frame, true);
153160
} catch (UnsupportedMessageException e) {
154-
JDWP.LOGGER.warning(() -> "Unable to get scope for " + currentNode.getClass());
161+
if (controller != null) {
162+
controller.warning(() -> "Unable to get scope for " + currentNode.getClass());
163+
}
155164
}
156165
} else {
157-
JDWP.LOGGER.warning(() -> "Unable to get scope for " + currentNode.getClass());
166+
if (controller != null) {
167+
controller.warning(() -> "Unable to get scope for " + currentNode.getClass());
168+
}
158169
}
159170
return scope;
160171
}

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

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

25-
import com.oracle.truffle.espresso.jdwp.impl.JDWP;
25+
import com.oracle.truffle.espresso.jdwp.impl.DebuggerController;
2626

2727
import java.lang.ref.WeakReference;
2828
import java.util.Arrays;
2929
import java.util.HashMap;
30+
import java.util.function.Supplier;
3031
import java.util.regex.Matcher;
3132
import java.util.regex.Pattern;
3233

@@ -54,6 +55,8 @@ public final class Ids<T> {
5455

5556
private HashMap<String, Long> innerClassIDMap = new HashMap<>(16);
5657

58+
private DebuggerController controller;
59+
5760
@SuppressWarnings({"unchecked", "rawtypes"})
5861
public Ids(T nullObject) {
5962
this.nullObject = nullObject;
@@ -68,15 +71,15 @@ public Ids(T nullObject) {
6871
*/
6972
public long getIdAsLong(T object) {
7073
if (object == null) {
71-
JDWP.LOGGER.finest(() -> "Null object when getting ID");
74+
log(() -> "Null object when getting ID");
7275
return 0;
7376
}
7477
// lookup in cache
7578
for (int i = 1; i < objects.length; i++) {
7679
// really slow lookup path
7780
if (objects[i].get() == object) {
7881
final int index = i;
79-
JDWP.LOGGER.finest(() -> "ID cache hit for object: " + object + " with ID: " + index);
82+
log(() -> "ID cache hit for object: " + object + " with ID: " + index);
8083
return i;
8184
}
8285
}
@@ -107,7 +110,7 @@ public long getId(Object object) {
107110
// really slow lookup path
108111
if (objects[i].get() == object) {
109112
final int index = i;
110-
JDWP.LOGGER.finest(() -> "ID cache hit for object: " + object + " with ID: " + index);
113+
log(() -> "ID cache hit for object: " + object + " with ID: " + index);
111114
return i;
112115
}
113116
}
@@ -122,16 +125,16 @@ public long getId(Object object) {
122125
*/
123126
public T fromId(int id) {
124127
if (id == 0) {
125-
JDWP.LOGGER.fine(() -> "Null object from ID: " + id);
128+
log(() -> "Null object from ID: " + id);
126129
return nullObject;
127130
}
128131
WeakReference<T> ref = objects[id];
129132
T o = ref.get();
130133
if (o == null) {
131-
JDWP.LOGGER.finest(() -> "object with ID: " + id + " was garbage collected");
134+
log(() -> "object with ID: " + id + " was garbage collected");
132135
return null;
133136
} else {
134-
JDWP.LOGGER.finest(() -> "returning object: " + o + " for ID: " + id);
137+
log(() -> "returning object: " + o + " for ID: " + id);
135138
return o;
136139
}
137140
}
@@ -147,7 +150,7 @@ private synchronized long generateUniqueId(T object) {
147150
WeakReference<T>[] expandedArray = Arrays.copyOf(objects, objects.length + 1);
148151
expandedArray[objects.length] = new WeakReference<>(object);
149152
objects = expandedArray;
150-
JDWP.LOGGER.finest(() -> "Generating new ID: " + id + " for object: " + object);
153+
log(() -> "Generating new ID: " + id + " for object: " + object);
151154
if (object instanceof KlassRef) {
152155
KlassRef klass = (KlassRef) object;
153156
Matcher matcher = ANON_INNER_CLASS_PATTERN.matcher(klass.getNameAsString());
@@ -161,7 +164,7 @@ private synchronized long generateUniqueId(T object) {
161164
public void replaceObject(T original, T replacement) {
162165
int id = (int) getIdAsLong(original);
163166
objects[id] = new WeakReference<>(replacement);
164-
JDWP.LOGGER.finest(() -> "Replaced ID: " + id);
167+
log(() -> "Replaced ID: " + id);
165168
}
166169

167170
@SuppressWarnings({"unchecked", "rawtypes"})
@@ -186,4 +189,14 @@ private void removeId(KlassRef klass) {
186189
public boolean checkRemoved(long refTypeId) {
187190
return innerClassIDMap.containsValue(refTypeId);
188191
}
192+
193+
public void injectController(DebuggerController control) {
194+
this.controller = control;
195+
}
196+
197+
private void log(Supplier<String> supplier) {
198+
if (controller != null) {
199+
controller.finest(supplier);
200+
}
201+
}
189202
}

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

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2019, 2022, 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
@@ -279,7 +279,7 @@ public Void call() {
279279
if (holdEvents) {
280280
heldEvents.add(stream);
281281
} else {
282-
JDWP.LOGGER.fine(() -> "SENDING CLASS PREPARE EVENT FOR KLASS: " + klass.getNameAsString() + " WITH THREAD " + context.getThreadName(prepareThread));
282+
debuggerController.fine(() -> "SENDING CLASS PREPARE EVENT FOR KLASS: " + klass.getNameAsString() + " WITH THREAD " + context.getThreadName(prepareThread));
283283
connection.queuePacket(stream);
284284
}
285285
return null;
@@ -320,7 +320,7 @@ public void breakpointHit(BreakpointInfo info, CallFrame frame, Object currentTh
320320
stream.writeLong(frame.getClassId());
321321
stream.writeLong(frame.getMethodId());
322322
stream.writeLong(frame.getCodeIndex());
323-
JDWP.LOGGER.fine(() -> "Sending breakpoint hit event in thread: " + context.getThreadName(currentThread) + " with suspension policy: " + info.getSuspendPolicy());
323+
debuggerController.fine(() -> "Sending breakpoint hit event in thread: " + context.getThreadName(currentThread) + " with suspension policy: " + info.getSuspendPolicy());
324324
if (holdEvents) {
325325
heldEvents.add(stream);
326326
} else {
@@ -492,7 +492,7 @@ public void stepCompleted(SteppingInfo info, CallFrame currentFrame) {
492492
if (info.isPopFrames()) {
493493
// send reply packet when "step" is completed
494494
PacketStream reply = new PacketStream().replyPacket().id(info.getRequestId());
495-
JDWP.LOGGER.fine(() -> "Sending pop frames reply packet");
495+
debuggerController.fine(() -> "Sending pop frames reply packet");
496496
if (holdEvents) {
497497
heldEvents.add(reply);
498498
} else {
@@ -515,7 +515,7 @@ public void stepCompleted(SteppingInfo info, CallFrame currentFrame) {
515515
stream.writeLong(currentFrame.getMethodId());
516516
long codeIndex = info.getStepOutBCI() != -1 ? info.getStepOutBCI() : currentFrame.getCodeIndex();
517517
stream.writeLong(codeIndex);
518-
JDWP.LOGGER.fine(() -> "Sending step completed event");
518+
debuggerController.fine(() -> "Sending step completed event");
519519

520520
if (holdEvents) {
521521
heldEvents.add(stream);
@@ -548,7 +548,7 @@ private void sendMonitorContendedEnterEvent(MonitorEvent monitorEvent, CallFrame
548548
stream.writeLong(currentFrame.getMethodId());
549549
long codeIndex = currentFrame.getCodeIndex();
550550
stream.writeLong(codeIndex);
551-
JDWP.LOGGER.fine(() -> "Sending monitor contended event");
551+
debuggerController.fine(() -> "Sending monitor contended event");
552552

553553
if (holdEvents) {
554554
heldEvents.add(stream);
@@ -590,7 +590,7 @@ private void sendMonitorContendedEnteredEvent(MonitorEvent monitorEvent, CallFra
590590
stream.writeLong(currentFrame.getMethodId());
591591
long codeIndex = currentFrame.getCodeIndex();
592592
stream.writeLong(codeIndex);
593-
JDWP.LOGGER.fine(() -> "Sending monitor contended entered event");
593+
debuggerController.fine(() -> "Sending monitor contended entered event");
594594

595595
if (holdEvents) {
596596
heldEvents.add(stream);
@@ -634,7 +634,7 @@ public void sendMonitorWaitEvent(Object monitor, long timeout, RequestFilter fil
634634

635635
// timeout
636636
stream.writeLong(timeout);
637-
JDWP.LOGGER.fine(() -> "Sending monitor wait event");
637+
debuggerController.fine(() -> "Sending monitor wait event");
638638

639639
if (holdEvents) {
640640
heldEvents.add(stream);
@@ -711,7 +711,7 @@ private void sendMonitorWaitedEvent(Object monitor, boolean timedOut, RequestFil
711711

712712
// timeout
713713
stream.writeBoolean(timedOut);
714-
JDWP.LOGGER.fine(() -> "Sending monitor wait event");
714+
debuggerController.fine(() -> "Sending monitor wait event");
715715

716716
if (holdEvents) {
717717
heldEvents.add(stream);
@@ -852,7 +852,7 @@ public void threadStarted(Object thread) {
852852
stream.writeByte(RequestedJDWPEvents.THREAD_START);
853853
stream.writeInt(threadStartedRequestId);
854854
stream.writeLong(ids.getIdAsLong(thread));
855-
JDWP.LOGGER.fine(() -> "sending thread started event for thread: " + context.getThreadName(thread));
855+
debuggerController.fine(() -> "sending thread started event for thread: " + context.getThreadName(thread));
856856
if (holdEvents) {
857857
heldEvents.add(stream);
858858
} else {
@@ -909,26 +909,26 @@ public boolean vmDied() {
909909
stream.writeByte(RequestedJDWPEvents.VM_DEATH);
910910
stream.writeInt(0);
911911
// don't queue this packet, send immediately
912-
connection.sendVMDied(stream);
912+
connection.sendVMDied(stream, debuggerController);
913913
return vmDeathSuspendPolicy != SuspendStrategy.NONE;
914914
}
915915

916916
@Override
917917
public void addClassUnloadRequestId(int id) {
918918
// not implemented yet
919-
JDWP.LOGGER.fine(() -> "class unload events not yet implemented!");
919+
debuggerController.fine(() -> "class unload events not yet implemented!");
920920
}
921921

922922
@Override
923923
public void addThreadStartedRequestId(int id, byte suspendPolicy) {
924-
JDWP.LOGGER.fine(() -> "Adding thread start listener");
924+
debuggerController.fine(() -> "Adding thread start listener");
925925
this.threadStartedRequestId = id;
926926
this.threadStartSuspendPolicy = suspendPolicy;
927927
}
928928

929929
@Override
930930
public void addThreadDiedRequestId(int id, byte suspendPolicy) {
931-
JDWP.LOGGER.fine(() -> "Adding thread death listener");
931+
debuggerController.fine(() -> "Adding thread death listener");
932932
this.threadDeathRequestId = id;
933933
this.threadDeathSuspendPolicy = suspendPolicy;
934934
}

0 commit comments

Comments
 (0)