Skip to content
Permalink
Browse files
8260473: [vector] ZGC: VectorReshape test produces incorrect results …
…with ZGC enabled

Co-authored-by: Stuart Monteith <smonteith@openjdk.org>
Co-authored-by: Wang Chao <casparcwang@tencent.com>
Reviewed-by: vlivanov, neliasso
  • Loading branch information
2 people authored and DamonFool committed Feb 1, 2021
1 parent bc41bb1 commit 0fdf9cdd3a234d363468d71f6493fbc5b687b0e4
Showing with 174 additions and 9 deletions.
  1. +12 −9 src/hotspot/share/opto/vector.cpp
  2. +162 −0 test/hotspot/jtreg/compiler/vectorapi/VectorRebracket128Test.java
@@ -23,6 +23,7 @@
*/

#include "precompiled.hpp"
#include "gc/shared/barrierSet.hpp"
#include "opto/castnode.hpp"
#include "opto/graphKit.hpp"
#include "opto/phaseX.hpp"
@@ -412,15 +413,17 @@ void PhaseVector::expand_vunbox_node(VectorUnboxNode* vec_unbox) {

Node* mem = vec_unbox->mem();
Node* ctrl = vec_unbox->in(0);
Node* vec_field_ld = LoadNode::make(gvn,
ctrl,
mem,
vec_adr,
vec_adr->bottom_type()->is_ptr(),
TypeOopPtr::make_from_klass(field->type()->as_klass()),
T_OBJECT,
MemNode::unordered);
vec_field_ld = gvn.transform(vec_field_ld);
Node* vec_field_ld;
{
DecoratorSet decorators = MO_UNORDERED | IN_HEAP;
C2AccessValuePtr addr(vec_adr, vec_adr->bottom_type()->is_ptr());
MergeMemNode* local_mem = MergeMemNode::make(mem);
gvn.record_for_igvn(local_mem);
BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2();
C2OptAccess access(gvn, ctrl, local_mem, decorators, T_OBJECT, obj, addr);
const Type* type = TypeOopPtr::make_from_klass(field->type()->as_klass());
vec_field_ld = bs->load_at(access, type);
}

// For proper aliasing, attach concrete payload type.
ciKlass* payload_klass = ciTypeArrayKlass::make(bt);
@@ -0,0 +1,162 @@
/*
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import jdk.incubator.vector.*;
import jdk.internal.vm.annotation.ForceInline;
import org.testng.Assert;
import org.testng.annotations.Test;
import org.testng.annotations.DataProvider;

import java.lang.invoke.MethodHandles;
import java.lang.invoke.VarHandle;
import java.nio.ByteOrder;
import java.util.Arrays;
import java.util.List;
import java.util.function.IntFunction;
import java.util.function.IntUnaryOperator;
import jdk.incubator.vector.VectorShape;
import jdk.incubator.vector.VectorSpecies;
import jdk.internal.vm.annotation.ForceInline;

/*
* @test
* @bug 8260473
* @requires vm.gc.Z
* @modules jdk.incubator.vector
* @modules java.base/jdk.internal.vm.annotation
* @run testng/othervm -XX:CompileCommand=compileonly,jdk/incubator/vector/ByteVector.fromByteBuffer
* -XX:-TieredCompilation -XX:CICompilerCount=1 -XX:+UseZGC -Xbatch -Xmx256m VectorRebracket128Test
*/

@Test
public class VectorRebracket128Test {
static final int INVOC_COUNT = Integer.getInteger("jtreg.compiler.vectorapi.vectorrebracket128test.loop-iterations", 1000);
static final int NUM_ITER = 200 * INVOC_COUNT;

static final VectorSpecies<Integer> ispec128 = IntVector.SPECIES_128;
static final VectorSpecies<Float> fspec128 = FloatVector.SPECIES_128;
static final VectorSpecies<Long> lspec128 = LongVector.SPECIES_128;
static final VectorSpecies<Double> dspec128 = DoubleVector.SPECIES_128;
static final VectorSpecies<Byte> bspec128 = ByteVector.SPECIES_128;
static final VectorSpecies<Short> sspec128 = ShortVector.SPECIES_128;

static <T> IntFunction<T> withToString(String s, IntFunction<T> f) {
return new IntFunction<T>() {
@Override
public T apply(int v) {
return f.apply(v);
}

@Override
public String toString() {
return s;
}
};
}

interface ToByteF {
byte apply(int i);
}

static byte[] fill_byte(int s , ToByteF f) {
return fill_byte(new byte[s], f);
}

static byte[] fill_byte(byte[] a, ToByteF f) {
for (int i = 0; i < a.length; i++) {
a[i] = f.apply(i);
}
return a;
}

static final List<IntFunction<byte[]>> BYTE_GENERATORS = List.of(
withToString("byte(i)", (int s) -> {
return fill_byte(s, i -> (byte)(i+1));
})
);

@DataProvider
public Object[][] byteUnaryOpProvider() {
return BYTE_GENERATORS.stream().
map(f -> new Object[]{f}).
toArray(Object[][]::new);
}

static
void checkPartialResult(VectorSpecies<?> a, VectorSpecies<?> b,
byte[] input, byte[] output, byte[] expected,
int part, int origin) {
if (Arrays.equals(expected, output)) {
return;
}
int block;
block = Math.min(a.vectorByteSize(), b.vectorByteSize());

System.out.println("input: "+Arrays.toString(input));
System.out.println("Failing with "+a+"->"+b+
" (reinterpret)"+
", block=" + block +
", part=" + part +
", origin=" + origin);
System.out.println("expect: "+Arrays.toString(expected));
System.out.println("output: "+Arrays.toString(output));
Assert.assertEquals(expected, output);
}

@ForceInline
static <E,F>
void testVectorRebracket(VectorSpecies<E> a, VectorSpecies<F> b, byte[] input, byte[] output) {
Vector<E> av = a.fromByteArray(input, 0, ByteOrder.nativeOrder());
int block;
assert(input.length == output.length);

block = Math.min(a.vectorByteSize(), b.vectorByteSize());
if (false)
System.out.println("testing "+a+"->"+b+
(false?" (lanewise)":" (reinterpret)")+
", block=" + block);
byte[] expected;
int origin;

int part = 0;
Vector<F> bv = av.reinterpretShape(b, part);
bv.intoByteArray(output, 0, ByteOrder.nativeOrder());
// in-place copy, no resize
expected = input;
origin = 0;
checkPartialResult(a, b, input, output, expected,
part, origin);

}

@Test(dataProvider = "byteUnaryOpProvider")
static void testRebracket128(IntFunction<byte[]> fa) {
byte[] barr = fa.apply(128/Byte.SIZE);
byte[] bout = new byte[barr.length];
for (int i = 0; i < NUM_ITER; i++) {
testVectorRebracket(bspec128, bspec128, barr, bout);
testVectorRebracket(bspec128, sspec128, barr, bout);
testVectorRebracket(bspec128, ispec128, barr, bout);
}
}

}

0 comments on commit 0fdf9cd

Please sign in to comment.