Neo
Neo

Reputation: 5463

What are the methods for optimizing bytecode in Android's DX tool?

I'm learning Dalvik bytecode now, it has many differences from the JVM bytecode. I want to know what optimizations it makes when converting java bytecode into dalvik bytecode.

The optimization I'm talking about is not like converting to registers or reducing the size of bytecode, I want to know about control flow merging and code reuse.

For example: jvm's byetcode:

public static void demo();
    descriptor: ()V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=3, locals=4, args_size=0
         0: new           #2                  // class java/util/Random
         3: dup
         4: invokespecial #3                  // Method java/util/Random."<init>":()V
         7: astore_0
         8: aload_0
         9: invokevirtual #4                  // Method java/util/Random.nextInt:()I
        12: istore_1
        13: iload_1
        14: ifge          27
        17: getstatic     #5                  // Field java/lang/System.out:Ljava/io/PrintStream;
        20: iload_1
        21: invokevirtual #6                  // Method java/io/PrintStream.println:(I)V
        24: goto          147
        27: iload_1
        28: iconst_1
        29: if_icmple     116
        32: iload_1
        33: iconst_4
        34: if_icmpge     116
        37: getstatic     #5                  // Field java/lang/System.out:Ljava/io/PrintStream;
        40: iload_1
        41: iconst_1
        42: iadd
        43: invokevirtual #6                  // Method java/io/PrintStream.println:(I)V
        46: aload_0
        47: invokevirtual #4                  // Method java/util/Random.nextInt:()I
        50: istore_2
        51: aload_0
        52: invokevirtual #4                  // Method java/util/Random.nextInt:()I
        55: istore_3
        56: iload_2
        57: bipush        10
        59: if_icmple     73
        62: getstatic     #5                  // Field java/lang/System.out:Ljava/io/PrintStream;
        65: ldc           #7                  // String abc is 10
        67: invokevirtual #8                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        70: goto          113
        73: iload_2
        74: bipush        20
        76: if_icmple     113
        79: iload_2
        80: bipush        100
        82: if_icmpge     113
        85: getstatic     #5                  // Field java/lang/System.out:Ljava/io/PrintStream;
        88: ldc           #9                  // String abc less 100
        90: invokevirtual #8                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        93: iload_3
        94: sipush        1000
        97: if_icmple     113
       100: getstatic     #5                  // Field java/lang/System.out:Ljava/io/PrintStream;
       103: ldc           #10                 // String ccc
       105: invokevirtual #8                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
       108: aload_0
       109: invokevirtual #4                  // Method java/util/Random.nextInt:()I
       112: istore_3
       113: goto          147
       116: iload_1
       117: iconst_3
       118: if_icmpeq     127
       121: iload_1
       122: bipush        10
       124: if_icmple     139
       127: getstatic     #5                  // Field java/lang/System.out:Ljava/io/PrintStream;
       130: iload_1
       131: iconst_3
       132: iadd
       133: invokevirtual #6                  // Method java/io/PrintStream.println:(I)V
       136: goto          147
       139: getstatic     #5                  // Field java/lang/System.out:Ljava/io/PrintStream;
       142: ldc           #11                 // String n
       144: invokevirtual #8                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
       147: return

same method in dalvik bytecode

[000198] IfTest.demo:()V
0000: const/16 v3, #int 10 // #a
0002: new-instance v0, Ljava/util/Random; // type@0006
0004: invoke-direct {v0}, Ljava/util/Random;.<init>:()V // method@0006
0007: invoke-virtual {v0}, Ljava/util/Random;.nextInt:()I // method@0007
000a: move-result v1
000b: if-gez v1, 0013 // +0008
000d: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0000
000f: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(I)V // method@0003
0012: return-void
0013: const/4 v2, #int 1 // #1
0014: if-le v1, v2, 0050 // +003c
0016: const/4 v2, #int 4 // #4
0017: if-ge v1, v2, 0050 // +0039
0019: sget-object v2, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0000
001b: add-int/lit8 v1, v1, #int 1 // #01
001d: invoke-virtual {v2, v1}, Ljava/io/PrintStream;.println:(I)V // method@0003
0020: invoke-virtual {v0}, Ljava/util/Random;.nextInt:()I // method@0007
0023: move-result v1
0024: invoke-virtual {v0}, Ljava/util/Random;.nextInt:()I // method@0007
0027: move-result v2
0028: if-le v1, v3, 0032 // +000a
002a: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0000
002c: const-string v1, "abc is 10" // string@000d
002e: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@0004
0031: goto 0012 // -001f
0032: const/16 v3, #int 20 // #14
0034: if-le v1, v3, 0012 // -0022
0036: const/16 v3, #int 100 // #64
0038: if-ge v1, v3, 0012 // -0026
003a: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0000
003c: const-string v3, "abc less 100" // string@000e
003e: invoke-virtual {v1, v3}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@0004
0041: const/16 v1, #int 1000 // #3e8
0043: if-le v2, v1, 0012 // -0031
0045: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0000
0047: const-string v2, "ccc" // string@000f
0049: invoke-virtual {v1, v2}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@0004
004c: invoke-virtual {v0}, Ljava/util/Random;.nextInt:()I // method@0007
004f: goto 0012 // -003d
0050: const/4 v0, #int 3 // #3
0051: if-eq v1, v0, 0055 // +0004
0053: if-le v1, v3, 005d // +000a
0055: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0000
0057: add-int/lit8 v1, v1, #int 3 // #03
0059: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(I)V // method@0003
005c: goto 0012 // -004a
005d: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0000
005f: const-string v1, "n" // string@0011
0061: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@0004
0064: goto 0012 // -0052

the dalvik bytecode reuses return-void at offset 0012, and if statement's true target also can reuses the return-void.

This looks like if a return occurs, then the following places that need to return will jump to the first return.

Upvotes: 0

Views: 76

Answers (0)

Related Questions