@@ -1479,12 +1479,8 @@ class BytecodeGenerator extends RecursiveVisitor {
14791479 }
14801480 if (condition is EqualsNull ) {
14811481 _generateNode (condition.expression);
1482- if (options.emitDebuggerStops &&
1483- condition.fileOffset != TreeNode .noOffset) {
1484- final savedSourcePosition = asm.currentSourcePosition;
1485- _recordSourcePosition (condition.fileOffset);
1486- asm.emitDebugCheck ();
1487- asm.currentSourcePosition = savedSourcePosition;
1482+ if (condition.fileOffset != TreeNode .noOffset) {
1483+ _emitLocalSourcePosition (condition.fileOffset);
14881484 }
14891485 if (value) {
14901486 asm.emitJumpIfNull (dest);
@@ -1631,23 +1627,20 @@ class BytecodeGenerator extends RecursiveVisitor {
16311627 savedAssemblers = null ;
16321628 currentLoopDepth = 0 ;
16331629 savedMaxSourcePositions = < int > [];
1634- maxSourcePosition = node.fileOffset;
1635-
1636- locals = new LocalVariables (node, options, staticTypeContext);
1637- locals.enterScope (node);
1638-
1639- int position;
16401630 if (node is Procedure ) {
1641- position = node.fileStartOffset;
1631+ maxSourcePosition = node.fileStartOffset;
16421632 } else if (node is Constructor ) {
1643- position = node.startFileOffset;
1633+ maxSourcePosition = node.startFileOffset;
16441634 } else {
1645- position = node.fileOffset;
1635+ maxSourcePosition = node.fileOffset;
16461636 }
1647- _recordSourcePosition (position);
1637+
1638+ locals = new LocalVariables (node, options, staticTypeContext);
1639+ locals.enterScope (node);
1640+
16481641 _genPrologue (node, node.function);
16491642 _setupInitialContext (node.function);
1650- _emitFirstDebugCheck (node.function);
1643+ _emitFirstDebugCheck (node, node .function);
16511644 _genEqualsOperatorNullHandling (node);
16521645 if (node is Procedure && node.isInstanceMember) {
16531646 _checkArguments (node.function);
@@ -1864,7 +1857,7 @@ class BytecodeGenerator extends RecursiveVisitor {
18641857 return localVariables;
18651858 }
18661859
1867- void _genPrologue (Node node, FunctionNode ? function) {
1860+ void _genPrologue (TreeNode node, FunctionNode ? function) {
18681861 if (locals.makesCopyOfParameters) {
18691862 final int numOptionalPositional = function! .positionalParameters.length -
18701863 function.requiredParameterCount;
@@ -1957,6 +1950,7 @@ class BytecodeGenerator extends RecursiveVisitor {
19571950
19581951 // CheckStack must see a properly initialized context when stress-testing
19591952 // stack trace collection.
1953+ _recordInitialSourcePositionForFunction (node, function);
19601954 asm.emitCheckStack (0 );
19611955
19621956 if (locals.hasFunctionTypeArgsVar && isClosure) {
@@ -2047,25 +2041,31 @@ class BytecodeGenerator extends RecursiveVisitor {
20472041 }
20482042 }
20492043
2050- void _emitFirstDebugCheck (FunctionNode ? function) {
2044+ int _initialSourcePositionForFunction (TreeNode node, FunctionNode ? function) {
2045+ // The debugger expects the initial source position to correspond to the
2046+ // declaration position of the last parameter, if any, or of the function.
2047+ if (function? .namedParameters.isNotEmpty ?? false ) {
2048+ return function! .namedParameters.last.fileOffset;
2049+ } else if (function? .positionalParameters.isNotEmpty ?? false ) {
2050+ return function! .positionalParameters.last.fileOffset;
2051+ } else if (function != null ) {
2052+ return function.fileOffset;
2053+ } else {
2054+ return node.fileOffset;
2055+ }
2056+ }
2057+
2058+ void _recordInitialSourcePositionForFunction (
2059+ TreeNode node, FunctionNode ? function) {
2060+ _recordSourcePosition (_initialSourcePositionForFunction (node, function));
2061+ }
2062+
2063+ void _emitFirstDebugCheck (TreeNode node, FunctionNode ? function) {
20512064 if (options.emitDebuggerStops) {
20522065 // DebugCheck instruction should be emitted after parameter variables
20532066 // are declared and copied into context.
2054- // The debugger expects the source position to correspond to the
2055- // declaration position of the last parameter, if any, or of the function.
20562067 // The DebugCheck must be encountered each time an async op is reentered.
2057- if (options.emitSourcePositions && function != null ) {
2058- var pos = TreeNode .noOffset;
2059- if (function.namedParameters.isNotEmpty) {
2060- pos = function.namedParameters.last.fileOffset;
2061- } else if (function.positionalParameters.isNotEmpty) {
2062- pos = function.positionalParameters.last.fileOffset;
2063- }
2064- if (pos == TreeNode .noOffset) {
2065- pos = function.fileOffset;
2066- }
2067- _recordSourcePosition (pos);
2068- }
2068+ _recordInitialSourcePositionForFunction (node, function);
20692069 asm.emitDebugCheck ();
20702070 }
20712071 }
@@ -2411,11 +2411,10 @@ class BytecodeGenerator extends RecursiveVisitor {
24112411
24122412 final int closureFunctionIndex = cp.addClosureFunction (closureIndex);
24132413
2414- _recordSourcePosition ( function.fileOffset);
2414+ maxSourcePosition = math. max (maxSourcePosition, function.fileOffset);
24152415 _genPrologue (node, function);
2416-
24172416 _setupInitialContext (function);
2418- _emitFirstDebugCheck (function);
2417+ _emitFirstDebugCheck (node, function);
24192418 _checkArguments (function);
24202419 _initSuspendableFunction (function);
24212420
@@ -2685,16 +2684,34 @@ class BytecodeGenerator extends RecursiveVisitor {
26852684 continuation ();
26862685 }
26872686
2687+ // Emits a source position entry and/or debugger stop as appropriate.
2688+ void _emitSourcePosition () {
2689+ if (options.emitSourcePositions) {
2690+ asm.emitSourcePosition ();
2691+ }
2692+ if (options.emitDebuggerStops) {
2693+ asm.emitDebugCheck ();
2694+ }
2695+ }
2696+
2697+ // Records the given file offset as the current source position and
2698+ // emits a source position entry and/or debugger stop as appropriate,
2699+ // restoring the current source position afterwards.
2700+ void _emitLocalSourcePosition (int fileOffset) {
2701+ final savedSourcePosition = asm.currentSourcePosition;
2702+ _recordSourcePosition (fileOffset);
2703+ _emitSourcePosition ();
2704+ asm.currentSourcePosition = savedSourcePosition;
2705+ }
2706+
26882707 /// Generates non-local transfer from inner node [from] into the outer
26892708 /// node, executing finally blocks on the way out. [to] can be null,
26902709 /// in such case all enclosing finally blocks are executed.
26912710 /// [continuation] is invoked to generate control transfer code following
26922711 /// the last finally block.
26932712 void _generateNonLocalControlTransfer (
26942713 TreeNode from, TreeNode to, GenerateContinuation continuation) {
2695- if (options.emitDebuggerStops && from.fileOffset != TreeNode .noOffset) {
2696- asm.emitDebugCheck (); // Before context is unwound.
2697- }
2714+ _emitLocalSourcePosition (from.fileOffset);
26982715 List <TryFinally > tryFinallyBlocks = _getEnclosingTryFinallyBlocks (from, to);
26992716 _addFinallyBlocks (tryFinallyBlocks, continuation);
27002717 }
@@ -3389,9 +3406,8 @@ class BytecodeGenerator extends RecursiveVisitor {
33893406 }
33903407 tryCatches! [tryCatch]! .needsStackTrace = true ;
33913408
3392- if (options.emitDebuggerStops) {
3393- asm.emitDebugCheck (); // Allow breakpoint on explicit rethrow statement.
3394- }
3409+ // Allow breakpoint on explicit rethrow statement.
3410+ _emitSourcePosition ();
33953411 _genRethrow (tryCatch);
33963412 }
33973413
@@ -3505,9 +3521,8 @@ class BytecodeGenerator extends RecursiveVisitor {
35053521
35063522 final target = node.target;
35073523 if (target is Field && ! _needsSetter (target)) {
3508- if (options.emitDebuggerStops &&
3509- _variableSetNeedsDebugCheck (node.value)) {
3510- asm.emitDebugCheck ();
3524+ if (_variableSetNeedsDebugCheck (node.value)) {
3525+ _emitSourcePosition ();
35113526 }
35123527 int cpIndex = cp.addStaticField (target);
35133528 asm.emitStoreStaticTOS (cpIndex);
@@ -3562,9 +3577,7 @@ class BytecodeGenerator extends RecursiveVisitor {
35623577 void visitThrow (Throw node) {
35633578 _generateNode (node.expression);
35643579
3565- if (options.emitDebuggerStops) {
3566- asm.emitDebugCheck ();
3567- }
3580+ _emitSourcePosition ();
35683581 asm.emitThrow (0 );
35693582 }
35703583
@@ -3649,8 +3662,8 @@ class BytecodeGenerator extends RecursiveVisitor {
36493662
36503663 _generateNode (node.value);
36513664
3652- if (options.emitDebuggerStops && _variableSetNeedsDebugCheck (node.value)) {
3653- asm. emitDebugCheck ();
3665+ if (_variableSetNeedsDebugCheck (node.value)) {
3666+ _emitSourcePosition ();
36543667 }
36553668
36563669 if (isLateFinal) {
@@ -3902,9 +3915,7 @@ class BytecodeGenerator extends RecursiveVisitor {
39023915
39033916 @override
39043917 void visitFunctionDeclaration (ast.FunctionDeclaration node) {
3905- if (options.emitDebuggerStops) {
3906- asm.emitDebugCheck ();
3907- }
3918+ _emitSourcePosition ();
39083919 _genPushContextIfCaptured (node.variable);
39093920 _genClosure (node, node.variable.name! , node.function);
39103921 _genStoreVar (node.variable);
@@ -4311,14 +4322,12 @@ class BytecodeGenerator extends RecursiveVisitor {
43114322 }
43124323 }
43134324
4314- if (options.emitDebuggerStops &&
4315- (initializer == null || _variableSetNeedsDebugCheck (initializer))) {
4316- final savedSourcePosition = asm.currentSourcePosition;
4317- if (node.fileEqualsOffset != TreeNode .noOffset) {
4318- _recordSourcePosition (node.fileEqualsOffset);
4319- }
4320- asm.emitDebugCheck ();
4321- asm.currentSourcePosition = savedSourcePosition;
4325+ // Emit a source position only as part of a DebugCheck instruction or
4326+ // if there's a store instruction to be emitted for the current PC offset.
4327+ if ((initializer == null || _variableSetNeedsDebugCheck (initializer)) &&
4328+ (options.emitDebuggerStops || emitStore)) {
4329+ _recordSourcePosition (node.fileEqualsOffset);
4330+ _emitSourcePosition ();
43224331 }
43234332
43244333 if (options.emitLocalVarInfo && ! asm.isUnreachable && node.name != null ) {
0 commit comments