Skip to content

Commit

Permalink
Fix the "double breakpoints" problem (except in blocks of main program)
Browse files Browse the repository at this point in the history
  • Loading branch information
skinny85 committed Jan 8, 2025
1 parent d23dc8b commit e37527b
Show file tree
Hide file tree
Showing 8 changed files with 73 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ protected CallTarget parse(ParsingRequest request) throws Exception {
ParsingResult parsingResult = EasyScriptTruffleParser.parse(
request.getSource(), this.shapesAndPrototypes);
var programRootNode = new StmtBlockRootNode(this, parsingResult.topLevelFrameDescriptor,
parsingResult.programStmtBlock, ":program");
parsingResult.programStmtBlock, ":program", parsingResult.programSourceSection);
return programRootNode.getCallTarget();
}

Expand All @@ -96,8 +96,7 @@ protected EasyScriptLanguageContext createContext(Env env) {
new StmtBlockRootNode(
this,
FrameDescriptor.newBuilder().build(),
new BlockStmtNode(Collections.emptyList()),
null).getCallTarget(),
new BlockStmtNode(Collections.emptyList())).getCallTarget(),
0));
}

Expand Down Expand Up @@ -152,8 +151,7 @@ private DynamicObject createGlobalScopeObject(DynamicObjectLibrary objectLibrary
new StringLiteralExprNode(entry.getKey()),
"name"
), null)
)),
"constructor").getCallTarget(),
))).getCallTarget(),
1),
0);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import com.oracle.truffle.api.frame.FrameDescriptor;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.nodes.RootNode;
import com.oracle.truffle.api.source.SourceSection;

