Skip to content

Commit bcd866b

Browse files
author
Jaroslav Tulach
committed
Allow Insight scripts to iterate over current stack
1 parent 39f111b commit bcd866b

3 files changed

Lines changed: 99 additions & 1 deletion

File tree

tools/src/com.oracle.truffle.tools.agentscript/src/com/oracle/truffle/tools/agentscript/impl/EventContextObject.java

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,16 +25,26 @@
2525
package com.oracle.truffle.tools.agentscript.impl;
2626

2727
import com.oracle.truffle.api.CompilerDirectives;
28+
import com.oracle.truffle.api.Truffle;
29+
import com.oracle.truffle.api.TruffleStackTrace;
30+
import com.oracle.truffle.api.frame.Frame;
31+
import com.oracle.truffle.api.frame.FrameInstance;
32+
import com.oracle.truffle.api.frame.FrameSlot;
2833
import com.oracle.truffle.api.instrumentation.EventContext;
2934
import com.oracle.truffle.api.interop.ArityException;
3035
import com.oracle.truffle.api.interop.InteropException;
3136
import com.oracle.truffle.api.interop.InteropLibrary;
37+
import com.oracle.truffle.api.interop.NodeLibrary;
3238
import com.oracle.truffle.api.interop.TruffleObject;
3339
import com.oracle.truffle.api.interop.UnknownIdentifierException;
40+
import com.oracle.truffle.api.interop.UnsupportedMessageException;
41+
import com.oracle.truffle.api.interop.UnsupportedTypeException;
3442
import com.oracle.truffle.api.library.ExportLibrary;
3543
import com.oracle.truffle.api.library.ExportMessage;
3644
import com.oracle.truffle.api.nodes.Node;
3745
import com.oracle.truffle.api.source.SourceSection;
46+
import java.util.logging.Level;
47+
import java.util.logging.Logger;
3848

3949
@SuppressWarnings("unused")
4050
@ExportLibrary(InteropLibrary.class)
@@ -142,12 +152,40 @@ static Object invokeMember(EventContextObject obj, String member, Object[] args)
142152
VariablesObject vars = (VariablesObject) args[0];
143153
return vars.getReturnValue();
144154
}
155+
if ("iterateFrames".equals(member)) {
156+
CompilerDirectives.transferToInterpreter();
157+
if (args.length == 0 || !(args[0] instanceof VariablesObject)) {
158+
return NullObject.nullCheck(null);
159+
}
160+
VariablesObject vars = (VariablesObject) args[0];
161+
Truffle.getRuntime().iterateFrames((frameInstance) -> {
162+
if (frameInstance.getCallNode() == null) {
163+
// skip top most record about the instrument
164+
return null;
165+
}
166+
final Frame frame = frameInstance.getFrame(FrameInstance.FrameAccess.READ_ONLY);
167+
NodeLibrary lib = NodeLibrary.getUncached();
168+
InteropLibrary iop = InteropLibrary.getUncached();
169+
final Node n = frameInstance.getCallNode() == null ? obj.getInstrumentedNode() : frameInstance.getCallNode();
170+
boolean scope = lib.hasScope(n, frame);
171+
if (scope) {
172+
try {
173+
Object frameVars = lib.getScope(n, frame, false);
174+
iop.execute(args[1], /* XXX */ obj, frameVars);
175+
} catch (UnsupportedMessageException | UnsupportedTypeException | ArityException ex) {
176+
Logger.getLogger(EventContextObject.class.getName()).log(Level.SEVERE, null, ex);
177+
}
178+
}
179+
return null;
180+
});
181+
return NullObject.nullCheck(null);
182+
}
145183
throw UnknownIdentifierException.create(member);
146184
}
147185

148186
@ExportMessage
149187
static boolean isMemberInvocable(EventContextObject obj, String member) {
150-
return "returnNow".equals(member) || "returnValue".equals(member);
188+
return "returnNow".equals(member) || "returnValue".equals(member) || "iterateFrames".equals(member);
151189
}
152190

153191
Node getInstrumentedNode() {
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
insight.on("return", function(ctx, frame) {
2+
if (ctx.line != 8 || frame.n != 1) {
3+
return;
4+
}
5+
try {
6+
throw new Error("This is the stack:");
7+
} catch (e) {
8+
print(e.stack);
9+
}
10+
let depth = 0;
11+
ctx.iterateFrames(frame, (frameCtx, frameVars) => {
12+
depth++;
13+
for (let p in frameVars) {
14+
print(` #${depth} frame: ${p} has value ${frameVars[p]}`);
15+
}
16+
});
17+
print("end of locals");
18+
}, {
19+
roots: true
20+
});
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
> cp iterateFrames.js ${TMP_DIR}/iterateFrames.js
2+
> cp agent-fib.js ${TMP_DIR}/fib.js
3+
> cd ${TMP_DIR}
4+
>[0] js --insight=iterateFrames.js fib.js
5+
Error: This is the stack:
6+
at iterateFrames.js:6:13
7+
at fib (fib.js:8:3)
8+
at fib (fib.js:10:15)
9+
at fib (fib.js:10:15)
10+
at fib (fib.js:10:15)
11+
at fib.js:12:32
12+
#1 frame: n has value 1
13+
#2 frame: n has value 2
14+
#3 frame: n has value 3
15+
#4 frame: n has value 4
16+
#5 frame: <return> has value undefined
17+
end of locals
18+
Error: This is the stack:
19+
at iterateFrames.js:6:13
20+
at fib (fib.js:8:3)
21+
at fib (fib.js:10:34)
22+
at fib (fib.js:10:15)
23+
at fib.js:12:32
24+
#1 frame: n has value 1
25+
#2 frame: n has value 3
26+
#3 frame: n has value 4
27+
#4 frame: <return> has value undefined
28+
end of locals
29+
Error: This is the stack:
30+
at iterateFrames.js:6:13
31+
at fib (fib.js:8:3)
32+
at fib (fib.js:10:15)
33+
at fib (fib.js:10:34)
34+
at fib.js:12:32
35+
#1 frame: n has value 1
36+
#2 frame: n has value 2
37+
#3 frame: n has value 4
38+
#4 frame: <return> has value undefined
39+
end of locals
40+
Three is the result 3

0 commit comments

Comments
 (0)