comparison graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/HotSpotNativeFunctionInterface.java @ 13895:4731c1a0b1f3

consolidated GNFI code into graal.hotspot project and cleaned up the documentation and code
author Doug Simon <doug.simon@oracle.com>
date Thu, 06 Feb 2014 18:44:14 +0100
parents graal/com.oracle.graal.nfi.hotspot.amd64/src/com/oracle/graal/nfi/hotspot/amd64/AMD64HotSpotNativeFunctionInterface.java@43678ad7ae92
children 3089e9a7cf44
comparison
equal deleted inserted replaced
13894:4fa77c58ad8f 13895:4731c1a0b1f3
1 /*
2 * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23 package com.oracle.graal.hotspot.nfi;
24
25 import static com.oracle.graal.api.code.CodeUtil.*;
26 import static com.oracle.graal.graph.UnsafeAccess.*;
27 import static com.oracle.graal.hotspot.nfi.NativeCallStubGraphBuilder.*;
28
29 import com.oracle.graal.api.code.*;
30 import com.oracle.graal.api.code.CallingConvention.*;
31 import com.oracle.graal.api.meta.*;
32 import com.oracle.graal.api.meta.ProfilingInfo.*;
33 import com.oracle.graal.compiler.*;
34 import com.oracle.graal.compiler.target.*;
35 import com.oracle.graal.debug.*;
36 import com.oracle.graal.debug.Debug.*;
37 import com.oracle.graal.hotspot.*;
38 import com.oracle.graal.hotspot.meta.*;
39 import com.oracle.graal.lir.asm.*;
40 import com.oracle.graal.nodes.*;
41 import com.oracle.graal.phases.*;
42 import com.oracle.graal.phases.tiers.*;
43
44 public class HotSpotNativeFunctionInterface implements NativeFunctionInterface {
45
46 private final HotSpotProviders providers;
47 private final Backend backend;
48 private final HotSpotNativeLibraryHandle rtldDefault;
49 private final HotSpotNativeFunctionPointer libraryLoadFunctionPointer;
50 private final HotSpotNativeFunctionPointer functionLookupFunctionPointer;
51 private final RawNativeCallNodeFactory factory;
52
53 private HotSpotNativeFunctionHandle libraryLookupFunctionHandle;
54 private HotSpotNativeFunctionHandle dllLookupFunctionHandle;
55
56 public HotSpotNativeFunctionInterface(HotSpotProviders providers, RawNativeCallNodeFactory factory, Backend backend, long dlopen, long dlsym, long rtldDefault) {
57 this.rtldDefault = rtldDefault == HotSpotVMConfig.INVALID_RTLD_DEFAULT_HANDLE ? null : new HotSpotNativeLibraryHandle("RTLD_DEFAULT", rtldDefault);
58 this.providers = providers;
59 this.backend = backend;
60 this.factory = factory;
61 this.libraryLoadFunctionPointer = new HotSpotNativeFunctionPointer(dlopen, "os::dll_load");
62 this.functionLookupFunctionPointer = new HotSpotNativeFunctionPointer(dlsym, "os::dll_lookup");
63 }
64
65 @Override
66 public HotSpotNativeLibraryHandle getLibraryHandle(String libPath) {
67 if (libraryLookupFunctionHandle == null) {
68 libraryLookupFunctionHandle = createHandle(libraryLoadFunctionPointer, long.class, long.class, long.class, int.class);
69 }
70
71 int ebufLen = 1024;
72 // Allocating a single chunk for both the error message buffer and the
73 // file name simplifies deallocation below.
74 long buffer = unsafe.allocateMemory(ebufLen + libPath.length() + 1);
75 long ebuf = buffer;
76 long libPathCString = writeCString(libPath, buffer + ebufLen);
77 try {
78 long handle = (long) libraryLookupFunctionHandle.call(libPathCString, ebuf, ebufLen);
79 if (handle == 0) {
80 throw new UnsatisfiedLinkError(libPath);
81 }
82 return new HotSpotNativeLibraryHandle(libPath, handle);
83 } finally {
84 unsafe.freeMemory(buffer);
85 }
86 }
87
88 @Override
89 public HotSpotNativeFunctionHandle getFunctionHandle(NativeLibraryHandle library, String name, Class returnType, Class... argumentTypes) {
90 HotSpotNativeFunctionPointer functionPointer = lookupFunctionPointer(name, library, true);
91 return getFunctionHandle(functionPointer, returnType, argumentTypes);
92 }
93
94 @Override
95 public HotSpotNativeFunctionHandle getFunctionHandle(NativeLibraryHandle[] libraries, String name, Class returnType, Class... argumentTypes) {
96 HotSpotNativeFunctionPointer functionPointer = null;
97 for (NativeLibraryHandle libraryHandle : libraries) {
98 functionPointer = lookupFunctionPointer(name, libraryHandle, false);
99 if (functionPointer != null) {
100 return createHandle(functionPointer, returnType, argumentTypes);
101 }
102 }
103 // Fall back to default library path
104 return getFunctionHandle(name, returnType, argumentTypes);
105 }
106
107 @Override
108 public HotSpotNativeFunctionHandle getFunctionHandle(String name, Class returnType, Class... argumentTypes) {
109 if (rtldDefault == null) {
110 throw new UnsatisfiedLinkError(name);
111 }
112 return getFunctionHandle(rtldDefault, name, returnType, argumentTypes);
113 }
114
115 private HotSpotNativeFunctionPointer lookupFunctionPointer(String name, NativeLibraryHandle library, boolean linkageErrorIfMissing) {
116 if (name == null || library == null) {
117 throw new NullPointerException();
118 }
119 if (dllLookupFunctionHandle == null) {
120 dllLookupFunctionHandle = createHandle(functionLookupFunctionPointer, long.class, long.class, long.class);
121 }
122 long nameCString = createCString(name);
123 try {
124 long functionPointer = (long) dllLookupFunctionHandle.call(((HotSpotNativeLibraryHandle) library).value, nameCString);
125 if (functionPointer == 0L) {
126 if (!linkageErrorIfMissing) {
127 return null;
128 }
129 throw new UnsatisfiedLinkError(name);
130 }
131 return new HotSpotNativeFunctionPointer(functionPointer, name);
132 } finally {
133 unsafe.freeMemory(nameCString);
134 }
135 }
136
137 @Override
138 public HotSpotNativeFunctionHandle getFunctionHandle(NativeFunctionPointer functionPointer, Class returnType, Class... argumentTypes) {
139 if (!(functionPointer instanceof HotSpotNativeFunctionPointer)) {
140 throw new UnsatisfiedLinkError(functionPointer.getName());
141 }
142 return createHandle(functionPointer, returnType, argumentTypes);
143 }
144
145 private HotSpotNativeFunctionHandle createHandle(NativeFunctionPointer functionPointer, Class returnType, Class... argumentTypes) {
146 HotSpotNativeFunctionPointer hs = (HotSpotNativeFunctionPointer) functionPointer;
147 InstalledCode code = installNativeFunctionStub(hs.value, returnType, argumentTypes);
148 return new HotSpotNativeFunctionHandle(code, hs.name, argumentTypes);
149 }
150
151 /**
152 * Creates and installs a stub for calling a native function.
153 */
154 private InstalledCode installNativeFunctionStub(long functionPointer, Class returnType, Class... argumentTypes) {
155 StructuredGraph g = getGraph(providers, factory, functionPointer, returnType, argumentTypes);
156 Suites suites = providers.getSuites().createSuites();
157 PhaseSuite<HighTierContext> phaseSuite = backend.getSuites().getDefaultGraphBuilderSuite().copy();
158 CallingConvention cc = getCallingConvention(providers.getCodeCache(), Type.JavaCallee, g.method(), false);
159 CompilationResult compResult = GraalCompiler.compileGraph(g, cc, g.method(), providers, backend, backend.getTarget(), null, phaseSuite, OptimisticOptimizations.ALL,
160 DefaultProfilingInfo.get(TriState.UNKNOWN), null, suites, true, new CompilationResult(), CompilationResultBuilderFactory.Default);
161 InstalledCode installedCode;
162 try (Scope s = Debug.scope("CodeInstall", providers.getCodeCache(), g.method())) {
163 installedCode = providers.getCodeCache().addMethod(g.method(), compResult, null);
164 }
165 return installedCode;
166 }
167
168 @Override
169 public HotSpotNativeFunctionPointer getFunctionPointer(NativeLibraryHandle[] libraries, String name) {
170 for (NativeLibraryHandle libraryHandle : libraries) {
171 HotSpotNativeFunctionPointer functionPointer = lookupFunctionPointer(name, libraryHandle, false);
172 if (functionPointer != null) {
173 return functionPointer;
174 }
175 }
176 // Fall back to default library path
177 if (rtldDefault == null) {
178 throw new UnsatisfiedLinkError(name);
179 }
180 return lookupFunctionPointer(name, rtldDefault, true);
181 }
182
183 @Override
184 public NativeFunctionPointer getNativeFunctionPointerFromRawValue(long rawValue) {
185 return new HotSpotNativeFunctionPointer(rawValue, null);
186 }
187 }