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..b903c34a33b245b303024cbba5565adec471c612 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 @@ -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..24b0336f2668f3b682ed2e38fa9b382879fe682e 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 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/RFFIUpCallMethod.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/RFFIUpCallMethod.java new file mode 100644 index 0000000000000000000000000000000000000000..280484b54e9225a9efbd92cc65588b8f7e6b8fca --- /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("(object) : 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("(object) : 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("(object, object) : sint32"), + Rf_install("(object) : object"), + Rf_isNull("(object) : sint32"), + Rf_isString("(object) : sint32"), + Rf_lengthgets("(object, sint32) : object"), + Rf_mkCharLenCE("(object, sint32, sint32) : object"), + Rf_ncols("(object) : sint32"), + Rf_nrows("(object) : sint32"), + Rf_setAttrib("(object, object, object) : void"), + Rf_warning("(object) : void"), + Rf_warningcall("(object, object) : void"), + Rprintf("(object) : 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 %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 index 2ba610c7b3796937d4ad400887ef22547e7d5bb8..2c42a92eb5bbeb27d1cc5d4124875a3fdddc3174 100644 --- 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 @@ -96,7 +96,7 @@ public class TraceUpCallsAdapter implements UpCallsRFFI { } @Override - public Object Rf_mkCharLenCE(byte[] bytes, int encoding) { + public Object Rf_mkCharLenCE(Object bytes, int len, int encoding) { if (RFFIUtils.traceEnabled()) { RFFIUtils.traceUpCall("Rf_mkCharLenCE", bytes); } @@ -119,7 +119,7 @@ public class TraceUpCallsAdapter implements UpCallsRFFI { } @Override - public Object R_do_MAKE_CLASS(String clazz) { + public Object R_do_MAKE_CLASS(Object clazz) { if (RFFIUtils.traceEnabled()) { RFFIUtils.traceUpCall("R_do_MAKE_CLASS", clazz); } @@ -166,7 +166,7 @@ public class TraceUpCallsAdapter implements UpCallsRFFI { } @Override - public int Rf_inherits(Object x, String clazz) { + public int Rf_inherits(Object x, Object clazz) { if (RFFIUtils.traceEnabled()) { RFFIUtils.traceUpCall("Rf_inherits", x, clazz); } @@ -174,7 +174,7 @@ public class TraceUpCallsAdapter implements UpCallsRFFI { } @Override - public Object Rf_install(String name) { + public Object Rf_install(Object name) { if (RFFIUtils.traceEnabled()) { RFFIUtils.traceUpCall("Rf_install", name); } @@ -214,21 +214,21 @@ public class TraceUpCallsAdapter implements UpCallsRFFI { } @Override - public void Rf_error(String msg) { + public void Rf_error(Object msg) { if (RFFIUtils.traceEnabled()) { RFFIUtils.traceUpCall("Rf_error", msg); } } @Override - public void Rf_warning(String msg) { + public void Rf_warning(Object msg) { if (RFFIUtils.traceEnabled()) { RFFIUtils.traceUpCall("Rf_warning", msg); } } @Override - public void Rf_warningcall(Object call, String msg) { + public void Rf_warningcall(Object call, Object msg) { if (RFFIUtils.traceEnabled()) { RFFIUtils.traceUpCall("Rf_warningcall", call, msg); } @@ -721,7 +721,7 @@ public class TraceUpCallsAdapter implements UpCallsRFFI { } @Override - public void Rprintf(String message) { + public void Rprintf(Object message) { if (RFFIUtils.traceEnabled()) { RFFIUtils.traceUpCall("Rprintf", message); } @@ -883,9 +883,9 @@ public class TraceUpCallsAdapter implements UpCallsRFFI { } @Override - public REnvironment R_NewHashedEnv(REnvironment parent, String name, boolean hashed, int initialSize) { + public REnvironment R_NewHashedEnv(REnvironment parent, int initialSize) { if (RFFIUtils.traceEnabled()) { - RFFIUtils.traceUpCall("R_NewHashedEnv", parent, name, hashed, initialSize); + RFFIUtils.traceUpCall("R_NewHashedEnv", parent, 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..dca6fda9cfd1bd9e9245eb6de371502cb15c9d45 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 @@ -108,7 +108,7 @@ public class UpCallsRFFIImpl implements UpCallsRFFI { if (RFFIUtils.traceEnabled()) { tracer = new TraceUpCallsAdapter(); } - UpCallsIndex.register(); + FFIUpCallRootNode.register(); } // Checkstyle: stop method name check @@ -157,7 +157,7 @@ public class UpCallsRFFIImpl implements UpCallsRFFI { if (tracer != null) { tracer.Rf_asInteger(x); } - return (int) FFIUpCallRootNode.getCallTarget(UpCallsIndex.Rf_asInteger).call(x); + return (int) FFIUpCallRootNode.getCallTarget(RFFIUpCallMethod.Rf_asInteger).call(x); } @Override @@ -165,7 +165,7 @@ public class UpCallsRFFIImpl implements UpCallsRFFI { if (tracer != null) { tracer.Rf_asReal(x); } - return (double) FFIUpCallRootNode.getCallTarget(UpCallsIndex.Rf_asReal).call(x); + return (double) FFIUpCallRootNode.getCallTarget(RFFIUpCallMethod.Rf_asReal).call(x); } @Override @@ -173,7 +173,7 @@ public class UpCallsRFFIImpl implements UpCallsRFFI { if (tracer != null) { tracer.Rf_asLogical(x); } - return (int) FFIUpCallRootNode.getCallTarget(UpCallsIndex.Rf_asLogical).call(x); + return (int) FFIUpCallRootNode.getCallTarget(RFFIUpCallMethod.Rf_asLogical).call(x); } @Override @@ -181,16 +181,16 @@ public class UpCallsRFFIImpl implements UpCallsRFFI { if (tracer != null) { tracer.Rf_asChar(x); } - return FFIUpCallRootNode.getCallTarget(UpCallsIndex.Rf_asChar).call(x); + return FFIUpCallRootNode.getCallTarget(RFFIUpCallMethod.Rf_asChar).call(x); } @Override - public Object Rf_mkCharLenCE(byte[] bytes, int encoding) { + public Object Rf_mkCharLenCE(Object bytes, int len, int encoding) { if (tracer != null) { - tracer.Rf_mkCharLenCE(bytes, encoding); + tracer.Rf_mkCharLenCE(bytes, len, encoding); } // TODO: handle encoding properly - return CharSXPWrapper.create(new String(bytes, StandardCharsets.UTF_8)); + return CharSXPWrapper.create(new String((byte[]) bytes, StandardCharsets.UTF_8)); } @Override @@ -216,7 +216,7 @@ public class UpCallsRFFIImpl implements UpCallsRFFI { } @Override - public Object R_do_MAKE_CLASS(String clazz) { + public Object R_do_MAKE_CLASS(Object clazz) { if (tracer != null) { tracer.R_do_MAKE_CLASS(clazz); } @@ -349,7 +349,7 @@ public class UpCallsRFFIImpl implements UpCallsRFFI { } @Override - public int Rf_inherits(Object x, String clazz) { + public int Rf_inherits(Object x, Object clazz) { if (tracer != null) { tracer.Rf_inherits(x, clazz); } @@ -364,11 +364,11 @@ public class UpCallsRFFIImpl implements UpCallsRFFI { } @Override - public Object Rf_install(String name) { + public Object Rf_install(Object name) { if (tracer != null) { tracer.Rf_install(name); } - return RDataFactory.createSymbolInterned(name); + return RDataFactory.createSymbolInterned((String) name); } @Override @@ -409,7 +409,7 @@ public class UpCallsRFFIImpl implements UpCallsRFFI { } @Override - public void Rf_error(String msg) { + public void Rf_error(Object msg) { if (tracer != null) { tracer.Rf_error(msg); } @@ -417,7 +417,7 @@ public class UpCallsRFFIImpl implements UpCallsRFFI { } @Override - public void Rf_warning(String msg) { + public void Rf_warning(Object msg) { if (tracer != null) { tracer.Rf_warning(msg); } @@ -425,11 +425,11 @@ public class UpCallsRFFIImpl implements UpCallsRFFI { } @Override - public void Rf_warningcall(Object call, String msg) { + public void Rf_warningcall(Object call, Object msg) { if (tracer != null) { tracer.Rf_warningcall(call, msg); } - RErrorHandling.warningcallRFFI(call, msg); + RErrorHandling.warningcallRFFI(call, (String) msg); } @Override @@ -536,7 +536,7 @@ public class UpCallsRFFIImpl implements UpCallsRFFI { if (tracer != null) { tracer.LENGTH(x); } - return (int) FFIUpCallRootNode.getCallTarget(UpCallsIndex.LENGTH).call(x); + return (int) FFIUpCallRootNode.getCallTarget(RFFIUpCallMethod.LENGTH).call(x); } @Override @@ -755,7 +755,7 @@ public class UpCallsRFFIImpl implements UpCallsRFFI { if (tracer != null) { tracer.CAR(e); } - return FFIUpCallRootNode.getCallTarget(UpCallsIndex.CAR).call(e); + return FFIUpCallRootNode.getCallTarget(RFFIUpCallMethod.CAR).call(e); } @Override @@ -763,7 +763,7 @@ public class UpCallsRFFIImpl implements UpCallsRFFI { if (tracer != null) { tracer.CDR(e); } - return FFIUpCallRootNode.getCallTarget(UpCallsIndex.CDR).call(e); + return FFIUpCallRootNode.getCallTarget(RFFIUpCallMethod.CDR).call(e); } @Override @@ -771,7 +771,7 @@ public class UpCallsRFFIImpl implements UpCallsRFFI { if (tracer != null) { tracer.CADR(e); } - return FFIUpCallRootNode.getCallTarget(UpCallsIndex.CADR).call(e); + return FFIUpCallRootNode.getCallTarget(RFFIUpCallMethod.CADR).call(e); } @Override @@ -779,7 +779,7 @@ public class UpCallsRFFIImpl implements UpCallsRFFI { if (tracer != null) { tracer.CADDR(e); } - return FFIUpCallRootNode.getCallTarget(UpCallsIndex.CADDR).call(e); + return FFIUpCallRootNode.getCallTarget(RFFIUpCallMethod.CADDR).call(e); } @Override @@ -787,7 +787,7 @@ public class UpCallsRFFIImpl implements UpCallsRFFI { if (tracer != null) { tracer.CDDR(e); } - return FFIUpCallRootNode.getCallTarget(UpCallsIndex.CDDR).call(e); + return FFIUpCallRootNode.getCallTarget(RFFIUpCallMethod.CDDR).call(e); } @Override @@ -1224,11 +1224,11 @@ public class UpCallsRFFIImpl implements UpCallsRFFI { } @Override - public void Rprintf(String message) { + public void Rprintf(Object message) { if (tracer != null) { tracer.Rprintf(message); } - RContext.getInstance().getConsoleHandler().print(message); + RContext.getInstance().getConsoleHandler().print((String) message); } @Override @@ -1481,11 +1481,11 @@ public class UpCallsRFFIImpl implements UpCallsRFFI { } @Override - public REnvironment R_NewHashedEnv(REnvironment parent, String name, boolean hashed, int initialSize) { + public REnvironment R_NewHashedEnv(REnvironment parent, int initialSize) { if (tracer != null) { - tracer.R_NewHashedEnv(parent, name, hashed, initialSize); + tracer.R_NewHashedEnv(parent, initialSize); } - REnvironment env = RDataFactory.createNewEnv(name, hashed, initialSize); + REnvironment env = RDataFactory.createNewEnv(REnvironment.UNNAMED, true, initialSize); RArguments.initializeEnclosingFrame(env.getFrame(), parent.getFrame()); return env; } 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..f39602135479b03085dc3d774a27aefe60f7b3d9 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(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(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(Object x, Object clazz); - Object Rf_install(String name); + Object Rf_install(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(Object msg); - void Rf_warning(String msg); + void Rf_warning(Object msg); - void Rf_warningcall(Object call, String msg); + void Rf_warningcall(Object call, 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(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..e9a7a0a5dcda166fdef346a6e17ecb33d8781388 --- /dev/null +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tools/RFFIUpCallMethodGenerate.java @@ -0,0 +1,91 @@ +/* + * 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.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.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(); + StringBuilder sb = new StringBuilder(); + sb.append('('); + for (int i = 0; i < paramTypes.length; i++) { + Class<?> paramType = paramTypes[i]; + String nfiParam = nfiParamName(paramType); + sb.append(nfiParam); + if (i != paramTypes.length - 1) { + sb.append(", "); + } + } + sb.append(')'); + sb.append(" : "); + sb.append(nfiParamName(m.getReturnType())); + return sb.toString(); + } + + static String nfiParamName(Class<?> paramType) { + String paramName = paramType.getSimpleName(); + switch (paramName) { + case "Object": + return "object"; + case "int": + return "sint32"; + case "double": + return "double"; + case "void": + return "void"; + default: + return "object"; + } + + } + +}