/**
* A {@link RootNode} that represents the execution of a block of statements.
Expand All @@ -27,23 +28,33 @@ public final class StmtBlockRootNode extends RootNode {
private EasyScriptStmtNode blockStmt;

private final String name;
private final SourceSection sourceSection;

public StmtBlockRootNode(EasyScriptTruffleLanguage truffleLanguage,
FrameDescriptor frameDescriptor, BlockStmtNode blockStmt, String name) {
this(truffleLanguage, frameDescriptor, (EasyScriptStmtNode) blockStmt, name);
FrameDescriptor frameDescriptor, BlockStmtNode blockStmt) {
this(truffleLanguage, frameDescriptor, blockStmt, null, null);
}

public StmtBlockRootNode(EasyScriptTruffleLanguage truffleLanguage,
FrameDescriptor frameDescriptor, UserFuncBodyStmtNode blockStmt, String name) {
this(truffleLanguage, frameDescriptor, (EasyScriptStmtNode) blockStmt, name);
FrameDescriptor frameDescriptor, BlockStmtNode blockStmt,
String name, SourceSection sourceSection) {
this(truffleLanguage, frameDescriptor, (EasyScriptStmtNode) blockStmt, name, sourceSection);
}

public StmtBlockRootNode(EasyScriptTruffleLanguage truffleLanguage,
FrameDescriptor frameDescriptor, UserFuncBodyStmtNode blockStmt,
String name, SourceSection sourceSection) {
this(truffleLanguage, frameDescriptor, (EasyScriptStmtNode) blockStmt, name, sourceSection);
}

private StmtBlockRootNode(EasyScriptTruffleLanguage truffleLanguage,
FrameDescriptor frameDescriptor, EasyScriptStmtNode blockStmt, String name) {
FrameDescriptor frameDescriptor, EasyScriptStmtNode blockStmt,
String name, SourceSection sourceSection) {
super(truffleLanguage, frameDescriptor);

this.blockStmt = blockStmt;
this.name = name;
this.sourceSection = sourceSection;
}

@Override
Expand All @@ -55,4 +66,9 @@ public Object execute(VirtualFrame frame) {
public String getName() {
return this.name;
}

@Override
public SourceSection getSourceSection() {
return this.sourceSection;
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package com.endoflineblog.truffle.part_15.nodes.stmts.blocks;

import com.endoflineblog.truffle.part_15.nodes.stmts.EasyScriptStmtNode;
import com.endoflineblog.truffle.part_15.nodes.stmts.SkippedStmtNode;
import com.endoflineblog.truffle.part_15.runtime.Undefined;
import com.endoflineblog.truffle.part_15.runtime.nodes.RefObject;
import com.oracle.truffle.api.CompilerDirectives;
Expand All @@ -12,6 +11,7 @@
import com.oracle.truffle.api.nodes.ExplodeLoop;
import com.oracle.truffle.api.nodes.Node;
import com.oracle.truffle.api.nodes.NodeUtil;
import com.oracle.truffle.api.source.SourceSection;

import java.util.List;

Expand All @@ -25,7 +25,7 @@
*
* @see #executeStatement
*/
public final class BlockStmtNode extends SkippedStmtNode {
public final class BlockStmtNode extends EasyScriptStmtNode {
@Children
private final EasyScriptStmtNode[] stmts;

Expand All @@ -34,11 +34,20 @@ public final class BlockStmtNode extends SkippedStmtNode {
@CompilationFinal(dimensions = 1)
private RefObject[] findLocalVarRefsCache;

public BlockStmtNode(SourceSection sourceSection, List<EasyScriptStmtNode> stmts) {
this(stmts, true, sourceSection);
}

public BlockStmtNode(List<EasyScriptStmtNode> stmts) {
this(stmts, false);
this(stmts, null);
}

public BlockStmtNode(List<EasyScriptStmtNode> stmts, SourceSection sourceSection) {
this(stmts, false, sourceSection);
}

public BlockStmtNode(List<EasyScriptStmtNode> stmts, boolean programBlock) {
private BlockStmtNode(List<EasyScriptStmtNode> stmts, boolean programBlock, SourceSection sourceSection) {
super(sourceSection);
this.stmts = stmts.toArray(new EasyScriptStmtNode[]{});
this.programBlock = programBlock;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import com.oracle.truffle.api.library.CachedLibrary;
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.object.DynamicObjectLibrary;
import com.oracle.truffle.api.source.SourceSection;

/**
* A Node that represents the declaration of a function in EasyScript.
Expand All @@ -28,11 +29,13 @@
@NodeField(name = "frameDescriptor", type = FrameDescriptor.class)
@NodeField(name = "funcBody", type = UserFuncBodyStmtNode.class)
@NodeField(name = "argumentCount", type = int.class)
@NodeField(name = "funcBodySource", type = SourceSection.class)
public abstract class FuncDeclStmtNode extends SkippedStmtNode {
protected abstract String getFuncName();
protected abstract FrameDescriptor getFrameDescriptor();
protected abstract UserFuncBodyStmtNode getFuncBody();
protected abstract int getArgumentCount();
protected abstract SourceSection getFuncBodySource();

@CompilationFinal
private FunctionObject cachedFunction;
Expand All @@ -45,7 +48,7 @@ protected Object declareFunction(DynamicObject containerObject,

var truffleLanguage = this.currentTruffleLanguage();
var funcRootNode = new StmtBlockRootNode(truffleLanguage,
this.getFrameDescriptor(), this.getFuncBody(), this.getFuncName());
this.getFrameDescriptor(), this.getFuncBody(), this.getFuncName(), this.getFuncBodySource());
var callTarget = funcRootNode.getCallTarget();

ShapesAndPrototypes shapesAndPrototypes = this.currentLanguageContext().shapesAndPrototypes;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -182,9 +182,20 @@ private EasyScriptTruffleParser(Source source, ShapesAndPrototypes shapesAndProt

public ParsingResult parse() {
List<EasyScriptStmtNode> stmts = this.parseStmtsList(this.parser.start().stmt());
SourceSection programSourceSection = this.source.createSection(0, this.source.getLength());
return new ParsingResult(
new BlockStmtNode(stmts, true),
this.frameDescriptor.build());
new BlockStmtNode(programSourceSection, stmts),
this.frameDescriptor.build(),

// unit tests pass with these,
// but the actual debugger has "double breakpoints" -
// however, only in blocks in the main program!
null

// the unit test for breakpoint setting fails for this,
// but the actual debugger works fine!
// programSourceSection
);
}

private List<EasyScriptStmtNode> parseStmtsList(List<EasyScriptParser.StmtContext> stmts) {
Expand Down Expand Up @@ -379,7 +390,7 @@ private EasyScriptStmtNode parseStmt(EasyScriptParser.StmtContext stmt) {
List<EasyScriptStmtNode> parsedStmts = this.parseStmtsList(List.of(stmt));
return parsedStmts.size() == 1
? parsedStmts.get(0)
: new BlockStmtNode(parsedStmts);
: new BlockStmtNode(parsedStmts, this.createSourceSection(stmt));
}

private BlockStmtNode parseStmtBlock(EasyScriptParser.Stmt_blockContext stmtBlock) {
Expand All @@ -398,7 +409,7 @@ private BlockStmtNode parseStmtBlock(EasyScriptParser.Stmt_blockContext stmtBloc
this.state = previousParserState;
this.localScopes.pop();

return new BlockStmtNode(ret);
return new BlockStmtNode(ret, this.createSourceSection(stmtBlock));
}

private FuncDeclStmtNode parseFuncDeclStmt(EasyScriptParser.FuncDeclStmtContext funcDeclStmt) {
Expand Down Expand Up @@ -486,7 +497,8 @@ private FuncDeclStmtNode parseSubroutineDecl(EasyScriptParser.Subroutine_declCon
subroutineDecl.name.getText(),
frameDescriptor,
new UserFuncBodyStmtNode(funcStmts, this.createSourceSection(subroutineDecl)),
argumentCount);
argumentCount,
this.createSourceSection(subroutineDecl));
}

private EasyScriptExprNode parseExpr1(EasyScriptParser.Expr1Context expr1) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.endoflineblog.truffle.part_15.nodes.stmts.blocks.BlockStmtNode;
import com.oracle.truffle.api.frame.FrameDescriptor;
import com.oracle.truffle.api.source.SourceSection;

/**
* The class used as the result of parsing in
Expand All @@ -18,8 +19,12 @@ public final class ParsingResult {
*/
public final FrameDescriptor topLevelFrameDescriptor;

public ParsingResult(BlockStmtNode programStmtBlock, FrameDescriptor topLevelFrameDescriptor) {
public final SourceSection programSourceSection;

public ParsingResult(BlockStmtNode programStmtBlock, FrameDescriptor topLevelFrameDescriptor,
SourceSection programSourceSection) {
this.programStmtBlock = programStmtBlock;
this.topLevelFrameDescriptor = topLevelFrameDescriptor;
this.programSourceSection = programSourceSection;
}
}
8 changes: 5 additions & 3 deletions part-16/src/main/resources/fibonacci.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ function fib(unused, num) {
}
}

let fib5;
fib5 = fib("unused", 3);
fib5;
let fib3;
fib3 = fib("unused", 3);
if (true) {
fib3 + 5;
}
Original file line number Diff line number Diff line change
Expand Up @@ -176,17 +176,18 @@ void setting_breakpoint_suspends_execution() {

try (DebuggerSession debuggerSession = this.debuggerTester.startSession()) {
debuggerSession.suspendNextExecution();
debuggerSession.install(Breakpoint.newBuilder(source.getURI()).lineIs(4).build());
debuggerSession.install(Breakpoint.newBuilder(source.getURI()).lineIs(7).build());
this.debuggerTester.startEval(source);
this.debuggerTester.expectSuspended(event -> {
assertState(event, ":program", 16, SuspendAnchor.BEFORE, "const fibM1 = fib('unused-1', -1);");
event.prepareContinue();
});
this.debuggerTester.expectSuspended(event -> {
assertState(event, "fib", 4, SuspendAnchor.BEFORE, "let i = 1;",
assertState(event, "fib", 7, SuspendAnchor.BEFORE, "n1 = n2;",
List.of(
Map.of("num", "2", "this", "undefined", "n1", "0", "n2", "1"),
Map.of("i", "undefined")));
Map.of("i", "1"),
Map.of("next", "1")));
event.prepareContinue();
});

Expand Down

0 comments on commit e37527b

Please sign in to comment.