Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/Java/Openjdk/test/jdk/java/foreign/normalize/   (Sun/Oracle ©)  Datei vom 13.11.2022 mit Größe 9 kB image not shown  

Quelle  TestNormalize.java   Sprache: JAVA

 
/*
 * Copyright (c) 2022, 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.
 */


/*
 * @test
 * @enablePreview
 * @library ../
 * @requires ((os.arch == "amd64" | os.arch == "x86_64") & sun.arch.data.model == "64") | os.arch == "aarch64"
 * @run testng/othervm
 *   --enable-native-access=ALL-UNNAMED
 *   -Xbatch
 *   -XX:CompileCommand=dontinline,TestNormalize::doCall*
 *   TestNormalize
 */


import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

import java.lang.foreign.Arena;
import java.lang.foreign.FunctionDescriptor;
import java.lang.foreign.Linker;
import java.lang.foreign.MemorySegment;
import java.lang.foreign.ValueLayout;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;

import static java.lang.foreign.ValueLayout.ADDRESS;
import static java.lang.foreign.ValueLayout.JAVA_BOOLEAN;
import static java.lang.foreign.ValueLayout.JAVA_BYTE;
import static java.lang.foreign.ValueLayout.JAVA_CHAR;
import static java.lang.foreign.ValueLayout.JAVA_INT;
import static java.lang.foreign.ValueLayout.JAVA_SHORT;
import static org.testng.Assert.assertEquals;

// test normalization of smaller than int primitive types
public class TestNormalize extends NativeTestHelper {

    private static final Linker LINKER = Linker.nativeLinker();
    private static final MethodHandle SAVE_BOOLEAN_AS_INT;
    private static final MethodHandle SAVE_BYTE_AS_INT;
    private static final MethodHandle SAVE_SHORT_AS_INT;
    private static final MethodHandle SAVE_CHAR_AS_INT;

    private static final MethodHandle BOOLEAN_TO_INT;
    private static final MethodHandle BYTE_TO_INT;
    private static final MethodHandle SHORT_TO_INT;
    private static final MethodHandle CHAR_TO_INT;

    private static final MethodHandle NATIVE_BOOLEAN_TO_INT;

    private static final int BOOLEAN_HOB_MASK = ~0b1;
    private static final int BYTE_HOB_MASK    = ~0xFF;
    private static final int SHORT_HOB_MASK   = ~0xFFFF;
    private static final int CHAR_HOB_MASK    = ~0xFFFF;

    private static final MethodHandle SAVE_BOOLEAN;

    static {
        System.loadLibrary("Normalize");

        try {
            MethodHandles.Lookup lookup = MethodHandles.lookup();
            SAVE_BOOLEAN_AS_INT = lookup.findStatic(TestNormalize.class"saveBooleanAsInt", MethodType.methodType(void.classboolean.classint[].class));
            SAVE_BYTE_AS_INT = lookup.findStatic(TestNormalize.class"saveByteAsInt", MethodType.methodType(void.classbyte.classint[].class));
            SAVE_SHORT_AS_INT = lookup.findStatic(TestNormalize.class"saveShortAsInt", MethodType.methodType(void.classshort.classint[].class));
            SAVE_CHAR_AS_INT = lookup.findStatic(TestNormalize.class"saveCharAsInt", MethodType.methodType(void.classchar.classint[].class));

            BOOLEAN_TO_INT = lookup.findStatic(TestNormalize.class"booleanToInt", MethodType.methodType(int.classboolean.class));
            BYTE_TO_INT = lookup.findStatic(TestNormalize.class"byteToInt", MethodType.methodType(int.classbyte.class));
            SHORT_TO_INT = lookup.findStatic(TestNormalize.class"shortToInt", MethodType.methodType(int.classshort.class));
            CHAR_TO_INT = lookup.findStatic(TestNormalize.class"charToInt", MethodType.methodType(int.classchar.class));

            NATIVE_BOOLEAN_TO_INT = LINKER.downcallHandle(findNativeOrThrow("int_identity"), FunctionDescriptor.of(JAVA_INT, JAVA_BOOLEAN));

            SAVE_BOOLEAN = lookup.findStatic(TestNormalize.class"saveBoolean", MethodType.methodType(void.classboolean.classboolean[].class));
        } catch (ReflectiveOperationException e) {
            throw new ExceptionInInitializerError(e);
        }
    }

