From d8b723e20208440bf3a483ceb71f30be9373af9f Mon Sep 17 00:00:00 2001 From: Zbynek Slajchrt <zbynek.slajchrt@oracle.com> Date: Tue, 14 Aug 2018 10:02:42 +0200 Subject: [PATCH] Sulong's new lookup mechanism adopted --- .../r/ffi/impl/llvm/TruffleLLVM_Call.java | 13 ++- .../r/ffi/impl/llvm/TruffleLLVM_Context.java | 59 ++++++++++++- .../r/ffi/impl/llvm/TruffleLLVM_DLL.java | 83 +++++++++++++------ .../llvm/TruffleLLVM_DownCallNodeFactory.java | 5 +- .../llvm/TruffleLLVM_UpCallsRFFIImpl.java | 12 ++- .../com/oracle/truffle/r/runtime/ffi/DLL.java | 4 + .../urand/Makefile | 13 ++- mx.fastr/suite.py | 1 + 8 files changed, 153 insertions(+), 37 deletions(-) diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_Call.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_Call.java index c83f50b2f2..e929961913 100644 --- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_Call.java +++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_Call.java @@ -31,10 +31,12 @@ import com.oracle.truffle.api.interop.ForeignAccess; import com.oracle.truffle.api.interop.InteropException; import com.oracle.truffle.api.interop.Message; import com.oracle.truffle.api.interop.TruffleObject; +import com.oracle.truffle.api.interop.UnknownIdentifierException; import com.oracle.truffle.api.nodes.ExplodeLoop; import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.r.ffi.impl.llvm.TruffleLLVM_CallFactory.ToNativeNodeGen; import com.oracle.truffle.r.ffi.impl.llvm.TruffleLLVM_CallFactory.TruffleLLVM_InvokeCallNodeGen; +import com.oracle.truffle.r.ffi.impl.llvm.TruffleLLVM_DLL.LLVM_Handle; import com.oracle.truffle.r.ffi.impl.llvm.upcalls.BytesToNativeCharArrayCall; import com.oracle.truffle.r.ffi.impl.llvm.upcalls.CharSXPToNativeArrayCall; import com.oracle.truffle.r.ffi.impl.upcalls.Callbacks; @@ -46,6 +48,7 @@ import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RScalar; import com.oracle.truffle.r.runtime.data.RVector; import com.oracle.truffle.r.runtime.ffi.CallRFFI; +import com.oracle.truffle.r.runtime.ffi.DLL; import com.oracle.truffle.r.runtime.ffi.FFIUnwrapNode; import com.oracle.truffle.r.runtime.ffi.DLL.SymbolHandle; import com.oracle.truffle.r.runtime.ffi.NativeCallInfo; @@ -95,8 +98,9 @@ final class TruffleLLVM_Call implements CallRFFI { callbacks = (TruffleObject) context.getEnv().asGuestValue(callbacksArray); + LLVM_Handle rdllInfo = (LLVM_Handle) DLL.getRdllInfo().handle; + SymbolHandle setClbkAddrSymbolHandle = new SymbolHandle(rdllInfo.parsedIRs[0].lookup("Rinternals_setCallbacksAddress")); Node setClbkAddrExecuteNode = Message.EXECUTE.createNode(); - SymbolHandle setClbkAddrSymbolHandle = new SymbolHandle(context.getEnv().importSymbol("@" + "Rinternals_setCallbacksAddress")); setCallbacksAddress = setClbkAddrSymbolHandle.asTruffleObject(); // Initialize the callbacks global variable ForeignAccess.sendExecute(setClbkAddrExecuteNode, setCallbacksAddress, context.getEnv().asGuestValue(new TruffleObject[0])); @@ -123,8 +127,13 @@ final class TruffleLLVM_Call implements CallRFFI { public static void initVariables(RContext context) { // must have parsed the variables module in libR + LLVM_Handle rdllInfo = (LLVM_Handle) DLL.getRdllInfo().handle; for (INIT_VAR_FUN initVarFun : INIT_VAR_FUN.values()) { - initVarFun.symbolHandle = new SymbolHandle(context.getEnv().importSymbol("@" + initVarFun.funName)); + try { + initVarFun.symbolHandle = new SymbolHandle(rdllInfo.parsedIRs[0].lookup(initVarFun.funName)); + } catch (UnknownIdentifierException e) { + throw RInternalError.shouldNotReachHere(e); + } } Node executeNode = Message.EXECUTE.createNode(); RFFIVariables[] variables = RFFIVariables.initialize(context); diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_Context.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_Context.java index 2657178aac..66863f8698 100644 --- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_Context.java +++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_Context.java @@ -23,14 +23,25 @@ package com.oracle.truffle.r.ffi.impl.llvm; import java.nio.file.FileSystems; +import java.util.EnumMap; +import com.oracle.truffle.api.CompilerAsserts; +import com.oracle.truffle.api.interop.ForeignAccess; +import com.oracle.truffle.api.interop.Message; import com.oracle.truffle.api.interop.TruffleObject; +import com.oracle.truffle.api.interop.UnknownIdentifierException; +import com.oracle.truffle.api.interop.UnsupportedMessageException; +import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.r.ffi.impl.common.LibPaths; +import com.oracle.truffle.r.ffi.impl.llvm.TruffleLLVM_DLL.LLVM_Handle; +import com.oracle.truffle.r.ffi.impl.llvm.TruffleLLVM_DLL.ParsedLLVM_IR; import com.oracle.truffle.r.runtime.REnvVars; +import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.context.RContext.ContextState; import com.oracle.truffle.r.runtime.ffi.BaseRFFI; import com.oracle.truffle.r.runtime.ffi.DLL; +import com.oracle.truffle.r.runtime.ffi.DLL.DLLInfo; import com.oracle.truffle.r.runtime.ffi.DLLRFFI; import com.oracle.truffle.r.runtime.ffi.LapackRFFI; import com.oracle.truffle.r.runtime.ffi.MiscRFFI; @@ -104,9 +115,53 @@ final class TruffleLLVM_Context extends RFFIContext { callState.beforeDispose(context); } + private final EnumMap<NativeFunction, TruffleObject> nativeFunctions = new EnumMap<>(NativeFunction.class); + @Override public TruffleObject lookupNativeFunction(NativeFunction function) { - Object symValue = RContext.getInstance().getEnv().importSymbol("@" + function.getCallName()); - return (TruffleObject) symValue; + CompilerAsserts.neverPartOfCompilation(); + if (!nativeFunctions.containsKey(function)) { + TruffleObject[] lookupObjects = new TruffleObject[0]; + if (function.getLibrary() == NativeFunction.baseLibrary()) { + TruffleObject lookupObject = (TruffleObject) ((LLVM_Handle) DLL.getRdllInfo().handle).parsedIRs[0].lookupObject; + lookupObjects = new TruffleObject[]{lookupObject}; + } else if (function.getLibrary() == NativeFunction.anyLibrary()) { + DLLInfo dllInfo = DLL.findLibraryContainingSymbol(RContext.getInstance(), function.getCallName()); + if (dllInfo == null) { + throw RInternalError.shouldNotReachHere("Could not find library containing symbol " + function.getCallName()); + } + lookupObjects = getLookupObjects(dllInfo); + } else { + DLLInfo dllInfo = DLL.findLibrary(function.getLibrary()); + if (dllInfo == null) { + throw RInternalError.shouldNotReachHere("Could not find library " + function.getLibrary()); + } + lookupObjects = getLookupObjects(dllInfo); + } + TruffleObject target = null; + final Node lookupNode = Message.READ.createNode(); + for (int i = 0; i < lookupObjects.length; i++) { + try { + target = (TruffleObject) ForeignAccess.sendRead(lookupNode, lookupObjects[i], function.getCallName()); + break; + } catch (UnknownIdentifierException e) { + continue; + } catch (UnsupportedMessageException e) { + RInternalError.shouldNotReachHere(); + } + } + nativeFunctions.put(function, target); + } + return nativeFunctions.get(function); + } + + private static TruffleObject[] getLookupObjects(DLLInfo dllInfo) { + TruffleObject[] lookupObjects; + final ParsedLLVM_IR[] parsedIRs = ((LLVM_Handle) dllInfo.handle).parsedIRs; + lookupObjects = new TruffleObject[parsedIRs.length]; + for (int i = 0; i < parsedIRs.length; i++) { + lookupObjects[i] = (TruffleObject) parsedIRs[i].lookupObject; + } + return lookupObjects; } } diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_DLL.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_DLL.java index 2077369f77..5758125b43 100644 --- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_DLL.java +++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_DLL.java @@ -44,6 +44,11 @@ import java.util.zip.ZipInputStream; import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.interop.ForeignAccess; +import com.oracle.truffle.api.interop.Message; +import com.oracle.truffle.api.interop.TruffleObject; +import com.oracle.truffle.api.interop.UnknownIdentifierException; +import com.oracle.truffle.api.interop.UnsupportedMessageException; import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.source.Source; import com.oracle.truffle.r.runtime.RInternalError; @@ -94,6 +99,7 @@ public class TruffleLLVM_DLL implements DLLRFFI { */ @Override public ContextState initialize(RContext context) { + // TODO: Is it really needed when using the new lookup mechanism? if (!context.isInitial()) { for (LLVM_IR ir : truffleDLL.libRModules) { parseLLVM("libR", ir); @@ -105,8 +111,8 @@ public class TruffleLLVM_DLL implements DLLRFFI { for (DLLInfo dllInfo : loadedDLLs) { if (dllInfo.handle instanceof LLVM_Handle) { LLVM_Handle llvmHandle = (LLVM_Handle) dllInfo.handle; - for (LLVM_IR ir : llvmHandle.irs) { - parseLLVM(llvmHandle.libName, ir); + for (ParsedLLVM_IR parsedIR : llvmHandle.parsedIRs) { + parseLLVM(llvmHandle.libName, parsedIR.ir); } } } @@ -128,14 +134,34 @@ public class TruffleLLVM_DLL implements DLLRFFI { return new ContextStateImpl(); } + static class ParsedLLVM_IR { + final LLVM_IR ir; + final Object lookupObject; + + ParsedLLVM_IR(LLVM_IR ir, Object lookupObject) { + this.ir = ir; + this.lookupObject = lookupObject; + } + + Object lookup(String symbol) throws UnknownIdentifierException { + try { + return ForeignAccess.sendRead(Message.READ.createNode(), (TruffleObject) lookupObject, symbol); + } catch (UnsupportedMessageException e) { + throw RInternalError.shouldNotReachHere(e); + } + } + + } + static class LLVM_Handle { - private final String libName; - private final LLVM_IR[] irs; + final String libName; + final ParsedLLVM_IR[] parsedIRs; - LLVM_Handle(String libName, LLVM_IR[] irs) { + LLVM_Handle(String libName, ParsedLLVM_IR[] irs) { this.libName = libName; - this.irs = irs; + this.parsedIRs = irs; } + } @FunctionalInterface @@ -236,10 +262,13 @@ public class TruffleLLVM_DLL implements DLLRFFI { } else { loadNativeLibs(ar.nativeLibs); } - for (LLVM_IR ir : irs) { - parseLLVM(libName, ir); + ParsedLLVM_IR[] parsedIRs = new ParsedLLVM_IR[irs.length]; + for (int i = 0; i < irs.length; i++) { + LLVM_IR ir = irs[i]; + Object irLookupObject = parseLLVM(libName, ir).call(); + parsedIRs[i] = new ParsedLLVM_IR(ir, irLookupObject); } - return new LLVM_Handle(libName, irs); + return new LLVM_Handle(libName, parsedIRs); } catch (Exception ex) { CompilerDirectives.transferToInterpreter(); StringBuilder sb = new StringBuilder(); @@ -276,15 +305,30 @@ public class TruffleLLVM_DLL implements DLLRFFI { } private static class TruffleLLVM_DLSymNode extends Node implements DLSymNode { + @Child private Node lookupNode = Message.READ.createNode(); + @Override public SymbolHandle execute(Object handle, String symbol) throws UnsatisfiedLinkError { assert handle instanceof LLVM_Handle; - Object symValue = RContext.getInstance().getEnv().importSymbol("@" + symbol); + LLVM_Handle llvmHandle = (LLVM_Handle) handle; + Object symValue = null; + for (int i = 0; i < llvmHandle.parsedIRs.length; i++) { + ParsedLLVM_IR pir = llvmHandle.parsedIRs[i]; + try { + symValue = ForeignAccess.sendRead(lookupNode, (TruffleObject) pir.lookupObject, symbol); + break; + } catch (UnknownIdentifierException e) { + continue; + } catch (UnsupportedMessageException e) { + RInternalError.shouldNotReachHere(); + } + } if (symValue == null) { throw new UnsatisfiedLinkError(); } return new SymbolHandle(symValue); } + } private static class TruffleLLVM_DLCloseNode extends Node implements DLCloseNode { @@ -321,25 +365,10 @@ public class TruffleLLVM_DLL implements DLLRFFI { */ private LLVM_IR[] libRModules; - private static final String[] PARSE_ERRORS = new String[0]; - - private static boolean parseFails(String libName, LLVM_IR ir) { - for (int i = 0; i < PARSE_ERRORS.length / 2; i++) { - String plibName = PARSE_ERRORS[i * 2]; - String pModule = PARSE_ERRORS[i * 2 + 1]; - if (libName.equals(plibName) && ir.name.equals(pModule)) { - return true; - } - } - return false; - } - - private static void parseLLVM(String libName, LLVM_IR ir) { + private static CallTarget parseLLVM(String libName, LLVM_IR ir) { if (ir instanceof LLVM_IR.Binary) { LLVM_IR.Binary bir = (LLVM_IR.Binary) ir; - if (!parseFails(libName, ir)) { - parseBinary(libName, bir); - } + return parseBinary(libName, bir); } else { throw RInternalError.unimplemented("LLVM text IR"); } diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_DownCallNodeFactory.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_DownCallNodeFactory.java index 905e78c7c4..8a3b57d632 100644 --- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_DownCallNodeFactory.java +++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_DownCallNodeFactory.java @@ -23,6 +23,7 @@ package com.oracle.truffle.r.ffi.impl.llvm; import static com.oracle.truffle.r.runtime.ffi.NativeFunction.anyLibrary; +import static com.oracle.truffle.r.runtime.ffi.NativeFunction.baseLibrary; import java.nio.charset.StandardCharsets; @@ -67,7 +68,9 @@ final class TruffleLLVM_DownCallNodeFactory extends DownCallNodeFactory { CompilerAsserts.neverPartOfCompilation(); String library = fn.getLibrary(); DLLInfo dllInfo = null; - if (library != anyLibrary()) { + if (library == baseLibrary()) { + dllInfo = DLL.getRdllInfo(); + } else if (library != anyLibrary()) { dllInfo = DLL.findLibrary(library); } SymbolHandle result = DLL.findSymbol(fn.getCallName(), dllInfo); diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_UpCallsRFFIImpl.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_UpCallsRFFIImpl.java index a7dc6e740a..5e723d35fe 100644 --- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_UpCallsRFFIImpl.java +++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_UpCallsRFFIImpl.java @@ -29,11 +29,11 @@ import com.oracle.truffle.api.interop.TruffleObject; import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.r.ffi.impl.common.JavaUpCallsRFFIImpl; import com.oracle.truffle.r.ffi.impl.common.RFFIUtils; +import com.oracle.truffle.r.ffi.impl.llvm.TruffleLLVM_DLL.LLVM_Handle; import com.oracle.truffle.r.ffi.impl.upcalls.Callbacks; import com.oracle.truffle.r.runtime.REnvVars; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RInternalError; -import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.data.CharSXPWrapper; import com.oracle.truffle.r.runtime.data.RDouble; import com.oracle.truffle.r.runtime.data.RInteger; @@ -42,10 +42,9 @@ import com.oracle.truffle.r.runtime.data.RScalar; import com.oracle.truffle.r.runtime.data.RString; import com.oracle.truffle.r.runtime.data.RTypedValue; import com.oracle.truffle.r.runtime.ffi.DLL; -import com.oracle.truffle.r.runtime.ffi.FFIUnwrapNode; import com.oracle.truffle.r.runtime.ffi.DLL.CEntry; import com.oracle.truffle.r.runtime.ffi.DLL.DLLInfo; -import com.oracle.truffle.r.runtime.ffi.DLL.SymbolHandle; +import com.oracle.truffle.r.runtime.ffi.FFIUnwrapNode; import com.oracle.truffle.r.runtime.ffi.VectorRFFIWrapper; import com.oracle.truffle.r.runtime.ffi.interop.NativeCharArray; @@ -58,7 +57,12 @@ public class TruffleLLVM_UpCallsRFFIImpl extends JavaUpCallsRFFIImpl { private TruffleObject setSymbolHandle; void initialize() { - setSymbolHandle = new SymbolHandle(RContext.getInstance().getEnv().importSymbol("@" + "Rdynload_setSymbol")).asTruffleObject(); + LLVM_Handle rdllInfo = (LLVM_Handle) DLL.getRdllInfo().handle; + try { + setSymbolHandle = (TruffleObject) rdllInfo.parsedIRs[0].lookup("Rdynload_setSymbol"); + } catch (Exception e) { + RInternalError.shouldNotReachHere(e); + } } public Object charSXPToNativeCharArray(Object x) { diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/DLL.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/DLL.java index fb0226d208..44aede9833 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/DLL.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/DLL.java @@ -829,6 +829,10 @@ public class DLL { return null; } + public static DLLInfo getRdllInfo() { + return ContextStateImpl.libRdllInfo; + } + /** * Search for symbol {@code name} in library defined by {@code dllInfo}, or {@code null} for * search in all loaded libraries. Used in the rare cases where no Truffle execution context diff --git a/com.oracle.truffle.r.test.native/urand/Makefile b/com.oracle.truffle.r.test.native/urand/Makefile index cf9282e5b6..fb67e638de 100644 --- a/com.oracle.truffle.r.test.native/urand/Makefile +++ b/com.oracle.truffle.r.test.native/urand/Makefile @@ -43,11 +43,22 @@ C_LIBNAME := liburand.so C_OBJECTS := $(subst $(SRC),$(OBJ),$(C_SOURCES:.c=.o)) C_LIB := $(OBJ)/$(C_LIBNAME) - INCLUDE_DIR := $(NATIVE_PROJECT)/include +ifeq ($(FASTR_RFFI),llvm) + all: $(C_LIB) +else + +C_LIB_LLVM_DUMMY := $(C_LIB)l +all: $(C_LIB) $(C_LIB_LLVM_DUMMY) + +$(C_LIB_LLVM_DUMMY): + touch $(C_LIB_LLVM_DUMMY) + +endif + $(C_LIB): $(OBJ) $(C_OBJECTS) $(DYLIB_LD) $(DYLIB_LDFLAGS) -o $(C_LIB) $(C_OBJECTS) diff --git a/mx.fastr/suite.py b/mx.fastr/suite.py index ac48d796fd..151d71ec30 100644 --- a/mx.fastr/suite.py +++ b/mx.fastr/suite.py @@ -162,6 +162,7 @@ suite = { "output" : "com.oracle.truffle.r.test.native", "results" :[ "urand/lib/liburand.so", + "urand/lib/liburand.sol", ], "workingSets" : "FastR", }, -- GitLab