Uploaded image for project: 'Groovy'
  1. Groovy
  2. GROOVY-8742

Line number information for method is confusing debugger

    XMLWordPrintableJSON

Details

    Description

      I have been investigating a case where the IDE will not break on a line breakpoint in a test method. This method has no parameters or local variables (this affects its line number table in the bytecode) and the code is all on one line, with a chain of three method calls. When line-breaking the code or assigning to temporary, the line numbers table changes and the line breakpoints work as expected.

      package a
      import org.junit.*
      final class Tests {
        @Test
        void testSomething() { // line 29
          Assert.assertFalse(this.method(one(), "two", Three.class)) // line 30
        }
        boolean method(... args) { true }
        def one() {}
      }
      

      When compiled with Groovy 2.4 and normal/dynamic groovy, the method has line information:

            Line numbers:
              [pc: 4, line: 29]
              [pc: 19, line: 30]
              [pc: 68, line: 30]
            Local variable table:
              [pc: 0, pc: 109] local: this index: 0 type: a.Tests
      

      I have not tried with the "fast path" optimization disabled. I think its prelude is what bumps the PC from 0 to 4 and results in the two PC entries for line 30 (pc 19 and pc 68).

      If I assign the result of method to a new local variable, the line numbers are altered:

            Line numbers:
              [pc: 6, line: 30]
              [pc: 63, line: 30]
              [pc: 100, line: 31]
            Local variable table:
              [pc: 0, pc: 113] local: this index: 0 type: a.Tests
              [pc: 6, pc: 113] local: variable index: 2 type: java.lang.Object
      

      If I compile with invoke dynamic on, I get this for the original code:

            Line numbers:
              [pc: 0, line: 30]
            Local variable table:
              [pc: 0, pc: 30] local: this index: 0 type: a.Tests
      

      I'm not sure the exact outcome expected here in terms of the bytecode, but I looked at similar methods from Java sources. For a Java test method, the line number table began with [pc: 0, line: whatever].

      I looked at GROOVY-4505, which mentions that AsmClassGenerator.visitBlockStatement should not be writing line number information for the block statement (the source of line 29). StatementWriter.writeBlockStatement indeed retains a note about this. However, the overload in OptimizingStatementWriter still triggers `onLineNumber` from its `writeBlockStatement` -> writeGuards. Should onLineNumber check for BlockStatement and exit early? I tried this quickly and it did alter the line numbers table, but it did not help my debugger find the breakpoint on line 30.

      Attachments

        Issue Links

          Activity

            People

              paulk Paul King
              emilles Eric Milles
              Votes:
              1 Vote for this issue
              Watchers:
              3 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved: