1 /*
   2  * Copyright (c) 2019, 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 import jdk.test.lib.Asserts;
  26 
  27 import java.lang.reflect.*;
  28 import java.util.Random;
  29 import java.util.Arrays;
  30 import java.util.Comparator;
  31 
  32 import jdk.internal.misc.Unsafe;
  33 import jdk.internal.vm.jni.SubElementSelector;
  34 
  35 /*
  36  * @test
  37  * @summary Test flattened arrays accesses through JNI
  38  * @modules java.base/jdk.internal.misc java.base/jdk.internal.vm.jni
  39  * @library /testlibrary /test/lib
  40  * @requires (os.simpleArch == "x64")
  41  * @requires (os.family == "linux" | os.family == "mac")
  42  * @compile -XDallowGenericsOverValues -XDallowWithFieldOperator TestJNIArrays.java
  43  * @run main/othervm/native/timeout=3000 -XX:ValueArrayElemMaxFlatSize=128 -XX:+PrintFlattenableLayouts -XX:+UseCompressedOops TestJNIArrays
  44  * @run main/othervm/native/timeout=3000 -XX:ValueArrayElemMaxFlatSize=128 -XX:+PrintFlattenableLayouts -XX:-UseCompressedOops TestJNIArrays
  45  */
  46 
  47 public class TestJNIArrays {
  48 
  49     static final Unsafe U = Unsafe.getUnsafe();
  50     
  51     public static final int ARRAY_SIZE = 1024;
  52     static long seed;
  53     static Random random;
  54 
  55     static {
  56         seed = System.nanoTime();
  57         System.out.println("Seed = " + seed); 
  58         random = new Random(seed);
  59     }
  60 
  61     static {
  62         System.loadLibrary("TestJNIArrays");
  63     }
  64 
  65     static inline class IntInt {
  66         int i0;
  67         int i1;
  68 
  69         public IntInt(int i0, int i1) {
  70             this.i0 = i0;
  71             this.i1 = i1;
  72         }
  73     }
  74 
  75     static class IntIntComparator implements Comparator<IntInt> {
  76         public int compare(IntInt a, IntInt b) {
  77             if (a.i0 < b.i0) return -1;
  78             if (a.i0 > b.i0) return 1;
  79             if (a.i1 < b.i1) return -1;
  80             if (a.i1 > b.i1) return 1;
  81             return 0;
  82         }
  83     }
  84 
  85     static inline class Containee {
  86         float f;
  87         short s;
  88 
  89         Containee(float f, short s) {
  90             this.f = f;
  91             this.s = s;
  92         }
  93     }
  94     
  95     static inline class Container {
  96         double d;
  97         Containee c;
  98         byte b;
  99 
 100         Container(double d, Containee c, byte b) {
 101             this.d = d ;
 102             this.c = c;
 103             this.b = b;
 104         }
 105 
 106         Container setc(Containee c) {
 107             Container res = __WithField(this.c, c);
 108             return res;
 109         }
 110 
 111     }
 112 
 113     static inline class LongLongLongLong {
 114         long l0, l1, l2, l3;
 115 
 116         public LongLongLongLong(long l0, long l1, long l2, long l3) {
 117             this.l0 = l0;
 118             this.l1 = l1;
 119             this.l2 = l2;
 120             this.l3 = l3;
 121         }
 122     }
 123 
 124     static inline class BigValue {
 125         long l0 = 0, l1 = 0,   l2 = 0, l3 = 0, l4 = 0, l5 = 0, l6 = 0, l7 = 0, l8 = 0, l9 = 0;
 126         long l10 = 0, l11 = 0, l12 = 0, l13 = 0, l14 = 0, l15 = 0, l16 = 0, l17 = 0, l18 = 0, l19 = 0;
 127         long l20 = 0, l21 = 0, l22 = 0, l23 = 0, l24 = 0, l25 = 0, l26 = 0, l27 = 0, l28 = 0, l29 = 0;
 128         long l30 = 0, l31 = 0, l32 = 0, l33 = 0, l34 = 0, l35 = 0, l36 = 0, l37 = 0, l38 = 0, l39 = 0;
 129     }
 130 
 131     static inline class ValueWithOops {
 132         String s = "bonjour";
 133         int i = 0;
 134         Containee c = new Containee(2.3f, (short)4);
 135         BigValue b = new BigValue();
 136     }
 137     
 138     public static void main(String[] args) {
 139         TestJNIArrays test = new TestJNIArrays();
 140         test.checkGetFlattenedArrayElementSize();
 141         test.checkGetFlattenedArrayElementClass();
 142         test.checkGetFieldOffsetInFlattenedLayout();
 143         test.checkGetFlattenedArrayElements();
 144         test.checkSubElementAPI();
 145         test.checkBehaviors();
 146         // test.mesureInitializationTime(1024 * 1024 * 10 , 1000);
 147         // test.mesureInitializationTime2(1024 * 1024 * 10 , 1000);
 148         // test.mesureUpdateTime2(1024 * 1024 * 10, 1000);
 149         // test.mesureSortingTime(1024 * 1024, 100); // reduced number of iterations because Java sorting is slow (because of generics?)
 150         test.mesureInitializationTime3(1024 * 1024 * 2 , 1000);
 151     }
 152 
 153     void checkSubElementAPI() {
 154         Throwable e = null;
 155         ValueWithOops[] arrayWithOops = new ValueWithOops[100];
 156         ValueWithOops v = new ValueWithOops();
 157         for (int i = 0; i < 100; i++) {
 158             arrayWithOops[i] = v;
 159         }
 160         SubElementSelector selector1 = createSubElementSelector(arrayWithOops);
 161         SubElementSelector selector2 = getSubElementSelector(selector1, ValueWithOops.class, "s", "Ljava/lang/String;");
 162         String s = (String) getObjectSubElement(arrayWithOops, selector2, 1);
 163         System.out.println("s = " + s);
 164         Asserts.assertEquals(s.equals("bonjour"), true, "Wrong string, expecting \"bonjour\", got " + s); 
 165         SubElementSelector selector3 = getSubElementSelector(selector1, ValueWithOops.class, "c", "QTestJNIArrays$Containee;");
 166         Containee c = (Containee) getObjectSubElement(arrayWithOops, selector3, 2);
 167         Asserts.assertEquals(c.f, 2.3f, "Wrong float value: " + c.f);
 168         Asserts.assertEquals(c.s, (short)4, "Wrong short value " + c.s);
 169         setObjectSubElement(arrayWithOops, selector2, 1, "Hello");
 170         Asserts.assertEquals(arrayWithOops[1].s.equals("Hello"), true, "Wrong string, expecting \"Hello\", got " + s);
 171         Integer myInteger = new Integer(345);
 172         e = null;
 173         try {
 174             setObjectSubElement(arrayWithOops, selector2, 1, myInteger);
 175         } catch(Throwable t) {
 176             e = t;
 177         }
 178         Asserts.assertNotNull(e, "An exception should have been thrown");
 179         Asserts.assertEquals(e.getClass(), java.lang.ArrayStoreException.class, "Wrong exception type");
 180         c = new Containee(9.8f, (short)-3);
 181         setObjectSubElement(arrayWithOops, selector3, 2, c);
 182         Asserts.assertEquals(c.f, 9.8f, "Wrong float value: " + c.f);
 183         Asserts.assertEquals(c.s, (short)-3, "Wrong short value " + c.s);
 184         e = null;
 185         try {
 186             setObjectSubElement(arrayWithOops, selector3, 2, null);
 187         } catch(Throwable t) {
 188             e = t;
 189         }
 190         Asserts.assertNotNull(e, "An exception should have been thrown");
 191         Asserts.assertEquals(e.getClass(), java.lang.ArrayStoreException.class, "Wrong exception type");
 192         SubElementSelector selector4 = getSubElementSelector(selector3, TestJNIArrays.Containee.class, "s", "S");
 193         short s2 = getShortSubElement(arrayWithOops, selector4, 3);
 194         Asserts.assertEquals(s2, (short)4, "Wrong short value " + s2);
 195         setShortSubElement(arrayWithOops, selector4, 3, (short)7);
 196         Asserts.assertEquals(arrayWithOops[3].c.s, (short)7, "Wrong short value " + arrayWithOops[3].c.s);
 197         e = null;
 198         try {
 199             // should fail because selector4 designates a field with type short, not int
 200             getIntSubElement(arrayWithOops, selector4, 3);
 201         } catch(Throwable t) {
 202             e = t;
 203         }
 204         Asserts.assertNotNull(e, "An exception should have been thrown");
 205         Asserts.assertEquals(e.getClass(), java.lang.IllegalArgumentException.class, "Wrong exception type");
 206         SubElementSelector selector5 = getSubElementSelector(selector1, ValueWithOops.class, "b", "QTestJNIArrays$BigValue;");
 207         e = null;
 208         try {
 209             // Should fail because selector5 designates a non-flattened field
 210             SubElementSelector selector6 = getSubElementSelector(selector5, TestJNIArrays.BigValue.class, "l0", "J");
 211         } catch(Throwable t) {
 212             e = t;
 213         }
 214         Asserts.assertNotNull(e, "An exception should have been thrown");
 215         Asserts.assertEquals(e.getClass(), java.lang.IllegalArgumentException.class, "Wrong exception type");
 216         System.gc();
 217     }
 218     
 219     void checkGetFlattenedArrayElementSize() {
 220         Throwable exception = null;
 221         try {
 222             Object o = new Object();
 223             GetFlattenedArrayElementSizeWrapper(o);
 224         } catch(Throwable t) {
 225             exception = t;
 226         }
 227         Asserts.assertNotNull(exception, "An IAE should have been thrown");
 228         Asserts.assertEquals(exception.getClass(), IllegalArgumentException.class , "Wrong exception type");
 229         exception = null;
 230         try {
 231             int[] array = new int[16];
 232             Object o = array;
 233             GetFlattenedArrayElementSizeWrapper(o);
 234         } catch(Throwable t) {
 235             exception = t;
 236         }
 237         Asserts.assertNotNull(exception, "An IAE should have been thrown");
 238         Asserts.assertEquals(exception.getClass(), IllegalArgumentException.class , "Wrong exception type");
 239         exception = null;
 240         try {
 241             GetFlattenedArrayElementSizeWrapper(new String[16]);
 242         } catch(Throwable t) {
 243             exception = t;
 244         }
 245         Asserts.assertNotNull(exception, "An IAE should have been thrown");
 246         Asserts.assertEquals(exception.getClass(), IllegalArgumentException.class , "Wrong exception type");
 247         exception = null;
 248         try {
 249             // Array of BigValue should not be flattened because BigValue is *big*
 250             GetFlattenedArrayElementSizeWrapper(new BigValue[16]);
 251         } catch(Throwable t) {
 252             exception = t;
 253         }
 254         Asserts.assertNotNull(exception, "An IAE should have been thrown");
 255         Asserts.assertTrue(exception instanceof IllegalArgumentException , "Exception should be a IAE");
 256         exception = null;
 257         int size = -1;
 258         try {
 259             size = GetFlattenedArrayElementSizeWrapper(new IntInt[16]);
 260         } catch(Throwable t) {
 261             exception = t;
 262         }
 263         Asserts.assertNull(exception, "No exception should have been thrown");
 264         Asserts.assertEquals(size, 8, "Wrong size");
 265     }
 266 
 267     void checkGetFlattenedArrayElementClass() {
 268         Throwable exception = null;
 269         try {
 270             Object o = new Object();
 271             GetFlattenedArrayElementClassWrapper(o);
 272         } catch(Throwable t) {
 273             exception = t;
 274         }
 275         Asserts.assertNotNull(exception, "An IAE should have been thrown");
 276         Asserts.assertEquals(exception.getClass(), IllegalArgumentException.class , "Wrong exception type");
 277         exception = null;
 278         try {
 279             int[] array = new int[16];
 280             Object o = array;
 281             GetFlattenedArrayElementClassWrapper(o);
 282         } catch(Throwable t) {
 283             exception = t;
 284         }
 285         Asserts.assertNotNull(exception, "An IAE should have been thrown");
 286         Asserts.assertEquals(exception.getClass(), IllegalArgumentException.class , "Wrong exception type");
 287         exception = null;
 288         try {
 289             GetFlattenedArrayElementClassWrapper(new String[16]);
 290         } catch(Throwable t) {
 291             exception = t;
 292         }
 293         Asserts.assertNotNull(exception, "An IAE should have been thrown");
 294         Asserts.assertEquals(exception.getClass(), IllegalArgumentException.class , "Wrong exception type");
 295         exception = null;
 296         try {
 297             // Array of BigValue should not be flattened because BigValue is *big*
 298             GetFlattenedArrayElementClassWrapper(new BigValue[16]);
 299         } catch(Throwable t) {
 300             exception = t;
 301         }
 302         Asserts.assertNotNull(exception, "An IAE should have been thrown");
 303         Asserts.assertTrue(exception instanceof IllegalArgumentException , "Exception should be a IAE");
 304         exception = null;
 305         Class c = null;
 306         try {
 307             c = GetFlattenedArrayElementClassWrapper(new IntInt[16]);
 308         } catch(Throwable t) {
 309             exception = t;
 310         }
 311         Asserts.assertNull(exception, "No exception should have been thrown");
 312         Asserts.assertEquals(c, IntInt.class, "Wrong class");
 313     }
 314 
 315     void checkGetFieldOffsetInFlattenedLayout() {
 316         Throwable exception = null;
 317         try {
 318             Object o = new Object();
 319             GetFieldOffsetInFlattenedLayoutWrapper(o.getClass(), "foo", "I", true);
 320         } catch(Throwable t) {
 321             exception = t;
 322         }
 323         Asserts.assertNotNull(exception, "An IAE should have been thrown");
 324         Asserts.assertEquals(exception.getClass(), IllegalArgumentException.class , "Wrong exception type");
 325         exception = null;
 326         try {
 327             int[] array = new int[16];
 328             GetFieldOffsetInFlattenedLayoutWrapper(array.getClass(), "foo", "I", true);
 329         } catch(Throwable t) {
 330             exception = t;
 331         }
 332         Asserts.assertNotNull(exception, "An IAE should have been thrown");
 333         Asserts.assertEquals(exception.getClass(), IllegalArgumentException.class , "Wrong exception type");
 334         exception = null;
 335         try {
 336             String[] array = new String[16];
 337             GetFieldOffsetInFlattenedLayoutWrapper(array.getClass(), "foo", "I", true);
 338         } catch(Throwable t) {
 339             exception = t;
 340         }
 341         Asserts.assertNotNull(exception, "An IAE should have been thrown");
 342         Asserts.assertEquals(exception.getClass(), IllegalArgumentException.class , "Wrong exception type");
 343         exception = null;
 344         Containee ce  = new Containee(3.4f, (short)5);
 345         Container c = new Container(123.876, ce, (byte)7);
 346         Class<?> cclass = c.getClass();
 347         Container[] containerArray = new Container[32];
 348         int elementSize = GetFlattenedArrayElementSizeWrapper(containerArray);
 349         int offset = -1;
 350         try {
 351             offset = GetFieldOffsetInFlattenedLayoutWrapper(cclass, "d", "D", false);
 352         } catch(Throwable t) {
 353             exception = t;
 354         }
 355         Asserts.assertNull(exception, "No exception should have been thrown");
 356         Field f = null;
 357         try {
 358             f = cclass.getDeclaredField("d");
 359         } catch(NoSuchFieldException e) {
 360             e.printStackTrace();
 361             return;
 362         }
 363         Asserts.assertEquals(U.valueHeaderSize(cclass) + offset, U.objectFieldOffset(cclass, f.getName()),
 364                              "Incorrect offset");
 365         Asserts.assertLessThan(offset, elementSize, "Invalid offset");
 366         exception = null;
 367         try {
 368             // Field c should be flattened, so last argument is true, no exception expected
 369             GetFieldOffsetInFlattenedLayoutWrapper(cclass, "c", "QTestJNIArrays$Containee;", true);
 370         } catch(Throwable t) {
 371             exception = t;
 372         }
 373         Asserts.assertNull(exception, "No exception should have been thrown");
 374         Asserts.assertLessThan(offset, elementSize, "Invalid offset");
 375         exception = null;
 376         try {
 377             // Field c should be flattened, with last argument being false, exception expected from the wrapper 
 378             GetFieldOffsetInFlattenedLayoutWrapper(cclass, "c", "QTestJNIArrays$Containee;", false);
 379         } catch(Throwable t) {
 380             exception = t;
 381         }
 382         Asserts.assertNotNull(exception, "Wrapper should have thrown a RuntimeException");
 383         Asserts.assertEquals(exception.getClass(), RuntimeException.class , "Wrong exception type");
 384     }
 385     
 386      void checkGetFlattenedArrayElements() {
 387         Throwable exception = null;
 388         Object o = new Object();
 389         try {
 390             GetFlattenedArrayElementsWrapper(o);
 391         } catch(Throwable t) {
 392             exception = t;
 393         }
 394         Asserts.assertNotNull(exception, "An IAE should have been thrown");
 395         Asserts.assertEquals(exception.getClass(), IllegalArgumentException.class , "Wrong exception type");
 396         exception = null;
 397         int[] a1 = new int[16];
 398         o = a1;
 399         try {
 400             GetFlattenedArrayElementsWrapper(o);
 401         } catch(Throwable t) {
 402             exception = t;
 403         }
 404         Asserts.assertNotNull(exception, "An IAE should have been thrown");
 405         Asserts.assertEquals(exception.getClass(), IllegalArgumentException.class , "Wrong exception type");
 406         exception = null;
 407         try {
 408             GetFlattenedArrayElementsWrapper(new String[16]);
 409         } catch(Throwable t) {
 410             exception = t;
 411         }
 412         Asserts.assertNotNull(exception, "An IAE should have been thrown");
 413         Asserts.assertEquals(exception.getClass(), IllegalArgumentException.class , "Wrong exception type");
 414         exception = null;
 415         try {
 416             // Array of BigValue should not be flattened because BigValue is *big*
 417             GetFlattenedArrayElementsWrapper(new BigValue[16]);
 418         } catch(Throwable t) {
 419             exception = t;
 420         }
 421         Asserts.assertNotNull(exception, "An IAE should have been thrown");
 422         Asserts.assertTrue(exception instanceof IllegalArgumentException , "Exception should be a IAE");
 423         exception = null;
 424         try {
 425             // Direct native access to flattened arrays is not allowed if elements contain oops
 426             GetFlattenedArrayElementsWrapper(new ValueWithOops[16]);
 427         } catch(Throwable t) {
 428             exception = t;
 429         }
 430         Asserts.assertNotNull(exception, "An IAE should have been thrown");
 431         Asserts.assertTrue(exception instanceof IllegalArgumentException , "Exception should be a IAE");
 432         exception = null;
 433         long addr = 0;
 434         IntInt[] a2 = new IntInt[16];
 435         try {
 436             addr = GetFlattenedArrayElementsWrapper(a2);
 437         } catch(Throwable t) {
 438             exception = t;
 439         }
 440         Asserts.assertNull(exception, "No exception should have been thrown");
 441         if (exception == null) {
 442             ReleaseFlattenedArrayElementsWrapper(a2, addr, 0);
 443         }
 444     }
 445     
 446     void checkBehaviors() {
 447         System.out.println("Check 1");
 448         IntInt[] array = new IntInt[ARRAY_SIZE];
 449         int value = getIntFieldAtIndex(array, 1, "i0", "I");
 450         Asserts.assertEquals(value, 0, "Initial value must be zero");
 451         printArrayInformation(array);
 452         int i0_value = 42;
 453         int i1_value = -314;
 454         initializeIntIntArrayBuffer(array, i0_value, i1_value);
 455         System.gc();
 456         for (int i = 0; i < array.length; i++) {
 457             Asserts.assertEquals(array[i].i0, i0_value, "Bad value of i0 at index " + i);
 458             Asserts.assertEquals(array[i].i1, i1_value, "Bad value of i1 at index " + i);
 459         }
 460         System.out.println("Check 2");
 461         array = new IntInt[ARRAY_SIZE];
 462         i0_value = -194;
 463         i1_value = 91;
 464         initializeIntIntArrayFields(array, i0_value, i1_value);
 465         System.gc();
 466         for (int i = 0; i < array.length; i++) {
 467             Asserts.assertEquals(array[i].i0, i0_value, "Bad value of i0 at index " + i);
 468             Asserts.assertEquals(array[i].i1, i1_value, "Bad value of i1 at index " + i);
 469         }
 470         System.out.println("Check 3");
 471         array = new IntInt[ARRAY_SIZE];
 472         initializeIntIntArrayJava(array, i0_value, i1_value);
 473         System.gc();
 474         for (int i = 0; i < array.length; i++) {
 475             Asserts.assertEquals(array[i].i0, i0_value, "Bad value of i0 at index " + i);
 476             Asserts.assertEquals(array[i].i1, i1_value, "Bad value of i1 at index " + i);
 477         }
 478         System.out.println("Check 4");
 479         random = new Random(seed);
 480         array = new IntInt[ARRAY_SIZE];
 481         for (int i = 0; i < ARRAY_SIZE; i++) {
 482             array[i] = new IntInt(random.nextInt(), random.nextInt());
 483         }
 484         sortIntIntArray(array);
 485         System.gc();
 486         for (int i = 0; i < array.length - 1; i++) {
 487             Asserts.assertLessThanOrEqual(array[i].i0, array[i+1].i0, "Incorrect i0 fields ordering at index " + i);
 488             if (array[i].i0 == array[i+1].i0) {
 489                 Asserts.assertLessThanOrEqual(array[i].i1, array[i+1].i1, "Incorrect i1 fields ordering at index " + i);
 490             }
 491         }
 492         System.out.println("Check 5");
 493         random = new Random(seed);
 494         array = new IntInt[ARRAY_SIZE];
 495         for (int i = 0; i < ARRAY_SIZE; i++) {
 496             array[i] = new IntInt(random.nextInt(), random.nextInt());
 497         }
 498         Arrays.sort(array, new IntIntComparator());
 499         System.gc();
 500         for (int i = 0; i < array.length - 1; i++) {
 501             Asserts.assertLessThanOrEqual(array[i].i0, array[i+1].i0, "Incorrect i0 fields ordering at index " + i);
 502             if (array[i].i0 == array[i+1].i0) {
 503                 Asserts.assertLessThanOrEqual(array[i].i1, array[i+1].i1, "Incorrect i1 fields ordering at index " + i);
 504             }
 505         }
 506         System.out.println("Check 6");
 507         Container[] array2 = new Container[ARRAY_SIZE];
 508         double d  = 1.23456789;
 509         float f = -987.654321f;
 510         short s = -512;
 511         byte b = 127;
 512         Containee c = new Containee(f,s);
 513         Container c2 = new Container(d, c, b);
 514         initializeContainerArray(array2, d, f, s, b);
 515         System.gc();
 516         for (int i = 0; i < array2.length; i++) {
 517             Asserts.assertEquals(array2[i], c2, "Incorrect value at index " + i);
 518             Asserts.assertEquals(array2[i].d, d, "Incorrect d value at index " + i);
 519             Asserts.assertEquals(array2[i].c.f, f, "Incorrect f value at index " + i);
 520             Asserts.assertEquals(array2[i].c.s, s, "Incorrect s value at index " + i);
 521             Asserts.assertEquals(array2[i].b, b, "Incorrect b value at inde " +i);
 522         }
 523         System.out.println("Check 7");
 524         f = 19.2837465f;
 525         s = 231;
 526         updateContainerArray(array2, f, s);
 527         System.gc();
 528         for (int i = 0; i < array2.length; i++) {
 529             Asserts.assertEquals(array2[i].d, d, "Incorrect d value at index " + i);
 530             Asserts.assertEquals(array2[i].c.f, f, "Incorrect f value at index " + i);
 531             Asserts.assertEquals(array2[i].c.s, s, "Incorrect s value at index " + i);
 532             Asserts.assertEquals(array2[i].b, b, "Incorrect b value at inde " +i);
 533         }
 534         System.out.println("Check 8");
 535         long l0 = 52467923;
 536         long l1= -7854022;
 537         long l2 = 230947485;
 538         long l3 = -752497024;
 539         LongLongLongLong[] array3 = new LongLongLongLong[ARRAY_SIZE/8];
 540         initializeLongLongLongLongArray(array3, l0, l1, l2, l3);
 541         System.gc();
 542         for (int i = 0; i < array3.length; i++) {
 543             Asserts.assertEquals(array3[i].l0, l0, "Bad value of l0 at index " + i);
 544             Asserts.assertEquals(array3[i].l1, l1, "Bad value of l1 at index " + i);
 545             Asserts.assertEquals(array3[i].l2, l2, "Bad value of l2 at index " + i);
 546             Asserts.assertEquals(array3[i].l3, l3, "Bad value of l3 at index " + i);
 547         }
 548     }
 549 
 550     void initializeIntIntArrayJava(IntInt[] array, int i0, int i1) {
 551         IntInt ii = new IntInt(i0, i1);
 552         for (int i = 0; i < array.length; i++) {
 553             array[i] = ii;
 554         }
 555     }
 556 
 557     void initializeContainerArrayJava(Container[] array, double d, float f, short s, byte b) {
 558         Containee c = new Containee(f,s);
 559         Container c2 = new Container(d, c, b);
 560         for (int i = 0; i < array.length; i++) {
 561             array[i] = c2;
 562         }
 563     }
 564 
 565     void updateContainerArrayJava(Container[] array, float f, short s) {
 566         Containee c = new Containee(f, s);
 567         for (int i = 0; i < array.length; i++) {
 568             array[i] = array[i].setc(c);;
 569         }
 570     }
 571 
 572     void initializeLongLongLongLongArrayJava(LongLongLongLong[] array, long l0, long l1, long l2, long l3) {
 573         LongLongLongLong llll = new LongLongLongLong(l0, l1, l2, l3);
 574         for (int i = 0; i < array.length; i++) {
 575             array[i] = llll;
 576         }
 577     }
 578     
 579     void mesureInitializationTime(int array_size, int iterations) {
 580         System.out.println("\nInitialization time for IntInt[]:");
 581         long[] start = new long[iterations];
 582         long[] end = new long[iterations];
 583 
 584         
 585         System.out.println("\nJava:");
 586         // Warmup
 587         for (int i = 0; i < 10; i++) {
 588             IntInt[] array = new IntInt[array_size];
 589             initializeIntIntArrayJava(array, 42, -314);
 590         }
 591         // Measure
 592         for (int i = 0; i < iterations; i++) {
 593             IntInt[] array = new IntInt[array_size];
 594             start[i] = System.nanoTime();
 595             initializeIntIntArrayJava(array, 42, -314);
 596             end[i] = System.nanoTime();
 597         }
 598         // Results
 599         computeStatistics(start, end);
 600 
 601         System.out.println("\nNative(memcpy):");
 602         // Warmup
 603         for (int i = 0; i < 10; i++) {
 604             IntInt[] array = new IntInt[array_size];
 605             initializeIntIntArrayBuffer(array, 42, -314);
 606         }
 607         // Measure
 608         for (int i = 0; i < iterations; i++) {
 609             IntInt[] array = new IntInt[array_size];
 610             start[i] = System.nanoTime();
 611             initializeIntIntArrayBuffer(array, 42, -314);
 612             end[i] = System.nanoTime();
 613         }
 614         // Results
 615         computeStatistics(start, end);
 616         
 617         
 618         System.out.println("\nNative(fields):");
 619         // Warmup
 620         for (int i = 0; i < 10; i++) {
 621             IntInt[] array = new IntInt[array_size];
 622             initializeIntIntArrayFields(array, 42, -314);
 623         }
 624         // Measure
 625         for (int i = 0; i < iterations; i++) {
 626             IntInt[] array = new IntInt[array_size];
 627             start[i] = System.nanoTime();
 628             initializeIntIntArrayFields(array, 42, -314);
 629             end[i] = System.nanoTime();
 630         }
 631         // Results
 632         computeStatistics(start, end);
 633     }
 634 
 635     void mesureInitializationTime2(int array_size, int iterations) {
 636         System.out.println("\nInitialization time for Container[]:");
 637         long[] start = new long[iterations];
 638         long[] end = new long[iterations];
 639 
 640         double d = 0.369852147;
 641         float f = -321.654987f;
 642         short s = -3579;
 643         byte b = 42;
 644         
 645         System.out.println("\nJava:");
 646         // Warmup
 647         for (int i = 0; i < 10; i++) {
 648             Container[] array = new Container[array_size];
 649             initializeContainerArrayJava(array, d, f, s, b);
 650         }
 651         // Measure
 652         for (int i = 0; i < iterations; i++) {
 653             Container[] array = new Container[array_size];
 654             start[i] = System.nanoTime();
 655             initializeContainerArrayJava(array, d, f, s, b);
 656             end[i] = System.nanoTime();
 657         }
 658         // Results
 659         computeStatistics(start, end);
 660 
 661         System.out.println("\nNative:");
 662         // Warmup
 663         for (int i = 0; i < 10; i++) {
 664             Container[] array = new Container[array_size];
 665             initializeContainerArray(array, d, f, s, b);
 666         }
 667         // Measure
 668         for (int i = 0; i < iterations; i++) {
 669             Container[] array = new Container[array_size];
 670             start[i] = System.nanoTime();
 671             initializeContainerArray(array, d, f, s, b);
 672             end[i] = System.nanoTime();
 673         }
 674         // Results
 675         computeStatistics(start, end);
 676     }
 677 
 678     void mesureUpdateTime2(int array_size, int iterations) {
 679         System.out.println("\nUpdating Container[]:");
 680         long[] start = new long[iterations];
 681         long[] end = new long[iterations];
 682 
 683         double d = 0.369852147;
 684         float f = -321.654987f;
 685         short s = -3579;
 686         byte b = 42;
 687 
 688         Containee c = new Containee(f,s);
 689         Container c2 = new Container(d, c, b);
 690         
 691         System.out.println("\nJava:");
 692         // Warmup
 693         for (int i = 0; i < 10; i++) {
 694             Container[] array = new Container[array_size];
 695             for (int j = 0; j < array.length; j++) {
 696                 array[j] = c2;
 697             }
 698             updateContainerArrayJava(array, f, s);
 699         }
 700         // Measure
 701         for (int i = 0; i < iterations; i++) {
 702             Container[] array = new Container[array_size];
 703             for (int j = 0; j < array.length; j++) {
 704                 array[i] = c2;
 705             }
 706             start[i] = System.nanoTime();
 707             updateContainerArrayJava(array, f, s);
 708             end[i] = System.nanoTime();
 709         }
 710         // Results
 711         computeStatistics(start, end);
 712 
 713         System.out.println("\nNative:");
 714         // Warmup
 715         for (int i = 0; i < 10; i++) {
 716             Container[] array = new Container[array_size];
 717             for (int j = 0; j < array.length; j++) {
 718                 array[i] = c2;
 719             }
 720             updateContainerArray(array, f, s);
 721         }
 722         // Measure
 723         for (int i = 0; i < iterations; i++) {
 724             Container[] array = new Container[array_size];
 725             for (int j = 0; j < array.length; j++) {
 726                 array[i] = c2;
 727             }
 728             start[i] = System.nanoTime();
 729             updateContainerArray(array, f, s);
 730             end[i] = System.nanoTime();
 731         }
 732         // Results
 733         computeStatistics(start, end);
 734     }
 735     
 736     void mesureSortingTime(int array_size, int iterations) {
 737         System.out.println("\nSorting time:");
 738         long[] start = new long[iterations];
 739         long[] end = new long[iterations];
 740 
 741         random = new Random(seed);
 742         System.out.println("\nJava:");
 743         IntIntComparator comparator = new IntIntComparator();
 744         // Warmup
 745         for (int i = 0; i < 10; i++) {
 746             IntInt[] array = new IntInt[array_size];
 747             array = new IntInt[array_size];
 748             for (int j = 0; j < array_size; j++) {
 749                 array[j] = new IntInt(random.nextInt(), random.nextInt());
 750             }
 751             Arrays.sort(array, comparator);
 752         }
 753         // Measure
 754         for (int i = 0; i < iterations; i++) {
 755             IntInt[] array = new IntInt[array_size];
 756             for (int j = 0; j < array_size; j++) {
 757                 array[j] = new IntInt(random.nextInt(), random.nextInt());
 758             }
 759             start[i] = System.nanoTime();
 760             Arrays.sort(array, comparator);
 761             end[i] = System.nanoTime();
 762         }
 763         // Results
 764         computeStatistics(start, end);
 765 
 766         random = new Random(seed);
 767         System.out.println("\nNative:");
 768         // Warmup
 769         for (int i = 0; i < 10; i++) {
 770             IntInt[] array = new IntInt[array_size];
 771             array = new IntInt[array_size];
 772             for (int j = 0; j < array_size; j++) {
 773                 array[j] = new IntInt(random.nextInt(), random.nextInt());
 774             }
 775             sortIntIntArray(array);
 776         }
 777         // Measure
 778         for (int i = 0; i < iterations; i++) {
 779             IntInt[] array = new IntInt[array_size];
 780             for (int j = 0; j < array_size; j++) {
 781                 array[j] = new IntInt(random.nextInt(), random.nextInt());
 782             }
 783             start[i] = System.nanoTime();
 784             sortIntIntArray(array);
 785             end[i] = System.nanoTime();
 786         }
 787         // Results
 788         computeStatistics(start, end);
 789     }
 790 
 791 
 792     void mesureInitializationTime3(int array_size, int iterations) {
 793         System.out.println("\nInitialization time for LongLongLongLong[]:");
 794         long[] start = new long[iterations];
 795         long[] end = new long[iterations];
 796 
 797         long l0 = 123456;
 798         long l1 = -987654;
 799         long l2 = 192837;
 800         long l3 = -56473829;
 801         
 802         System.out.println("\nJava:");
 803         // Warmup
 804         for (int i = 0; i < 10; i++) {
 805             LongLongLongLong[] array = new LongLongLongLong[array_size];
 806             initializeLongLongLongLongArrayJava(array, l0, l1, l2, l3);
 807         }
 808         // Measure
 809         for (int i = 0; i < iterations; i++) {
 810             LongLongLongLong[] array = new LongLongLongLong[array_size];
 811             start[i] = System.nanoTime();
 812             initializeLongLongLongLongArrayJava(array, l0, l1, l2, l3);
 813             end[i] = System.nanoTime();
 814         }
 815         // Results
 816         computeStatistics(start, end);
 817 
 818         System.out.println("\nNative:");
 819         // Warmup
 820         for (int i = 0; i < 10; i++) {
 821             LongLongLongLong[] array = new LongLongLongLong[array_size];
 822             initializeLongLongLongLongArray(array, l0, l1, l2, l3);
 823         }
 824         // Measure
 825         for (int i = 0; i < iterations; i++) {
 826             LongLongLongLong[] array = new LongLongLongLong[array_size];
 827             start[i] = System.nanoTime();
 828             initializeLongLongLongLongArray(array, l0, l1, l2, l3);
 829             end[i] = System.nanoTime();
 830         }
 831         // Results
 832         computeStatistics(start, end);
 833     }
 834     
 835     void computeStatistics(long[] start, long[] end) {
 836         int iterations = start.length;
 837         long[] duration = new long[iterations];
 838         long sum = 0;
 839         long min = end[0] - start[0];
 840         long max = min;
 841         double var = 0.0;
 842         for (int i = 0 ; i < iterations; i++) {
 843             duration[i] = end[i] - start[i];
 844             if (duration[i] < min) min = duration[i];
 845             if (duration[i] > max) max = duration[i];
 846             sum += duration[i];
 847             double d = (double) duration[i];
 848             var += Math.pow(d, 2);
 849         }
 850         double avg = (sum/iterations) / 1000;
 851         double std = (Math.sqrt(var/iterations - Math.pow(sum/iterations, 2))) / 1000;
 852         System.out.println(String.format("Avg: %8.2f us", avg));
 853         System.out.println(String.format("Std: %8.2f us", std));
 854         System.out.println(String.format("Min: %8d us", (min/1000)));
 855         System.out.println(String.format("Max: %8d us", (max/1000)));
 856     }
 857 
 858     native int GetFlattenedArrayElementSizeWrapper(Object array);
 859     native Class GetFlattenedArrayElementClassWrapper(Object array);
 860     native long GetFlattenedArrayElementsWrapper(Object array);
 861     native void ReleaseFlattenedArrayElementsWrapper(Object array, long addr,int mode);
 862     native int GetFieldOffsetInFlattenedLayoutWrapper(Class klass, String name, String signature, boolean flattened);
 863     
 864     native int getIntFieldAtIndex(Object[] array, int index, String fieldName, String FieldSignature);
 865     native void printArrayInformation(Object[] array);
 866 
 867     native void initializeIntIntArrayBuffer(Object[] array, int i0, int i1);
 868     native void initializeIntIntArrayFields(Object[] array, int i0, int i1);
 869     native void sortIntIntArray(Object[] array);
 870 
 871     native void initializeContainerArray(Object[] array, double d, float f, short s, byte b);
 872     native void updateContainerArray(Object[] array, float f, short s);
 873 
 874     native void initializeLongLongLongLongArray(Object[] array, long l0, long l1, long l2, long l3);
 875 
 876     native SubElementSelector createSubElementSelector(Object[] array);
 877     native SubElementSelector getSubElementSelector(SubElementSelector selector, Class<?> klass, String name, String signature);
 878     native Object getObjectSubElement(Object[] array, SubElementSelector selector, int index);
 879     native void setObjectSubElement(Object[] array, SubElementSelector selector, int index, Object value);
 880 
 881     native short getShortSubElement(Object[] array, SubElementSelector selector, int index);
 882     native void setShortSubElement(Object[] array, SubElementSelector selector, int index, short value);
 883     native int getIntSubElement(Object[] array, SubElementSelector selector, int index);
 884     native void setIntSubElement(Object[] array, SubElementSelector selector, int index, int value);
 885 }