Skip to content

Commit

Permalink
Added support to step until next node with given tag
Browse files Browse the repository at this point in the history
Signed-off-by: Stefan Marr <git@stefan-marr.de>
  • Loading branch information
smarr committed Sep 1, 2018
1 parent d448d9c commit 7689d6f
Show file tree
Hide file tree
Showing 4 changed files with 128 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
import com.oracle.truffle.api.instrumentation.SourceSectionFilter.Builder;
import com.oracle.truffle.api.instrumentation.StandardTags.CallTag;
import com.oracle.truffle.api.instrumentation.StandardTags.RootTag;
import com.oracle.truffle.api.instrumentation.Tag;
import com.oracle.truffle.api.nodes.ExecutableNode;
import com.oracle.truffle.api.nodes.LanguageInfo;
import com.oracle.truffle.api.nodes.Node;
Expand Down Expand Up @@ -416,6 +417,17 @@ synchronized void resume(Thread t) {
setSteppingStrategy(t, SteppingStrategy.createContinue(), true);
}

/**
* Prepare interpreter to step to the next source section with the given tag.
*
* @since smarr/debugger
*/
public void prepareStepUntilNext(Class<? extends Tag> tag, SuspendAnchor anchor, Thread thread) {
StepConfig stepConfig = StepConfig.newBuilder().tag(tag, anchor).build();
SteppingStrategy strat = SteppingStrategy.createStepNext(this, stepConfig);
setSteppingStrategy(thread, strat, true);
}

