2012/4/22 Rémi Forax <fo...@univ-mlv.fr>:
>> So as you can see, 30 and 12 are not recognized as constants.
>
> You're right, 30 and 12 are not recognized as int constant
> but they are recognized as java/lang/Integer constant.
>
> 0x00007f785ca29706: mov    $0x7d66619d8,%r10  ;   {oop(a 'java/ang/nteger' = 
> 30)}
>
> so escape analysis works but Hotspot doesn't trust
> final field thus doesn't consider the value in the Integer
> as a constant.

I see why HotSpot can't in general trust the 'final' keyword, but it
sure would be nice if it can at least for these boxed types. After
all, if Integer.value is modified via reflection, all kinds of weird
things start to happen...

>> After a few more experiments, I realize the root cause of this isn't
>> so much as JSR-292 but more in HotSpot. For example, the following
>> method produces the following assembly code, and as you can see it's
>> failing to optimize body() into just "return false".
>
> In fact, Hotspot doesn't fail.
> But Hotspot also obfuscates the code :(
>
>> So my question is:
>>
>>   - Am I missing something?
>
> yes :)
> in that case, the body of 'body' is
> (there is a ret at 0x00007fadf244130c)
>
> 0x00007fadf24412e6: mov    $0x7d6602fe0,%r10  ;   {oop(a 'java/lang/Class' = 
> 'java/lang/Boolean')}
>   0x00007fadf24412f0: mov    0x74(%r10),%r8d    ;*getstatic FALSE

This is doing "Boolean %r8 = Boolean.FALSE"

> java.lang.Boolean::valueOf@10 (line 149)
>                                                 ; -
> BoxedBooleanInlineTest::bool1@1 (line 29)
>                                                 ; -
> BoxedBooleanInlineTest::body@1 (line 21)
>   0x00007fadf24412f4: movzbl 0xc(%r12,%r8,8),%r11d

This is doing "%r11 = %r8.value" with proper sign bit expansion

>   0x00007fadf24412fa: test   %r11d,%r11d

and this is testing if %r11 is 0.

>   0x00007fadf24412fd: jne    0x00007fadf244130d  ;*iconst_0
>                                                 ; -
> BoxedBooleanInlineTest::body@24 (line 21)
>   0x00007fadf24412ff: xor    %eax,%eax          ;*ireturn

and yes, this is "return 0"

> The code is fully optimized xor %eax, %eax put 0 in eax,
> which is by convention the register containing the return value
> and the rest of the code is not used.
> The question here is why Hostspot generates the unnecessary codes
> above the xor instruction. The code tests that zero is equals to zero
> before returning zero :)

I don't see that as a question. As I said and as you observed earlier,
this code is *not* fully optimized, in that it doesn't treat
"Boolean.FALSE.value" as a constant. And under that assumption, every
instruction in the above code does make sense.


>>   - How do other language implementers cope with this?
>
> You are the first as far as I know to use only a tree of method handles
> to implement expressions. The rest of us generates bytecodes
> and have a compiler that does constant propagation.

OK, that's good to know, but I'm not seeing how that changes the picture.

The issue is that, as things stand now, the language runtime would
have to do the type inference to use primitive types instead of
Object, or else it won't benefit from constant propagation (which
triggers other optimizations like dead code elimination and further
escape analysis.)

Say I compile "a.foo() && a.bar()" in JEXL to a byte code (or "a.foo
&& a.bar" in JRuby if that helps people understand the example
better.) Unless I can somehow prove that "a.foo()" returns a boolean,
I'd have to treat it like they return Object. And so even if at the
runtime HotSpot discovers that "a" is mostly bound to a specific type
that implements foo() as "return true", it ends up in the assembly
code like my example (with the guard if statement on top to check if
the type of 'a' is of this common type), not the equivalent of "return
false" --- suboptimal result.

Yet as I see it, such type inference is hard/impossible for most
dynamic languages. I certainly don't see how JRuby can do that. And I
thought the whole point of this new addition in Java7 was to let
HotSpot do these optimizations, as opposed to have each language
runtime do it.

So again, I don't see how shifting from method handle tree to byte
code generation would somehow make this non-issue.


But I think I got the answer to half of my questions anyway --- that I
wasn't failing to have HotSpot optimize to its fullest potential, and
instead it's the design choice / current shortcoming in HotSpot that
it doesn't consider "Boolean.FALSE.value" as "false".

That leaves me just with the other question, that how other
implementors are coping with this. The observation from Mark was
interesting --- maybe it actually doesn't cost as much as it looks in
the assembly, with branch prediction and Boolean.FALSE on cache, etc.
OTOH, I still think the constant propagation can trigger more
optimizations and those add up to something non-trivial...

-- 
Kohsuke Kawaguchi
_______________________________________________
mlvm-dev mailing list
mlvm-dev@openjdk.java.net
http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev

Reply via email to