forEach broken in build 48?

Maurizio Cimadamore maurizio.cimadamore at oracle.com
Thu Jul 26 03:32:14 PDT 2012


On 26/07/12 10:39, Maurizio Cimadamore wrote:
> On 26/07/12 03:53, bitter_fox wrote:
>> Hi, Arul and Mike
>> I guess Revision(langtools):1430[1] has a problem.
>>
>> In LambdaTranslator#makeFunctionalDescriptorType:
>>           return erased ? types.erasure(descType) : descType;
>>
>> This is wrong I think.
> Why do you think it's wrong? The code is meant to erase the descriptor
> type only if the erased flagh is set (which only is when doing 292
> translation).
>
> Maurizio
Also, while I see the problem in b48, I'm not able to reproduce on a 
freshly built lambda repo, which prints out the correct sequence of names:

Alice
Bob
Charlie
Dave

After looking at the differences in the generated code, I realized that 
the problem was caused by a problem with constant folding that I knew 
about and fixed yesterday ;-)

Here's the culprit:

*** Good code ***

public void apply(java.lang.String);
   Code:
    Stack=2, Locals=2, Args_size=2
    0:    aload_0
    1:    getfield    #4; //Field rec$:Ljava/io/PrintStream;
    4:    aload_1
    5:    invokevirtual    #5; //Method 
java/io/PrintStream.println:(Ljava/lang/String;)V
    8:    return

*** Bad code ***

public void apply(java.lang.String);
   Code:
    Stack=2, Locals=2, Args_size=2
    0:    aload_0
    1:    getfield    #4; //Field rec$:Ljava/io/PrintStream;
    4:    ldc    #5; //String Dave
    6:    invokevirtual    #6; //Method 
java/io/PrintStream.println:(Ljava/lang/String;)V
    9:    return

As you can see, the compiler has erroneously constant folded the access 
to the lambda parameter, thinking that the result would always be 
'Dave'. The problem lies in type inference of Arrays.asList which was 
erroneously returning a constant type whose value was 'Dave' (the last 
constant seen in the varargs call). This was caused by a missing call to 
'baseType' in Resolve.java which has now been corrected.

Maurizio
>> I tried this one and the problem looks resolved:
>>           return erased ? descType : types.erasure(descType);
>>
>> Please ignore this mail if you already notice that.
>>
>> [1]:http://mail.openjdk.java.net/pipermail/lambda-dev/2012-July/005187.html
>>
>> Regards,
>> bitter_fox
>>
>>
>> 2012/7/26 Mike Duigou <mike.duigou at oracle.com>
>>
>>> I've looked into the problem and am able to replicate it. I did some
>>> debugging and it appears to be a problem in the VM. I am notifying those
>>> working on this area.
>>>
>>> Mike
>>>
>>>
>>> On Jul 21 2012, at 01:39 , Arul Dhesiaseelan wrote:
>>>
>>>> Hi,
>>>>
>>>> It looks like forEach is broke in the latest build. It always prints the
>>>> last item in the collection. It works fine in b45. It works in b48 only
>>> if
>>>> we expand the code, not if we perform method reference on an instance.
>>>>
>>>> public class InstanceMethodReference {
>>>>
>>>>      public static void main(String[] args) {
>>>>          Arrays.asList("Alice", "Bob", "Charlie",
>>>> "Dave").forEach(System.out::println);//INCORRECT RESULT
>>>>          Arrays.asList("Alice", "Bob", "Charlie", "Dave").forEach(new
>>>> MyBlock(System.out));//CORRECT RESULT
>>>>      }
>>>>
>>>>      public static class MyBlock implements Block<String> {
>>>>          PrintStream ps;
>>>>
>>>>          public MyBlock(PrintStream ps) {
>>>>              this.ps = ps;
>>>>          }
>>>>
>>>>          @Override
>>>>          public void apply(String s) {
>>>>              ps.println(s);
>>>>          }
>>>>      }
>>>> }
>>>>
>>>> build45 correctly prints:
>>>> Alice
>>>> Bob
>>>> Charlie
>>>> Dave
>>>> Alice
>>>> Bob
>>>> Charlie
>>>> Dave
>>>>
>>>> build48 prints:
>>>> Dave
>>>> Dave
>>>> Dave
>>>> Dave
>>>> Alice
>>>> Bob
>>>> Charlie
>>>> Dave
>>>>
>>>>
>>>> -Arul
>>>>
>>>
>



More information about the lambda-dev mailing list