Skip to content
Snippets Groups Projects
Commit 730d98b9 authored by Lukas Stadler's avatar Lukas Stadler
Browse files

simplify access to interop factories (no more explicit thread safety management needed)

parent 1f2708cb
No related branches found
No related tags found
No related merge requests found
......@@ -23,12 +23,9 @@
package com.oracle.truffle.r.engine.interop;
import com.oracle.truffle.api.CompilerAsserts;
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.api.TruffleLanguage;
import com.oracle.truffle.api.interop.ForeignAccess;
import com.oracle.truffle.api.interop.MessageResolution;
import com.oracle.truffle.api.interop.TruffleObject;
import com.oracle.truffle.api.vm.PolyglotEngine;
import com.oracle.truffle.r.engine.TruffleRLanguage;
import com.oracle.truffle.r.runtime.RInternalError;
import com.oracle.truffle.r.runtime.context.RContext;
......@@ -49,106 +46,59 @@ import com.oracle.truffle.r.runtime.ffi.CharSXPWrapper;
import com.oracle.truffle.r.runtime.ffi.DLL;
/**
* A {@link ForeignAccess} instance captures the {@link Thread} that creates it and all uses are
* checked against the current thread. Therefore, in a world with multiple {@link PolyglotEngine}s,
* aka multiple {@link Thread} and {@link RContext} instances, it is not possible to use a simple
* global constant value for the {@link ForeignAccess} instance that could be associated directly
* with the {@link TruffleObject} class.
*
* This factory provides a generic solution for all FastR types (all of which are
* {@link TruffleObject}s), at some cost in performance.
*
* 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
* abstract classes.
*
*/
public final class RForeignAccessFactoryImpl implements RForeignAccessFactory {
private static final class TableEntry {
private final Class<? extends RTruffleObject> clazz; // for sanity check
private final ForeignAccess foreignAccess;
/**
* {@link PolyglotEngine} checks the thread on a {@link ForeignAccess}.
*/
private final Thread thread;
private TableEntry(Class<? extends RTruffleObject> clazz, ForeignAccess foreignAccess) {
this.clazz = clazz;
this.foreignAccess = foreignAccess;
this.thread = Thread.currentThread();
}
}
private final TableEntry[] table = new TableEntry[32];
int tableIndex;
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;
}
}
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.ACCESS;
} else if (RList.class.isAssignableFrom(clazz)) {
foreignAccess = RListMRForeign.ACCESS;
} else if (REnvironment.class.isAssignableFrom(clazz)) {
foreignAccess = REnvironmentMRForeign.ACCESS;
} else if (RPairList.class.isAssignableFrom(clazz)) {
foreignAccess = RPairListMRForeign.ACCESS;
} else if (RFunction.class.isAssignableFrom(clazz)) {
foreignAccess = RFunctionMRForeign.ACCESS;
} else if (DLL.DLLInfo.class.isAssignableFrom(clazz)) {
foreignAccess = DLLInfoMRForeign.ACCESS;
} else if (DLL.DotSymbol.class.isAssignableFrom(clazz)) {
foreignAccess = DLLDotSymbolMRForeign.ACCESS;
} else if (RSymbol.class.isAssignableFrom(clazz)) {
foreignAccess = RSymbolMRForeign.ACCESS;
} else if (RExternalPtr.class.isAssignableFrom(clazz)) {
foreignAccess = RExternalPtrMRForeign.ACCESS;
} else if (RUnboundValue.class.isAssignableFrom(clazz)) {
foreignAccess = RUnboundValueMRForeign.ACCESS;
} else if (NativeRawArray.class.isAssignableFrom(clazz)) {
foreignAccess = NativeRawArrayMRForeign.ACCESS;
} else if (NativeLogicalArray.class.isAssignableFrom(clazz)) {
foreignAccess = NativeLogicalArrayMRForeign.ACCESS;
} else if (NativeCharArray.class.isAssignableFrom(clazz)) {
foreignAccess = NativeCharArrayMRForeign.ACCESS;
} else if (NativeDoubleArray.class.isAssignableFrom(clazz)) {
foreignAccess = NativeDoubleArrayMRForeign.ACCESS;
} else if (NativeIntegerArray.class.isAssignableFrom(clazz)) {
foreignAccess = NativeIntegerArrayMRForeign.ACCESS;
} else if (RInteger.class.isAssignableFrom(clazz)) {
foreignAccess = RIntegerMRForeign.ACCESS;
} else if (RDouble.class.isAssignableFrom(clazz)) {
foreignAccess = RDoubleMRForeign.ACCESS;
} else if (CharSXPWrapper.class.isAssignableFrom(clazz)) {
foreignAccess = CharSXPWrapperMRForeign.ACCESS;
@Override
public ForeignAccess getForeignAccess(RTruffleObject obj) {
CompilerAsserts.neverPartOfCompilation("getForeignAccess");
if (obj instanceof RNull) {
return RNullMRForeign.ACCESS;
} else if (obj instanceof RList) {
return RListMRForeign.ACCESS;
} else if (obj instanceof REnvironment) {
return REnvironmentMRForeign.ACCESS;
} else if (obj instanceof RPairList) {
return RPairListMRForeign.ACCESS;
} else if (obj instanceof RFunction) {
return RFunctionMRForeign.ACCESS;
} else if (obj instanceof DLL.DLLInfo) {
return DLLInfoMRForeign.ACCESS;
} else if (obj instanceof DLL.DotSymbol) {
return DLLDotSymbolMRForeign.ACCESS;
} else if (obj instanceof RSymbol) {
return RSymbolMRForeign.ACCESS;
} else if (obj instanceof RExternalPtr) {
return RExternalPtrMRForeign.ACCESS;
} else if (obj instanceof RUnboundValue) {
return RUnboundValueMRForeign.ACCESS;
} else if (obj instanceof NativeRawArray) {
return NativeRawArrayMRForeign.ACCESS;
} else if (obj instanceof NativeLogicalArray) {
return NativeLogicalArrayMRForeign.ACCESS;
} else if (obj instanceof NativeCharArray) {
return NativeCharArrayMRForeign.ACCESS;
} else if (obj instanceof NativeDoubleArray) {
return NativeDoubleArrayMRForeign.ACCESS;
} else if (obj instanceof NativeIntegerArray) {
return NativeIntegerArrayMRForeign.ACCESS;
} else if (obj instanceof RInteger) {
return RIntegerMRForeign.ACCESS;
} else if (obj instanceof RDouble) {
return RDoubleMRForeign.ACCESS;
} else if (obj instanceof CharSXPWrapper) {
return CharSXPWrapperMRForeign.ACCESS;
} else {
if (RAbstractVector.class.isAssignableFrom(clazz)) {
foreignAccess = ForeignAccess.create(RAbstractVector.class, new RAbstractVectorAccessFactory());
if (obj instanceof RAbstractVector) {
return ForeignAccess.create(RAbstractVector.class, new RAbstractVectorAccessFactory());
} else {
throw RInternalError.unimplemented("foreignAccess: " + name);
throw RInternalError.unimplemented("missing foreign access factory for " + obj.getClass().getSimpleName());
}
}
return foreignAccess;
}
@Override
public ForeignAccess getForeignAccess(RTruffleObject obj) {
CompilerAsserts.neverPartOfCompilation("getForeignAccess");
return get(obj);
}
@Override
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment