From 86bcea6011406de21c5c4a6a38bfd4c4ecf71fb8 Mon Sep 17 00:00:00 2001 From: Zbynek Slajchrt <zbynek.slajchrt@oracle.com> Date: Thu, 22 Feb 2018 20:32:35 +0100 Subject: [PATCH] Miscellaneous LLVM-related fixes --- .../ffi/impl/common/JavaUpCallsRFFIImpl.java | 233 ++++++++---------- .../r/ffi/impl/llvm/TruffleLLVM_Call.java | 17 +- .../r/ffi/impl/llvm/TruffleLLVM_Context.java | 4 + .../upcalls/BytesToNativeCharArrayCallMR.java | 1 + .../r/ffi/impl/nodes/DoMakeClassNode.java | 47 ++++ .../r/ffi/impl/nodes/GetClassDefNode.java | 47 ++++ .../ffi/impl/nodes/NativeStringCastNode.java | 66 +++++ .../impl/nodes/NewCustomConnectionNode.java | 37 +-- .../r/ffi/impl/nodes/Str2TypeNode.java | 84 +++++++ .../r/ffi/impl/upcalls/StdUpCallsRFFI.java | 12 +- .../fficall/src/truffle_llvm/Memory.c | 14 +- .../llvm_tools/llvm-ar | 13 +- .../llvm_tools/llvm-c++ | 20 +- .../llvm_tools/llvm-cc | 20 +- .../llvm_tools/llvm-fc | 7 +- .../llvm_tools/llvm-helper | 115 +++++++-- .../r/runtime/data/CharSXPWrapper.java | 1 - .../r/runtime/data/NativeDataAccess.java | 1 + .../truffle/r/runtime/data/RObject.java | 19 +- .../truffle/r/test/generate/FastRSession.java | 4 +- 20 files changed, 536 insertions(+), 226 deletions(-) create mode 100644 com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/DoMakeClassNode.java create mode 100644 com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/GetClassDefNode.java create mode 100644 com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/NativeStringCastNode.java create mode 100644 com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/Str2TypeNode.java 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 c7984a2e49..b219056de0 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 @@ -1869,100 +1826,101 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI { } }); } - } - @MessageResolution(receiverType = VectorWrapper.class) - public static class VectorWrapperMR { + @MessageResolution(receiverType = VectorWrapper.class) + public static class VectorWrapperMR { - @Resolve(message = "IS_POINTER") - public abstract static class IntVectorWrapperNativeIsPointerNode extends Node { - protected Object access(@SuppressWarnings("unused") VectorWrapper receiver) { - return false; + @Resolve(message = "IS_POINTER") + public abstract static class IntVectorWrapperNativeIsPointerNode extends Node { + protected Object access(@SuppressWarnings("unused") VectorWrapper receiver) { + return false; + } } - } - @Resolve(message = "TO_NATIVE") - public abstract static class IntVectorWrapperNativeAsPointerNode extends Node { - protected Object access(VectorWrapper receiver) { - return new VectorWrapperNativePointer(receiver.vector); + @Resolve(message = "TO_NATIVE") + public abstract static class IntVectorWrapperNativeAsPointerNode extends Node { + protected Object access(VectorWrapper receiver) { + return new VectorWrapperNativePointer(receiver.vector); + } } - } - @Resolve(message = "HAS_SIZE") - public abstract static class VectorWrapperHasSizeNode extends Node { - protected Object access(@SuppressWarnings("unused") VectorWrapper receiver) { - return true; + @Resolve(message = "HAS_SIZE") + public abstract static class VectorWrapperHasSizeNode extends Node { + protected Object access(@SuppressWarnings("unused") VectorWrapper receiver) { + return true; + } } - } - @Resolve(message = "GET_SIZE") - public abstract static class VectorWrapperGetSizeNode extends Node { - @Child private Node getSizeMsg = Message.GET_SIZE.createNode(); + @Resolve(message = "GET_SIZE") + public abstract static class VectorWrapperGetSizeNode extends Node { + @Child private Node getSizeMsg = Message.GET_SIZE.createNode(); - protected Object access(VectorWrapper receiver) { - try { - return ForeignAccess.sendGetSize(getSizeMsg, receiver.vector); - } catch (UnsupportedMessageException e) { - throw RInternalError.shouldNotReachHere(e); + protected Object access(VectorWrapper receiver) { + try { + return ForeignAccess.sendGetSize(getSizeMsg, receiver.vector); + } catch (UnsupportedMessageException e) { + throw RInternalError.shouldNotReachHere(e); + } } } - } - @Resolve(message = "READ") - abstract static class VectorWrapperReadNode extends Node { - @Child private Node readMsg = Message.READ.createNode(); + @Resolve(message = "READ") + abstract static class VectorWrapperReadNode extends Node { + @Child private Node readMsg = Message.READ.createNode(); - public Object access(VectorWrapper receiver, Object index) { - try { - return ForeignAccess.sendRead(readMsg, receiver.vector, index); - } catch (UnsupportedMessageException | UnknownIdentifierException e) { - throw RInternalError.shouldNotReachHere(e); + public Object access(VectorWrapper receiver, Object index) { + try { + return ForeignAccess.sendRead(readMsg, receiver.vector, index); + } catch (UnsupportedMessageException | UnknownIdentifierException e) { + throw RInternalError.shouldNotReachHere(e); + } } } - } - @Resolve(message = "WRITE") - abstract static class VectorWrapperWriteNode extends Node { - @Child private Node writeMsg = Message.WRITE.createNode(); + @Resolve(message = "WRITE") + abstract static class VectorWrapperWriteNode extends Node { + @Child private Node writeMsg = Message.WRITE.createNode(); - public Object access(VectorWrapper receiver, Object index, Object value) { - try { - return ForeignAccess.sendWrite(writeMsg, receiver.vector, index, value); - } catch (UnsupportedMessageException | UnknownIdentifierException | UnsupportedTypeException e) { - throw RInternalError.shouldNotReachHere(e); + public Object access(VectorWrapper receiver, Object index, Object value) { + try { + return ForeignAccess.sendWrite(writeMsg, receiver.vector, index, value); + } catch (UnsupportedMessageException | UnknownIdentifierException | UnsupportedTypeException e) { + throw RInternalError.shouldNotReachHere(e); + } } } - } - @Resolve(message = "IS_EXECUTABLE") - abstract static class VectorWrapperIsExecutableNode extends Node { - @Child private Node isExecMsg = Message.IS_EXECUTABLE.createNode(); + @Resolve(message = "IS_EXECUTABLE") + abstract static class VectorWrapperIsExecutableNode extends Node { + @Child private Node isExecMsg = Message.IS_EXECUTABLE.createNode(); - public Object access(VectorWrapper receiver) { - return ForeignAccess.sendIsExecutable(isExecMsg, receiver.vector); + public Object access(VectorWrapper receiver) { + return ForeignAccess.sendIsExecutable(isExecMsg, receiver.vector); + } } - } - - @Resolve(message = "EXECUTE") - abstract static class VectorWrapperExecuteNode extends Node { - @Child private Node execMsg = Message.createExecute(0).createNode(); - protected Object access(VectorWrapper receiver, Object[] arguments) { - try { - // 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); - } catch (UnsupportedMessageException | UnsupportedTypeException | ArityException e) { - throw RInternalError.shouldNotReachHere(e); + @Resolve(message = "EXECUTE") + abstract static class VectorWrapperExecuteNode extends Node { + @Child private Node execMsg = Message.createExecute(0).createNode(); + + protected Object access(VectorWrapper receiver, Object[] arguments) { + try { + // 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); + } catch (UnsupportedMessageException | UnsupportedTypeException | ArityException e) { + throw RInternalError.shouldNotReachHere(e); + } } } - } - @CanResolve - public abstract static class VectorWrapperCheck extends Node { - protected static boolean test(TruffleObject receiver) { - return receiver instanceof VectorWrapper; + @CanResolve + public abstract static class VectorWrapperCheck extends Node { + protected static boolean test(TruffleObject receiver) { + return receiver instanceof VectorWrapper; + } } } } @@ -1973,6 +1931,20 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI { public VectorWrapper(TruffleObject vector) { this.vector = vector; + ((RObject) vector).setNativeWrapper(this); + } + + static Object get(TruffleObject x) { + assert x instanceof RObject; + Object wrapper = ((RObject) x).getNativeWrapper(); + if (wrapper != null) { + return wrapper; + } else { + wrapper = new VectorWrapper(x); + // Establish the 1-1 relationship between the object and its native wrapper + ((RObject) x).setNativeWrapper(wrapper); + return wrapper; + } } public TruffleObject getVector() { @@ -1983,38 +1955,49 @@ 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)); + TruffleObject xto = guaranteeVectorOrNull(x, CharSXPWrapper.class); + if (xto == RNull.instance) { + return xto; + } + CharSXPWrapper chw = (CharSXPWrapper) xto; + return VectorWrapper.get(chw); } @Override 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 1075ab3f63..27448accd6 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_Context.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_Context.java index 65330af2da..c48bb4886a 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 @@ -86,6 +86,10 @@ final class TruffleLLVM_Context extends RFFIContext { String libzPath = LibPaths.getBuiltinLibPath("z"); TruffleLLVM_NativeDLL.NativeDLOpenRootNode.create().getCallTarget().call(libzPath, false, true); + + // String curlPath = LibPaths.getBuiltinLibPath("curl.4"); + String curlPath = "libcurl.dylib"; + TruffleLLVM_NativeDLL.NativeDLOpenRootNode.create().getCallTarget().call(curlPath, false, true); } @Override 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 dc51516b4f..ebefcef623 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 @@ -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 0000000000..1abceefade --- /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 0000000000..05f10669c9 --- /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 0000000000..4c7f70db2c --- /dev/null +++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/NativeStringCastNode.java @@ -0,0 +1,66 @@ +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 dc8e816a7d..6378bf00df 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 0000000000..cbc29c664e --- /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/StdUpCallsRFFI.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/StdUpCallsRFFI.java index 7151f48559..a576084b4f 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/fficall/src/truffle_llvm/Memory.c b/com.oracle.truffle.r.native/fficall/src/truffle_llvm/Memory.c index 1f8079ac75..680d13aaad 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 @@ -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) { diff --git a/com.oracle.truffle.r.native/llvm_tools/llvm-ar b/com.oracle.truffle.r.native/llvm_tools/llvm-ar index 2462ea65ed..2045a4ef82 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 ee6af85450..54c0ef43ed 100755 --- a/com.oracle.truffle.r.native/llvm_tools/llvm-c++ +++ b/com.oracle.truffle.r.native/llvm_tools/llvm-c++ @@ -31,12 +31,22 @@ 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 + #get_llvm_tool + #runit $llvm_tool_bin $llvm_args + echo "Clang args: $llvm_args" + clang --version + clang $llvm_args + + # 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 1d88276ba5..38f1d992b0 100755 --- a/com.oracle.truffle.r.native/llvm_tools/llvm-cc +++ b/com.oracle.truffle.r.native/llvm_tools/llvm-cc @@ -29,15 +29,21 @@ 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 + #llvm_tool=clang + #get_llvm_tool + #runit $llvm_tool_bin $llvm_args + runit clang $llvm_args + # 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 084f68d2df..03bd793753 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 598bb39e40..102283405c 100644 --- a/com.oracle.truffle.r.native/llvm_tools/llvm-helper +++ b/com.oracle.truffle.r.native/llvm_tools/llvm-helper @@ -69,19 +69,19 @@ function analyze_args() { 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 ;; *) ;; @@ -113,9 +113,10 @@ function get_llvm_tool() { function mem2reg_opt() { - llvm_tool="opt" - get_llvm_tool - runit ${llvm_tool_bin} -mem2reg $llvm_ir_file -o ${llvm_ir_file}.opt + #llvm_tool="opt" + #get_llvm_tool + #runit ${llvm_tool_bin} -mem2reg $llvm_ir_file -o ${llvm_ir_file}.opt + runit opt -mem2reg $llvm_ir_file -o ${llvm_ir_file}.opt rc=$? if [ $rc -eq 0 ] then @@ -138,16 +139,19 @@ function create_bc_lib() { case $1 in -o) shift - lib=$1 + lib=$1 + ;; + -*) + # ignore options ;; *) - f=$1 + f=$(basename $1) ext=${f##*.} - if [ $ext == 'o' ] - then - fn=${f%%.*}.bc - bcfiles+="$fn " - fi + if [ $ext == 'o' ] + then + fn="$(dirname $1)/${f%%.*}.bc" + bcfiles+="$fn " + fi ;; esac shift @@ -157,9 +161,68 @@ function create_bc_lib() { # 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 - runit $llvm_tool_bin $bcfiles -o $lib.bc + #llvm_tool=llvm-link + #get_llvm_tool + #runit $llvm_tool_bin $bcfiles -o $lib.bc + echo "Linking $lib.bc with $bcfiles" + runit llvm-link $bcfiles -o $lib.bc runit zip -r $lib $lib.bc 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 + arargs+="$fn " + echo "$(basename $fn) $fullPath" >> $archObjCSVtmp + else + arargs+="$1 " + fi + ;; + esac + shift + done + + sort -d --field-separator=' ' --key=1 $archObjCSVtmp > $archObjCSV + + # 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 +} 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 1f7f724a11..cf4b856b0a 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 970c53a91d..3b404e84df 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 @@ -662,6 +662,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++) { 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 1b3555e35b..c4f8cdc520 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 @@ -25,6 +25,15 @@ package com.oracle.truffle.r.runtime.data; public abstract class RObject { private Object nativeMirror; + /** + * 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; public final void setNativeMirror(Object mirror) { this.nativeMirror = mirror; @@ -33,4 +42,12 @@ public abstract class RObject { public final Object getNativeMirror() { return nativeMirror; } + + public void setNativeWrapper(Object wrapper) { + this.nativeWrapper = wrapper; + } + + public Object getNativeWrapper() { + return this.nativeWrapper; + } } 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 1782f4b2ef..e37ea75380 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 { -- GitLab