1 /*
   2  * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 
  25 /*
  26  * @test
  27  * @summary test VarHandle on inline class array
  28  * @compile -XDallowWithFieldOperator Point.java
  29  * @compile -XDallowWithFieldOperator Line.java
  30  * @compile -XDallowWithFieldOperator MutablePath.java
  31  * @compile -XDallowWithFieldOperator MixedValues.java NonFlattenValue.java
  32  * @run testng/othervm -XX:+EnableValhalla -XX:ValueArrayElemMaxFlatSize=-1 ArrayElementVarHandleTest
  33  * @run testng/othervm -XX:+EnableValhalla -XX:ValueArrayElemMaxFlatSize=0  ArrayElementVarHandleTest
  34  */
  35 
  36 import java.lang.invoke.*;
  37 
  38 import org.testng.annotations.DataProvider;
  39 import org.testng.annotations.Test;
  40 import static org.testng.Assert.*;
  41 
  42 public class ArrayElementVarHandleTest {
  43     private static final Point P = Point.makePoint(10, 20);
  44     private static final Line L = Line.makeLine(10, 20, 30, 40);
  45     private static final MutablePath PATH = MutablePath.makePath(10, 20, 30, 40);
  46 
  47     private static Class<?> nullablePointArrayClass() {
  48         Object a = new Point?[0];
  49         return a.getClass();
  50     }
  51 
  52     @DataProvider(name="arrayTests")
  53     static Object[][] arrayTests() {
  54         return new Object[][]{
  55             new Object[] { Point[].class,
  56                            new Point[] { Point.makePoint(1, 2),
  57                                          Point.makePoint(10, 20),
  58                                          Point.makePoint(100, 200)}},
  59             new Object[] { Point[][].class,
  60                            new Point[][] { new Point[] { Point.makePoint(1, 2),
  61                                                          Point.makePoint(10, 20)}}},
  62             new Object[] { nullablePointArrayClass(),
  63                            new Point?[] { Point.makePoint(11, 22),
  64                                           Point.makePoint(110, 220),
  65                                           null}},
  66             new Object[] { Line[].class,
  67                            new Line[] { Line.makeLine(1, 2, 3, 4),
  68                                         Line.makeLine(10, 20, 30, 40),
  69                                         Line.makeLine(15, 25, 35, 45),
  70                                         Line.makeLine(20, 30, 40, 50)}},
  71             new Object[] { MutablePath[].class,
  72                            new MutablePath[] { MutablePath.makePath(1, 2, 3, 4),
  73                                                MutablePath.makePath(10, 20, 30, 40),
  74                                                MutablePath.makePath(15, 25, 35, 45),
  75                                                MutablePath.makePath(20, 30, 40, 50)}},
  76             new Object[] { MixedValues[].class,
  77                            new MixedValues[] { new MixedValues(P, L, PATH, "mixed", "values")}},
  78             new Object[] { NonFlattenValue[].class,
  79                            new NonFlattenValue[] { NonFlattenValue.make(1, 2),
  80                                                    NonFlattenValue.make(10, 20),
  81                                                    NonFlattenValue.make(100, 200)}},
  82         };
  83     }
  84 
  85     @Test(dataProvider="arrayTests")
  86     public void set(Class<?> arrayType, Object[] elements) throws Throwable {
  87         VarHandle vh = MethodHandles.arrayElementVarHandle(arrayType);
  88         MethodHandle ctor = MethodHandles.arrayConstructor(arrayType);
  89         Object[] array = (Object[])ctor.invoke(elements.length);
  90         for (int i=0; i < elements.length; i++) {
  91             vh.set(array, i, elements[i]);
  92         }
  93         for (int i=0; i < elements.length; i++) {
  94             Object v = (Object)vh.get(array, i);
  95             assertEquals(v, elements[i]);
  96         }
  97     }
  98 
  99     @Test(dataProvider="arrayTests")
 100     public void setVolatile(Class<?> arrayType, Object[] elements) throws Throwable {
 101         VarHandle vh = MethodHandles.arrayElementVarHandle(arrayType);
 102         MethodHandle ctor = MethodHandles.arrayConstructor(arrayType);
 103         Object[] array = (Object[])ctor.invoke(elements.length);
 104         for (int i=0; i < elements.length; i++) {
 105             vh.setVolatile(array, i, elements[i]);
 106         }
 107         for (int i=0; i < elements.length; i++) {
 108             Object v = (Object)vh.getVolatile(array, i);
 109             assertEquals(v, elements[i]);
 110         }
 111     }
 112 
 113     @Test(dataProvider="arrayTests")
 114     public void setOpaque(Class<?> arrayType, Object[] elements) throws Throwable {
 115         VarHandle vh = MethodHandles.arrayElementVarHandle(arrayType);
 116         MethodHandle ctor = MethodHandles.arrayConstructor(arrayType);
 117         Object[] array = (Object[])ctor.invoke(elements.length);
 118         for (int i=0; i < elements.length; i++) {
 119             vh.setOpaque(array, i, elements[i]);
 120         }
 121         for (int i=0; i < elements.length; i++) {
 122             Object v = (Object)vh.getOpaque(array, i);
 123             assertEquals(v, elements[i]);
 124         }
 125     }
 126 
 127     @Test(dataProvider="arrayTests")
 128     public void getAndSet(Class<?> arrayType, Object[] elements) throws Throwable {
 129         VarHandle vh = MethodHandles.arrayElementVarHandle(arrayType);
 130         MethodHandle ctor = MethodHandles.arrayConstructor(arrayType);
 131         Object[] array = (Object[])ctor.invoke(elements.length);
 132         for (int i=0; i < elements.length; i++) {
 133             Object o = vh.getAndSet(array, i, elements[i]);
 134         }
 135         for (int i=0; i < elements.length; i++) {
 136             Object v = (Object)vh.get(array, i);
 137             assertEquals(v, elements[i]);
 138         }
 139     }
 140 }