    // The idea of this test is that we pass a 'dirty' int value down to native code, and then receive it back
    // as the argument to an upcall, as well as the result of the downcall, but with a sub-int type (boolean, byte, short, char).
    // When we do either of those, argument normalization should take place, so that the resulting value is sane (1).
    // After that we convert the value back to int again, the JVM can/will skip value normalization here.
    // We then check the high order bits of the resulting int. If argument normalization took place at (1), they should all be 0.
    @Test(dataProvider = "cases")
    public void testNormalize(ValueLayout layout, int testValue, int hobMask, MethodHandle toInt, MethodHandle saver) throws Throwable {
        // use actual type as parameter type to test upcall arg normalization
        FunctionDescriptor upcallDesc = FunctionDescriptor.ofVoid(layout);
        // use actual type as return type to test downcall return normalization
        FunctionDescriptor downcallDesc = FunctionDescriptor.of(layout, ADDRESS, JAVA_INT);

        MemorySegment target = findNativeOrThrow("test");
        MethodHandle downcallHandle = LINKER.downcallHandle(target, downcallDesc);
        downcallHandle = MethodHandles.filterReturnValue(downcallHandle, toInt);

        try (Arena arena = Arena.openConfined()) {
            int[] box = new int[1];
            saver = MethodHandles.insertArguments(saver, 1, box);
            MemorySegment upcallStub = LINKER.upcallStub(saver, upcallDesc, arena.scope());
            int dirtyValue = testValue | hobMask; // set all bits that should not be set

            // test after JIT as well
            for (int i = 0; i < 20_000; i++) {
                doCall(downcallHandle, upcallStub, box, dirtyValue, hobMask);
            }
        }
    }

    private static void doCall(MethodHandle downcallHandle, MemorySegment upcallStub,
                               int[] box, int dirtyValue, int hobMask) throws Throwable {
        int result = (int) downcallHandle.invokeExact(upcallStub, dirtyValue);
        assertEquals(box[0] & hobMask, 0); // check normalized upcall arg
        assertEquals(result & hobMask, 0); // check normalized downcall return value
    }

    public static void saveBooleanAsInt(boolean b, int[] box) {
        box[0] = booleanToInt(b);
    }
    public static void saveByteAsInt(byte b, int[] box) {
        box[0] = byteToInt(b);
    }
    public static void saveShortAsInt(short s, int[] box) {
        box[0] = shortToInt(s);
    }
    public static void saveCharAsInt(char c, int[] box) {
        box[0] = charToInt(c);
    }

    public static int booleanToInt(boolean b) {
        try {
            return (int) NATIVE_BOOLEAN_TO_INT.invokeExact(b); // FIXME do in pure Java?
        } catch (Throwable e) {
            throw new RuntimeException(e);
        }
    }
    public static int byteToInt(byte b) {
        return b;
    }
    public static int charToInt(char c) {
        return c;
    }
    public static int shortToInt(short s) {
        return s;
    }

    @DataProvider
    public static Object[][] cases() {
        return new Object[][] {
            { JAVA_BOOLEAN, booleanToInt(true),     BOOLEAN_HOB_MASK, BOOLEAN_TO_INT, SAVE_BOOLEAN_AS_INT },
            { JAVA_BYTE,    byteToInt((byte) 42),   BYTE_HOB_MASK,    BYTE_TO_INT,    SAVE_BYTE_AS_INT    },
            { JAVA_SHORT,   shortToInt((short) 42), SHORT_HOB_MASK,   SHORT_TO_INT,   SAVE_SHORT_AS_INT   },
            { JAVA_CHAR,    charToInt('a'),         CHAR_HOB_MASK,    CHAR_TO_INT,    SAVE_CHAR_AS_INT    }
        };
    }

    // test which int values are considered true and false
    // we currently convert any int with a non-zero first byte to true, otherwise false.
    @Test(dataProvider = "bools")
    public void testBool(int testValue, boolean expected) throws Throwable {
        MemorySegment addr = findNativeOrThrow("test");
        MethodHandle target = LINKER.downcallHandle(addr, FunctionDescriptor.of(JAVA_BOOLEAN, ADDRESS, JAVA_INT));

        boolean[] box = new boolean[1];
        MethodHandle upcallTarget = MethodHandles.insertArguments(SAVE_BOOLEAN, 1, box);

        try (Arena arena = Arena.openConfined()) {
            MemorySegment callback = LINKER.upcallStub(upcallTarget, FunctionDescriptor.ofVoid(JAVA_BOOLEAN), arena.scope());
            boolean result = (boolean) target.invokeExact(callback, testValue);
            assertEquals(box[0], expected);
            assertEquals(result, expected);
        }
    }

    private static void saveBoolean(boolean b, boolean[] box) {
        box[0] = b;
    }

    @DataProvider
    public static Object[][] bools() {
        return new Object[][]{
            { 0b10,          true  }, // zero least significant bit, but non-zero first byte
            { 0b1_0000_0000, false }  // zero first byte
        };
    }
}

97%


¤ Dauer der Verarbeitung: 0.34 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung ist noch experimentell.