diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RForeignAccessFactoryImpl.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RForeignAccessFactoryImpl.java index b2c2a28a826ed7994a44f37c6aac5c3514170fe2..1b8aca885df504ab57b6b46bcac74eec7523a8b6 100644 --- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RForeignAccessFactoryImpl.java +++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RForeignAccessFactoryImpl.java @@ -22,11 +22,8 @@ */ package com.oracle.truffle.r.engine.interop; -import com.oracle.truffle.api.Assumption; import com.oracle.truffle.api.CompilerAsserts; -import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.interop.ForeignAccess; import com.oracle.truffle.api.interop.MessageResolution; @@ -36,23 +33,13 @@ import com.oracle.truffle.r.engine.TruffleRLanguage; import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.context.RForeignAccessFactory; -import com.oracle.truffle.r.runtime.data.RComplex; -import com.oracle.truffle.r.runtime.data.RComplexVector; import com.oracle.truffle.r.runtime.data.RDouble; -import com.oracle.truffle.r.runtime.data.RDoubleSequence; -import com.oracle.truffle.r.runtime.data.RDoubleVector; import com.oracle.truffle.r.runtime.data.RExternalPtr; import com.oracle.truffle.r.runtime.data.RFunction; -import com.oracle.truffle.r.runtime.data.RIntSequence; -import com.oracle.truffle.r.runtime.data.RIntVector; import com.oracle.truffle.r.runtime.data.RInteger; import com.oracle.truffle.r.runtime.data.RList; -import com.oracle.truffle.r.runtime.data.RLogicalVector; import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.RPairList; -import com.oracle.truffle.r.runtime.data.RRaw; -import com.oracle.truffle.r.runtime.data.RRawVector; -import com.oracle.truffle.r.runtime.data.RStringVector; import com.oracle.truffle.r.runtime.data.RSymbol; import com.oracle.truffle.r.runtime.data.RTruffleObject; import com.oracle.truffle.r.runtime.data.RUnboundValue; @@ -60,8 +47,6 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractVector; import com.oracle.truffle.r.runtime.env.REnvironment; import com.oracle.truffle.r.runtime.ffi.CharSXPWrapper; import com.oracle.truffle.r.runtime.ffi.DLL; -import com.oracle.truffle.r.runtime.ffi.DLL.DLLInfo; -import com.oracle.truffle.r.runtime.ffi.DLL.DotSymbol; /** * A {@link ForeignAccess} instance captures the {@link Thread} that creates it and all uses are @@ -73,16 +58,6 @@ import com.oracle.truffle.r.runtime.ffi.DLL.DotSymbol; * This factory provides a generic solution for all FastR types (all of which are * {@link TruffleObject}s), at some cost in performance. * - * The REALLY bad news is that we cannot use {@link RContext} to store the state because, although - * that should be possible, at the time the call to {@link #getForeignAccess(RTruffleObject)} - * happens the {@link RContext} may not have been associated with a thread, so - * {@link RContext#getInstance()} will fail. In short the mapping has to be established using - * {@link Thread} not {@link RContext} and there is no call that informs us ahead of a call to - * {@link #getForeignAccess} that a new thread is in play. We use a Truffle {@link Assumption} to - * provide a fast path in the normal, single-threaded, case. TODO Apparently a call to - * {@link #getForeignAccess(RTruffleObject)} should,in fact, only occur on the slow path, and an - * assertion to that effect has been added. If true, then the fast path code can be simplified. - * * For most types we use the {@link MessageResolution} facility to automatically generate the * factory for creating the {@link ForeignAccess} instance. The exceptions are the (many) subclasses * of {@link RAbstractVector} as these have the same handling but the generator cannot handle @@ -90,198 +65,90 @@ import com.oracle.truffle.r.runtime.ffi.DLL.DotSymbol; * */ public final class RForeignAccessFactoryImpl implements RForeignAccessFactory { - /** - * The subset of the full set of types that are supported for foreign access. N.B. This list - * includes types that are not expected to travel between high-level languages, but may travel - * into the native world (when implemented in Truffle). - */ - private static final Class<?>[] FOREIGN_CLASSES = new Class<?>[]{ - RRaw.class, RComplex.class, RIntSequence.class, - RDoubleSequence.class, RIntVector.class, RDoubleVector.class, - RRawVector.class, RComplexVector.class, RStringVector.class, RLogicalVector.class, - RFunction.class, RNull.class, REnvironment.class, - RList.class, RSymbol.class, - RPairList.class, RExternalPtr.class, RUnboundValue.class, - DLLInfo.class, DotSymbol.class, - NativeRawArray.class, NativeCharArray.class, NativeIntegerArray.class, - NativeDoubleArray.class, NativeLogicalArray.class, - RDouble.class, RInteger.class, CharSXPWrapper.class}; - - private static final class ForeignAccessState { - - private static final class TableEntry { - private final Class<? extends RTruffleObject> clazz; // for sanity check - private final ForeignAccess foreignAccess; - - private TableEntry(Class<? extends RTruffleObject> clazz, ForeignAccess foreignAccess) { - this.clazz = clazz; - this.foreignAccess = foreignAccess; - } - } - + private static final class TableEntry { + private final Class<? extends RTruffleObject> clazz; // for sanity check + private final ForeignAccess foreignAccess; /** - * Table with a unique index for each class in {@link #FOREIGN_CLASSES}. - */ - private static Class<?>[] classTable; - /** - * Isomorphic to {@link #classTable} but contains the {@link ForeignAccess} instance. - */ - private final TableEntry[] table; - /** - * Mask to efficiently compute the table index. - */ - @CompilationFinal private static int tableMask; - /** - * The thread that this state is generated for. + * {@link PolyglotEngine} checks the thread on a {@link ForeignAccess}. */ private final Thread thread; - private ForeignAccessState() { + private TableEntry(Class<? extends RTruffleObject> clazz, ForeignAccess foreignAccess) { + this.clazz = clazz; + this.foreignAccess = foreignAccess; this.thread = Thread.currentThread(); - table = new TableEntry[classTable.length]; - for (int i = 0; i < table.length; i++) { - @SuppressWarnings("unchecked") - Class<? extends RTruffleObject> checkedClass = (Class<? extends RTruffleObject>) classTable[i]; - if (checkedClass != null) { - table[i] = new TableEntry(checkedClass, createForeignAccess(checkedClass)); - } - } - } - - private ForeignAccess get(RTruffleObject obj) { - Class<? extends RTruffleObject> clazz = obj.getClass(); - return get(clazz); } + } - private ForeignAccess get(Class<? extends RTruffleObject> clazz) { - int index = System.identityHashCode(clazz) & tableMask; - assert table[index].clazz == clazz; - return table[index].foreignAccess; - } + private final TableEntry[] table = new TableEntry[32]; + int tableIndex; - static { - generatePrototypeTable(); - } - - /** - * Create a table that has a unique index for every member of {@link #FOREIGN_CLASSES} for - * efficient access. Since {@link System#identityHashCode(Object)} can vary from run to run, - * the size of the table may vary, but is typically in the range 64-4096. - */ - private static void generatePrototypeTable() { - int ts = 32; - while (true) { - classTable = new Class<?>[ts]; - boolean collision = false; - for (int i = 0; i < FOREIGN_CLASSES.length; i++) { - Class<?> clazz = FOREIGN_CLASSES[i]; - int h = System.identityHashCode(clazz); - int hc = h % ts; - if (classTable[hc] == null) { - classTable[hc] = clazz; - } else { - collision = true; - break; - } - } - if (!collision) { - break; - } else { - ts = ts * 2; - } + private synchronized ForeignAccess get(RTruffleObject obj) { + Class<? extends RTruffleObject> objclazz = obj.getClass(); + Thread thread = Thread.currentThread(); + for (int i = 0; i < tableIndex; i++) { + TableEntry te = table[i]; + if (te.clazz == objclazz && te.thread == thread) { + return te.foreignAccess; } - tableMask = ts - 1; } + return createForeignAccess(objclazz); + } - @TruffleBoundary - private static ForeignAccess createForeignAccess(Class<? extends RTruffleObject> clazz) { - ForeignAccess foreignAccess = null; - String name = clazz.getSimpleName(); - if (RNull.class.isAssignableFrom(clazz)) { - foreignAccess = RNullMRForeign.createAccess(); - } else if (RList.class.isAssignableFrom(clazz)) { - foreignAccess = RListMRForeign.createAccess(); - } else if (REnvironment.class.isAssignableFrom(clazz)) { - foreignAccess = REnvironmentMRForeign.createAccess(); - } else if (RPairList.class.isAssignableFrom(clazz)) { - foreignAccess = RPairListMRForeign.createAccess(); - } else if (RFunction.class.isAssignableFrom(clazz)) { - foreignAccess = RFunctionMRForeign.createAccess(); - } else if (DLL.DLLInfo.class.isAssignableFrom(clazz)) { - foreignAccess = DLLInfoMRForeign.createAccess(); - } else if (DLL.DotSymbol.class.isAssignableFrom(clazz)) { - foreignAccess = DLLDotSymbolMRForeign.createAccess(); - } else if (RSymbol.class.isAssignableFrom(clazz)) { - foreignAccess = RSymbolMRForeign.createAccess(); - } else if (RExternalPtr.class.isAssignableFrom(clazz)) { - foreignAccess = RExternalPtrMRForeign.createAccess(); - } else if (RUnboundValue.class.isAssignableFrom(clazz)) { - foreignAccess = RUnboundValueMRForeign.createAccess(); - } else if (NativeRawArray.class.isAssignableFrom(clazz)) { - foreignAccess = NativeRawArrayMRForeign.createAccess(); - } else if (NativeLogicalArray.class.isAssignableFrom(clazz)) { - foreignAccess = NativeLogicalArrayMRForeign.createAccess(); - } else if (NativeCharArray.class.isAssignableFrom(clazz)) { - foreignAccess = NativeCharArrayMRForeign.createAccess(); - } else if (NativeDoubleArray.class.isAssignableFrom(clazz)) { - foreignAccess = NativeDoubleArrayMRForeign.createAccess(); - } else if (NativeIntegerArray.class.isAssignableFrom(clazz)) { - foreignAccess = NativeIntegerArrayMRForeign.createAccess(); - } else if (RInteger.class.isAssignableFrom(clazz)) { - foreignAccess = RIntegerMRForeign.createAccess(); - } else if (RDouble.class.isAssignableFrom(clazz)) { - foreignAccess = RDoubleMRForeign.createAccess(); - } else if (CharSXPWrapper.class.isAssignableFrom(clazz)) { - foreignAccess = CharSXPWrapperMRForeign.createAccess(); + @TruffleBoundary + private static ForeignAccess createForeignAccess(Class<? extends RTruffleObject> clazz) { + ForeignAccess foreignAccess = null; + String name = clazz.getSimpleName(); + if (RNull.class.isAssignableFrom(clazz)) { + foreignAccess = RNullMRForeign.createAccess(); + } else if (RList.class.isAssignableFrom(clazz)) { + foreignAccess = RListMRForeign.createAccess(); + } else if (REnvironment.class.isAssignableFrom(clazz)) { + foreignAccess = REnvironmentMRForeign.createAccess(); + } else if (RPairList.class.isAssignableFrom(clazz)) { + foreignAccess = RPairListMRForeign.createAccess(); + } else if (RFunction.class.isAssignableFrom(clazz)) { + foreignAccess = RFunctionMRForeign.createAccess(); + } else if (DLL.DLLInfo.class.isAssignableFrom(clazz)) { + foreignAccess = DLLInfoMRForeign.createAccess(); + } else if (DLL.DotSymbol.class.isAssignableFrom(clazz)) { + foreignAccess = DLLDotSymbolMRForeign.createAccess(); + } else if (RSymbol.class.isAssignableFrom(clazz)) { + foreignAccess = RSymbolMRForeign.createAccess(); + } else if (RExternalPtr.class.isAssignableFrom(clazz)) { + foreignAccess = RExternalPtrMRForeign.createAccess(); + } else if (RUnboundValue.class.isAssignableFrom(clazz)) { + foreignAccess = RUnboundValueMRForeign.createAccess(); + } else if (NativeRawArray.class.isAssignableFrom(clazz)) { + foreignAccess = NativeRawArrayMRForeign.createAccess(); + } else if (NativeLogicalArray.class.isAssignableFrom(clazz)) { + foreignAccess = NativeLogicalArrayMRForeign.createAccess(); + } else if (NativeCharArray.class.isAssignableFrom(clazz)) { + foreignAccess = NativeCharArrayMRForeign.createAccess(); + } else if (NativeDoubleArray.class.isAssignableFrom(clazz)) { + foreignAccess = NativeDoubleArrayMRForeign.createAccess(); + } else if (NativeIntegerArray.class.isAssignableFrom(clazz)) { + foreignAccess = NativeIntegerArrayMRForeign.createAccess(); + } else if (RInteger.class.isAssignableFrom(clazz)) { + foreignAccess = RIntegerMRForeign.createAccess(); + } else if (RDouble.class.isAssignableFrom(clazz)) { + foreignAccess = RDoubleMRForeign.createAccess(); + } else if (CharSXPWrapper.class.isAssignableFrom(clazz)) { + foreignAccess = CharSXPWrapperMRForeign.createAccess(); + } else { + if (RAbstractVector.class.isAssignableFrom(clazz)) { + foreignAccess = ForeignAccess.create(RAbstractVector.class, new RAbstractVectorAccessFactory()); } else { - if (RAbstractVector.class.isAssignableFrom(clazz)) { - foreignAccess = ForeignAccess.create(RAbstractVector.class, new RAbstractVectorAccessFactory()); - } else { - throw RInternalError.unimplemented("foreignAccess: " + name); - } + throw RInternalError.unimplemented("foreignAccess: " + name); } - return foreignAccess; } + return foreignAccess; } - /** - * In normal execution, there is only one thread. - */ - private static final Assumption singleStateAssumption = Truffle.getRuntime().createAssumption("single ForeignAccessState"); - /** - * In case of multiple threads, the per-thread state. - */ - private static final ThreadLocal<ForeignAccessState> threadLocalState = new ThreadLocal<>(); - /** - * In single thread mode, a fast path to the state. In multi-thread mode set to {@code null}. - */ - @CompilationFinal private static ForeignAccessState singleForeignAccessState; - @Override public ForeignAccess getForeignAccess(RTruffleObject obj) { CompilerAsserts.neverPartOfCompilation("getForeignAccess"); - ForeignAccessState foreignAccessState; - if (singleStateAssumption.isValid()) { - foreignAccessState = singleForeignAccessState; - if (foreignAccessState == null) { - // very first call - foreignAccessState = new ForeignAccessState(); - singleForeignAccessState = foreignAccessState; - threadLocalState.set(foreignAccessState); - } else { - // check thread - if (Thread.currentThread() != foreignAccessState.thread) { - singleStateAssumption.invalidate(); - singleForeignAccessState = null; - foreignAccessState = new ForeignAccessState(); - } - } - } else { - // use the threadLocal - foreignAccessState = threadLocalState.get(); - } - ForeignAccess result = foreignAccessState.get(obj); - return result; + return get(obj); } @Override diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/llvm/TruffleLLVM_UpCallsRFFIImpl.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/llvm/TruffleLLVM_UpCallsRFFIImpl.java index ba772aadafd1ae5e92c821eaa469420bf0f711e6..d5f87c515079f54d6310322924b28f21b450b839 100644 --- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/llvm/TruffleLLVM_UpCallsRFFIImpl.java +++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/llvm/TruffleLLVM_UpCallsRFFIImpl.java @@ -32,7 +32,7 @@ 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.nodes.ffi.JavaUpCallsRFFIImpl; import com.oracle.truffle.r.runtime.REnvVars; import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.data.RDataFactory; @@ -47,10 +47,10 @@ import com.oracle.truffle.r.runtime.ffi.CharSXPWrapper; import com.oracle.truffle.r.runtime.ffi.RFFIVariables; /** - * (Incomplete) Variant of {@link UpCallsRFFIImpl} for Truffle LLVM. + * (Incomplete) Variant of {@link JavaUpCallsRFFIImpl} for Truffle LLVM. * */ -public class TruffleLLVM_UpCallsRFFIImpl extends UpCallsRFFIImpl implements VariableUpCallsRFFI { +public class TruffleLLVM_UpCallsRFFIImpl extends JavaUpCallsRFFIImpl implements VariableUpCallsRFFI { private static TruffleLLVM_UpCallsRFFIImpl singleton; private static TruffleObject singletonTruffleObject; @@ -69,14 +69,16 @@ public class TruffleLLVM_UpCallsRFFIImpl extends UpCallsRFFIImpl implements Vari // Checkstyle: stop method name check - public Object Rf_mkCharLenCE(Object bytes, int encoding) { + @Override + public Object Rf_mkCharLenCE(Object bytes, int len, int encoding) { if (bytes instanceof NativeCharArray) { - return super.Rf_mkCharLenCE(((NativeCharArray) bytes).getBytes(), encoding); + return super.Rf_mkCharLenCE(((NativeCharArray) bytes).getBytes(), len, encoding); } else { throw RInternalError.unimplemented(); } } + @Override public Object Rf_install(Object name) { if (name instanceof NativeCharArray) { return RDataFactory.createSymbolInterned(new String(((NativeCharArray) name).getBytes(), StandardCharsets.UTF_8)); 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 5d57760780e479a08eff65ae183d677e4c88a9a1..92b618c6f10d6e92dcbdb2ea16f1b375b9cdb1c8 100644 --- a/com.oracle.truffle.r.native/fficall/src/jni/Rinternals.c +++ b/com.oracle.truffle.r.native/fficall/src/jni/Rinternals.c @@ -151,24 +151,24 @@ void init_internals(JNIEnv *env) { Rf_setAttribMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_setAttrib", "(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)V", 0); Rf_isStringMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_isString", "(Ljava/lang/Object;)I", 0); Rf_isNullMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_isNull", "(Ljava/lang/Object;)I", 0); - Rf_installMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_install", "(Ljava/lang/String;)Ljava/lang/Object;", 0); - Rf_warningMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_warning", "(Ljava/lang/String;)V", 0); - Rf_warningcallMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_warningcall", "(Ljava/lang/Object;Ljava/lang/String;)V", 0); - Rf_errorMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_error", "(Ljava/lang/String;)V", 0); + Rf_installMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_install", "(Ljava/lang/Object;)Ljava/lang/Object;", 0); + Rf_warningMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_warning", "(Ljava/lang/Object;)V", 0); + Rf_warningcallMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_warningcall", "(Ljava/lang/Object;Ljava/lang/Object;)V", 0); + Rf_errorMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_error", "(Ljava/lang/Object;)V", 0); Rf_allocateVectorMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_allocateVector", "(II)Ljava/lang/Object;", 0); Rf_allocateMatrixMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_allocateMatrix", "(III)Ljava/lang/Object;", 0); Rf_allocateArrayMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_allocateArray", "(ILjava/lang/Object;)Ljava/lang/Object;", 0); Rf_duplicateMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_duplicate", "(Ljava/lang/Object;I)Ljava/lang/Object;", 0); Rf_anyDuplicatedMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_anyDuplicated", "(Ljava/lang/Object;I)I", 0); - R_NewHashedEnvMethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_NewHashedEnv", "(Lcom/oracle/truffle/r/runtime/env/REnvironment;Ljava/lang/String;ZI)Lcom/oracle/truffle/r/runtime/env/REnvironment;", 0); + R_NewHashedEnvMethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_NewHashedEnv", "(Lcom/oracle/truffle/r/runtime/env/REnvironment;I)Lcom/oracle/truffle/r/runtime/env/REnvironment;", 0); Rf_classgetsMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_classgets", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", 0); - RprintfMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rprintf", "(Ljava/lang/String;)V", 0); - R_do_MAKE_CLASS_MethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_do_MAKE_CLASS", "(Ljava/lang/String;)Ljava/lang/Object;", 0); + RprintfMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rprintf", "(Ljava/lang/Object;)V", 0); + R_do_MAKE_CLASS_MethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_do_MAKE_CLASS", "(Ljava/lang/Object;)Ljava/lang/Object;", 0); R_FindNamespaceMethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_FindNamespace", "(Ljava/lang/Object;)Ljava/lang/Object;", 0); R_BindingIsLockedID = checkGetMethodID(env, UpCallsRFFIClass, "R_BindingIsLocked", "(Ljava/lang/Object;Ljava/lang/Object;)I", 0); Rf_GetOption1MethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_GetOption1", "(Ljava/lang/Object;)Ljava/lang/Object;", 0); Rf_gsetVarMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_gsetVar", "(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)V", 0); - Rf_inheritsMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_inherits", "(Ljava/lang/Object;Ljava/lang/String;)I", 0); + Rf_inheritsMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_inherits", "(Ljava/lang/Object;Ljava/lang/Object;)I", 0); Rf_lengthgetsMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_lengthgets", "(Ljava/lang/Object;I)Ljava/lang/Object;", 0); // Rf_rPsortMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_rPsort", "(Lcom/oracle/truffle/r/runtime/data/RDoubleVector;II)", 0); // Rf_iPsortMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_iPsort", "(Lcom/oracle/truffle/r/runtime/data/RIntVector;II)", 0); @@ -197,7 +197,7 @@ void init_internals(JNIEnv *env) { 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_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_mkCharLenCEMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_mkCharLenCE", "(Ljava/lang/Object;II)Ljava/lang/Object;", 0); Rf_asLogicalMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_asLogical", "(Ljava/lang/Object;)I", 0); Rf_PairToVectorListMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_PairToVectorList", "(Ljava/lang/Object;)Ljava/lang/Object;", 0); NAMED_MethodID = checkGetMethodID(env, UpCallsRFFIClass, "NAMED", "(Ljava/lang/Object;)I", 0); @@ -527,7 +527,7 @@ SEXP Rf_mkCharLenCE(const char *x, int len, cetype_t enc) { JNIEnv *thisenv = getEnv(); jbyteArray bytes = (*thisenv)->NewByteArray(thisenv, len); (*thisenv)->SetByteArrayRegion(thisenv, bytes, 0, len, (const jbyte *) x); - SEXP result = (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, Rf_mkCharLenCEMethodID, bytes, (int) enc); + SEXP result = (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, Rf_mkCharLenCEMethodID, bytes, len, (int) enc); return checkRef(thisenv, result); } 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 index 1c159c108c494f4d645280b917ea9c78937a6934..6cd1f9fe0e8c635adc38406c9c9cdcd95d5a8572 100644 --- 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 @@ -29,11 +29,17 @@ 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.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.RInternalError; import com.oracle.truffle.r.runtime.context.RContext; public final class FFIUpCallRootNode extends RootNode { - private static RootCallTarget[] rootCallTargets = new RootCallTarget[UpCallsIndex.TABLE_LENGTH]; + private static final RootCallTarget[] rootCallTargets = new RootCallTarget[RFFIUpCallMethod.values().length]; @Child private FFIUpCallNode theFFIUpCallNode; private final int numArgs; @@ -61,15 +67,29 @@ public final class FFIUpCallRootNode extends RootNode { } } - static void add(int index, Supplier<FFIUpCallNode> constructor) { + static void add(RFFIUpCallMethod upCallMethod, Supplier<FFIUpCallNode> constructor) { + FFIUpCallRootNode rootNode = new FFIUpCallRootNode(constructor.get()); - rootCallTargets[index] = Truffle.getRuntime().createCallTarget(rootNode); + rootCallTargets[upCallMethod.ordinal()] = Truffle.getRuntime().createCallTarget(rootNode); } - public static RootCallTarget getCallTarget(int index) { - RootCallTarget target = rootCallTargets[index]; + public static RootCallTarget getCallTarget(RFFIUpCallMethod upCallMethod) { + RootCallTarget target = rootCallTargets[upCallMethod.ordinal()]; assert target != null; return target; } + static void register() { + FFIUpCallRootNode.add(RFFIUpCallMethod.Rf_asReal, AsRealNodeGen::create); + FFIUpCallRootNode.add(RFFIUpCallMethod.Rf_asLogical, AsLogicalNodeGen::create); + FFIUpCallRootNode.add(RFFIUpCallMethod.Rf_asInteger, AsIntegerNodeGen::create); + FFIUpCallRootNode.add(RFFIUpCallMethod.Rf_asChar, AsCharNodeGen::create); + FFIUpCallRootNode.add(RFFIUpCallMethod.CAR, CARNodeGen::create); + FFIUpCallRootNode.add(RFFIUpCallMethod.CDR, CDRNodeGen::create); + FFIUpCallRootNode.add(RFFIUpCallMethod.CADR, CADRNodeGen::create); + FFIUpCallRootNode.add(RFFIUpCallMethod.CADDR, CADDRNodeGen::create); + FFIUpCallRootNode.add(RFFIUpCallMethod.CDDR, CDDRNodeGen::create); + FFIUpCallRootNode.add(RFFIUpCallMethod.LENGTH, LENGTHNodeGen::create); + } + } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/JavaUpCallsRFFIImpl.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/JavaUpCallsRFFIImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..8441fc32c7dec2c65d0a48bd48be67c685ac538c --- /dev/null +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/JavaUpCallsRFFIImpl.java @@ -0,0 +1,1145 @@ +/* + * 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 static com.oracle.truffle.r.nodes.ffi.RFFIUtils.*; + +import java.nio.charset.StandardCharsets; +import java.util.function.Function; + +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.frame.Frame; +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; +import com.oracle.truffle.r.runtime.REnvVars; +import com.oracle.truffle.r.runtime.RError; +import com.oracle.truffle.r.runtime.RErrorHandling; +import com.oracle.truffle.r.runtime.RInternalError; +import com.oracle.truffle.r.runtime.RRuntime; +import com.oracle.truffle.r.runtime.RSource; +import com.oracle.truffle.r.runtime.RSrcref; +import com.oracle.truffle.r.runtime.RStartParams.SA_TYPE; +import com.oracle.truffle.r.runtime.RType; +import com.oracle.truffle.r.runtime.Utils; +import com.oracle.truffle.r.runtime.context.Engine.ParseException; +import com.oracle.truffle.r.runtime.context.RContext; +import com.oracle.truffle.r.runtime.data.RAttributable; +import com.oracle.truffle.r.runtime.data.RAttributesLayout; +import com.oracle.truffle.r.runtime.data.RComplex; +import com.oracle.truffle.r.runtime.data.RComplexVector; +import com.oracle.truffle.r.runtime.data.RDataFactory; +import com.oracle.truffle.r.runtime.data.RDoubleSequence; +import com.oracle.truffle.r.runtime.data.RDoubleVector; +import com.oracle.truffle.r.runtime.data.RExpression; +import com.oracle.truffle.r.runtime.data.RExternalPtr; +import com.oracle.truffle.r.runtime.data.RFunction; +import com.oracle.truffle.r.runtime.data.RIntSequence; +import com.oracle.truffle.r.runtime.data.RIntVector; +import com.oracle.truffle.r.runtime.data.RLanguage; +import com.oracle.truffle.r.runtime.data.RList; +import com.oracle.truffle.r.runtime.data.RLogicalVector; +import com.oracle.truffle.r.runtime.data.RNull; +import com.oracle.truffle.r.runtime.data.RPairList; +import com.oracle.truffle.r.runtime.data.RPromise; +import com.oracle.truffle.r.runtime.data.RRaw; +import com.oracle.truffle.r.runtime.data.RRawVector; +import com.oracle.truffle.r.runtime.data.RS4Object; +import com.oracle.truffle.r.runtime.data.RSequence; +import com.oracle.truffle.r.runtime.data.RShareable; +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.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.gnur.SEXPTYPE; +import com.oracle.truffle.r.runtime.nodes.DuplicationHelper; +import com.oracle.truffle.r.runtime.nodes.RNode; +import com.oracle.truffle.r.runtime.rng.RRNG; + +/** + * This class provides a simple Java-based implementation of {@link UpCallsRFFI}, where all the + * argument values are standarde Java types, i.e. no special types used by Truffle NFI or Truffle + * LLVM. + * + * TODO Many of the implementations here are incomplete and/or duplicate code that exists in the + * Truffle side of the implementation, i.e., {@link RNode} subclasses. A complete refactoring that + * accesses the Truffle implementations (possibly somewhat refactored owing to the fact that the + * Truffle side is driven by the builtins yet these functions don't not always map 1-1 to a builtin) + * 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 JavaUpCallsRFFIImpl implements UpCallsRFFI { + + // Checkstyle: stop method name check + + @Override + public RIntVector Rf_ScalarInteger(int value) { + return RDataFactory.createIntVectorFromScalar(value); + } + + @Override + public RLogicalVector Rf_ScalarLogical(int value) { + byte byteValue; + if (value == RRuntime.INT_NA) { + byteValue = RRuntime.LOGICAL_NA; + } else { + byteValue = (byte) (value & 0xFF); + } + return RDataFactory.createLogicalVectorFromScalar(byteValue); + } + + @Override + public RDoubleVector Rf_ScalarDouble(double value) { + return RDataFactory.createDoubleVectorFromScalar(value); + } + + @Override + public RStringVector Rf_ScalarString(Object value) { + CharSXPWrapper chars = guaranteeInstanceOf(value, CharSXPWrapper.class); + return RDataFactory.createStringVectorFromScalar(chars.getContents()); + } + + @Override + public int Rf_asInteger(Object x) { + return (int) FFIUpCallRootNode.getCallTarget(RFFIUpCallMethod.Rf_asInteger).call(x); + } + + @Override + public double Rf_asReal(Object x) { + return (double) FFIUpCallRootNode.getCallTarget(RFFIUpCallMethod.Rf_asReal).call(x); + } + + @Override + public int Rf_asLogical(Object x) { + return (int) FFIUpCallRootNode.getCallTarget(RFFIUpCallMethod.Rf_asLogical).call(x); + } + + @Override + public Object Rf_asChar(Object x) { + return FFIUpCallRootNode.getCallTarget(RFFIUpCallMethod.Rf_asChar).call(x); + } + + @Override + public Object Rf_mkCharLenCE(Object bytes, int len, int encoding) { + // TODO: handle encoding properly + return CharSXPWrapper.create(new String((byte[]) bytes, StandardCharsets.UTF_8)); + } + + @Override + public Object Rf_cons(Object car, Object cdr) { + return RDataFactory.createPairList(car, cdr); + } + + @Override + public void Rf_defineVar(Object symbolArg, Object value, Object envArg) { + REnvironment env = (REnvironment) envArg; + RSymbol name = (RSymbol) symbolArg; + try { + env.put(name.getName(), value); + } catch (PutException ex) { + throw RError.error(RError.SHOW_CALLER2, ex); + } + } + + @Override + public Object R_do_MAKE_CLASS(Object 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), null, clazz); + } + + @Override + public Object Rf_findVar(Object symbolArg, Object envArg) { + return findVarInFrameHelper(envArg, symbolArg, true); + } + + @Override + public Object Rf_findVarInFrame(Object envArg, Object symbolArg) { + return findVarInFrameHelper(envArg, symbolArg, false); + } + + @Override + public Object Rf_findVarInFrame3(Object envArg, Object symbolArg, int doGet) { + // GNU R has code for IS_USER_DATBASE that uses doGet + // This is a lookup in the single environment (envArg) only, i.e. inherits=false + return findVarInFrameHelper(envArg, symbolArg, false); + } + + private static Object findVarInFrameHelper(Object envArg, Object symbolArg, boolean inherits) { + if (envArg == RNull.instance) { + throw RError.error(RError.SHOW_CALLER2, RError.Message.USE_NULL_ENV_DEFUNCT); + } + if (!(envArg instanceof REnvironment)) { + throw RError.error(RError.SHOW_CALLER2, RError.Message.ARG_NOT_AN_ENVIRONMENT, inherits ? "findVar" : "findVarInFrame"); + } + RSymbol name = (RSymbol) symbolArg; + REnvironment env = (REnvironment) envArg; + while (env != REnvironment.emptyEnv()) { + Object value = env.get(name.getName()); + if (value != null) { + return value; + } + if (!inherits) { + // simgle frame lookup + break; + } + env = env.getParent(); + } + return RUnboundValue.instance; + } + + @Override + public Object Rf_getAttrib(Object obj, Object name) { + Object result = RNull.instance; + if (obj instanceof RAttributable) { + RAttributable attrObj = (RAttributable) obj; + DynamicObject attrs = attrObj.getAttributes(); + if (attrs != null) { + String nameAsString = ((RSymbol) name).getName().intern(); + Object attr = attrs.get(nameAsString); + if (attr != null) { + result = attr; + } + } + } + return result; + } + + @Override + @TruffleBoundary + public void Rf_setAttrib(Object obj, Object name, Object val) { + if (obj instanceof RAttributable) { + RAttributable attrObj = (RAttributable) obj; + String nameAsString; + if (name instanceof RSymbol) { + nameAsString = ((RSymbol) name).getName(); + } else { + nameAsString = RRuntime.asString(name); + assert nameAsString != null; + } + nameAsString = nameAsString.intern(); + if (val == RNull.instance) { + removeAttr(attrObj, nameAsString); + } else if ("class" == nameAsString) { + attrObj.initAttributes().define(nameAsString, val); + } else { + attrObj.setAttr(nameAsString, val); + } + } + } + + @TruffleBoundary + private static void removeAttr(RAttributable a, String name) { + a.removeAttr(name); + } + + public static RStringVector getClassHr(Object v) { + RStringVector result; + if (v instanceof RAttributable) { + result = ((RAttributable) v).getClassHierarchy(); + } else if (v instanceof Byte) { + result = RLogicalVector.implicitClassHeader; + } else if (v instanceof String) { + result = RStringVector.implicitClassHeader; + } else if (v instanceof Integer) { + result = RIntVector.implicitClassHeader; + } else if (v instanceof Double) { + result = RDoubleVector.implicitClassHeader; + } else if (v instanceof RComplex) { + result = RComplexVector.implicitClassHeader; + } else if (v instanceof RRaw) { + result = RRawVector.implicitClassHeader; + } else { + guaranteeInstanceOf(v, RNull.class); + result = RNull.implicitClassHeader; + } + return result; + } + + @Override + public int Rf_inherits(Object x, Object clazz) { + int result = 0; + RStringVector hierarchy = getClassHr(x); + for (int i = 0; i < hierarchy.getLength(); i++) { + if (hierarchy.getDataAt(i).equals(clazz)) { + result = 1; + } + } + return result; + } + + @Override + public Object Rf_install(Object name) { + return RDataFactory.createSymbolInterned((String) name); + } + + @Override + public Object Rf_lengthgets(Object x, int newSize) { + RAbstractVector vec = (RAbstractVector) RRuntime.asAbstractVector(x); + return vec.resize(newSize); + } + + @Override + public int Rf_isString(Object x) { + return RRuntime.checkType(x, RType.Character) ? 1 : 0; + } + + @Override + public int Rf_isNull(Object x) { + return x == RNull.instance ? 1 : 0; + } + + @Override + public Object Rf_PairToVectorList(Object x) { + if (x == RNull.instance) { + return RDataFactory.createList(); + } + RPairList pl = (RPairList) x; + return pl.toRList(); + } + + @Override + public void Rf_error(Object msg) { + throw RError.error(RError.SHOW_CALLER2, RError.Message.GENERIC, msg); + } + + @Override + public void Rf_warning(Object msg) { + RError.warning(RError.SHOW_CALLER2, RError.Message.GENERIC, msg); + } + + @Override + public void Rf_warningcall(Object call, Object msg) { + RErrorHandling.warningcallRFFI(call, (String) msg); + } + + @Override + public Object Rf_allocateVector(int mode, int n) { + SEXPTYPE type = SEXPTYPE.mapInt(mode); + if (n < 0) { + throw RError.error(RError.SHOW_CALLER2, RError.Message.NEGATIVE_LENGTH_VECTORS_NOT_ALLOWED); + // TODO check long vector + } + switch (type) { + case INTSXP: + return RDataFactory.createIntVector(new int[n], RDataFactory.COMPLETE_VECTOR); + case REALSXP: + return RDataFactory.createDoubleVector(new double[n], RDataFactory.COMPLETE_VECTOR); + case LGLSXP: + return RDataFactory.createLogicalVector(new byte[n], RDataFactory.COMPLETE_VECTOR); + case STRSXP: + return RDataFactory.createStringVector(new String[n], RDataFactory.COMPLETE_VECTOR); + case CPLXSXP: + return RDataFactory.createComplexVector(new double[2 * n], RDataFactory.COMPLETE_VECTOR); + case RAWSXP: + return RDataFactory.createRawVector(new byte[n]); + case VECSXP: + return RDataFactory.createList(n); + case LANGSXP: + return RDataFactory.createLangPairList(n); + default: + throw unimplemented("unexpected SEXPTYPE " + type); + } + } + + @Override + public Object Rf_allocateArray(int mode, Object dimsObj) { + RIntVector dims = (RIntVector) dimsObj; + int n = 1; + int[] newDims = new int[dims.getLength()]; + // TODO check long vector + for (int i = 0; i < newDims.length; i++) { + newDims[i] = dims.getDataAt(i); + n *= newDims[i]; + } + RAbstractVector result = (RAbstractVector) Rf_allocateVector(mode, n); + setDims(newDims, result); + return result; + + } + + @TruffleBoundary + private static void setDims(int[] newDims, RAbstractVector result) { + result.setDimensions(newDims); + } + + @Override + public Object Rf_allocateMatrix(int mode, int nrow, int ncol) { + SEXPTYPE type = SEXPTYPE.mapInt(mode); + if (nrow < 0 || ncol < 0) { + throw RError.error(RError.SHOW_CALLER2, RError.Message.NEGATIVE_EXTENTS_TO_MATRIX); + } + // TODO check long vector + int[] dims = new int[]{nrow, ncol}; + switch (type) { + case INTSXP: + return RDataFactory.createIntVector(new int[nrow * ncol], RDataFactory.COMPLETE_VECTOR, dims); + case REALSXP: + return RDataFactory.createDoubleVector(new double[nrow * ncol], RDataFactory.COMPLETE_VECTOR, dims); + case LGLSXP: + return RDataFactory.createLogicalVector(new byte[nrow * ncol], RDataFactory.COMPLETE_VECTOR, dims); + case STRSXP: + return RDataFactory.createStringVector(new String[nrow * ncol], RDataFactory.COMPLETE_VECTOR, dims); + case CPLXSXP: + return RDataFactory.createComplexVector(new double[2 * (nrow * ncol)], RDataFactory.COMPLETE_VECTOR, dims); + default: + throw unimplemented(); + } + } + + @Override + public int Rf_nrows(Object x) { + return RRuntime.nrows(x); + } + + @Override + public int Rf_ncols(Object x) { + return RRuntime.ncols(x); + } + + @Override + public int LENGTH(Object x) { + return (int) FFIUpCallRootNode.getCallTarget(RFFIUpCallMethod.LENGTH).call(x); + } + + @Override + public void SET_STRING_ELT(Object x, int i, Object v) { + RStringVector vector = guaranteeInstanceOf(x, RStringVector.class); + CharSXPWrapper element = guaranteeInstanceOf(v, CharSXPWrapper.class); + vector.setElement(i, element.getContents()); + } + + @Override + public void SET_VECTOR_ELT(Object x, int i, Object v) { + RList list = guaranteeInstanceOf(x, RList.class); + list.setElement(i, v); + } + + @Override + public Object RAW(Object x) { + if (x instanceof RRawVector) { + return ((RRawVector) x).getDataWithoutCopying(); + } else if (x instanceof RRaw) { + return new byte[]{((RRaw) x).getValue()}; + } else { + throw unimplemented(); + } + } + + @Override + public Object LOGICAL(Object x) { + if (x instanceof RLogicalVector) { + return ((RLogicalVector) x).getDataWithoutCopying(); + } else if (x instanceof Byte) { + return new byte[]{(Byte) x}; + } else { + throw unimplemented(); + } + } + + @Override + public Object INTEGER(Object x) { + if (x instanceof RIntVector) { + return ((RIntVector) x).getDataWithoutCopying(); + } else if (x instanceof RIntSequence) { + return ((RIntSequence) x).materialize().getDataWithoutCopying(); + } else if (x instanceof Integer) { + return new int[]{(Integer) x}; + } else if (x instanceof RLogicalVector) { + RLogicalVector vec = (RLogicalVector) x; + int[] result = new int[vec.getLength()]; + for (int i = 0; i < result.length; i++) { + result[i] = vec.getDataAt(i); + } + return result; + } else { + guaranteeInstanceOf(x, Byte.class); + return new int[]{(Byte) x}; + } + } + + @Override + public Object REAL(Object x) { + if (x instanceof RDoubleVector) { + return ((RDoubleVector) x).getDataWithoutCopying(); + } else if (x instanceof RDoubleSequence) { + return ((RDoubleSequence) x).materialize().getDataWithoutCopying(); + } else { + guaranteeInstanceOf(x, Double.class); + return new double[]{(Double) x}; + } + } + + @Override + public Object STRING_ELT(Object x, int i) { + RAbstractStringVector vector = guaranteeInstanceOf(RRuntime.asAbstractVector(x), RAbstractStringVector.class); + return CharSXPWrapper.create(vector.getDataAt(i)); + } + + @Override + public Object VECTOR_ELT(Object x, int i) { + Object vec = x; + if (vec instanceof RExpression) { + return ((RExpression) vec).getDataAt(i); + } + RAbstractListVector list = guaranteeInstanceOf(RRuntime.asAbstractVector(vec), RAbstractListVector.class); + return list.getDataAt(i); + } + + @Override + public int NAMED(Object x) { + if (x instanceof RShareable) { + return ((RShareable) x).isShared() ? 1 : 0; + } else { + throw unimplemented(); + } + } + + @Override + public Object SET_TYPEOF_FASTR(Object x, int v) { + int code = SEXPTYPE.gnuRCodeForObject(x); + if (code == SEXPTYPE.LISTSXP.code && v == SEXPTYPE.LANGSXP.code) { + return RLanguage.fromList(x, RLanguage.RepType.CALL); + } else { + throw unimplemented(); + } + } + + @Override + public int TYPEOF(Object x) { + if (x instanceof CharSXPWrapper) { + return SEXPTYPE.CHARSXP.code; + } else { + return SEXPTYPE.gnuRCodeForObject(x); + } + } + + @Override + @TruffleBoundary + public int OBJECT(Object x) { + if (x instanceof RAttributable) { + return ((RAttributable) x).getAttr(RRuntime.CLASS_ATTR_KEY) == null ? 0 : 1; + } else { + return 0; + } + } + + @Override + public Object Rf_duplicate(Object x, int deep) { + guarantee(x != null, "unexpected type: null instead of " + x.getClass().getSimpleName()); + guarantee(x instanceof RShareable || x instanceof RSequence || x instanceof RExternalPtr, + "unexpected type: " + x + " is " + x.getClass().getSimpleName() + " instead of RShareable or RExternalPtr"); + if (x instanceof RShareable) { + return deep == 1 ? ((RShareable) x).deepCopy() : ((RShareable) x).copy(); + } else if (x instanceof RSequence) { + return ((RSequence) x).materializeToShareable(); + } else { + return ((RExternalPtr) x).copy(); + } + } + + @Override + public int Rf_anyDuplicated(Object x, int fromLast) { + RAbstractVector vec = (RAbstractVector) x; + if (vec.getLength() == 0) { + return 0; + } else { + return DuplicationHelper.analyze(vec, null, true, fromLast != 0).getIndex(); + } + } + + @Override + public Object PRINTNAME(Object x) { + guaranteeInstanceOf(x, RSymbol.class); + return CharSXPWrapper.create(((RSymbol) x).getName()); + } + + @Override + public Object TAG(Object e) { + if (e instanceof RPairList) { + return ((RPairList) e).getTag(); + } else { + guaranteeInstanceOf(e, RExternalPtr.class); + // at the moment, this can only be used to null out the pointer + return ((RExternalPtr) e).getTag(); + } + } + + @Override + public Object CAR(Object e) { + return FFIUpCallRootNode.getCallTarget(RFFIUpCallMethod.CAR).call(e); + } + + @Override + public Object CDR(Object e) { + return FFIUpCallRootNode.getCallTarget(RFFIUpCallMethod.CDR).call(e); + } + + @Override + public Object CADR(Object e) { + return FFIUpCallRootNode.getCallTarget(RFFIUpCallMethod.CADR).call(e); + } + + @Override + public Object CADDR(Object e) { + return FFIUpCallRootNode.getCallTarget(RFFIUpCallMethod.CADDR).call(e); + } + + @Override + public Object CDDR(Object e) { + return FFIUpCallRootNode.getCallTarget(RFFIUpCallMethod.CDDR).call(e); + } + + @Override + public Object SET_TAG(Object x, Object y) { + if (x instanceof RPairList) { + ((RPairList) x).setTag(y); + } else { + guaranteeInstanceOf(x, RExternalPtr.class); + // at the moment, this can only be used to null out the pointer + ((RExternalPtr) x).setTag(y); + } + return y; + } + + @Override + public Object SETCAR(Object x, Object y) { + guaranteeInstanceOf(x, RPairList.class); + ((RPairList) x).setCar(y); + return y; + } + + @Override + public Object SETCDR(Object x, Object y) { + guaranteeInstanceOf(x, RPairList.class); + ((RPairList) x).setCdr(y); + return y; + } + + @Override + public Object SETCADR(Object x, Object y) { + SETCAR(CDR(x), y); + return y; + } + + @Override + public Object SYMVALUE(Object x) { + if (!(x instanceof RSymbol)) { + throw RInternalError.shouldNotReachHere(); + } + Object res = REnvironment.baseEnv().get(((RSymbol) x).getName()); + if (res == null) { + return RUnboundValue.instance; + } else { + return res; + } + } + + @Override + public void SET_SYMVALUE(Object x, Object v) { + if (!(x instanceof RSymbol)) { + throw RInternalError.shouldNotReachHere(); + } + REnvironment.baseEnv().safePut(((RSymbol) x).getName(), v); + } + + @Override + public int R_BindingIsLocked(Object sym, Object env) { + guaranteeInstanceOf(sym, RSymbol.class); + guaranteeInstanceOf(env, REnvironment.class); + return ((REnvironment) env).bindingIsLocked(((RSymbol) sym).getName()) ? 1 : 0; + } + + @Override + public Object R_FindNamespace(Object name) { + Object result = RContext.getInstance().stateREnvironment.getNamespaceRegistry().get(RRuntime.asString(name)); + return result; + } + + @Override + public Object Rf_eval(Object expr, Object env) { + guarantee(env instanceof REnvironment); + Object result; + if (expr instanceof RPromise) { + result = RContext.getRRuntimeASTAccess().forcePromise(null, expr); + } else if (expr instanceof RExpression) { + result = RContext.getEngine().eval((RExpression) expr, (REnvironment) env, RCaller.topLevel); + } else if (expr instanceof RLanguage) { + result = RContext.getEngine().eval((RLanguage) expr, (REnvironment) env, RCaller.topLevel); + } else if (expr instanceof RPairList) { + RPairList l = (RPairList) expr; + RFunction f = (RFunction) l.car(); + Object args = l.cdr(); + if (args == RNull.instance) { + result = RContext.getEngine().evalFunction(f, env == REnvironment.globalEnv() ? null : ((REnvironment) env).getFrame(), RCaller.topLevel, null, new Object[0]); + } else { + RList argsList = ((RPairList) args).toRList(); + result = RContext.getEngine().evalFunction(f, env == REnvironment.globalEnv() ? null : ((REnvironment) env).getFrame(), RCaller.topLevel, argsList.getNames(), + argsList.getDataNonShared()); + } + } else { + // just return value + result = expr; + } + return result; + } + + @Override + public Object Rf_findfun(Object symbolObj, Object envObj) { + guarantee(envObj instanceof REnvironment); + REnvironment env = (REnvironment) envObj; + guarantee(symbolObj instanceof RSymbol); + RSymbol symbol = (RSymbol) symbolObj; + // Works but not remotely efficient + Source source = RSource.fromTextInternal("get(\"" + symbol.getName() + "\", mode=\"function\")", RSource.Internal.RF_FINDFUN); + try { + Object result = RContext.getEngine().parseAndEval(source, env.getFrame(), false); + return result; + } catch (ParseException ex) { + throw RInternalError.shouldNotReachHere(ex); + } + } + + @Override + public Object Rf_GetOption1(Object tag) { + guarantee(tag instanceof RSymbol); + Object result = RContext.getInstance().stateROptions.getValue(((RSymbol) tag).getName()); + return result; + } + + @Override + public void Rf_gsetVar(Object symbol, Object value, Object rho) { + guarantee(symbol instanceof RSymbol); + REnvironment baseEnv = RContext.getInstance().stateREnvironment.getBaseEnv(); + guarantee(rho == baseEnv); + try { + baseEnv.put(((RSymbol) symbol).getName(), value); + } catch (PutException e) { + e.printStackTrace(); + } + } + + @Override + public void DUPLICATE_ATTRIB(Object to, Object from) { + if (from instanceof RAttributable) { + guaranteeInstanceOf(to, RAttributable.class); + DynamicObject attributes = ((RAttributable) from).getAttributes(); + ((RAttributable) to).initAttributes(attributes == null ? null : RAttributesLayout.copy(attributes)); + } + // TODO: copy OBJECT? and S4 attributes + } + + @Override + public int R_computeIdentical(Object x, Object y, int flags) { + RFunction indenticalBuiltin = RContext.lookupBuiltin("identical"); + Object res = RContext.getEngine().evalFunction(indenticalBuiltin, null, null, null, x, y, RRuntime.asLogical((!((flags & 1) == 0))), + RRuntime.asLogical((!((flags & 2) == 0))), RRuntime.asLogical((!((flags & 4) == 0))), RRuntime.asLogical((!((flags & 8) == 0))), RRuntime.asLogical((!((flags & 16) == 0)))); + return (int) res; + } + + @Override + public void Rf_copyListMatrix(Object s, Object t, int byrow) { + throw unimplemented(); + } + + @Override + public void Rf_copyMatrix(Object s, Object t, int byrow) { + throw unimplemented(); + } + + @Override + public Object R_tryEval(Object expr, Object env, boolean silent) { + Object handlerStack = RErrorHandling.getHandlerStack(); + Object restartStack = RErrorHandling.getRestartStack(); + try { + // TODO handle silent + RErrorHandling.resetStacks(); + Object result = Rf_eval(expr, env); + return result; + } catch (Throwable t) { + return null; + } finally { + RErrorHandling.restoreStacks(handlerStack, restartStack); + } + } + + /** + * Helper function for {@code R_TopLevelExec} which is similar to {@code R_TryEval} except that + * a C function is invoked (in the native layer) instead of an R expression. assert: this is + * ONLY called from R_TopLevelExec prior to calling C function. + */ + @Override + public Object R_ToplevelExec() { + return RErrorHandling.resetAndGetHandlerStacks(); + } + + @Override + public int RDEBUG(Object x) { + REnvironment env = guaranteeInstanceOf(x, REnvironment.class); + if (env instanceof REnvironment.Function) { + REnvironment.Function funcEnv = (REnvironment.Function) env; + RFunction func = RArguments.getFunction(funcEnv.getFrame()); + return RContext.getRRuntimeASTAccess().isDebugged(func) ? 1 : 0; + } else { + return 0; + } + } + + @Override + public void SET_RDEBUG(Object x, int v) { + REnvironment env = guaranteeInstanceOf(x, REnvironment.class); + if (env instanceof REnvironment.Function) { + REnvironment.Function funcEnv = (REnvironment.Function) env; + RFunction func = RArguments.getFunction(funcEnv.getFrame()); + if (v == 1) { + RContext.getRRuntimeASTAccess().enableDebug(func, false); + } else { + RContext.getRRuntimeASTAccess().disableDebug(func); + } + } + } + + @Override + public int RSTEP(Object x) { + @SuppressWarnings("unused") + REnvironment env = guaranteeInstanceOf(x, REnvironment.class); + throw RInternalError.unimplemented("RSTEP"); + } + + @Override + public void SET_RSTEP(Object x, int v) { + @SuppressWarnings("unused") + REnvironment env = guaranteeInstanceOf(x, REnvironment.class); + throw RInternalError.unimplemented("SET_RSTEP"); + } + + @Override + public Object ENCLOS(Object x) { + REnvironment env = guaranteeInstanceOf(x, REnvironment.class); + Object result = env.getParent(); + if (result == null) { + result = RNull.instance; + } + return result; + } + + @Override + public Object PRVALUE(Object x) { + RPromise p = guaranteeInstanceOf(x, RPromise.class); + return p.isEvaluated() ? p.getValue() : RUnboundValue.instance; + } + + @Override + public Object R_ParseVector(Object text, int n, Object srcFile) { + // TODO general case + assert n == 1; + assert srcFile == RNull.instance; + String textString = RRuntime.asString(text); + assert textString != null; + + try { + Source source = RSource.fromTextInternal(textString, RSource.Internal.R_PARSEVECTOR); + RExpression exprs = RContext.getEngine().parse(source); + return new ParseResult(ParseStatus.PARSE_OK.ordinal(), exprs); + } catch (ParseException ex) { + // TODO incomplete + return new ParseResult(ParseStatus.PARSE_ERROR.ordinal(), RNull.instance); + } + } + + @Override + public Object R_lsInternal3(Object envArg, int allArg, int sortedArg) { + boolean sorted = sortedArg != 0; + boolean all = allArg != 0; + REnvironment env = guaranteeInstanceOf(envArg, REnvironment.class); + return env.ls(all, null, sorted); + } + + @Override + public String R_HomeDir() { + return REnvVars.rHome(); + } + + @Override + public void R_CleanUp(int sa, int status, int runlast) { + RCleanUp.stdCleanUp(SA_TYPE.values()[sa], status, runlast != 0); + } + + @Override + public Object R_GlobalContext() { + Utils.warn("Potential memory leak (global context object)"); + Frame frame = Utils.getActualCurrentFrame(); + if (frame == null) { + return RCaller.topLevel; + } + if (RContext.getInstance().stateInstrumentation.getBrowserState().inBrowser()) { + return RContext.getInstance().stateInstrumentation.getBrowserState().getInBrowserCaller(); + } + RCaller rCaller = RArguments.getCall(frame); + return rCaller == null ? RCaller.topLevel : rCaller; + } + + @Override + public Object R_GlobalEnv() { + return RContext.getInstance().stateREnvironment.getGlobalEnv(); + } + + @Override + public Object R_BaseEnv() { + return RContext.getInstance().stateREnvironment.getBaseEnv(); + } + + @Override + public Object R_BaseNamespace() { + return RContext.getInstance().stateREnvironment.getBaseNamespace(); + } + + @Override + public Object R_NamespaceRegistry() { + return RContext.getInstance().stateREnvironment.getNamespaceRegistry(); + } + + @Override + public int R_Interactive() { + return RContext.getInstance().isInteractive() ? 1 : 0; + } + + @Override + public int IS_S4_OBJECT(Object x) { + return x instanceof RS4Object ? 1 : 0; + } + + @Override + public void Rprintf(Object message) { + RContext.getInstance().getConsoleHandler().print((String) message); + } + + @Override + public void GetRNGstate() { + RRNG.getRNGState(); + } + + @Override + public void PutRNGstate() { + RRNG.putRNGState(); + } + + @Override + public double unif_rand() { + return RRNG.unifRand(); + } + + // Checkstyle: stop method name check + + @Override + public Object R_getGlobalFunctionContext() { + Utils.warn("Potential memory leak (global function context object)"); + Frame frame = Utils.getActualCurrentFrame(); + if (frame == null) { + return RNull.instance; + } + RCaller currentCaller = RArguments.getCall(frame); + while (currentCaller != null) { + if (!currentCaller.isPromise() && currentCaller.isValidCaller() && currentCaller != RContext.getInstance().stateInstrumentation.getBrowserState().getInBrowserCaller()) { + break; + } + currentCaller = currentCaller.getParent(); + } + return currentCaller == null || currentCaller == RCaller.topLevel ? RNull.instance : currentCaller; + } + + @Override + public Object R_getParentFunctionContext(Object c) { + Utils.warn("Potential memory leak (parent function context object)"); + RCaller currentCaller = guaranteeInstanceOf(c, RCaller.class); + while (true) { + currentCaller = currentCaller.getParent(); + if (currentCaller == null || + (!currentCaller.isPromise() && currentCaller.isValidCaller() && currentCaller != RContext.getInstance().stateInstrumentation.getBrowserState().getInBrowserCaller())) { + break; + } + } + return currentCaller == null || currentCaller == RCaller.topLevel ? RNull.instance : currentCaller; + } + + @Override + public Object R_getContextEnv(Object c) { + RCaller rCaller = guaranteeInstanceOf(c, RCaller.class); + if (rCaller == RCaller.topLevel) { + return RContext.getInstance().stateREnvironment.getGlobalEnv(); + } + Frame frame = Utils.getActualCurrentFrame(); + if (RArguments.getCall(frame) == rCaller) { + return REnvironment.frameToEnvironment(frame.materialize()); + } else { + Object result = Utils.iterateRFrames(FrameAccess.READ_ONLY, new Function<Frame, Object>() { + + @Override + public Object apply(Frame f) { + RCaller currentCaller = RArguments.getCall(f); + if (currentCaller == rCaller) { + return REnvironment.frameToEnvironment(f.materialize()); + } else { + return null; + } + } + }); + return result; + } + } + + @Override + public Object R_getContextFun(Object c) { + RCaller rCaller = guaranteeInstanceOf(c, RCaller.class); + if (rCaller == RCaller.topLevel) { + return RNull.instance; + } + Frame frame = Utils.getActualCurrentFrame(); + if (RArguments.getCall(frame) == rCaller) { + return RArguments.getFunction(frame); + } else { + Object result = Utils.iterateRFrames(FrameAccess.READ_ONLY, new Function<Frame, Object>() { + + @Override + public Object apply(Frame f) { + RCaller currentCaller = RArguments.getCall(f); + if (currentCaller == rCaller) { + return RArguments.getFunction(f); + } else { + return null; + } + } + }); + return result; + } + } + + @Override + public Object R_getContextCall(Object c) { + RCaller rCaller = guaranteeInstanceOf(c, RCaller.class); + if (rCaller == RCaller.topLevel) { + return RNull.instance; + } + return RContext.getRRuntimeASTAccess().getSyntaxCaller(rCaller); + } + + @Override + public Object R_getContextSrcRef(Object c) { + Object o = R_getContextFun(c); + if (!(o instanceof RFunction)) { + return RNull.instance; + } else { + RFunction f = (RFunction) o; + SourceSection ss = f.getRootNode().getSourceSection(); + String path = RSource.getPath(ss.getSource()); + // TODO: is it OK to pass "" if path is null? + return RSrcref.createLloc(ss, path == null ? "" : path); + } + } + + @Override + public int R_insideBrowser() { + return RContext.getInstance().stateInstrumentation.getBrowserState().inBrowser() ? 1 : 0; + } + + @Override + public int R_isGlobal(Object c) { + RCaller rCaller = guaranteeInstanceOf(c, RCaller.class); + + return rCaller == RCaller.topLevel ? 1 : 0; + } + + @Override + public int R_isEqual(Object x, Object y) { + return x == y ? 1 : 0; + } + + @Override + @TruffleBoundary + public Object Rf_classgets(Object x, Object y) { + RAbstractVector vector = guaranteeInstanceOf(x, RAbstractVector.class); + vector.setClassAttr(guaranteeInstanceOf(y, RStringVector.class)); + return RNull.instance; + } + + @Override + public RExternalPtr R_MakeExternalPtr(long addr, Object tag, Object prot) { + return RDataFactory.createExternalPtr(new SymbolHandle(addr), tag, prot); + } + + @Override + public long R_ExternalPtrAddr(Object x) { + RExternalPtr p = guaranteeInstanceOf(x, RExternalPtr.class); + return p.getAddr().asAddress(); + } + + @Override + public Object R_ExternalPtrTag(Object x) { + RExternalPtr p = guaranteeInstanceOf(x, RExternalPtr.class); + return p.getTag(); + } + + @Override + public Object R_ExternalPtrProt(Object x) { + RExternalPtr p = guaranteeInstanceOf(x, RExternalPtr.class); + return p.getProt(); + } + + @Override + public void R_SetExternalPtrAddr(Object x, long addr) { + RExternalPtr p = guaranteeInstanceOf(x, RExternalPtr.class); + p.setAddr(new SymbolHandle(addr)); + } + + @Override + public void R_SetExternalPtrTag(Object x, Object tag) { + RExternalPtr p = guaranteeInstanceOf(x, RExternalPtr.class); + p.setTag(tag); + } + + @Override + public void R_SetExternalPtrProt(Object x, Object prot) { + RExternalPtr p = guaranteeInstanceOf(x, RExternalPtr.class); + p.setProt(prot); + } + + @Override + public REnvironment R_NewHashedEnv(REnvironment parent, int initialSize) { + REnvironment env = RDataFactory.createNewEnv(REnvironment.UNNAMED, true, initialSize); + RArguments.initializeEnclosingFrame(env.getFrame(), parent.getFrame()); + return env; + } + +} diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/RFFIUpCallMethod.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/RFFIUpCallMethod.java new file mode 100644 index 0000000000000000000000000000000000000000..fc354a931de72d93a2b997e4c3d9bf0011a529b5 --- /dev/null +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/RFFIUpCallMethod.java @@ -0,0 +1,159 @@ +/* + * 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 com.oracle.truffle.r.runtime.ffi.UpCallsRFFI; + +/** + * Generated from {@link UpCallsRFFI}. Any native code that is dependent on the ordinal value of + * these enums must be kept in sync. The {@link #main} method will generate the appropriate C + * #define statements. + */ +public enum RFFIUpCallMethod { + CADDR("(object) : object"), + CADR("(object) : object"), + CAR("(object) : object"), + CDDR("(object) : object"), + CDR("(object) : object"), + DUPLICATE_ATTRIB("(object, object) : void"), + ENCLOS("(object) : object"), + GetRNGstate("() : void"), + INTEGER("(object) : object"), + IS_S4_OBJECT("(object) : sint32"), + LENGTH("(object) : sint32"), + LOGICAL("(object) : object"), + NAMED("(object) : sint32"), + OBJECT("(object) : sint32"), + PRINTNAME("(object) : object"), + PRVALUE("(object) : object"), + PutRNGstate("() : void"), + RAW("(object) : object"), + RDEBUG("(object) : sint32"), + REAL("(object) : object"), + RSTEP("(object) : sint32"), + R_BaseEnv("() : object"), + R_BaseNamespace("() : object"), + R_BindingIsLocked("(object, object) : sint32"), + R_CleanUp("(sint32, sint32, sint32) : void"), + R_ExternalPtrAddr("(object) : object"), + R_ExternalPtrProt("(object) : object"), + R_ExternalPtrTag("(object) : object"), + R_FindNamespace("(object) : object"), + R_GlobalContext("() : object"), + R_GlobalEnv("() : object"), + R_HomeDir("() : object"), + R_Interactive("() : sint32"), + R_MakeExternalPtr("(object, object, object) : object"), + R_NamespaceRegistry("() : object"), + R_NewHashedEnv("(object, sint32) : object"), + R_ParseVector("(object, sint32, object) : object"), + R_SetExternalPtrAddr("(object, object) : void"), + R_SetExternalPtrProt("(object, object) : void"), + R_SetExternalPtrTag("(object, object) : void"), + R_ToplevelExec("() : object"), + R_computeIdentical("(object, object, sint32) : sint32"), + R_do_MAKE_CLASS("(pointer) : object"), + R_getContextCall("(object) : object"), + R_getContextEnv("(object) : object"), + R_getContextFun("(object) : object"), + R_getContextSrcRef("(object) : object"), + R_getGlobalFunctionContext("() : object"), + R_getParentFunctionContext("(object) : object"), + R_insideBrowser("() : sint32"), + R_isEqual("(object, object) : sint32"), + R_isGlobal("(object) : sint32"), + R_lsInternal3("(object, sint32, sint32) : object"), + R_tryEval("(object, object, object) : object"), + Rf_GetOption1("(object) : object"), + Rf_PairToVectorList("(object) : object"), + Rf_ScalarDouble("(double) : object"), + Rf_ScalarInteger("(sint32) : object"), + Rf_ScalarLogical("(sint32) : object"), + Rf_ScalarString("(object) : object"), + Rf_allocateArray("(sint32, object) : object"), + Rf_allocateMatrix("(sint32, sint32, sint32) : object"), + Rf_allocateVector("(sint32, sint32) : object"), + Rf_anyDuplicated("(object, sint32) : sint32"), + Rf_asChar("(object) : object"), + Rf_asInteger("(object) : sint32"), + Rf_asLogical("(object) : sint32"), + Rf_asReal("(object) : double"), + Rf_classgets("(object, object) : object"), + Rf_cons("(object, object) : object"), + Rf_copyListMatrix("(object, object, sint32) : void"), + Rf_copyMatrix("(object, object, sint32) : void"), + Rf_defineVar("(object, object, object) : void"), + Rf_duplicate("(object, sint32) : object"), + Rf_error("(pointer) : void"), + Rf_eval("(object, object) : object"), + Rf_findVar("(object, object) : object"), + Rf_findVarInFrame("(object, object) : object"), + Rf_findVarInFrame3("(object, object, sint32) : object"), + Rf_findfun("(object, object) : object"), + Rf_getAttrib("(object, object) : object"), + Rf_gsetVar("(object, object, object) : void"), + Rf_inherits("(pointer, object) : sint32"), + Rf_install("(pointer) : object"), + Rf_isNull("(object) : sint32"), + Rf_isString("(object) : sint32"), + Rf_lengthgets("(object, sint32) : object"), + Rf_mkCharLenCE("(pointer, sint32, sint32) : object"), + Rf_ncols("(object) : sint32"), + Rf_nrows("(object) : sint32"), + Rf_setAttrib("(object, object, object) : void"), + Rf_warning("(pointer) : void"), + Rf_warningcall("(object, pointer) : void"), + Rprintf("(pointer) : void"), + SETCADR("(object, object) : object"), + SETCAR("(object, object) : object"), + SETCDR("(object, object) : object"), + SET_RDEBUG("(object, sint32) : void"), + SET_RSTEP("(object, sint32) : void"), + SET_STRING_ELT("(object, sint32, object) : void"), + SET_SYMVALUE("(object, object) : void"), + SET_TAG("(object, object) : object"), + SET_TYPEOF_FASTR("(object, sint32) : object"), + SET_VECTOR_ELT("(object, sint32, object) : void"), + STRING_ELT("(object, sint32) : object"), + SYMVALUE("(object) : object"), + TAG("(object) : object"), + TYPEOF("(object) : sint32"), + VECTOR_ELT("(object, sint32) : object"), + unif_rand("() : double"); + + /** + * The signature used for the upcall in Truffle NFI. + */ + public final String nfiSignature; + + RFFIUpCallMethod(String signature) { + this.nfiSignature = signature; + } + + public static void main(String[] args) { + for (RFFIUpCallMethod f : RFFIUpCallMethod.values()) { + System.out.printf("#define %s_x %d\n", f.name(), f.ordinal()); + } + } + +} diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/TraceUpCallsAdapter.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/TraceUpCallsAdapter.java deleted file mode 100644 index 2ba610c7b3796937d4ad400887ef22547e7d5bb8..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/TraceUpCallsAdapter.java +++ /dev/null @@ -1,892 +0,0 @@ -/* - * 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 - * 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.r.runtime.data.RDoubleVector; -import com.oracle.truffle.r.runtime.data.RExternalPtr; -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.UpCallsRFFI; - -public class TraceUpCallsAdapter implements UpCallsRFFI { - @Override - public RIntVector Rf_ScalarInteger(int value) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("Rf_ScalarInteger", value); - } - return null; - } - - @Override - public RLogicalVector Rf_ScalarLogical(int value) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("Rf_ScalarLogical", value); - } - return null; - } - - @Override - public RDoubleVector Rf_ScalarDouble(double value) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("Rf_ScalarDouble", value); - } - return null; - } - - @Override - public RStringVector Rf_ScalarString(Object value) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("Rf_ScalarString", value); - } - return null; - } - - @Override - public int Rf_asInteger(Object x) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("Rf_asInteger", x); - } - return 0; - } - - @Override - public double Rf_asReal(Object x) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("Rf_asReal", x); - } - return 0; - } - - @Override - public int Rf_asLogical(Object x) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("Rf_asLogical", x); - } - return 0; - } - - @Override - public Object Rf_asChar(Object x) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("Rf_asChar", x); - } - return null; - } - - @Override - public Object Rf_mkCharLenCE(byte[] bytes, int encoding) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("Rf_mkCharLenCE", bytes); - } - return null; - } - - @Override - public Object Rf_cons(Object car, Object cdr) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("Rf_cons", car, cdr); - } - return null; - } - - @Override - public void Rf_defineVar(Object symbolArg, Object value, Object envArg) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("Rf_defineVar", symbolArg, value, envArg); - } - } - - @Override - public Object R_do_MAKE_CLASS(String clazz) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("R_do_MAKE_CLASS", clazz); - } - return null; - } - - @Override - public Object Rf_findVar(Object symbolArg, Object envArg) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("Rf_findVar", symbolArg, envArg); - } - return null; - } - - @Override - public Object Rf_findVarInFrame(Object envArg, Object symbolArg) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("Rf_findVarInFrame", envArg, symbolArg); - } - return null; - } - - @Override - public Object Rf_findVarInFrame3(Object envArg, Object symbolArg, int doGet) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("Rf_findVarInFrame3", envArg, symbolArg); - } - return null; - } - - @Override - public Object Rf_getAttrib(Object obj, Object name) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("Rf_getAttrib", obj, name); - } - return null; - } - - @Override - public void Rf_setAttrib(Object obj, Object name, Object val) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("Rf_setAttrib", obj, name, val); - } - } - - @Override - public int Rf_inherits(Object x, String clazz) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("Rf_inherits", x, clazz); - } - return 0; - } - - @Override - public Object Rf_install(String name) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("Rf_install", name); - } - return null; - } - - @Override - public Object Rf_lengthgets(Object x, int newSize) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("Rf_lengthgets", x, newSize); - } - return null; - } - - @Override - public int Rf_isString(Object x) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("Rf_isString", x); - } - return 0; - } - - @Override - public int Rf_isNull(Object x) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("Rf_isNull", x); - } - return 0; - } - - @Override - public Object Rf_PairToVectorList(Object x) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("Rf_PairToVectorList", x); - } - return null; - } - - @Override - public void Rf_error(String msg) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("Rf_error", msg); - } - } - - @Override - public void Rf_warning(String msg) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("Rf_warning", msg); - } - } - - @Override - public void Rf_warningcall(Object call, String msg) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("Rf_warningcall", call, msg); - } - } - - @Override - public Object Rf_allocateVector(int mode, int n) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("Rf_allocateVector", mode, n); - } - return null; - } - - @Override - public Object Rf_allocateArray(int mode, Object dimsObj) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("Rf_allocateArray", mode, dimsObj); - } - return null; - } - - @Override - public Object Rf_allocateMatrix(int mode, int nrow, int ncol) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("Rf_allocateMatrix", mode, ncol, nrow); - } - return null; - } - - @Override - public int Rf_nrows(Object x) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("Rf_nrows", x); - } - return 0; - } - - @Override - public int Rf_ncols(Object x) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("Rf_ncols", x); - } - return 0; - } - - @Override - public int LENGTH(Object x) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("LENGTH", x); - } - return 0; - } - - @Override - public void SET_STRING_ELT(Object x, int i, Object v) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("SET_STRING_ELT", x, i, v); - } - } - - @Override - public void SET_VECTOR_ELT(Object x, int i, Object v) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("SET_VECTOR_ELT", i, v); - } - } - - @Override - public Object RAW(Object x) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("RAW", x); - } - return null; - } - - @Override - public Object LOGICAL(Object x) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("LOGICAL", x); - } - return null; - } - - @Override - public Object INTEGER(Object x) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("INTEGER", x); - } - return null; - } - - @Override - public Object REAL(Object x) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("REAL", x); - } - return null; - } - - @Override - public Object STRING_ELT(Object x, int i) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("STRING_ELT", x, i); - } - return null; - } - - @Override - public Object VECTOR_ELT(Object x, int i) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("VECTOR_ELT", x, i); - } - return null; - } - - @Override - public int NAMED(Object x) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("NAMED", x); - } - return 0; - } - - @Override - public Object SET_TYPEOF_FASTR(Object x, int v) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("SET_TYPEOF_FASTR", x, v); - } - return null; - } - - @Override - public int TYPEOF(Object x) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("TYPEOF", x); - } - return 0; - } - - @Override - public int OBJECT(Object x) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("OBJECT", x); - } - return 0; - } - - @Override - public Object Rf_duplicate(Object x, int deep) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("Rf_duplicate", x, deep); - } - return null; - } - - @Override - public int Rf_anyDuplicated(Object x, int fromLast) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("Rf_anyDuplicated", x, fromLast); - } - return 0; - } - - @Override - public Object PRINTNAME(Object x) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("PRINTNAME", x); - } - return null; - } - - @Override - public Object TAG(Object e) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("TAG", e); - } - return null; - } - - @Override - public Object CAR(Object e) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("CAR", e); - } - return null; - } - - @Override - public Object CDR(Object e) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("CDR", e); - } - return null; - } - - @Override - public Object CADR(Object e) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("CADR", e); - } - return null; - } - - @Override - public Object CADDR(Object e) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("CADDR", e); - } - return null; - } - - @Override - public Object CDDR(Object e) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("CDDR", e); - } - return null; - } - - @Override - public Object SET_TAG(Object x, Object y) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("SET_TAG", x, y); - } - return null; - } - - @Override - public Object SETCAR(Object x, Object y) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("SETCAR", x, y); - } - return null; - } - - @Override - public Object SETCDR(Object x, Object y) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("SETCDR", x, y); - } - return null; - } - - @Override - public Object SETCADR(Object x, Object y) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("SETCADR", x); - } - return null; - } - - @Override - public Object SYMVALUE(Object x) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("SYMVALUE", x); - } - return null; - } - - @Override - public void SET_SYMVALUE(Object x, Object v) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("SET_SYMVALUE", x, v); - } - } - - @Override - public int R_BindingIsLocked(Object sym, Object env) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("R_BindingIsLocked", sym, env); - } - return 0; - } - - @Override - public Object R_FindNamespace(Object name) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("R_FindNamespace", name); - } - return null; - } - - @Override - public Object Rf_eval(Object expr, Object env) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("Rf_eval", expr, env); - } - return null; - } - - @Override - public Object Rf_findfun(Object symbolObj, Object envObj) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("Rf_findfun", symbolObj, envObj); - } - return null; - } - - @Override - public Object Rf_GetOption1(Object tag) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("Rf_GetOption1", tag); - } - return null; - } - - @Override - public void Rf_gsetVar(Object symbol, Object value, Object rho) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("Rf_gsetVar", symbol, value, rho); - } - } - - @Override - public void DUPLICATE_ATTRIB(Object to, Object from) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("DUPLICATE_ATTRIB", to, from); - } - } - - @Override - public int R_computeIdentical(Object x, Object y, int flags) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("R_computeIdentical", x, y, flags); - } - return 0; - } - - @Override - public void Rf_copyListMatrix(Object s, Object t, int byrow) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("Rf_copyListMatrix", t, byrow); - } - } - - @Override - public void Rf_copyMatrix(Object s, Object t, int byrow) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("Rf_copyMatrix", t, byrow); - } - } - - @Override - public Object R_tryEval(Object expr, Object env, boolean silent) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("R_tryEval", expr, env, silent); - } - return null; - } - - @Override - public Object R_ToplevelExec() { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("R_TopLevelExec"); - } - return null; - } - - @Override - public int RDEBUG(Object x) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("RDEBUG", x); - } - return 0; - } - - @Override - public void SET_RDEBUG(Object x, int v) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("SET_RDEBUG", x, v); - } - } - - @Override - public int RSTEP(Object x) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("RSTEP", x); - } - return 0; - } - - @Override - public void SET_RSTEP(Object x, int v) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("SET_RSTEP", x, v); - } - } - - @Override - public Object ENCLOS(Object x) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("ENCLOS", x); - } - return null; - } - - @Override - public Object PRVALUE(Object x) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("PRVALUE", x); - } - return null; - } - - @Override - public Object R_ParseVector(Object text, int n, Object srcFile) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("R_ParseVector", text, n, srcFile); - } - return null; - } - - @Override - public Object R_lsInternal3(Object envArg, int allArg, int sortedArg) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("R_lsInternal3", envArg, allArg, sortedArg); - } - return null; - } - - @Override - public String R_HomeDir() { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("R_HomeDir"); - } - return null; - } - - @Override - public void R_CleanUp(int sa, int status, int runlast) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("R_Cleanup", sa, status, runlast); - } - } - - @Override - public Object R_GlobalContext() { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("R_GlobalContext"); - } - return null; - } - - @Override - public Object R_GlobalEnv() { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("R_GlobalEnv"); - } - return null; - } - - @Override - public Object R_BaseEnv() { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("R_BaseEnv"); - } - return null; - } - - @Override - public Object R_BaseNamespace() { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("R_BaseNamespace"); - } - return null; - } - - @Override - public Object R_NamespaceRegistry() { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("R_NamespaceRegistry"); - } - return null; - } - - @Override - public int R_Interactive() { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("isInteractive"); - } - return 0; - } - - @Override - public int IS_S4_OBJECT(Object x) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("isS4Object"); - } - return 0; - } - - @Override - public void Rprintf(String message) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("Rprintf", message); - } - } - - @Override - public void GetRNGstate() { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("GetRNGstate"); - } - } - - @Override - public void PutRNGstate() { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("PutRNGstate"); - } - } - - @Override - public double unif_rand() { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("unif_rand"); - } - return 0; - } - - @Override - public Object R_getGlobalFunctionContext() { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("R_getGlobalFunctionContext"); - } - return null; - } - - @Override - public Object R_getParentFunctionContext(Object c) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("R_getParentFunctionContext"); - } - return null; - } - - @Override - public Object R_getContextEnv(Object c) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("R_getContextEnv", c); - } - return null; - } - - @Override - public Object R_getContextFun(Object c) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("R_getContextFun", c); - } - return null; - } - - @Override - public Object R_getContextCall(Object c) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("R_getContextCall", c); - } - return null; - } - - @Override - public Object R_getContextSrcRef(Object c) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("R_getContextSrcRef", c); - } - return null; - } - - @Override - public int R_insideBrowser() { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("R_insideBrowser"); - } - return 0; - } - - @Override - public int R_isGlobal(Object c) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("R_isGlobal", c); - } - return 0; - } - - @Override - public int R_isEqual(Object x, Object y) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("isEqual", x, y); - } - return 0; - } - - @Override - public Object Rf_classgets(Object x, Object y) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("Rf_classgets", x, y); - } - return null; - } - - @Override - public RExternalPtr R_MakeExternalPtr(long addr, Object tag, Object prot) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("R_MakeExternalPtr", addr, tag, prot); - } - return null; - } - - @Override - public long R_ExternalPtrAddr(Object x) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("R_ExternalPtrAddr", x); - } - return 0; - } - - @Override - public Object R_ExternalPtrTag(Object x) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("R_ExternalPtrTag", x); - } - return null; - } - - @Override - public Object R_ExternalPtrProt(Object x) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("R_ExternalPtrProt", x); - } - return null; - } - - @Override - public void R_SetExternalPtrAddr(Object x, long addr) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("R_SetExternalPtrAddr", x); - } - } - - @Override - public void R_SetExternalPtrTag(Object x, Object tag) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("R_SetExternalPtrTag", x); - } - } - - @Override - public void R_SetExternalPtrProt(Object x, Object prot) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("R_ExternalPtrProt", x); - } - } - - @Override - public REnvironment R_NewHashedEnv(REnvironment parent, String name, boolean hashed, int initialSize) { - if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("R_NewHashedEnv", parent, name, hashed, initialSize); - } - return null; - } -} 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 deleted file mode 100644 index 21915f44541558cce6c82ac03908fa67c8d8d500..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/UpCallsIndex.java +++ /dev/null @@ -1,165 +0,0 @@ -/* - * 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 R_Interactive = 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.nodes/src/com/oracle/truffle/r/nodes/ffi/UpCallsRFFIImpl.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/UpCallsRFFIImpl.java index 7668581c10e53c63d3fdc890d3d9d907e2a2752a..59a0dbc1390adbfc6f9c1ebe90fffe5874ce4235 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/UpCallsRFFIImpl.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/UpCallsRFFIImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2017, 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,1480 +22,928 @@ */ 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; - -import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.api.frame.Frame; -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; -import com.oracle.truffle.r.runtime.REnvVars; -import com.oracle.truffle.r.runtime.RError; +import static com.oracle.truffle.r.nodes.ffi.RFFIUtils.guaranteeInstanceOf; + import com.oracle.truffle.r.runtime.RErrorHandling; -import com.oracle.truffle.r.runtime.RInternalError; -import com.oracle.truffle.r.runtime.RRuntime; -import com.oracle.truffle.r.runtime.RSource; -import com.oracle.truffle.r.runtime.RSrcref; -import com.oracle.truffle.r.runtime.RStartParams.SA_TYPE; -import com.oracle.truffle.r.runtime.RType; -import com.oracle.truffle.r.runtime.Utils; -import com.oracle.truffle.r.runtime.context.Engine.ParseException; -import com.oracle.truffle.r.runtime.context.RContext; -import com.oracle.truffle.r.runtime.data.RAttributable; -import com.oracle.truffle.r.runtime.data.RAttributesLayout; -import com.oracle.truffle.r.runtime.data.RComplex; -import com.oracle.truffle.r.runtime.data.RComplexVector; -import com.oracle.truffle.r.runtime.data.RDataFactory; -import com.oracle.truffle.r.runtime.data.RDoubleSequence; import com.oracle.truffle.r.runtime.data.RDoubleVector; -import com.oracle.truffle.r.runtime.data.RExpression; import com.oracle.truffle.r.runtime.data.RExternalPtr; -import com.oracle.truffle.r.runtime.data.RFunction; -import com.oracle.truffle.r.runtime.data.RIntSequence; import com.oracle.truffle.r.runtime.data.RIntVector; -import com.oracle.truffle.r.runtime.data.RLanguage; -import com.oracle.truffle.r.runtime.data.RList; import com.oracle.truffle.r.runtime.data.RLogicalVector; -import com.oracle.truffle.r.runtime.data.RNull; -import com.oracle.truffle.r.runtime.data.RPairList; -import com.oracle.truffle.r.runtime.data.RPromise; -import com.oracle.truffle.r.runtime.data.RRaw; -import com.oracle.truffle.r.runtime.data.RRawVector; -import com.oracle.truffle.r.runtime.data.RS4Object; -import com.oracle.truffle.r.runtime.data.RSequence; -import com.oracle.truffle.r.runtime.data.RShareable; 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.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.gnur.SEXPTYPE; -import com.oracle.truffle.r.runtime.nodes.DuplicationHelper; -import com.oracle.truffle.r.runtime.nodes.RNode; -import com.oracle.truffle.r.runtime.rng.RRNG; - -/** - * This class provides a simple Java-based implementation of {@link UpCallsRFFI}, using no Truffle - * mechanisms. - * - * TODO Many of the implementations here are incomplete and/or duplicate code that exists in the - * Truffle side of the implementation, i.e., {@link RNode} subclasses. A complete refactoring that - * accesses the Truffle implementations (possibly somewhat refactored owing to the fact that the - * Truffle side is driven by the builtins yet these functions don't not always map 1-1 to a builtin) - * 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 UpCallsRFFIImpl implements UpCallsRFFI { - protected TraceUpCallsAdapter tracer; +public final class UpCallsRFFIImpl implements UpCallsRFFI { + // Checkstyle: stop method name check - public UpCallsRFFIImpl() { - if (RFFIUtils.traceEnabled()) { - tracer = new TraceUpCallsAdapter(); - } - UpCallsIndex.register(); - } + private final UpCallsRFFI delegate; + private final boolean tracing; - // Checkstyle: stop method name check + public UpCallsRFFIImpl(UpCallsRFFI delegate) { + this.delegate = delegate; + FFIUpCallRootNode.register(); + tracing = RFFIUtils.traceEnabled(); + } @Override public RIntVector Rf_ScalarInteger(int value) { - if (tracer != null) { - tracer.Rf_ScalarInteger(value); + if (tracing) { + RFFIUtils.traceUpCall("Rf_ScalarInteger", value); } - return RDataFactory.createIntVectorFromScalar(value); + return delegate.Rf_ScalarInteger(value); } @Override public RLogicalVector Rf_ScalarLogical(int value) { - if (tracer != null) { - tracer.Rf_ScalarLogical(value); - } - byte byteValue; - if (value == RRuntime.INT_NA) { - byteValue = RRuntime.LOGICAL_NA; - } else { - byteValue = (byte) (value & 0xFF); + if (tracing) { + RFFIUtils.traceUpCall("Rf_ScalarLogical", value); } - return RDataFactory.createLogicalVectorFromScalar(byteValue); + return delegate.Rf_ScalarLogical(value); } @Override public RDoubleVector Rf_ScalarDouble(double value) { - if (tracer != null) { - tracer.Rf_ScalarDouble(value); + if (tracing) { + RFFIUtils.traceUpCall("Rf_ScalarDouble", value); } - return RDataFactory.createDoubleVectorFromScalar(value); + return delegate.Rf_ScalarDouble(value); } @Override public RStringVector Rf_ScalarString(Object value) { - if (tracer != null) { - tracer.Rf_ScalarString(value); + if (tracing) { + RFFIUtils.traceUpCall("Rf_ScalarString", value); } - CharSXPWrapper chars = guaranteeInstanceOf(value, CharSXPWrapper.class); - return RDataFactory.createStringVectorFromScalar(chars.getContents()); + return delegate.Rf_ScalarString(value); } @Override public int Rf_asInteger(Object x) { - if (tracer != null) { - tracer.Rf_asInteger(x); + if (tracing) { + RFFIUtils.traceUpCall("Rf_asInteger", x); } - return (int) FFIUpCallRootNode.getCallTarget(UpCallsIndex.Rf_asInteger).call(x); + return delegate.Rf_asInteger(x); } @Override public double Rf_asReal(Object x) { - if (tracer != null) { - tracer.Rf_asReal(x); + if (tracing) { + RFFIUtils.traceUpCall("Rf_asReal", x); } - return (double) FFIUpCallRootNode.getCallTarget(UpCallsIndex.Rf_asReal).call(x); + return delegate.Rf_asReal(x); } @Override public int Rf_asLogical(Object x) { - if (tracer != null) { - tracer.Rf_asLogical(x); + if (tracing) { + RFFIUtils.traceUpCall("Rf_asLogical", x); } - return (int) FFIUpCallRootNode.getCallTarget(UpCallsIndex.Rf_asLogical).call(x); + return delegate.Rf_asLogical(x); } @Override public Object Rf_asChar(Object x) { - if (tracer != null) { - tracer.Rf_asChar(x); + if (tracing) { + RFFIUtils.traceUpCall("Rf_asChar", x); } - return FFIUpCallRootNode.getCallTarget(UpCallsIndex.Rf_asChar).call(x); + return delegate.Rf_asChar(x); } @Override - public Object Rf_mkCharLenCE(byte[] bytes, int encoding) { - if (tracer != null) { - tracer.Rf_mkCharLenCE(bytes, encoding); + public Object Rf_mkCharLenCE(Object bytes, int len, int encoding) { + if (tracing) { + RFFIUtils.traceUpCall("Rf_mkCharLenCE", bytes); } - // TODO: handle encoding properly - return CharSXPWrapper.create(new String(bytes, StandardCharsets.UTF_8)); + return delegate.Rf_mkCharLenCE(bytes, len, encoding); } @Override public Object Rf_cons(Object car, Object cdr) { - if (tracer != null) { - tracer.Rf_cons(car, cdr); + if (tracing) { + RFFIUtils.traceUpCall("Rf_cons", car, cdr); } - return RDataFactory.createPairList(car, cdr); + return delegate.Rf_cons(car, cdr); } @Override public void Rf_defineVar(Object symbolArg, Object value, Object envArg) { - if (tracer != null) { - tracer.Rf_defineVar(symbolArg, value, envArg); - } - REnvironment env = (REnvironment) envArg; - RSymbol name = (RSymbol) symbolArg; - try { - env.put(name.getName(), value); - } catch (PutException ex) { - throw RError.error(RError.SHOW_CALLER2, ex); + if (tracing) { + RFFIUtils.traceUpCall("Rf_defineVar", symbolArg, value, envArg); } + delegate.Rf_defineVar(symbolArg, value, envArg); } @Override - public Object R_do_MAKE_CLASS(String clazz) { - if (tracer != null) { - tracer.R_do_MAKE_CLASS(clazz); + public Object R_do_MAKE_CLASS(Object clazz) { + if (tracing) { + RFFIUtils.traceUpCall("R_do_MAKE_CLASS", 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), null, clazz); + return delegate.R_do_MAKE_CLASS(clazz); } @Override public Object Rf_findVar(Object symbolArg, Object envArg) { - if (tracer != null) { - tracer.Rf_findVar(symbolArg, envArg); + if (tracing) { + RFFIUtils.traceUpCall("Rf_findVar", symbolArg, envArg); } - return findVarInFrameHelper(envArg, symbolArg, true); + return delegate.Rf_findVar(symbolArg, envArg); } @Override public Object Rf_findVarInFrame(Object envArg, Object symbolArg) { - if (tracer != null) { - tracer.Rf_findVarInFrame(envArg, symbolArg); + if (tracing) { + RFFIUtils.traceUpCall("Rf_findVarInFrame", envArg, symbolArg); } - return findVarInFrameHelper(envArg, symbolArg, false); + return delegate.Rf_findVarInFrame(envArg, symbolArg); } @Override public Object Rf_findVarInFrame3(Object envArg, Object symbolArg, int doGet) { - if (tracer != null) { - tracer.Rf_findVarInFrame3(envArg, symbolArg, doGet); + if (tracing) { + RFFIUtils.traceUpCall("Rf_findVarInFrame3", envArg, symbolArg); } - // GNU R has code for IS_USER_DATBASE that uses doGet - // This is a lookup in the single environment (envArg) only, i.e. inherits=false - return findVarInFrameHelper(envArg, symbolArg, false); - } - - private static Object findVarInFrameHelper(Object envArg, Object symbolArg, boolean inherits) { - if (envArg == RNull.instance) { - throw RError.error(RError.SHOW_CALLER2, RError.Message.USE_NULL_ENV_DEFUNCT); - } - if (!(envArg instanceof REnvironment)) { - throw RError.error(RError.SHOW_CALLER2, RError.Message.ARG_NOT_AN_ENVIRONMENT, inherits ? "findVar" : "findVarInFrame"); - } - RSymbol name = (RSymbol) symbolArg; - REnvironment env = (REnvironment) envArg; - while (env != REnvironment.emptyEnv()) { - Object value = env.get(name.getName()); - if (value != null) { - return value; - } - if (!inherits) { - // simgle frame lookup - break; - } - env = env.getParent(); - } - return RUnboundValue.instance; + return delegate.Rf_findVarInFrame3(envArg, symbolArg, doGet); } @Override public Object Rf_getAttrib(Object obj, Object name) { - if (tracer != null) { - tracer.Rf_getAttrib(obj, name); + if (tracing) { + RFFIUtils.traceUpCall("Rf_getAttrib", obj, name); } - Object result = RNull.instance; - if (obj instanceof RAttributable) { - RAttributable attrObj = (RAttributable) obj; - DynamicObject attrs = attrObj.getAttributes(); - if (attrs != null) { - String nameAsString = ((RSymbol) name).getName().intern(); - Object attr = attrs.get(nameAsString); - if (attr != null) { - result = attr; - } - } - } - return result; + return delegate.Rf_getAttrib(obj, name); } @Override - @TruffleBoundary public void Rf_setAttrib(Object obj, Object name, Object val) { - if (tracer != null) { - tracer.Rf_setAttrib(obj, name, val); - } - if (obj instanceof RAttributable) { - RAttributable attrObj = (RAttributable) obj; - String nameAsString; - if (name instanceof RSymbol) { - nameAsString = ((RSymbol) name).getName(); - } else { - nameAsString = RRuntime.asString(name); - assert nameAsString != null; - } - nameAsString = nameAsString.intern(); - if (val == RNull.instance) { - removeAttr(attrObj, nameAsString); - } else if ("class" == nameAsString) { - attrObj.initAttributes().define(nameAsString, val); - } else { - attrObj.setAttr(nameAsString, val); - } + if (tracing) { + RFFIUtils.traceUpCall("Rf_setAttrib", obj, name, val); } - } - - @TruffleBoundary - private static void removeAttr(RAttributable a, String name) { - a.removeAttr(name); - } - - public static RStringVector getClassHr(Object v) { - RStringVector result; - if (v instanceof RAttributable) { - result = ((RAttributable) v).getClassHierarchy(); - } else if (v instanceof Byte) { - result = RLogicalVector.implicitClassHeader; - } else if (v instanceof String) { - result = RStringVector.implicitClassHeader; - } else if (v instanceof Integer) { - result = RIntVector.implicitClassHeader; - } else if (v instanceof Double) { - result = RDoubleVector.implicitClassHeader; - } else if (v instanceof RComplex) { - result = RComplexVector.implicitClassHeader; - } else if (v instanceof RRaw) { - result = RRawVector.implicitClassHeader; - } else { - guaranteeInstanceOf(v, RNull.class); - result = RNull.implicitClassHeader; - } - return result; + delegate.Rf_setAttrib(obj, name, val); } @Override - public int Rf_inherits(Object x, String clazz) { - if (tracer != null) { - tracer.Rf_inherits(x, clazz); - } - int result = 0; - RStringVector hierarchy = getClassHr(x); - for (int i = 0; i < hierarchy.getLength(); i++) { - if (hierarchy.getDataAt(i).equals(clazz)) { - result = 1; - } + public int Rf_inherits(Object x, Object clazz) { + if (tracing) { + RFFIUtils.traceUpCall("Rf_inherits", x, clazz); } - return result; + return delegate.Rf_inherits(x, clazz); } @Override - public Object Rf_install(String name) { - if (tracer != null) { - tracer.Rf_install(name); + public Object Rf_install(Object name) { + if (tracing) { + RFFIUtils.traceUpCall("Rf_install", name); } - return RDataFactory.createSymbolInterned(name); + return delegate.Rf_install(name); } @Override public Object Rf_lengthgets(Object x, int newSize) { - if (tracer != null) { - tracer.Rf_lengthgets(x, newSize); + if (tracing) { + RFFIUtils.traceUpCall("Rf_lengthgets", x, newSize); } - RAbstractVector vec = (RAbstractVector) RRuntime.asAbstractVector(x); - return vec.resize(newSize); + return delegate.Rf_lengthgets(x, newSize); } @Override public int Rf_isString(Object x) { - if (tracer != null) { - tracer.Rf_isString(x); + if (tracing) { + RFFIUtils.traceUpCall("Rf_isString", x); } - return RRuntime.checkType(x, RType.Character) ? 1 : 0; + return delegate.Rf_isString(x); } @Override public int Rf_isNull(Object x) { - if (tracer != null) { - tracer.Rf_isNull(x); + if (tracing) { + RFFIUtils.traceUpCall("Rf_isNull", x); } - return x == RNull.instance ? 1 : 0; + return delegate.Rf_isNull(x); } @Override public Object Rf_PairToVectorList(Object x) { - if (tracer != null) { - tracer.Rf_PairToVectorList(x); + if (tracing) { + RFFIUtils.traceUpCall("Rf_PairToVectorList", x); } - if (x == RNull.instance) { - return RDataFactory.createList(); - } - RPairList pl = (RPairList) x; - return pl.toRList(); + return delegate.Rf_PairToVectorList(x); } @Override - public void Rf_error(String msg) { - if (tracer != null) { - tracer.Rf_error(msg); + public void Rf_error(Object msg) { + if (tracing) { + RFFIUtils.traceUpCall("Rf_error", msg); } - throw RError.error(RError.SHOW_CALLER2, RError.Message.GENERIC, msg); + delegate.Rf_error(msg); } @Override - public void Rf_warning(String msg) { - if (tracer != null) { - tracer.Rf_warning(msg); + public void Rf_warning(Object msg) { + if (tracing) { + RFFIUtils.traceUpCall("Rf_warning", msg); } - RError.warning(RError.SHOW_CALLER2, RError.Message.GENERIC, msg); + delegate.Rf_warning(msg); } @Override - public void Rf_warningcall(Object call, String msg) { - if (tracer != null) { - tracer.Rf_warningcall(call, msg); + public void Rf_warningcall(Object call, Object msg) { + if (tracing) { + RFFIUtils.traceUpCall("Rf_warningcall", call, msg); } - RErrorHandling.warningcallRFFI(call, msg); + delegate.Rf_warningcall(call, msg); } @Override public Object Rf_allocateVector(int mode, int n) { - if (tracer != null) { - tracer.Rf_allocateVector(mode, n); - } - SEXPTYPE type = SEXPTYPE.mapInt(mode); - if (n < 0) { - throw RError.error(RError.SHOW_CALLER2, RError.Message.NEGATIVE_LENGTH_VECTORS_NOT_ALLOWED); - // TODO check long vector - } - switch (type) { - case INTSXP: - return RDataFactory.createIntVector(new int[n], RDataFactory.COMPLETE_VECTOR); - case REALSXP: - return RDataFactory.createDoubleVector(new double[n], RDataFactory.COMPLETE_VECTOR); - case LGLSXP: - return RDataFactory.createLogicalVector(new byte[n], RDataFactory.COMPLETE_VECTOR); - case STRSXP: - return RDataFactory.createStringVector(new String[n], RDataFactory.COMPLETE_VECTOR); - case CPLXSXP: - return RDataFactory.createComplexVector(new double[2 * n], RDataFactory.COMPLETE_VECTOR); - case RAWSXP: - return RDataFactory.createRawVector(new byte[n]); - case VECSXP: - return RDataFactory.createList(n); - case LANGSXP: - return RDataFactory.createLangPairList(n); - default: - throw unimplemented("unexpected SEXPTYPE " + type); + if (tracing) { + RFFIUtils.traceUpCall("Rf_allocateVector", mode, n); } + return delegate.Rf_allocateVector(mode, n); } @Override public Object Rf_allocateArray(int mode, Object dimsObj) { - if (tracer != null) { - tracer.Rf_allocateArray(mode, dimsObj); - } - RIntVector dims = (RIntVector) dimsObj; - int n = 1; - int[] newDims = new int[dims.getLength()]; - // TODO check long vector - for (int i = 0; i < newDims.length; i++) { - newDims[i] = dims.getDataAt(i); - n *= newDims[i]; + if (tracing) { + RFFIUtils.traceUpCall("Rf_allocateArray", mode, dimsObj); } - RAbstractVector result = (RAbstractVector) Rf_allocateVector(mode, n); - setDims(newDims, result); - return result; - - } - - @TruffleBoundary - private static void setDims(int[] newDims, RAbstractVector result) { - result.setDimensions(newDims); + return null; } @Override public Object Rf_allocateMatrix(int mode, int nrow, int ncol) { - if (tracer != null) { - tracer.Rf_allocateMatrix(mode, ncol, nrow); - } - SEXPTYPE type = SEXPTYPE.mapInt(mode); - if (nrow < 0 || ncol < 0) { - throw RError.error(RError.SHOW_CALLER2, RError.Message.NEGATIVE_EXTENTS_TO_MATRIX); - } - // TODO check long vector - int[] dims = new int[]{nrow, ncol}; - switch (type) { - case INTSXP: - return RDataFactory.createIntVector(new int[nrow * ncol], RDataFactory.COMPLETE_VECTOR, dims); - case REALSXP: - return RDataFactory.createDoubleVector(new double[nrow * ncol], RDataFactory.COMPLETE_VECTOR, dims); - case LGLSXP: - return RDataFactory.createLogicalVector(new byte[nrow * ncol], RDataFactory.COMPLETE_VECTOR, dims); - case STRSXP: - return RDataFactory.createStringVector(new String[nrow * ncol], RDataFactory.COMPLETE_VECTOR, dims); - case CPLXSXP: - return RDataFactory.createComplexVector(new double[2 * (nrow * ncol)], RDataFactory.COMPLETE_VECTOR, dims); - default: - throw unimplemented(); + if (tracing) { + RFFIUtils.traceUpCall("Rf_allocateMatrix", mode, ncol, nrow); } + return delegate.Rf_allocateMatrix(mode, nrow, ncol); } @Override public int Rf_nrows(Object x) { - if (tracer != null) { - tracer.Rf_nrows(x); + if (tracing) { + RFFIUtils.traceUpCall("Rf_nrows", x); } - return RRuntime.nrows(x); + return delegate.Rf_nrows(x); } @Override public int Rf_ncols(Object x) { - if (tracer != null) { - tracer.Rf_ncols(x); + if (tracing) { + RFFIUtils.traceUpCall("Rf_ncols", x); } - return RRuntime.ncols(x); + return delegate.Rf_ncols(x); } @Override public int LENGTH(Object x) { - if (tracer != null) { - tracer.LENGTH(x); + if (tracing) { + RFFIUtils.traceUpCall("LENGTH", x); } - return (int) FFIUpCallRootNode.getCallTarget(UpCallsIndex.LENGTH).call(x); + return delegate.LENGTH(x); } @Override public void SET_STRING_ELT(Object x, int i, Object v) { - if (tracer != null) { - tracer.SET_STRING_ELT(x, i, v); + if (tracing) { + RFFIUtils.traceUpCall("SET_STRING_ELT", x, i, v); } - RStringVector vector = guaranteeInstanceOf(x, RStringVector.class); - CharSXPWrapper element = guaranteeInstanceOf(v, CharSXPWrapper.class); - vector.setElement(i, element.getContents()); + delegate.SET_STRING_ELT(x, i, v); } @Override public void SET_VECTOR_ELT(Object x, int i, Object v) { - if (tracer != null) { - tracer.SET_VECTOR_ELT(x, i, v); + if (tracing) { + RFFIUtils.traceUpCall("SET_VECTOR_ELT", i, v); } - RList list = guaranteeInstanceOf(x, RList.class); - list.setElement(i, v); + delegate.SET_VECTOR_ELT(x, i, v); } @Override public Object RAW(Object x) { - if (tracer != null) { - tracer.RAW(x); - } - if (x instanceof RRawVector) { - return ((RRawVector) x).getDataWithoutCopying(); - } else if (x instanceof RRaw) { - return new byte[]{((RRaw) x).getValue()}; - } else { - throw unimplemented(); + if (tracing) { + RFFIUtils.traceUpCall("RAW", x); } + return delegate.RAW(x); } @Override public Object LOGICAL(Object x) { - if (tracer != null) { - tracer.LOGICAL(x); - } - if (x instanceof RLogicalVector) { - return ((RLogicalVector) x).getDataWithoutCopying(); - } else if (x instanceof Byte) { - return new byte[]{(Byte) x}; - } else { - throw unimplemented(); + if (tracing) { + RFFIUtils.traceUpCall("LOGICAL", x); } + return delegate.LOGICAL(x); } @Override public Object INTEGER(Object x) { - if (tracer != null) { - tracer.INTEGER(x); - } - if (x instanceof RIntVector) { - return ((RIntVector) x).getDataWithoutCopying(); - } else if (x instanceof RIntSequence) { - return ((RIntSequence) x).materialize().getDataWithoutCopying(); - } else if (x instanceof Integer) { - return new int[]{(Integer) x}; - } else if (x instanceof RLogicalVector) { - RLogicalVector vec = (RLogicalVector) x; - int[] result = new int[vec.getLength()]; - for (int i = 0; i < result.length; i++) { - result[i] = vec.getDataAt(i); - } - return result; - } else { - guaranteeInstanceOf(x, Byte.class); - return new int[]{(Byte) x}; + if (tracing) { + RFFIUtils.traceUpCall("INTEGER", x); } + return delegate.INTEGER(x); } @Override public Object REAL(Object x) { - if (tracer != null) { - tracer.REAL(x); - } - if (x instanceof RDoubleVector) { - return ((RDoubleVector) x).getDataWithoutCopying(); - } else if (x instanceof RDoubleSequence) { - return ((RDoubleSequence) x).materialize().getDataWithoutCopying(); - } else { - guaranteeInstanceOf(x, Double.class); - return new double[]{(Double) x}; + if (tracing) { + RFFIUtils.traceUpCall("REAL", x); } + return delegate.REAL(x); } @Override public Object STRING_ELT(Object x, int i) { - if (tracer != null) { - tracer.STRING_ELT(x, i); + if (tracing) { + RFFIUtils.traceUpCall("STRING_ELT", x, i); } - RAbstractStringVector vector = guaranteeInstanceOf(RRuntime.asAbstractVector(x), RAbstractStringVector.class); - return CharSXPWrapper.create(vector.getDataAt(i)); + return delegate.STRING_ELT(x, i); } @Override public Object VECTOR_ELT(Object x, int i) { - if (tracer != null) { - tracer.VECTOR_ELT(x, i); - } - Object vec = x; - if (vec instanceof RExpression) { - return ((RExpression) vec).getDataAt(i); + if (tracing) { + RFFIUtils.traceUpCall("VECTOR_ELT", x, i); } - RAbstractListVector list = guaranteeInstanceOf(RRuntime.asAbstractVector(vec), RAbstractListVector.class); - return list.getDataAt(i); + return delegate.VECTOR_ELT(x, i); } @Override public int NAMED(Object x) { - if (tracer != null) { - tracer.NAMED(x); - } - if (x instanceof RShareable) { - return ((RShareable) x).isShared() ? 1 : 0; - } else { - throw unimplemented(); + if (tracing) { + RFFIUtils.traceUpCall("NAMED", x); } + return delegate.NAMED(x); } @Override public Object SET_TYPEOF_FASTR(Object x, int v) { - if (tracer != null) { - tracer.SET_TYPEOF_FASTR(x, v); - } - int code = SEXPTYPE.gnuRCodeForObject(x); - if (code == SEXPTYPE.LISTSXP.code && v == SEXPTYPE.LANGSXP.code) { - return RLanguage.fromList(x, RLanguage.RepType.CALL); - } else { - throw unimplemented(); + if (tracing) { + RFFIUtils.traceUpCall("SET_TYPEOF_FASTR", x, v); } + return delegate.SET_TYPEOF_FASTR(x, v); } @Override public int TYPEOF(Object x) { - if (tracer != null) { - tracer.TYPEOF(x); - } - if (x instanceof CharSXPWrapper) { - return SEXPTYPE.CHARSXP.code; - } else { - return SEXPTYPE.gnuRCodeForObject(x); + if (tracing) { + RFFIUtils.traceUpCall("TYPEOF", x); } + return delegate.TYPEOF(x); } @Override - @TruffleBoundary public int OBJECT(Object x) { - if (tracer != null) { - tracer.OBJECT(x); - } - if (x instanceof RAttributable) { - return ((RAttributable) x).getAttr(RRuntime.CLASS_ATTR_KEY) == null ? 0 : 1; - } else { - return 0; + if (tracing) { + RFFIUtils.traceUpCall("OBJECT", x); } + return delegate.OBJECT(x); } @Override public Object Rf_duplicate(Object x, int deep) { - if (tracer != null) { - tracer.Rf_duplicate(x, deep); - } - guarantee(x != null, "unexpected type: null instead of " + x.getClass().getSimpleName()); - guarantee(x instanceof RShareable || x instanceof RSequence || x instanceof RExternalPtr, - "unexpected type: " + x + " is " + x.getClass().getSimpleName() + " instead of RShareable or RExternalPtr"); - if (x instanceof RShareable) { - return deep == 1 ? ((RShareable) x).deepCopy() : ((RShareable) x).copy(); - } else if (x instanceof RSequence) { - return ((RSequence) x).materializeToShareable(); - } else { - return ((RExternalPtr) x).copy(); + if (tracing) { + RFFIUtils.traceUpCall("Rf_duplicate", x, deep); } + return delegate.Rf_duplicate(x, deep); } @Override public int Rf_anyDuplicated(Object x, int fromLast) { - if (tracer != null) { - tracer.Rf_anyDuplicated(x, fromLast); - } - RAbstractVector vec = (RAbstractVector) x; - if (vec.getLength() == 0) { - return 0; - } else { - return DuplicationHelper.analyze(vec, null, true, fromLast != 0).getIndex(); + if (tracing) { + RFFIUtils.traceUpCall("Rf_anyDuplicated", x, fromLast); } + return delegate.Rf_anyDuplicated(x, fromLast); } @Override public Object PRINTNAME(Object x) { - if (tracer != null) { - tracer.PRINTNAME(x); + if (tracing) { + RFFIUtils.traceUpCall("PRINTNAME", x); } - guaranteeInstanceOf(x, RSymbol.class); - return CharSXPWrapper.create(((RSymbol) x).getName()); + return delegate.PRINTNAME(x); } @Override public Object TAG(Object e) { - if (tracer != null) { - tracer.TAG(e); - } - if (e instanceof RPairList) { - return ((RPairList) e).getTag(); - } else { - guaranteeInstanceOf(e, RExternalPtr.class); - // at the moment, this can only be used to null out the pointer - return ((RExternalPtr) e).getTag(); + if (tracing) { + RFFIUtils.traceUpCall("TAG", e); } + return delegate.TAG(e); } @Override public Object CAR(Object e) { - if (tracer != null) { - tracer.CAR(e); + if (tracing) { + RFFIUtils.traceUpCall("CAR", e); } - return FFIUpCallRootNode.getCallTarget(UpCallsIndex.CAR).call(e); + return delegate.CAR(e); } @Override public Object CDR(Object e) { - if (tracer != null) { - tracer.CDR(e); + if (tracing) { + RFFIUtils.traceUpCall("CDR", e); } - return FFIUpCallRootNode.getCallTarget(UpCallsIndex.CDR).call(e); + return delegate.CDR(e); } @Override public Object CADR(Object e) { - if (tracer != null) { - tracer.CADR(e); + if (tracing) { + RFFIUtils.traceUpCall("CADR", e); } - return FFIUpCallRootNode.getCallTarget(UpCallsIndex.CADR).call(e); + return delegate.CADR(e); } @Override public Object CADDR(Object e) { - if (tracer != null) { - tracer.CADDR(e); + if (tracing) { + RFFIUtils.traceUpCall("CADDR", e); } - return FFIUpCallRootNode.getCallTarget(UpCallsIndex.CADDR).call(e); + return delegate.CADDR(e); } @Override public Object CDDR(Object e) { - if (tracer != null) { - tracer.CDDR(e); + if (tracing) { + RFFIUtils.traceUpCall("CDDR", e); } - return FFIUpCallRootNode.getCallTarget(UpCallsIndex.CDDR).call(e); + return delegate.CDDR(e); } @Override public Object SET_TAG(Object x, Object y) { - if (tracer != null) { - tracer.SET_TAG(x, y); - } - if (x instanceof RPairList) { - ((RPairList) x).setTag(y); - } else { - guaranteeInstanceOf(x, RExternalPtr.class); - // at the moment, this can only be used to null out the pointer - ((RExternalPtr) x).setTag(y); + if (tracing) { + RFFIUtils.traceUpCall("SET_TAG", x, y); } - return y; + return delegate.SET_TAG(x, y); } @Override public Object SETCAR(Object x, Object y) { - if (tracer != null) { - tracer.SETCAR(x, y); + if (tracing) { + RFFIUtils.traceUpCall("SETCAR", x, y); } - guaranteeInstanceOf(x, RPairList.class); - ((RPairList) x).setCar(y); - return y; + return delegate.SETCAR(x, y); } @Override public Object SETCDR(Object x, Object y) { - if (tracer != null) { - tracer.SETCDR(x, y); + if (tracing) { + RFFIUtils.traceUpCall("SETCDR", x, y); } - guaranteeInstanceOf(x, RPairList.class); - ((RPairList) x).setCdr(y); - return y; + return delegate.SETCDR(x, y); } @Override public Object SETCADR(Object x, Object y) { - if (tracer != null) { - tracer.SETCADR(x, y); + if (tracing) { + RFFIUtils.traceUpCall("SETCADR", x); } - SETCAR(CDR(x), y); - return y; + return delegate.SETCADR(x, y); } @Override public Object SYMVALUE(Object x) { - if (tracer != null) { - tracer.SYMVALUE(x); - } - if (!(x instanceof RSymbol)) { - throw RInternalError.shouldNotReachHere(); - } - Object res = REnvironment.baseEnv().get(((RSymbol) x).getName()); - if (res == null) { - return RUnboundValue.instance; - } else { - return res; + if (tracing) { + RFFIUtils.traceUpCall("SYMVALUE", x); } + return delegate.SYMVALUE(x); } @Override public void SET_SYMVALUE(Object x, Object v) { - if (tracer != null) { - tracer.SET_SYMVALUE(x, v); - } - if (!(x instanceof RSymbol)) { - throw RInternalError.shouldNotReachHere(); + if (tracing) { + RFFIUtils.traceUpCall("SET_SYMVALUE", x, v); } - REnvironment.baseEnv().safePut(((RSymbol) x).getName(), v); + delegate.SET_SYMVALUE(x, v); } @Override public int R_BindingIsLocked(Object sym, Object env) { - if (tracer != null) { - tracer.R_BindingIsLocked(sym, env); + if (tracing) { + RFFIUtils.traceUpCall("R_BindingIsLocked", sym, env); } - guaranteeInstanceOf(sym, RSymbol.class); - guaranteeInstanceOf(env, REnvironment.class); - return ((REnvironment) env).bindingIsLocked(((RSymbol) sym).getName()) ? 1 : 0; + return delegate.R_BindingIsLocked(sym, env); } @Override public Object R_FindNamespace(Object name) { - if (tracer != null) { - tracer.R_FindNamespace(name); + if (tracing) { + RFFIUtils.traceUpCall("R_FindNamespace", name); } - Object result = RContext.getInstance().stateREnvironment.getNamespaceRegistry().get(RRuntime.asString(name)); - return result; + return delegate.R_FindNamespace(name); } @Override public Object Rf_eval(Object expr, Object env) { - if (tracer != null) { - tracer.Rf_eval(expr, env); - } - guarantee(env instanceof REnvironment); - Object result; - if (expr instanceof RPromise) { - result = RContext.getRRuntimeASTAccess().forcePromise(null, expr); - } else if (expr instanceof RExpression) { - result = RContext.getEngine().eval((RExpression) expr, (REnvironment) env, RCaller.topLevel); - } else if (expr instanceof RLanguage) { - result = RContext.getEngine().eval((RLanguage) expr, (REnvironment) env, RCaller.topLevel); - } else if (expr instanceof RPairList) { - RPairList l = (RPairList) expr; - RFunction f = (RFunction) l.car(); - Object args = l.cdr(); - if (args == RNull.instance) { - result = RContext.getEngine().evalFunction(f, env == REnvironment.globalEnv() ? null : ((REnvironment) env).getFrame(), RCaller.topLevel, null, new Object[0]); - } else { - RList argsList = ((RPairList) args).toRList(); - result = RContext.getEngine().evalFunction(f, env == REnvironment.globalEnv() ? null : ((REnvironment) env).getFrame(), RCaller.topLevel, argsList.getNames(), - argsList.getDataNonShared()); - } - } else { - // just return value - result = expr; - } - return result; + if (tracing) { + RFFIUtils.traceUpCall("Rf_eval", expr, env); + } + return delegate.Rf_eval(expr, env); } @Override public Object Rf_findfun(Object symbolObj, Object envObj) { - if (tracer != null) { - tracer.Rf_findfun(symbolObj, envObj); - } - guarantee(envObj instanceof REnvironment); - REnvironment env = (REnvironment) envObj; - guarantee(symbolObj instanceof RSymbol); - RSymbol symbol = (RSymbol) symbolObj; - // Works but not remotely efficient - Source source = RSource.fromTextInternal("get(\"" + symbol.getName() + "\", mode=\"function\")", RSource.Internal.RF_FINDFUN); - try { - Object result = RContext.getEngine().parseAndEval(source, env.getFrame(), false); - return result; - } catch (ParseException ex) { - throw RInternalError.shouldNotReachHere(ex); + if (tracing) { + RFFIUtils.traceUpCall("Rf_findfun", symbolObj, envObj); } + return delegate.Rf_findfun(symbolObj, envObj); } @Override public Object Rf_GetOption1(Object tag) { - if (tracer != null) { - tracer.Rf_GetOption1(tag); + if (tracing) { + RFFIUtils.traceUpCall("Rf_GetOption1", tag); } - guarantee(tag instanceof RSymbol); - Object result = RContext.getInstance().stateROptions.getValue(((RSymbol) tag).getName()); - return result; + return delegate.Rf_GetOption1(tag); } @Override public void Rf_gsetVar(Object symbol, Object value, Object rho) { - if (tracer != null) { - tracer.Rf_gsetVar(symbol, value, rho); - } - guarantee(symbol instanceof RSymbol); - REnvironment baseEnv = RContext.getInstance().stateREnvironment.getBaseEnv(); - guarantee(rho == baseEnv); - try { - baseEnv.put(((RSymbol) symbol).getName(), value); - } catch (PutException e) { - e.printStackTrace(); + if (tracing) { + RFFIUtils.traceUpCall("Rf_gsetVar", symbol, value, rho); } + delegate.Rf_gsetVar(symbol, value, rho); } @Override public void DUPLICATE_ATTRIB(Object to, Object from) { - if (tracer != null) { - tracer.DUPLICATE_ATTRIB(to, from); + if (tracing) { + RFFIUtils.traceUpCall("DUPLICATE_ATTRIB", to, from); } - if (from instanceof RAttributable) { - guaranteeInstanceOf(to, RAttributable.class); - DynamicObject attributes = ((RAttributable) from).getAttributes(); - ((RAttributable) to).initAttributes(attributes == null ? null : RAttributesLayout.copy(attributes)); - } - // TODO: copy OBJECT? and S4 attributes + delegate.DUPLICATE_ATTRIB(to, from); } @Override public int R_computeIdentical(Object x, Object y, int flags) { - if (tracer != null) { - tracer.R_computeIdentical(x, y, flags); + if (tracing) { + RFFIUtils.traceUpCall("R_computeIdentical", x, y, flags); } - RFunction indenticalBuiltin = RContext.lookupBuiltin("identical"); - Object res = RContext.getEngine().evalFunction(indenticalBuiltin, null, null, null, x, y, RRuntime.asLogical((!((flags & 1) == 0))), - RRuntime.asLogical((!((flags & 2) == 0))), RRuntime.asLogical((!((flags & 4) == 0))), RRuntime.asLogical((!((flags & 8) == 0))), RRuntime.asLogical((!((flags & 16) == 0)))); - return (int) res; + return delegate.R_computeIdentical(x, y, flags); } @Override public void Rf_copyListMatrix(Object s, Object t, int byrow) { - if (tracer != null) { - tracer.Rf_copyListMatrix(s, t, byrow); + if (tracing) { + RFFIUtils.traceUpCall("Rf_copyListMatrix", t, byrow); } - throw unimplemented(); + delegate.Rf_copyListMatrix(s, t, byrow); } @Override public void Rf_copyMatrix(Object s, Object t, int byrow) { - if (tracer != null) { - tracer.Rf_copyMatrix(s, t, byrow); + if (tracing) { + RFFIUtils.traceUpCall("Rf_copyMatrix", t, byrow); } - throw unimplemented(); + delegate.Rf_copyMatrix(s, t, byrow); } @Override public Object R_tryEval(Object expr, Object env, boolean silent) { - if (tracer != null) { - tracer.R_tryEval(expr, env, silent); - } - Object handlerStack = RErrorHandling.getHandlerStack(); - Object restartStack = RErrorHandling.getRestartStack(); - try { - // TODO handle silent - RErrorHandling.resetStacks(); - Object result = Rf_eval(expr, env); - return result; - } catch (Throwable t) { - return null; - } finally { - RErrorHandling.restoreStacks(handlerStack, restartStack); + if (tracing) { + RFFIUtils.traceUpCall("R_tryEval", expr, env, silent); } + return delegate.R_tryEval(expr, env, silent); } - /** - * Helper function for {@code R_TopLevelExec} which is similar to {@code R_TryEval} except that - * a C function is invoked (in the native layer) instead of an R expression. assert: this is - * ONLY called from R_TopLevelExec prior to calling C function. - */ @Override public Object R_ToplevelExec() { - if (tracer != null) { - tracer.R_ToplevelExec(); + if (tracing) { + RFFIUtils.traceUpCall("R_TopLevelExec"); } - return RErrorHandling.resetAndGetHandlerStacks(); - } - - /** - * Helper function for {@code R_TopLevelExec}, see {@link #R_ToplevelExec()}, called after C - * function returns. - */ - public void R_ToplevelExecRestoreErrorHandlerStacks(Object stacks) { - RErrorHandling.HandlerStacks handlerStacks = guaranteeInstanceOf(stacks, RErrorHandling.HandlerStacks.class); - RErrorHandling.restoreHandlerStacks(handlerStacks); + return delegate.R_ToplevelExec(); } @Override public int RDEBUG(Object x) { - if (tracer != null) { - tracer.RDEBUG(x); - } - REnvironment env = guaranteeInstanceOf(x, REnvironment.class); - if (env instanceof REnvironment.Function) { - REnvironment.Function funcEnv = (REnvironment.Function) env; - RFunction func = RArguments.getFunction(funcEnv.getFrame()); - return RContext.getRRuntimeASTAccess().isDebugged(func) ? 1 : 0; - } else { - return 0; + if (tracing) { + RFFIUtils.traceUpCall("RDEBUG", x); } + return delegate.RDEBUG(x); } @Override public void SET_RDEBUG(Object x, int v) { - if (tracer != null) { - tracer.SET_RDEBUG(x, v); - } - REnvironment env = guaranteeInstanceOf(x, REnvironment.class); - if (env instanceof REnvironment.Function) { - REnvironment.Function funcEnv = (REnvironment.Function) env; - RFunction func = RArguments.getFunction(funcEnv.getFrame()); - if (v == 1) { - RContext.getRRuntimeASTAccess().enableDebug(func, false); - } else { - RContext.getRRuntimeASTAccess().disableDebug(func); - } + if (tracing) { + RFFIUtils.traceUpCall("SET_RDEBUG", x, v); } + delegate.SET_RDEBUG(x, v); } @Override public int RSTEP(Object x) { - if (tracer != null) { - tracer.RSTEP(x); + if (tracing) { + RFFIUtils.traceUpCall("RSTEP", x); } - @SuppressWarnings("unused") - REnvironment env = guaranteeInstanceOf(x, REnvironment.class); - throw RInternalError.unimplemented("RSTEP"); + return delegate.RSTEP(x); } @Override public void SET_RSTEP(Object x, int v) { - if (tracer != null) { - tracer.SET_RSTEP(x, v); + if (tracing) { + RFFIUtils.traceUpCall("SET_RSTEP", x, v); } - @SuppressWarnings("unused") - REnvironment env = guaranteeInstanceOf(x, REnvironment.class); - throw RInternalError.unimplemented("SET_RSTEP"); + delegate.SET_RSTEP(x, v); } @Override public Object ENCLOS(Object x) { - if (tracer != null) { - tracer.ENCLOS(x); + if (tracing) { + RFFIUtils.traceUpCall("ENCLOS", x); } - REnvironment env = guaranteeInstanceOf(x, REnvironment.class); - Object result = env.getParent(); - if (result == null) { - result = RNull.instance; - } - return result; + return delegate.ENCLOS(x); } @Override public Object PRVALUE(Object x) { - if (tracer != null) { - tracer.PRVALUE(x); + if (tracing) { + RFFIUtils.traceUpCall("PRVALUE", x); } - RPromise p = guaranteeInstanceOf(x, RPromise.class); - return p.isEvaluated() ? p.getValue() : RUnboundValue.instance; + return delegate.PRVALUE(x); } @Override public Object R_ParseVector(Object text, int n, Object srcFile) { - if (tracer != null) { - tracer.R_ParseVector(text, n, srcFile); - } - // TODO general case - assert n == 1; - assert srcFile == RNull.instance; - String textString = RRuntime.asString(text); - assert textString != null; - - try { - Source source = RSource.fromTextInternal(textString, RSource.Internal.R_PARSEVECTOR); - RExpression exprs = RContext.getEngine().parse(source); - return new ParseResult(ParseStatus.PARSE_OK.ordinal(), exprs); - } catch (ParseException ex) { - // TODO incomplete - return new ParseResult(ParseStatus.PARSE_ERROR.ordinal(), RNull.instance); + if (tracing) { + RFFIUtils.traceUpCall("R_ParseVector", text, n, srcFile); } + return delegate.R_ParseVector(text, n, srcFile); } @Override public Object R_lsInternal3(Object envArg, int allArg, int sortedArg) { - if (tracer != null) { - tracer.R_lsInternal3(envArg, allArg, sortedArg); + if (tracing) { + RFFIUtils.traceUpCall("R_lsInternal3", envArg, allArg, sortedArg); } - boolean sorted = sortedArg != 0; - boolean all = allArg != 0; - REnvironment env = guaranteeInstanceOf(envArg, REnvironment.class); - return env.ls(all, null, sorted); + return delegate.R_lsInternal3(envArg, allArg, sortedArg); } @Override public String R_HomeDir() { - if (tracer != null) { - tracer.R_HomeDir(); + if (tracing) { + RFFIUtils.traceUpCall("R_HomeDir"); } - return REnvVars.rHome(); + return delegate.R_HomeDir(); } @Override public void R_CleanUp(int sa, int status, int runlast) { - if (tracer != null) { - tracer.R_CleanUp(sa, status, runlast); + if (tracing) { + RFFIUtils.traceUpCall("R_Cleanup", sa, status, runlast); } - RCleanUp.stdCleanUp(SA_TYPE.values()[sa], status, runlast != 0); + delegate.R_CleanUp(sa, status, runlast); } @Override public Object R_GlobalContext() { - if (tracer != null) { - tracer.R_GlobalContext(); - } - Utils.warn("Potential memory leak (global context object)"); - Frame frame = Utils.getActualCurrentFrame(); - if (frame == null) { - return RCaller.topLevel; - } - if (RContext.getInstance().stateInstrumentation.getBrowserState().inBrowser()) { - return RContext.getInstance().stateInstrumentation.getBrowserState().getInBrowserCaller(); + if (tracing) { + RFFIUtils.traceUpCall("R_GlobalContext"); } - RCaller rCaller = RArguments.getCall(frame); - return rCaller == null ? RCaller.topLevel : rCaller; + return delegate.R_GlobalContext(); } @Override public Object R_GlobalEnv() { - if (tracer != null) { - tracer.R_GlobalEnv(); + if (tracing) { + RFFIUtils.traceUpCall("R_GlobalEnv"); } - return RContext.getInstance().stateREnvironment.getGlobalEnv(); + return delegate.R_GlobalEnv(); } @Override public Object R_BaseEnv() { - if (tracer != null) { - tracer.R_BaseEnv(); + if (tracing) { + RFFIUtils.traceUpCall("R_BaseEnv"); } - return RContext.getInstance().stateREnvironment.getBaseEnv(); + return delegate.R_BaseEnv(); } @Override public Object R_BaseNamespace() { - if (tracer != null) { - tracer.R_BaseNamespace(); + if (tracing) { + RFFIUtils.traceUpCall("R_BaseNamespace"); } - return RContext.getInstance().stateREnvironment.getBaseNamespace(); + return delegate.R_BaseNamespace(); } @Override public Object R_NamespaceRegistry() { - if (tracer != null) { - tracer.R_NamespaceRegistry(); + if (tracing) { + RFFIUtils.traceUpCall("R_NamespaceRegistry"); } - return RContext.getInstance().stateREnvironment.getNamespaceRegistry(); + return delegate.R_NamespaceRegistry(); } @Override public int R_Interactive() { - if (tracer != null) { - tracer.R_Interactive(); + if (tracing) { + RFFIUtils.traceUpCall("isInteractive"); } - return RContext.getInstance().isInteractive() ? 1 : 0; + return delegate.R_Interactive(); } @Override public int IS_S4_OBJECT(Object x) { - if (tracer != null) { - tracer.IS_S4_OBJECT(x); + if (tracing) { + RFFIUtils.traceUpCall("isS4Object"); } - return x instanceof RS4Object ? 1 : 0; + return delegate.IS_S4_OBJECT(x); } @Override - public void Rprintf(String message) { - if (tracer != null) { - tracer.Rprintf(message); + public void Rprintf(Object message) { + if (tracing) { + RFFIUtils.traceUpCall("Rprintf", message); } - RContext.getInstance().getConsoleHandler().print(message); + delegate.Rprintf(message); } @Override public void GetRNGstate() { - if (tracer != null) { - tracer.GetRNGstate(); + if (tracing) { + RFFIUtils.traceUpCall("GetRNGstate"); } - RRNG.getRNGState(); + delegate.GetRNGstate(); } @Override public void PutRNGstate() { - if (tracer != null) { - tracer.PutRNGstate(); + if (tracing) { + RFFIUtils.traceUpCall("PutRNGstate"); } - RRNG.putRNGState(); + delegate.PutRNGstate(); } @Override public double unif_rand() { - if (tracer != null) { - tracer.unif_rand(); + if (tracing) { + RFFIUtils.traceUpCall("unif_rand"); } - return RRNG.unifRand(); + return delegate.unif_rand(); } - // Checkstyle: stop method name check - @Override public Object R_getGlobalFunctionContext() { - if (tracer != null) { - tracer.R_getGlobalFunctionContext(); - } - Utils.warn("Potential memory leak (global function context object)"); - Frame frame = Utils.getActualCurrentFrame(); - if (frame == null) { - return RNull.instance; + if (tracing) { + RFFIUtils.traceUpCall("R_getGlobalFunctionContext"); } - RCaller currentCaller = RArguments.getCall(frame); - while (currentCaller != null) { - if (!currentCaller.isPromise() && currentCaller.isValidCaller() && currentCaller != RContext.getInstance().stateInstrumentation.getBrowserState().getInBrowserCaller()) { - break; - } - currentCaller = currentCaller.getParent(); - } - return currentCaller == null || currentCaller == RCaller.topLevel ? RNull.instance : currentCaller; + return delegate.R_getGlobalFunctionContext(); } @Override public Object R_getParentFunctionContext(Object c) { - if (tracer != null) { - tracer.R_getParentFunctionContext(c); - } - Utils.warn("Potential memory leak (parent function context object)"); - RCaller currentCaller = guaranteeInstanceOf(c, RCaller.class); - while (true) { - currentCaller = currentCaller.getParent(); - if (currentCaller == null || - (!currentCaller.isPromise() && currentCaller.isValidCaller() && currentCaller != RContext.getInstance().stateInstrumentation.getBrowserState().getInBrowserCaller())) { - break; - } + if (tracing) { + RFFIUtils.traceUpCall("R_getParentFunctionContext"); } - return currentCaller == null || currentCaller == RCaller.topLevel ? RNull.instance : currentCaller; + return delegate.R_getParentFunctionContext(c); } @Override public Object R_getContextEnv(Object c) { - if (tracer != null) { - tracer.R_getContextEnv(c); - } - RCaller rCaller = guaranteeInstanceOf(c, RCaller.class); - if (rCaller == RCaller.topLevel) { - return RContext.getInstance().stateREnvironment.getGlobalEnv(); - } - Frame frame = Utils.getActualCurrentFrame(); - if (RArguments.getCall(frame) == rCaller) { - return REnvironment.frameToEnvironment(frame.materialize()); - } else { - Object result = Utils.iterateRFrames(FrameAccess.READ_ONLY, new Function<Frame, Object>() { - - @Override - public Object apply(Frame f) { - RCaller currentCaller = RArguments.getCall(f); - if (currentCaller == rCaller) { - return REnvironment.frameToEnvironment(f.materialize()); - } else { - return null; - } - } - }); - return result; + if (tracing) { + RFFIUtils.traceUpCall("R_getContextEnv", c); } + return delegate.R_getContextEnv(c); } @Override public Object R_getContextFun(Object c) { - if (tracer != null) { - tracer.R_getContextFun(c); - } - RCaller rCaller = guaranteeInstanceOf(c, RCaller.class); - if (rCaller == RCaller.topLevel) { - return RNull.instance; - } - Frame frame = Utils.getActualCurrentFrame(); - if (RArguments.getCall(frame) == rCaller) { - return RArguments.getFunction(frame); - } else { - Object result = Utils.iterateRFrames(FrameAccess.READ_ONLY, new Function<Frame, Object>() { - - @Override - public Object apply(Frame f) { - RCaller currentCaller = RArguments.getCall(f); - if (currentCaller == rCaller) { - return RArguments.getFunction(f); - } else { - return null; - } - } - }); - return result; + if (tracing) { + RFFIUtils.traceUpCall("R_getContextFun", c); } + return delegate.R_getContextFun(c); } @Override public Object R_getContextCall(Object c) { - if (tracer != null) { - tracer.R_getContextCall(c); - } - RCaller rCaller = guaranteeInstanceOf(c, RCaller.class); - if (rCaller == RCaller.topLevel) { - return RNull.instance; + if (tracing) { + RFFIUtils.traceUpCall("R_getContextCall", c); } - return RContext.getRRuntimeASTAccess().getSyntaxCaller(rCaller); + return delegate.R_getContextCall(c); } @Override public Object R_getContextSrcRef(Object c) { - if (tracer != null) { - tracer.R_getContextSrcRef(c); - } - Object o = R_getContextFun(c); - if (!(o instanceof RFunction)) { - return RNull.instance; - } else { - RFunction f = (RFunction) o; - SourceSection ss = f.getRootNode().getSourceSection(); - String path = RSource.getPath(ss.getSource()); - // TODO: is it OK to pass "" if path is null? - return RSrcref.createLloc(ss, path == null ? "" : path); + if (tracing) { + RFFIUtils.traceUpCall("R_getContextSrcRef", c); } + return delegate.R_getContextSrcRef(c); } @Override public int R_insideBrowser() { - if (tracer != null) { - tracer.R_insideBrowser(); + if (tracing) { + RFFIUtils.traceUpCall("R_insideBrowser"); } - return RContext.getInstance().stateInstrumentation.getBrowserState().inBrowser() ? 1 : 0; + return delegate.R_insideBrowser(); } @Override public int R_isGlobal(Object c) { - if (tracer != null) { - tracer.R_isGlobal(c); + if (tracing) { + RFFIUtils.traceUpCall("R_isGlobal", c); } - RCaller rCaller = guaranteeInstanceOf(c, RCaller.class); - - return rCaller == RCaller.topLevel ? 1 : 0; + return delegate.R_isGlobal(c); } @Override public int R_isEqual(Object x, Object y) { - if (tracer != null) { - tracer.R_isEqual(x, y); + if (tracing) { + RFFIUtils.traceUpCall("isEqual", x, y); } - return x == y ? 1 : 0; + return delegate.R_isEqual(x, y); } @Override - @TruffleBoundary public Object Rf_classgets(Object x, Object y) { - if (tracer != null) { - tracer.Rf_classgets(x, y); + if (tracing) { + RFFIUtils.traceUpCall("Rf_classgets", x, y); } - RAbstractVector vector = guaranteeInstanceOf(x, RAbstractVector.class); - vector.setClassAttr(guaranteeInstanceOf(y, RStringVector.class)); - return RNull.instance; + return delegate.Rf_classgets(x, y); } @Override public RExternalPtr R_MakeExternalPtr(long addr, Object tag, Object prot) { - if (tracer != null) { - tracer.R_MakeExternalPtr(addr, tag, prot); + if (tracing) { + RFFIUtils.traceUpCall("R_MakeExternalPtr", addr, tag, prot); } - return RDataFactory.createExternalPtr(new SymbolHandle(addr), tag, prot); + return delegate.R_MakeExternalPtr(addr, tag, prot); } @Override public long R_ExternalPtrAddr(Object x) { - if (tracer != null) { - tracer.R_ExternalPtrAddr(x); + if (tracing) { + RFFIUtils.traceUpCall("R_ExternalPtrAddr", x); } - RExternalPtr p = guaranteeInstanceOf(x, RExternalPtr.class); - return p.getAddr().asAddress(); + return delegate.R_ExternalPtrAddr(x); } @Override public Object R_ExternalPtrTag(Object x) { - if (tracer != null) { - tracer.R_ExternalPtrTag(x); + if (tracing) { + RFFIUtils.traceUpCall("R_ExternalPtrTag", x); } - RExternalPtr p = guaranteeInstanceOf(x, RExternalPtr.class); - return p.getTag(); + return delegate.R_ExternalPtrTag(x); } @Override public Object R_ExternalPtrProt(Object x) { - if (tracer != null) { - tracer.R_ExternalPtrProt(x); + if (tracing) { + RFFIUtils.traceUpCall("R_ExternalPtrProt", x); } - RExternalPtr p = guaranteeInstanceOf(x, RExternalPtr.class); - return p.getProt(); + return delegate.R_ExternalPtrProt(x); } @Override public void R_SetExternalPtrAddr(Object x, long addr) { - if (tracer != null) { - tracer.R_SetExternalPtrAddr(x, addr); + if (tracing) { + RFFIUtils.traceUpCall("R_SetExternalPtrAddr", x); } - RExternalPtr p = guaranteeInstanceOf(x, RExternalPtr.class); - p.setAddr(new SymbolHandle(addr)); + delegate.R_SetExternalPtrAddr(x, addr); } @Override public void R_SetExternalPtrTag(Object x, Object tag) { - if (tracer != null) { - tracer.R_SetExternalPtrTag(x, tag); + if (tracing) { + RFFIUtils.traceUpCall("R_SetExternalPtrTag", x); } - RExternalPtr p = guaranteeInstanceOf(x, RExternalPtr.class); - p.setTag(tag); + delegate.R_SetExternalPtrTag(x, tag); } @Override public void R_SetExternalPtrProt(Object x, Object prot) { - if (tracer != null) { - tracer.R_SetExternalPtrProt(x, prot); + if (tracing) { + RFFIUtils.traceUpCall("R_ExternalPtrProt", x); } - RExternalPtr p = guaranteeInstanceOf(x, RExternalPtr.class); - p.setProt(prot); + delegate.R_SetExternalPtrProt(x, prot); } @Override - public REnvironment R_NewHashedEnv(REnvironment parent, String name, boolean hashed, int initialSize) { - if (tracer != null) { - tracer.R_NewHashedEnv(parent, name, hashed, initialSize); + public REnvironment R_NewHashedEnv(REnvironment parent, int initialSize) { + if (tracing) { + RFFIUtils.traceUpCall("R_NewHashedEnv", parent, initialSize); } - REnvironment env = RDataFactory.createNewEnv(name, hashed, initialSize); - RArguments.initializeEnclosingFrame(env.getFrame(), parent.getFrame()); - return env; + return delegate.R_NewHashedEnv(parent, initialSize); } // Implementation specific support + /** + * Helper function for {@code R_TopLevelExec}, see {@link #R_ToplevelExec()}, called after C + * function returns. + */ + @SuppressWarnings("static-method") + public void R_ToplevelExecRestoreErrorHandlerStacks(Object stacks) { + RErrorHandling.HandlerStacks handlerStacks = guaranteeInstanceOf(stacks, RErrorHandling.HandlerStacks.class); + RErrorHandling.restoreHandlerStacks(handlerStacks); + } + /** * Called to possibly update the "complete" status on {@code x}. N.B. {@code x} may not be an * object with a concrete {@code setComplete} method, e.g. see {@link #INTEGER(Object)}. */ + @SuppressWarnings("static-method") public void setComplete(Object x, boolean complete) { // only care about concrete vectors if (x instanceof RVector) { @@ -1506,6 +954,7 @@ public class UpCallsRFFIImpl implements UpCallsRFFI { /** * Called when a {@link CharSXPWrapper} is expected and not found. */ + @SuppressWarnings("static-method") public void logNotCharSXPWrapper(Object x) { System.out.println("object " + x); System.out.println("class " + x.getClass()); 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 d7154d5a2cdd42a3f668d7cceb8a4b398a60dadd..b766682261eb2c0da7e604ac025fdb10927dff39 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 @@ -27,8 +27,9 @@ 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.JavaUpCallsRFFIImpl; import com.oracle.truffle.r.nodes.ffi.RFFIUtils; +import com.oracle.truffle.r.nodes.ffi.UpCallsRFFIImpl; import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.ffi.CallRFFI; import com.oracle.truffle.r.runtime.ffi.NativeCallInfo; @@ -128,7 +129,7 @@ public class JNI_Call implements CallRFFI { traceDownCall("initialize"); } try { - initialize(new UpCallsRFFIImpl(), RFFIVariables.initialize()); + initialize(new UpCallsRFFIImpl(new JavaUpCallsRFFIImpl()), RFFIVariables.initialize()); } finally { if (traceEnabled()) { traceDownCallReturn("initialize", null); diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFICstring.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFICstring.java new file mode 100644 index 0000000000000000000000000000000000000000..c8dbee39e12f83ea246b81d120268560bb150ae7 --- /dev/null +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFICstring.java @@ -0,0 +1,37 @@ +/* + * 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.runtime.ffi; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Tags an upcall argument as being (on the native side) a C string. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.PARAMETER) +public @interface RFFICstring { + +} diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/StdUpCallsRFFI.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/StdUpCallsRFFI.java index 057cfaaba71e78bf7ddc0033b84d788b0532d424..b8f0ecf89d961d276e182a8fdb62576e4a77a304 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/StdUpCallsRFFI.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/StdUpCallsRFFI.java @@ -39,6 +39,10 @@ import com.oracle.truffle.r.runtime.env.REnvironment; * writing. From the GNU R perspective all {@code Object} parameters are {@code SEXP} instances. * Some of the functions are typed with a specific return type but, again, this is a {@code SEXP} in * GNU R terms. The native side does not require a specific Java type. + * + * N.B. It is important not to be too specific about types owing the support for Truffle interop + * implementations. For example, many arguments are "strings" but we do not specify them as + * {@code String} here. */ public interface StdUpCallsRFFI { // Checkstyle: stop method name check @@ -59,13 +63,13 @@ public interface StdUpCallsRFFI { Object Rf_asChar(Object x); - Object Rf_mkCharLenCE(byte[] bytes, int encoding); + Object Rf_mkCharLenCE(@RFFICstring Object bytes, int len, int encoding); Object Rf_cons(Object car, Object cdr); void Rf_defineVar(Object symbolArg, Object value, Object envArg); - Object R_do_MAKE_CLASS(String clazz); + Object R_do_MAKE_CLASS(@RFFICstring Object clazz); /** * WARNING: argument order reversed from Rf_findVarInFrame! @@ -80,9 +84,9 @@ public interface StdUpCallsRFFI { void Rf_setAttrib(Object obj, Object name, Object val); - int Rf_inherits(Object x, String clazz); + int Rf_inherits(@RFFICstring Object x, Object clazz); - Object Rf_install(String name); + Object Rf_install(@RFFICstring Object name); Object Rf_lengthgets(Object x, int newSize); @@ -92,11 +96,11 @@ public interface StdUpCallsRFFI { Object Rf_PairToVectorList(Object x); - void Rf_error(String msg); + void Rf_error(@RFFICstring Object msg); - void Rf_warning(String msg); + void Rf_warning(@RFFICstring Object msg); - void Rf_warningcall(Object call, String msg); + void Rf_warningcall(Object call, @RFFICstring Object msg); Object Rf_allocateVector(int mode, int n); @@ -208,7 +212,7 @@ public interface StdUpCallsRFFI { int IS_S4_OBJECT(Object x); - void Rprintf(String message); + void Rprintf(@RFFICstring Object message); void GetRNGstate(); @@ -234,6 +238,6 @@ public interface StdUpCallsRFFI { void R_CleanUp(int sa, int status, int runlast); - REnvironment R_NewHashedEnv(REnvironment parent, String name, boolean hashed, int initialSize); + REnvironment R_NewHashedEnv(REnvironment parent, int initialSize); } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tools/RFFIUpCallMethodGenerate.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tools/RFFIUpCallMethodGenerate.java new file mode 100644 index 0000000000000000000000000000000000000000..60881ee7aa783cb76a6fd2a395922f92b7c708df --- /dev/null +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tools/RFFIUpCallMethodGenerate.java @@ -0,0 +1,96 @@ +/* + * 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.test.tools; + +import java.lang.annotation.Annotation; +import java.lang.reflect.AnnotatedType; +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.Comparator; + +import com.oracle.truffle.r.nodes.ffi.RFFIUpCallMethod; +import com.oracle.truffle.r.runtime.ffi.RFFICstring; +import com.oracle.truffle.r.runtime.ffi.UpCallsRFFI; + +/** + * Generates the entries for {@link RFFIUpCallMethod}. + */ +public class RFFIUpCallMethodGenerate { + + public static void main(String[] args) { + Method[] methods = UpCallsRFFI.class.getMethods(); + + Arrays.sort(methods, new Comparator<Method>() { + + @Override + public int compare(Method a, Method b) { + return a.getName().compareTo(b.getName()); + } + + }); + for (int i = 0; i < methods.length; i++) { + Method m = methods[i]; + String sig = getNFISignature(m); + System.out.printf("%s(\"%s\")%s%n", m.getName(), sig, i == methods.length - 1 ? ";" : ","); + } + + } + + private static String getNFISignature(Method m) { + Class<?>[] paramTypes = m.getParameterTypes(); + Annotation[][] annotations = m.getParameterAnnotations(); + StringBuilder sb = new StringBuilder(); + sb.append('('); + for (int i = 0; i < paramTypes.length; i++) { + Class<?> paramType = paramTypes[i]; + String nfiParam = nfiParamName(paramType, annotations[i]); + sb.append(nfiParam); + if (i != paramTypes.length - 1) { + sb.append(", "); + } + } + sb.append(')'); + sb.append(" : "); + sb.append(nfiParamName(m.getReturnType(), new Annotation[0])); + return sb.toString(); + } + + static String nfiParamName(Class<?> paramType, Annotation[] annotation) { + String paramName = paramType.getSimpleName(); + Class<?> klass = annotation.length == 0 ? null : annotation[0].annotationType(); + switch (paramName) { + case "Object": + return klass == null ? "object" : "pointer"; + case "int": + return "sint32"; + case "double": + return "double"; + case "void": + return "void"; + default: + return "object"; + } + + } + +}