Dex post processing tools

71 views
Skip to first unread message

msg555

unread,
Sep 5, 2010, 11:38:00 PM9/5/10
to android-platform
Subject, are there any?

Just taking a cursorary glance at the result of disassembling an app
that I've been working on I see a number of things that appear to not
be optimized at all. For example I found the following sequence

000d: v0 = v4.this$0;
000f: monitor-enter v00
0010: v1 = v4.this$0;
0012: v2 = v4.this$0;
0014: v0002 = GPS.access$200(v2);
0018: v3 = v4.this$0;
001a: v0003 = GPS.access$100(v3);
001e: v0002 = v2.getGpsStatus(v3);
0022: GPS.access$102(v1, v2);
0025: monitor-exit v00
0026: return-void

It seems there is room for a post processing bytecode optimizing tool
if one hasn't been made. Any thoughts?

Also, why was it necessary to add access$xxx methods? Is this
something that happens at javac time or dx time? Does it somehow make
validation easier if inner classes aren't accessing members of their
parents directly? (are there other cases where this is used?)

msg555

unread,
Sep 6, 2010, 12:01:13 AM9/6/10
to android-platform
And perhaps even more disturbing is this little gem, though I think
it's just because of the obviousness of it.

0010: new-instance v00 type@Audio$1
0012: v0.<init>(v1);
0015: v1.audioNotif = v0;
0017: v0 = v1.audioNotif;

I guess I should mention as well that there are no points in either of
these segments that flow control could branch into the middle of them.

Chris Stratton

unread,
Sep 6, 2010, 3:12:46 AM9/6/10
to android-platform
Try some hand optimizations that look tempting and see if it still
works.

I can't help wondering if the two stage compilation process is smart,
or if it was more a way to get a working platform shipped without
getting distracted into compiler engineering.

On Sep 5, 11:38 pm, msg555 <msg...@gmail.com> wrote:

fadden

unread,
Sep 7, 2010, 6:55:31 PM9/7/10
to android-platform
On Sep 5, 8:38 pm, msg555 <msg...@gmail.com> wrote:
> It seems there is room for a post processing bytecode optimizing tool
> if one hasn't been made.  Any thoughts?

Try running dx with "--no-locals --positions=important", or pass in
code that was built without "-g". If there's no debug info to
preserve, the dx optimizer is a bit more aggressive about crunching
stuff out.

public class Ack {
public void splat() {
int i;
i = 1; i = 1; i = 1; i = 1; i = 1;
i = 1; i = 1; i = 1; i = 1; i = 1;
}
}

With "javac -g":
000110: 1210 | 0000: const/4 v0, #int 1 // #1
000112: 1210 | 0001: const/4 v0, #int 1 // #1
000114: 1210 | 0002: const/4 v0, #int 1 // #1
000116: 1210 | 0003: const/4 v0, #int 1 // #1
000118: 1210 | 0004: const/4 v0, #int 1 // #1
00011a: 1210 | 0005: const/4 v0, #int 1 // #1
00011c: 1210 | 0006: const/4 v0, #int 1 // #1
00011e: 1210 | 0007: const/4 v0, #int 1 // #1
000120: 1210 | 0008: const/4 v0, #int 1 // #1
000122: 1210 | 0009: const/4 v0, #int 1 // #1
000124: 0e00 | 000a: return-void

Without "-g":

000100: 0e00 | 0000: return-void


> Also, why was it necessary to add access$xxx methods?  Is this
> something that happens at javac time or dx time?  Does it somehow make
> validation easier if inner classes aren't accessing members of their
> parents directly? (are there other cases where this is used?)

That's a javac thing. Inner and outer classes have no special
relationship once the compiler is done, but the compiler gives them
special treatment for access to private methods and fields. The
compiler generates synthetic access methods to get at the private
bits.

msg555

unread,
Sep 8, 2010, 2:30:27 PM9/8/10
to android-platform
Interesting. I tried doing as you said with the same codebase as
before and I arrived with the same results when I looked at the two
methods from before. The only difference it seems is now I don't have
debugging information. The actual instructions are exactly the same
(at least in the two places I mentioned before).

Is there someway I need to turn on optimizations with dex or javac?

msg555

unread,
Sep 9, 2010, 2:56:20 PM9/9/10
to android-platform
So I went ahead and made a basic post optimizer. The code is all open
source and is now part of the dxcut project on source forge.

http://sourceforge.net/projects/dxcut/files/

The generated binary is called "basic_opt". Right now the only thing
that it does is remove consecutive {i,s}put, {i,s}get instructions
with the same registers and fields within the same basic block. Maybe
this can open the door to other people to make this kind of thing.

msg555

unread,
Sep 23, 2010, 1:12:49 PM9/23/10
to android-platform
Hi again everyone. I've been working on my post processing dalvik
optimizer and I think I've gotten it to a point where other people
might find it interesting. What I have it doing now is changing the
registers used by operations when two registers are aliased to only
use one of them and then removing operations that have no side effects
that have their output never used. Note that here I'm considering a
field access and const-string/class to have no side effects even
though they could potentially throw.

So for the previous piece of code it is now automatically rewritten
as:

000d: v0 = v4.this$0;
000f: monitor-enter v00
0010: v1 = v4.this$0;
0012: v0002 = GPS.access$200(v1);
0016: v0003 = GPS.access$100(v1);
001a: v0002 = v2.getGpsStatus(v3);
001e: GPS.access$102(v1, v2);
0021: monitor-exit v00
0022: return-void

When I run the tool on my app I trim 356 instructions out of 30194
(approx. 1%). I trim 5316 of 546233 instructions when I run it on the
framework library's classes.dex.

Obviously there is still some work to be done. For example 0010 could
be delete here and replace all instances of v1 with v0. This
currently isn't done because 000d,000f are in a different basic blocks
(though they are the only entry basic block to 0010-0022) than the
rest and the register rewriting is done only at the basic block level
currently.

You can find the tool with the same link I gave before (v0.3.1). I
don't suggest using this in production yet as the correctness of the
transformations has only loosely been tested. Nevertheless you might
be interested in how much better your app could be and perhaps you
could help the post op effort.

Check out the source for basic_opt at
http://dxcut.svn.sourceforge.net/viewvc/dxcut/tools/basic_opt/basic_opt.cpp?revision=HEAD&view=markup
Most of the interesting work happens in opt_bb and opt_func.

fadden

unread,
Sep 23, 2010, 5:56:32 PM9/23/10
to android-platform
On Sep 23, 10:12 am, msg555 <msg...@gmail.com> wrote:
>       000d: v0 = v4.this$0;
>       000f: monitor-enter v00
>       0010: v1 = v4.this$0;
[...]
> Obviously there is still some work to be done.  For example 0010 could
> be delete here and replace all instances of v1 with v0.

Well, maybe.

You're not allowed to move code out of a synchronized block, only in.
More concretely, I don't think you can guarantee that no other thread
has altered v4.this$0 between the first and second reads.

If you're going to perform optimizations at this level, you really
need to be familiar with JSR-133 (Java Memory Model) to understand
what reorderings are and aren't allowed.

Chen Yang

unread,
Sep 23, 2010, 6:20:55 PM9/23/10
to android-...@googlegroups.com
Cool, how about the performance result with your optimization? Thanks.
--
Chen

--
You received this message because you are subscribed to the Google Groups "android-platform" group.
To post to this group, send email to android-...@googlegroups.com.
To unsubscribe from this group, send email to android-platfo...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/android-platform?hl=en.


Reply all
Reply to author
Forward
0 new messages