Skip to content
Snippets Groups Projects
Commit 05f63277 authored by Martin Entlicher's avatar Martin Entlicher
Browse files

[GR-2011] Update wrapper nodes and add a debugger test of unwind of frames.

PullRequest: fastr/1324
parents 2f5bd335 80e19306
No related branches found
No related tags found
No related merge requests found
......@@ -56,41 +56,77 @@ public class RCallBaseNodeWrapperFactory implements InstrumentableFactory<RCallB
@Override
public Object execute(VirtualFrame frame) {
try {
probeNode.onEnter(frame);
Object returnValue = delegate.execute(frame);
probeNode.onReturnValue(frame, returnValue);
return returnValue;
} catch (Throwable t) {
probeNode.onReturnExceptional(frame, t);
throw t;
Object returnValue;
for (;;) {
boolean wasOnReturnExecuted = false;
try {
probeNode.onEnter(frame);
returnValue = delegate.execute(frame);
wasOnReturnExecuted = true;
probeNode.onReturnValue(frame, returnValue);
break;
} catch (Throwable t) {
Object result = probeNode.onReturnExceptionalOrUnwind(frame, t, wasOnReturnExecuted);
if (result == ProbeNode.UNWIND_ACTION_REENTER) {
continue;
} else if (result != null) {
returnValue = result;
break;
}
throw t;
}
}
return returnValue;
}
@Override
public Object visibleExecute(VirtualFrame frame) {
try {
probeNode.onEnter(frame);
Object returnValue = delegate.visibleExecute(frame);
probeNode.onReturnValue(frame, returnValue);
return returnValue;
} catch (Throwable t) {
probeNode.onReturnExceptional(frame, t);
throw t;
Object returnValue;
for (;;) {
boolean wasOnReturnExecuted = false;
try {
probeNode.onEnter(frame);
returnValue = delegate.visibleExecute(frame);
wasOnReturnExecuted = true;
probeNode.onReturnValue(frame, returnValue);
break;
} catch (Throwable t) {
Object result = probeNode.onReturnExceptionalOrUnwind(frame, t, wasOnReturnExecuted);
if (result == ProbeNode.UNWIND_ACTION_REENTER) {
continue;
} else if (result != null) {
returnValue = result;
break;
}
throw t;
}
}
return returnValue;
}
@Override
public Object execute(VirtualFrame frame, Object function) {
try {
probeNode.onEnter(frame);
Object returnValue = delegate.execute(frame, function);
probeNode.onReturnValue(frame, returnValue);
return returnValue;
} catch (Throwable t) {
probeNode.onReturnExceptional(frame, t);
throw t;
Object returnValue;
for (;;) {
boolean wasOnReturnExecuted = false;
try {
probeNode.onEnter(frame);
returnValue = delegate.execute(frame, function);
wasOnReturnExecuted = true;
probeNode.onReturnValue(frame, returnValue);
break;
} catch (Throwable t) {
Object result = probeNode.onReturnExceptionalOrUnwind(frame, t, wasOnReturnExecuted);
if (result == ProbeNode.UNWIND_ACTION_REENTER) {
continue;
} else if (result != null) {
returnValue = result;
break;
}
throw t;
}
}
return returnValue;
}
@Override
......
......@@ -58,40 +58,74 @@ public final class RNodeWrapperFactory implements InstrumentableFactory<RNode> {
@Override
public Object execute(VirtualFrame frame) {
try {
probeNode.onEnter(frame);
Object returnValue = delegate.execute(frame);
probeNode.onReturnValue(frame, returnValue);
return returnValue;
} catch (Throwable t) {
probeNode.onReturnExceptional(frame, t);
throw t;
Object returnValue;
for (;;) {
boolean wasOnReturnExecuted = false;
try {
probeNode.onEnter(frame);
returnValue = delegate.execute(frame);
wasOnReturnExecuted = true;
probeNode.onReturnValue(frame, returnValue);
break;
} catch (Throwable t) {
Object result = probeNode.onReturnExceptionalOrUnwind(frame, t, wasOnReturnExecuted);
if (result == ProbeNode.UNWIND_ACTION_REENTER) {
continue;
} else if (result != null) {
returnValue = result;
break;
}
throw t;
}
}
return returnValue;
}
@Override
public void voidExecute(VirtualFrame frame) {
try {
probeNode.onEnter(frame);
delegate.voidExecute(frame);
probeNode.onReturnValue(frame, null);
} catch (Throwable t) {
probeNode.onReturnExceptional(frame, t);
throw t;
for (;;) {
boolean wasOnReturnExecuted = false;
try {
probeNode.onEnter(frame);
delegate.voidExecute(frame);
wasOnReturnExecuted = true;
probeNode.onReturnValue(frame, null);
break;
} catch (Throwable t) {
Object result = probeNode.onReturnExceptionalOrUnwind(frame, t, wasOnReturnExecuted);
if (result == ProbeNode.UNWIND_ACTION_REENTER) {
continue;
} else if (result != null) {
break;
}
throw t;
}
}
}
@Override
public Object visibleExecute(VirtualFrame frame) {
try {
probeNode.onEnter(frame);
Object returnValue = delegate.visibleExecute(frame);
probeNode.onReturnValue(frame, returnValue);
return returnValue;
} catch (Throwable t) {
probeNode.onReturnExceptional(frame, t);
throw t;
Object returnValue;
for (;;) {
boolean wasOnReturnExecuted = false;
try {
probeNode.onEnter(frame);
returnValue = delegate.visibleExecute(frame);
wasOnReturnExecuted = true;
probeNode.onReturnValue(frame, returnValue);
break;
} catch (Throwable t) {
Object result = probeNode.onReturnExceptionalOrUnwind(frame, t, wasOnReturnExecuted);
if (result == ProbeNode.UNWIND_ACTION_REENTER) {
continue;
} else if (result != null) {
returnValue = result;
break;
}
throw t;
}
}
return returnValue;
}
@Override
......
......@@ -29,15 +29,18 @@ import static org.junit.Assert.assertTrue;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import com.oracle.truffle.api.debug.Breakpoint;
......@@ -56,7 +59,6 @@ import com.oracle.truffle.tck.DebuggerTester;
import org.graalvm.polyglot.Context;
import org.graalvm.polyglot.Source;
import org.graalvm.polyglot.Value;
import org.junit.Ignore;
public class FastRDebugTest {
private Debugger debugger;
......@@ -386,7 +388,7 @@ public class FastRDebugTest {
assertArguments(1, "main(1, 2, 3, 4)");
stepInto(1);
assertArguments(2, "x <- 10L", "a", "b", "c", "d");
assertArguments(2, "x <- 10L", "a", "1.0", "b", "2.0", "c", "3.0", "d", "4.0");
continueExecution();
performWork();
......@@ -496,6 +498,49 @@ public class FastRDebugTest {
assertExecutedOK();
}
@Test
@Ignore
public void testReenterArgumentsAndValues() throws Throwable {
// Test that after a re-enter, arguments are kept and variables are cleared.
final Source source = sourceFromText("" +
"main <- function () {\n" +
" i <- 10\n" +
" fnc(i <- i + 1, 20)\n" +
"}\n" +
"fnc <- function(n, m) {\n" +
" x <- n + m\n" +
" n <- m - n\n" +
" m <- m / 2\n" +
" x <- x + n * m\n" +
" x\n" +
"}\n" +
"main()\n", "testReenterArgsAndVals.r");
run.addLast(() -> {
assertNull(suspendedEvent);
assertNotNull(debuggerSession);
debuggerSession.install(Breakpoint.newBuilder(DebuggerTester.getSourceImpl(source)).lineIs(6).build());
});
assertArguments(6, "x <- n + m", "n", "<unevaluated>", "m", "20.0");
assertScope(6, "x <- n + m", false, true, "n", "<unevaluated>", "m", "20.0");
stepOver(4);
assertArguments(10, "x", "n", "9.0", "m", "10.0");
assertScope(10, "x", false, true, "n", "9.0", "m", "10.0", "x", "121.0");
run.addLast(() -> suspendedEvent.prepareUnwindFrame(suspendedEvent.getTopStackFrame()));
assertArguments(3, "return fnc(i <- i + 1, 20)");
assertScope(3, "return fnc(i <- i + 1, 20)", false, true, "i", "11.0");
continueExecution();
assertArguments(6, "x <- n + m", "n", "11.0", "m", "20.0");
assertScope(6, "x <- n + m", false, true, "n", "11.0", "m", "20.0");
continueExecution();
performWork();
Value ret = context.eval(source);
assertEquals(121, ret.asInt());
assertExecutedOK();
}
private void performWork() {
try {
if (ex == null && !run.isEmpty()) {
......@@ -609,19 +654,24 @@ public class FastRDebugTest {
scope = suspendedEvent.getSession().getTopScope("R");
}
Set<String> actualIdentifiers = new HashSet<>();
scope.getArguments().forEach((x) -> actualIdentifiers.add(x.getName()));
int n = expectedArgs.length / 2;
List<DebugValue> actualValues = new ArrayList<>(n);
scope.getArguments().forEach((x) -> actualValues.add(x));
assertEquals(line + ": " + code, expectedArgs.length, actualIdentifiers.size());
assertEquals(line + ": " + code, n, actualValues.size());
Set<String> expectedIds = new HashSet<>(Arrays.asList(expectedArgs));
Assert.assertEquals(expectedIds, actualIdentifiers);
for (int i = 0; i < n; i++) {
int i2 = i << 1;
assertEquals(expectedArgs[i2], actualValues.get(i).getName());
assertEquals(expectedArgs[i2 + 1], actualValues.get(i).as(String.class));
}
if (!run.isEmpty()) {
run.removeFirst().run();
}
} catch (RuntimeException | Error e) {
e.printStackTrace(System.err);
final DebugStackFrame frame = suspendedEvent.getTopStackFrame();
frame.forEach(var -> {
System.out.println(var);
......@@ -700,7 +750,7 @@ public class FastRDebugTest {
/**
* Assert either meta object or string value for a set of variables.
*
*
* @param expectedSource expected source in which the values should be examined.
* @param metaObjects <code>true</code> for checking metaObject or <code>false</code> for
* checking <code>value.as(String.class)</code>.
......
......@@ -7,7 +7,7 @@ suite = {
{
"name" : "truffle",
"subdir" : True,
"version" : "e140680ae7ebc4329e5cd96889258a75b6987dfe",
"version" : "3a00d021027f4136667915386f83b56311db7c12",
"urls" : [
{"url" : "https://github.com/graalvm/graal", "kind" : "git"},
{"url" : "https://curio.ssw.jku.at/nexus/content/repositories/snapshots", "kind" : "binary"},
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment