001/* 002 * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. 003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 004 * 005 * This code is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU General Public License version 2 only, as 007 * published by the Free Software Foundation. 008 * 009 * This code is distributed in the hope that it will be useful, but WITHOUT 010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 011 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 012 * version 2 for more details (a copy is included in the LICENSE file that 013 * accompanied this code). 014 * 015 * You should have received a copy of the GNU General Public License version 016 * 2 along with this work; if not, write to the Free Software Foundation, 017 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 018 * 019 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 020 * or visit www.oracle.com if you need additional information or have any 021 * questions. 022 */ 023package com.oracle.graal.truffle.hotspot.nfi; 024 025import jdk.internal.jvmci.code.*; 026import jdk.internal.jvmci.code.CallingConvention.*; 027import com.oracle.graal.debug.*; 028import com.oracle.graal.debug.Debug.*; 029import jdk.internal.jvmci.hotspot.*; 030import jdk.internal.jvmci.meta.*; 031import static com.oracle.graal.truffle.hotspot.nfi.NativeCallStubGraphBuilder.*; 032import static jdk.internal.jvmci.code.CodeUtil.*; 033import static jdk.internal.jvmci.common.UnsafeAccess.*; 034 035import com.oracle.graal.compiler.*; 036import com.oracle.graal.compiler.target.*; 037import com.oracle.graal.hotspot.meta.*; 038import com.oracle.graal.lir.asm.*; 039import com.oracle.graal.lir.phases.*; 040import com.oracle.graal.nodes.*; 041import com.oracle.graal.phases.*; 042import com.oracle.graal.phases.tiers.*; 043import com.oracle.nfi.api.*; 044 045public class HotSpotNativeFunctionInterface implements NativeFunctionInterface { 046 047 private final HotSpotProviders providers; 048 private final Backend backend; 049 private final HotSpotNativeLibraryHandle rtldDefault; 050 private final HotSpotNativeFunctionPointer libraryLoadFunctionPointer; 051 private final HotSpotNativeFunctionPointer functionLookupFunctionPointer; 052 private final RawNativeCallNodeFactory factory; 053 054 private HotSpotNativeFunctionHandle libraryLookupFunctionHandle; 055 private HotSpotNativeFunctionHandle dllLookupFunctionHandle; 056 057 public HotSpotNativeFunctionInterface(HotSpotProviders providers, RawNativeCallNodeFactory factory, Backend backend, long dlopen, long dlsym, long rtldDefault) { 058 this.rtldDefault = rtldDefault == HotSpotVMConfig.INVALID_RTLD_DEFAULT_HANDLE ? null : new HotSpotNativeLibraryHandle("RTLD_DEFAULT", rtldDefault); 059 this.providers = providers; 060 assert backend != null; 061 this.backend = backend; 062 this.factory = factory; 063 this.libraryLoadFunctionPointer = new HotSpotNativeFunctionPointer(dlopen, "os::dll_load"); 064 this.functionLookupFunctionPointer = new HotSpotNativeFunctionPointer(dlsym, "os::dll_lookup"); 065 } 066 067 @Override 068 public HotSpotNativeLibraryHandle getLibraryHandle(String libPath) { 069 if (libraryLookupFunctionHandle == null) { 070 libraryLookupFunctionHandle = createHandle(libraryLoadFunctionPointer, long.class, long.class, long.class, int.class); 071 } 072 073 int ebufLen = 1024; 074 // Allocating a single chunk for both the error message buffer and the 075 // file name simplifies deallocation below. 076 long buffer = unsafe.allocateMemory(ebufLen + libPath.length() + 1); 077 long ebuf = buffer; 078 long libPathCString = writeCString(libPath, buffer + ebufLen); 079 try { 080 long handle = (long) libraryLookupFunctionHandle.call(libPathCString, ebuf, ebufLen); 081 if (handle == 0) { 082 throw new UnsatisfiedLinkError(libPath); 083 } 084 return new HotSpotNativeLibraryHandle(libPath, handle); 085 } finally { 086 unsafe.freeMemory(buffer); 087 } 088 } 089 090 @Override 091 public HotSpotNativeFunctionHandle getFunctionHandle(NativeLibraryHandle library, String name, Class<?> returnType, Class<?>... argumentTypes) { 092 HotSpotNativeFunctionPointer functionPointer = lookupFunctionPointer(name, library, false); 093 return createHandle(functionPointer, returnType, argumentTypes); 094 } 095 096 @Override 097 public HotSpotNativeFunctionHandle getFunctionHandle(NativeLibraryHandle[] libraries, String name, Class<?> returnType, Class<?>... argumentTypes) { 098 HotSpotNativeFunctionPointer functionPointer = null; 099 for (NativeLibraryHandle libraryHandle : libraries) { 100 functionPointer = lookupFunctionPointer(name, libraryHandle, false); 101 if (functionPointer != null) { 102 return createHandle(functionPointer, returnType, argumentTypes); 103 } 104 } 105 // Fall back to default library path 106 return getFunctionHandle(name, returnType, argumentTypes); 107 } 108 109 @Override 110 public HotSpotNativeFunctionHandle getFunctionHandle(String name, Class<?> returnType, Class<?>... argumentTypes) { 111 if (rtldDefault == null) { 112 throw new UnsatisfiedLinkError(name); 113 } 114 return getFunctionHandle(rtldDefault, name, returnType, argumentTypes); 115 } 116 117 private HotSpotNativeFunctionPointer lookupFunctionPointer(String name, NativeLibraryHandle library, boolean linkageErrorIfMissing) { 118 if (name == null || library == null) { 119 throw new NullPointerException(); 120 } 121 122 if (dllLookupFunctionHandle == null) { 123 dllLookupFunctionHandle = createHandle(functionLookupFunctionPointer, long.class, long.class, long.class); 124 } 125 long nameCString = createCString(name); 126 try { 127 long functionPointer = (long) dllLookupFunctionHandle.call(((HotSpotNativeLibraryHandle) library).value, nameCString); 128 if (functionPointer == 0L) { 129 if (!linkageErrorIfMissing) { 130 return null; 131 } 132 throw new UnsatisfiedLinkError(name); 133 } 134 return new HotSpotNativeFunctionPointer(functionPointer, name); 135 } finally { 136 unsafe.freeMemory(nameCString); 137 } 138 } 139 140 @Override 141 public HotSpotNativeFunctionHandle getFunctionHandle(NativeFunctionPointer functionPointer, Class<?> returnType, Class<?>... argumentTypes) { 142 if (!(functionPointer instanceof HotSpotNativeFunctionPointer)) { 143 throw new UnsatisfiedLinkError(functionPointer.getName()); 144 } 145 return createHandle(functionPointer, returnType, argumentTypes); 146 } 147 148 private HotSpotNativeFunctionHandle createHandle(NativeFunctionPointer functionPointer, Class<?> returnType, Class<?>... argumentTypes) { 149 HotSpotNativeFunctionPointer hs = (HotSpotNativeFunctionPointer) functionPointer; 150 if (hs != null) { 151 InstalledCode code = installNativeFunctionStub(hs.value, returnType, argumentTypes); 152 return new HotSpotNativeFunctionHandle(code, hs.name, argumentTypes); 153 } else { 154 return null; 155 } 156 } 157 158 /** 159 * Creates and installs a stub for calling a native function. 160 */ 161 private InstalledCode installNativeFunctionStub(long functionPointer, Class<?> returnType, Class<?>... argumentTypes) { 162 StructuredGraph g = getGraph(providers, factory, functionPointer, returnType, argumentTypes); 163 Suites suites = providers.getSuites().createSuites(); 164 LIRSuites lirSuites = providers.getSuites().createLIRSuites(); 165 PhaseSuite<HighTierContext> phaseSuite = backend.getSuites().getDefaultGraphBuilderSuite().copy(); 166 CallingConvention cc = getCallingConvention(providers.getCodeCache(), Type.JavaCallee, g.method(), false); 167 CompilationResult compResult = GraalCompiler.compileGraph(g, cc, g.method(), providers, backend, backend.getTarget(), phaseSuite, OptimisticOptimizations.ALL, 168 DefaultProfilingInfo.get(TriState.UNKNOWN), suites, lirSuites, new CompilationResult(), CompilationResultBuilderFactory.Default); 169 InstalledCode installedCode; 170 try (Scope s = Debug.scope("CodeInstall", providers.getCodeCache(), g.method())) { 171 installedCode = providers.getCodeCache().addMethod(g.method(), compResult, null, null); 172 } catch (Throwable e) { 173 throw Debug.handle(e); 174 } 175 return installedCode; 176 } 177 178 @Override 179 public HotSpotNativeFunctionPointer getFunctionPointer(NativeLibraryHandle[] libraries, String name) { 180 for (NativeLibraryHandle libraryHandle : libraries) { 181 HotSpotNativeFunctionPointer functionPointer = lookupFunctionPointer(name, libraryHandle, false); 182 if (functionPointer != null) { 183 return functionPointer; 184 } 185 } 186 // Fall back to default library path 187 if (rtldDefault == null) { 188 throw new UnsatisfiedLinkError(name); 189 } 190 return lookupFunctionPointer(name, rtldDefault, false); 191 } 192 193 public boolean isDefaultLibrarySearchSupported() { 194 return rtldDefault != null; 195 } 196 197 @Override 198 public NativeFunctionPointer getNativeFunctionPointerFromRawValue(long rawValue) { 199 return new HotSpotNativeFunctionPointer(rawValue, null); 200 } 201}