diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/TruffleCallHelper.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/TruffleCallHelper.java index 420b4218e7b55c868b73c880a4fd5a45476be0e4..64126ff2c7de51b08f2db0ef561c15ee636b5510 100644 --- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/TruffleCallHelper.java +++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/TruffleCallHelper.java @@ -31,6 +31,8 @@ import com.oracle.truffle.r.engine.interop.NativeDoubleArray; import com.oracle.truffle.r.engine.interop.NativeIntegerArray; import com.oracle.truffle.r.engine.interop.NativeLogicalArray; import com.oracle.truffle.r.engine.interop.NativeRawArray; +import com.oracle.truffle.r.nodes.ffi.RFFIUtils; +import com.oracle.truffle.r.nodes.ffi.UpCallsRFFIImpl; import com.oracle.truffle.r.runtime.REnvVars; import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.data.RDataFactory; @@ -42,14 +44,13 @@ import com.oracle.truffle.r.runtime.data.RScalar; import com.oracle.truffle.r.runtime.data.RTypedValue; import com.oracle.truffle.r.runtime.data.RUnboundValue; import com.oracle.truffle.r.runtime.ffi.CharSXPWrapper; -import com.oracle.truffle.r.runtime.ffi.JavaUpCallsRFFI; /** * A wrapper class that can be instantiated and export for method lookup. For now just delegates to - * {@link JavaUpCallsRFFI}. + * {@link UpCallsRFFIImpl}. * */ -public class TruffleCallHelper extends JavaUpCallsRFFI { +public class TruffleCallHelper extends UpCallsRFFIImpl { private static TruffleCallHelper singleton; private static TruffleObject singletonTruffleObject; @@ -62,7 +63,7 @@ public class TruffleCallHelper extends JavaUpCallsRFFI { } public Object charSXPToNativeCharArray(Object x) { - CharSXPWrapper chars = guaranteeInstanceOf(x, CharSXPWrapper.class); + CharSXPWrapper chars = RFFIUtils.guaranteeInstanceOf(x, CharSXPWrapper.class); return new NativeCharArray(chars.getContents().getBytes()); } diff --git a/com.oracle.truffle.r.native/fficall/src/common/coerce_fastr.c b/com.oracle.truffle.r.native/fficall/src/common/coerce_fastr.c index a49307a11779bc2093e0410ad88ebc71d4a5f449..2e0b2fe4c58d3d1fc3eb9390f065138dd297030a 100644 --- a/com.oracle.truffle.r.native/fficall/src/common/coerce_fastr.c +++ b/com.oracle.truffle.r.native/fficall/src/common/coerce_fastr.c @@ -6,7 +6,7 @@ * Copyright (c) 1995, 1996, 1997 Robert Gentleman and Ross Ihaka * Copyright (c) 1995-2014, The R Core Team * Copyright (c) 2002-2008, The R Foundation - * Copyright (c) 2015, 2016, Oracle and/or its affiliates + * Copyright (c) 2015, 2017, Oracle and/or its affiliates * * All rights reserved. */ @@ -425,38 +425,3 @@ SEXP Rf_coerceVector(SEXP v, SEXPTYPE type) #undef COERCE_ERROR -double Rf_asReal(SEXP x) -{ - int warn = 0; - double res; - - if (isVectorAtomic(x) && XLENGTH(x) >= 1) { - switch (TYPEOF(x)) { - case LGLSXP: - res = RealFromLogical(LOGICAL(x)[0], &warn); - CoercionWarning(warn); - return res; - case INTSXP: - res = RealFromInteger(INTEGER(x)[0], &warn); - CoercionWarning(warn); - return res; - case REALSXP: - return REAL(x)[0]; - case CPLXSXP: - res = RealFromComplex(COMPLEX(x)[0], &warn); - CoercionWarning(warn); - return res; - case STRSXP: - res = RealFromString(STRING_ELT(x, 0), &warn); - CoercionWarning(warn); - return res; - default: - UNIMPLEMENTED_TYPE("asReal", x); - } - } else if(TYPEOF(x) == CHARSXP) { - res = RealFromString(x, &warn); - CoercionWarning(warn); - return res; - } - return NA_REAL; -} diff --git a/com.oracle.truffle.r.native/fficall/src/jni/Parse.c b/com.oracle.truffle.r.native/fficall/src/jni/Parse.c index 233a58dbc129066a73b9a1cb364bc7cffde33b1a..723290cfea319d97cce90c45762f13087bd4ed28 100644 --- a/com.oracle.truffle.r.native/fficall/src/jni/Parse.c +++ b/com.oracle.truffle.r.native/fficall/src/jni/Parse.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2017, 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 @@ -31,7 +31,7 @@ static jfieldID parseExprFieldID; void init_parse(JNIEnv *env) { parseMethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_ParseVector", "(Ljava/lang/Object;ILjava/lang/Object;)Ljava/lang/Object;", 0); - parseResultClass = checkFindClass(env, "com/oracle/truffle/r/runtime/ffi/ParseResult"); + parseResultClass = checkFindClass(env, "com/oracle/truffle/r/nodes/ffi/ParseResult"); parseStatusFieldID = checkGetFieldID(env, parseResultClass, "parseStatus", "I", 0); parseExprFieldID = checkGetFieldID(env, parseResultClass, "expr", "Ljava/lang/Object;", 0); } diff --git a/com.oracle.truffle.r.native/fficall/src/jni/Rinternals.c b/com.oracle.truffle.r.native/fficall/src/jni/Rinternals.c index 540621ad1600f0694ab8c21c598f3fbe7efd6dcf..bfa6afc5257d824d9321e3269b5779d99cebf2d4 100644 --- a/com.oracle.truffle.r.native/fficall/src/jni/Rinternals.c +++ b/com.oracle.truffle.r.native/fficall/src/jni/Rinternals.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2017, 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 @@ -90,7 +90,7 @@ static jmethodID STRING_ELT_MethodID; static jmethodID VECTOR_ELT_MethodID; static jmethodID LENGTH_MethodID; static jmethodID Rf_asIntegerMethodID; -//static jmethodID Rf_asRealMethodID; +static jmethodID Rf_asRealMethodID; static jmethodID Rf_asCharMethodID; static jmethodID Rf_mkCharLenCEMethodID; static jmethodID Rf_asLogicalMethodID; @@ -195,7 +195,7 @@ void init_internals(JNIEnv *env) { VECTOR_ELT_MethodID = checkGetMethodID(env, UpCallsRFFIClass, "VECTOR_ELT", "(Ljava/lang/Object;I)Ljava/lang/Object;", 0); LENGTH_MethodID = checkGetMethodID(env, UpCallsRFFIClass, "LENGTH", "(Ljava/lang/Object;)I", 0); Rf_asIntegerMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_asInteger", "(Ljava/lang/Object;)I", 0); -// Rf_asRealMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_asReal", "(Ljava/lang/Object;)D", 0); + Rf_asRealMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_asReal", "(Ljava/lang/Object;)D", 0); Rf_asCharMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_asChar", "(Ljava/lang/Object;)Ljava/lang/Object;", 0); Rf_mkCharLenCEMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_mkCharLenCE", "([BI)Ljava/lang/Object;", 0); Rf_asLogicalMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_asLogical", "(Ljava/lang/Object;)I", 0); @@ -1246,11 +1246,11 @@ int Rf_asInteger(SEXP x) { return (*thisenv)->CallIntMethod(thisenv, UpCallsRFFIObject, Rf_asIntegerMethodID, x); } -//double Rf_asReal(SEXP x) { -// TRACE(TARGp, x); -// JNIEnv *thisenv = getEnv(); -// return (*thisenv)->CallDoubleMethod(thisenv, UpCallsRFFIObject, Rf_asRealMethodID, x); -//} +double Rf_asReal(SEXP x) { + TRACE(TARGp, x); + JNIEnv *thisenv = getEnv(); + return (*thisenv)->CallDoubleMethod(thisenv, UpCallsRFFIObject, Rf_asRealMethodID, x); +} Rcomplex Rf_asComplex(SEXP x){ unimplemented("Rf_asLogical"); diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/AsCharNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/AsCharNode.java new file mode 100644 index 0000000000000000000000000000000000000000..95b124519c139f21b75544d9bd0ed43123c65a5b --- /dev/null +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/AsCharNode.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2014, 2017, 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.nodes.ffi; + +import com.oracle.truffle.api.dsl.Cached; +import com.oracle.truffle.api.dsl.Fallback; +import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.dsl.TypeSystemReference; +import com.oracle.truffle.r.nodes.unary.CastStringNode; +import com.oracle.truffle.r.runtime.RInternalError; +import com.oracle.truffle.r.runtime.RRuntime; +import com.oracle.truffle.r.runtime.data.RSymbol; +import com.oracle.truffle.r.runtime.data.RTypesFlatLayout; +import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; +import com.oracle.truffle.r.runtime.ffi.CharSXPWrapper; + +@TypeSystemReference(RTypesFlatLayout.class) +public abstract class AsCharNode extends FFIUpCallNode.Arg1 { + private static final CharSXPWrapper CharSXPWrapper_NA = CharSXPWrapper.create(RRuntime.STRING_NA); + + @Specialization + protected CharSXPWrapper asChar(CharSXPWrapper obj) { + return obj; + } + + @Specialization + protected CharSXPWrapper asChar(RAbstractStringVector obj) { + if (obj.getLength() == 0) { + return CharSXPWrapper_NA; + } else { + return CharSXPWrapper.create(obj.getDataAt(0)); + } + } + + @Specialization + protected CharSXPWrapper asChar(RSymbol obj) { + return CharSXPWrapper.create(obj.getName()); + } + + @Specialization(guards = "isVectorAtomicNodeLG0.execute(obj)") + protected CharSXPWrapper asChar(Object obj, + @Cached("createNonPreserving()") CastStringNode castStringNode, + @SuppressWarnings("unused") @Cached("create()") IsVectorAtomicNodeLG0 isVectorAtomicNodeLG0) { + Object castObj = castStringNode.executeString(obj); + if (castObj instanceof String) { + return CharSXPWrapper.create((String) castObj); + } else if (castObj instanceof RAbstractStringVector) { + return CharSXPWrapper.create(((RAbstractStringVector) castObj).getDataAt(0)); + } else { + throw RInternalError.shouldNotReachHere(); + } + } + + @Fallback + protected CharSXPWrapper asCharFallback(@SuppressWarnings("unused") Object obj) { + return CharSXPWrapper_NA; + } + +} diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/AsIntegerNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/AsIntegerNode.java new file mode 100644 index 0000000000000000000000000000000000000000..b2cb77d981e2e68b5664679817b3c804eac5cd43 --- /dev/null +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/AsIntegerNode.java @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2014, 2017, 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.nodes.ffi; + +import com.oracle.truffle.api.dsl.Cached; +import com.oracle.truffle.api.dsl.Fallback; +import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.dsl.TypeSystemReference; +import com.oracle.truffle.r.nodes.unary.CastIntegerNode; +import com.oracle.truffle.r.runtime.RInternalError; +import com.oracle.truffle.r.runtime.RRuntime; +import com.oracle.truffle.r.runtime.data.RTypesFlatLayout; +import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; + +/** + * Implements the {@code Rf_asInteger} GNU R function . The behavior is subtly different (more + * permissive error-wise) that {@link CastIntegerNode}. Non-castable values return {@code NA}. + */ +@TypeSystemReference(RTypesFlatLayout.class) +public abstract class AsIntegerNode extends FFIUpCallNode.Arg1 { + + @Specialization + protected int asInteger(int obj) { + return obj; + } + + @Specialization + protected int asInteger(double obj) { + return (int) obj; + } + + @Specialization + protected int asReal(RAbstractDoubleVector obj) { + if (obj.getLength() == 0) { + return RRuntime.INT_NA; + } + return (int) obj.getDataAt(0); + } + + @Specialization + protected int asReal(RAbstractIntVector obj) { + if (obj.getLength() == 0) { + return RRuntime.INT_NA; + } + return obj.getDataAt(0); + } + + @Specialization(guards = "isVectorAtomicNodeLG0.execute(obj)") + protected int asReal(Object obj, + @Cached("createNonPreserving()") CastIntegerNode castIntegerNode, + @SuppressWarnings("unused") @Cached("create()") IsVectorAtomicNodeLG0 isVectorAtomicNodeLG0) { + Object castObj = castIntegerNode.executeInt(obj); + if (castObj instanceof Integer) { + return (Integer) castObj; + } else if (castObj instanceof RAbstractIntVector) { + return ((RAbstractIntVector) castObj).getDataAt(0); + } else { + throw RInternalError.shouldNotReachHere(); + } + } + + @Fallback + protected int asRealFallback(@SuppressWarnings("unused") Object obj) { + return RRuntime.INT_NA; + } + +} diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/AsLogicalNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/AsLogicalNode.java new file mode 100644 index 0000000000000000000000000000000000000000..bb67a13e0314bfc8957312e46778c31d9d2f2ffd --- /dev/null +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/AsLogicalNode.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2014, 2017, 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.nodes.ffi; + +import com.oracle.truffle.api.dsl.Cached; +import com.oracle.truffle.api.dsl.Fallback; +import com.oracle.truffle.api.dsl.ImportStatic; +import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.dsl.TypeSystemReference; +import com.oracle.truffle.r.nodes.unary.CastLogicalNode; +import com.oracle.truffle.r.runtime.RInternalError; +import com.oracle.truffle.r.runtime.RRuntime; +import com.oracle.truffle.r.runtime.data.RTypesFlatLayout; +import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector; + +@TypeSystemReference(RTypesFlatLayout.class) +@ImportStatic(IsVectorAtomicNodeLG0.class) +public abstract class AsLogicalNode extends FFIUpCallNode.Arg1 { + + @Specialization + protected int asLogical(byte b) { + return b; + } + + @Specialization + protected int asLogical(RAbstractLogicalVector obj) { + if (obj.getLength() == 0) { + return RRuntime.INT_NA; + } + return obj.getDataAt(0); + } + + @Specialization(guards = "isVectorAtomicNodeLG0.execute(obj)") + protected int asLogical(Object obj, + @Cached("createNonPreserving()") CastLogicalNode castLogicalNode, + @SuppressWarnings("unused") @Cached("create()") IsVectorAtomicNodeLG0 isVectorAtomicNodeLG0) { + Object castObj = castLogicalNode.execute(obj); + if (castObj instanceof Byte) { + return (byte) castObj; + } else if (castObj instanceof RAbstractLogicalVector) { + return ((RAbstractLogicalVector) castObj).getDataAt(0); + } else { + throw RInternalError.shouldNotReachHere(); + } + } + + @Fallback + protected int asLogicalFallback(@SuppressWarnings("unused") Object obj) { + return RRuntime.INT_NA; + } + +} diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/AsRealNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/AsRealNode.java index cfca08ce67c7e0a3170bbd9f667709baf99665ab..27502aea2ca1bb55f6840e94bb4fec5604f4ca46 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/AsRealNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/AsRealNode.java @@ -12,37 +12,36 @@ */ package com.oracle.truffle.r.nodes.ffi; +import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Fallback; +import com.oracle.truffle.api.dsl.ImportStatic; import com.oracle.truffle.api.dsl.Specialization; -import com.oracle.truffle.api.nodes.Node; +import com.oracle.truffle.api.dsl.TypeSystemReference; import com.oracle.truffle.r.nodes.unary.CastDoubleNode; import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.RRuntime; -import com.oracle.truffle.r.runtime.data.RDoubleVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector; +import com.oracle.truffle.r.runtime.data.RTypesFlatLayout; import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractVector; /** * Implements the {@code Rf_asReal} GNU R function (which is also used internally). The behavior is * subtly different (more permissive error-wise) that {@link CastDoubleNode}. Non-castable values * return {@code NA}. */ -public abstract class AsRealNode extends Node { - @Child private CastDoubleNode castDoubleNode = CastDoubleNode.createNonPreserving(); +@TypeSystemReference(RTypesFlatLayout.class) +@ImportStatic(IsVectorAtomicNodeLG0.class) +public abstract class AsRealNode extends FFIUpCallNode.Arg1 { public abstract double execute(Object obj); @Specialization - protected double asReal(Double obj) { + protected double asReal(double obj) { return obj; } @Specialization - protected double asReal(Integer obj) { + protected double asReal(int obj) { return obj; } @@ -62,13 +61,15 @@ public abstract class AsRealNode extends Node { return obj.getDataAt(0); } - @Specialization(guards = "isVectorAtomic(obj)") - protected double asReal(Object obj) { + @Specialization(guards = "isVectorAtomicNodeLG0.execute(obj)") + protected double asReal(Object obj, + @Cached("createNonPreserving()") CastDoubleNode castDoubleNode, + @SuppressWarnings("unused") @Cached("create()") IsVectorAtomicNodeLG0 isVectorAtomicNodeLG0) { Object castObj = castDoubleNode.executeDouble(obj); if (castObj instanceof Double) { return (double) castObj; - } else if (castObj instanceof RDoubleVector) { - return ((RDoubleVector) castObj).getDataAt(0); + } else if (castObj instanceof RAbstractDoubleVector) { + return ((RAbstractDoubleVector) castObj).getDataAt(0); } else { throw RInternalError.shouldNotReachHere(); } @@ -79,16 +80,4 @@ public abstract class AsRealNode extends Node { return RRuntime.DOUBLE_NA; } - public static boolean isVectorAtomic(Object obj) { - return obj instanceof Byte || obj instanceof String || isNonScalarVectorAtomic(obj); - } - - private static boolean isNonScalarVectorAtomic(Object obj) { - if (obj instanceof RAbstractLogicalVector || obj instanceof RAbstractStringVector || obj instanceof RAbstractComplexVector) { - RAbstractVector avec = (RAbstractVector) obj; - return avec.getLength() >= 1; - } else { - return false; - } - } } diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/JavaUpCallsRFFIFactory.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/FFIUpCallNode.java similarity index 50% rename from com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/JavaUpCallsRFFIFactory.java rename to com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/FFIUpCallNode.java index 6bf0183d8e85302127526f6631c99f81662030f6..7cf4549706518f3fc9c496a10f11bcc125c9d9c2 100644 --- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/JavaUpCallsRFFIFactory.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/FFIUpCallNode.java @@ -20,12 +20,48 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package com.oracle.truffle.r.runtime.ffi; +package com.oracle.truffle.r.nodes.ffi; -public class JavaUpCallsRFFIFactory extends UpCallsRFFIFactory { +import com.oracle.truffle.api.nodes.Node; + +public abstract class FFIUpCallNode extends Node { + protected abstract int numArgs(); + + public abstract static class Arg0 extends FFIUpCallNode { + public abstract Object executeObject(); + + @Override + protected int numArgs() { + return 0; + } - @Override - public UpCallsRFFI getUpcallsRFFI() { - return new JavaUpCallsRFFI(); } + + public abstract static class Arg1 extends FFIUpCallNode { + public abstract Object executeObject(Object arg0); + + @Override + protected int numArgs() { + return 1; + } + } + + public abstract static class Arg2 extends FFIUpCallNode { + public abstract Object executeObject(Object arg0, Object arg1); + + @Override + protected int numArgs() { + return 2; + } + } + + public abstract static class Arg3 extends FFIUpCallNode { + public abstract Object executeObject(Object arg0, Object arg1, Object arg2); + + @Override + protected int numArgs() { + return 3; + } + } + } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/FFIUpCallRootNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/FFIUpCallRootNode.java new file mode 100644 index 0000000000000000000000000000000000000000..1c159c108c494f4d645280b917ea9c78937a6934 --- /dev/null +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/FFIUpCallRootNode.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2014, 2017, 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.nodes.ffi; + +import java.util.function.Supplier; + +import com.oracle.truffle.api.RootCallTarget; +import com.oracle.truffle.api.Truffle; +import com.oracle.truffle.api.frame.FrameDescriptor; +import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.api.nodes.RootNode; +import com.oracle.truffle.r.runtime.RInternalError; +import com.oracle.truffle.r.runtime.context.RContext; + +public final class FFIUpCallRootNode extends RootNode { + private static RootCallTarget[] rootCallTargets = new RootCallTarget[UpCallsIndex.TABLE_LENGTH]; + + @Child private FFIUpCallNode theFFIUpCallNode; + private final int numArgs; + + private FFIUpCallRootNode(FFIUpCallNode child) { + super(RContext.getRRuntimeASTAccess().getTruffleRLanguage(), null, new FrameDescriptor()); + theFFIUpCallNode = child; + this.numArgs = child.numArgs(); + } + + @Override + public Object execute(VirtualFrame frame) { + Object[] args = frame.getArguments(); + switch (numArgs) { + case 0: + return ((FFIUpCallNode.Arg0) theFFIUpCallNode).executeObject(); + case 1: + return ((FFIUpCallNode.Arg1) theFFIUpCallNode).executeObject(args[0]); + case 2: + return ((FFIUpCallNode.Arg2) theFFIUpCallNode).executeObject(args[0], args[1]); + case 3: + return ((FFIUpCallNode.Arg3) theFFIUpCallNode).executeObject(args[0], args[1], args[2]); + default: + throw RInternalError.shouldNotReachHere(); + } + } + + static void add(int index, Supplier<FFIUpCallNode> constructor) { + FFIUpCallRootNode rootNode = new FFIUpCallRootNode(constructor.get()); + rootCallTargets[index] = Truffle.getRuntime().createCallTarget(rootNode); + } + + public static RootCallTarget getCallTarget(int index) { + RootCallTarget target = rootCallTargets[index]; + assert target != null; + return target; + } + +} diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/IsVectorAtomicNodeLG0.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/IsVectorAtomicNodeLG0.java new file mode 100644 index 0000000000000000000000000000000000000000..337982d1e8c35e832edda26f419bd53d31cf03d6 --- /dev/null +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/IsVectorAtomicNodeLG0.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2014, 2017, 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.nodes.ffi; + +import com.oracle.truffle.api.dsl.Fallback; +import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.dsl.TypeSystemReference; +import com.oracle.truffle.api.nodes.Node; +import com.oracle.truffle.r.runtime.data.RTypesFlatLayout; +import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; + +/** + * Implements the GNU R function {@code isVectorAtomic} and checks whether length is > 0. + */ +@TypeSystemReference(RTypesFlatLayout.class) +public abstract class IsVectorAtomicNodeLG0 extends Node { + public abstract boolean execute(Object obj); + + @Specialization + protected boolean isVectorAtomicNode(@SuppressWarnings("unused") Byte obj) { + return true; + } + + @Specialization + protected boolean isVectorAtomicNode(@SuppressWarnings("unused") String obj) { + return true; + } + + @Specialization + protected boolean isVectorAtomicNode(RAbstractLogicalVector obj) { + return obj.getLength() > 0; + } + + @Specialization + protected boolean isVectorAtomicNode(RAbstractIntVector obj) { + return obj.getLength() > 0; + } + + @Specialization + protected boolean isVectorAtomicNode(RAbstractDoubleVector obj) { + return obj.getLength() > 0; + } + + @Specialization + protected boolean isVectorAtomicNode(RAbstractStringVector obj) { + return obj.getLength() > 0; + } + + @Specialization + protected boolean isVectorAtomicNode(RAbstractComplexVector obj) { + return obj.getLength() > 0; + } + + @Fallback + protected boolean isVectorAtomicNode(@SuppressWarnings("unused") Object obj) { + return false; + } + + public static IsVectorAtomicNodeLG0 create() { + return IsVectorAtomicNodeLG0NodeGen.create(); + } + +} diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/ListAccessNodes.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/ListAccessNodes.java new file mode 100644 index 0000000000000000000000000000000000000000..1b443987e44dea159fc884aef156d3318affecdc --- /dev/null +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/ListAccessNodes.java @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2017, 2017, 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.nodes.ffi; + +import static com.oracle.truffle.r.nodes.ffi.RFFIUtils.unimplemented; + +import com.oracle.truffle.api.dsl.Fallback; +import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.dsl.TypeSystemReference; +import com.oracle.truffle.r.runtime.data.RLanguage; +import com.oracle.truffle.r.runtime.data.RPairList; +import com.oracle.truffle.r.runtime.data.RTypesFlatLayout; + +/** + * Nodes that implement {@code CAR}, {@code CDR}, etc. N.B. GNU R does not error check the + * arguments; it will crash (segv) if given, say, a numeric arg. + */ +public final class ListAccessNodes { + + @TypeSystemReference(RTypesFlatLayout.class) + public abstract static class CARNode extends FFIUpCallNode.Arg1 { + @Specialization + protected Object car(RPairList pl) { + return pl.car(); + } + + @Specialization + protected Object car(RLanguage lang) { + return lang.getDataAtAsObject(0); + } + + @Fallback + protected Object car(@SuppressWarnings("unused") Object obj) { + throw unimplemented("CAR only works on pair lists and language objects"); + } + + } + + @TypeSystemReference(RTypesFlatLayout.class) + public abstract static class CDRNode extends FFIUpCallNode.Arg1 { + @Specialization + protected Object cdr(RPairList pl) { + return pl.cdr(); + } + + @Specialization + protected Object cdr(RLanguage lang) { + RPairList l = lang.getPairList(); + return l.cdr(); + } + + @Fallback + protected Object cdr(@SuppressWarnings("unused") Object obj) { + throw unimplemented("CDR only works on pair lists and language objects"); + + } + } + + @TypeSystemReference(RTypesFlatLayout.class) + public abstract static class CADRNode extends FFIUpCallNode.Arg1 { + @Specialization + protected Object cadr(RPairList pl) { + return pl.cadr(); + } + + @Specialization + protected Object cadr(RLanguage lang) { + return lang.getDataAtAsObject(1); + } + + @Fallback + protected Object cadr(@SuppressWarnings("unused") Object obj) { + throw unimplemented("CADR only works on pair lists and language objects"); + } + + } + + @TypeSystemReference(RTypesFlatLayout.class) + public abstract static class CADDRNode extends FFIUpCallNode.Arg1 { + @Specialization + protected Object caddr(RPairList pl) { + return pl.caddr(); + } + + @Specialization + protected Object caddr(RLanguage lang) { + return lang.getDataAtAsObject(2); + } + + @Fallback + protected Object caddr(@SuppressWarnings("unused") Object obj) { + throw unimplemented("CADDR only works on pair lists and language objects"); + } + + } + + @TypeSystemReference(RTypesFlatLayout.class) + public abstract static class CDDRNode extends FFIUpCallNode.Arg1 { + @Specialization + protected Object cddr(RPairList pl) { + return pl.cddr(); + } + + @Specialization + protected Object cdr(RLanguage lang) { + RPairList l = lang.getPairList(); + return l.cddr(); + } + + @Fallback + protected Object cddr(@SuppressWarnings("unused") Object obj) { + throw unimplemented("CDDR only works on pair lists and language objects"); + + } + } + +} diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/MiscNodes.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/MiscNodes.java new file mode 100644 index 0000000000000000000000000000000000000000..4d833e1641f64b7dc1614d2792ff47265f4cacee --- /dev/null +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/MiscNodes.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2017, 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.nodes.ffi; + +import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.dsl.Fallback; +import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.dsl.TypeSystemReference; +import com.oracle.truffle.r.runtime.RError; +import com.oracle.truffle.r.runtime.data.RNull; +import com.oracle.truffle.r.runtime.data.RTypesFlatLayout; +import com.oracle.truffle.r.runtime.data.model.RAbstractContainer; +import com.oracle.truffle.r.runtime.ffi.CharSXPWrapper; +import com.oracle.truffle.r.runtime.gnur.SEXPTYPE; + +public final class MiscNodes { + + @TypeSystemReference(RTypesFlatLayout.class) + public abstract static class LENGTHNode extends FFIUpCallNode.Arg1 { + + @Specialization + protected int length(@SuppressWarnings("unused") RNull obj) { + return 0; + } + + @Specialization + protected int length(@SuppressWarnings("unused") int x) { + return 1; + } + + @Specialization + protected int length(@SuppressWarnings("unused") double x) { + return 1; + } + + @Specialization + protected int length(@SuppressWarnings("unused") byte x) { + return 1; + } + + @Specialization + protected int length(@SuppressWarnings("unused") String x) { + return 1; + } + + @Specialization + protected int length(CharSXPWrapper obj) { + return obj.getContents().length(); + } + + @Specialization + protected int length(RAbstractContainer obj) { + // Should this use RLengthNode? + return obj.getLength(); + } + + @Fallback + protected int length(Object obj) { + CompilerDirectives.transferToInterpreter(); + throw RError.error(RError.SHOW_CALLER2, RError.Message.LENGTH_MISAPPLIED, SEXPTYPE.gnuRTypeForObject(obj).name()); + } + } +} diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/ParseResult.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/ParseResult.java similarity index 90% rename from com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/ParseResult.java rename to com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/ParseResult.java index d4c71e01bd9db7b54b821bdeec2afda8ea9589b6..1a5dc11242769558430a273c3f16dc61f598b8bb 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/ParseResult.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/ParseResult.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2017, 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 @@ -20,7 +20,9 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package com.oracle.truffle.r.runtime.ffi; +package com.oracle.truffle.r.nodes.ffi; + +import com.oracle.truffle.r.runtime.ffi.UpCallsRFFI; /** * Used in implementation of {@link UpCallsRFFI#R_ParseVector(Object, int, Object)}. diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/RFFIUtils.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/RFFIUtils.java similarity index 87% rename from com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/RFFIUtils.java rename to com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/RFFIUtils.java index fa21f16be67c76d37887a304de50831c867f8f4d..6cda0147f1d4cb3b3a96c11ac7e8b66924e5072c 100644 --- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/RFFIUtils.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/RFFIUtils.java @@ -20,7 +20,7 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package com.oracle.truffle.r.runtime.ffi; +package com.oracle.truffle.r.nodes.ffi; import java.io.FileDescriptor; import java.io.FileOutputStream; @@ -29,6 +29,7 @@ import java.nio.file.Path; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.r.runtime.FastROptions; +import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.Utils; import com.oracle.truffle.r.runtime.data.RPairList; import com.oracle.truffle.r.runtime.data.RSymbol; @@ -181,6 +182,34 @@ public class RFFIUtils { } } + // Error handling + static RuntimeException unimplemented() { + return unimplemented(""); + } + + static RuntimeException unimplemented(String message) { + throw RInternalError.unimplemented(message); + } + + static void guarantee(boolean condition) { + guarantee(condition, ""); + } + + static void guarantee(boolean condition, String message) { + if (!condition) { + unimplemented(message); + } + } + + public static <T> T guaranteeInstanceOf(Object x, Class<T> clazz) { + if (x == null) { + guarantee(false, "unexpected type: null instead of " + clazz.getSimpleName()); + } else if (!clazz.isInstance(x)) { + guarantee(false, "unexpected type: " + x + " is " + x.getClass().getSimpleName() + " instead of " + clazz.getSimpleName()); + } + return clazz.cast(x); + } + // Miscellaneous support functions public static byte[] wrapChar(char v) { diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/TraceUpCallsAdapter.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/TraceUpCallsAdapter.java similarity index 99% rename from com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/TraceUpCallsAdapter.java rename to com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/TraceUpCallsAdapter.java index 1b6d8aab816bc180e5a361d2e3311c02d40e3749..4dea6ab018ec73cb19f80b0ca3b955733c7237d4 100644 --- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/TraceUpCallsAdapter.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/TraceUpCallsAdapter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, 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 @@ -20,7 +20,7 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package com.oracle.truffle.r.runtime.ffi.jni; +package com.oracle.truffle.r.nodes.ffi; import com.oracle.truffle.r.runtime.data.RDoubleVector; import com.oracle.truffle.r.runtime.data.RExternalPtr; @@ -28,7 +28,6 @@ import com.oracle.truffle.r.runtime.data.RIntVector; import com.oracle.truffle.r.runtime.data.RLogicalVector; import com.oracle.truffle.r.runtime.data.RStringVector; import com.oracle.truffle.r.runtime.env.REnvironment; -import com.oracle.truffle.r.runtime.ffi.RFFIUtils; import com.oracle.truffle.r.runtime.ffi.UpCallsRFFI; public class TraceUpCallsAdapter implements UpCallsRFFI { diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/UpCallsIndex.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/UpCallsIndex.java new file mode 100644 index 0000000000000000000000000000000000000000..fa9f03d430184303fbafa64f71dd0c3e15d96b46 --- /dev/null +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/UpCallsIndex.java @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2017, 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.nodes.ffi; + +import com.oracle.truffle.api.RootCallTarget; +import com.oracle.truffle.r.nodes.ffi.ListAccessNodesFactory.CADDRNodeGen; +import com.oracle.truffle.r.nodes.ffi.ListAccessNodesFactory.CADRNodeGen; +import com.oracle.truffle.r.nodes.ffi.ListAccessNodesFactory.CARNodeGen; +import com.oracle.truffle.r.nodes.ffi.ListAccessNodesFactory.CDDRNodeGen; +import com.oracle.truffle.r.nodes.ffi.ListAccessNodesFactory.CDRNodeGen; +import com.oracle.truffle.r.nodes.ffi.MiscNodesFactory.LENGTHNodeGen; +import com.oracle.truffle.r.runtime.ffi.UpCallsRFFI; + +/** + * Provides indices for indexing into table of {@link RootCallTarget}s for any upcall implemented in + * Truffle, and a {@link #register} method to associate exactly those calls which are implemented in + * Truffle. The indices were initially generated automatically from {@link UpCallsRFFI}. + */ +final class UpCallsIndex { + static final int TABLE_LENGTH = 110; + + static final int CADDR = 0; + static final int CADR = 1; + static final int CAR = 2; + static final int CDDR = 3; + static final int CDR = 4; + static final int DUPLICATE_ATTRIB = 5; + static final int ENCLOS = 6; + static final int GetRNGstate = 7; + static final int INTEGER = 8; + static final int LENGTH = 9; + static final int LOGICAL = 10; + static final int NAMED = 11; + static final int OBJECT = 12; + static final int PRINTNAME = 13; + static final int PRVALUE = 14; + static final int PutRNGstate = 15; + static final int RAW = 16; + static final int RDEBUG = 17; + static final int REAL = 18; + static final int RSTEP = 19; + static final int R_BaseEnv = 20; + static final int R_BaseNamespace = 21; + static final int R_BindingIsLocked = 22; + static final int R_CleanUp = 23; + static final int R_ExternalPtrAddr = 24; + static final int R_ExternalPtrProt = 25; + static final int R_ExternalPtrTag = 26; + static final int R_FindNamespace = 27; + static final int R_GlobalContext = 28; + static final int R_GlobalEnv = 29; + static final int R_HomeDir = 30; + static final int R_MakeExternalPtr = 31; + static final int R_NamespaceRegistry = 32; + static final int R_NewHashedEnv = 33; + static final int R_ParseVector = 34; + static final int R_SetExternalPtrAddr = 35; + static final int R_SetExternalPtrProt = 36; + static final int R_SetExternalPtrTag = 37; + static final int R_ToplevelExec = 38; + static final int R_computeIdentical = 39; + static final int R_do_MAKE_CLASS = 40; + static final int R_getContextCall = 41; + static final int R_getContextEnv = 42; + static final int R_getContextFun = 43; + static final int R_getContextSrcRef = 44; + static final int R_getGlobalFunctionContext = 45; + static final int R_getParentFunctionContext = 46; + static final int R_insideBrowser = 47; + static final int R_isEqual = 48; + static final int R_isGlobal = 49; + static final int R_lsInternal3 = 50; + static final int R_tryEval = 51; + static final int Rf_GetOption1 = 52; + static final int Rf_PairToVectorList = 53; + static final int Rf_ScalarDouble = 54; + static final int Rf_ScalarInteger = 55; + static final int Rf_ScalarLogical = 56; + static final int Rf_ScalarString = 57; + static final int Rf_allocateArray = 58; + static final int Rf_allocateMatrix = 59; + static final int Rf_allocateVector = 60; + static final int Rf_anyDuplicated = 61; + static final int Rf_asChar = 62; + static final int Rf_asInteger = 63; + static final int Rf_asLogical = 64; + static final int Rf_asReal = 65; + static final int Rf_classgets = 66; + static final int Rf_cons = 67; + static final int Rf_copyListMatrix = 68; + static final int Rf_copyMatrix = 69; + static final int Rf_defineVar = 70; + static final int Rf_duplicate = 71; + static final int Rf_error = 72; + static final int Rf_eval = 73; + static final int Rf_findVar = 74; + static final int Rf_findVarInFrame = 75; + static final int Rf_findVarInFrame3 = 76; + static final int Rf_findfun = 77; + static final int Rf_getAttrib = 78; + static final int Rf_gsetVar = 79; + static final int Rf_inherits = 80; + static final int Rf_install = 81; + static final int Rf_isNull = 82; + static final int Rf_isString = 83; + static final int Rf_lengthgets = 84; + static final int Rf_mkCharLenCE = 85; + static final int Rf_ncols = 86; + static final int Rf_nrows = 87; + static final int Rf_setAttrib = 88; + static final int Rf_warning = 89; + static final int Rf_warningcall = 90; + static final int Rprintf = 91; + static final int SETCADR = 92; + static final int SETCAR = 93; + static final int SETCDR = 94; + static final int SET_RDEBUG = 95; + static final int SET_RSTEP = 96; + static final int SET_STRING_ELT = 97; + static final int SET_SYMVALUE = 98; + static final int SET_TAG = 99; + static final int SET_TYPEOF_FASTR = 100; + static final int SET_VECTOR_ELT = 101; + static final int STRING_ELT = 102; + static final int SYMVALUE = 103; + static final int TAG = 104; + static final int TYPEOF = 105; + static final int VECTOR_ELT = 106; + static final int isInteractive = 107; + static final int isS4Object = 108; + static final int unif_rand = 109; + + static void register() { + FFIUpCallRootNode.add(Rf_asReal, AsRealNodeGen::create); + FFIUpCallRootNode.add(Rf_asLogical, AsLogicalNodeGen::create); + FFIUpCallRootNode.add(Rf_asInteger, AsIntegerNodeGen::create); + FFIUpCallRootNode.add(Rf_asChar, AsCharNodeGen::create); + FFIUpCallRootNode.add(CAR, CARNodeGen::create); + FFIUpCallRootNode.add(CDR, CDRNodeGen::create); + FFIUpCallRootNode.add(CADR, CADRNodeGen::create); + FFIUpCallRootNode.add(CADDR, CADDRNodeGen::create); + FFIUpCallRootNode.add(CDDR, CDDRNodeGen::create); + FFIUpCallRootNode.add(LENGTH, LENGTHNodeGen::create); + } +} diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/JavaUpCallsRFFI.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/UpCallsRFFIImpl.java similarity index 90% rename from com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/JavaUpCallsRFFI.java rename to com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/UpCallsRFFIImpl.java index 498519f4837e28824ff4fa6d9fc840e2c3636967..cc0883388ba36345a3582985028ca9e54c2b7b41 100644 --- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/JavaUpCallsRFFI.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/UpCallsRFFIImpl.java @@ -20,7 +20,9 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package com.oracle.truffle.r.runtime.ffi; +package com.oracle.truffle.r.nodes.ffi; + +import static com.oracle.truffle.r.nodes.ffi.RFFIUtils.*; import java.nio.charset.StandardCharsets; import java.util.function.Function; @@ -31,6 +33,7 @@ import com.oracle.truffle.api.frame.FrameInstance.FrameAccess; import com.oracle.truffle.api.object.DynamicObject; import com.oracle.truffle.api.source.Source; import com.oracle.truffle.api.source.SourceSection; +import com.oracle.truffle.r.nodes.ffi.ParseResult.ParseStatus; import com.oracle.truffle.r.runtime.RArguments; import com.oracle.truffle.r.runtime.RCaller; import com.oracle.truffle.r.runtime.RCleanUp; @@ -73,15 +76,14 @@ import com.oracle.truffle.r.runtime.data.RStringVector; import com.oracle.truffle.r.runtime.data.RSymbol; import com.oracle.truffle.r.runtime.data.RUnboundValue; import com.oracle.truffle.r.runtime.data.RVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractContainer; import com.oracle.truffle.r.runtime.data.model.RAbstractListVector; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; import com.oracle.truffle.r.runtime.env.REnvironment; import com.oracle.truffle.r.runtime.env.REnvironment.PutException; +import com.oracle.truffle.r.runtime.ffi.CharSXPWrapper; +import com.oracle.truffle.r.runtime.ffi.UpCallsRFFI; import com.oracle.truffle.r.runtime.ffi.DLL.SymbolHandle; -import com.oracle.truffle.r.runtime.ffi.ParseResult.ParseStatus; -import com.oracle.truffle.r.runtime.ffi.jni.TraceUpCallsAdapter; import com.oracle.truffle.r.runtime.gnur.SEXPTYPE; import com.oracle.truffle.r.runtime.nodes.DuplicationHelper; import com.oracle.truffle.r.runtime.nodes.RNode; @@ -98,52 +100,15 @@ import com.oracle.truffle.r.runtime.rng.RRNG; * is desirable. In some cases it may be possible to "implement" the functions in R (which is a * simple way to achieve the above). */ -public class JavaUpCallsRFFI implements UpCallsRFFI { +public class UpCallsRFFIImpl implements UpCallsRFFI { - private TraceUpCallsAdapter tracer; + protected TraceUpCallsAdapter tracer; - public JavaUpCallsRFFI() { + public UpCallsRFFIImpl() { if (RFFIUtils.traceEnabled()) { tracer = new TraceUpCallsAdapter(); } - } - - private static RuntimeException unimplemented() { - return unimplemented(""); - } - - private static RuntimeException unimplemented(String message) { - System.err.println(message); - try { - throw RInternalError.unimplemented(message); - } catch (Error e) { - e.printStackTrace(); - try { - Thread.sleep(100000); - } catch (InterruptedException e2) { - e2.printStackTrace(); - } - throw e; - } - } - - private static void guarantee(boolean condition) { - guarantee(condition, ""); - } - - private static void guarantee(boolean condition, String message) { - if (!condition) { - unimplemented(message); - } - } - - public static <T> T guaranteeInstanceOf(Object x, Class<T> clazz) { - if (x == null) { - guarantee(false, "unexpected type: null instead of " + clazz.getSimpleName()); - } else if (!clazz.isInstance(x)) { - guarantee(false, "unexpected type: " + x + " is " + x.getClass().getSimpleName() + " instead of " + clazz.getSimpleName()); - } - return clazz.cast(x); + UpCallsIndex.register(); } // Checkstyle: stop method name check @@ -161,7 +126,13 @@ public class JavaUpCallsRFFI implements UpCallsRFFI { if (tracer != null) { tracer.Rf_ScalarLogical(value); } - return RDataFactory.createLogicalVectorFromScalar(value != 0); + byte byteValue; + if (value == RRuntime.INT_NA) { + byteValue = RRuntime.LOGICAL_NA; + } else { + byteValue = (byte) (value & 0xFF); + } + return RDataFactory.createLogicalVectorFromScalar(byteValue); } @Override @@ -186,19 +157,7 @@ public class JavaUpCallsRFFI implements UpCallsRFFI { if (tracer != null) { tracer.Rf_asInteger(x); } - // TODO this is quite incomplete and really should be implemented with CastIntegerNode - if (x instanceof Integer) { - return ((Integer) x).intValue(); - } else if (x instanceof Double) { - return RRuntime.double2int((Double) x); - } else if (x instanceof Byte) { - return RRuntime.logical2int((Byte) x); - } else if (x instanceof RLogicalVector) { - return RRuntime.logical2int(((RLogicalVector) x).getDataAt(0)); - } else { - guaranteeInstanceOf(x, RIntVector.class); - return ((RIntVector) x).getDataAt(0); - } + return (int) FFIUpCallRootNode.getCallTarget(UpCallsIndex.Rf_asInteger).call(x); } @Override @@ -206,14 +165,7 @@ public class JavaUpCallsRFFI implements UpCallsRFFI { if (tracer != null) { tracer.Rf_asReal(x); } - if (x instanceof Double) { - return ((Double) x).doubleValue(); - } else if (x instanceof Byte) { - return RRuntime.logical2double((Byte) x); - } else { - guaranteeInstanceOf(x, RDoubleVector.class); - return ((RDoubleVector) x).getDataAt(0); - } + return (double) FFIUpCallRootNode.getCallTarget(UpCallsIndex.Rf_asReal).call(x); } @Override @@ -221,12 +173,7 @@ public class JavaUpCallsRFFI implements UpCallsRFFI { if (tracer != null) { tracer.Rf_asLogical(x); } - if (x instanceof Byte) { - return ((Byte) x).intValue(); - } else { - guaranteeInstanceOf(x, RLogicalVector.class); - return ((RLogicalVector) x).getDataAt(0); - } + return (int) FFIUpCallRootNode.getCallTarget(UpCallsIndex.Rf_asLogical).call(x); } @Override @@ -234,25 +181,7 @@ public class JavaUpCallsRFFI implements UpCallsRFFI { if (tracer != null) { tracer.Rf_asChar(x); } - if (x instanceof CharSXPWrapper) { - return x; - } else if (x instanceof RSymbol) { - return CharSXPWrapper.create(((RSymbol) x).getName()); - } - - Object obj = RRuntime.asAbstractVector(x); - if (obj instanceof RAbstractVector) { - RAbstractVector vector = (RAbstractVector) obj; - if (vector.getLength() > 0) { - if (vector instanceof RAbstractStringVector) { - return CharSXPWrapper.create(((RAbstractStringVector) vector).getDataAt(0)); - } else { - unimplemented("asChar type " + x.getClass()); - } - } - } - - return CharSXPWrapper.create(RRuntime.STRING_NA); + return FFIUpCallRootNode.getCallTarget(UpCallsIndex.Rf_asChar).call(x); } @Override @@ -607,17 +536,7 @@ public class JavaUpCallsRFFI implements UpCallsRFFI { if (tracer != null) { tracer.LENGTH(x); } - if (x instanceof RAbstractContainer) { - return ((RAbstractContainer) x).getLength(); - } else if (x == RNull.instance) { - return 0; - } else if (x instanceof CharSXPWrapper) { - return ((CharSXPWrapper) x).getContents().length(); - } else if (x instanceof Integer || x instanceof Double || x instanceof Byte || x instanceof String) { - return 1; - } else { - throw unimplemented("unexpected value: " + x); - } + return (int) FFIUpCallRootNode.getCallTarget(UpCallsIndex.LENGTH).call(x); } @Override @@ -836,12 +755,7 @@ public class JavaUpCallsRFFI implements UpCallsRFFI { if (tracer != null) { tracer.CAR(e); } - guarantee(e != null && (RPairList.class.isInstance(e) || RLanguage.class.isInstance(e)), "CAR only works on pair lists and language objects"); - if (e instanceof RPairList) { - return ((RPairList) e).car(); - } else { - return ((RLanguage) e).getDataAtAsObject(0); - } + return FFIUpCallRootNode.getCallTarget(UpCallsIndex.CAR).call(e); } @Override @@ -849,14 +763,7 @@ public class JavaUpCallsRFFI implements UpCallsRFFI { if (tracer != null) { tracer.CDR(e); } - if (e instanceof RLanguage) { - RLanguage lang = (RLanguage) e; - RPairList l = lang.getPairList(); - return l.cdr(); - } else { - guaranteeInstanceOf(e, RPairList.class); - return ((RPairList) e).cdr(); - } + return FFIUpCallRootNode.getCallTarget(UpCallsIndex.CDR).call(e); } @Override @@ -864,12 +771,7 @@ public class JavaUpCallsRFFI implements UpCallsRFFI { if (tracer != null) { tracer.CADR(e); } - guarantee(e != null && (RPairList.class.isInstance(e) || RLanguage.class.isInstance(e)), "CADR only works on pair lists and language objects"); - if (e instanceof RPairList) { - return ((RPairList) e).cadr(); - } else { - return ((RLanguage) e).getDataAtAsObject(1); - } + return FFIUpCallRootNode.getCallTarget(UpCallsIndex.CADR).call(e); } @Override @@ -877,12 +779,7 @@ public class JavaUpCallsRFFI implements UpCallsRFFI { if (tracer != null) { tracer.CADDR(e); } - guarantee(e != null && (RPairList.class.isInstance(e) || RLanguage.class.isInstance(e)), "CADDR only works on pair lists and language objects"); - if (e instanceof RPairList) { - return ((RPairList) e).caddr(); - } else { - return ((RLanguage) e).getDataAtAsObject(2); - } + return FFIUpCallRootNode.getCallTarget(UpCallsIndex.CADDR).call(e); } @Override @@ -890,14 +787,7 @@ public class JavaUpCallsRFFI implements UpCallsRFFI { if (tracer != null) { tracer.CDDR(e); } - if (e instanceof RLanguage) { - RLanguage lang = (RLanguage) e; - RPairList l = lang.getPairList(); - return l.cddr(); - } else { - guaranteeInstanceOf(e, RPairList.class); - return ((RPairList) e).cddr(); - } + return FFIUpCallRootNode.getCallTarget(UpCallsIndex.CDDR).call(e); } @Override diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_C.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_C.java index a4e26e084cb26a2b33636465fd06b613b18346ba..26f233a1fad2f1da4d59a33118043d9f4f9b7a91 100644 --- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_C.java +++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_C.java @@ -22,8 +22,8 @@ */ package com.oracle.truffle.r.runtime.ffi.jni; -import static com.oracle.truffle.r.runtime.ffi.RFFIUtils.traceDownCall; -import static com.oracle.truffle.r.runtime.ffi.RFFIUtils.traceEnabled; +import static com.oracle.truffle.r.nodes.ffi.RFFIUtils.traceDownCall; +import static com.oracle.truffle.r.nodes.ffi.RFFIUtils.traceEnabled; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.r.runtime.ffi.CRFFI; diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Call.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Call.java index d05fc1e0d965cfde992b255c747d9e22de172062..00ba4c6fa9190f4d91e711de8ebdc0a0510f5d8a 100644 --- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Call.java +++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Call.java @@ -22,21 +22,21 @@ */ package com.oracle.truffle.r.runtime.ffi.jni; -import static com.oracle.truffle.r.runtime.ffi.RFFIUtils.traceDownCall; -import static com.oracle.truffle.r.runtime.ffi.RFFIUtils.traceDownCallReturn; -import static com.oracle.truffle.r.runtime.ffi.RFFIUtils.traceEnabled; +import static com.oracle.truffle.r.nodes.ffi.RFFIUtils.traceDownCall; +import static com.oracle.truffle.r.nodes.ffi.RFFIUtils.traceDownCallReturn; +import static com.oracle.truffle.r.nodes.ffi.RFFIUtils.traceEnabled; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.r.nodes.ffi.UpCallsRFFIImpl; +import com.oracle.truffle.r.nodes.ffi.RFFIUtils; import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.ffi.CallRFFI; import com.oracle.truffle.r.runtime.ffi.DLL; import com.oracle.truffle.r.runtime.ffi.DLLRFFI; import com.oracle.truffle.r.runtime.ffi.LibPaths; import com.oracle.truffle.r.runtime.ffi.NativeCallInfo; -import com.oracle.truffle.r.runtime.ffi.RFFIUtils; import com.oracle.truffle.r.runtime.ffi.RFFIVariables; import com.oracle.truffle.r.runtime.ffi.UpCallsRFFI; -import com.oracle.truffle.r.runtime.ffi.UpCallsRFFIFactory; /** * The only variety in the signatures for {@code .Call} is the number of arguments. GnuR supports a @@ -171,7 +171,7 @@ public class JNI_Call implements CallRFFI { traceDownCall("initialize"); } try { - initialize(UpCallsRFFIFactory.getInstance().getUpcallsRFFI(), RFFIVariables.values()); + initialize(new UpCallsRFFIImpl(), RFFIVariables.values()); } finally { if (traceEnabled()) { traceDownCallReturn("initialize", null); diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Misc.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Misc.java index eb9acfc8566c51815bdb537e07d5a842ddb8bad8..25035bfc14be70f11f84b916ffb519ac8281e4eb 100644 --- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Misc.java +++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Misc.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, 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 @@ -22,9 +22,9 @@ */ package com.oracle.truffle.r.runtime.ffi.jni; -import static com.oracle.truffle.r.runtime.ffi.RFFIUtils.traceDownCall; -import static com.oracle.truffle.r.runtime.ffi.RFFIUtils.traceDownCallReturn; -import static com.oracle.truffle.r.runtime.ffi.RFFIUtils.traceEnabled; +import static com.oracle.truffle.r.nodes.ffi.RFFIUtils.traceDownCall; +import static com.oracle.truffle.r.nodes.ffi.RFFIUtils.traceDownCallReturn; +import static com.oracle.truffle.r.nodes.ffi.RFFIUtils.traceEnabled; import com.oracle.truffle.r.runtime.ffi.MiscRFFI; diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java index f0a8433fdbc67f01c81da9b60ed8dcf87b58853a..8f3c3a3a6d95b03e1562a73192828cdfa61f1bf0 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java @@ -777,11 +777,12 @@ public final class RError extends RuntimeException { FIRST_ELEMENT_ONLY("only first element of '%s' argument used"), MUST_BE_GE_ONE("'%s' must be of length >= 1"), MORE_THAN_ONE_MATCH("there is more than one match in '%s'"), - TOO_MANY_ARGS("too many arguments"), ARG_MUST_BE_CHARACTER("argument '%s' must be character"), INCORRECT_NOF_ARGS("Incorrect number of arguments (%d), expecting %d for '%s'"), MACRO_CAN_BE_APPLIED_TO("%s can only be applied to a '%s', not a '%s'"), - LOSS_OF_ACCURACY_MOD("probable complete loss of accuracy in modulus"); + LOSS_OF_ACCURACY_MOD("probable complete loss of accuracy in modulus"), + LENGTH_MISAPPLIED("LENGTH or similar applied to %s object"), + TOO_MANY_ARGS("too many arguments"); public final String message; final boolean hasArgs; diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/CharSXPWrapper.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/CharSXPWrapper.java index 161a93b520a4d41b676bf864830e1df530eb7461..914742898c1751e9a2a333c4070f2a90a87c5575 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/CharSXPWrapper.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/CharSXPWrapper.java @@ -48,7 +48,7 @@ public final class CharSXPWrapper { return "CHARSXP(" + contents + ")"; } - public static Object create(String contents) { + public static CharSXPWrapper create(String contents) { return new CharSXPWrapper(contents); } } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/UpCallsRFFIFactory.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/UpCallsRFFIFactory.java deleted file mode 100644 index ad90095e5d43c62b89736d67dc05c0a60d035c1a..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/UpCallsRFFIFactory.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2016, 2016, 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.runtime.ffi; - -public abstract class UpCallsRFFIFactory { - static { - final String prop = System.getProperty("fastr.upcalls.factory.class", "com.oracle.truffle.r.runtime.ffi.JavaUpCallsRFFIFactory"); - try { - theInstance = (UpCallsRFFIFactory) Class.forName(prop).newInstance(); - } catch (Exception ex) { - // CheckStyle: stop system..print check - System.err.println("Failed to instantiate class: " + prop); - } - } - - private static UpCallsRFFIFactory theInstance; - - public static UpCallsRFFIFactory getInstance() { - return theInstance; - } - - public abstract UpCallsRFFI getUpcallsRFFI(); - -} diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/gnur/SEXPTYPE.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/gnur/SEXPTYPE.java index 2735f2873b6f49f1e2e17099f5e8513eebd3d60b..4740bd9bc7c7364e73f758441c9621f7c8a45a30 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/gnur/SEXPTYPE.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/gnur/SEXPTYPE.java @@ -5,7 +5,7 @@ * * Copyright (c) 1995-2012, The R Core Team * Copyright (c) 2003, The R Foundation - * Copyright (c) 2013, 2016, Oracle and/or its affiliates + * Copyright (c) 2013, 2017, Oracle and/or its affiliates * * All rights reserved. */ @@ -157,8 +157,15 @@ public enum SEXPTYPE { * Accessed from FFI layer. */ public static int gnuRCodeForObject(Object obj) { + return gnuRTypeForObject(obj).code; + } + + /** + * Accessed from FFI layer. + */ + public static SEXPTYPE gnuRTypeForObject(Object obj) { SEXPTYPE type = typeForClass(obj.getClass()); - return gnuRType(type, obj).code; + return gnuRType(type, obj); } /** diff --git a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/R/testrffi.R b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/R/testrffi.R index 48d34db470d1bc751044c3411b51a433f78c5d02..d482babaaccb3273a41e04bbd89879c250c25ad2 100644 --- a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/R/testrffi.R +++ b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/R/testrffi.R @@ -125,4 +125,31 @@ rffi.null.C <- function() { .Call(C_null) } +rffi.asReal <- function(x) { + .Call("test_asReal", x) +} + +rffi.asInteger <- function(x) { + .Call("test_asInteger", x) +} + +rffi.asLogical <- function(x) { + .Call("test_asLogical", x) +} + +rffi.asChar <- function(x) { + .Call("test_asChar", x) +} + +rffi.CAR <- function(x) { + .Call("test_CAR", x) +} + +rffi.CDR <- function(x) { + .Call("test_CDR", x) +} + +rffi.LENGTH <- function(x) { + .Call("test_LENGTH", x) +} diff --git a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/init.c b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/init.c index 5af8e6bb9f7b8298be0b5a6ee5a99fafd51ffe25..8ac5196404c7c117a757160d193864554b728259 100644 --- a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/init.c +++ b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/init.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2017, 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 @@ -58,6 +58,13 @@ static const R_CallMethodDef CallEntries[] = { CALLDEF(preserve_object, 0), CALLDEF(release_object, 1), CALLDEF(findvar, 2), + CALLDEF(test_asReal, 1), + CALLDEF(test_asChar, 1), + CALLDEF(test_asInteger, 1), + CALLDEF(test_asLogical, 1), + CALLDEF(test_CAR, 1), + CALLDEF(test_CDR, 1), + CALLDEF(test_LENGTH, 1), {NULL, NULL, 0} }; diff --git a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/testrffi.c b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/testrffi.c index b8f04f014f1932f69092eaeda8e7e26737c065e7..e15a466e947a7acb2f3ce0dfd7515e354afee256 100644 --- a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/testrffi.c +++ b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/testrffi.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2017, 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 @@ -290,3 +290,30 @@ SEXP findvar(SEXP x, SEXP env) { } } +SEXP test_asReal(SEXP x) { + return Rf_ScalarReal(Rf_asReal(x)); +} + +SEXP test_asInteger(SEXP x) { + return Rf_ScalarInteger(Rf_asInteger(x)); +} + +SEXP test_asLogical(SEXP x) { + return Rf_ScalarLogical(Rf_asLogical(x)); +} + +SEXP test_asChar(SEXP x) { + return Rf_ScalarString(Rf_asChar(x)); +} + +SEXP test_CAR(SEXP x) { + return CAR(x); +} + +SEXP test_CDR(SEXP x) { + return CDR(x); +} + +SEXP test_LENGTH(SEXP x) { + return ScalarInteger(LENGTH(x)); +} diff --git a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/testrffi.h b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/testrffi.h index 44de64f3dacf7f6b4dcda78ca61fe0ab4b58eff2..040107cedf1d35e934248ce635cd3f95d11e355c 100644 --- a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/testrffi.h +++ b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/testrffi.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, 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 @@ -71,3 +71,18 @@ extern SEXP preserve_object(void); extern SEXP release_object(SEXP x); extern SEXP findvar(SEXP x, SEXP env); + +extern SEXP test_asReal(SEXP x); + +extern SEXP test_asChar(SEXP x); + +extern SEXP test_asInteger(SEXP x); + +extern SEXP test_asLogical(SEXP x); + +extern SEXP test_CAR(SEXP x); + +extern SEXP test_CDR(SEXP x); + +extern SEXP test_LENGTH(SEXP x); + diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test index ce4e31970c1c8b676edc3d5efb2b65ba18b0450b..0732ffe87e3190c9065c358ff959feccb57d8d9c 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test @@ -136983,6 +136983,195 @@ non-integer value 12345678909876543212L qualified with L; using numeric value #'\ ' == ' ' [1] TRUE +##com.oracle.truffle.r.test.rffi.TestRFFIPackage.TestLENGTH#Output.MayIgnoreErrorContext# +#{ library("testrffi", lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); x <- list(); x <- x <- append(x, rffi.LENGTH(1)); x <- append(x, rffi.LENGTH(c(1,2,3))); x <- append(x, rffi.LENGTH(list(1,2,3))); x <- append(x, rffi.LENGTH(expression(1,2))); ; detach("package:testrffi", unload=T); x } +[[1]] +[1] 1 + +[[2]] +[1] 3 + +[[3]] +[1] 3 + +[[4]] +[1] 2 + + +##com.oracle.truffle.r.test.rffi.TestRFFIPackage.testAsFunctions#Output.MayIgnoreWarningContext# +#{ library("testrffi", lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); x <- list(); x <- x <- append(x, rffi.asChar(1L)); x <- append(x, rffi.asInteger(1L)); x <- append(x, rffi.asReal(1L)); x <- append(x, rffi.asLogical(1L)); x <- append(x, rffi.asChar(2)); x <- append(x, rffi.asInteger(2)); x <- append(x, rffi.asReal(2)); x <- append(x, rffi.asLogical(2)); x <- append(x, rffi.asChar(2.2)); x <- append(x, rffi.asInteger(2.2)); x <- append(x, rffi.asReal(2.2)); x <- append(x, rffi.asLogical(2.2)); x <- append(x, rffi.asChar(T)); x <- append(x, rffi.asInteger(T)); x <- append(x, rffi.asReal(T)); x <- append(x, rffi.asLogical(T)); x <- append(x, rffi.asChar(integer())); x <- append(x, rffi.asInteger(integer())); x <- append(x, rffi.asReal(integer())); x <- append(x, rffi.asLogical(integer())); x <- append(x, rffi.asChar(numeric())); x <- append(x, rffi.asInteger(numeric())); x <- append(x, rffi.asReal(numeric())); x <- append(x, rffi.asLogical(numeric())); x <- append(x, rffi.asChar(logical())); x <- append(x, rffi.asInteger(logical())); x <- append(x, rffi.asReal(logical())); x <- append(x, rffi.asLogical(logical())); x <- append(x, rffi.asChar(character())); x <- append(x, rffi.asInteger(character())); x <- append(x, rffi.asReal(character())); x <- append(x, rffi.asLogical(character())); x <- append(x, rffi.asChar(c(5,6))); x <- append(x, rffi.asInteger(c(5,6))); x <- append(x, rffi.asReal(c(5,6))); x <- append(x, rffi.asLogical(c(5,6))); x <- append(x, rffi.asChar(c(2.3, 3.4))); x <- append(x, rffi.asInteger(c(2.3, 3.4))); x <- append(x, rffi.asReal(c(2.3, 3.4))); x <- append(x, rffi.asLogical(c(2.3, 3.4))); x <- append(x, rffi.asChar(c(T, F))); x <- append(x, rffi.asInteger(c(T, F))); x <- append(x, rffi.asReal(c(T, F))); x <- append(x, rffi.asLogical(c(T, F))); x <- append(x, rffi.asChar(as.symbol("sym"))); x <- append(x, rffi.asInteger(as.symbol("sym"))); x <- append(x, rffi.asReal(as.symbol("sym"))); x <- append(x, rffi.asLogical(as.symbol("sym"))); x <- append(x, rffi.asChar(list())); x <- append(x, rffi.asInteger(list())); x <- append(x, rffi.asReal(list())); x <- append(x, rffi.asLogical(list())); ; detach("package:testrffi", unload=T); x } +[[1]] +[1] "1" + +[[2]] +[1] 1 + +[[3]] +[1] 1 + +[[4]] +[1] TRUE + +[[5]] +[1] "2" + +[[6]] +[1] 2 + +[[7]] +[1] 2 + +[[8]] +[1] TRUE + +[[9]] +[1] "2.2" + +[[10]] +[1] 2 + +[[11]] +[1] 2.2 + +[[12]] +[1] TRUE + +[[13]] +[1] "TRUE" + +[[14]] +[1] 1 + +[[15]] +[1] 1 + +[[16]] +[1] TRUE + +[[17]] +[1] NA + +[[18]] +[1] NA + +[[19]] +[1] NA + +[[20]] +[1] NA + +[[21]] +[1] NA + +[[22]] +[1] NA + +[[23]] +[1] NA + +[[24]] +[1] NA + +[[25]] +[1] NA + +[[26]] +[1] NA + +[[27]] +[1] NA + +[[28]] +[1] NA + +[[29]] +[1] NA + +[[30]] +[1] NA + +[[31]] +[1] NA + +[[32]] +[1] NA + +[[33]] +[1] "5" + +[[34]] +[1] 5 + +[[35]] +[1] 5 + +[[36]] +[1] TRUE + +[[37]] +[1] "2.3" + +[[38]] +[1] 2 + +[[39]] +[1] 2.3 + +[[40]] +[1] TRUE + +[[41]] +[1] "TRUE" + +[[42]] +[1] 1 + +[[43]] +[1] 1 + +[[44]] +[1] TRUE + +[[45]] +[1] "sym" + +[[46]] +[1] NA + +[[47]] +[1] NA + +[[48]] +[1] NA + +[[49]] +[1] NA + +[[50]] +[1] NA + +[[51]] +[1] NA + +[[52]] +[1] NA + + +##com.oracle.truffle.r.test.rffi.TestRFFIPackage.testListFunctions#Output.MayIgnoreErrorContext# +#{ library("testrffi", lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); x <- list(); x <- x <- append(x, rffi.CAR(pairlist(1,2))); x <- append(x, rffi.CDR(pairlist(1,2))); x <- append(x, rffi.CAR(pairlist(x=1L, y=2L))); x <- append(x, rffi.CDR(pairlist(x=1L, y=2L))); ; detach("package:testrffi", unload=T); x } +[[1]] +[1] 1 + +[[2]] +[1] 2 + +[[3]] +[1] 1 + +$y +[1] 2 + + ##com.oracle.truffle.r.test.rffi.TestRFFIPackage.testRFFI1# #{ library("testrffi", lib.loc = "tmptest/com.oracle.truffle.r.test.rpackages"); x <- rffi.addInt(2L, 3L); detach("package:testrffi", unload=T); x } [1] 5 diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rffi/TestRFFIPackage.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rffi/TestRFFIPackage.java index 400a9c7b8f90f0a833c0fa568b46212095152d8c..372f4a1f906ef6f4df0f67c57524e0142e8729ca 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rffi/TestRFFIPackage.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rffi/TestRFFIPackage.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2017, 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 @@ -27,6 +27,7 @@ import org.junit.BeforeClass; import org.junit.Test; import com.oracle.truffle.r.test.TestBase; +import com.oracle.truffle.r.test.TestTrait; import com.oracle.truffle.r.test.rpackages.TestRPackages; public class TestRFFIPackage extends TestRPackages { @@ -48,12 +49,22 @@ public class TestRFFIPackage extends TestRPackages { * micro-tests in one big test. It might be that this should be switched to an R file-based * approach as the number of tests increase. */ - private void assertEvalWithLibWithSetup(String setup, String test) { - assertEval(TestBase.template("{ library(\"testrffi\", lib.loc = \"%0\"); " + setup + "x <- " + test + "; detach(\"package:testrffi\", unload=T); x }", new String[]{TestRPackages.libLoc()})); + private void assertEvalWithLibWithSetupAndTrait(TestTrait trait, String setup, String test) { + String[] tests = TestBase.template("{ library(\"testrffi\", lib.loc = \"%0\"); " + setup + "x <- " + test + "; detach(\"package:testrffi\", unload=T); x }", + new String[]{TestRPackages.libLoc()}); + if (trait == null) { + assertEval(tests); + } else { + assertEval(trait, tests); + } } private void assertEvalWithLib(String test) { - assertEvalWithLibWithSetup("", test); + assertEvalWithLibWithSetupAndTrait(null, "", test); + } + + private void assertEvalWithLibWithSetup(String setup, String test) { + assertEvalWithLibWithSetupAndTrait(null, setup, test); } @Test @@ -165,4 +176,44 @@ public class TestRFFIPackage extends TestRPackages { public void testRFFI20() { assertEvalWithLibWithSetup("x <- \"12345\"; ", "rffi.char_length(x)"); } + + private static final String[] AS_VALUES = new String[]{"1L", "2", "2.2", "T", "integer()", "numeric()", "logical()", "character()", "c(5,6)", "c(2.3, 3.4)", "c(T, F)", + "as.symbol(\"sym\")", "list()"}; + + private static final String[] AS_FUNS = new String[]{"Char", "Integer", "Real", "Logical"}; + + @Test + public void testAsFunctions() { + String[] asCalls = template("x <- append(x, rffi.as%0(%1)); ", AS_FUNS, AS_VALUES); + assertEvalWithLibWithSetupAndTrait(Output.MayIgnoreWarningContext, "x <- list(); ", flatten(asCalls)); + } + + private static final String[] LIST_FUNS = new String[]{"CAR", "CDR"}; + + private static final String[] LIST_VALUES = new String[]{"pairlist(1,2)", "pairlist(x=1L, y=2L)"}; + + @Test + public void testListFunctions() { + String[] calls = template("x <- append(x, rffi.%0(%1)); ", LIST_FUNS, LIST_VALUES); + assertEvalWithLibWithSetupAndTrait(Output.MayIgnoreErrorContext, "x <- list(); ", flatten(calls)); + + } + + private static String flatten(String[] tests) { + StringBuilder sb = new StringBuilder(); + for (String test : tests) { + sb.append(test); + } + return sb.toString(); + } + + private static final String[] LENGTH_VALUES = new String[]{"1", "c(1,2,3)", "list(1,2,3)", "expression(1,2)"}; + + // Checkstyle: stop method name check + @Test + public void TestLENGTH() { + String[] calls = template("x <- append(x, rffi.LENGTH(%0)); ", LENGTH_VALUES); + assertEvalWithLibWithSetupAndTrait(Output.MayIgnoreErrorContext, "x <- list(); ", flatten(calls)); + } + } diff --git a/mx.fastr/suite.py b/mx.fastr/suite.py index 347e963809bda3f4b3530ec00eb103088bb3ae12..a556b1a51e80115339ef0f4014b5dcf0035ab2f7 100644 --- a/mx.fastr/suite.py +++ b/mx.fastr/suite.py @@ -230,7 +230,7 @@ suite = { "com.oracle.truffle.r.runtime.ffi" : { "sourceDirs" : ["src"], "dependencies" : [ - "com.oracle.truffle.r.runtime", + "com.oracle.truffle.r.nodes", ], "checkstyle" : "com.oracle.truffle.r.runtime", "javaCompliance" : "1.8", @@ -253,7 +253,6 @@ suite = { "com.oracle.truffle.r.library" : { "sourceDirs" : ["src"], "dependencies" : [ - "com.oracle.truffle.r.nodes", "com.oracle.truffle.r.runtime.ffi", ], "annotationProcessors" : [