|
25 | 25 | package com.oracle.truffle.tools.agentscript.impl; |
26 | 26 |
|
27 | 27 | 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; |
28 | 33 | import com.oracle.truffle.api.instrumentation.EventContext; |
29 | 34 | import com.oracle.truffle.api.interop.ArityException; |
30 | 35 | import com.oracle.truffle.api.interop.InteropException; |
31 | 36 | import com.oracle.truffle.api.interop.InteropLibrary; |
| 37 | +import com.oracle.truffle.api.interop.NodeLibrary; |
32 | 38 | import com.oracle.truffle.api.interop.TruffleObject; |
33 | 39 | import com.oracle.truffle.api.interop.UnknownIdentifierException; |
| 40 | +import com.oracle.truffle.api.interop.UnsupportedMessageException; |
| 41 | +import com.oracle.truffle.api.interop.UnsupportedTypeException; |
34 | 42 | import com.oracle.truffle.api.library.ExportLibrary; |
35 | 43 | import com.oracle.truffle.api.library.ExportMessage; |
36 | 44 | import com.oracle.truffle.api.nodes.Node; |
37 | 45 | import com.oracle.truffle.api.source.SourceSection; |
| 46 | +import java.util.logging.Level; |
| 47 | +import java.util.logging.Logger; |
38 | 48 |
|
39 | 49 | @SuppressWarnings("unused") |
40 | 50 | @ExportLibrary(InteropLibrary.class) |
@@ -142,12 +152,40 @@ static Object invokeMember(EventContextObject obj, String member, Object[] args) |
142 | 152 | VariablesObject vars = (VariablesObject) args[0]; |
143 | 153 | return vars.getReturnValue(); |
144 | 154 | } |
| 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 | + } |
145 | 183 | throw UnknownIdentifierException.create(member); |
146 | 184 | } |
147 | 185 |
|
148 | 186 | @ExportMessage |
149 | 187 | 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); |
151 | 189 | } |
152 | 190 |
|
153 | 191 | Node getInstrumentedNode() { |
|
0 commit comments