private synchronized void setSteppingStrategy(Thread thread, SteppingStrategy strategy, boolean updateStepping) {
if (closed) {
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import java.util.Set;

import com.oracle.truffle.api.instrumentation.EventContext;
import com.oracle.truffle.api.instrumentation.Tag;

/**
* Represents a debugger step configuration. A debugger step is defined by it's depth and a set of
Expand All @@ -52,14 +53,19 @@
*/
public final class StepConfig {

private static final StepConfig EMPTY = new StepConfig(null, 0);
private static final StepConfig EMPTY = new StepConfig(null, 0, null, null);

private final Set<SourceElement> sourceElements;
private final int stepCount;

StepConfig(Set<SourceElement> sourceElements, int count) {
private final Class<? extends Tag> tag;
private final SuspendAnchor tagAnchor;

StepConfig(Set<SourceElement> sourceElements, int count, Class<? extends Tag> tag, SuspendAnchor tagAnchor) {
this.sourceElements = sourceElements;
this.stepCount = count;
this.tag = tag;
this.tagAnchor = tagAnchor;
}

/**
Expand Down Expand Up @@ -104,9 +110,20 @@ boolean matches(DebuggerSession session, EventContext context, SuspendAnchor anc
return true;
}
}
if (tag != null) {
return context.hasTag(tag) && this.tagAnchor == anchor;
}
return false;
}

Class<? extends Tag> getTag() {
return tag;
}

SuspendAnchor getTagAnchor() {
return tagAnchor;
}

boolean containsSourceElement(DebuggerSession session, SourceElement sourceElement) {
Set<SourceElement> elements = sourceElements;
if (elements == null) {
Expand Down Expand Up @@ -134,6 +151,9 @@ public final class Builder {
private Set<SourceElement> stepElements;
private int stepCount = -1;

private Class<? extends Tag> tag;
private SuspendAnchor tagAnchor;

private Builder() {
}

Expand Down Expand Up @@ -162,6 +182,23 @@ public Builder sourceElements(SourceElement... elements) {
return this;
}

/**
* Set a tag to filter the applicable source sections.
*
* @since smarr/debugger
*/
public Builder tag(@SuppressWarnings("hiding") Class<? extends Tag> tag, @SuppressWarnings("hiding") SuspendAnchor tagAnchor) {
if (this.tag != null && this.tagAnchor != null) {
throw new IllegalStateException("Tag and anchor can only be set once per the builder.");
}
if (tag == null && tagAnchor == null) {
throw new IllegalArgumentException("Tag and anchor cannot be null");
}
this.tag = tag;
this.tagAnchor = tagAnchor;
return this;
}

/**
* Provide the step count. It specifies the number of times the step repeats itself before
* it suspends the execution. Can only be invoked once per builder.
Expand Down Expand Up @@ -189,7 +226,7 @@ public StepConfig build() {
if (stepCount < 0) {
stepCount = 1;
}
return new StepConfig(stepElements, stepCount);
return new StepConfig(stepElements, stepCount, tag, tagAnchor);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

import com.oracle.truffle.api.instrumentation.EventContext;
import com.oracle.truffle.api.instrumentation.ProbeNode;
import com.oracle.truffle.api.nodes.Node;

/**
* Implementation of a strategy for a debugger <em>action</em> that allows execution to continue
Expand Down Expand Up @@ -147,6 +148,10 @@ static SteppingStrategy createStepOver(DebuggerSession session, StepConfig confi
return new StepOver(session, config);
}

static SteppingStrategy createStepNext(DebuggerSession session, StepConfig config) {
return new StepNext(session, config);
}

static SteppingStrategy createUnwind(int depth) {
return new Unwind(depth);
}
Expand Down Expand Up @@ -512,6 +517,56 @@ public String toString() {

}

private static final class StepNext extends SteppingStrategy {
private final DebuggerSession session;
private final StepConfig stepConfig;

private int stackCounter;
private boolean activeFrame;
private Node targetNode;

StepNext(DebuggerSession session, StepConfig stepConfig) {
this.session = session;
this.stepConfig = stepConfig;
}

@Override
void notifyCallEntry() {
stackCounter += 1;
activeFrame = stackCounter == 0;
}

@Override
void notifyCallExit() {
stackCounter -= 1;
if (stackCounter == 0) {
activeFrame = true;
}
}

@Override
void notifyNodeEntry(EventContext context) {
if (targetNode == null && context.hasTag(stepConfig.getTag())) {
// record the target node
targetNode = context.getInstrumentedNode();

// adjust the stackCounter to reflect that this is where we want to be
stackCounter = 0;
activeFrame = true;
}
}

@Override
boolean isActive(EventContext context, SuspendAnchor suspendAnchor) {
return activeFrame && targetNode == context.getInstrumentedNode() && stepConfig.matches(session, context, suspendAnchor);
}

@Override
boolean step(DebuggerSession steppingSession, EventContext context, SuspendAnchor suspendAnchor) {
return isActive(context, suspendAnchor);
}
}

static final class Unwind extends SteppingStrategy {

private final int depth; // Negative depth
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
import com.oracle.truffle.api.frame.FrameInstanceVisitor;
import com.oracle.truffle.api.frame.MaterializedFrame;
import com.oracle.truffle.api.instrumentation.Instrumenter;
import com.oracle.truffle.api.instrumentation.Tag;
import com.oracle.truffle.api.nodes.Node;
import com.oracle.truffle.api.nodes.RootNode;
import com.oracle.truffle.api.source.SourceSection;
Expand Down Expand Up @@ -216,13 +217,6 @@ InsertableNode getInsertableNode() {
return insertableNode;
}

/**
* @since smarr/debugger
*/
public SteppingLocation getLocation() {
return location;
}

/**
* SM: Reintroduce getNode(). Removed from Truffle 0.25
*
Expand Down Expand Up @@ -590,6 +584,26 @@ public SuspendedEvent prepareStepOver(StepConfig stepConfig) {
return this;
}

/**
* Step until the next element with the give tag.
*
* @since smarr/debugger
*/
public SuspendedEvent prepareStepUntilNext(Class<? extends Tag> tag, SuspendAnchor anchor) {
return prepareStepUntilNext(StepConfig.newBuilder().tag(tag, anchor).build());
}

/**
* Step next with the given stepConfig.
*
* @since smarr/debugger
*/
public SuspendedEvent prepareStepUntilNext(StepConfig stepConfig) {
verifyConfig(stepConfig);
setNextStrategy(SteppingStrategy.createStepNext(session, stepConfig));
return this;
}

private void verifyConfig(StepConfig stepConfig) {
Set<SourceElement> sessionElements = session.getSourceElements();
if (sessionElements.isEmpty()) {
Expand Down

0 comments on commit 7689d6f

Please sign in to comment.