# HG changeset patch # User Christian Wirth # Date 1391599016 -3600 # Node ID c6b1802ae32b4479f9efff39c98c9322c9e00a12 # Parent 54892f32714e9414a543421b519300bf7f49f4c3# Parent 43678ad7ae92a4285728788eeb001a055a69b303 Merged diff -r 54892f32714e -r c6b1802ae32b graal/com.oracle.graal.ffi.amd64.test/test/com/oracle/graal/ffi/amd64/test/LibCallTest.java --- a/graal/com.oracle.graal.ffi.amd64.test/test/com/oracle/graal/ffi/amd64/test/LibCallTest.java Wed Feb 05 11:44:10 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.ffi.amd64.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 54892f32714e -r c6b1802ae32b graal/com.oracle.graal.ffi.amd64.test/test/com/oracle/graal/ffi/amd64/test/MathLibCallTest.java --- a/graal/com.oracle.graal.ffi.amd64.test/test/com/oracle/graal/ffi/amd64/test/MathLibCallTest.java Wed Feb 05 11:44:10 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.ffi.amd64.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 54892f32714e -r c6b1802ae32b graal/com.oracle.graal.ffi.amd64.test/test/com/oracle/graal/ffi/amd64/test/StdLibCallTest.java --- a/graal/com.oracle.graal.ffi.amd64.test/test/com/oracle/graal/ffi/amd64/test/StdLibCallTest.java Wed Feb 05 11:44:10 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.ffi.amd64.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 54892f32714e -r c6b1802ae32b graal/com.oracle.graal.ffi.amd64/src/com/oracle/graal/ffi/amd64/AMD64NativeFunctionHandle.java --- a/graal/com.oracle.graal.ffi.amd64/src/com/oracle/graal/ffi/amd64/AMD64NativeFunctionHandle.java Wed Feb 05 11:44:10 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.ffi.amd64; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.compiler.target.*; -import com.oracle.graal.ffi.amd64.util.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.hotspot.meta.*; -import com.oracle.graal.nodes.*; - -public class AMD64NativeFunctionHandle implements NativeFunctionHandle { - - private final InstalledCode code; - private final String functionName; - - protected final HotSpotProviders providers; - protected final Backend backend; - - public AMD64NativeFunctionHandle(HotSpotProviders providers, Backend backend, AMD64NativeFunctionPointer 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 54892f32714e -r c6b1802ae32b graal/com.oracle.graal.ffi.amd64/src/com/oracle/graal/ffi/amd64/AMD64NativeFunctionInterface.java --- a/graal/com.oracle.graal.ffi.amd64/src/com/oracle/graal/ffi/amd64/AMD64NativeFunctionInterface.java Wed Feb 05 11:44:10 2014 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,175 +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.ffi.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.meta.*; - -public class AMD64NativeFunctionInterface 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 AMD64NativeLibraryHandle rtldDefault; - protected final AMD64NativeFunctionPointer libraryLoadFunctionPointer; - protected final AMD64NativeFunctionPointer functionLookupFunctionPointer; - - private AMD64NativeFunctionHandle libraryLookupFunctionHandle; - private AMD64NativeFunctionHandle dllLookupFunctionHandle; - - public AMD64NativeFunctionInterface(HotSpotProviders providers, Backend backend, AMD64NativeFunctionPointer libraryLoadFunctionPointer, AMD64NativeFunctionPointer functionLookUpFunctionPointer, - AMD64NativeLibraryHandle rtldDefault) { - this.rtldDefault = rtldDefault; - this.providers = providers; - this.backend = backend; - this.libraryLoadFunctionPointer = libraryLoadFunctionPointer; - this.functionLookupFunctionPointer = functionLookUpFunctionPointer; - } - - @Override - public AMD64NativeLibraryHandle getLibraryHandle(String libPath) { - if (libraryLookupFunctionHandle == null) { - libraryLookupFunctionHandle = new AMD64NativeFunctionHandle(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 AMD64NativeLibraryHandle(libraryHandle); - } - - @Override - public AMD64NativeFunctionHandle getFunctionHandle(NativeLibraryHandle libraryHandle, String functionName, Class returnType, Class[] argumentTypes) { - AMD64NativeFunctionPointer functionPointer = lookupFunctionPointer(functionName, libraryHandle); - if (!functionPointer.isValid()) { - throw new IllegalStateException(functionName + " not found!"); - } - return getFunctionHandle(functionPointer, returnType, argumentTypes); - } - - @Override - public AMD64NativeFunctionHandle getFunctionHandle(NativeLibraryHandle[] libraryHandles, String functionName, Class returnType, Class[] argumentTypes) { - AMD64NativeFunctionPointer functionPointer = null; - for (NativeLibraryHandle libraryHandle : libraryHandles) { - functionPointer = lookupFunctionPointer(functionName, libraryHandle); - if (functionPointer.isValid()) { - return new AMD64NativeFunctionHandle(providers, backend, functionPointer, returnType, argumentTypes); - } - } - return getFunctionHandle(functionName, returnType, argumentTypes); - } - - @Override - public AMD64NativeFunctionHandle getFunctionHandle(String functionName, Class returnType, Class[] argumentTypes) { - if (rtldDefault.asRawValue() == AMD64NativeLibraryHandle.INVALID_RTLD_DEFAULT_HANDLE) { - throw new AssertionError("No library provided or RTLD_DEFAULT not supported!"); - } - return getFunctionHandle(rtldDefault, functionName, returnType, argumentTypes); - } - - private AMD64NativeFunctionPointer lookupFunctionPointer(String functionName, NativeLibraryHandle handle) { - - if (!functionLookupFunctionPointer.isValid()) { - throw new IllegalStateException("no dlsym function pointer"); - } - if (dllLookupFunctionHandle == null) { - dllLookupFunctionHandle = new AMD64NativeFunctionHandle(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 AMD64NativeFunctionPointer(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 AMD64NativeFunctionHandle getFunctionHandle(NativeFunctionPointer functionPointer, Class returnType, Class[] argumentTypes) { - if (functionPointer instanceof AMD64NativeFunctionPointer) { - if (!((AMD64NativeFunctionPointer) functionPointer).isValid()) { - throw new IllegalStateException("Function Symbol not found"); - } - } else { - throw new IllegalStateException("AMD64 function pointer required!"); - } - return new AMD64NativeFunctionHandle(providers, backend, (AMD64NativeFunctionPointer) functionPointer, returnType, argumentTypes); - } - - @Override - public AMD64NativeFunctionPointer getFunctionPointer(NativeLibraryHandle[] libraryHandles, String functionName) { - for (NativeLibraryHandle libraryHandle : libraryHandles) { - AMD64NativeFunctionPointer functionPointer = lookupFunctionPointer(functionName, libraryHandle); - if (functionPointer.isValid()) { - return functionPointer; - } - } - throw new LinkageError("Function not found: " + functionName); - } - - @Override - public NativeFunctionPointer getNativeFunctionPointerFromRawValue(long rawValue) { - return new AMD64NativeFunctionPointer(rawValue, null); - } - -} diff -r 54892f32714e -r c6b1802ae32b graal/com.oracle.graal.ffi.amd64/src/com/oracle/graal/ffi/amd64/AMD64NativeFunctionPointer.java --- a/graal/com.oracle.graal.ffi.amd64/src/com/oracle/graal/ffi/amd64/AMD64NativeFunctionPointer.java Wed Feb 05 11:44:10 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.ffi.amd64; - -import com.oracle.graal.api.code.*; - -public class AMD64NativeFunctionPointer implements NativeFunctionPointer { - - private final long functionPointer; - private final String functionName; - - public AMD64NativeFunctionPointer(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 54892f32714e -r c6b1802ae32b graal/com.oracle.graal.ffi.amd64/src/com/oracle/graal/ffi/amd64/AMD64NativeLibraryHandle.java --- a/graal/com.oracle.graal.ffi.amd64/src/com/oracle/graal/ffi/amd64/AMD64NativeLibraryHandle.java Wed Feb 05 11:44:10 2014 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,48 +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.ffi.amd64; - -import com.oracle.graal.api.code.*; - -public class AMD64NativeLibraryHandle implements NativeLibraryHandle { - - private final long handle; - // The native side (graalCompilerToVM.cpp) sets the rtldDefault handle to 0xDEADFACE if the - // platform is Windows. - // AMD64NativeFunctionInterface checks if rtld_default handle is valid. - // Windows is currently not supported. - // Using 0 is not possible as it is a valid value for rtldDefault on some platforms. - public static final long INVALID_RTLD_DEFAULT_HANDLE = 0xDEADFACE; - - public AMD64NativeLibraryHandle(long handle) { - this.handle = handle; - } - - public long asRawValue() { - return handle; - } - - public boolean isValid() { - return handle != 0; - } -} diff -r 54892f32714e -r c6b1802ae32b graal/com.oracle.graal.ffi.amd64/src/com/oracle/graal/ffi/amd64/node/AMD64RawNativeCallNode.java --- a/graal/com.oracle.graal.ffi.amd64/src/com/oracle/graal/ffi/amd64/node/AMD64RawNativeCallNode.java Wed Feb 05 11:44:10 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.ffi.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 54892f32714e -r c6b1802ae32b graal/com.oracle.graal.ffi.amd64/src/com/oracle/graal/ffi/amd64/util/InstallUtil.java --- a/graal/com.oracle.graal.ffi.amd64/src/com/oracle/graal/ffi/amd64/util/InstallUtil.java Wed Feb 05 11:44:10 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.ffi.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 54892f32714e -r c6b1802ae32b graal/com.oracle.graal.ffi.amd64/src/com/oracle/graal/ffi/amd64/util/NativeCallStubGraphBuilder.java --- a/graal/com.oracle.graal.ffi.amd64/src/com/oracle/graal/ffi/amd64/util/NativeCallStubGraphBuilder.java Wed Feb 05 11:44:10 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.ffi.amd64.util; - -import java.util.*; - -import sun.misc.*; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.ffi.amd64.*; -import com.oracle.graal.ffi.amd64.node.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.hotspot.*; -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 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, AMD64NativeFunctionPointer 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 54892f32714e -r c6b1802ae32b 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 Wed Feb 05 11:44:10 2014 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java Wed Feb 05 12:16:56 2014 +0100 @@ -40,7 +40,6 @@ import com.oracle.graal.asm.amd64.AMD64Assembler.ConditionFlag; import com.oracle.graal.compiler.gen.*; import com.oracle.graal.compiler.target.*; -import com.oracle.graal.ffi.amd64.*; import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.bridge.*; @@ -49,6 +48,7 @@ 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 +311,12 @@ @Override public NativeFunctionInterface getNativeFunctionInterface() { - AMD64NativeFunctionPointer libraryLoadPointer = new AMD64NativeFunctionPointer(getRuntime().getConfig().libraryLoadAddress, "GNFI_UTIL_LOADLIBRARY"); - AMD64NativeFunctionPointer functionLookupPointer = new AMD64NativeFunctionPointer(getRuntime().getConfig().functionLookupAddress, "GNFI_UTIL_FUNCTIONLOOKUP"); - AMD64NativeLibraryHandle rtldDefault = new AMD64NativeLibraryHandle(getRuntime().getConfig().rtldDefault); + 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 AMD64NativeFunctionInterface(this.getProviders(), this, libraryLoadPointer, functionLookupPointer, rtldDefault); + return new AMD64HotSpotNativeFunctionInterface(this.getProviders(), this, libraryLoadPointer, functionLookupPointer, rtldDefault); } } diff -r 54892f32714e -r c6b1802ae32b 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 Wed Feb 05 11:44:10 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Wed Feb 05 12:16:56 2014 +0100 @@ -840,9 +840,15 @@ @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. + public static final long INVALID_RTLD_DEFAULT_HANDLE = 0xDEADFACE; + @Stable public long libraryLoadAddress; @Stable public long functionLookupAddress; - @Stable public long rtldDefault; + @Stable public long rtldDefault = INVALID_RTLD_DEFAULT_HANDLE; /** * This field is used to pass exception objects into and out of the runtime system during diff -r 54892f32714e -r c6b1802ae32b graal/com.oracle.graal.nfi.hotspot.amd64/src/com/oracle/graal/nfi/hotspot/amd64/AMD64HotSpotNativeFunctionHandle.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nfi.hotspot.amd64/src/com/oracle/graal/nfi/hotspot/amd64/AMD64HotSpotNativeFunctionHandle.java Wed Feb 05 12:16:56 2014 +0100 @@ -0,0 +1,61 @@ +/* + * 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 54892f32714e -r c6b1802ae32b graal/com.oracle.graal.nfi.hotspot.amd64/src/com/oracle/graal/nfi/hotspot/amd64/AMD64HotSpotNativeFunctionInterface.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nfi.hotspot.amd64/src/com/oracle/graal/nfi/hotspot/amd64/AMD64HotSpotNativeFunctionInterface.java Wed Feb 05 12:16:56 2014 +0100 @@ -0,0 +1,176 @@ +/* + * 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 54892f32714e -r c6b1802ae32b graal/com.oracle.graal.nfi.hotspot.amd64/src/com/oracle/graal/nfi/hotspot/amd64/AMD64HotSpotNativeFunctionPointer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nfi.hotspot.amd64/src/com/oracle/graal/nfi/hotspot/amd64/AMD64HotSpotNativeFunctionPointer.java Wed Feb 05 12:16:56 2014 +0100 @@ -0,0 +1,50 @@ +/* + * 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 54892f32714e -r c6b1802ae32b graal/com.oracle.graal.nfi.hotspot.amd64/src/com/oracle/graal/nfi/hotspot/amd64/AMD64HotSpotNativeLibraryHandle.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nfi.hotspot.amd64/src/com/oracle/graal/nfi/hotspot/amd64/AMD64HotSpotNativeLibraryHandle.java Wed Feb 05 12:16:56 2014 +0100 @@ -0,0 +1,42 @@ +/* + * 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 54892f32714e -r c6b1802ae32b graal/com.oracle.graal.nfi.hotspot.amd64/src/com/oracle/graal/nfi/hotspot/amd64/node/AMD64RawNativeCallNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nfi.hotspot.amd64/src/com/oracle/graal/nfi/hotspot/amd64/node/AMD64RawNativeCallNode.java Wed Feb 05 12:16:56 2014 +0100 @@ -0,0 +1,80 @@ +/* + * 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 54892f32714e -r c6b1802ae32b graal/com.oracle.graal.nfi.hotspot.amd64/src/com/oracle/graal/nfi/hotspot/amd64/util/InstallUtil.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nfi.hotspot.amd64/src/com/oracle/graal/nfi/hotspot/amd64/util/InstallUtil.java Wed Feb 05 12:16:56 2014 +0100 @@ -0,0 +1,81 @@ +/* + * 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 54892f32714e -r c6b1802ae32b graal/com.oracle.graal.nfi.hotspot.amd64/src/com/oracle/graal/nfi/hotspot/amd64/util/NativeCallStubGraphBuilder.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nfi.hotspot.amd64/src/com/oracle/graal/nfi/hotspot/amd64/util/NativeCallStubGraphBuilder.java Wed Feb 05 12:16:56 2014 +0100 @@ -0,0 +1,271 @@ +/* + * 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 54892f32714e -r c6b1802ae32b graal/com.oracle.graal.nfi.test/test/com/oracle/graal/nfi/test/LibCallTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nfi.test/test/com/oracle/graal/nfi/test/LibCallTest.java Wed Feb 05 12:16:56 2014 +0100 @@ -0,0 +1,86 @@ +/* + * 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 54892f32714e -r c6b1802ae32b graal/com.oracle.graal.nfi.test/test/com/oracle/graal/nfi/test/MathLibCallTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nfi.test/test/com/oracle/graal/nfi/test/MathLibCallTest.java Wed Feb 05 12:16:56 2014 +0100 @@ -0,0 +1,53 @@ +/* + * 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 54892f32714e -r c6b1802ae32b graal/com.oracle.graal.nfi.test/test/com/oracle/graal/nfi/test/StdLibCallTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nfi.test/test/com/oracle/graal/nfi/test/StdLibCallTest.java Wed Feb 05 12:16:56 2014 +0100 @@ -0,0 +1,192 @@ +/* + * 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 54892f32714e -r c6b1802ae32b mx/projects --- a/mx/projects Wed Feb 05 11:44:10 2014 +0100 +++ b/mx/projects Wed Feb 05 12:16:56 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.ffi.amd64,com.oracle.graal.replacements.amd64 +project@com.oracle.graal.hotspot.amd64@dependencies=com.oracle.graal.nfi.hotspot.amd64,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,21 +651,21 @@ project@com.oracle.graal.asm.sparc@javaCompliance=1.7 project@com.oracle.graal.asm.sparc@workingSets=Graal,Assembler,SPARC -# graal.ffi.amd64 -project@com.oracle.graal.ffi.amd64@subDir=graal -project@com.oracle.graal.ffi.amd64@sourceDirs=src -project@com.oracle.graal.ffi.amd64@dependencies=com.oracle.graal.compiler.amd64,com.oracle.graal.hotspot -project@com.oracle.graal.ffi.amd64@checkstyle=com.oracle.graal.graph -project@com.oracle.graal.ffi.amd64@javaCompliance=1.7 -project@com.oracle.graal.ffi.amd64.test@workingSets=Graal,AMD64 +# 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.ffi.amd64.test -project@com.oracle.graal.ffi.amd64.test@subDir=graal -project@com.oracle.graal.ffi.amd64.test@sourceDirs=test -project@com.oracle.graal.ffi.amd64.test@dependencies=JUNIT,com.oracle.graal.runtime -project@com.oracle.graal.ffi.amd64.test@checkstyle=com.oracle.graal.graph -project@com.oracle.graal.ffi.amd64.test@javaCompliance=1.7 -project@com.oracle.graal.ffi.amd64.test@workingSets=Graal,AMD64,Test +# 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 diff -r 54892f32714e -r c6b1802ae32b src/share/vm/graal/graalCompilerToVM.cpp --- a/src/share/vm/graal/graalCompilerToVM.cpp Wed Feb 05 11:44:10 2014 +0100 +++ b/src/share/vm/graal/graalCompilerToVM.cpp Wed Feb 05 12:16:56 2014 +0100 @@ -562,11 +562,6 @@ set_long("functionLookupAddress", (jlong) os::dll_lookup); #if defined(TARGET_OS_FAMILY_bsd) || defined(TARGET_OS_FAMILY_linux) set_long("rtldDefault", (jlong) RTLD_DEFAULT); - #else - // Windows is not supported at the moment. - // On Java-side we do a check on 0xDEADFACE and crash if rtldDefault == 0xDEADFACE. - // Using 0 is not possible as it is a valid value for rtldDefault on some platforms. - set_long("rtldDefault", (jlong) 0xDEADFACE); #endif #undef set_boolean