[vector] ClassCastException in C2 with Mask rebracketing

Vladimir Ivanov vladimir.x.ivanov at oracle.com
Thu Feb 22 16:31:56 UTC 2018



On 2/22/18 6:47 PM, Vladimir Ivanov wrote:
> Adam,
> 
> I was able to reproduce the bug. It is unrelated to the problem I 
> described earlier.
> 
> Please, try the following patch:

Nevermind, it doesn't fix the problem.

Best regards,
Vladimir Ivanov

> diff --git a/src/hotspot/share/opto/library_call.cpp 
> b/src/hotspot/share/opto/library_call.cpp
> --- a/src/hotspot/share/opto/library_call.cpp
> +++ b/src/hotspot/share/opto/library_call.cpp
> @@ -7934,7 +7934,7 @@
>       return false;
>     }
> 
> -  Node* result = wrapWithVectorBox(opd1, box_type);
> +  Node* result = box_vector(vector, box_type, type, num_elem)
>     setVectorOutput(result);
>     return true;
>   }
> 
> The problem is that rebracketing intrinsic computes wrong box class for 
> masks.
> 
> Best regards,
> Vladimir Ivanov
> 
> On 2/21/18 11:59 PM, Adam Pocock wrote:
>> Ok. I'm trying to work around this issue by turning off C2 compilation 
>> of the binarySearchCDF method, so I can do correctness testing on the 
>> rest of the SIMD code, and maybe put it in a profiler to see how many 
>> cache misses I'm causing etc.
>>
>> I'm using "-XX:CompilerDirectivesFile=filename" pointed at a 
>> directives file containing:
>>
>> [
>> {
>>      match: 
>> "com/oracle/labs/mlrg/topicmodel/util/vector/BinarySearch.binarySearchCDF*", 
>>
>>      c2: {
>>              Exclude: true,
>>      },
>> },
>> {
>>      match: "*Float256Vector$Float256Mask.rebracket*",
>>      c2: {
>>              Exclude: true,
>>      },
>> },
>> {
>>      match: "*Int256Vector$Int256Mask.rebracket*",
>>      c2: {
>>              Exclude: true,
>>      },
>> },
>> ]
>>
>> but all I've managed to do is move around the place where I get a 
>> ClassCastException. It's still in the binarySearch but it moves to 
>> different rebracket operations. I did once manage to move it to a 
>> completely incomprehensible place where it dies with 
>> ClassCastException from Float256Vector to Int256Vector, in a function 
>> which only takes IntVector arguments, but that was after the binary 
>> search call and I suspect something weird is happening.
>>
>> Also now when I turn off the vector intrinsics with 
>> "-XX:-UseVectorApiIntrinsics" and remove the compiler directives, 
>> Hotspot core dumps midway through execution. It runs past that point 
>> if I turn off C2 with "-XX:TieredStopAtLevel=3".
>>
>> Feb 21, 2018 3:53:08 PM 
>> com.oracle.labs.mlrg.topicmodel.model.train.SSCA train
>> INFO: Iteration 0
>> #
>> # A fatal error has been detected by the Java Runtime Environment:
>> #
>> #  Internal Error (compile.cpp:2695), pid=21949, tid=21976
>> #  Error: fatal error
>> #
>> # JRE version: OpenJDK Runtime Environment (11.0) (build 
>> 11-internal+0-adhoc.apocock.panama)
>> # Java VM: OpenJDK 64-Bit Server VM 
>> (11-internal+0-adhoc.apocock.panama, mixed mode, tiered, compressed 
>> oops, g1 gc, linux-amd64)
>> # Core dump will be written. Default location: Core dumps may be 
>> processed with "/usr/share/apport/apport %p %s %c %d %P" (or dumping 
>> to /local/Repositories/TopicModel/reuters-test/core.21949)
>>
>> Should I just wait till the generalised intrinsics support has fully 
>> landed? Is there some Hotspot incantation which will let me test out 
>> areas of the code which don't use casting.
>>
>> Thanks,
>>
>> Adam
>>
>> On 16/02/18 18:14, Vladimir Ivanov wrote:
>>>
>>>> Yep, the problem went away with "-XX:-UseVectorApiIntrinsics". My 
>>>> vector shapes are unchanging though, everything is fixed at S256Bit 
>>>> as that's what I've got on my desktop. I thought the rebracket for 
>>>> things like masks were supposed to be optimised out, as a Float 256 
>>>> Mask is the same bit string as an Integer 256 Mask.
>>>
>>> Yes, rebracketing turns into an no-op when boxes go away. Otherwise, 
>>> the operand has to be boxed/reboxed.
>>>
>>>> Any idea when the generalized intrinsics will land?
>>>
>>> The first batch is already there, but no exact dates when the rest 
>>> follow.
>>>
>>> Best regards,
>>> Vladimir Ivanov
>>>
>>>> On 15/02/18 12:50, Vladimir Ivanov wrote:
>>>>> Adam,
>>>>>
>>>>> Thanks for the report.
>>>>>
>>>>> I hit a similar problem with vectors and tracked it down to a 
>>>>> changes in Parse::do_call (disabled C->optimize_virtual_call() on 
>>>>> vectors). The bug is devirtualized non-inlined call can float 
>>>>> before the type check it depends on. It leads to a wrong method 
>>>>> being called when type check fails and manifests as a CCE in 
>>>>> interpreter after deoptimization (due to failed type check). It 
>>>>> usually happens when vector shapes change at runtime: C2 produces a 
>>>>> method specialized for some particular vector shape and then the 
>>>>> first time the method observes a different vector shape.
>>>>>
>>>>> The problem is specific to original intrinsics which rely on some 
>>>>> inlining tweaks (like in Parse::do_call) to make intrinsification 
>>>>> more reliable.
>>>>>
>>>>> I suggest you to try -XX:-UseVectorApiIntrinsics and check whether 
>>>>> the problem goes away.
>>>>>
>>>>> Generalized intrinsics will be used (where available) and they 
>>>>> shouldn't be prone to that problem (relevant code path in 
>>>>> Parse::do_call is used only for original intrinsics).
>>>>>
>>>>> Unfortunately, not all operations are covered by generalized 
>>>>> intrinsics yet. So, generated code quality may suffer as well.
>>>>>
>>>>> I didn't bother fixing the bug because the plan is to replace 
>>>>> original intrinsics with generalized ones and remove inlining tweaks.
>>>>>
>>>>> Best regards,
>>>>> Vladimir Ivanov
>>>>>
>>>>> On 2/15/18 8:11 PM, Adam Pocock wrote:
>>>>>> Hi,
>>>>>>
>>>>>> I've been working on more involved machine learning demos on top 
>>>>>> of the vector API. As part of that I built a binary search demo 
>>>>>> that searches n vectors at the same time using an n-wide SIMD. 
>>>>>> This keeps rebracketing the Mask from Integer to Float and back 
>>>>>> again as it searches through the arrays.
>>>>>>
>>>>>> Paul Sandoz has been helping me debug it, and when this code is 
>>>>>> run using C1 or lower it executes fine, but when it's recompiled 
>>>>>> with C2 (triggered by executing binarySearchCDF in a loop with the 
>>>>>> same arguments and a print statement, takes about 300-500 
>>>>>> iterations) it throws a ClassCastException (stack trace below). 
>>>>>> Turning off C2 with "-XX:TieredStopAtLevel=3" allows the loop to 
>>>>>> complete.
>>>>>>
>>>>>> Code:
>>>>>>
>>>>>>      public static <S extends Vector.Shape> IntVector<S> 
>>>>>> binarySearchCDF(IntSpecies<S> spec, float[][] input, int 
>>>>>> fromIndex, int toIndex, FloatVector<S> key) {
>>>>>>          IntVector<S> low = spec.broadcast(fromIndex);
>>>>>>          IntVector<S> high = spec.broadcast(toIndex - 1);
>>>>>>          IntVector<S> one = spec.broadcast(1);
>>>>>>
>>>>>>          Mask<Float,S> mask = key.species().trueMask();
>>>>>>
>>>>>>          int[] indicesBuffer = new int[key.length()];
>>>>>>          float[] valuesBuffer = new float[key.length()];
>>>>>>
>>>>>>          while (mask.anyTrue()) {
>>>>>>              IntVector<S> mid = 
>>>>>> low.add(high,mask.rebracket(Integer.class)).shiftR(1);
>>>>>>              mid.intoArray(indicesBuffer,0);
>>>>>>              for (int i = 0; i < valuesBuffer.length; i++) {
>>>>>>                  valuesBuffer[i] = input[i][indicesBuffer[i]];
>>>>>>              }
>>>>>>              FloatVector<S> values = 
>>>>>> key.species().fromArray(valuesBuffer,0);
>>>>>>
>>>>>>              Mask<Integer,S> lessThanKey = 
>>>>>> values.lessThan(key).and(mask).rebracket(Integer.class);
>>>>>>              low = low.blend(mid.add(one),lessThanKey);
>>>>>>              Mask<Integer,S> greaterThanKey = 
>>>>>> values.greaterThan(key).and(mask).rebracket(Integer.class);
>>>>>>              high = high.blend(mid.sub(one),greaterThanKey);
>>>>>>              Mask<Integer,S> equalsKey = 
>>>>>> values.equal(key).and(mask).rebracket(Integer.class);
>>>>>>              low = low.blend(mid,equalsKey);
>>>>>>              mask = mask.and(equalsKey.rebracket(Float.class).not());
>>>>>>              mask = 
>>>>>> mask.and(low.lessThan(high).rebracket(Float.class));
>>>>>>          }
>>>>>>
>>>>>>          return low;
>>>>>>      }
>>>>>>
>>>>>> Stack trace:
>>>>>>
>>>>>> Caused by: java.lang.ClassCastException: 
>>>>>> jdk.incubator.vector/jdk.incubator.vector.Int256Vector$Int256Mask 
>>>>>> cannot be cast to 
>>>>>> jdk.incubator.vector/jdk.incubator.vector.Float256Vector$Float256Mask
>>>>>>      at 
>>>>>> jdk.incubator.vector/jdk.incubator.vector.Float256Vector$Float256Mask.and(Float256Vector.java:488) 
>>>>>>
>>>>>>      at 
>>>>>> jdk.incubator.vector/jdk.incubator.vector.Float256Vector$Float256Mask.and(Float256Vector.java:430) 
>>>>>>
>>>>>>      at 
>>>>>> mlrg.topicmodel/com.oracle.labs.mlrg.topicmodel.util.vector.BinarySearch.binarySearchCDF(BinarySearch.java:37) 
>>>>>>
>>>>>>
>>>>>> Line 37 is:
>>>>>>              mask = mask.and(equalsKey.rebracket(Float.class).not());
>>>>>>
>>>>>> Thanks,
>>>>>>
>>>>>> Adam
>>>>>>
>>>>
>>


More information about the panama-dev mailing list