groovy-notifications mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Eric Milles (JIRA)" <j...@apache.org>
Subject [jira] [Comment Edited] (GROOVY-8289) STC and default value in ctor is causing debugging error
Date Thu, 17 Aug 2017 16:39:00 GMT

    [ https://issues.apache.org/jira/browse/GROOVY-8289?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16130782#comment-16130782
] 

Eric Milles edited comment on GROOVY-8289 at 8/17/17 4:38 PM:
--------------------------------------------------------------

I'm a little out on a limb here, but when I rewrite the class with explicit {{super()}} constructor
invocations, things work fine in the debugger.  That is I now have this:
{code}
@groovy.transform.CompileStatic
class C {
  String string
  C(String s = null) {
    super()
    string = s
  }
  static void main(args) {
    def c = new C('') // put breakpoint on this line, run as Java app, and step
    println c
  }
}
{code}

>From what I can gather, AsmClassGenerator.visitStdMethod is where this matters.  If I
leave out the call to super, the upper part kicks in.  If I explicitly call super, those instructons
are inserted as part of super.visitConstructorOrMethod, which happens on the other side of
scope and param init.  I'm going to experiment by moving {{init}} and {{makeSiteEntry}} to
the start of the method.

{code}
    private void visitStdMethod(MethodNode node, boolean isConstructor, Parameter[] parameters,
Statement code) {
        MethodVisitor mv = controller.getMethodVisitor();
        final ClassNode superClass = controller.getClassNode().getSuperClass();
        if (isConstructor && (code == null || !((ConstructorNode) node).firstStatementIsSpecialConstructorCall()))
{
            boolean hasCallToSuper = false;
            if (code!=null && controller.getClassNode() instanceof InnerClassNode)
{
                // if the class not is an inner class node, there are chances that the call
to super is already added
                // so we must ensure not to add it twice (see GROOVY-4471)
                if (code instanceof BlockStatement) {
                    for (Statement statement : ((BlockStatement) code).getStatements()) {
                        if (statement instanceof ExpressionStatement) {
                            final Expression expression = ((ExpressionStatement) statement).getExpression();
                            if (expression instanceof ConstructorCallExpression) {
                                ConstructorCallExpression call = (ConstructorCallExpression)
expression;
                                if (call.isSuperCall()) {
                                    hasCallToSuper = true;
                                    break;
                                }
                            }
                        }
                    }
                }
            }
            if (!hasCallToSuper) {
                // invokes the super class constructor
                mv.visitVarInsn(ALOAD, 0);
                mv.visitMethodInsn(INVOKESPECIAL, BytecodeHelper.getClassInternalName(superClass),
"<init>", "()V", false);
            }
        }

        controller.getCompileStack().init(node.getVariableScope(), parameters);
        controller.getCallSiteWriter().makeSiteEntry();

        // handle body
        super.visitConstructorOrMethod(node, isConstructor);
{code}


was (Author: emilles):
I'm a little out on a limb here, but when I rewrite the class with explicit {{super()}} constructor
invocations, things work fine in the debugger.  This is I now have this:
{code}
@groovy.transform.CompileStatic
class C {
  String string
  C(String s = null) {
    super()
    string = s
  }
  static void main(args) {
    def c = new C('') // put breakpoint on this line, run as Java app, and step
    println c
  }
}
{code}

>From what I can gather, AsmClassGenerator.visitStdMethod is where this matters.  If I
leave out the call to super, the upper part kicks in.  If I explicitly call super, those instructons
are inserted as part of super.visitConstructorOrMethod, which happens on the other side of
scope and param init.  I'm going to experiment by moving {{init}} and {{makeSiteEntry}} to
the start of the method.

{code}
    private void visitStdMethod(MethodNode node, boolean isConstructor, Parameter[] parameters,
Statement code) {
        MethodVisitor mv = controller.getMethodVisitor();
        final ClassNode superClass = controller.getClassNode().getSuperClass();
        if (isConstructor && (code == null || !((ConstructorNode) node).firstStatementIsSpecialConstructorCall()))
{
            boolean hasCallToSuper = false;
            if (code!=null && controller.getClassNode() instanceof InnerClassNode)
{
                // if the class not is an inner class node, there are chances that the call
to super is already added
                // so we must ensure not to add it twice (see GROOVY-4471)
                if (code instanceof BlockStatement) {
                    for (Statement statement : ((BlockStatement) code).getStatements()) {
                        if (statement instanceof ExpressionStatement) {
                            final Expression expression = ((ExpressionStatement) statement).getExpression();
                            if (expression instanceof ConstructorCallExpression) {
                                ConstructorCallExpression call = (ConstructorCallExpression)
expression;
                                if (call.isSuperCall()) {
                                    hasCallToSuper = true;
                                    break;
                                }
                            }
                        }
                    }
                }
            }
            if (!hasCallToSuper) {
                // invokes the super class constructor
                mv.visitVarInsn(ALOAD, 0);
                mv.visitMethodInsn(INVOKESPECIAL, BytecodeHelper.getClassInternalName(superClass),
"<init>", "()V", false);
            }
        }

        controller.getCompileStack().init(node.getVariableScope(), parameters);
        controller.getCallSiteWriter().makeSiteEntry();

        // handle body
        super.visitConstructorOrMethod(node, isConstructor);
{code}

> STC and default value in ctor is causing debugging error
> --------------------------------------------------------
>
>                 Key: GROOVY-8289
>                 URL: https://issues.apache.org/jira/browse/GROOVY-8289
>             Project: Groovy
>          Issue Type: Bug
>          Components: bytecode
>    Affects Versions: 2.4.12
>            Reporter: Eric Milles
>         Attachments: C1.txt, C2.txt
>
>
> When debugging in the IDE, there is a curious behavior where it looks like step requests
are not being respected.  One thing I have found is that JDWP requests to the JVM process
are failing to resolve the variable "this" in certain cases.  I need some help from someone
who knows the bytecode better than myself to figure out where the problem lies.
> Original issue: https://github.com/groovy/groovy-eclipse/issues/312
> I have narrowed it down to a small bit of code with static compilation enabled.
> {code}
> @groovy.transform.CompileStatic
> class C {
>   String string
>   C(String s = null) { string = s }
>   static void main(args) {
>     def c = new C('') // put breakpoint on this line, run as Java app, and step
>     println c
>   }
> }
> {code}
> Debug stepping fails when executing the constructor for C.  If I use {{new C(string:'')}},
the generated default constructor is used instead and debugging works fine.  So I think it
has something to do with the one-arg constructor's bytecode.
> I dumped the class file using javap and have attached them.  {{C1.txt}} is for the code
above.  {{C2.txt}} is the above with the named args constructor used instead.  I'm not sure
if the local args table for the single-argument constructor is bad and that is why "this"
cannot be resolved.
> There are several similar bugs reported for other tools and whatnots when looking for
"JDWP error code 35".  Hopefully, these help point to something in the bytecode that can be
corrected.
> http://bugs.java.com/bugdatabase/view_bug.do?bug_id=5005668
> https://bugs.openjdk.java.net/browse/JDK-4992932



--
This message was sent by Atlassian JIRA
(v6.4.14#64029)

Mime
View raw message