diff --git a/ci.hocon b/ci.hocon index f274b102ffab633d0266a478af40497b0283a00e..4c97461fc140d1de63becdf5323cd0dcb8e08801 100644 --- a/ci.hocon +++ b/ci.hocon @@ -146,7 +146,7 @@ gateTestLinuxLLVM : ${common} ${requireGCC} { environment : { TZDIR: "/usr/share/zoneinfo" FASTR_RFFI : "llvm" - FASTR_LLVM_HOME : "$DRAGONEGG_LLVM/bin" + FASTR_LLVM_TOOLS : "$DRAGONEGG_LLVM/bin" FASTR_LLVM_GFORTRAN_LLVM_AS : "$DRAGONEGG_LLVM/bin/llvm-as" FASTR_LLVM_GFORTRAN : "$DRAGONEGG_GCC/bin/gfortran" FASTR_LLVM_DRAGONEGG : "$DRAGONEGG_GCC/lib/dragonegg.so" @@ -192,7 +192,7 @@ gateTestDarwinLLVM: ${common} ${darwinEnvironment} ${requireGCC} { environment : { FASTR_RFFI : "llvm" - FASTR_LLVM_HOME : "$DRAGONEGG_LLVM/bin" + FASTR_LLVM_TOOLS : "$DRAGONEGG_LLVM/bin" FASTR_LLVM_GFORTRAN_LLVM_AS : "$DRAGONEGG_LLVM/bin/llvm-as" FASTR_LLVM_GFORTRAN : "$DRAGONEGG_GCC/bin/gfortran" FASTR_LLVM_DRAGONEGG : "$DRAGONEGG_GCC/lib/dragonegg.so" diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/JavaUpCallsRFFIImpl.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/JavaUpCallsRFFIImpl.java index c7984a2e4953a5c1b80e11efebc6db76bc7f5180..523b80e3b1e3fd1e07026931e2e2f47a1c1caffa 100644 --- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/JavaUpCallsRFFIImpl.java +++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/JavaUpCallsRFFIImpl.java @@ -31,7 +31,6 @@ import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; -import java.util.HashMap; import java.util.IdentityHashMap; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Function; @@ -234,18 +233,14 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI { @Override @TruffleBoundary - public Object R_getClassDef(String clazz) { - String name = "getClassDef"; - RFunction getClass = (RFunction) RContext.getRRuntimeASTAccess().forcePromise(name, REnvironment.getRegisteredNamespace("methods").get(name)); - return RContext.getEngine().evalFunction(getClass, null, RCaller.createInvalid(null), true, null, clazz); + public Object R_getClassDef(Object clazz) { + throw implementedAsNode(); } @Override @TruffleBoundary - public Object R_do_MAKE_CLASS(String clazz) { - String name = "getClass"; - RFunction getClass = (RFunction) RContext.getRRuntimeASTAccess().forcePromise(name, REnvironment.getRegisteredNamespace("methods").get(name)); - return RContext.getEngine().evalFunction(getClass, null, RCaller.createInvalid(null), true, null, clazz); + public Object R_do_MAKE_CLASS(Object clazz) { + throw implementedAsNode(); } @Override @@ -1517,48 +1512,10 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI { } } - private static HashMap<String, Integer> name2typeTable; - - static { - name2typeTable = new HashMap<>(26); - name2typeTable.put("NULL", SEXPTYPE.NILSXP.code); - /* real types */ - name2typeTable.put("symbol", SEXPTYPE.SYMSXP.code); - name2typeTable.put("pairlist", SEXPTYPE.LISTSXP.code); - name2typeTable.put("closure", SEXPTYPE.CLOSXP.code); - name2typeTable.put("environment", SEXPTYPE.ENVSXP.code); - name2typeTable.put("promise", SEXPTYPE.PROMSXP.code); - name2typeTable.put("language", SEXPTYPE.LANGSXP.code); - name2typeTable.put("special", SEXPTYPE.SPECIALSXP.code); - name2typeTable.put("builtin", SEXPTYPE.BUILTINSXP.code); - name2typeTable.put("char", SEXPTYPE.CHARSXP.code); - name2typeTable.put("logical", SEXPTYPE.LGLSXP.code); - name2typeTable.put("integer", SEXPTYPE.INTSXP.code); - name2typeTable.put("double", SEXPTYPE.REALSXP.code); - /*- "real", for R <= 0.61.x */ - name2typeTable.put("complex", SEXPTYPE.CPLXSXP.code); - name2typeTable.put("character", SEXPTYPE.STRSXP.code); - name2typeTable.put("...", SEXPTYPE.DOTSXP.code); - name2typeTable.put("any", SEXPTYPE.ANYSXP.code); - name2typeTable.put("expression", SEXPTYPE.EXPRSXP.code); - name2typeTable.put("list", SEXPTYPE.VECSXP.code); - name2typeTable.put("externalptr", SEXPTYPE.EXTPTRSXP.code); - name2typeTable.put("bytecode", SEXPTYPE.BCODESXP.code); - name2typeTable.put("weakref", SEXPTYPE.WEAKREFSXP.code); - name2typeTable.put("raw", SEXPTYPE.RAWSXP.code); - name2typeTable.put("S4", SEXPTYPE.S4SXP.code); - name2typeTable.put("numeric", SEXPTYPE.REALSXP.code); - name2typeTable.put("name", SEXPTYPE.SYMSXP.code); - } - - @Override - @TruffleBoundary - public int Rf_str2type(String name) { - if (name == null) { - return -1; - } - Integer result = name2typeTable.get(name); - return result != null ? result : -1; + @Override + @TruffleBoundary + public int Rf_str2type(Object name) { + throw implementedAsNode(); } @Override @@ -1949,7 +1906,8 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI { protected Object access(VectorWrapper receiver, Object[] arguments) { try { - // Currently, there is only one "executable" object, which is CharSXPWrapper. + // Currently, there is only one "executable" object, which is + // CharSXPWrapper. // See CharSXPWrapperMR for the EXECUTABLE message handler. assert arguments.length == 0 && receiver.vector instanceof CharSXPWrapper; return ForeignAccess.sendExecute(execMsg, receiver.vector); @@ -1972,7 +1930,22 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI { private final TruffleObject vector; public VectorWrapper(TruffleObject vector) { + assert vector instanceof RObject; this.vector = vector; + NativeDataAccess.setNativeWrapper((RObject) vector, this); + } + + static Object get(TruffleObject x) { + assert x instanceof RObject; + Object wrapper = NativeDataAccess.getNativeWrapper((RObject) x); + if (wrapper != null) { + return wrapper; + } else { + wrapper = new VectorWrapper(x); + // Establish the 1-1 relationship between the object and its native wrapper + NativeDataAccess.setNativeWrapper((RObject) x, wrapper); + return wrapper; + } } public TruffleObject getVector() { @@ -1983,38 +1956,44 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI { public ForeignAccess getForeignAccess() { return VectorWrapperMRForeign.ACCESS; } + + @Override + public int hashCode() { + return vector.hashCode(); + } + } @Override public Object INTEGER(Object x) { // also handles LOGICAL assert x instanceof RIntVector || x instanceof RLogicalVector || x == RNull.instance; - return new VectorWrapper(guaranteeVectorOrNull(x, RVector.class)); + return VectorWrapper.get(guaranteeVectorOrNull(x, RVector.class)); } @Override public Object LOGICAL(Object x) { - return new VectorWrapper(guaranteeVectorOrNull(x, RLogicalVector.class)); + return VectorWrapper.get(guaranteeVectorOrNull(x, RLogicalVector.class)); } @Override public Object REAL(Object x) { - return new VectorWrapper(guaranteeVectorOrNull(x, RDoubleVector.class)); + return VectorWrapper.get(guaranteeVectorOrNull(x, RDoubleVector.class)); } @Override public Object RAW(Object x) { - return new VectorWrapper(guaranteeVectorOrNull(x, RRawVector.class)); + return VectorWrapper.get(guaranteeVectorOrNull(x, RRawVector.class)); } @Override public Object COMPLEX(Object x) { - return new VectorWrapper(guaranteeVectorOrNull(x, RComplexVector.class)); + return VectorWrapper.get(guaranteeVectorOrNull(x, RComplexVector.class)); } @Override public Object R_CHAR(Object x) { - return new VectorWrapper(guaranteeVectorOrNull(x, CharSXPWrapper.class)); + return VectorWrapper.get(guaranteeVectorOrNull(x, CharSXPWrapper.class)); } @Override diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/package-info.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/package-info.java index 19ebc60087b43aa9e717c0a82e3ff6f7027e67be..fc661a180f319a6b2b04c8bccec9318a9bd04788 100644 --- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/package-info.java +++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -23,10 +23,5 @@ /** * A collection of types and {@link com.oracle.truffle.api.interop.MessageResolution} classes that * support the implementations. - * - * See {@link com.oracle.truffle.r.ffi.impl.interop.base} and - * {@link com.oracle.truffle.r.ffi.impl.interop.pcre} for similar classes specific to the - * {@link com.oracle.truffle.r.runtime.ffi.BaseRFFI} and - * {@link com.oracle.truffle.r.runtime.ffi.PCRERFFI} interfaces. */ package com.oracle.truffle.r.ffi.impl.interop; 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 1075ab3f6368df16c2638431abd54e1193c5e20b..27448accd62d39405390e1353a3fe5ea079a1d5f 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 @@ -41,6 +41,7 @@ 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; import com.oracle.truffle.r.ffi.impl.upcalls.FFIUnwrapNode; +import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.context.RContext; @@ -162,12 +163,12 @@ final class TruffleLLVM_Call implements CallRFFI { @Specialization protected static Object convert(int value) { - return RDataFactory.createIntVector(new int[]{value}, RRuntime.isNA(value)); + return RDataFactory.createIntVector(new int[]{value}, !RRuntime.isNA(value)); } @Specialization protected static Object convert(double value) { - return RDataFactory.createDoubleVector(new double[]{value}, RRuntime.isNA(value)); + return RDataFactory.createDoubleVector(new double[]{value}, !RRuntime.isNA(value)); } @Specialization @@ -182,12 +183,12 @@ final class TruffleLLVM_Call implements CallRFFI { @Specialization protected static Object convert(byte value) { - return RDataFactory.createLogicalVector(new byte[]{value}, RRuntime.isNA(value)); + return RDataFactory.createLogicalVector(new byte[]{value}, !RRuntime.isNA(value)); } @Specialization protected static Object convert(String value) { - return RDataFactory.createStringVector(new String[]{value}, RRuntime.isNA(value)); + return RDataFactory.createStringVector(new String[]{value}, !RRuntime.isNA(value)); } @Fallback @@ -259,6 +260,14 @@ final class TruffleLLVM_Call implements CallRFFI { return result; } catch (InteropException ex) { throw RInternalError.shouldNotReachHere(ex); + } catch (Exception ex) { + if (ex.getCause() instanceof RError) { + // Sulong wraps an error having occurred in an upcall, so let's propagate the + // wrapped one instead of the Sulong one. + throw (RError) ex.getCause(); + } else { + throw ex; + } } finally { RContext.getRForeignAccessFactory().setIsNull(isNullSetting); } 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 568b273a72b0de402d520a02798a4940a67f643b..f934408376f508f80b0035af089d84c9f1622f2f 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 @@ -23,14 +23,22 @@ package com.oracle.truffle.r.ffi.impl.llvm; import java.io.BufferedInputStream; +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; +import java.io.InputStreamReader; import java.io.PrintStream; import java.nio.file.FileSystems; import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; @@ -39,6 +47,8 @@ import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.source.Source; import com.oracle.truffle.r.runtime.RInternalError; +import com.oracle.truffle.r.runtime.RPlatform; +import com.oracle.truffle.r.runtime.RPlatform.OSInfo; import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.context.RContext.ContextState; import com.oracle.truffle.r.runtime.ffi.DLL; @@ -63,6 +73,18 @@ import com.oracle.truffle.r.runtime.ffi.DLLRFFI; * */ public class TruffleLLVM_DLL implements DLLRFFI { + /* + * The LIBS file, which is included in the LLVM archive, enumerates native dynamic libraries to + * be linked with the LLVM library in the archive. + */ + private static final String LIBS = "LIBS"; + + private static final Set<String> ignoredNativeLibs = new HashSet<>(); + static { + ignoredNativeLibs.add("Rblas"); + ignoredNativeLibs.add("Rlapack"); + } + static class ContextStateImpl implements RContext.ContextState { /** * When a new {@link RContext} is created we have to re-parse the libR modules, @@ -121,7 +143,19 @@ public class TruffleLLVM_DLL implements DLLRFFI { boolean match(String name); } - public static LLVM_IR[] getZipLLVMIR(String path) { + public static final class LLVMArchive { + public final LLVM_IR[] irs; + public final List<String> nativeLibs; + + private LLVMArchive(LLVM_IR[] irs, List<String> nativeLibs) { + super(); + this.irs = irs; + this.nativeLibs = nativeLibs; + } + } + + public static LLVMArchive getZipLLVMIR(String path) { + List<String> nativeLibs = Collections.emptyList(); try (ZipInputStream zis = new ZipInputStream(new BufferedInputStream(new FileInputStream(path)))) { ArrayList<LLVM_IR> irList = new ArrayList<>(); while (true) { @@ -130,24 +164,28 @@ public class TruffleLLVM_DLL implements DLLRFFI { break; } int size = (int) entry.getSize(); - byte[] bc = new byte[size]; + byte[] bytes = new byte[size]; int n; int totalRead = 0; - while (totalRead < size && (n = zis.read(bc, totalRead, size - totalRead)) != -1) { + while (totalRead < size && (n = zis.read(bytes, totalRead, size - totalRead)) != -1) { totalRead += n; } + if (LIBS.equals(entry.getName())) { + nativeLibs = getNativeLibs(bytes); + continue; + } Path zipName = Paths.get(entry.getName()); String name = zipName.getFileName().toString(); int ix = name.indexOf('.'); if (ix > 0) { name = name.substring(0, ix); } - LLVM_IR.Binary ir = new LLVM_IR.Binary(name, bc); + LLVM_IR.Binary ir = new LLVM_IR.Binary(name, bytes); irList.add(ir); // debugging if (System.getenv("FASTR_LLVM_DEBUG") != null) { try (FileOutputStream bs = new FileOutputStream(Paths.get("tmpzip", name).toString())) { - bs.write(bc); + bs.write(bytes); } try (PrintStream bs = new PrintStream(new FileOutputStream(Paths.get("tmpb64", name).toString()))) { bs.print(ir.base64); @@ -156,13 +194,24 @@ public class TruffleLLVM_DLL implements DLLRFFI { } LLVM_IR[] result = new LLVM_IR[irList.size()]; irList.toArray(result); - return result; + return new LLVMArchive(result, nativeLibs); } catch (IOException ex) { // not a zip file return null; } } + private static List<String> getNativeLibs(byte[] bytes) throws IOException { + List<String> libs = new LinkedList<>(); + try (BufferedReader libReader = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(bytes)))) { + String lib = null; + while ((lib = libReader.readLine()) != null) { + libs.add(lib); + } + } + return libs; + } + private static class TruffleLLVM_DLOpenNode extends Node implements DLOpenNode { @Child private TruffleLLVM_NativeDLL.TruffleLLVM_NativeDLOpen nativeDLLOpenNode; @@ -175,7 +224,8 @@ public class TruffleLLVM_DLL implements DLLRFFI { @Override public Object execute(String path, boolean local, boolean now) { try { - LLVM_IR[] irs = getZipLLVMIR(path); + LLVMArchive ar = getZipLLVMIR(path); + LLVM_IR[] irs = ar.irs; if (irs == null) { return tryOpenNative(path, local, now); } @@ -183,6 +233,8 @@ public class TruffleLLVM_DLL implements DLLRFFI { if (libName.equals("libR")) { // save for new RContexts truffleDLL.libRModules = irs; + } else { + loadNativeLibs(ar.nativeLibs); } for (LLVM_IR ir : irs) { parseLLVM(libName, ir); @@ -199,10 +251,22 @@ public class TruffleLLVM_DLL implements DLLRFFI { sb.append(t.getMessage()); t = t.getCause(); } + ex.printStackTrace(); throw new UnsatisfiedLinkError(sb.toString()); } } + private void loadNativeLibs(List<String> nativeLibs) { + OSInfo osInfo = RPlatform.getOSInfo(); + for (String nativeLib : nativeLibs) { + if (ignoredNativeLibs.contains(nativeLib)) { + continue; + } + String nativeLibName = "lib" + nativeLib + "." + osInfo.libExt; + tryOpenNative(nativeLibName, false, true); + } + } + private long tryOpenNative(String path, boolean local, boolean now) throws UnsatisfiedLinkError { if (nativeDLLOpenNode == null) { nativeDLLOpenNode = insert(new TruffleLLVM_NativeDLL.TruffleLLVM_NativeDLOpen()); 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 d6a1f4b67f5d8153fc01a3d1bf6abb775ef4b247..ad6eed382d4b3c7322dc5fbefc3d4fddc11ec70c 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 @@ -40,6 +40,7 @@ import com.oracle.truffle.r.runtime.data.RDouble; import com.oracle.truffle.r.runtime.data.RInteger; import com.oracle.truffle.r.runtime.data.RLogical; 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.DLL.CEntry; @@ -108,6 +109,8 @@ public class TruffleLLVM_UpCallsRFFIImpl extends JavaUpCallsRFFIImpl { return RInteger.valueOf((int) x); } else if (x instanceof Byte) { return RLogical.valueOf((byte) x); + } else if (x instanceof String) { + return RString.valueOf((String) x); } else { throw RInternalError.shouldNotReachHere(); } diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/tools/ShowLLVMIR.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/tools/ShowLLVMIR.java index 91acc85892f4595697ed8dc15351271b23478039..a606291213ba4c953413408904d4b63850e00cdb 100644 --- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/tools/ShowLLVMIR.java +++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/tools/ShowLLVMIR.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2018, 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 @@ -28,6 +28,7 @@ import java.io.OutputStream; import com.oracle.truffle.r.ffi.impl.llvm.LLVM_IR; import com.oracle.truffle.r.ffi.impl.llvm.TruffleLLVM_DLL; +import com.oracle.truffle.r.ffi.impl.llvm.TruffleLLVM_DLL.LLVMArchive; import com.oracle.truffle.r.runtime.ProcessOutputManager; public class ShowLLVMIR { @@ -64,7 +65,8 @@ public class ShowLLVMIR { usage(); } try { - LLVM_IR[] irs = TruffleLLVM_DLL.getZipLLVMIR(objPath); + LLVMArchive ar = TruffleLLVM_DLL.getZipLLVMIR(objPath); + LLVM_IR[] irs = ar.irs; if (irs == null) { System.out.printf("no llvm ir in %s\n", objPath); System.exit(1); diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/upcalls/BytesToNativeCharArrayCallMR.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/upcalls/BytesToNativeCharArrayCallMR.java index dc51516b4fccfc8c95208324e32a5781c659ed12..96e7f6e18b8d8a2fc17ed4597feaf5211878d49b 100644 --- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/upcalls/BytesToNativeCharArrayCallMR.java +++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/upcalls/BytesToNativeCharArrayCallMR.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -30,6 +30,7 @@ import com.oracle.truffle.api.nodes.Node; @MessageResolution(receiverType = BytesToNativeCharArrayCall.class) public class BytesToNativeCharArrayCallMR { + @Resolve(message = "EXECUTE") public abstract static class BytesToNativeCharArrayCallExecute extends Node { protected java.lang.Object access(BytesToNativeCharArrayCall receiver, Object[] arguments) { diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/DoMakeClassNode.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/DoMakeClassNode.java new file mode 100644 index 0000000000000000000000000000000000000000..1abceefaded81c425d756a971bee4a98a59e020b --- /dev/null +++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/DoMakeClassNode.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2018, 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.truffle.r.ffi.impl.nodes; + +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.dsl.Cached; +import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.r.runtime.RCaller; +import com.oracle.truffle.r.runtime.context.RContext; +import com.oracle.truffle.r.runtime.data.RFunction; +import com.oracle.truffle.r.runtime.env.REnvironment; + +public abstract class DoMakeClassNode extends FFIUpCallNode.Arg1 { + + public static DoMakeClassNode create() { + return DoMakeClassNodeGen.create(); + } + + @Specialization + @TruffleBoundary + Object handleString(Object cls, @Cached("create()") NativeStringCastNode nscn) { + String clazz = nscn.executeObject(cls); + String name = "getClass"; + RFunction getClass = (RFunction) RContext.getRRuntimeASTAccess().forcePromise(name, REnvironment.getRegisteredNamespace("methods").get(name)); + return RContext.getEngine().evalFunction(getClass, null, RCaller.createInvalid(null), true, null, clazz); + } +} diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/GetClassDefNode.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/GetClassDefNode.java new file mode 100644 index 0000000000000000000000000000000000000000..05f10669c977a2aa5206913e784749c7f3064553 --- /dev/null +++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/GetClassDefNode.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2018, 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.truffle.r.ffi.impl.nodes; + +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.dsl.Cached; +import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.r.runtime.RCaller; +import com.oracle.truffle.r.runtime.context.RContext; +import com.oracle.truffle.r.runtime.data.RFunction; +import com.oracle.truffle.r.runtime.env.REnvironment; + +public abstract class GetClassDefNode extends FFIUpCallNode.Arg1 { + + public static GetClassDefNode create() { + return GetClassDefNodeGen.create(); + } + + @Specialization + @TruffleBoundary + Object handleString(Object cls, @Cached("create()") NativeStringCastNode nscn) { + String clazz = nscn.executeObject(cls); + String name = "getClassDef"; + RFunction getClass = (RFunction) RContext.getRRuntimeASTAccess().forcePromise(name, REnvironment.getRegisteredNamespace("methods").get(name)); + return RContext.getEngine().evalFunction(getClass, null, RCaller.createInvalid(null), true, null, clazz); + } +} diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/NativeStringCastNode.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/NativeStringCastNode.java new file mode 100644 index 0000000000000000000000000000000000000000..92d7e734174965433a9a453dff0308b3106c4968 --- /dev/null +++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/NativeStringCastNode.java @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2018, 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.truffle.r.ffi.impl.nodes; + +import static com.oracle.truffle.r.runtime.data.NativeDataAccess.readNativeString; + +import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.dsl.Cached; +import com.oracle.truffle.api.dsl.Specialization; +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.UnsupportedMessageException; +import com.oracle.truffle.api.nodes.Node; +import com.oracle.truffle.r.runtime.RInternalError; + +public abstract class NativeStringCastNode extends Node { + + @Child private Node isPtrNode; + + public static NativeStringCastNode create() { + return NativeStringCastNodeGen.create(); + } + + public abstract String executeObject(Object s); + + @Specialization + @TruffleBoundary + String handleString(String s) { + return s; + } + + protected static Node createAsPointerNode() { + return Message.AS_POINTER.createNode(); + } + + protected static Node createToNativeNode() { + return Message.TO_NATIVE.createNode(); + } + + protected boolean isPointerNode(TruffleObject s) { + if (isPtrNode == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + isPtrNode = insert(Message.IS_POINTER.createNode()); + } + return ForeignAccess.sendIsPointer(isPtrNode, s); + } + + @Specialization(guards = "isPointerNode(s)") + String handlePointerAddress(TruffleObject s, @Cached("createAsPointerNode()") Node sAsPtrNode) { + try { + return readNativeString(ForeignAccess.sendAsPointer(sAsPtrNode, s)); + } catch (UnsupportedMessageException e) { + throw RInternalError.shouldNotReachHere(e); + } + } + + @Specialization(guards = "!isPointerNode(s)") + String handleNonPointerAddress(TruffleObject s, @Cached("createToNativeNode()") Node sToNativeNode, @Cached("createAsPointerNode()") Node sAsPtrNode) { + try { + Object sNative = ForeignAccess.sendToNative(sToNativeNode, s); + return readNativeString(ForeignAccess.sendAsPointer(sAsPtrNode, (TruffleObject) sNative)); + } catch (UnsupportedMessageException e) { + throw RInternalError.shouldNotReachHere(e); + } + } +} diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/NewCustomConnectionNode.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/NewCustomConnectionNode.java index dc8e816a7d5ae6cf967e8facb8c3683e1b13f0c8..6378bf00df6df13562e6ff0e3f66194cd0bfb477 100644 --- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/NewCustomConnectionNode.java +++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/NewCustomConnectionNode.java @@ -22,19 +22,11 @@ */ package com.oracle.truffle.r.ffi.impl.nodes; -import static com.oracle.truffle.r.runtime.data.NativeDataAccess.readNativeString; - import java.io.IOException; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Specialization; -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.UnsupportedMessageException; -import com.oracle.truffle.api.nodes.Node; -import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.conn.ConnectionSupport.InvalidConnection; import com.oracle.truffle.r.runtime.conn.NativeConnections.NativeRConnection; import com.oracle.truffle.r.runtime.data.RExternalPtr; @@ -47,36 +39,11 @@ public abstract class NewCustomConnectionNode extends FFIUpCallNode.Arg4 { @Specialization @TruffleBoundary - Object handleStrings(String description, String mode, String className, RExternalPtr connAddr) { - try { - return new NativeRConnection(description, mode, className, connAddr).asVector(); - } catch (IOException e) { - return InvalidConnection.instance.asVector(); - } - } - - protected static Node createAsPointerNode() { - return Message.AS_POINTER.createNode(); - } - - @Specialization - @TruffleBoundary - Object handleAddresses(TruffleObject description, TruffleObject mode, TruffleObject className, RExternalPtr connAddr, - @Cached("createAsPointerNode()") Node descriptionAsPtrNode, @Cached("createAsPointerNode()") Node modeAsPtrNode, @Cached("createAsPointerNode()") Node classNameAsPtrNode) { - try { - return handleAddresses(ForeignAccess.sendAsPointer(descriptionAsPtrNode, description), ForeignAccess.sendAsPointer(modeAsPtrNode, mode), - ForeignAccess.sendAsPointer(classNameAsPtrNode, className), connAddr); - } catch (UnsupportedMessageException e) { - throw RInternalError.shouldNotReachHere(e); - } - } - - private static Object handleAddresses(long description, long mode, long className, RExternalPtr connAddr) { + Object handleStrings(Object description, Object mode, Object className, RExternalPtr connAddr, @Cached("create()") NativeStringCastNode nscn) { try { - return new NativeRConnection(readNativeString(description), readNativeString(mode), readNativeString(className), connAddr).asVector(); + return new NativeRConnection(nscn.executeObject(description), nscn.executeObject(mode), nscn.executeObject(className), connAddr).asVector(); } catch (IOException e) { return InvalidConnection.instance.asVector(); } } - } diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/Str2TypeNode.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/Str2TypeNode.java new file mode 100644 index 0000000000000000000000000000000000000000..cbc29c664e479ce754ebd79f06161476eb6e0200 --- /dev/null +++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/Str2TypeNode.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2018, 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.truffle.r.ffi.impl.nodes; + +import java.util.HashMap; + +import com.oracle.truffle.api.dsl.Cached; +import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.nodes.Node; +import com.oracle.truffle.r.runtime.gnur.SEXPTYPE; + +public abstract class Str2TypeNode extends FFIUpCallNode.Arg1 { + + private static HashMap<String, Integer> name2typeTable; + + static { + name2typeTable = new HashMap<>(26); + name2typeTable.put("NULL", SEXPTYPE.NILSXP.code); + /* real types */ + name2typeTable.put("symbol", SEXPTYPE.SYMSXP.code); + name2typeTable.put("pairlist", SEXPTYPE.LISTSXP.code); + name2typeTable.put("closure", SEXPTYPE.CLOSXP.code); + name2typeTable.put("environment", SEXPTYPE.ENVSXP.code); + name2typeTable.put("promise", SEXPTYPE.PROMSXP.code); + name2typeTable.put("language", SEXPTYPE.LANGSXP.code); + name2typeTable.put("special", SEXPTYPE.SPECIALSXP.code); + name2typeTable.put("builtin", SEXPTYPE.BUILTINSXP.code); + name2typeTable.put("char", SEXPTYPE.CHARSXP.code); + name2typeTable.put("logical", SEXPTYPE.LGLSXP.code); + name2typeTable.put("integer", SEXPTYPE.INTSXP.code); + name2typeTable.put("double", SEXPTYPE.REALSXP.code); + /*- "real", for R <= 0.61.x */ + name2typeTable.put("complex", SEXPTYPE.CPLXSXP.code); + name2typeTable.put("character", SEXPTYPE.STRSXP.code); + name2typeTable.put("...", SEXPTYPE.DOTSXP.code); + name2typeTable.put("any", SEXPTYPE.ANYSXP.code); + name2typeTable.put("expression", SEXPTYPE.EXPRSXP.code); + name2typeTable.put("list", SEXPTYPE.VECSXP.code); + name2typeTable.put("externalptr", SEXPTYPE.EXTPTRSXP.code); + name2typeTable.put("bytecode", SEXPTYPE.BCODESXP.code); + name2typeTable.put("weakref", SEXPTYPE.WEAKREFSXP.code); + name2typeTable.put("raw", SEXPTYPE.RAWSXP.code); + name2typeTable.put("S4", SEXPTYPE.S4SXP.code); + name2typeTable.put("numeric", SEXPTYPE.REALSXP.code); + name2typeTable.put("name", SEXPTYPE.SYMSXP.code); + } + + @Child private Node clazzIsPtrNode; + + public static Str2TypeNode create() { + return Str2TypeNodeGen.create(); + } + + @Specialization + Object handleString(Object n, @Cached("create()") NativeStringCastNode sc) { + String name = sc.executeObject(n); + if (name == null) { + return -1; + } + Integer result = name2typeTable.get(name); + return result != null ? result : -1; + } + +} diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/FFIWrapNode.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/FFIWrapNode.java index 115713fabac830b3415f1a145e1abde714fb6d5a..e6d51dbe8cf31523fe99b9882a4e1a984b8691ac 100644 --- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/FFIWrapNode.java +++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/FFIWrapNode.java @@ -38,6 +38,7 @@ import com.oracle.truffle.r.runtime.data.RRaw; import com.oracle.truffle.r.runtime.data.RScalarList; import com.oracle.truffle.r.runtime.data.RScalarVector; import com.oracle.truffle.r.runtime.data.RSequence; +import com.oracle.truffle.r.runtime.data.RString; public abstract class FFIWrapNode extends Node { @@ -63,6 +64,11 @@ public abstract class FFIWrapNode extends Node { return wrap(RDataFactory.createStringVectorFromScalar(value)); } + @Specialization + protected static Object wrap(RString value) { + return wrap(RDataFactory.createStringVectorFromScalar(value.getValue())); + } + @Specialization protected static Object wrap(RInteger value) { return wrap(RDataFactory.createIntVectorFromScalar(value.getValue())); diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/StdUpCallsRFFI.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/StdUpCallsRFFI.java index 7151f48559114fb8d46b16b17ced7a418ab8e13e..a576084b4f92e967c536c75f70d17c849d4f3745 100644 --- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/StdUpCallsRFFI.java +++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/StdUpCallsRFFI.java @@ -32,7 +32,9 @@ import com.oracle.truffle.r.ffi.impl.nodes.AttributesAccessNodes.GetAttrib; import com.oracle.truffle.r.ffi.impl.nodes.AttributesAccessNodes.TAG; import com.oracle.truffle.r.ffi.impl.nodes.CoerceNodes.CoerceVectorNode; import com.oracle.truffle.r.ffi.impl.nodes.CoerceNodes.VectorToPairListNode; +import com.oracle.truffle.r.ffi.impl.nodes.DoMakeClassNode; import com.oracle.truffle.r.ffi.impl.nodes.DuplicateNodes; +import com.oracle.truffle.r.ffi.impl.nodes.GetClassDefNode; import com.oracle.truffle.r.ffi.impl.nodes.EnvNodes.LockBindingNode; import com.oracle.truffle.r.ffi.impl.nodes.EnvNodes.UnlockBindingNode; import com.oracle.truffle.r.ffi.impl.nodes.ListAccessNodes.CAARNode; @@ -57,6 +59,7 @@ import com.oracle.truffle.r.ffi.impl.nodes.NewCustomConnectionNode; import com.oracle.truffle.r.ffi.impl.nodes.RMakeExternalPtrNode; import com.oracle.truffle.r.ffi.impl.nodes.RandFunctionsNodes; import com.oracle.truffle.r.ffi.impl.nodes.RfEvalNode; +import com.oracle.truffle.r.ffi.impl.nodes.Str2TypeNode; import com.oracle.truffle.r.ffi.impl.nodes.TryRfEvalNode; import com.oracle.truffle.r.ffi.processor.RFFICpointer; import com.oracle.truffle.r.ffi.processor.RFFICstring; @@ -111,9 +114,11 @@ public interface StdUpCallsRFFI { void Rf_defineVar(Object symbolArg, Object value, Object envArg); - Object R_getClassDef(@RFFICstring String clazz); + @RFFIUpCallNode(GetClassDefNode.class) + Object R_getClassDef(@RFFICstring(convert = false) Object clazz); - Object R_do_MAKE_CLASS(@RFFICstring String clazz); + @RFFIUpCallNode(DoMakeClassNode.class) + Object R_do_MAKE_CLASS(@RFFICstring(convert = false) Object clazz); @RFFIUpCallNode(MiscNodes.RDoNewObjectNode.class) Object R_do_new_object(Object classDef); @@ -403,7 +408,8 @@ public interface StdUpCallsRFFI { Object R_MethodsNamespace(); - int Rf_str2type(@RFFICstring String name); + @RFFIUpCallNode(Str2TypeNode.class) + int Rf_str2type(@RFFICstring(convert = false) Object name); int FASTR_getConnectionChar(Object obj); diff --git a/com.oracle.truffle.r.native/Makefile b/com.oracle.truffle.r.native/Makefile index 514fd0857f73d08e6155749f40f68344b75049ce..159c2720d3a39a7032180944bd783e3d5d77db06 100644 --- a/com.oracle.truffle.r.native/Makefile +++ b/com.oracle.truffle.r.native/Makefile @@ -1,5 +1,5 @@ # -# Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2014, 2018, 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 @@ -21,7 +21,7 @@ # questions. # -.PHONY: all clean +.PHONY: all clean export TOPDIR = $(CURDIR) export FASTR_R_HOME=$(abspath $(TOPDIR)/..) @@ -30,6 +30,15 @@ export FASTR_NATIVE_DIR = $(TOPDIR) export R_VERSION = 3.4.0 export GNUR_HOME = $(TOPDIR)/gnur/patch-build +ifeq ($(FASTR_RFFI),llvm) +ifndef FASTR_LLVM_TOOLS +ifdef FASTR_LLVM_FOR_DRAGONEGG_HOME +export FASTR_LLVM_TOOLS = $(FASTR_LLVM_FOR_DRAGONEGG_HOME)/bin +$(info FASTR_LLVM_TOOLS set to $(FASTR_LLVM_TOOLS)) +endif +endif +endif + $(info R_VERSION: $(R_VERSION)) $(info GNUR_HOME: $(GNUR_HOME)) @@ -43,7 +52,7 @@ $(info GNUR_HOME_BINARY not set. Assuming the default location at $(GNUR_HOME_BI endif # Completely accurate dependency analysis is very difficult for this project, so use a version number -# to force a clean build, and elsewhere use sentinels to avoid rebuilding when we can't compute the +# to force a clean build, and elsewhere use sentinels to avoid rebuilding when we can't compute the # dependencies accurately. all: checkversion @@ -54,7 +63,7 @@ all: checkversion $(MAKE) -C run cp version.source version.built -clean: +clean: $(MAKE) -C include clean $(MAKE) -C fficall clean $(MAKE) -C run clean diff --git a/com.oracle.truffle.r.native/fficall/Makefile b/com.oracle.truffle.r.native/fficall/Makefile index f6176fd2d0aa5d3f78ee729487b1dfa2c7a38ecf..e6e0b6a202f5e7ebfec8c341944fe6501e0b5d8d 100644 --- a/com.oracle.truffle.r.native/fficall/Makefile +++ b/com.oracle.truffle.r.native/fficall/Makefile @@ -57,7 +57,7 @@ ifeq ($(FASTR_RFFI),managed) else ifeq ($(OS_NAME),Darwin) $(DYLIB_LD) $(DYLIB_LDFLAGS) -Wl,-rpath,@loader_path/ -o $(R_LIB) $(wildcard lib/*.o) -L$(FASTR_LIB_DIR) -ldl -lRblas -lRlapack -lpcre -lz $(VERSION_FLAGS) -ifneq ($(FASTR_RFFI),llvm) +ifneq ($(FASTR_RFFI),llvm) install_name_tool -change libRblas.dylib @rpath/libRblas.dylib $(R_LIB) install_name_tool -change libRlapack.dylib @rpath/libRlapack.dylib $(R_LIB) install_name_tool -id @rpath/libR.dylib $(R_LIB) @@ -80,6 +80,7 @@ fficall.done: common.done else ifeq ($(FASTR_RFFI),llvm) +export R_PACKAGE_DIR="lib" fficall.done: common.done $(MAKE) -C src/truffle_llvm all touch fficall.done @@ -90,7 +91,7 @@ endif #nfi endif #managed common.done: - $(MAKE) -C src/common all + $(MAKE) -C src/common all touch common.done clean: @@ -109,4 +110,3 @@ endif rm -rf $(R_LIB) rm -rf fficall.done rm -rf common.done - diff --git a/com.oracle.truffle.r.native/fficall/src/common/rffi_upcalls.h b/com.oracle.truffle.r.native/fficall/src/common/rffi_upcalls.h index 307b1d2fcd52091e8055fa8d94262cfc8684ea77..1a6bc2c49b7a21559098ea7126a3d1a70ec9c902 100644 --- a/com.oracle.truffle.r.native/fficall/src/common/rffi_upcalls.h +++ b/com.oracle.truffle.r.native/fficall/src/common/rffi_upcalls.h @@ -288,9 +288,7 @@ typedef Rboolean (*call_Rf_NonNullStringMatch)(SEXP s, SEXP t); typedef SEXP (*call_getvar)(); typedef SEXP (*call_R_ParseVector)(SEXP text, int n, SEXP srcFile); typedef SEXPTYPE (*call_Rf_str2type)(const char *s); -typedef SEXP (*call_CLOENV)(SEXP closure); typedef SEXP (*call_octsize)(SEXP size); -typedef void (*call_Rf_PrintValue)(SEXP x); // connections diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_llvm/Memory.c b/com.oracle.truffle.r.native/fficall/src/truffle_llvm/Memory.c index 1f8079ac7515c46a009fe93d244ab87af3d2020d..734c99bdd75b19f40c5ac23027972176eedcb324 100644 --- a/com.oracle.truffle.r.native/fficall/src/truffle_llvm/Memory.c +++ b/com.oracle.truffle.r.native/fficall/src/truffle_llvm/Memory.c @@ -5,7 +5,7 @@ * * Copyright (c) 1995-2015, The R Core Team * Copyright (c) 2003, The R Foundation - * Copyright (c) 2015, 2017, Oracle and/or its affiliates + * Copyright (c) 2015, 2018, Oracle and/or its affiliates * * All rights reserved. */ @@ -19,22 +19,25 @@ // The table of transient objects that have been allocated dur the current FFI call static void **tMemTable; // hwm of tMemTable -static int tMemTableIndex; +static int tMemTableIndex = -1; static int tMemTableLength; void *R_chk_calloc(size_t nelem, size_t elsize); // Memory that is auto-reclaimed across FFI calls char *R_alloc(size_t n, int size) { + tMemTableIndex++; void *p = R_chk_calloc(n, size); if (tMemTableIndex >= tMemTableLength) { - int newLength = 2 * tMemTableLength; + int newLength = tMemTableLength == 0 ? 1 : 2 * tMemTableLength; void *newtMemTable = malloc(sizeof(void*) * newLength); if (newtMemTable == NULL) { fatalError("malloc failure"); } - memcpy(newtMemTable, tMemTable, tMemTableLength * sizeof(void*)); - free(tMemTable); + if (tMemTableLength > 0) { + memcpy(newtMemTable, tMemTable, tMemTableLength * sizeof(void*)); + free(tMemTable); + } tMemTable = newtMemTable; tMemTableLength = newLength; } @@ -54,9 +57,10 @@ char* S_realloc(char *p, long a, long b, int size) { void allocExit() { int i; - for (i = 0; i < tMemTableIndex; i++) { + for (i = 0; i <= tMemTableIndex; i++) { free(tMemTable[i]); } + tMemTableIndex = 0; } void *R_chk_calloc(size_t nelem, size_t elsize) { @@ -116,4 +120,3 @@ SEXP Rf_allocS4Object() { unimplemented("Rf_allocS4Object unimplemented"); return NULL; } - diff --git a/com.oracle.truffle.r.native/gnur/patch/src/library/Makefile b/com.oracle.truffle.r.native/gnur/patch/src/library/Makefile index 7c53c00be0dd72304ec050614f070433a4c29214..6861f1ebc71f116b02a5461391cfce1a6ad9fbfd 100644 --- a/com.oracle.truffle.r.native/gnur/patch/src/library/Makefile +++ b/com.oracle.truffle.r.native/gnur/patch/src/library/Makefile @@ -1,5 +1,5 @@ # -# Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2014, 2018, 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 @@ -25,6 +25,7 @@ SUBDIRS = base compiler datasets utils grDevices graphics grid parallel splines stats stats4 methods tools export FASTR_LIBRARY_DIR = $(abspath $(TOPDIR)/../library) +export R_PACKAGE_DIR="." all: libdir make_subdirs @@ -39,6 +40,6 @@ clean_subdirs: for dir in $(SUBDIRS); do \ $(MAKE) PACKAGE=$$dir -C $$dir clean || exit 1; \ done - + libdir: mkdir -p $(FASTR_LIBRARY_DIR) diff --git a/com.oracle.truffle.r.native/gnur/patch/src/library/stats/Makefile b/com.oracle.truffle.r.native/gnur/patch/src/library/stats/Makefile index 20981356dc097eca04fb87403d78872f5ff8c180..ed0b9d2ac4dced1d261355f019cbb3d9b048894a 100644 --- a/com.oracle.truffle.r.native/gnur/patch/src/library/stats/Makefile +++ b/com.oracle.truffle.r.native/gnur/patch/src/library/stats/Makefile @@ -1,5 +1,5 @@ # -# Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2014, 2018, 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 @@ -33,5 +33,4 @@ endif PKG_LIBS := $(LAPACK_LIBS) $(BLAS_LIBS) -L$(FASTR_LIB_DIR) $(FLIBS) PKG_INCLUDES = -I src - include ../lib.mk diff --git a/com.oracle.truffle.r.native/llvm_tools/llvm-ar b/com.oracle.truffle.r.native/llvm_tools/llvm-ar index 2462ea65edb0de5e818c42ebd2f05d7cb4263696..2045a4ef823ca58a12b1c07b6892882f551b0739 100755 --- a/com.oracle.truffle.r.native/llvm_tools/llvm-ar +++ b/com.oracle.truffle.r.native/llvm_tools/llvm-ar @@ -25,13 +25,6 @@ SOURCE="$0" DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" -while [[ $# -gt 0 ]] -do - f=`basename $1` - ext=${f##*.} - if [ $ext == 'o' ] - then - echo $1 >> $R_PACKAGE_DIR/libobjects - fi - shift -done +. $DIR/llvm-helper + +create_bc_archive $@ diff --git a/com.oracle.truffle.r.native/llvm_tools/llvm-c++ b/com.oracle.truffle.r.native/llvm_tools/llvm-c++ index ee6af85450f4d49ce68115f66c972da8fd3e8db7..ec93f97e3d15ef4168b0221b2e714401f2ef4b28 100755 --- a/com.oracle.truffle.r.native/llvm_tools/llvm-c++ +++ b/com.oracle.truffle.r.native/llvm_tools/llvm-c++ @@ -31,12 +31,23 @@ analyze_args "$@" if [ $is_link -eq 1 ] then - extraObj=`cat $R_PACKAGE_DIR/libobjects` + extraObj="" + if [ -f "$R_PACKAGE_DIR/libobjects" ]; then + extraObj=`cat "$R_PACKAGE_DIR/libobjects"` + fi create_bc_lib $@ $extraObj else llvm_tool=clang++ get_llvm_tool + unamestr=`uname` + if [[ "$unamestr" == 'Linux' ]]; then + llvm_args="-stdlib=libc++ -I/usr/include/libcxxabi $llvm_args" + fi runit $llvm_tool_bin $llvm_args - mem2reg_opt - fake_obj + + # the llvm_ir_file is empty if the result is sent to stdout + if [ -n "$llvm_ir_file" ]; then + mem2reg_opt + fake_obj + fi fi diff --git a/com.oracle.truffle.r.native/llvm_tools/llvm-cc b/com.oracle.truffle.r.native/llvm_tools/llvm-cc index 1d88276ba548d5963757f5e6d168930e76822097..42acf7a3271e7f3dc4c266c76d8928ce8940ae91 100755 --- a/com.oracle.truffle.r.native/llvm_tools/llvm-cc +++ b/com.oracle.truffle.r.native/llvm_tools/llvm-cc @@ -29,15 +29,20 @@ DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" fortran=0 analyze_args "$@" - if [ $is_link -eq 1 ] then - extraObj=`cat $R_PACKAGE_DIR/libobjects` + extraObj="" + if [ -f "$R_PACKAGE_DIR/libobjects" ]; then + extraObj=`cat "$R_PACKAGE_DIR/libobjects"` + fi create_bc_lib $@ $extraObj else llvm_tool=clang get_llvm_tool runit $llvm_tool_bin $llvm_args - mem2reg_opt - fake_obj + # the llvm_ir_file is empty if the result is sent to stdout + if [ -n "$llvm_ir_file" ]; then + mem2reg_opt + fake_obj + fi fi diff --git a/com.oracle.truffle.r.native/llvm_tools/llvm-fc b/com.oracle.truffle.r.native/llvm_tools/llvm-fc index 084f68d2df945ab446df70d3df1a56f090f34770..03bd793753a3789d904cdb23a54af2d4c1d759e6 100755 --- a/com.oracle.truffle.r.native/llvm_tools/llvm-fc +++ b/com.oracle.truffle.r.native/llvm_tools/llvm-fc @@ -59,5 +59,8 @@ ll_to_bc runit $FASTR_LLVM_GFORTRAN_LLVM_AS $llvm_ir_file -o $llvm_ir_bc_file runit rm $llvm_ir_file llvm_ir_file=$llvm_ir_bc_file -mem2reg_opt -fake_obj +# the llvm_ir_file is empty if the result is sent to stdout +if [ -n "$llvm_ir_file" ]; then + mem2reg_opt + fake_obj +fi diff --git a/com.oracle.truffle.r.native/llvm_tools/llvm-helper b/com.oracle.truffle.r.native/llvm_tools/llvm-helper index 598bb39e4058d6469a6d9d94fb69e5e0af4cb252..2f06ecefc74eeeb388e7254d19e9f884609e2195 100644 --- a/com.oracle.truffle.r.native/llvm_tools/llvm-helper +++ b/com.oracle.truffle.r.native/llvm_tools/llvm-helper @@ -62,26 +62,26 @@ function analyze_args() { is_link=0 llvm_ir_file="" - + while [[ $# -gt 0 ]] do llvm_args+="$1 " case $1 in -o) shift - p=$1 - f=`basename $p` - d=`dirname $p` - ext=${f##*.} - if [ $ext == 'so' ] || [ $ext == 'dylib' ] - then - is_link=1 - elif [ $ext == 'o' ] - then - llvm_ir_file=${d}/${f%%.*} - llvm_ir_file+=$llvm_file_ext - llvm_args+="$llvm_ir_file " - fi + p=$1 + f=`basename $p` + d=`dirname $p` + ext=${f##*.} + if [ $ext == 'so' ] || [ $ext == 'dylib' ] + then + is_link=1 + elif [ $ext == 'o' ] + then + llvm_ir_file=${d}/${f%%.*} + llvm_ir_file+=$llvm_file_ext + llvm_args+="$llvm_ir_file " + fi ;; *) ;; @@ -96,9 +96,9 @@ function analyze_args() { # path to tool (defaults to plain ${llvm_tool}, assumed to be on the PATH) function get_llvm_tool() { - if [ -n "${FASTR_LLVM_HOME}" ] + if [ -n "${FASTR_LLVM_TOOLS}" ] then - llvm_tool_bin=${FASTR_LLVM_HOME}/${llvm_tool} + llvm_tool_bin=${FASTR_LLVM_TOOLS}/${llvm_tool} else llvm_tool_uc=`echo ${llvm_tool} | tr /a-z/ /A-Z/ | tr /+/ /P/` x=FASTR_LLVM_${llvm_tool_uc} @@ -111,7 +111,6 @@ function get_llvm_tool() { fi } - function mem2reg_opt() { llvm_tool="opt" get_llvm_tool @@ -126,40 +125,118 @@ function mem2reg_opt() { function fake_obj() { f=`basename $llvm_ir_file` d=`dirname $llvm_ir_file` - runit touch ${d}/${f%%.*}.o + runit touch ${d}/${f%%.*}.o } # Input: all the arguments to the original command line function create_bc_lib() { bcfiles="" lib="" + statlibs="$R_PACKAGE_DIR/statlibs" + linkedLibs="LIBS" + > $linkedLibs while [[ $# -gt 0 ]] do case $1 in -o) shift - lib=$1 - ;; + lib=$1 + ;; + -l*) + linkedLib=`echo $1 | cut -c 3-` + statLibFound='0' + if [ -f "$statlibs" ]; then + statLibFound=`cat "$statlibs" | grep "lib${linkedLib}.a" | wc -l` + fi + if [ $statLibFound == '0' ] + then + echo $linkedLib >> $linkedLibs + fi + ;; + -*) + # ignore other options + ;; + *) + f=$(basename $1) + ext=${f##*.} + if [ $ext == 'o' ] + then + fn="$(dirname $1)/${f%%.*}.bc" + bcfiles+="$fn " + fi + ;; + esac + shift + done + +# we do not have the luxury of controlling the name of the entry (unlike in python) +# it will be the pathname, which we will reduce to a module name on input in FastR + +# link the bitcode files into a single one using llvm-link before zipping it + llvm_tool=llvm-link + get_llvm_tool + echo "Linking $lib.bc from LLVM modules: $bcfiles" + runit $llvm_tool_bin $bcfiles -o $lib.bc + runit zip -r $lib $lib.bc $linkedLibs + rm $lib.bc +} + +# It appends objects constituting a static library to the list of extra object files. +# This list is maintained in $R_PACKAGE_DIR/libobjects and is later read in llvm-cc and +# llvm-c++ to append the object files from the list to other objects when making +# the package dynamic library. This mechanism is a workaround for the fact that the llvm +# linker does not support linking to static libraries, as the standard linker does +# through the -l and -L options. +function create_bc_archive() { + + # Create a CSV file containing all object files constituting the archive (i.e. the static library). + # The CSV has two columns: the object name in the archive and the full path of the object file. + # The object name columns serves as the join column when joining with the set of unique + # symbols objects (see below) to get the final list of objects to be linked with + # the package dynamic library in the end. + shift + archname=$1 + arargs="rcs $archname " + shift + + archObjCSVtmp="archived_objects.tmp" + archObjCSV="archived_objects.csv" + exportedObjCSV="exported_objects.csv" + > $archObjCSV + + while [[ $# -gt 0 ]] + do + case $1 in *) f=$1 ext=${f##*.} if [ $ext == 'o' ] then + fullPath=`echo $(cd $(dirname $1) && pwd -P)/$(basename $1)` fn=${f%%.*}.bc - bcfiles+="$fn " + arargs+="$fn " + echo "$(basename $fn) $fullPath" >> $archObjCSVtmp + else + arargs+="$1 " fi ;; esac shift done -# we do not have the luxury of controlling the name of the entry (unlike in python) -# it will be the pathname, which we will reduce to a module name on input in FastR + sort -d --field-separator=' ' --key=1 $archObjCSVtmp > $archObjCSV -# link the bitcode files into a single one using llvm-link before zipping it - llvm_tool=llvm-link - get_llvm_tool - runit $llvm_tool_bin $bcfiles -o $lib.bc - runit zip -r $lib $lib.bc - rm $lib.bc + # Create the archive (via llvm-ar) that is then used to read the symbol table via llvm-nm. + # The symbol table allows for selecting a set of objects exporting unique symbols. + llvm-ar $arargs + + # This command extracts a set of objects from the archive that do not export duplicate symbols + llvm-nm -print-file-name $archname | grep "\-\-\-\-" | awk -F ' ' '{print $1" "$4}' | sort -d --field-separator=' ' --key=2 -u | awk -F ':' '{print $2}' | sort -d -u > $exportedObjCSV + + # Join the archived objects CSV with the unique symbols objects CSV to get the list of objects to be statically linked to the package dynamic library. + # Append the result to the global list of extra object files. + join -t " " -1 1 -2 1 $archObjCSV $exportedObjCSV | awk -F ' ' '{print $2}' >> "$R_PACKAGE_DIR/libobjects" + + # Record the archive (static library) name to distinguish between LLVM static libs and native libs when linking (via -l) + echo $archname >> "$R_PACKAGE_DIR/statlibs" } diff --git a/com.oracle.truffle.r.native/run/edMakeconf.etc.llvm b/com.oracle.truffle.r.native/run/edMakeconf.etc.llvm index d9a5864d77d6d0115a2d5ab58a250f6e39a18487..c4972785f1b97ace17efcf41e7d9d36f203e2910 100644 --- a/com.oracle.truffle.r.native/run/edMakeconf.etc.llvm +++ b/com.oracle.truffle.r.native/run/edMakeconf.etc.llvm @@ -8,6 +8,11 @@ d i CXX = $(R_HOME)/bin/llvm-c++ . +/^CXX11 =/ +d +i +CXX11 = $(R_HOME)/bin/llvm-c++ +. /^FC =/ d i diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/CharSXPWrapper.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/CharSXPWrapper.java index 1f7f724a112834a8b6167f6033fd92acd594c93b..cf4b856b0a456b684d605d25c2fb3a05fdcec023 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/CharSXPWrapper.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/CharSXPWrapper.java @@ -41,7 +41,6 @@ import com.oracle.truffle.r.runtime.RRuntime; */ public final class CharSXPWrapper extends RObject implements RTruffleObject { private static final CharSXPWrapper NA = new CharSXPWrapper(RRuntime.STRING_NA); - private String contents; private byte[] bytes; diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/NativeDataAccess.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/NativeDataAccess.java index 970c53a91db9977ee5094312eddea7c689293683..09b82c05c43a5a1e6f9dbf57cceae1b0c579f59b 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/NativeDataAccess.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/NativeDataAccess.java @@ -114,6 +114,16 @@ public final class NativeDataAccess { */ private long length; + /** + * It maintains the <code>1-?</code> relationship between this object and its native wrapper + * through which the native code accesses it. For instance, Sulong implements the "pointer" + * equality of two objects that are not pointers (i.e. <code>IS_POINTER</code> returns + * <code>false</code>) as the reference equality of the objects. It follows that the pointer + * comparison would fail if the same <code>RObject</code> instance were wrapped by two + * different native wrappers. + */ + private Object nativeWrapper; + NativeMirror() { this.id = counter.incrementAndGet(); } @@ -204,8 +214,8 @@ public final class NativeDataAccess { if (arg instanceof RObject) { RObject obj = (RObject) arg; NativeMirror mirror = (NativeMirror) obj.getNativeMirror(); - if (mirror == null) { - mirror = putMirrorObject(arg, obj); + if (mirror == null || mirror.id == 0) { + mirror = putMirrorObject(arg, obj, mirror); } return mirror.id; } @@ -213,16 +223,19 @@ public final class NativeDataAccess { } @TruffleBoundary - private static NativeMirror putMirrorObject(Object arg, RObject obj) { - NativeMirror mirror; - obj.setNativeMirror(mirror = arg instanceof CustomNativeMirror ? new NativeMirror(((CustomNativeMirror) arg).getCustomMirrorAddress()) : new NativeMirror()); + private static NativeMirror putMirrorObject(Object arg, RObject obj, NativeMirror oldMirror) { + NativeMirror newMirror; + obj.setNativeMirror(newMirror = arg instanceof CustomNativeMirror ? new NativeMirror(((CustomNativeMirror) arg).getCustomMirrorAddress()) : new NativeMirror()); + if (oldMirror != null) { + newMirror.nativeWrapper = oldMirror.nativeWrapper; + } // System.out.println(String.format("adding %16x = %s", mirror.id, // obj.getClass().getSimpleName())); - nativeMirrors.put(mirror.id, new WeakReference<>(obj)); + nativeMirrors.put(newMirror.id, new WeakReference<>(obj)); if (TRACE_MIRROR_ALLOCATION_SITES) { - registerAllocationSite(arg, mirror); + registerAllocationSite(arg, newMirror); } - return mirror; + return newMirror; } @TruffleBoundary @@ -662,6 +675,7 @@ public final class NativeDataAccess { return mirror.dataAddress; } + @TruffleBoundary public static String readNativeString(long addr) { int len; for (len = 0; UnsafeAdapter.UNSAFE.getByte(addr + len) != 0; len++) { @@ -691,4 +705,23 @@ public final class NativeDataAccess { mirror.length = length; } + + public static void setNativeWrapper(RObject obj, Object wrapper) { + NativeMirror mirror = (NativeMirror) obj.getNativeMirror(); + if (mirror == null) { + mirror = new NativeMirror(0); + obj.setNativeMirror(mirror); + } + mirror.nativeWrapper = wrapper; + } + + public static Object getNativeWrapper(RObject obj) { + NativeMirror mirror = (NativeMirror) obj.getNativeMirror(); + if (mirror == null) { + return null; + } else { + return mirror.nativeWrapper; + } + } + } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RObject.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RObject.java index 1b3555e35bade73c1fea251848d3169a5205df5d..d80f67f4bfb92aa100155117965e7870442e499f 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RObject.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RObject.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2018, 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 @@ -33,4 +33,5 @@ public abstract class RObject { public final Object getNativeMirror() { return nativeMirror; } + } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPairList.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPairList.java index e3be9c96ea3e37a40fd7df240ff2bfbe95fa3640..8ba6f70a6a9a78a99fd0fcf5609becef434cf1af 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPairList.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPairList.java @@ -390,6 +390,9 @@ public final class RPairList extends RSharingAttributeStorage implements RAbstra @Override public RPairList next() { + if (plt instanceof RLanguage) { + plt = ((RLanguage) plt).getPairList(); + } assert plt instanceof RPairList; RPairList curr = (RPairList) plt; plt = curr.cdr; diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/generate/FastRSession.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/generate/FastRSession.java index 1782f4b2ef57276d7ccc638f17c53ac1acb80cd1..e37ea7538097fd365f84645c4c9845dbbe46919e 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/generate/FastRSession.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/generate/FastRSession.java @@ -134,7 +134,7 @@ public final class FastRSession implements RSession { ChildContextInfo ctx = ChildContextInfo.create(params, env, contextKind, contextKind == ContextKind.SHARE_NOTHING ? null : mainRContext, input, output, output); RContext.childInfo = ctx; - return Context.newBuilder("R").engine(mainEngine).build(); + return Context.newBuilder("R", "llvm").engine(mainEngine).build(); } private FastRSession() { @@ -154,7 +154,7 @@ public final class FastRSession implements RSession { ChildContextInfo info = ChildContextInfo.create(params, null, ContextKind.SHARE_NOTHING, null, input, output, output); RContext.childInfo = info; mainEngine = Engine.newBuilder().in(input).out(output).err(output).build(); - mainContext = Context.newBuilder("R").engine(mainEngine).build(); + mainContext = Context.newBuilder("R", "llvm").engine(mainEngine).build(); mainRContext = mainContext.eval(GET_CONTEXT).asHostObject(); } finally { try { diff --git a/documentation/dev/truffle_llvm_ffi.md b/documentation/dev/truffle_llvm_ffi.md index c0cbb908c0ec77477037ff3386533ea9fb05fa80..bff8c9114a7b862b5262873317c8832898a08391 100644 --- a/documentation/dev/truffle_llvm_ffi.md +++ b/documentation/dev/truffle_llvm_ffi.md @@ -65,7 +65,7 @@ FastR necessarily provides very fine control over the versions of the llvm tools The tools needed to build FastR and to install packages containing native code are `clang`, `clang++` and `opt`. Precisely which versions of these tools are used can be controlled in two ways. -1. Set `FASTR_LLVM_HOME` to a directory containing the tools, named as above. N.B. Since MacPorts uses names of the form `clang-mp-3.8` this requires using symbolic links. E.g. create a directory called, say, `llvm-3.8` and symlink to the MacPorts binary, e.g., `clang-mp-3.8` and name it as `clang`. Then set `FASTR_LLVM_HOME` to that directory. +1. Set `FASTR_LLVM_TOOLS` to a directory containing the tools, named as above. N.B. Since MacPorts uses names of the form `clang-mp-3.8` this requires using symbolic links. E.g. create a directory called, say, `llvm-3.8` and symlink to the MacPorts binary, e.g., `clang-mp-3.8` and name it as `clang`. Then set `FASTR_LLVM_TOOLS` to that directory. 2. Set `FASTR_LLVM_CLANG`, `FASTR_LLVM_CLANGPP` and `FASTR_LLVM_OPT` to the actual binary images, e.g., `export FASTR_LLVM_CLANG=/opt/local/bin/clang-mp-3.8`. Not all versions of the llvm tools can compile FastR. `clang-3.2` that is downloaded as part of the DragonEgg build is known to work. This currently is placed in `sulong/cache/tools/llvm/bin` by the DragonEgg build and, again, can be copied to a shared location. `clang-3.8` and `clang-4.0` are known not to work, but `clang-3.9` does.