# HG changeset patch # User Doug Simon # Date 1391708654 -3600 # Node ID 4731c1a0b1f3cb7162596105ccea55bfcb0a6c6d # Parent 4fa77c58ad8f37689db77091245735f5bf500482 consolidated GNFI code into graal.hotspot project and cleaned up the documentation and code diff -r 4fa77c58ad8f -r 4731c1a0b1f3 graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/NativeFunctionHandle.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/NativeFunctionHandle.java Thu Feb 06 18:42:45 2014 +0100 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/NativeFunctionHandle.java Thu Feb 06 18:44:14 2014 +0100 @@ -23,28 +23,25 @@ package com.oracle.graal.api.code; /** - * The handle of a native foreign function. Use a {@code NativeFunctionHandle} to invoke native - * target functions. - *

- * The user of a {@code NativeFunctionHandle} has to pack the boxed arguments into an - * {@code Object[]} according to the ABI of the target platform (e.g. Unix AMD64 system: - * {@link "http://www.uclibc.org/docs/psABI-x86_64.pdf"}). The {@code NativeFunctionHandle} unboxes - * the arguments and places them into the right location (register / stack) according to the ABI. - *

- * A {@code NativeFunctionHandle} returns the boxed return value of the native target function. The - * boxed value is the return value as specified by the ABI. + * A handle that can be used to {@linkplain #call(Object[]) call} a native function. */ public interface NativeFunctionHandle { /** - * Calls the native foreign function. + * Calls the native function. + *

+ * The caller is responsible for ensuring {@code args} comply with the platform ABI (e.g. Unix AMD64 ABI). If the library + * function has struct parameters, the fields of the struct must be passed as individual + * arguments. * - * @param args the arguments that will be passed to the native foreign function + * @param args the arguments that will be passed to the native function + * @return boxed return value of the function call */ - Object call(Object[] args); + Object call(Object... args); /** - * Returns the installed code of the call stub for the native foreign function call. + * Returns the installed code of the call stub for the native function call. * * @return the installed code of the native call stub */ diff -r 4fa77c58ad8f -r 4731c1a0b1f3 graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/NativeFunctionInterface.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/NativeFunctionInterface.java Thu Feb 06 18:42:45 2014 +0100 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/NativeFunctionInterface.java Thu Feb 06 18:44:14 2014 +0100 @@ -23,91 +23,91 @@ package com.oracle.graal.api.code; /** - * Interface to resolve a {@code NativeFunctionHandle} or a {@code NativeFunctionPointer} to a - * native foreign function and a {@code NativeLibraryHandle} of a library. A - * {@code NativeFunctionPointer} wraps the raw function pointer. A {@code NativeFunctionHandle} is a - * callable representation of a native target function in Java. - *

- * To resolve a {@code NativeFunctionHandle}, one has to provide the signature of the native target - * function according to the calling convention of the target platform (e.g. Unix AMD64: - * {@link "http://www.uclibc.org/docs/psABI-x86_64.pdf"}). The signature contains the type (e.g. - * {@code int.class} for a C integer, ( {@code long.class} for a 64bit pointer) of each value, which - * is passed to the native target function. + * Interface to get a {@linkplain NativeFunctionHandle handle} or {@linkplain NativeFunctionPointer + * pointer} to a native function or a {@linkplain NativeLibraryHandle handle} to an open native + * library. */ public interface NativeFunctionInterface { /** - * Resolves and returns a library handle. + * Resolves and returns a handle to an open native library. This method will open the library + * only if it is not already open. * * @param libPath the absolute path to the library * @return the resolved library handle + * @throws UnsatisfiedLinkError if the library could not be found or opened */ NativeLibraryHandle getLibraryHandle(String libPath); /** - * Resolves the {@code NativeFunctionHandle} of a native function that can be called. Use a - * {@code NativeFunctionHandle} to invoke the native target function. + * Resolves the function pointer {@code NativeFunctionPointer} of a native function. * - * @param libraryHandle the handle to a resolved library - * @param functionName the name of the function to be resolved + * @param libraries the ordered list of libraries to search for the function + * @param name the name of the function to be resolved + * @return a pointer to the native function + * @throws UnsatisfiedLinkError if the function could not be resolved + */ + NativeFunctionPointer getFunctionPointer(NativeLibraryHandle[] libraries, String name); + + /** + * Resolves a function name to a {@linkplain NativeFunctionHandle handle} that can be called + * with a given signature. The signature contains the types of the arguments that will be passed + * to the handle when it is {@linkplain NativeFunctionHandle#call(Object...) called}. + * + * @param library the handle to a resolved library + * @param name the name of the function to be resolved * @param returnType the type of the return value * @param argumentTypes the types of the arguments - * @return the function handle of the native foreign function + * @return the function handle of the native function + * @throws UnsatisfiedLinkError if the function handle could not be resolved */ - NativeFunctionHandle getFunctionHandle(NativeLibraryHandle libraryHandle, String functionName, Class returnType, Class[] argumentTypes); - - /** - * Resolves the {@code NativeFunctionHandle} of a native function that can be called. Use a - * {@code NativeFunctionHandle} to invoke the native target function. - * - * @param functionPointer the function pointer - * @param returnType the type of the return value - * @param argumentTypes the types of the arguments - * @return the function handle of the native foreign function - */ - NativeFunctionHandle getFunctionHandle(NativeFunctionPointer functionPointer, Class returnType, Class[] argumentTypes); + NativeFunctionHandle getFunctionHandle(NativeLibraryHandle library, String name, Class returnType, Class... argumentTypes); /** - * Resolves the function pointer {@code NativeFunctionPointer} of a native function. A - * {@code NativeFunctionPointer} wraps the raw pointer value. + * Resolves a function pointer to a {@linkplain NativeFunctionHandle handle} that can be called + * with a given signature. The signature contains the types of the arguments that will be passed + * to the handle when it is {@linkplain NativeFunctionHandle#call(Object...) called}. * - * @param libraryHandles the handles to a various resolved library, the first library containing - * the method wins - * @param functionName the name of the function to be resolved - * @return the function handle of the native foreign function + * @param functionPointer a function pointer + * @param returnType the type of the return value + * @param argumentTypes the types of the arguments + * @return the function handle of the native function + * @throws UnsatisfiedLinkError if the function handle could not be created */ - NativeFunctionPointer getFunctionPointer(NativeLibraryHandle[] libraryHandles, String functionName); + NativeFunctionHandle getFunctionHandle(NativeFunctionPointer functionPointer, Class returnType, Class... argumentTypes); /** - * Resolves the {@code NativeFunctionHandle} of a native function that can be called. Use a - * {@code NativeFunctionHandle} to invoke the native target function. + * Resolves a function name to a {@linkplain NativeFunctionHandle handle} that can be called + * with a given signature. The signature contains the types of the arguments that will be passed + * to the handle when it is {@linkplain NativeFunctionHandle#call(Object...) called}. * - * @param libraryHandles the handles to a various resolved library, the first library containing - * the method wins - * @param functionName the name of the function to be resolved + * @param libraries the ordered list of libraries to search for the function + * @param name the name of the function to be resolved * @param returnType the type of the return value * @param argumentTypes the types of the arguments - * @return the function handle of the native foreign function + * @return the function handle of the native function + * @throws UnsatisfiedLinkError if the function handle could not be created */ - NativeFunctionHandle getFunctionHandle(NativeLibraryHandle[] libraryHandles, String functionName, Class returnType, Class[] argumentTypes); + NativeFunctionHandle getFunctionHandle(NativeLibraryHandle[] libraries, String name, Class returnType, Class... argumentTypes); /** - * Resolves the {@code NativeFunctionHandle} of a native function that can be called. Use a - * {@code NativeFunctionHandle} to invoke the native target function. + * Resolves a function name to a {@linkplain NativeFunctionHandle handle} that can be called + * with a given signature. The signature contains the types of the arguments that will be passed + * to the handle when it is {@linkplain NativeFunctionHandle#call(Object...) called}. * - * @param functionName the name of the function to be resolved + * @param name the name of the function to be resolved * @param returnType the type of the return value * @param argumentTypes the types of the arguments - * @return the function handle of the native foreign function + * @return the function handle of the native function + * @throws UnsatisfiedLinkError if the function could not be resolved */ - NativeFunctionHandle getFunctionHandle(String functionName, Class returnType, Class[] argumentTypes); + NativeFunctionHandle getFunctionHandle(String name, Class returnType, Class... argumentTypes); /** - * Creates {@code NativeFunctionPointer} from raw value. A {@code NativeFunctionPointer} wraps - * the raw pointer value. + * Creates a {@link NativeFunctionPointer} from a raw value. * - * @param rawValue Raw pointer value - * @return {@code NativeFunctionPointer} of the raw pointer + * @param rawValue raw function pointer + * @return {@code NativeFunctionPointer} for {@code rawValue} */ NativeFunctionPointer getNativeFunctionPointerFromRawValue(long rawValue); } diff -r 4fa77c58ad8f -r 4731c1a0b1f3 graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/NativeFunctionPointer.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/NativeFunctionPointer.java Thu Feb 06 18:42:45 2014 +0100 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/NativeFunctionPointer.java Thu Feb 06 18:44:14 2014 +0100 @@ -23,32 +23,19 @@ package com.oracle.graal.api.code; /** - * Wraps the raw function pointer value. + * An opaque representation of a native function pointer. *

- * Use the {@code NativeFunctionInterface} to resolve a {@code NativeFunctionHandle} of this pointer - * to invoke the native target function. + * Use {@code NativeFunctionInterface#getFunctionHandle(NativeFunctionPointer, Class, Class...)} to + * get a handle enabling the native function to be {@linkplain NativeFunctionHandle#call(Object...) + * called}. */ public interface NativeFunctionPointer { /** - * Returns whether the pointer is valid. - * - * @return true if the pointer is valid - */ - boolean isValid(); - - /** - * Returns function pointer as raw value. - * - * @return raw value of function pointer - */ - long asRawValue(); - - /** * Returns the name of the function. * * @return name of the function */ - String getFunctionName(); + String getName(); } diff -r 4fa77c58ad8f -r 4731c1a0b1f3 graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/NativeLibraryHandle.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/NativeLibraryHandle.java Thu Feb 06 18:42:45 2014 +0100 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/NativeLibraryHandle.java Thu Feb 06 18:44:14 2014 +0100 @@ -23,24 +23,10 @@ package com.oracle.graal.api.code; /** - * The library handle of the native library. - *

- * The {@code NativeFunctionInterface} can use a {@code NativeLibraryHandle} to look up a - * {@code NativeFunctionPointer} or a {@code NativeFunctionHandle} in this library. + * An opaque representation of a native library handle. A handle is obtained via + * {@link NativeFunctionInterface#getLibraryHandle(String)}. A handle is used to resolve a string to + * a {@linkplain NativeFunctionInterface#getFunctionHandle(String, Class, Class...) handle} or + * {@linkplain NativeFunctionInterface#getFunctionPointer(NativeLibraryHandle[], String) pointer}. */ public interface NativeLibraryHandle { - - /** - * Returns whether the handle is valid. - * - * @return true if the handle is valid - */ - boolean isValid(); - - /** - * Returns function pointer as raw value. - * - * @return raw value of function pointer - */ - long asRawValue(); } diff -r 4fa77c58ad8f -r 4731c1a0b1f3 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/nfi/NativeFunctionInterfaceTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/nfi/NativeFunctionInterfaceTest.java Thu Feb 06 18:44:14 2014 +0100 @@ -0,0 +1,212 @@ +/* + * Copyright (c) 2013, 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. + */ +package com.oracle.graal.compiler.test.nfi; + +import static com.oracle.graal.graph.UnsafeAccess.*; +import static org.junit.Assert.*; + +import java.util.*; + +import org.junit.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.runtime.*; +import com.oracle.graal.compiler.target.*; +import com.oracle.graal.runtime.*; + +public class NativeFunctionInterfaceTest { + + public final RuntimeProvider runtimeProvider; + public final NativeFunctionInterface ffi; + + public NativeFunctionInterfaceTest() { + this.runtimeProvider = Graal.getRequiredCapability(RuntimeProvider.class); + Assume.assumeTrue(runtimeProvider.getHostBackend() instanceof HostBackend); + ffi = ((HostBackend) runtimeProvider.getHostBackend()).getNativeFunctionInterface(); + } + + private List allocations = new ArrayList<>(); + + protected long malloc(int length) { + long buf = unsafe.allocateMemory(length); + allocations.add(buf); + return buf; + } + + @After + public void cleanup() { + for (long buf : allocations) { + unsafe.freeMemory(buf); + } + } + + private static void assertCStringEquals(long cString, String s) { + for (int i = 0; i < s.length(); i++) { + assertEquals(unsafe.getByte(cString + i) & 0xFF, (byte) s.charAt(i)); + } + assertEquals(unsafe.getByte(cString + s.length()) & 0xFF, (byte) '\0'); + } + + @Test + public void test1() { + + NativeFunctionHandle malloc = ffi.getFunctionHandle("malloc", long.class, int.class); + NativeFunctionHandle snprintf = ffi.getFunctionHandle("snprintf", int.class, long.class, int.class, long.class); + NativeFunctionHandle free = ffi.getFunctionHandle("free", void.class, long.class); + + String string = "GRAAL"; + int bufferLength = string.length() + 1; + long cString = (long) malloc.call(bufferLength); + writeCString(string, cString); + + long cStringCopy = malloc(bufferLength); + int result = (int) snprintf.call(cStringCopy, bufferLength, cString); + Assert.assertEquals(string.length(), result); + assertCStringEquals(cString, string); + assertCStringEquals(cStringCopy, string); + + free.call(cString); + } + + @Test + public void test2() { + String formatString = "AB %f%f"; + long formatCString = writeCString("AB %f%f", malloc(formatString.length() + 1)); + + String referenceString = "AB 1.0000001.000000"; + int bufferLength = referenceString.length() + 1; + long buffer = malloc(bufferLength); + + NativeFunctionHandle snprintf = ffi.getFunctionHandle("snprintf", int.class, long.class, int.class, long.class, double.class, double.class); + int result = (int) snprintf.call(buffer, bufferLength, formatCString, 1.0D, 1.0D); + + assertCStringEquals(buffer, referenceString); + Assert.assertEquals(referenceString.length(), result); + } + + @Test + public void test3() { + String format = "%i%i%i%i%i%i%i%i%i%i%i%i"; + long formatCString = writeCString(format, malloc(format.length() + 1)); + String referenceString = "01234567891011"; + + int bufferLength = referenceString.length() + 1; + long buffer = malloc(bufferLength); + + NativeFunctionHandle snprintf = ffi.getFunctionHandle("snprintf", int.class, long.class, int.class, long.class, int.class, int.class, int.class, int.class, int.class, int.class, int.class, + int.class, int.class, int.class, int.class, int.class); + + int result = (int) snprintf.call(buffer, bufferLength, formatCString, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11); + assertCStringEquals(buffer, referenceString); + Assert.assertEquals(referenceString.length(), result); + } + + @Test + public void test4() { + long str = malloc(49); + int[] val = new int[12]; + for (int i = 0; i < 12; i++) { + unsafe.putByte(str + 2 * i, (byte) '%'); + unsafe.putByte(str + 2 * i + 1, (byte) 'i'); + val[i] = i; + } + double[] dval = new double[12]; + for (int i = 12; i < 24; i++) { + unsafe.putByte(str + 2 * i, (byte) '%'); + unsafe.putByte(str + 2 * i + 1, (byte) 'f'); + dval[i - 12] = i + 0.5; + } + unsafe.putByte(str + 48, (byte) '\0'); + + String referenceString = "0123456789101112.50000013.50000014.50000015.50000016.50000017.50000018.50000019.50000020.500000" + "21.50000022.50000023.500000"; + int bufferLength = referenceString.length() + 1; + + long buffer = malloc(bufferLength); + + NativeFunctionHandle snprintf = ffi.getFunctionHandle("snprintf", int.class, long.class, int.class, long.class, int.class, int.class, int.class, int.class, int.class, int.class, int.class, + int.class, int.class, int.class, int.class, int.class, double.class, double.class, double.class, double.class, double.class, double.class, double.class, double.class, + double.class, double.class, double.class, double.class); + + int result = (int) snprintf.call(buffer, bufferLength, str, val[0], val[1], val[2], val[3], val[4], val[5], val[6], val[7], val[8], val[9], val[10], val[11], dval[0], dval[1], dval[2], + dval[3], dval[4], dval[5], dval[6], dval[7], dval[8], dval[9], dval[10], dval[11]); + assertCStringEquals(buffer, referenceString); + Assert.assertEquals(referenceString.length(), result); + } + + @Test + public void test5() { + long str = malloc(73); + int[] val = new int[12]; + for (int i = 0; i < 12; i++) { + unsafe.putByte(str + 2 * i, (byte) '%'); + unsafe.putByte(str + 2 * i + 1, (byte) 'i'); + val[i] = i; + } + double[] dval = new double[12]; + for (int i = 12; i < 24; i++) { + unsafe.putByte(str + 2 * i, (byte) '%'); + unsafe.putByte(str + 2 * i + 1, (byte) 'f'); + dval[i - 12] = i + 0.5; + } + char[] cval = new char[12]; + for (int i = 24; i < 36; i++) { + unsafe.putByte(str + 2 * i, (byte) '%'); + unsafe.putByte(str + 2 * i + 1, (byte) 'c'); + cval[i - 24] = (char) ('a' + (i - 24)); + } + unsafe.putByte(str + 72, (byte) '\0'); + + String referenceString = "0123456789101112.50000013.50000014.50000015.50000016.50000017.50000018.50000019.50000020.50000021.50000022.50000023.500000abcdefghijkl"; + int bufferLength = referenceString.length() + 1; + + long buffer = malloc(bufferLength); + + NativeFunctionHandle snprintf = ffi.getFunctionHandle("snprintf", int.class, long.class, int.class, long.class, int.class, int.class, int.class, int.class, int.class, int.class, int.class, + int.class, int.class, int.class, int.class, int.class, double.class, double.class, double.class, double.class, double.class, double.class, double.class, double.class, + double.class, double.class, double.class, double.class, char.class, char.class, char.class, char.class, char.class, char.class, char.class, char.class, char.class, char.class, + char.class, char.class); + + int result = (int) snprintf.call(buffer, bufferLength, str, val[0], val[1], val[2], val[3], val[4], val[5], val[6], val[7], val[8], val[9], val[10], val[11], dval[0], dval[1], dval[2], + dval[3], dval[4], dval[5], dval[6], dval[7], dval[8], dval[9], dval[10], dval[11], cval[0], cval[1], cval[2], cval[3], cval[4], cval[5], cval[6], cval[7], cval[8], cval[9], + cval[10], cval[11]); + assertCStringEquals(buffer, referenceString); + Assert.assertEquals(referenceString.length(), result); + } + + @Test + public void test6() { + NativeFunctionHandle handle = ffi.getFunctionHandle("pow", double.class, double.class, double.class); + double result = (double) handle.call(3D, 5.5D); + assertEquals(Math.pow(3D, 5.5D), result, 0); + } + + @Test + public void test7() { + double result = 0; + NativeFunctionHandle handle = ffi.getFunctionHandle("pow", double.class, double.class, double.class); + for (int i = 0; i < 100000; i++) { + result = (double) handle.call(3D, 5.5D); + } + assertEquals(Math.pow(3D, 5.5D), result, 0); + } +} diff -r 4fa77c58ad8f -r 4731c1a0b1f3 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java Thu Feb 06 18:42:45 2014 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java Thu Feb 06 18:44:14 2014 +0100 @@ -40,15 +40,14 @@ import com.oracle.graal.asm.amd64.AMD64Assembler.ConditionFlag; import com.oracle.graal.compiler.gen.*; import com.oracle.graal.compiler.target.*; -import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.bridge.*; import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.hotspot.nfi.*; import com.oracle.graal.hotspot.stubs.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.amd64.*; import com.oracle.graal.lir.asm.*; -import com.oracle.graal.nfi.hotspot.amd64.*; import com.oracle.graal.nodes.*; /** @@ -311,12 +310,12 @@ @Override public NativeFunctionInterface getNativeFunctionInterface() { - AMD64HotSpotNativeFunctionPointer libraryLoadPointer = new AMD64HotSpotNativeFunctionPointer(getRuntime().getConfig().libraryLoadAddress, "GNFI_UTIL_LOADLIBRARY"); - AMD64HotSpotNativeFunctionPointer functionLookupPointer = new AMD64HotSpotNativeFunctionPointer(getRuntime().getConfig().functionLookupAddress, "GNFI_UTIL_FUNCTIONLOOKUP"); - AMD64HotSpotNativeLibraryHandle rtldDefault = new AMD64HotSpotNativeLibraryHandle(getRuntime().getConfig().rtldDefault); - if (!libraryLoadPointer.isValid() || !functionLookupPointer.isValid()) { - throw GraalInternalError.shouldNotReachHere("Lookup Pointers null"); - } - return new AMD64HotSpotNativeFunctionInterface(this.getProviders(), this, libraryLoadPointer, functionLookupPointer, rtldDefault); + HotSpotVMConfig config = getRuntime().getConfig(); + RawNativeCallNodeFactory factory = new RawNativeCallNodeFactory() { + public FixedWithNextNode createRawCallNode(Kind returnType, Constant functionPointer, ValueNode... args) { + return new AMD64RawNativeCallNode(returnType, functionPointer, args); + } + }; + return new HotSpotNativeFunctionInterface(getProviders(), factory, this, config.dllLoad, config.dllLookup, config.rtldDefault); } } diff -r 4fa77c58ad8f -r 4731c1a0b1f3 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64RawNativeCallNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64RawNativeCallNode.java Thu Feb 06 18:44:14 2014 +0100 @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2014, 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. + */ +package com.oracle.graal.hotspot.amd64; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.code.CallingConvention.Type; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.amd64.*; +import com.oracle.graal.compiler.gen.*; +import com.oracle.graal.compiler.target.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.type.*; + +public class AMD64RawNativeCallNode extends FixedWithNextNode implements LIRGenLowerable { + + private final Constant functionPointer; + @Input private final NodeInputList args; + + public AMD64RawNativeCallNode(Kind returnType, Constant functionPointer, ValueNode[] args) { + super(StampFactory.forKind(returnType)); + this.functionPointer = functionPointer; + this.args = new NodeInputList<>(this, args); + } + + @Override + public void generate(LIRGenerator generator) { + AMD64LIRGenerator gen = (AMD64LIRGenerator) generator; + Value[] parameter = new Value[args.count()]; + JavaType[] parameterTypes = new JavaType[args.count()]; + for (int i = 0; i < args.count(); i++) { + parameter[i] = generator.operand(args.get(i)); + parameterTypes[i] = args.get(i).stamp().javaType(gen.getMetaAccess()); + } + ResolvedJavaType returnType = stamp().javaType(gen.getMetaAccess()); + CallingConvention cc = generator.getCodeCache().getRegisterConfig().getCallingConvention(Type.NativeCall, returnType, parameterTypes, generator.target(), false); + gen.emitCCall(functionPointer.asLong(), cc, parameter, countFloatingTypeArguments(args)); + if (this.kind() != Kind.Void) { + generator.setResult(this, gen.emitMove(cc.getReturn())); + } + } + + private static int countFloatingTypeArguments(NodeInputList args) { + int count = 0; + for (ValueNode n : args) { + if (n.kind() == Kind.Double || n.kind() == Kind.Float) { + count++; + } + } + if (count > 8) { + return 8; + } + return count; + } + +} diff -r 4fa77c58ad8f -r 4731c1a0b1f3 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Thu Feb 06 18:42:45 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Thu Feb 06 18:44:14 2014 +0100 @@ -840,14 +840,35 @@ @HotSpotVMField(name = "JavaThread::_vm_result", type = "oop", get = HotSpotVMField.Type.OFFSET) @Stable public int threadObjectResultOffset; @HotSpotVMField(name = "JavaThread::_graal_counters[0]", type = "jlong", get = HotSpotVMField.Type.OFFSET, optional = true) @Stable public int graalCountersThreadOffset; - // The native side (graalCompilerToVM.cpp) sets the rtldDefault if the - // platform is NOT Windows (Windows is currently not supported). - // AMD64NativeFunctionInterface checks if rtld_default handle is valid. - // Using 0 is not possible as it is a valid value for rtldDefault on some platforms. + /** + * An invalid value for {@link #rtldDefault}. + */ public static final long INVALID_RTLD_DEFAULT_HANDLE = 0xDEADFACE; - @Stable public long libraryLoadAddress; - @Stable public long functionLookupAddress; + /** + * Address of the library lookup routine. The C signature of this routine is: + * + *

+     *     void* (const char *filename, char *ebuf, int ebuflen)
+     * 
+ */ + @Stable public long dllLoad; + + /** + * Address of the library lookup routine. The C signature of this routine is: + * + *
+     *     void* (void* handle, const char* name)
+     * 
+ */ + @Stable public long dllLookup; + + /** + * A pseudo-handle which when used as the first argument to {@link #dllLookup} means + * lookup will return the first occurrence of the desired symbol using the default library + * search order. If this field is {@value #INVALID_RTLD_DEFAULT_HANDLE}, then this capability is + * not supported on the current platform. + */ @Stable public long rtldDefault = INVALID_RTLD_DEFAULT_HANDLE; /** diff -r 4fa77c58ad8f -r 4731c1a0b1f3 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/HotSpotNativeFunctionHandle.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/HotSpotNativeFunctionHandle.java Thu Feb 06 18:44:14 2014 +0100 @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2014, 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. + */ +package com.oracle.graal.hotspot.nfi; + +import java.util.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.debug.*; +import com.oracle.graal.debug.Debug.Scope; +import com.oracle.graal.graph.*; + +public class HotSpotNativeFunctionHandle implements NativeFunctionHandle { + + private final InstalledCode code; + private final String name; + private final Class[] argumentTypes; + + public HotSpotNativeFunctionHandle(InstalledCode code, String name, Class... argumentTypes) { + this.argumentTypes = argumentTypes; + this.name = name; + this.code = code; + } + + private void traceCall(Object... args) { + try (Scope s = Debug.scope("GNFI")) { + if (Debug.isLogEnabled()) { + Debug.log("[GNFI] %s%s", name, Arrays.toString(args)); + } + } + } + + private void traceResult(Object result) { + try (Scope s = Debug.scope("GNFI")) { + if (Debug.isLogEnabled()) { + Debug.log("[GNFI] %s --> %s", name, result); + } + } + } + + @Override + public Object call(Object... args) { + assert checkArgs(args); + try { + traceCall(args); + Object res = code.execute(args, null, null); + traceResult(res); + return res; + } catch (InvalidInstalledCodeException e) { + throw GraalInternalError.shouldNotReachHere("Execution of GNFI Callstub failed: " + name); + } + } + + private boolean checkArgs(Object... args) { + assert args.length == argumentTypes.length : this + " expected " + argumentTypes.length + " args, got " + args.length; + for (int i = 0; i < argumentTypes.length; i++) { + Object arg = args[i]; + assert arg != null; + Class expectedType = argumentTypes[i]; + if (expectedType.isPrimitive()) { + Kind kind = Kind.fromJavaClass(expectedType); + expectedType = kind.toBoxedJavaClass(); + } + assert expectedType == arg.getClass() : this + " expected arg " + i + " to be " + expectedType.getName() + ", not " + arg.getClass().getName(); + + } + return true; + } + + public InstalledCode getCallStub() { + return code; + } + + @Override + public String toString() { + return name + Arrays.toString(argumentTypes); + } +} diff -r 4fa77c58ad8f -r 4731c1a0b1f3 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/HotSpotNativeFunctionInterface.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/HotSpotNativeFunctionInterface.java Thu Feb 06 18:44:14 2014 +0100 @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2014, 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. + */ +package com.oracle.graal.hotspot.nfi; + +import static com.oracle.graal.api.code.CodeUtil.*; +import static com.oracle.graal.graph.UnsafeAccess.*; +import static com.oracle.graal.hotspot.nfi.NativeCallStubGraphBuilder.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.code.CallingConvention.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.meta.ProfilingInfo.*; +import com.oracle.graal.compiler.*; +import com.oracle.graal.compiler.target.*; +import com.oracle.graal.debug.*; +import com.oracle.graal.debug.Debug.*; +import com.oracle.graal.hotspot.*; +import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.lir.asm.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.phases.*; +import com.oracle.graal.phases.tiers.*; + +public class HotSpotNativeFunctionInterface implements NativeFunctionInterface { + + private final HotSpotProviders providers; + private final Backend backend; + private final HotSpotNativeLibraryHandle rtldDefault; + private final HotSpotNativeFunctionPointer libraryLoadFunctionPointer; + private final HotSpotNativeFunctionPointer functionLookupFunctionPointer; + private final RawNativeCallNodeFactory factory; + + private HotSpotNativeFunctionHandle libraryLookupFunctionHandle; + private HotSpotNativeFunctionHandle dllLookupFunctionHandle; + + public HotSpotNativeFunctionInterface(HotSpotProviders providers, RawNativeCallNodeFactory factory, Backend backend, long dlopen, long dlsym, long rtldDefault) { + this.rtldDefault = rtldDefault == HotSpotVMConfig.INVALID_RTLD_DEFAULT_HANDLE ? null : new HotSpotNativeLibraryHandle("RTLD_DEFAULT", rtldDefault); + this.providers = providers; + this.backend = backend; + this.factory = factory; + this.libraryLoadFunctionPointer = new HotSpotNativeFunctionPointer(dlopen, "os::dll_load"); + this.functionLookupFunctionPointer = new HotSpotNativeFunctionPointer(dlsym, "os::dll_lookup"); + } + + @Override + public HotSpotNativeLibraryHandle getLibraryHandle(String libPath) { + if (libraryLookupFunctionHandle == null) { + libraryLookupFunctionHandle = createHandle(libraryLoadFunctionPointer, long.class, long.class, long.class, int.class); + } + + int ebufLen = 1024; + // Allocating a single chunk for both the error message buffer and the + // file name simplifies deallocation below. + long buffer = unsafe.allocateMemory(ebufLen + libPath.length() + 1); + long ebuf = buffer; + long libPathCString = writeCString(libPath, buffer + ebufLen); + try { + long handle = (long) libraryLookupFunctionHandle.call(libPathCString, ebuf, ebufLen); + if (handle == 0) { + throw new UnsatisfiedLinkError(libPath); + } + return new HotSpotNativeLibraryHandle(libPath, handle); + } finally { + unsafe.freeMemory(buffer); + } + } + + @Override + public HotSpotNativeFunctionHandle getFunctionHandle(NativeLibraryHandle library, String name, Class returnType, Class... argumentTypes) { + HotSpotNativeFunctionPointer functionPointer = lookupFunctionPointer(name, library, true); + return getFunctionHandle(functionPointer, returnType, argumentTypes); + } + + @Override + public HotSpotNativeFunctionHandle getFunctionHandle(NativeLibraryHandle[] libraries, String name, Class returnType, Class... argumentTypes) { + HotSpotNativeFunctionPointer functionPointer = null; + for (NativeLibraryHandle libraryHandle : libraries) { + functionPointer = lookupFunctionPointer(name, libraryHandle, false); + if (functionPointer != null) { + return createHandle(functionPointer, returnType, argumentTypes); + } + } + // Fall back to default library path + return getFunctionHandle(name, returnType, argumentTypes); + } + + @Override + public HotSpotNativeFunctionHandle getFunctionHandle(String name, Class returnType, Class... argumentTypes) { + if (rtldDefault == null) { + throw new UnsatisfiedLinkError(name); + } + return getFunctionHandle(rtldDefault, name, returnType, argumentTypes); + } + + private HotSpotNativeFunctionPointer lookupFunctionPointer(String name, NativeLibraryHandle library, boolean linkageErrorIfMissing) { + if (name == null || library == null) { + throw new NullPointerException(); + } + if (dllLookupFunctionHandle == null) { + dllLookupFunctionHandle = createHandle(functionLookupFunctionPointer, long.class, long.class, long.class); + } + long nameCString = createCString(name); + try { + long functionPointer = (long) dllLookupFunctionHandle.call(((HotSpotNativeLibraryHandle) library).value, nameCString); + if (functionPointer == 0L) { + if (!linkageErrorIfMissing) { + return null; + } + throw new UnsatisfiedLinkError(name); + } + return new HotSpotNativeFunctionPointer(functionPointer, name); + } finally { + unsafe.freeMemory(nameCString); + } + } + + @Override + public HotSpotNativeFunctionHandle getFunctionHandle(NativeFunctionPointer functionPointer, Class returnType, Class... argumentTypes) { + if (!(functionPointer instanceof HotSpotNativeFunctionPointer)) { + throw new UnsatisfiedLinkError(functionPointer.getName()); + } + return createHandle(functionPointer, returnType, argumentTypes); + } + + private HotSpotNativeFunctionHandle createHandle(NativeFunctionPointer functionPointer, Class returnType, Class... argumentTypes) { + HotSpotNativeFunctionPointer hs = (HotSpotNativeFunctionPointer) functionPointer; + InstalledCode code = installNativeFunctionStub(hs.value, returnType, argumentTypes); + return new HotSpotNativeFunctionHandle(code, hs.name, argumentTypes); + } + + /** + * Creates and installs a stub for calling a native function. + */ + private InstalledCode installNativeFunctionStub(long functionPointer, Class returnType, Class... argumentTypes) { + StructuredGraph g = getGraph(providers, factory, functionPointer, returnType, argumentTypes); + Suites suites = providers.getSuites().createSuites(); + PhaseSuite phaseSuite = backend.getSuites().getDefaultGraphBuilderSuite().copy(); + CallingConvention cc = getCallingConvention(providers.getCodeCache(), Type.JavaCallee, g.method(), false); + CompilationResult compResult = GraalCompiler.compileGraph(g, cc, g.method(), providers, backend, backend.getTarget(), null, phaseSuite, OptimisticOptimizations.ALL, + DefaultProfilingInfo.get(TriState.UNKNOWN), null, suites, true, new CompilationResult(), CompilationResultBuilderFactory.Default); + InstalledCode installedCode; + try (Scope s = Debug.scope("CodeInstall", providers.getCodeCache(), g.method())) { + installedCode = providers.getCodeCache().addMethod(g.method(), compResult, null); + } + return installedCode; + } + + @Override + public HotSpotNativeFunctionPointer getFunctionPointer(NativeLibraryHandle[] libraries, String name) { + for (NativeLibraryHandle libraryHandle : libraries) { + HotSpotNativeFunctionPointer functionPointer = lookupFunctionPointer(name, libraryHandle, false); + if (functionPointer != null) { + return functionPointer; + } + } + // Fall back to default library path + if (rtldDefault == null) { + throw new UnsatisfiedLinkError(name); + } + return lookupFunctionPointer(name, rtldDefault, true); + } + + @Override + public NativeFunctionPointer getNativeFunctionPointerFromRawValue(long rawValue) { + return new HotSpotNativeFunctionPointer(rawValue, null); + } +} diff -r 4fa77c58ad8f -r 4731c1a0b1f3 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/HotSpotNativeFunctionPointer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/HotSpotNativeFunctionPointer.java Thu Feb 06 18:44:14 2014 +0100 @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2014, 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. + */ +package com.oracle.graal.hotspot.nfi; + +import com.oracle.graal.api.code.*; + +public class HotSpotNativeFunctionPointer implements NativeFunctionPointer { + + final long value; + final String name; + + public HotSpotNativeFunctionPointer(long value, String name) { + if (value == 0) { + throw new UnsatisfiedLinkError(name); + } + this.value = value; + this.name = name; + } + + public String getName() { + return name; + } + + public long getValue() { + return value; + } + + @Override + public String toString() { + return name + "@0x" + Long.toHexString(value); + } +} diff -r 4fa77c58ad8f -r 4731c1a0b1f3 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/HotSpotNativeLibraryHandle.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/HotSpotNativeLibraryHandle.java Thu Feb 06 18:44:14 2014 +0100 @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2014, 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. + */ +package com.oracle.graal.hotspot.nfi; + +import com.oracle.graal.api.code.*; + +public class HotSpotNativeLibraryHandle implements NativeLibraryHandle { + + final long value; + final String name; + + public HotSpotNativeLibraryHandle(String name, long handle) { + this.name = name; + this.value = handle; + } + + @Override + public String toString() { + return name + "@" + value; + } +} diff -r 4fa77c58ad8f -r 4731c1a0b1f3 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/NativeCallStubGraphBuilder.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/NativeCallStubGraphBuilder.java Thu Feb 06 18:44:14 2014 +0100 @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2014, 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. + */ +package com.oracle.graal.hotspot.nfi; + +import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; + +import java.util.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.nodes.java.*; +import com.oracle.graal.nodes.type.*; +import com.oracle.graal.nodes.virtual.*; +import com.oracle.graal.word.phases.*; + +/** + * Utility creating a graph for a stub used to call a native function. + */ +public class NativeCallStubGraphBuilder { + + /** + * Creates a graph for a stub used to call a native function. + * + * @param functionPointer a native function pointer + * @param returnType the type of the return value + * @param argumentTypes the types of the arguments + * @return the graph that represents the call stub + */ + public static StructuredGraph getGraph(HotSpotProviders providers, RawNativeCallNodeFactory factory, long functionPointer, Class returnType, Class... argumentTypes) { + try { + ResolvedJavaMethod method = providers.getMetaAccess().lookupJavaMethod(NativeCallStubGraphBuilder.class.getMethod("libCall", Object.class, Object.class, Object.class)); + StructuredGraph g = new StructuredGraph(method); + ParameterNode arg0 = g.unique(new ParameterNode(0, StampFactory.forKind(Kind.Object))); + ParameterNode arg1 = g.unique(new ParameterNode(1, StampFactory.forKind(Kind.Object))); + ParameterNode arg2 = g.unique(new ParameterNode(2, StampFactory.forKind(Kind.Object))); + FrameState frameState = g.add(new FrameState(method, 0, Arrays.asList(new ValueNode[]{arg0, arg1, arg2}), 3, 0, false, false, new ArrayList(), + new ArrayList())); + g.start().setStateAfter(frameState); + List parameters = new ArrayList<>(); + FixedWithNextNode fixedWithNext = getParameters(g, arg0, argumentTypes.length, argumentTypes, parameters, providers); + Constant functionPointerNode = Constant.forLong(functionPointer); + + ValueNode[] arguments = new ValueNode[parameters.size()]; + + for (int i = 0; i < arguments.length; i++) { + arguments[i] = parameters.get(i); + } + + FixedWithNextNode callNode = g.add(factory.createRawCallNode(getKind(returnType), functionPointerNode, arguments)); + + if (fixedWithNext == null) { + g.start().setNext(callNode); + } else { + fixedWithNext.setNext(callNode); + } + + // box result + BoxNode boxedResult; + if (callNode.kind() != Kind.Void) { + if (callNode.kind() == Kind.Object) { + throw new IllegalArgumentException("Return type not supported: " + returnType.getName()); + } + ResolvedJavaType type = providers.getMetaAccess().lookupJavaType(callNode.kind().toBoxedJavaClass()); + boxedResult = g.unique(new BoxNode(callNode, type, callNode.kind())); + } else { + boxedResult = g.unique(new BoxNode(ConstantNode.forLong(0, g), providers.getMetaAccess().lookupJavaType(Long.class), Kind.Long)); + } + + ReturnNode returnNode = g.add(new ReturnNode(boxedResult)); + callNode.setNext(returnNode); + (new WordTypeRewriterPhase(providers.getMetaAccess(), Kind.Long)).apply(g); + return g; + } catch (NoSuchMethodException e) { + throw GraalInternalError.shouldNotReachHere("Call Stub method not found"); + } + } + + private static FixedWithNextNode getParameters(StructuredGraph g, ParameterNode argumentsArray, int numArgs, Class[] argumentTypes, List args, HotSpotProviders providers) { + assert numArgs == argumentTypes.length; + FixedWithNextNode last = null; + for (int i = 0; i < numArgs; i++) { + // load boxed array element: + LoadIndexedNode boxedElement = g.add(new LoadIndexedNode(argumentsArray, ConstantNode.forInt(i, g), Kind.Object)); + if (i == 0) { + g.start().setNext(boxedElement); + last = boxedElement; + } else { + last.setNext(boxedElement); + last = boxedElement; + } + Class type = argumentTypes[i]; + Kind kind = getKind(type); + if (kind == Kind.Object) { + // array value + Kind arrayElementKind = getElementKind(type); + LocationIdentity locationIdentity = NamedLocationIdentity.getArrayLocation(arrayElementKind); + int displacement = getArrayBaseOffset(arrayElementKind); + ConstantNode index = ConstantNode.forInt(0, g); + int indexScaling = getArrayIndexScale(arrayElementKind); + IndexedLocationNode locationNode = IndexedLocationNode.create(locationIdentity, arrayElementKind, displacement, index, g, indexScaling); + Stamp wordStamp = StampFactory.forKind(providers.getCodeCache().getTarget().wordKind); + ComputeAddressNode arrayAddress = g.unique(new ComputeAddressNode(boxedElement, locationNode, wordStamp)); + args.add(arrayAddress); + } else { + // boxed primitive value + try { + ResolvedJavaField field = providers.getMetaAccess().lookupJavaField(kind.toBoxedJavaClass().getDeclaredField("value")); + LoadFieldNode loadFieldNode = g.add(new LoadFieldNode(boxedElement, field)); + last.setNext(loadFieldNode); + last = loadFieldNode; + args.add(loadFieldNode); + } catch (NoSuchFieldException e) { + throw new GraalInternalError(e); + } + } + } + return last; + } + + public static Kind getElementKind(Class clazz) { + Class componentType = clazz.getComponentType(); + if (componentType == null) { + throw new IllegalArgumentException("Parameter type not supported: " + clazz); + } + if (componentType.isPrimitive()) { + Kind.fromJavaClass(componentType); + } + throw new IllegalArgumentException("Parameter type not supported: " + clazz); + } + + private static Kind getKind(Class clazz) { + if (clazz == int.class || clazz == Integer.class) { + return Kind.Int; + } else if (clazz == long.class || clazz == Long.class) { + return Kind.Long; + } else if (clazz == char.class || clazz == Character.class) { + return Kind.Char; + } else if (clazz == byte.class || clazz == Byte.class) { + return Kind.Byte; + } else if (clazz == float.class || clazz == Float.class) { + return Kind.Float; + } else if (clazz == double.class || clazz == Double.class) { + return Kind.Double; + } else if (clazz == int[].class || clazz == long[].class || clazz == char[].class || clazz == byte[].class || clazz == float[].class || clazz == double[].class) { + return Kind.Object; + } else if (clazz == void.class) { + return Kind.Void; + } else { + throw new IllegalArgumentException("Type not supported: " + clazz); + } + } + + @SuppressWarnings("unused") + public static Object libCall(Object argLoc, Object unused1, Object unused2) { + throw GraalInternalError.shouldNotReachHere("GNFI libCall method must not be called"); + } +} diff -r 4fa77c58ad8f -r 4731c1a0b1f3 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/RawNativeCallNodeFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/RawNativeCallNodeFactory.java Thu Feb 06 18:44:14 2014 +0100 @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2014, 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. + */ +package com.oracle.graal.hotspot.nfi; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.nodes.*; + +/** + * Factory for creating a node that makes a direct call to a native function pointer. + */ +public interface RawNativeCallNodeFactory { + FixedWithNextNode createRawCallNode(Kind returnType, Constant functionPointer, ValueNode... args); +} diff -r 4fa77c58ad8f -r 4731c1a0b1f3 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotReplacementsUtil.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotReplacementsUtil.java Thu Feb 06 18:42:45 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotReplacementsUtil.java Thu Feb 06 18:44:14 2014 +0100 @@ -718,14 +718,4 @@ throw new GraalInternalError(e); } } - - @Fold - public static long dllLoad() { - return config().libraryLoadAddress; - } - - @Fold - public static long dllLookup() { - return config().functionLookupAddress; - } } diff -r 4fa77c58ad8f -r 4731c1a0b1f3 graal/com.oracle.graal.nfi.hotspot.amd64/src/com/oracle/graal/nfi/hotspot/amd64/AMD64HotSpotNativeFunctionHandle.java --- a/graal/com.oracle.graal.nfi.hotspot.amd64/src/com/oracle/graal/nfi/hotspot/amd64/AMD64HotSpotNativeFunctionHandle.java Thu Feb 06 18:42:45 2014 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2014, 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. - */ -package com.oracle.graal.nfi.hotspot.amd64; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.compiler.target.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.hotspot.meta.*; -import com.oracle.graal.nfi.hotspot.amd64.util.*; -import com.oracle.graal.nodes.*; - -public class AMD64HotSpotNativeFunctionHandle implements NativeFunctionHandle { - - private final InstalledCode code; - private final String functionName; - - protected final HotSpotProviders providers; - protected final Backend backend; - - public AMD64HotSpotNativeFunctionHandle(HotSpotProviders providers, Backend backend, AMD64HotSpotNativeFunctionPointer functionPointer, Class returnType, Class[] argumentTypes) { - this.providers = providers; - this.backend = backend; - this.functionName = functionPointer.getFunctionName(); - StructuredGraph graph = NativeCallStubGraphBuilder.getGraph(providers, functionPointer, returnType, argumentTypes); - InstallUtil installer = new InstallUtil(providers, backend); - this.code = installer.install(graph); - } - - @Override - public Object call(Object[] args) { - try { - return code.execute(args, null, null); - } catch (InvalidInstalledCodeException e) { - throw GraalInternalError.shouldNotReachHere("Execution of GNFI Callstub failed: " + functionName); - } - } - - public InstalledCode getCallStub() { - return code; - } -} diff -r 4fa77c58ad8f -r 4731c1a0b1f3 graal/com.oracle.graal.nfi.hotspot.amd64/src/com/oracle/graal/nfi/hotspot/amd64/AMD64HotSpotNativeFunctionInterface.java --- a/graal/com.oracle.graal.nfi.hotspot.amd64/src/com/oracle/graal/nfi/hotspot/amd64/AMD64HotSpotNativeFunctionInterface.java Thu Feb 06 18:42:45 2014 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,176 +0,0 @@ -/* - * Copyright (c) 2014, 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. - */ -package com.oracle.graal.nfi.hotspot.amd64; - -import java.lang.reflect.*; - -import sun.misc.*; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.compiler.target.*; -import com.oracle.graal.hotspot.*; -import com.oracle.graal.hotspot.meta.*; - -public class AMD64HotSpotNativeFunctionInterface implements NativeFunctionInterface { - - private static final Class LOOKUP_FUNCTION_RETURNTYPE = long.class; - private static final Class[] LOOKUP_FUNCTION_SIGNATURE = new Class[]{long.class, long.class}; - - private static final Unsafe unsafe = getUnsafe(); - - private static final int STD_BUFFER_SIZE = 1024; - - protected final HotSpotProviders providers; - protected final Backend backend; - protected final AMD64HotSpotNativeLibraryHandle rtldDefault; - protected final AMD64HotSpotNativeFunctionPointer libraryLoadFunctionPointer; - protected final AMD64HotSpotNativeFunctionPointer functionLookupFunctionPointer; - - private AMD64HotSpotNativeFunctionHandle libraryLookupFunctionHandle; - private AMD64HotSpotNativeFunctionHandle dllLookupFunctionHandle; - - public AMD64HotSpotNativeFunctionInterface(HotSpotProviders providers, Backend backend, AMD64HotSpotNativeFunctionPointer libraryLoadFunctionPointer, - AMD64HotSpotNativeFunctionPointer functionLookUpFunctionPointer, AMD64HotSpotNativeLibraryHandle rtldDefault) { - this.rtldDefault = rtldDefault; - this.providers = providers; - this.backend = backend; - this.libraryLoadFunctionPointer = libraryLoadFunctionPointer; - this.functionLookupFunctionPointer = functionLookUpFunctionPointer; - } - - @Override - public AMD64HotSpotNativeLibraryHandle getLibraryHandle(String libPath) { - if (libraryLookupFunctionHandle == null) { - libraryLookupFunctionHandle = new AMD64HotSpotNativeFunctionHandle(providers, backend, libraryLoadFunctionPointer, long.class, new Class[]{long.class, long.class, int.class}); - } - - long allocatedMemory = -1; - try { - allocatedMemory = unsafe.allocateMemory(STD_BUFFER_SIZE); - } catch (OutOfMemoryError e) { - throw new AssertionError(); - } - - Object[] args = new Object[]{copyStringToMemory(libPath), allocatedMemory, STD_BUFFER_SIZE}; - long libraryHandle = (long) libraryLookupFunctionHandle.call(args); - unsafe.freeMemory(allocatedMemory); - return new AMD64HotSpotNativeLibraryHandle(libraryHandle); - } - - @Override - public AMD64HotSpotNativeFunctionHandle getFunctionHandle(NativeLibraryHandle libraryHandle, String functionName, Class returnType, Class[] argumentTypes) { - AMD64HotSpotNativeFunctionPointer functionPointer = lookupFunctionPointer(functionName, libraryHandle); - if (!functionPointer.isValid()) { - throw new IllegalStateException(functionName + " not found!"); - } - return getFunctionHandle(functionPointer, returnType, argumentTypes); - } - - @Override - public AMD64HotSpotNativeFunctionHandle getFunctionHandle(NativeLibraryHandle[] libraryHandles, String functionName, Class returnType, Class[] argumentTypes) { - AMD64HotSpotNativeFunctionPointer functionPointer = null; - for (NativeLibraryHandle libraryHandle : libraryHandles) { - functionPointer = lookupFunctionPointer(functionName, libraryHandle); - if (functionPointer.isValid()) { - return new AMD64HotSpotNativeFunctionHandle(providers, backend, functionPointer, returnType, argumentTypes); - } - } - return getFunctionHandle(functionName, returnType, argumentTypes); - } - - @Override - public AMD64HotSpotNativeFunctionHandle getFunctionHandle(String functionName, Class returnType, Class[] argumentTypes) { - if (rtldDefault.asRawValue() == HotSpotVMConfig.INVALID_RTLD_DEFAULT_HANDLE) { - throw new AssertionError("No library provided or RTLD_DEFAULT not supported!"); - } - return getFunctionHandle(rtldDefault, functionName, returnType, argumentTypes); - } - - private AMD64HotSpotNativeFunctionPointer lookupFunctionPointer(String functionName, NativeLibraryHandle handle) { - - if (!functionLookupFunctionPointer.isValid()) { - throw new IllegalStateException("no dlsym function pointer"); - } - if (dllLookupFunctionHandle == null) { - dllLookupFunctionHandle = new AMD64HotSpotNativeFunctionHandle(providers, backend, functionLookupFunctionPointer, LOOKUP_FUNCTION_RETURNTYPE, LOOKUP_FUNCTION_SIGNATURE); - } - long allocatedMemory = copyStringToMemory(functionName); - Object[] args = new Object[]{handle, allocatedMemory}; - long functionPointer = (long) dllLookupFunctionHandle.call(args); - unsafe.freeMemory(allocatedMemory); - return new AMD64HotSpotNativeFunctionPointer(functionPointer, functionName); - } - - private static long copyStringToMemory(String str) { - int size = str.length(); - long ptr = unsafe.allocateMemory(size + 1); - for (int i = 0; i < size; i++) { - unsafe.putByte(ptr + i, (byte) str.charAt(i)); - } - unsafe.putByte(ptr + size, (byte) '\0'); - return ptr; - } - - private static Unsafe getUnsafe() { - try { - return Unsafe.getUnsafe(); - } catch (SecurityException e) { - } - try { - Field theUnsafeInstance = Unsafe.class.getDeclaredField("theUnsafe"); - theUnsafeInstance.setAccessible(true); - return (Unsafe) theUnsafeInstance.get(Unsafe.class); - } catch (IllegalArgumentException | SecurityException | NoSuchFieldException | IllegalAccessException e) { - throw new RuntimeException("exception while trying to get Unsafe.theUnsafe via reflection:", e); - } - } - - @Override - public AMD64HotSpotNativeFunctionHandle getFunctionHandle(NativeFunctionPointer functionPointer, Class returnType, Class[] argumentTypes) { - if (functionPointer instanceof AMD64HotSpotNativeFunctionPointer) { - if (!((AMD64HotSpotNativeFunctionPointer) functionPointer).isValid()) { - throw new IllegalStateException("Function Symbol not found"); - } - } else { - throw new IllegalStateException("AMD64 function pointer required!"); - } - return new AMD64HotSpotNativeFunctionHandle(providers, backend, (AMD64HotSpotNativeFunctionPointer) functionPointer, returnType, argumentTypes); - } - - @Override - public AMD64HotSpotNativeFunctionPointer getFunctionPointer(NativeLibraryHandle[] libraryHandles, String functionName) { - for (NativeLibraryHandle libraryHandle : libraryHandles) { - AMD64HotSpotNativeFunctionPointer functionPointer = lookupFunctionPointer(functionName, libraryHandle); - if (functionPointer.isValid()) { - return functionPointer; - } - } - throw new LinkageError("Function not found: " + functionName); - } - - @Override - public NativeFunctionPointer getNativeFunctionPointerFromRawValue(long rawValue) { - return new AMD64HotSpotNativeFunctionPointer(rawValue, null); - } - -} diff -r 4fa77c58ad8f -r 4731c1a0b1f3 graal/com.oracle.graal.nfi.hotspot.amd64/src/com/oracle/graal/nfi/hotspot/amd64/AMD64HotSpotNativeFunctionPointer.java --- a/graal/com.oracle.graal.nfi.hotspot.amd64/src/com/oracle/graal/nfi/hotspot/amd64/AMD64HotSpotNativeFunctionPointer.java Thu Feb 06 18:42:45 2014 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2014, 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. - */ -package com.oracle.graal.nfi.hotspot.amd64; - -import com.oracle.graal.api.code.*; - -public class AMD64HotSpotNativeFunctionPointer implements NativeFunctionPointer { - - private final long functionPointer; - private final String functionName; - - public AMD64HotSpotNativeFunctionPointer(long functionPointer, String functionName) { - this.functionPointer = functionPointer; - this.functionName = functionName; - } - - public boolean isValid() { - return functionPointer != 0; - } - - @Override - public long asRawValue() { - return functionPointer; - } - - public String getFunctionName() { - return functionName; - } - -} diff -r 4fa77c58ad8f -r 4731c1a0b1f3 graal/com.oracle.graal.nfi.hotspot.amd64/src/com/oracle/graal/nfi/hotspot/amd64/AMD64HotSpotNativeLibraryHandle.java --- a/graal/com.oracle.graal.nfi.hotspot.amd64/src/com/oracle/graal/nfi/hotspot/amd64/AMD64HotSpotNativeLibraryHandle.java Thu Feb 06 18:42:45 2014 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2014, 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. - */ -package com.oracle.graal.nfi.hotspot.amd64; - -import com.oracle.graal.api.code.*; - -public class AMD64HotSpotNativeLibraryHandle implements NativeLibraryHandle { - - private final long handle; - - public AMD64HotSpotNativeLibraryHandle(long handle) { - this.handle = handle; - } - - public long asRawValue() { - return handle; - } - - public boolean isValid() { - return handle != 0; - } -} diff -r 4fa77c58ad8f -r 4731c1a0b1f3 graal/com.oracle.graal.nfi.hotspot.amd64/src/com/oracle/graal/nfi/hotspot/amd64/node/AMD64RawNativeCallNode.java --- a/graal/com.oracle.graal.nfi.hotspot.amd64/src/com/oracle/graal/nfi/hotspot/amd64/node/AMD64RawNativeCallNode.java Thu Feb 06 18:42:45 2014 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,80 +0,0 @@ -/* - * Copyright (c) 2014, 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. - */ -package com.oracle.graal.nfi.hotspot.amd64.node; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.code.CallingConvention.Type; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.amd64.*; -import com.oracle.graal.compiler.gen.*; -import com.oracle.graal.compiler.target.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.type.*; - -public class AMD64RawNativeCallNode extends FixedWithNextNode implements LIRGenLowerable { - - private final Constant functionPointer; - @Input private final NodeInputList args; - - public AMD64RawNativeCallNode(Kind returnType, Constant functionPointer, ValueNode[] args) { - super(StampFactory.forKind(returnType)); - this.functionPointer = functionPointer; - this.args = new NodeInputList<>(this, args); - } - - @Override - public void generate(LIRGenerator generator) { - if (generator instanceof AMD64LIRGenerator) { - AMD64LIRGenerator amd64gen = (AMD64LIRGenerator) generator; - Value[] parameter = new Value[args.count()]; - JavaType[] parameterTypes = new JavaType[args.count()]; - for (int i = 0; i < args.count(); i++) { - parameter[i] = generator.operand(args.get(i)); - parameterTypes[i] = args.get(i).stamp().javaType(amd64gen.getMetaAccess()); - } - ResolvedJavaType returnType = stamp().javaType(amd64gen.getMetaAccess()); - CallingConvention cc = generator.getCodeCache().getRegisterConfig().getCallingConvention(Type.NativeCall, returnType, parameterTypes, generator.target(), false); - amd64gen.emitCCall(functionPointer.asLong(), cc, parameter, countFloatingTypeArguments(args)); - if (this.kind() != Kind.Void) { - generator.setResult(this, amd64gen.emitMove(cc.getReturn())); - } - } else { - throw GraalInternalError.shouldNotReachHere("GNFI Native call only supported with AMD64LIR Generator"); - } - } - - private static int countFloatingTypeArguments(NodeInputList args) { - int count = 0; - for (ValueNode n : args) { - if (n.kind() == Kind.Double || n.kind() == Kind.Float) { - count++; - } - } - if (count > 8) { - return 8; - } - return count; - } - -} diff -r 4fa77c58ad8f -r 4731c1a0b1f3 graal/com.oracle.graal.nfi.hotspot.amd64/src/com/oracle/graal/nfi/hotspot/amd64/util/InstallUtil.java --- a/graal/com.oracle.graal.nfi.hotspot.amd64/src/com/oracle/graal/nfi/hotspot/amd64/util/InstallUtil.java Thu Feb 06 18:42:45 2014 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,81 +0,0 @@ -/* - * Copyright (c) 2014, 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. - */ -package com.oracle.graal.nfi.hotspot.amd64.util; - -import static com.oracle.graal.api.code.CodeUtil.*; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.code.CallingConvention.Type; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.api.meta.ProfilingInfo.TriState; -import com.oracle.graal.compiler.*; -import com.oracle.graal.compiler.target.*; -import com.oracle.graal.debug.*; -import com.oracle.graal.debug.Debug.Scope; -import com.oracle.graal.graph.*; -import com.oracle.graal.hotspot.meta.*; -import com.oracle.graal.lir.asm.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.phases.*; -import com.oracle.graal.phases.tiers.*; -import com.oracle.graal.printer.*; - -/** - * Utility to install the code of the native call stub. - * - */ -public class InstallUtil { - - protected final HotSpotProviders providers; - protected final Backend backend; - - public InstallUtil(HotSpotProviders providers, Backend backend) { - DebugEnvironment.initialize(System.out); - this.providers = providers; - this.backend = backend; - } - - /** - * Attaches a graph to a method libCall. Compiles the graph and installs it. - * - * @param g the graph to be attached to a method and compiled - * @return returns the installed code that also holds a copy of graph g - */ - public InstalledCode install(final StructuredGraph g) { - try { - Suites suites = providers.getSuites().createSuites(); - PhaseSuite phaseSuite = backend.getSuites().getDefaultGraphBuilderSuite().copy(); - CallingConvention cc = getCallingConvention(providers.getCodeCache(), Type.JavaCallee, g.method(), false); - CompilationResult compResult = GraalCompiler.compileGraph(g, cc, g.method(), providers, backend, backend.getTarget(), null, phaseSuite, OptimisticOptimizations.ALL, - DefaultProfilingInfo.get(TriState.UNKNOWN), null, suites, true, new CompilationResult(), CompilationResultBuilderFactory.Default); - InstalledCode installedCode; - try (Scope s = Debug.scope("CodeInstall", providers.getCodeCache(), g.method())) { - installedCode = providers.getCodeCache().addMethod(g.method(), compResult, null); - } - - return installedCode; - } catch (SecurityException e) { - throw GraalInternalError.shouldNotReachHere("Installation of GNFI Callstub failed."); - } - } -} diff -r 4fa77c58ad8f -r 4731c1a0b1f3 graal/com.oracle.graal.nfi.hotspot.amd64/src/com/oracle/graal/nfi/hotspot/amd64/util/NativeCallStubGraphBuilder.java --- a/graal/com.oracle.graal.nfi.hotspot.amd64/src/com/oracle/graal/nfi/hotspot/amd64/util/NativeCallStubGraphBuilder.java Thu Feb 06 18:42:45 2014 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,271 +0,0 @@ -/* - * Copyright (c) 2014, 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. - */ -package com.oracle.graal.nfi.hotspot.amd64.util; - -import java.util.*; - -import sun.misc.*; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.hotspot.*; -import com.oracle.graal.hotspot.meta.*; -import com.oracle.graal.nfi.hotspot.amd64.*; -import com.oracle.graal.nfi.hotspot.amd64.node.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.java.*; -import com.oracle.graal.nodes.type.*; -import com.oracle.graal.nodes.virtual.*; -import com.oracle.graal.word.phases.*; - -/** - * Utility that creates a Graal graph. The graph represents the native call stub for a foreign - * target function. - * - */ -public class NativeCallStubGraphBuilder { - - private static final ResolvedJavaType integerJavaType = HotSpotResolvedObjectType.fromClass(Integer.class); - private static final ResolvedJavaField[] integerInstanceFields = integerJavaType.getInstanceFields(false); - private static final ResolvedJavaField integerValueField = getValueField(integerInstanceFields); - - private static final ResolvedJavaType longJavaType = HotSpotResolvedObjectType.fromClass(Long.class); - private static final ResolvedJavaField[] longInstanceFields = longJavaType.getInstanceFields(false); - private static final ResolvedJavaField longValueField = getValueField(longInstanceFields); - - private static final ResolvedJavaType charJavaType = HotSpotResolvedObjectType.fromClass(Character.class); - private static final ResolvedJavaField[] charInstanceFields = charJavaType.getInstanceFields(false); - private static final ResolvedJavaField charValueField = getValueField(charInstanceFields); - - private static final ResolvedJavaType byteJavaType = HotSpotResolvedObjectType.fromClass(Byte.class); - private static final ResolvedJavaField[] byteInstanceFields = byteJavaType.getInstanceFields(false); - private static final ResolvedJavaField byteValueField = getValueField(byteInstanceFields); - - private static final ResolvedJavaType floatJavaType = HotSpotResolvedObjectType.fromClass(Float.class); - private static final ResolvedJavaField[] floatInstanceFields = floatJavaType.getInstanceFields(false); - private static final ResolvedJavaField floatValueField = getValueField(floatInstanceFields); - - private static final ResolvedJavaType doubleJavaType = HotSpotResolvedObjectType.fromClass(Double.class); - private static final ResolvedJavaField[] doubleInstanceFields = doubleJavaType.getInstanceFields(false); - private static final ResolvedJavaField doubleValueField = getValueField(doubleInstanceFields); - - private static ResolvedJavaField getValueField(ResolvedJavaField[] fields) { - for (ResolvedJavaField field : fields) { - if (field.getName().equals("value")) { - return field; - } - } - throw new AssertionError("value field not found!"); - } - - /** - * Creates a Graal graph that represents the call stub for a foreign target function. - * - * @param providers the HotSpot providers - * @param functionPointer a function pointer that points to the foreign target function - * @param returnType the type of the return value - * @param argumentTypes the types of the arguments - * @return the graph that represents the call stub - */ - public static StructuredGraph getGraph(HotSpotProviders providers, AMD64HotSpotNativeFunctionPointer functionPointer, Class returnType, Class[] argumentTypes) { - ResolvedJavaMethod method; - try { - method = providers.getMetaAccess().lookupJavaMethod(NativeCallStubGraphBuilder.class.getMethod("libCall", Object.class, Object.class, Object.class)); - StructuredGraph g = new StructuredGraph(method); - ParameterNode arg0 = g.unique(new ParameterNode(0, StampFactory.forKind(Kind.Object))); - ParameterNode arg1 = g.unique(new ParameterNode(1, StampFactory.forKind(Kind.Object))); - ParameterNode arg2 = g.unique(new ParameterNode(2, StampFactory.forKind(Kind.Object))); - FrameState frameState = g.add(new FrameState(method, 0, Arrays.asList(new ValueNode[]{arg0, arg1, arg2}), 3, 0, false, false, new ArrayList(), - new ArrayList())); - g.start().setStateAfter(frameState); - List parameters = new ArrayList<>(); - FixedWithNextNode fixedWithNext = getParameters(g, arg0, argumentTypes.length, argumentTypes, parameters, providers); - Constant functionPointerNode = Constant.forLong(functionPointer.asRawValue()); - - ValueNode[] arguments = new ValueNode[parameters.size()]; - - for (int i = 0; i < arguments.length; i++) { - arguments[i] = parameters.get(i); - } - - AMD64RawNativeCallNode callNode = g.add(new AMD64RawNativeCallNode(getKind(returnType), functionPointerNode, arguments)); - - if (fixedWithNext == null) { - g.start().setNext(callNode); - } else { - fixedWithNext.setNext(callNode); - } - - // box result - BoxNode boxedResult; - if (callNode.kind() != Kind.Void) { - ResolvedJavaType type = getResolvedJavaType(callNode.kind()); - boxedResult = new BoxNode(callNode, type, callNode.kind()); - } else { - boxedResult = new BoxNode(ConstantNode.forLong(0, g), longJavaType, Kind.Long); - } - - // box result: - BoxNode boxNode = g.unique(boxedResult); - - ReturnNode returnNode = g.add(new ReturnNode(boxNode)); - callNode.setNext(returnNode); - (new WordTypeRewriterPhase(providers.getMetaAccess(), Kind.Long)).apply(g); - return g; - } catch (NoSuchMethodException | SecurityException e) { - throw GraalInternalError.shouldNotReachHere("Call Stub method not found"); - } - } - - private static FixedWithNextNode getParameters(StructuredGraph g, ParameterNode argumentsArray, int numArgs, Class[] argumentClass, List args, HotSpotProviders providers) { - assert numArgs == argumentClass.length; - FixedWithNextNode fixedWithNext = null; - for (int i = 0; i < numArgs; i++) { - // load boxed array element: - LoadIndexedNode boxedElement = g.add(new LoadIndexedNode(argumentsArray, ConstantNode.forInt(i, g), Kind.Object)); - if (i == 0) { - g.start().setNext(boxedElement); - fixedWithNext = boxedElement; - } else { - fixedWithNext.setNext(boxedElement); - fixedWithNext = boxedElement; - } - if (getKind(argumentClass[i]) == Kind.Object) { - // array value - Kind arrayElementKind = getArrayValuesKind(argumentClass[i]); - LocationIdentity locationIdentity = NamedLocationIdentity.getArrayLocation(arrayElementKind); - IndexedLocationNode locationNode = IndexedLocationNode.create(locationIdentity, arrayElementKind, HotSpotGraalRuntime.getArrayBaseOffset(arrayElementKind), ConstantNode.forInt(0, g), - g, HotSpotGraalRuntime.getArrayIndexScale(arrayElementKind)); - ComputeAddressNode arrayAddress = g.unique(new ComputeAddressNode(boxedElement, locationNode, StampFactory.forKind(providers.getCodeCache().getTarget().wordKind))); - args.add(arrayAddress); - } else { - // boxed primitive value - LoadFieldNode loadFieldNode = g.add(new LoadFieldNode(boxedElement, getResolvedJavaField(argumentClass[i]))); - fixedWithNext.setNext(loadFieldNode); - fixedWithNext = loadFieldNode; - args.add(loadFieldNode); - } - } - return fixedWithNext; - } - - public static int getArrayValuesObjectOffset(Class clazz) { - if (clazz == int[].class) { - return Unsafe.ARRAY_INT_BASE_OFFSET; - } else if (clazz == long[].class) { - return Unsafe.ARRAY_LONG_BASE_OFFSET; - } else if (clazz == char[].class) { - return Unsafe.ARRAY_CHAR_BASE_OFFSET; - } else if (clazz == byte[].class) { - return Unsafe.ARRAY_BYTE_BASE_OFFSET; - } else if (clazz == float[].class) { - return Unsafe.ARRAY_FLOAT_BASE_OFFSET; - } else if (clazz == double[].class) { - return Unsafe.ARRAY_DOUBLE_BASE_OFFSET; - } else { - throw new IllegalArgumentException("Array Type not supported: " + clazz); - } - } - - public static Kind getArrayValuesKind(Class clazz) { - if (clazz == int[].class) { - return Kind.Int; - } else if (clazz == long[].class) { - return Kind.Long; - } else if (clazz == char[].class) { - return Kind.Char; - } else if (clazz == byte[].class) { - return Kind.Byte; - } else if (clazz == float[].class) { - return Kind.Float; - } else if (clazz == double[].class) { - return Kind.Double; - } else { - throw new IllegalArgumentException("Array Type not supported: " + clazz); - } - } - - private static Kind getKind(Class clazz) { - if (clazz == int.class || clazz == Integer.class) { - return Kind.Int; - } else if (clazz == long.class || clazz == Long.class) { - return Kind.Long; - } else if (clazz == char.class || clazz == Character.class) { - return Kind.Char; - } else if (clazz == byte.class || clazz == Byte.class) { - return Kind.Byte; - } else if (clazz == float.class || clazz == Float.class) { - return Kind.Float; - } else if (clazz == double.class || clazz == Double.class) { - return Kind.Double; - } else if (clazz == int[].class || clazz == long[].class || clazz == char[].class || clazz == byte[].class || clazz == float[].class || clazz == double[].class) { - return Kind.Object; - } else if (clazz == void.class) { - return Kind.Void; - } else { - throw new IllegalArgumentException("Type not supported: " + clazz); - } - } - - private static ResolvedJavaField getResolvedJavaField(Class containerClass) { - if (containerClass == int.class || containerClass == Integer.class) { - return integerValueField; - } else if (containerClass == long.class || containerClass == Long.class) { - return longValueField; - } else if (containerClass == char.class || containerClass == Character.class) { - return charValueField; - } else if (containerClass == byte.class || containerClass == Byte.class) { - return byteValueField; - } else if (containerClass == float.class || containerClass == Float.class) { - return floatValueField; - } else if (containerClass == double.class || containerClass == Double.class) { - return doubleValueField; - } else { - throw new IllegalArgumentException("Type not supported: " + containerClass); - } - } - - private static ResolvedJavaType getResolvedJavaType(Kind kind) { - if (kind == Kind.Int) { - return integerJavaType; - } else if (kind == Kind.Long) { - return longJavaType; - } else if (kind == Kind.Char) { - return charJavaType; - } else if (kind == Kind.Byte) { - return byteJavaType; - } else if (kind == Kind.Float) { - return floatJavaType; - } else if (kind == Kind.Double) { - return doubleJavaType; - } else { - throw GraalInternalError.shouldNotReachHere(); - } - } - - @SuppressWarnings("unused") - public static Object libCall(Object argLoc, Object unused1, Object unused2) { - throw GraalInternalError.shouldNotReachHere("GNFI Callstub method must not be called!"); - } -} diff -r 4fa77c58ad8f -r 4731c1a0b1f3 graal/com.oracle.graal.nfi.test/test/com/oracle/graal/nfi/test/LibCallTest.java --- a/graal/com.oracle.graal.nfi.test/test/com/oracle/graal/nfi/test/LibCallTest.java Thu Feb 06 18:42:45 2014 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,86 +0,0 @@ -/* - * Copyright (c) 2013, 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. - */ -package com.oracle.graal.nfi.test; - -import java.lang.reflect.*; - -import sun.misc.*; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.runtime.*; -import com.oracle.graal.compiler.target.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.runtime.*; - -public class LibCallTest { - - protected static final Unsafe unsafe = getUnsafe(); - public final RuntimeProvider runtimeProvider; - public final NativeFunctionInterface ffi; - - public LibCallTest() { - this.runtimeProvider = Graal.getRequiredCapability(RuntimeProvider.class); - if (runtimeProvider.getHostBackend() instanceof HostBackend) { - ffi = ((HostBackend) runtimeProvider.getHostBackend()).getNativeFunctionInterface(); - } else { - throw GraalInternalError.shouldNotReachHere("Cannot initialize GNFI - backend is not a HostBackend"); - } - } - - protected long getDouble(double val) { - Long d = unsafe.allocateMemory(8); - unsafe.putDouble(d, val); - return d; - } - - protected long getLong(long val) { - Long d = unsafe.allocateMemory(8); - unsafe.putLong(d, val); - return d; - } - - protected long getInt(int val) { - Long d = unsafe.allocateMemory(4); - unsafe.putInt(d, val); - return d; - } - - protected void free(long p) { - unsafe.freeMemory(p); - } - - private static Unsafe getUnsafe() { - try { - return Unsafe.getUnsafe(); - } catch (SecurityException e) { - } - try { - Field theUnsafeInstance = Unsafe.class.getDeclaredField("theUnsafe"); - theUnsafeInstance.setAccessible(true); - return (Unsafe) theUnsafeInstance.get(Unsafe.class); - } catch (Exception e) { - throw new RuntimeException("exception while trying to get Unsafe.theUnsafe via reflection:", e); - } - } - -} diff -r 4fa77c58ad8f -r 4731c1a0b1f3 graal/com.oracle.graal.nfi.test/test/com/oracle/graal/nfi/test/MathLibCallTest.java --- a/graal/com.oracle.graal.nfi.test/test/com/oracle/graal/nfi/test/MathLibCallTest.java Thu Feb 06 18:42:45 2014 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2013, 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. - */ -package com.oracle.graal.nfi.test; - -import org.junit.*; - -import com.oracle.graal.api.code.*; - -public class MathLibCallTest extends LibCallTest { - - private final Object[] args = new Object[]{Double.doubleToLongBits(3), Double.doubleToLongBits(5.5)}; - private final NativeFunctionHandle handle = ffi.getFunctionHandle("pow", double.class, new Class[]{double.class, double.class}); - - @Test - public void powTest() { - double result = (double) handle.call(args); - Assert.assertEquals(Math.pow(3, 5.5), result, 0); - } - - @Test - public void compilePowTest() { - double result = 0; - for (int i = 0; i < 100000; i++) { - result = callPow(); - } - Assert.assertEquals(Math.pow(3, 5.5), result, 0); - - } - - private double callPow() { - return (double) handle.call(args); - } -} diff -r 4fa77c58ad8f -r 4731c1a0b1f3 graal/com.oracle.graal.nfi.test/test/com/oracle/graal/nfi/test/StdLibCallTest.java --- a/graal/com.oracle.graal.nfi.test/test/com/oracle/graal/nfi/test/StdLibCallTest.java Thu Feb 06 18:42:45 2014 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,192 +0,0 @@ -/* - * Copyright (c) 2013, 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. - */ -package com.oracle.graal.nfi.test; - -import org.junit.*; - -import com.oracle.graal.api.code.*; - -public class StdLibCallTest extends LibCallTest { - - private static void copyString(long pointer, String s) { - for (int i = 0; i < s.length(); i++) { - unsafe.putByte(pointer + i, (byte) s.charAt(i)); - } - unsafe.putByte(pointer + s.length(), (byte) '\0'); - } - - private static void checkString(long pointer, String s) { - for (int i = 0; i < s.length(); i++) { - Assert.assertEquals(unsafe.getByte(pointer + i) & 0xFF, (byte) s.charAt(i)); - } - Assert.assertEquals(unsafe.getByte(pointer + s.length()) & 0xFF, (byte) '\0'); - } - - private static long getBuffer(int length) { - return unsafe.allocateMemory(length); - } - - @Test - public void mallocTest() { - String string = "GRAAL"; - int stringLength = string.length() + 1; - - Object[] args = new Object[]{1}; - args[0] = stringLength; - NativeFunctionHandle mallocHandle = ffi.getFunctionHandle("malloc", long.class, new Class[]{int.class}); - - long p = (long) mallocHandle.call(args); - copyString(p, string); - - long buffer = getBuffer(stringLength); - NativeFunctionHandle putsHandle = ffi.getFunctionHandle("snprintf", int.class, new Class[]{long.class, int.class, long.class}); - Object[] args2 = new Object[]{buffer, stringLength, p}; - int result = (int) putsHandle.call(args2); - Assert.assertTrue(0 < result); - checkString(p, string); - checkString(buffer, string); - - NativeFunctionHandle freeHandle = ffi.getFunctionHandle("free", void.class, new Class[]{long.class}); - freeHandle.call(args2); - } - - @Test - public void printfSimpleTest() { - long str = unsafe.allocateMemory(8); - copyString(str, "AB %f%f"); - - String referenceString = "AB 1.0000001.000000"; - int referenceStringLenght = referenceString.length() + 1; - - long buffer = getBuffer(referenceStringLenght); - - Object[] args = new Object[]{buffer, referenceStringLenght, str, Double.doubleToRawLongBits(1.0), Double.doubleToRawLongBits(1.0)}; - NativeFunctionHandle printfHandle = ffi.getFunctionHandle("snprintf", int.class, new Class[]{long.class, int.class, long.class, double.class, double.class}); - - int result = (int) printfHandle.call(args); - - checkString(buffer, referenceString); - Assert.assertTrue(0 < result); - } - - @Test - public void printfTest() { - long str = unsafe.allocateMemory(25); - int[] val = new int[12]; - for (int i = 0; i < 12; i++) { - unsafe.putByte(str + 2 * i, (byte) '%'); - unsafe.putByte(str + 2 * i + 1, (byte) 'i'); - val[i] = i; - } - unsafe.putByte(str + 24, (byte) '\0'); - - String referenceString = "01234567891011"; - int referenceStringLenght = referenceString.length() + 1; - - long buffer = getBuffer(referenceStringLenght); - - Object[] args = new Object[]{buffer, referenceStringLenght, str, val[0], val[1], val[2], val[3], val[4], val[5], val[6], val[7], val[8], val[9], val[10], val[11]}; - NativeFunctionHandle printfHandle = ffi.getFunctionHandle("snprintf", int.class, new Class[]{long.class, int.class, long.class, int.class, int.class, int.class, int.class, int.class, - int.class, int.class, int.class, int.class, int.class, int.class, int.class}); - - int result = (int) printfHandle.call(args); - checkString(buffer, referenceString); - Assert.assertTrue(0 < result); - } - - @Test - public void printfTest2() { - long str = unsafe.allocateMemory(49); - int[] val = new int[12]; - for (int i = 0; i < 12; i++) { - unsafe.putByte(str + 2 * i, (byte) '%'); - unsafe.putByte(str + 2 * i + 1, (byte) 'i'); - val[i] = i; - } - double[] dval = new double[12]; - for (int i = 12; i < 24; i++) { - unsafe.putByte(str + 2 * i, (byte) '%'); - unsafe.putByte(str + 2 * i + 1, (byte) 'f'); - dval[i - 12] = i + 0.5; - } - unsafe.putByte(str + 48, (byte) '\0'); - - String referenceString = "0123456789101112.50000013.50000014.50000015.50000016.50000017.50000018.50000019.50000020.500000" + "21.50000022.50000023.500000"; - int referenceStringLenght = referenceString.length() + 1; - - long buffer = getBuffer(referenceStringLenght); - - Object[] args = new Object[]{buffer, referenceStringLenght, str, val[0], val[1], val[2], val[3], val[4], val[5], val[6], val[7], val[8], val[9], val[10], val[11], dval[0], dval[1], dval[2], - dval[3], dval[4], dval[5], dval[6], dval[7], dval[8], dval[9], dval[10], dval[11]}; - - NativeFunctionHandle printfHandle = ffi.getFunctionHandle("snprintf", int.class, new Class[]{long.class, int.class, long.class, int.class, int.class, int.class, int.class, int.class, - int.class, int.class, int.class, int.class, int.class, int.class, int.class, double.class, double.class, double.class, double.class, double.class, double.class, double.class, - double.class, double.class, double.class, double.class, double.class}); - - int result = (int) printfHandle.call(args); - checkString(buffer, referenceString); - Assert.assertTrue(0 < result); - } - - @Test - public void printfTest3() { - long str = unsafe.allocateMemory(73); - int[] val = new int[12]; - for (int i = 0; i < 12; i++) { - unsafe.putByte(str + 2 * i, (byte) '%'); - unsafe.putByte(str + 2 * i + 1, (byte) 'i'); - val[i] = i; - } - double[] dval = new double[12]; - for (int i = 12; i < 24; i++) { - unsafe.putByte(str + 2 * i, (byte) '%'); - unsafe.putByte(str + 2 * i + 1, (byte) 'f'); - dval[i - 12] = i + 0.5; - } - char[] cval = new char[12]; - for (int i = 24; i < 36; i++) { - unsafe.putByte(str + 2 * i, (byte) '%'); - unsafe.putByte(str + 2 * i + 1, (byte) 'c'); - cval[i - 24] = (char) ('a' + (i - 24)); - } - unsafe.putByte(str + 72, (byte) '\0'); - - String referenceString = "0123456789101112.50000013.50000014.50000015.50000016.50000017.50000018.50000019.50000020.50000021.50000022.50000023.500000abcdefghijkl"; - int referenceStringLenght = referenceString.length() + 1; - - long buffer = getBuffer(referenceStringLenght); - - Object[] args = new Object[]{buffer, referenceStringLenght, str, val[0], val[1], val[2], val[3], val[4], val[5], val[6], val[7], val[8], val[9], val[10], val[11], dval[0], dval[1], dval[2], - dval[3], dval[4], dval[5], dval[6], dval[7], dval[8], dval[9], dval[10], dval[11], cval[0], cval[1], cval[2], cval[3], cval[4], cval[5], cval[6], cval[7], cval[8], cval[9], - cval[10], cval[11]}; - - NativeFunctionHandle printfHandle = ffi.getFunctionHandle("snprintf", int.class, new Class[]{long.class, int.class, long.class, int.class, int.class, int.class, int.class, int.class, - int.class, int.class, int.class, int.class, int.class, int.class, int.class, double.class, double.class, double.class, double.class, double.class, double.class, double.class, - double.class, double.class, double.class, double.class, double.class, char.class, char.class, char.class, char.class, char.class, char.class, char.class, char.class, - char.class, char.class, char.class, char.class}); - - int result = (int) printfHandle.call(args); - checkString(buffer, referenceString); - Assert.assertTrue(0 < result); - } -} diff -r 4fa77c58ad8f -r 4731c1a0b1f3 mx/projects --- a/mx/projects Thu Feb 06 18:42:45 2014 +0100 +++ b/mx/projects Thu Feb 06 18:44:14 2014 +0100 @@ -184,7 +184,7 @@ # graal.hotspot.amd64 project@com.oracle.graal.hotspot.amd64@subDir=graal project@com.oracle.graal.hotspot.amd64@sourceDirs=src -project@com.oracle.graal.hotspot.amd64@dependencies=com.oracle.graal.nfi.hotspot.amd64,com.oracle.graal.replacements.amd64 +project@com.oracle.graal.hotspot.amd64@dependencies=com.oracle.graal.compiler.amd64,com.oracle.graal.hotspot,com.oracle.graal.replacements.amd64 project@com.oracle.graal.hotspot.amd64@checkstyle=com.oracle.graal.graph project@com.oracle.graal.hotspot.amd64@annotationProcessors=com.oracle.graal.service.processor project@com.oracle.graal.hotspot.amd64@javaCompliance=1.7 @@ -651,22 +651,6 @@ project@com.oracle.graal.asm.sparc@javaCompliance=1.7 project@com.oracle.graal.asm.sparc@workingSets=Graal,Assembler,SPARC -# graal.nfi.hotspot.amd64 -project@com.oracle.graal.nfi.hotspot.amd64@subDir=graal -project@com.oracle.graal.nfi.hotspot.amd64@sourceDirs=src -project@com.oracle.graal.nfi.hotspot.amd64@dependencies=com.oracle.graal.compiler.amd64,com.oracle.graal.hotspot -project@com.oracle.graal.nfi.hotspot.amd64@checkstyle=com.oracle.graal.graph -project@com.oracle.graal.nfi.hotspot.amd64@javaCompliance=1.7 -project@com.oracle.graal.nfi.hotspot.amd64@workingSets=Graal,AMD64 - -# graal.nfi.test -project@com.oracle.graal.nfi.test@subDir=graal -project@com.oracle.graal.nfi.test@sourceDirs=test -project@com.oracle.graal.nfi.test@dependencies=JUNIT,com.oracle.graal.runtime -project@com.oracle.graal.nfi.test@checkstyle=com.oracle.graal.graph -project@com.oracle.graal.nfi.test@javaCompliance=1.7 -project@com.oracle.graal.nfi.test@workingSets=Graal,Test - # truffle.api project@com.oracle.truffle.api@subDir=graal project@com.oracle.truffle.api@sourceDirs=src diff -r 4fa77c58ad8f -r 4731c1a0b1f3 src/share/vm/graal/graalCompilerToVM.cpp --- a/src/share/vm/graal/graalCompilerToVM.cpp Thu Feb 06 18:42:45 2014 +0100 +++ b/src/share/vm/graal/graalCompilerToVM.cpp Thu Feb 06 18:44:14 2014 +0100 @@ -558,8 +558,8 @@ //------------------------------------------------------------------------------------------------ - set_long("libraryLoadAddress", (jlong) os::dll_load); - set_long("functionLookupAddress", (jlong) os::dll_lookup); + set_long("dllLoad", (jlong) os::dll_load); + set_long("dllLookup", (jlong) os::dll_lookup); #if defined(TARGET_OS_FAMILY_bsd) || defined(TARGET_OS_FAMILY_linux) set_long("rtldDefault", (jlong) RTLD_DEFAULT); #endif