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
Branches
No related tags found
No related merge requests found
...@@ -23,12 +23,9 @@ ...@@ -23,12 +23,9 @@
package com.oracle.truffle.r.engine.interop; package com.oracle.truffle.r.engine.interop;
import com.oracle.truffle.api.CompilerAsserts; import com.oracle.truffle.api.CompilerAsserts;
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.TruffleLanguage;
import com.oracle.truffle.api.interop.ForeignAccess; import com.oracle.truffle.api.interop.ForeignAccess;
import com.oracle.truffle.api.interop.MessageResolution; 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.engine.TruffleRLanguage;
import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.RInternalError;
import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.context.RContext;
...@@ -49,106 +46,59 @@ import com.oracle.truffle.r.runtime.ffi.CharSXPWrapper; ...@@ -49,106 +46,59 @@ import com.oracle.truffle.r.runtime.ffi.CharSXPWrapper;
import com.oracle.truffle.r.runtime.ffi.DLL; 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 * 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 * 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 * of {@link RAbstractVector} as these have the same handling but the generator cannot handle
* abstract classes. * abstract classes.
*
*/ */
public final class RForeignAccessFactoryImpl implements RForeignAccessFactory { 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) { @Override
Class<? extends RTruffleObject> objclazz = obj.getClass(); public ForeignAccess getForeignAccess(RTruffleObject obj) {
Thread thread = Thread.currentThread(); CompilerAsserts.neverPartOfCompilation("getForeignAccess");
for (int i = 0; i < tableIndex; i++) { if (obj instanceof RNull) {
TableEntry te = table[i]; return RNullMRForeign.ACCESS;
if (te.clazz == objclazz && te.thread == thread) { } else if (obj instanceof RList) {
return te.foreignAccess; return RListMRForeign.ACCESS;
} } else if (obj instanceof REnvironment) {
} return REnvironmentMRForeign.ACCESS;
return createForeignAccess(objclazz); } else if (obj instanceof RPairList) {
} return RPairListMRForeign.ACCESS;
} else if (obj instanceof RFunction) {
@TruffleBoundary return RFunctionMRForeign.ACCESS;
private static ForeignAccess createForeignAccess(Class<? extends RTruffleObject> clazz) { } else if (obj instanceof DLL.DLLInfo) {
ForeignAccess foreignAccess = null; return DLLInfoMRForeign.ACCESS;
String name = clazz.getSimpleName(); } else if (obj instanceof DLL.DotSymbol) {
if (RNull.class.isAssignableFrom(clazz)) { return DLLDotSymbolMRForeign.ACCESS;
foreignAccess = RNullMRForeign.ACCESS; } else if (obj instanceof RSymbol) {
} else if (RList.class.isAssignableFrom(clazz)) { return RSymbolMRForeign.ACCESS;
foreignAccess = RListMRForeign.ACCESS; } else if (obj instanceof RExternalPtr) {
} else if (REnvironment.class.isAssignableFrom(clazz)) { return RExternalPtrMRForeign.ACCESS;
foreignAccess = REnvironmentMRForeign.ACCESS; } else if (obj instanceof RUnboundValue) {
} else if (RPairList.class.isAssignableFrom(clazz)) { return RUnboundValueMRForeign.ACCESS;
foreignAccess = RPairListMRForeign.ACCESS; } else if (obj instanceof NativeRawArray) {
} else if (RFunction.class.isAssignableFrom(clazz)) { return NativeRawArrayMRForeign.ACCESS;
foreignAccess = RFunctionMRForeign.ACCESS; } else if (obj instanceof NativeLogicalArray) {
} else if (DLL.DLLInfo.class.isAssignableFrom(clazz)) { return NativeLogicalArrayMRForeign.ACCESS;
foreignAccess = DLLInfoMRForeign.ACCESS; } else if (obj instanceof NativeCharArray) {
} else if (DLL.DotSymbol.class.isAssignableFrom(clazz)) { return NativeCharArrayMRForeign.ACCESS;
foreignAccess = DLLDotSymbolMRForeign.ACCESS; } else if (obj instanceof NativeDoubleArray) {
} else if (RSymbol.class.isAssignableFrom(clazz)) { return NativeDoubleArrayMRForeign.ACCESS;
foreignAccess = RSymbolMRForeign.ACCESS; } else if (obj instanceof NativeIntegerArray) {
} else if (RExternalPtr.class.isAssignableFrom(clazz)) { return NativeIntegerArrayMRForeign.ACCESS;
foreignAccess = RExternalPtrMRForeign.ACCESS; } else if (obj instanceof RInteger) {
} else if (RUnboundValue.class.isAssignableFrom(clazz)) { return RIntegerMRForeign.ACCESS;
foreignAccess = RUnboundValueMRForeign.ACCESS; } else if (obj instanceof RDouble) {
} else if (NativeRawArray.class.isAssignableFrom(clazz)) { return RDoubleMRForeign.ACCESS;
foreignAccess = NativeRawArrayMRForeign.ACCESS; } else if (obj instanceof CharSXPWrapper) {
} else if (NativeLogicalArray.class.isAssignableFrom(clazz)) { return CharSXPWrapperMRForeign.ACCESS;
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;
} else { } else {
if (RAbstractVector.class.isAssignableFrom(clazz)) { if (obj instanceof RAbstractVector) {
foreignAccess = ForeignAccess.create(RAbstractVector.class, new RAbstractVectorAccessFactory()); return ForeignAccess.create(RAbstractVector.class, new RAbstractVectorAccessFactory());
} else { } 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 @Override
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment