MVT-based vectors: first stab

Vladimir Ivanov vladimir.x.ivanov at oracle.com
Wed Jun 28 14:36:45 UTC 2017



On 6/28/17 5:08 PM, Maurizio Cimadamore wrote:
> Great work Vlad; I have two questions before I dive in more details
> 
> * why did you need to handle arrayLength() specially? Since an array is 
> a reference, shouldn't it work already?

It's a workaround for C2 crashes I observed when working with 
arraylength method handle on Q-typed arrays. The problem for the 
compiler is that the implementation uses 
ArrayAccessor.lengthL(Object[]), so on bytecode level there's a conflict 
between declared & actual type (DVT[] doesn't extend Object[]).

IMO the proper fix would be to have "erased" version for such cases (or 
replace all primitive array specializations with a single "erased" version):

   static int lengthL(java.lang.Object);
          0: aload_0
          1: arraylength
          2: ireturn

But it can't be expressed in Java language and requires bytecode 
generation.

> * Can you explain me exactly what you were trying to achieve with 
> state.push/state.pop in the intrinsic generation? Typically the state is 
> updated through opcodes - so, assuming you are generating bytecodes that 
> make sense, you should not need this - unless there are bugs in the code 
> builder (which is possible!)

The following sequence usually hits the bug in the code builder:
   builder.goto_("l1");
   builder.label("l2");

goto_() doesn't wipe the state, but the state at l2 doesn't relate to 
the state when jumping to l1. It usually manifests as stack depth or 
type mismatches when trying to merge the states in builder.label().

Best regards,
Vladimir Ivanov

> On 28/06/17 14:17, Vladimir Ivanov wrote:
>> Hi,
>>
>> I started playing with MVT-based vectors recently and want to share my 
>> experience so far.
>>
>> For the first step, I decided to avoid specific treatment of 
>> super-longs (Long2/4/8) in the JVM we have in Panama and just mark 
>> them as VCCs for now:
>>   @DeriveValueType
>>   final class Long2 { public final long lo, hi; }
>>
>> As a test case I chose sum of array elements:
>>
>>   long sum(QLong2[] va) {
>>     QLong2 v = QLong2.default; // (0,0)
>>     for (int i = 0; i < va.length; i++) {
>>       QLong2 vi = va[i];
>>       v = QLong2(v.lo + vi.lo, v.hi + vi.hi);
>>     }
>>     return v.lo + v.hi;
>>   }
>>
>> Here are the changes:
>>  http://cr.openjdk.java.net/~vlivanov/valhalla/vectors.mvt/webrev.00/
>>
>> SUMMARY & RESULTS
>>
>> I hit some bugs along the way and had to extend the code for Q-types 
>> in some places to get decent code shape generated. (I'll shepherd the 
>> fixes in the repo separately.) I ended up with the following generated 
>> code:
>>
>> http://cr.openjdk.java.net/~vlivanov/valhalla/vectors.mvt/sumArrayL2.log
>>
>> Unfortunately, there are still 2 allocations left in the generated 
>> code (out of 5 initially). C2 can't scalarize the accumulator (v) 
>> inside the loop and has to put updated components (lo & hi) in 
>> allocated heap buffer on every iteration over the array (generated 
>> code [1], C2 EA output [2]).
>>
>>
>> GORY DETAILS
>>
>>   hotspot/src/share/vm/opto/type.cpp
>>
>>     * Type::get_typeflow_type() doesn't distinguish between 
>> TypeValueTypePtr & TypeValueType
>>
>>
>> jdk/src/java.base/share/classes/java/lang/invoke/LambdaFormBuilder.java
>>
>>     * introduced some LF intrinsics, e.g. LOOP and SELECT_ALTERNATIVE;
>>
>>     * had to workaround control flow-related bugs in the bytecode 
>> library (jdk.experimental.bytecode): broken JVM state after goto_() 
>> (see FIXME marks in the code);
>>
>>     * fixed 2-slot types support: wrong local indexes were used
>>
>>
>>
>> jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java
>>
>>     * MHI.unboxResultHandle misses unboxing step for Q-types
>>
>>
>> jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java
>> jdk/src/java.base/share/classes/jdk/experimental/value/ValueType.java
>>
>>     * had to add a specialization for arraylength on Q-typed array, 
>> because C2 can't handle arraylength Object[] when Q[] instance is on 
>> stack;
>>
>>
>> jdk/src/java.base/share/classes/jdk/experimental/bytecode/TypedCodeBuilder.java: 
>>
>>
>>     * changes required to workaround goto_() bug
>>
>>     * fixed CP patching support
>>
>>
>> jdk/src/java.base/share/classes/jdk/experimental/value/MethodHandleBuilder.java 
>>
>>
>>     * fixed CP patching support
>>
>>
>>   hotspot/src/share/vm/memory/metachunk.hpp
>>   hotspot/src/share/vm/oops/method.hpp
>>     Fix optimized JVM build.
>>
>> Best regards,
>> Vladimir Ivanov
>>
>> [1] 
>> http://cr.openjdk.java.net/~vlivanov/valhalla/vectors.mvt/sumArrayL2.log
>>
>> ;; B7: # B8 <- B9  top-of-loop
>>
>> mov    %r9,0x10(%rsp)
>> mov    0x8(%rsp),%r11d
>>
>> ;; B8: # B16 B9 <- B6 B7   Loop: B8-B7 inner
>>
>> mov    %r11d,0x8(%rsp)
>> movabs $0x7c0060420,%rsi  ; {metadata('valhalla/vector/Long2$Value')}
>> ...
>> callq  0x0000000117579820 ;   {runtime_call _new_instance_Java}
>>
>> ;; B9: # B7 B10 <- B8
>>
>> mov    %rax,%r9
>> mov    0x10(%rsp),%r11
>> mov    0x10(%r11),%r10
>> mov    0x18(%r11),%r11
>> movslq %ebp,%r8
>> shl    $0x4,%r8
>> mov    (%rsp),%rcx
>> mov    0x18(%rcx,%r8,1),%rax
>> mov    0x10(%rcx,%r8,1),%r8  ;*vaload
>> add    %r11,%rax          ;*ladd
>> mov    %rax,0x18(%r9)
>> add    %r10,%r8           ;*ladd
>> mov    %r8,0x10(%r9)
>> inc    %ebp               ;*iadd
>> cmp    0x8(%rsp),%ebp
>> jl     <B7>               ;*if_icmpge
>>
>> [2] Pruned EA output (full output in the log)
>> ======== Connection graph for valhalla.vector.VectorTest::sumArrayL2
>> JavaObject NoEscape(NoEscape) NSR [ 1267F 1265F 756F 754F 1581F 1579F 
>> [ 1259 1264 532 1525 ]]   1247    Allocate
>> LocalVar [ 1247P [ 1264 ]]   1259    Proj ... #5
>> LocalVar [ 1259 1247P [ 1267b 1265b 532 1525 ]]   1264 CheckCastPP ... 
>> #valuetype* valhalla/vector/Long2$Value:NotNull
>> LocalVar [ 324 1264 1247P 307P [ 756b 754b ]]   532    Phi ... 
>> #valuetype* valhalla/vector/Long2$Value:NotNull
>> LocalVar [ 1264 324 1247P 307P [ 1581b 1579b ]]   1525    Phi ... 
>> #valuetype* valhalla/vector/Long2$Value:NotNull
>>
>> JavaObject NoEscape(NoEscape) [ 1154F [ 1148 1153 ]]   1136 Allocate
>> LocalVar [ 1136P [ 1153 ]]   1148    Proj ... #5
>> LocalVar [ 1148 1136P [ 1154b ]]   1153    CheckCastPP ... #valuetype* 
>> valhalla/vector/Long2$Value:NotNull
>>
>> JavaObject NoEscape(NoEscape) [ [ 1053 ]]   1041    Allocate
>> LocalVar [ 1041P [ ]]   1053    Proj ... #5
>>
>> JavaObject NoEscape(NoEscape) [ 653F 651F [ 645 650 ]]   633 Allocate
>> LocalVar [ 633P [ 650 ]]   645    Proj ... #5
>> LocalVar [ 645 633P [ 653b 651b ]]   650    CheckCastPP ... 
>> #valuetype* valhalla/vector/Long2$Value:NotNull
>>
>> JavaObject NoEscape(NoEscape) NSR [ 756F 754F 1581F 1579F [ 319 324 
>> 532 1525 ]]   307    Allocate
>> LocalVar [ 307P [ 324 ]]   319    Proj ... #5
>> LocalVar [ 319 307P [ 532 1525 ]]   324    CheckCastPP  ... 
>> #valuetype* valhalla/vector/Long2$Value:NotNull
>> LocalVar [ 324 1264 1247P 307P [ 756b 754b ]]   532    Phi ... 
>> #valuetype* valhalla/vector/Long2$Value:NotNull
>> LocalVar [ 1264 324 1247P 307P [ 1581b 1579b ]]   1525    Phi ... 
>> #valuetype* valhalla/vector/Long2$Value:NotNull
>>
>> Scalar  1153    CheckCastPP ... #valuetype* 
>> valhalla/vector/Long2$Value:NotNull
>> ++++ Eliminated: 1136 Allocate
>> Scalar  1041    Allocate ...
>> ++++ Eliminated: 1041 Allocate
>> Scalar  650    CheckCastPP ... #valuetype* 
>> valhalla/vector/Long2$Value:NotNull
>> ++++ Eliminated: 633 Allocate
> 


More information about the valhalla-dev mailing list