blob: 64131f93c2793431f14c77dcfaab6ad8ae807a8e [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.netbeans.modules.debugger.jpda.backend.truffle;
import com.oracle.truffle.api.CallTarget;
import com.oracle.truffle.api.RootCallTarget;
import com.oracle.truffle.api.Truffle;
import com.oracle.truffle.api.frame.Frame;
import com.oracle.truffle.api.frame.FrameInstance;
import com.oracle.truffle.api.frame.FrameInstanceVisitor;
import com.oracle.truffle.api.frame.FrameSlot;
import com.oracle.truffle.api.instrumentation.InstrumentableNode;
import com.oracle.truffle.api.instrumentation.StandardTags;
import com.oracle.truffle.api.instrumentation.Tag;
import com.oracle.truffle.api.nodes.Node;
import com.oracle.truffle.api.nodes.NodeUtil;
import com.oracle.truffle.api.nodes.RootNode;
import com.oracle.truffle.api.source.SourceSection;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
/**
*
* @author martin
*/
public class TruffleAST {
private final FrameInstance frameInstance;
private TruffleAST(FrameInstance frameInstance) {
this.frameInstance = frameInstance;
}
static TruffleAST get(int depth) {
final AtomicInteger frameDepth = new AtomicInteger(depth);
FrameInstance frameInstance = Truffle.getRuntime().iterateFrames(new FrameInstanceVisitor<FrameInstance>() {
@Override
public FrameInstance visitFrame(FrameInstance frameInstance) {
CallTarget callTarget = frameInstance.getCallTarget();
if (!(callTarget instanceof RootCallTarget)) {
return null;
}
RootCallTarget rct = (RootCallTarget) callTarget;
SourceSection rootSourceSection = rct.getRootNode().getSourceSection();
if (rootSourceSection != null) {
if (frameDepth.getAndDecrement() == 0) {
return frameInstance;
}
}
return null;
}
});
return frameInstance == null ? null : new TruffleAST(frameInstance);
}
public Object[] getRawArguments() {
return frameInstance.getFrame(FrameInstance.FrameAccess.MATERIALIZE).getArguments();
}
public Object[] getRawSlots() {
Frame frame = frameInstance.getFrame(FrameInstance.FrameAccess.MATERIALIZE);
List<? extends FrameSlot> slots = frame.getFrameDescriptor().getSlots();
int n = slots.size();
Object[] slotInfo = new Object[2*n];
for (int i = 0; i < n; i++) {
FrameSlot slot = slots.get(i);
slotInfo[2*i] = slot.getIdentifier();
slotInfo[2*i + 1] = frame.getValue(slot);
}
return slotInfo;
}
/**
* Get the nodes hierarchy. Every node is described by:
* <ul>
* <li>node class</li>
* <li>node description</li>
* <li>node source section - either an empty line, or following items:</li>
* <ul>
* <li>URI</li>
* <li>&lt;start line&gt;:&lt;start column&gt;-&lt;end line&gt;:&lt;end column&gt;</li>
* </ul>
* <li>number of children</li>
* <li>&lt;child nodes follow...&gt;</li>
* </ul>
* @return a newline-separated list of elements describing the nodes hierarchy.
*/
public String getNodes() {
StringBuilder nodes = new StringBuilder();
RootCallTarget rct = (RootCallTarget) frameInstance.getCallTarget();
RootNode rootNode = rct.getRootNode();
fillNode(rootNode, nodes);
return nodes.toString();
}
private static void fillNode(Node node, StringBuilder nodes) {
nodes.append(node.getClass().getName());
nodes.append('\n');
nodes.append(node.getDescription());
nodes.append('\n');
SourceSection ss = node.getSourceSection();
if (ss == null) {
nodes.append('\n');
} else {
nodes.append(ss.getSource().getURI().toString());
nodes.append('\n');
nodes.append(Integer.toString(ss.getStartLine()));
nodes.append(':');
nodes.append(Integer.toString(ss.getStartColumn()));
nodes.append('-');
nodes.append(Integer.toString(ss.getEndLine()));
nodes.append(':');
nodes.append(Integer.toString(ss.getEndColumn()));
nodes.append('\n');
//nodes.add(ss.getCode());
}
// TAGS:
try {
StringBuilder tags = new StringBuilder();
if (node instanceof InstrumentableNode) {
InstrumentableNode inode = (InstrumentableNode) node;
for (Class<?> tag : StandardTags.class.getDeclaredClasses()) {
if (Tag.class.isAssignableFrom(tag)) {
if (inode.hasTag(tag.asSubclass(Tag.class))) {
if (tags.length() > 0) {
tags.append(',');
}
tags.append(tag.getSimpleName());
}
}
}
}
nodes.append(tags);
} catch (Throwable t) {
}
nodes.append('\n');
List<Node> ch = NodeUtil.findNodeChildren(node);
nodes.append(Integer.toString(ch.size()));
nodes.append('\n');
for (Node n : ch) {
fillNode(n, nodes);
}
}
}