# HG changeset patch # User Gilles Duboscq # Date 1428594055 -7200 # Node ID b1700db197c7fa761b27b8557ff80c4da164255f # Parent 762e03b40d3d6ac59ff71436da2ff4a042543b37 Move com.oracle.nfi implementation to graal.truffle.hotspot since it implements an interface that does not live in the graal class-loader diff -r 762e03b40d3d -r b1700db197c7 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java Thu Apr 09 17:50:15 2015 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java Thu Apr 09 17:40:55 2015 +0200 @@ -41,7 +41,6 @@ import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.meta.HotSpotCodeCacheProvider.MarkId; import com.oracle.graal.hotspot.meta.*; -import com.oracle.graal.hotspot.nfi.*; import com.oracle.graal.hotspot.stubs.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.amd64.*; @@ -50,7 +49,6 @@ import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.nfi.api.*; /** * HotSpot AMD64 specific backend. @@ -326,18 +324,4 @@ } } - /** - * Called from the VM. - */ - public static NativeFunctionInterface createNativeFunctionInterface() { - HotSpotVMConfig config = HotSpotGraalRuntime.runtime().getConfig(); - RawNativeCallNodeFactory factory = new RawNativeCallNodeFactory() { - public FixedWithNextNode createRawCallNode(Kind returnType, JavaConstant functionPointer, ValueNode... args) { - return new AMD64RawNativeCallNode(returnType, functionPointer, args); - } - }; - Backend backend = HotSpotGraalRuntime.runtime().getHostBackend(); - return new HotSpotNativeFunctionInterface(HotSpotGraalRuntime.runtime().getHostProviders(), factory, backend, config.dllLoad, config.dllLookup, config.rtldDefault); - } - } diff -r 762e03b40d3d -r b1700db197c7 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/HotSpotNativeFunctionHandle.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/HotSpotNativeFunctionHandle.java Thu Apr 09 17:50:15 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,95 +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.hotspot.nfi; - -import java.util.*; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.common.*; -import com.oracle.graal.debug.*; -import com.oracle.graal.debug.Debug.Scope; -import com.oracle.nfi.api.*; - -public class HotSpotNativeFunctionHandle implements NativeFunctionHandle { - - private final InstalledCode code; - private final String name; - private final Class[] argumentTypes; - - public HotSpotNativeFunctionHandle(InstalledCode code, String name, Class... argumentTypes) { - this.argumentTypes = argumentTypes; - this.name = name; - this.code = code; - } - - private void traceCall(Object... args) { - try (Scope s = Debug.scope("GNFI")) { - if (Debug.isLogEnabled()) { - Debug.log("[GNFI] %s%s", name, Arrays.toString(args)); - } - } - } - - private void traceResult(Object result) { - try (Scope s = Debug.scope("GNFI")) { - if (Debug.isLogEnabled()) { - Debug.log("[GNFI] %s --> %s", name, result); - } - } - } - - @Override - public Object call(Object... args) { - assert checkArgs(args); - try { - traceCall(args); - Object res = code.executeVarargs(args, null, null); - traceResult(res); - return res; - } catch (InvalidInstalledCodeException e) { - throw GraalInternalError.shouldNotReachHere("Execution of GNFI Callstub failed: " + name); - } - } - - private boolean checkArgs(Object... args) { - assert args.length == argumentTypes.length : this + " expected " + argumentTypes.length + " args, got " + args.length; - for (int i = 0; i < argumentTypes.length; i++) { - Object arg = args[i]; - assert arg != null; - Class expectedType = argumentTypes[i]; - if (expectedType.isPrimitive()) { - Kind kind = Kind.fromJavaClass(expectedType); - expectedType = kind.toBoxedJavaClass(); - } - assert expectedType == arg.getClass() : this + " expected arg " + i + " to be " + expectedType.getName() + ", not " + arg.getClass().getName(); - - } - return true; - } - - @Override - public String toString() { - return name + Arrays.toString(argumentTypes); - } -} diff -r 762e03b40d3d -r b1700db197c7 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/HotSpotNativeFunctionInterface.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/HotSpotNativeFunctionInterface.java Thu Apr 09 17:50:15 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,201 +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.hotspot.nfi; - -import static com.oracle.graal.api.code.CodeUtil.*; -import static com.oracle.graal.compiler.common.UnsafeAccess.*; -import static com.oracle.graal.hotspot.nfi.NativeCallStubGraphBuilder.*; - -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.*; -import com.oracle.graal.compiler.target.*; -import com.oracle.graal.debug.*; -import com.oracle.graal.debug.Debug.Scope; -import com.oracle.graal.hotspot.*; -import com.oracle.graal.hotspot.meta.*; -import com.oracle.graal.lir.asm.*; -import com.oracle.graal.lir.phases.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.phases.*; -import com.oracle.graal.phases.tiers.*; -import com.oracle.nfi.api.*; - -public class HotSpotNativeFunctionInterface implements NativeFunctionInterface { - - private final HotSpotProviders providers; - private final Backend backend; - private final HotSpotNativeLibraryHandle rtldDefault; - private final HotSpotNativeFunctionPointer libraryLoadFunctionPointer; - private final HotSpotNativeFunctionPointer functionLookupFunctionPointer; - private final RawNativeCallNodeFactory factory; - - private HotSpotNativeFunctionHandle libraryLookupFunctionHandle; - private HotSpotNativeFunctionHandle dllLookupFunctionHandle; - - public HotSpotNativeFunctionInterface(HotSpotProviders providers, RawNativeCallNodeFactory factory, Backend backend, long dlopen, long dlsym, long rtldDefault) { - this.rtldDefault = rtldDefault == HotSpotVMConfig.INVALID_RTLD_DEFAULT_HANDLE ? null : new HotSpotNativeLibraryHandle("RTLD_DEFAULT", rtldDefault); - this.providers = providers; - assert backend != null; - this.backend = backend; - this.factory = factory; - this.libraryLoadFunctionPointer = new HotSpotNativeFunctionPointer(dlopen, "os::dll_load"); - this.functionLookupFunctionPointer = new HotSpotNativeFunctionPointer(dlsym, "os::dll_lookup"); - } - - @Override - public HotSpotNativeLibraryHandle getLibraryHandle(String libPath) { - if (libraryLookupFunctionHandle == null) { - libraryLookupFunctionHandle = createHandle(libraryLoadFunctionPointer, long.class, long.class, long.class, int.class); - } - - int ebufLen = 1024; - // Allocating a single chunk for both the error message buffer and the - // file name simplifies deallocation below. - long buffer = unsafe.allocateMemory(ebufLen + libPath.length() + 1); - long ebuf = buffer; - long libPathCString = writeCString(libPath, buffer + ebufLen); - try { - long handle = (long) libraryLookupFunctionHandle.call(libPathCString, ebuf, ebufLen); - if (handle == 0) { - throw new UnsatisfiedLinkError(libPath); - } - return new HotSpotNativeLibraryHandle(libPath, handle); - } finally { - unsafe.freeMemory(buffer); - } - } - - @Override - public HotSpotNativeFunctionHandle getFunctionHandle(NativeLibraryHandle library, String name, Class returnType, Class... argumentTypes) { - HotSpotNativeFunctionPointer functionPointer = lookupFunctionPointer(name, library, false); - return createHandle(functionPointer, returnType, argumentTypes); - } - - @Override - public HotSpotNativeFunctionHandle getFunctionHandle(NativeLibraryHandle[] libraries, String name, Class returnType, Class... argumentTypes) { - HotSpotNativeFunctionPointer functionPointer = null; - for (NativeLibraryHandle libraryHandle : libraries) { - functionPointer = lookupFunctionPointer(name, libraryHandle, false); - if (functionPointer != null) { - return createHandle(functionPointer, returnType, argumentTypes); - } - } - // Fall back to default library path - return getFunctionHandle(name, returnType, argumentTypes); - } - - @Override - public HotSpotNativeFunctionHandle getFunctionHandle(String name, Class returnType, Class... argumentTypes) { - if (rtldDefault == null) { - throw new UnsatisfiedLinkError(name); - } - return getFunctionHandle(rtldDefault, name, returnType, argumentTypes); - } - - private HotSpotNativeFunctionPointer lookupFunctionPointer(String name, NativeLibraryHandle library, boolean linkageErrorIfMissing) { - if (name == null || library == null) { - throw new NullPointerException(); - } - - if (dllLookupFunctionHandle == null) { - dllLookupFunctionHandle = createHandle(functionLookupFunctionPointer, long.class, long.class, long.class); - } - long nameCString = createCString(name); - try { - long functionPointer = (long) dllLookupFunctionHandle.call(((HotSpotNativeLibraryHandle) library).value, nameCString); - if (functionPointer == 0L) { - if (!linkageErrorIfMissing) { - return null; - } - throw new UnsatisfiedLinkError(name); - } - return new HotSpotNativeFunctionPointer(functionPointer, name); - } finally { - unsafe.freeMemory(nameCString); - } - } - - @Override - public HotSpotNativeFunctionHandle getFunctionHandle(NativeFunctionPointer functionPointer, Class returnType, Class... argumentTypes) { - if (!(functionPointer instanceof HotSpotNativeFunctionPointer)) { - throw new UnsatisfiedLinkError(functionPointer.getName()); - } - return createHandle(functionPointer, returnType, argumentTypes); - } - - private HotSpotNativeFunctionHandle createHandle(NativeFunctionPointer functionPointer, Class returnType, Class... argumentTypes) { - HotSpotNativeFunctionPointer hs = (HotSpotNativeFunctionPointer) functionPointer; - if (hs != null) { - InstalledCode code = installNativeFunctionStub(hs.value, returnType, argumentTypes); - return new HotSpotNativeFunctionHandle(code, hs.name, argumentTypes); - } else { - return null; - } - } - - /** - * Creates and installs a stub for calling a native function. - */ - private InstalledCode installNativeFunctionStub(long functionPointer, Class returnType, Class... argumentTypes) { - StructuredGraph g = getGraph(providers, factory, functionPointer, returnType, argumentTypes); - Suites suites = providers.getSuites().createSuites(); - LIRSuites lirSuites = providers.getSuites().createLIRSuites(); - 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(), phaseSuite, OptimisticOptimizations.ALL, - DefaultProfilingInfo.get(TriState.UNKNOWN), null, suites, lirSuites, new CompilationResult(), CompilationResultBuilderFactory.Default); - InstalledCode installedCode; - try (Scope s = Debug.scope("CodeInstall", providers.getCodeCache(), g.method())) { - installedCode = providers.getCodeCache().addMethod(g.method(), compResult, null, null); - } catch (Throwable e) { - throw Debug.handle(e); - } - return installedCode; - } - - @Override - public HotSpotNativeFunctionPointer getFunctionPointer(NativeLibraryHandle[] libraries, String name) { - for (NativeLibraryHandle libraryHandle : libraries) { - HotSpotNativeFunctionPointer functionPointer = lookupFunctionPointer(name, libraryHandle, false); - if (functionPointer != null) { - return functionPointer; - } - } - // Fall back to default library path - if (rtldDefault == null) { - throw new UnsatisfiedLinkError(name); - } - return lookupFunctionPointer(name, rtldDefault, false); - } - - public boolean isDefaultLibrarySearchSupported() { - return rtldDefault != null; - } - - @Override - public NativeFunctionPointer getNativeFunctionPointerFromRawValue(long rawValue) { - return new HotSpotNativeFunctionPointer(rawValue, null); - } -} diff -r 762e03b40d3d -r b1700db197c7 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/HotSpotNativeFunctionPointer.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/HotSpotNativeFunctionPointer.java Thu Apr 09 17:50:15 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,52 +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.hotspot.nfi; - -import com.oracle.nfi.api.*; - -public class HotSpotNativeFunctionPointer implements NativeFunctionPointer { - - final long value; - final String name; - - public HotSpotNativeFunctionPointer(long value, String name) { - if (value == 0) { - throw new UnsatisfiedLinkError(name); - } - this.value = value; - this.name = name; - } - - public String getName() { - return name; - } - - public long getRawValue() { - return value; - } - - @Override - public String toString() { - return name + "@0x" + Long.toHexString(value); - } -} diff -r 762e03b40d3d -r b1700db197c7 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/HotSpotNativeLibraryHandle.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/HotSpotNativeLibraryHandle.java Thu Apr 09 17:50:15 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,59 +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.hotspot.nfi; - -import com.oracle.nfi.api.*; - -public class HotSpotNativeLibraryHandle implements NativeLibraryHandle { - - final long value; - final String name; - - public HotSpotNativeLibraryHandle(String name, long handle) { - this.name = name; - this.value = handle; - } - - public String getName() { - return name; - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof HotSpotNativeLibraryHandle) { - HotSpotNativeLibraryHandle that = (HotSpotNativeLibraryHandle) obj; - return that.value == value; - } - return false; - } - - @Override - public int hashCode() { - return (int) value; - } - - @Override - public String toString() { - return name + "@" + value; - } -} diff -r 762e03b40d3d -r b1700db197c7 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/NativeCallStubGraphBuilder.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/NativeCallStubGraphBuilder.java Thu Apr 09 17:50:15 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,178 +0,0 @@ -/* - * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.hotspot.nfi; - -import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; - -import java.util.*; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.common.*; -import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.hotspot.meta.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; -import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.java.*; -import com.oracle.graal.nodes.virtual.*; - -/** - * Utility creating a graph for a stub used to call a native function. - */ -public class NativeCallStubGraphBuilder { - - /** - * Creates a graph for a stub used to call a native function. - * - * @param functionPointer a native function pointer - * @param returnType the type of the return value - * @param argumentTypes the types of the arguments - * @return the graph that represents the call stub - */ - public static StructuredGraph getGraph(HotSpotProviders providers, RawNativeCallNodeFactory factory, long functionPointer, Class returnType, Class... argumentTypes) { - try { - ResolvedJavaMethod method = providers.getMetaAccess().lookupJavaMethod(NativeCallStubGraphBuilder.class.getMethod("libCall", Object.class, Object.class, Object.class)); - StructuredGraph g = new StructuredGraph(method, AllowAssumptions.NO); - 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(null, method, 0, Arrays.asList(new ValueNode[]{arg0, arg1, arg2}), 3, 0, false, false, null, new ArrayList())); - g.start().setStateAfter(frameState); - List parameters = new ArrayList<>(); - FixedWithNextNode fixedWithNext = getParameters(g, arg0, argumentTypes.length, argumentTypes, parameters, providers); - JavaConstant functionPointerNode = JavaConstant.forLong(functionPointer); - - ValueNode[] arguments = new ValueNode[parameters.size()]; - - for (int i = 0; i < arguments.length; i++) { - arguments[i] = parameters.get(i); - } - - FixedWithNextNode callNode = g.add(factory.createRawCallNode(getKind(returnType), functionPointerNode, arguments)); - - if (fixedWithNext == null) { - g.start().setNext(callNode); - } else { - fixedWithNext.setNext(callNode); - } - - // box result - BoxNode boxedResult; - if (callNode.getKind() != Kind.Void) { - if (callNode.getKind() == Kind.Object) { - throw new IllegalArgumentException("Return type not supported: " + returnType.getName()); - } - ResolvedJavaType type = providers.getMetaAccess().lookupJavaType(callNode.getKind().toBoxedJavaClass()); - boxedResult = g.unique(new BoxNode(callNode, type, callNode.getKind())); - } else { - boxedResult = g.unique(new BoxNode(ConstantNode.forLong(0, g), providers.getMetaAccess().lookupJavaType(Long.class), Kind.Long)); - } - - ReturnNode returnNode = g.add(new ReturnNode(boxedResult)); - callNode.setNext(returnNode); - return g; - } catch (NoSuchMethodException e) { - throw GraalInternalError.shouldNotReachHere("Call Stub method not found"); - } - } - - private static FixedWithNextNode getParameters(StructuredGraph g, ParameterNode argumentsArray, int numArgs, Class[] argumentTypes, List args, HotSpotProviders providers) { - assert numArgs == argumentTypes.length; - FixedWithNextNode last = null; - for (int i = 0; i < numArgs; i++) { - // load boxed array element: - LoadIndexedNode boxedElement = g.add(new LoadIndexedNode(argumentsArray, ConstantNode.forInt(i, g), Kind.Object)); - if (i == 0) { - g.start().setNext(boxedElement); - last = boxedElement; - } else { - last.setNext(boxedElement); - last = boxedElement; - } - Class type = argumentTypes[i]; - Kind kind = getKind(type); - if (kind == Kind.Object) { - // array value - Kind arrayElementKind = getElementKind(type); - LocationIdentity locationIdentity = NamedLocationIdentity.getArrayLocation(arrayElementKind); - int displacement = runtime().getArrayBaseOffset(arrayElementKind); - ConstantNode index = ConstantNode.forInt(0, g); - int indexScaling = runtime().getArrayIndexScale(arrayElementKind); - IndexedLocationNode locationNode = g.unique(new IndexedLocationNode(locationIdentity, displacement, index, indexScaling)); - Stamp wordStamp = StampFactory.forKind(providers.getWordTypes().getWordKind()); - ComputeAddressNode arrayAddress = g.unique(new ComputeAddressNode(boxedElement, locationNode, wordStamp)); - args.add(arrayAddress); - } else { - // boxed primitive value - try { - ResolvedJavaField field = providers.getMetaAccess().lookupJavaField(kind.toBoxedJavaClass().getDeclaredField("value")); - LoadFieldNode loadFieldNode = g.add(new LoadFieldNode(boxedElement, field)); - last.setNext(loadFieldNode); - last = loadFieldNode; - args.add(loadFieldNode); - } catch (NoSuchFieldException e) { - throw new GraalInternalError(e); - } - } - } - return last; - } - - public static Kind getElementKind(Class clazz) { - Class componentType = clazz.getComponentType(); - if (componentType == null) { - throw new IllegalArgumentException("Parameter type not supported: " + clazz); - } - if (componentType.isPrimitive()) { - return Kind.fromJavaClass(componentType); - } - throw new IllegalArgumentException("Parameter type not supported: " + clazz); - } - - private static Kind getKind(Class clazz) { - if (clazz == int.class || clazz == Integer.class) { - return Kind.Int; - } else if (clazz == long.class || clazz == Long.class) { - return Kind.Long; - } else if (clazz == char.class || clazz == Character.class) { - return Kind.Char; - } else if (clazz == byte.class || clazz == Byte.class) { - return Kind.Byte; - } else if (clazz == float.class || clazz == Float.class) { - return Kind.Float; - } else if (clazz == double.class || clazz == Double.class) { - return Kind.Double; - } else if (clazz == int[].class || clazz == long[].class || clazz == char[].class || clazz == byte[].class || clazz == float[].class || clazz == double[].class) { - return Kind.Object; - } else if (clazz == void.class) { - return Kind.Void; - } else { - throw new IllegalArgumentException("Type not supported: " + clazz); - } - } - - @SuppressWarnings("unused") - public static Object libCall(Object argLoc, Object unused1, Object unused2) { - throw GraalInternalError.shouldNotReachHere("GNFI libCall method must not be called"); - } -} diff -r 762e03b40d3d -r b1700db197c7 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/RawNativeCallNodeFactory.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/RawNativeCallNodeFactory.java Thu Apr 09 17:50:15 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.hotspot.nfi; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.nodes.*; - -/** - * Factory for creating a node that makes a direct call to a native function pointer. - */ -public interface RawNativeCallNodeFactory { - FixedWithNextNode createRawCallNode(Kind returnType, JavaConstant functionPointer, ValueNode... args); -} diff -r 762e03b40d3d -r b1700db197c7 graal/com.oracle.graal.truffle.hotspot.amd64/src/com/oracle/graal/truffle/hotspot/amd64/AMD64RawNativeCallNodeFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle.hotspot.amd64/src/com/oracle/graal/truffle/hotspot/amd64/AMD64RawNativeCallNodeFactory.java Thu Apr 09 17:40:55 2015 +0200 @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2015, 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.truffle.hotspot.amd64; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.runtime.*; +import com.oracle.graal.hotspot.amd64.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.truffle.hotspot.nfi.*; + +@ServiceProvider(RawNativeCallNodeFactory.class) +public class AMD64RawNativeCallNodeFactory implements RawNativeCallNodeFactory { + public FixedWithNextNode createRawCallNode(Kind returnType, JavaConstant functionPointer, ValueNode... args) { + return new AMD64RawNativeCallNode(returnType, functionPointer, args); + } + + public String getArchitecture() { + return "AMD64"; + } +} diff -r 762e03b40d3d -r b1700db197c7 graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime.java --- a/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime.java Thu Apr 09 17:50:15 2015 +0200 +++ b/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime.java Thu Apr 09 17:40:55 2015 +0200 @@ -57,6 +57,8 @@ import com.oracle.graal.printer.*; import com.oracle.graal.runtime.*; import com.oracle.graal.truffle.*; +import com.oracle.graal.truffle.hotspot.nfi.*; +import com.oracle.nfi.api.*; import com.oracle.truffle.api.*; import com.oracle.truffle.api.nodes.*; @@ -337,4 +339,27 @@ throw new GraalInternalError(e); } } + + private static RawNativeCallNodeFactory getRawNativeCallNodeFactory(String arch) { + for (RawNativeCallNodeFactory factory : Services.load(RawNativeCallNodeFactory.class)) { + if (factory.getArchitecture().equals(arch)) { + return factory; + } + } + // No RawNativeCallNodeFactory on this platform. + return null; + } + + /** + * Called from the VM. + */ + public static NativeFunctionInterface createNativeFunctionInterface() { + HotSpotVMConfig config = HotSpotGraalRuntime.runtime().getConfig(); + Backend backend = HotSpotGraalRuntime.runtime().getHostBackend(); + RawNativeCallNodeFactory factory = getRawNativeCallNodeFactory(backend.getTarget().arch.getName()); + if (factory == null) { + return null; + } + return new HotSpotNativeFunctionInterface(HotSpotGraalRuntime.runtime().getHostProviders(), factory, backend, config.dllLoad, config.dllLookup, config.rtldDefault); + } } diff -r 762e03b40d3d -r b1700db197c7 graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/nfi/HotSpotNativeFunctionHandle.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/nfi/HotSpotNativeFunctionHandle.java Thu Apr 09 17:40:55 2015 +0200 @@ -0,0 +1,95 @@ +/* + * 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.truffle.hotspot.nfi; + +import java.util.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.debug.*; +import com.oracle.graal.debug.Debug.Scope; +import com.oracle.nfi.api.*; + +public class HotSpotNativeFunctionHandle implements NativeFunctionHandle { + + private final InstalledCode code; + private final String name; + private final Class[] argumentTypes; + + public HotSpotNativeFunctionHandle(InstalledCode code, String name, Class... argumentTypes) { + this.argumentTypes = argumentTypes; + this.name = name; + this.code = code; + } + + private void traceCall(Object... args) { + try (Scope s = Debug.scope("GNFI")) { + if (Debug.isLogEnabled()) { + Debug.log("[GNFI] %s%s", name, Arrays.toString(args)); + } + } + } + + private void traceResult(Object result) { + try (Scope s = Debug.scope("GNFI")) { + if (Debug.isLogEnabled()) { + Debug.log("[GNFI] %s --> %s", name, result); + } + } + } + + @Override + public Object call(Object... args) { + assert checkArgs(args); + try { + traceCall(args); + Object res = code.executeVarargs(args, null, null); + traceResult(res); + return res; + } catch (InvalidInstalledCodeException e) { + throw GraalInternalError.shouldNotReachHere("Execution of GNFI Callstub failed: " + name); + } + } + + private boolean checkArgs(Object... args) { + assert args.length == argumentTypes.length : this + " expected " + argumentTypes.length + " args, got " + args.length; + for (int i = 0; i < argumentTypes.length; i++) { + Object arg = args[i]; + assert arg != null; + Class expectedType = argumentTypes[i]; + if (expectedType.isPrimitive()) { + Kind kind = Kind.fromJavaClass(expectedType); + expectedType = kind.toBoxedJavaClass(); + } + assert expectedType == arg.getClass() : this + " expected arg " + i + " to be " + expectedType.getName() + ", not " + arg.getClass().getName(); + + } + return true; + } + + @Override + public String toString() { + return name + Arrays.toString(argumentTypes); + } +} diff -r 762e03b40d3d -r b1700db197c7 graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/nfi/HotSpotNativeFunctionInterface.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/nfi/HotSpotNativeFunctionInterface.java Thu Apr 09 17:40:55 2015 +0200 @@ -0,0 +1,201 @@ +/* + * 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.truffle.hotspot.nfi; + +import static com.oracle.graal.api.code.CodeUtil.*; +import static com.oracle.graal.compiler.common.UnsafeAccess.*; +import static com.oracle.graal.truffle.hotspot.nfi.NativeCallStubGraphBuilder.*; + +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.*; +import com.oracle.graal.compiler.target.*; +import com.oracle.graal.debug.*; +import com.oracle.graal.debug.Debug.Scope; +import com.oracle.graal.hotspot.*; +import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.lir.asm.*; +import com.oracle.graal.lir.phases.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.phases.*; +import com.oracle.graal.phases.tiers.*; +import com.oracle.nfi.api.*; + +public class HotSpotNativeFunctionInterface implements NativeFunctionInterface { + + private final HotSpotProviders providers; + private final Backend backend; + private final HotSpotNativeLibraryHandle rtldDefault; + private final HotSpotNativeFunctionPointer libraryLoadFunctionPointer; + private final HotSpotNativeFunctionPointer functionLookupFunctionPointer; + private final RawNativeCallNodeFactory factory; + + private HotSpotNativeFunctionHandle libraryLookupFunctionHandle; + private HotSpotNativeFunctionHandle dllLookupFunctionHandle; + + public HotSpotNativeFunctionInterface(HotSpotProviders providers, RawNativeCallNodeFactory factory, Backend backend, long dlopen, long dlsym, long rtldDefault) { + this.rtldDefault = rtldDefault == HotSpotVMConfig.INVALID_RTLD_DEFAULT_HANDLE ? null : new HotSpotNativeLibraryHandle("RTLD_DEFAULT", rtldDefault); + this.providers = providers; + assert backend != null; + this.backend = backend; + this.factory = factory; + this.libraryLoadFunctionPointer = new HotSpotNativeFunctionPointer(dlopen, "os::dll_load"); + this.functionLookupFunctionPointer = new HotSpotNativeFunctionPointer(dlsym, "os::dll_lookup"); + } + + @Override + public HotSpotNativeLibraryHandle getLibraryHandle(String libPath) { + if (libraryLookupFunctionHandle == null) { + libraryLookupFunctionHandle = createHandle(libraryLoadFunctionPointer, long.class, long.class, long.class, int.class); + } + + int ebufLen = 1024; + // Allocating a single chunk for both the error message buffer and the + // file name simplifies deallocation below. + long buffer = unsafe.allocateMemory(ebufLen + libPath.length() + 1); + long ebuf = buffer; + long libPathCString = writeCString(libPath, buffer + ebufLen); + try { + long handle = (long) libraryLookupFunctionHandle.call(libPathCString, ebuf, ebufLen); + if (handle == 0) { + throw new UnsatisfiedLinkError(libPath); + } + return new HotSpotNativeLibraryHandle(libPath, handle); + } finally { + unsafe.freeMemory(buffer); + } + } + + @Override + public HotSpotNativeFunctionHandle getFunctionHandle(NativeLibraryHandle library, String name, Class returnType, Class... argumentTypes) { + HotSpotNativeFunctionPointer functionPointer = lookupFunctionPointer(name, library, false); + return createHandle(functionPointer, returnType, argumentTypes); + } + + @Override + public HotSpotNativeFunctionHandle getFunctionHandle(NativeLibraryHandle[] libraries, String name, Class returnType, Class... argumentTypes) { + HotSpotNativeFunctionPointer functionPointer = null; + for (NativeLibraryHandle libraryHandle : libraries) { + functionPointer = lookupFunctionPointer(name, libraryHandle, false); + if (functionPointer != null) { + return createHandle(functionPointer, returnType, argumentTypes); + } + } + // Fall back to default library path + return getFunctionHandle(name, returnType, argumentTypes); + } + + @Override + public HotSpotNativeFunctionHandle getFunctionHandle(String name, Class returnType, Class... argumentTypes) { + if (rtldDefault == null) { + throw new UnsatisfiedLinkError(name); + } + return getFunctionHandle(rtldDefault, name, returnType, argumentTypes); + } + + private HotSpotNativeFunctionPointer lookupFunctionPointer(String name, NativeLibraryHandle library, boolean linkageErrorIfMissing) { + if (name == null || library == null) { + throw new NullPointerException(); + } + + if (dllLookupFunctionHandle == null) { + dllLookupFunctionHandle = createHandle(functionLookupFunctionPointer, long.class, long.class, long.class); + } + long nameCString = createCString(name); + try { + long functionPointer = (long) dllLookupFunctionHandle.call(((HotSpotNativeLibraryHandle) library).value, nameCString); + if (functionPointer == 0L) { + if (!linkageErrorIfMissing) { + return null; + } + throw new UnsatisfiedLinkError(name); + } + return new HotSpotNativeFunctionPointer(functionPointer, name); + } finally { + unsafe.freeMemory(nameCString); + } + } + + @Override + public HotSpotNativeFunctionHandle getFunctionHandle(NativeFunctionPointer functionPointer, Class returnType, Class... argumentTypes) { + if (!(functionPointer instanceof HotSpotNativeFunctionPointer)) { + throw new UnsatisfiedLinkError(functionPointer.getName()); + } + return createHandle(functionPointer, returnType, argumentTypes); + } + + private HotSpotNativeFunctionHandle createHandle(NativeFunctionPointer functionPointer, Class returnType, Class... argumentTypes) { + HotSpotNativeFunctionPointer hs = (HotSpotNativeFunctionPointer) functionPointer; + if (hs != null) { + InstalledCode code = installNativeFunctionStub(hs.value, returnType, argumentTypes); + return new HotSpotNativeFunctionHandle(code, hs.name, argumentTypes); + } else { + return null; + } + } + + /** + * Creates and installs a stub for calling a native function. + */ + private InstalledCode installNativeFunctionStub(long functionPointer, Class returnType, Class... argumentTypes) { + StructuredGraph g = getGraph(providers, factory, functionPointer, returnType, argumentTypes); + Suites suites = providers.getSuites().createSuites(); + LIRSuites lirSuites = providers.getSuites().createLIRSuites(); + 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(), phaseSuite, OptimisticOptimizations.ALL, + DefaultProfilingInfo.get(TriState.UNKNOWN), null, suites, lirSuites, new CompilationResult(), CompilationResultBuilderFactory.Default); + InstalledCode installedCode; + try (Scope s = Debug.scope("CodeInstall", providers.getCodeCache(), g.method())) { + installedCode = providers.getCodeCache().addMethod(g.method(), compResult, null, null); + } catch (Throwable e) { + throw Debug.handle(e); + } + return installedCode; + } + + @Override + public HotSpotNativeFunctionPointer getFunctionPointer(NativeLibraryHandle[] libraries, String name) { + for (NativeLibraryHandle libraryHandle : libraries) { + HotSpotNativeFunctionPointer functionPointer = lookupFunctionPointer(name, libraryHandle, false); + if (functionPointer != null) { + return functionPointer; + } + } + // Fall back to default library path + if (rtldDefault == null) { + throw new UnsatisfiedLinkError(name); + } + return lookupFunctionPointer(name, rtldDefault, false); + } + + public boolean isDefaultLibrarySearchSupported() { + return rtldDefault != null; + } + + @Override + public NativeFunctionPointer getNativeFunctionPointerFromRawValue(long rawValue) { + return new HotSpotNativeFunctionPointer(rawValue, null); + } +} diff -r 762e03b40d3d -r b1700db197c7 graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/nfi/HotSpotNativeFunctionPointer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/nfi/HotSpotNativeFunctionPointer.java Thu Apr 09 17:40:55 2015 +0200 @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.truffle.hotspot.nfi; + +import com.oracle.nfi.api.*; + +public class HotSpotNativeFunctionPointer implements NativeFunctionPointer { + + final long value; + final String name; + + public HotSpotNativeFunctionPointer(long value, String name) { + if (value == 0) { + throw new UnsatisfiedLinkError(name); + } + this.value = value; + this.name = name; + } + + public String getName() { + return name; + } + + public long getRawValue() { + return value; + } + + @Override + public String toString() { + return name + "@0x" + Long.toHexString(value); + } +} diff -r 762e03b40d3d -r b1700db197c7 graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/nfi/HotSpotNativeLibraryHandle.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/nfi/HotSpotNativeLibraryHandle.java Thu Apr 09 17:40:55 2015 +0200 @@ -0,0 +1,59 @@ +/* + * 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.truffle.hotspot.nfi; + +import com.oracle.nfi.api.*; + +public class HotSpotNativeLibraryHandle implements NativeLibraryHandle { + + final long value; + final String name; + + public HotSpotNativeLibraryHandle(String name, long handle) { + this.name = name; + this.value = handle; + } + + public String getName() { + return name; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof HotSpotNativeLibraryHandle) { + HotSpotNativeLibraryHandle that = (HotSpotNativeLibraryHandle) obj; + return that.value == value; + } + return false; + } + + @Override + public int hashCode() { + return (int) value; + } + + @Override + public String toString() { + return name + "@" + value; + } +} diff -r 762e03b40d3d -r b1700db197c7 graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/nfi/NativeCallStubGraphBuilder.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/nfi/NativeCallStubGraphBuilder.java Thu Apr 09 17:40:55 2015 +0200 @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2014, 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.truffle.hotspot.nfi; + +import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; + +import java.util.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; +import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.nodes.java.*; +import com.oracle.graal.nodes.virtual.*; + +/** + * Utility creating a graph for a stub used to call a native function. + */ +public class NativeCallStubGraphBuilder { + + /** + * Creates a graph for a stub used to call a native function. + * + * @param functionPointer a native function pointer + * @param returnType the type of the return value + * @param argumentTypes the types of the arguments + * @return the graph that represents the call stub + */ + public static StructuredGraph getGraph(HotSpotProviders providers, RawNativeCallNodeFactory factory, long functionPointer, Class returnType, Class... argumentTypes) { + try { + ResolvedJavaMethod method = providers.getMetaAccess().lookupJavaMethod(NativeCallStubGraphBuilder.class.getMethod("libCall", Object.class, Object.class, Object.class)); + StructuredGraph g = new StructuredGraph(method, AllowAssumptions.NO); + 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(null, method, 0, Arrays.asList(new ValueNode[]{arg0, arg1, arg2}), 3, 0, false, false, null, new ArrayList())); + g.start().setStateAfter(frameState); + List parameters = new ArrayList<>(); + FixedWithNextNode fixedWithNext = getParameters(g, arg0, argumentTypes.length, argumentTypes, parameters, providers); + JavaConstant functionPointerNode = JavaConstant.forLong(functionPointer); + + ValueNode[] arguments = new ValueNode[parameters.size()]; + + for (int i = 0; i < arguments.length; i++) { + arguments[i] = parameters.get(i); + } + + FixedWithNextNode callNode = g.add(factory.createRawCallNode(getKind(returnType), functionPointerNode, arguments)); + + if (fixedWithNext == null) { + g.start().setNext(callNode); + } else { + fixedWithNext.setNext(callNode); + } + + // box result + BoxNode boxedResult; + if (callNode.getKind() != Kind.Void) { + if (callNode.getKind() == Kind.Object) { + throw new IllegalArgumentException("Return type not supported: " + returnType.getName()); + } + ResolvedJavaType type = providers.getMetaAccess().lookupJavaType(callNode.getKind().toBoxedJavaClass()); + boxedResult = g.unique(new BoxNode(callNode, type, callNode.getKind())); + } else { + boxedResult = g.unique(new BoxNode(ConstantNode.forLong(0, g), providers.getMetaAccess().lookupJavaType(Long.class), Kind.Long)); + } + + ReturnNode returnNode = g.add(new ReturnNode(boxedResult)); + callNode.setNext(returnNode); + return g; + } catch (NoSuchMethodException e) { + throw GraalInternalError.shouldNotReachHere("Call Stub method not found"); + } + } + + private static FixedWithNextNode getParameters(StructuredGraph g, ParameterNode argumentsArray, int numArgs, Class[] argumentTypes, List args, HotSpotProviders providers) { + assert numArgs == argumentTypes.length; + FixedWithNextNode last = null; + for (int i = 0; i < numArgs; i++) { + // load boxed array element: + LoadIndexedNode boxedElement = g.add(new LoadIndexedNode(argumentsArray, ConstantNode.forInt(i, g), Kind.Object)); + if (i == 0) { + g.start().setNext(boxedElement); + last = boxedElement; + } else { + last.setNext(boxedElement); + last = boxedElement; + } + Class type = argumentTypes[i]; + Kind kind = getKind(type); + if (kind == Kind.Object) { + // array value + Kind arrayElementKind = getElementKind(type); + LocationIdentity locationIdentity = NamedLocationIdentity.getArrayLocation(arrayElementKind); + int displacement = runtime().getArrayBaseOffset(arrayElementKind); + ConstantNode index = ConstantNode.forInt(0, g); + int indexScaling = runtime().getArrayIndexScale(arrayElementKind); + IndexedLocationNode locationNode = g.unique(new IndexedLocationNode(locationIdentity, displacement, index, indexScaling)); + Stamp wordStamp = StampFactory.forKind(providers.getWordTypes().getWordKind()); + ComputeAddressNode arrayAddress = g.unique(new ComputeAddressNode(boxedElement, locationNode, wordStamp)); + args.add(arrayAddress); + } else { + // boxed primitive value + try { + ResolvedJavaField field = providers.getMetaAccess().lookupJavaField(kind.toBoxedJavaClass().getDeclaredField("value")); + LoadFieldNode loadFieldNode = g.add(new LoadFieldNode(boxedElement, field)); + last.setNext(loadFieldNode); + last = loadFieldNode; + args.add(loadFieldNode); + } catch (NoSuchFieldException e) { + throw new GraalInternalError(e); + } + } + } + return last; + } + + public static Kind getElementKind(Class clazz) { + Class componentType = clazz.getComponentType(); + if (componentType == null) { + throw new IllegalArgumentException("Parameter type not supported: " + clazz); + } + if (componentType.isPrimitive()) { + return Kind.fromJavaClass(componentType); + } + throw new IllegalArgumentException("Parameter type not supported: " + clazz); + } + + private static Kind getKind(Class clazz) { + if (clazz == int.class || clazz == Integer.class) { + return Kind.Int; + } else if (clazz == long.class || clazz == Long.class) { + return Kind.Long; + } else if (clazz == char.class || clazz == Character.class) { + return Kind.Char; + } else if (clazz == byte.class || clazz == Byte.class) { + return Kind.Byte; + } else if (clazz == float.class || clazz == Float.class) { + return Kind.Float; + } else if (clazz == double.class || clazz == Double.class) { + return Kind.Double; + } else if (clazz == int[].class || clazz == long[].class || clazz == char[].class || clazz == byte[].class || clazz == float[].class || clazz == double[].class) { + return Kind.Object; + } else if (clazz == void.class) { + return Kind.Void; + } else { + throw new IllegalArgumentException("Type not supported: " + clazz); + } + } + + @SuppressWarnings("unused") + public static Object libCall(Object argLoc, Object unused1, Object unused2) { + throw GraalInternalError.shouldNotReachHere("GNFI libCall method must not be called"); + } +} diff -r 762e03b40d3d -r b1700db197c7 graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/nfi/RawNativeCallNodeFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/nfi/RawNativeCallNodeFactory.java Thu Apr 09 17:40:55 2015 +0200 @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2014, 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.truffle.hotspot.nfi; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.runtime.*; +import com.oracle.graal.nodes.*; + +/** + * Factory for creating a node that makes a direct call to a native function pointer. + */ +public interface RawNativeCallNodeFactory extends Service { + FixedWithNextNode createRawCallNode(Kind returnType, JavaConstant functionPointer, ValueNode... args); + + String getArchitecture(); +} diff -r 762e03b40d3d -r b1700db197c7 mx/suite.py --- a/mx/suite.py Thu Apr 09 17:50:15 2015 +0200 +++ b/mx/suite.py Thu Apr 09 17:40:55 2015 +0200 @@ -329,7 +329,6 @@ "com.oracle.graal.runtime", "com.oracle.graal.printer", "com.oracle.graal.hotspotvmconfig", - "com.oracle.nfi", ], "checkstyle" : "com.oracle.graal.graph", "annotationProcessors" : [ @@ -1079,6 +1078,7 @@ "dependencies" : [ "com.oracle.graal.truffle", "com.oracle.graal.hotspot", + "com.oracle.nfi", ], "checkstyle" : "com.oracle.graal.graph", "javaCompliance" : "1.8", @@ -1091,7 +1091,7 @@ "sourceDirs" : ["src"], "dependencies" : [ "com.oracle.graal.truffle.hotspot", - "com.oracle.graal.asm.amd64", + "com.oracle.graal.hotspot.amd64", ], "checkstyle" : "com.oracle.graal.graph", "javaCompliance" : "1.8", diff -r 762e03b40d3d -r b1700db197c7 src/share/vm/graal/graalRuntime.cpp --- a/src/share/vm/graal/graalRuntime.cpp Thu Apr 09 17:50:15 2015 +0200 +++ b/src/share/vm/graal/graalRuntime.cpp Thu Apr 09 17:40:55 2015 +0200 @@ -652,18 +652,8 @@ // private static NativeFunctionInterfaceRuntime.createInterface() JVM_ENTRY(jobject, JVM_CreateNativeFunctionInterface(JNIEnv *env, jclass c)) - const char* backendName = NULL; - #ifdef TARGET_ARCH_x86 - #ifdef _LP64 - backendName = "com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend"; - #endif - #endif - - if (backendName == NULL) { - return NULL; - } GraalRuntime::ensure_graal_class_loader_is_initialized(); - TempNewSymbol name = SymbolTable::new_symbol(backendName, CHECK_NULL); + TempNewSymbol name = SymbolTable::new_symbol("com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime", CHECK_NULL); KlassHandle klass = GraalRuntime::resolve_or_fail(name, CHECK_NULL); TempNewSymbol makeInstance = SymbolTable::new_symbol("createNativeFunctionInterface", CHECK_NULL);