Fixed
Status Update
Comments
ze...@google.com <ze...@google.com> #2
This issue appears to be the same issue as seen for for-loops in b/128024460 .
There the APK contains correct position info and it appears the studio debugger is failing to install the correct breakpoints or react correctly when hit.
In AS 3.4 RC1, using the activity:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
for(int i=1; i<=69; i++){ // breakpoint missed
for (int j=0;j<=20; j++){ // breakpoint missed
int x=10;
System.out.println(x);
}
}
System.out.println("done"); // breakpoint hit
}
}
The breakpoints for the if-statements are never hit, neither the loop entries or the back edges. For the above the first breakpoint hit is the continuation from the outer loop. The dexdump for the above is:
Virtual methods -
#0 : (in Lcom/example/myapplication128024460/MainActivity;)
name : 'onCreate'
type : '(Landroid/os/Bundle;)V'
access : 0x0004 (PROTECTED)
code -
registers : 6
ins : 2
outs : 2
insns size : 40 16-bit code units
123fc8: |[123fc8] com.example.myapplication128024460.MainActivity.onCreate:(Landroid/os/Bundle;)V
123fd8: 6f20 4924 5400 |0000: invoke-super {v4, v5}, Landroid/support/v7/app/AppCompatActivity;.onCreate:(Landroid/os/Bundle;)V // method@2449
123fde: 1400 1c00 097f |0003: const v0, #float 182104803330002376834593437781443215360.000000 // #7f09001c
123fe4: 6e20 773c 0400 |0006: invoke-virtual {v4, v0}, Lcom/example/myapplication128024460/MainActivity;.setContentView:(I)V // method@3c77
123fea: 1210 |0009: const/4 v0, #int 1 // #1
123fec: 1301 4500 |000a: const/16 v1, #int 69 // #45
123ff0: 3610 1400 |000c: if-gt v0, v1, 0020 // +0014
123ff4: 1201 |000e: const/4 v1, #int 0 // #0
123ff6: 1302 1400 |000f: const/16 v2, #int 20 // #14
123ffa: 3621 0c00 |0011: if-gt v1, v2, 001d // +000c
123ffe: 1302 0a00 |0013: const/16 v2, #int 10 // #a
124002: 6203 792c |0015: sget-object v3, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@2c79
124006: 6e20 ce3c 2300 |0017: invoke-virtual {v3, v2}, Ljava/io/PrintStream;.println:(I)V // method@3cce
12400c: d801 0101 |001a: add-int/lit8 v1, v1, #int 1 // #01
124010: 28f3 |001c: goto 000f // -000d
124012: d800 0001 |001d: add-int/lit8 v0, v0, #int 1 // #01
124016: 28eb |001f: goto 000a // -0015
124018: 6200 792c |0020: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@2c79
12401c: 1a01 a328 |0022: const-string v1, "done" // string@28a3
124020: 6e20 cf3c 1000 |0024: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@3ccf
124026: 0e00 |0027: return-void
catches : (none)
positions :
0x0000 line=10
0x0003 line=11
0x0009 line=12
0x000e line=13
0x0013 line=14
0x0015 line=15
0x001a line=13
0x001d line=12
0x0020 line=18
0x0027 line=19
locals :
0x0015 - 0x001a reg=2 x I
0x000f - 0x001d reg=1 j I
0x000a - 0x0020 reg=0 i I
0x0000 - 0x0028 reg=4 this Lcom/example/myapplication128024460/MainActivity;
0x0000 - 0x0028 reg=5 savedInstanceState Landroid/os/Bundle;
There the APK contains correct position info and it appears the studio debugger is failing to install the correct breakpoints or react correctly when hit.
In AS 3.4 RC1, using the activity:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
for(int i=1; i<=69; i++){ // breakpoint missed
for (int j=0;j<=20; j++){ // breakpoint missed
int x=10;
System.out.println(x);
}
}
System.out.println("done"); // breakpoint hit
}
}
The breakpoints for the if-statements are never hit, neither the loop entries or the back edges. For the above the first breakpoint hit is the continuation from the outer loop. The dexdump for the above is:
Virtual methods -
#0 : (in Lcom/example/myapplication128024460/MainActivity;)
name : 'onCreate'
type : '(Landroid/os/Bundle;)V'
access : 0x0004 (PROTECTED)
code -
registers : 6
ins : 2
outs : 2
insns size : 40 16-bit code units
123fc8: |[123fc8] com.example.myapplication128024460.MainActivity.onCreate:(Landroid/os/Bundle;)V
123fd8: 6f20 4924 5400 |0000: invoke-super {v4, v5}, Landroid/support/v7/app/AppCompatActivity;.onCreate:(Landroid/os/Bundle;)V // method@2449
123fde: 1400 1c00 097f |0003: const v0, #float 182104803330002376834593437781443215360.000000 // #7f09001c
123fe4: 6e20 773c 0400 |0006: invoke-virtual {v4, v0}, Lcom/example/myapplication128024460/MainActivity;.setContentView:(I)V // method@3c77
123fea: 1210 |0009: const/4 v0, #int 1 // #1
123fec: 1301 4500 |000a: const/16 v1, #int 69 // #45
123ff0: 3610 1400 |000c: if-gt v0, v1, 0020 // +0014
123ff4: 1201 |000e: const/4 v1, #int 0 // #0
123ff6: 1302 1400 |000f: const/16 v2, #int 20 // #14
123ffa: 3621 0c00 |0011: if-gt v1, v2, 001d // +000c
123ffe: 1302 0a00 |0013: const/16 v2, #int 10 // #a
124002: 6203 792c |0015: sget-object v3, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@2c79
124006: 6e20 ce3c 2300 |0017: invoke-virtual {v3, v2}, Ljava/io/PrintStream;.println:(I)V // method@3cce
12400c: d801 0101 |001a: add-int/lit8 v1, v1, #int 1 // #01
124010: 28f3 |001c: goto 000f // -000d
124012: d800 0001 |001d: add-int/lit8 v0, v0, #int 1 // #01
124016: 28eb |001f: goto 000a // -0015
124018: 6200 792c |0020: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@2c79
12401c: 1a01 a328 |0022: const-string v1, "done" // string@28a3
124020: 6e20 cf3c 1000 |0024: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@3ccf
124026: 0e00 |0027: return-void
catches : (none)
positions :
0x0000 line=10
0x0003 line=11
0x0009 line=12
0x000e line=13
0x0013 line=14
0x0015 line=15
0x001a line=13
0x001d line=12
0x0020 line=18
0x0027 line=19
locals :
0x0015 - 0x001a reg=2 x I
0x000f - 0x001d reg=1 j I
0x000a - 0x0020 reg=0 i I
0x0000 - 0x0028 reg=4 this Lcom/example/myapplication128024460/MainActivity;
0x0000 - 0x0028 reg=5 savedInstanceState Landroid/os/Bundle;
rp...@google.com <rp...@google.com> #3
Assigning to Kun for investigation.
Questions are:
* Is this a regression from 3.3?
* How common is this issue?
Questions are:
* Is this a regression from 3.3?
* How common is this issue?
ku...@google.com <ku...@google.com> #4
Please ignore my previous comments below.
----------------------------------------------------------
Maybe, it's because of setting? I unchecked the 'Do not step into the classes' checkbox in Settings/Stepping. And then I can do step over/step into.
----------------------------------------------------------
Maybe, it's because of setting? I unchecked the 'Do not step into the classes' checkbox in Settings/Stepping. And then I can do step over/step into.
ku...@google.com <ku...@google.com> #5
1) Yes, it's from 3.3
2) Though it's not as common as 'if' statement, still kind of common?
2) Though it's not as common as 'if' statement, still kind of common?
ku...@google.com <ku...@google.com> #6
Short update:
As 'get constant pool' is not supported in android, when 'removeSameLinelocations' is invoked in LineBreakpoint.createRequestForPrepsredClass, it just throws exception. Meaning, we actually don't resolve/create request on breakpoint at this location( 'for loop' statement) successfully. Thus, we don't stop.
Here is the commit from IJ,https://github.com/JetBrains/intellij-community/commit/4a89f2f950a4fe8ee5f2e7ef7d4a4206ffce4f74#diff-d5e3b0bb8af1ab80e8e2be223c2bfddf .
As 'get constant pool' is not supported in android, when 'removeSameLinelocations' is invoked in LineBreakpoint.createRequestForPrepsredClass, it just throws exception. Meaning, we actually don't resolve/create request on breakpoint at this location( 'for loop' statement) successfully. Thus, we don't stop.
Here is the commit from IJ,
rp...@google.com <rp...@google.com> #7
Here is the callstack:
java.lang.UnsupportedOperationException
at com.sun.tools.jdi.ReferenceTypeImpl.getConstantPoolInfo(ReferenceTypeImpl.java:981)
at com.sun.tools.jdi.ReferenceTypeImpl.constantPool(ReferenceTypeImpl.java:1025)
at com.intellij.debugger.jdi.MethodBytecodeUtil.getConstantPool(MethodBytecodeUtil.java:61)
at com.intellij.debugger.jdi.MethodBytecodeUtil.visit(MethodBytecodeUtil.java:68)
at com.intellij.debugger.jdi.MethodBytecodeUtil.visit(MethodBytecodeUtil.java:34)
at com.intellij.debugger.jdi.MethodBytecodeUtil.removeMethodSameLineLocations(MethodBytecodeUtil.java:305)
at com.intellij.debugger.jdi.MethodBytecodeUtil.removeSameLineLocations(MethodBytecodeUtil.java:292)
at com.intellij.debugger.ui.breakpoints.LineBreakpoint.createRequestForPreparedClass(LineBreakpoint.java:112)
java.lang.UnsupportedOperationException
at com.sun.tools.jdi.ReferenceTypeImpl.getConstantPoolInfo(ReferenceTypeImpl.java:981)
at com.sun.tools.jdi.ReferenceTypeImpl.constantPool(ReferenceTypeImpl.java:1025)
at com.intellij.debugger.jdi.MethodBytecodeUtil.getConstantPool(MethodBytecodeUtil.java:61)
at com.intellij.debugger.jdi.MethodBytecodeUtil.visit(MethodBytecodeUtil.java:68)
at com.intellij.debugger.jdi.MethodBytecodeUtil.visit(MethodBytecodeUtil.java:34)
at com.intellij.debugger.jdi.MethodBytecodeUtil.removeMethodSameLineLocations(MethodBytecodeUtil.java:305)
at com.intellij.debugger.jdi.MethodBytecodeUtil.removeSameLineLocations(MethodBytecodeUtil.java:292)
at com.intellij.debugger.ui.breakpoints.LineBreakpoint.createRequestForPreparedClass(LineBreakpoint.java:112)
rp...@google.com <rp...@google.com> #8
rp...@google.com <rp...@google.com> #9
(Note: See also b/127878290 )
rp...@google.com <rp...@google.com> #10
Note: For the record, the reason we are running into this issue is a combination of
1) Some code blocks have the same line number (e.g. line 12 and line 13 point to 2 code blocks in comment #2 .)
2) The ART JVM does not support the "getConstantPool" capability
3) The IJ change mentioned in #6 introduces a regression when trying to resolve a BP for a line that has more than 1 code block (because it assumes "getConstantPool" is supported by the JVM)
1) and 2) are not new behavior, i.e. this is existing behavior for a very long time.
3) Is a new behavior introduced in late 2018 IJ code base.
The fix will be to make the code introduced in 3) conditional on the JVM supporting the "getConstantPool" operation.
1) Some code blocks have the same line number (e.g. line 12 and line 13 point to 2 code blocks in
2) The ART JVM does not support the "getConstantPool" capability
3) The IJ change mentioned in #6 introduces a regression when trying to resolve a BP for a line that has more than 1 code block (because it assumes "getConstantPool" is supported by the JVM)
1) and 2) are not new behavior, i.e. this is existing behavior for a very long time.
3) Is a new behavior introduced in late 2018 IJ code base.
The fix will be to make the code introduced in 3) conditional on the JVM supporting the "getConstantPool" operation.
Description
When compiling with D8 1.3.54 (AGP 3.3) the result of compiling:
public class BreakOnIfTest {
public static void main(String[] args) {
if (args == null) {
System.out.println("args null");
}
System.out.println("after if");
}
}
is:
registers: 3, inputs: 1, outputs: 2
------------------------------------------------------------
inst# offset instruction arguments
------------------------------------------------------------
0x00, line 9, locals: [2 -> args]
0: 0x00: IfNez v2, 0x0a (+10)
0x02, line 10, locals: [2 -> args]
1: 0x02: SgetObject v0, Field java.io.PrintStream java.lang.System.out
2: 0x04: ConstString v1, "args null"
3: 0x06: InvokeVirtual { v0 v1 } Ljava/io/PrintStream;->println(Ljava/lang/String;)V
4: 0x09: Goto 0x0b (+2)
0x0a, line 9, locals: [2 -> args]
5: 0x0a: Nop
0x0b, line 12, locals: [2 -> args]
6: 0x0b: SgetObject v0, Field java.io.PrintStream java.lang.System.out
7: 0x0d: ConstString v1, "after if"
8: 0x0f: InvokeVirtual { v0 v1 } Ljava/io/PrintStream;->println(Ljava/lang/String;)V
0x12, line 13, locals: [2 -> args]
9: 0x12: ReturnVoid
Here the PCs for line 9 are {0x00, 0x0a}. When installing a breakpoint on line 9, it appears that Studio/Intellij will fail to install a breakpoint on PC 0x00. In the D8 debugger test infrastructure, setting a breakpoint on line 9 will result in a breakpoint installed on 0x00 and 0x0a and execution will hit and break twice. As a side note to this, it would be nice to ensure that the D8 testing infrastructure mirrors the studio behavior.
On tip-of-tree and after the fix for
registers: 3, inputs: 1, outputs: 2
------------------------------------------------------------
inst# offset instruction arguments
------------------------------------------------------------
0x00, line 9, locals: [2 -> args]
0: 0x00: IfNez v2, 0x09 (+9)
0x02, line 10, locals: [2 -> args]
1: 0x02: SgetObject v0, Field java.io.PrintStream java.lang.System.out
2: 0x04: ConstString v1, "args null"
3: 0x06: InvokeVirtual { v0 v1 } Ljava/io/PrintStream;->println(Ljava/lang/String;)V
0x09, line 12, locals: [2 -> args]
4: 0x09: SgetObject v0, Field java.io.PrintStream java.lang.System.out
5: 0x0b: ConstString v1, "after if"
6: 0x0d: InvokeVirtual { v0 v1 } Ljava/io/PrintStream;->println(Ljava/lang/String;)V
0x10, line 13, locals: [2 -> args]
7: 0x10: ReturnVoid
Here, the only PC for line 9 is 0x00 and studio/intellij does install and hit that breakpoint. The underlying issue however remains as D8 can't in general ensure that there is never a conditional after the branch at the same line. It is not clear if the issue in studio/intellij only occurs for a nop continuation at this point.