Question on layer/peeling

Maurizio Cimadamore maurizio.cimadamore at oracle.com
Tue Jan 6 10:57:39 UTC 2015


Hi Peter,
something seems to be broken in the compiler w.r.t. compound conditions 
- this small test case:

class Box<any T> {
     public boolean test(T t, Object obj) {
         return obj != null && t == t;
     }
}

Shows that there's a missing BMA attribute for the IF_ACMPNE:

public boolean test(T, java.lang.Object);
     Code:
       stack=2, locals=3, args_size=3
          0: aload_2
          1: ifnull        13
          4: aload_1
          5: aload_1
          6: if_acmpne     13
          9: iconst_1
         10: goto          14
         13: iconst_0
         14: ireturn
BytecodeMapping:
       Code_idx  Signature
           4:    TT;
           5:    TT;

That's why the specializer fails. I'll look into this.

Maurizio

On 06/01/15 09:41, Peter Levart wrote:
> Hi,
>
> Here's another one:
>
>
> public final class Box<any T> {
>
>     private T value;
>
>     public Box(T value) {
>         this.value = value;
>     }
>
>     public Box() {
>         // leave default value
>     }
>
>     public T get() {
>         return value;
>     }
>
>     @SuppressWarnings("unchecked")
>     @Override
>     public boolean equals(Object obj) {
>         return (this == obj) ||
>             (obj != null &&
>                 this.getClass() == obj.getClass() && // same 
> specialization, right?
>                 this.get() == ((Box<T>)obj).get());
>                 // I think the bytecode to compare two references is 
> not specialized here to compare two integers
>     }
> }
>
>
> public class Test {
>     public static void main(String[] args) {
>         System.out.println(new Box<int>(1).equals(new Box<int>(1)));
>     }
> }
>
>
> I get the following at run time:
>
>
> Specializing util.Box${0=I}; searching for util/Box.class (not found)
> Specializing util.Box${0=I}; searching for util/Box.class (found)
> Exception in thread "main" java.lang.VerifyError: Bad type on operand 
> stack
> Exception Details:
>   Location:
>     util/Box${0=I}.equals(Ljava/lang/Object;)Z @31: if_acmpne
>   Reason:
>     Type integer (current frame, stack[1]) is not assignable to 
> reference type
>   Current Frame:
>     bci: @31
>     flags: { }
>     locals: { 'util/Box${0=I}', 'java/lang/Object' }
>     stack: { integer, integer }
>   Bytecode:
>     0000000: 2a2b a500 202b c600 202a b600 172b b600
>     0000010: 17a6 0015 2ab6 0019 2bc0 0002 b600 19a6
>     0000020: 0007 04a7 0004 03ac
>   Stackmap Table:
>     same_frame(@34)
>     same_frame(@38)
>     same_locals_1_stack_item_frame(@39,Integer)
>
>         at util.Test.main(Test.java:8)
>
>
> Regards, Peter
>
> On 01/06/2015 09:21 AM, Peter Levart wrote:
>> This could be a temporary library trick:
>>
>> public class Default<any T> {
>>
>>     private T value;
>>
>>     private Default() {}
>>
>>     public static <any T> T value() {
>>         return new Default<T>().value;
>>     }
>> }
>>
>>
>> with use like:
>>
>>
>> public class Test {
>>     public static void main(String[] args) {
>>         int i = Default.value();
>>         long l = Default.value();
>>         Object o = Default.value();
>>     }
>> }
>>
>>
>>
>> ...but unfortunately the above Test produces the following runtime 
>> exception:
>>
>>
>> Specializing method 
>> util/Default$value${0=I}.value()Ljava/lang/Object; with class=[] and 
>> method=[I]
>> Specializing util.Default${0=I}; searching for util/Default.class 
>> (not found)
>> Specializing util.Default${0=I}; searching for util/Default.class 
>> (found)
>> Exception in thread "main" java.lang.BootstrapMethodError: call site 
>> initialization exception
>>         at java.lang.invoke.CallSite.makeSite(CallSite.java:341)
>>         at 
>> java.lang.invoke.MethodHandleNatives.linkCallSiteImpl(MethodHandleNatives.java:307)
>>         at 
>> java.lang.invoke.MethodHandleNatives.linkCallSite(MethodHandleNatives.java:297)
>>         at util.Test.main(Test.java:8)
>> Caused by: java.lang.VerifyError: Bad type on operand stack
>> Exception Details:
>>   Location:
>>     util/Default$value${0=I}.value()I @7: getfield
>>   Reason:
>>     Type 'util/Default${0=I}' (current frame, stack[0]) is not 
>> assignable to 'util/Default'
>>   Current Frame:
>>     bci: @7
>>     flags: { }
>>     locals: { }
>>     stack: { 'util/Default${0=I}' }
>>   Bytecode:
>>     0000000: bb00 0959 b700 0db4 0012 ac
>>
>>         at sun.misc.Unsafe.defineAnonymousClass(Native Method)
>>         at 
>> java.lang.invoke.GenericMethodSpecializer.metafactory(GenericMethodSpecializer.java:98)
>>         at java.lang.invoke.CallSite.makeSite(CallSite.java:302)
>>         ... 3 more
>>
>>
>> Seems like the specialization of static method is not entirely 
>> correct here.
>>
>> Regards, Peter
>>
>> On 01/06/2015 03:23 AM, Brian Goetz wrote:
>>> Yes, this is pretty straightforward.  In the bucket of "things that 
>>> are easy and small, so we'll ignore them until we solve the ones 
>>> that are big and difficult.")
>>>
>>> The hardest part is picking a syntax (please, no suggestions!)
>>>
>>>
>>> On 1/5/2015 9:19 PM, Vitaly Davidovich wrote:
>>>> C# has a default (T) keyword to allow generic code to obtain the 
>>>> "zero"
>>>> value for a type param.  Something like that for java would be nice.
>>>>
>>>> Sent from my phone
>>>> On Jan 5, 2015 9:15 PM, "Michael Barker" <mikeb01 at gmail.com> wrote:
>>>>
>>>>> Hi,
>>>>>
>>>>> The SotS talks about the use of 'layer' to create an alternative
>>>>> implementation of methods when the type of an <any T> is known to 
>>>>> be a
>>>>> reference type.  However, the examples only show the use of the layer
>>>>> keyword on an interface definition, where as I've encountered at 
>>>>> least one
>>>>> case where the internal implementation needs to differentiate 
>>>>> between a
>>>>> reference-type and value-type based collection.  The example I'm 
>>>>> thinking
>>>>> about is the null-ing out of array elements in a collection (which is
>>>>> obviously a no-op with a value type, but necessity with reference
>>>>> types).  Is an interface required in order to define a 'layer' or 
>>>>> could it
>>>>> be done within a concrete class?
>>>>>
>>>>> E.g. is the following or something similar possible?  If not, how 
>>>>> would it
>>>>> be achieved with current spec?
>>>>>
>>>>> class ArrayList<any T> {
>>>>>      T[] values;
>>>>>      int position;
>>>>>
>>>>>      void removeLast() {
>>>>>          if (position <= 0) {
>>>>>              return;
>>>>>          }
>>>>>
>>>>>          --position;
>>>>>          clear(position);
>>>>>      }
>>>>>
>>>>>      private void clear(int index) {
>>>>>      }
>>>>>
>>>>>      layer<ref T> {
>>>>>          private void clear(int index) {
>>>>>              values[index] = null;
>>>>>          }
>>>>>      }
>>>>> }
>>>>>
>>>>> Mike.
>>>>>
>>
>



More information about the valhalla-dev mailing list