diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/DLLDotSymbolMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/DLLDotSymbolMR.java new file mode 100644 index 0000000000000000000000000000000000000000..3342f4a737ae56c2d35cc346a46e3d94a7565624 --- /dev/null +++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/DLLDotSymbolMR.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.r.engine.interop; + +import com.oracle.truffle.api.interop.CanResolve; +import com.oracle.truffle.api.interop.MessageResolution; +import com.oracle.truffle.api.interop.TruffleObject; +import com.oracle.truffle.api.nodes.Node; +import com.oracle.truffle.r.engine.TruffleRLanguage; +import com.oracle.truffle.r.runtime.ffi.DLL; + +@MessageResolution(receiverType = DLL.DotSymbol.class, language = TruffleRLanguage.class) +public class DLLDotSymbolMR { + @CanResolve + public abstract static class DotSymbolCheck extends Node { + + protected static boolean test(TruffleObject receiver) { + return receiver instanceof DLL.DotSymbol; + } + } + +} diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/DLLInfoMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/DLLInfoMR.java new file mode 100644 index 0000000000000000000000000000000000000000..92a4118c055bfe7c4c27ff88caf52213eb8e25ba --- /dev/null +++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/DLLInfoMR.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.r.engine.interop; + +import com.oracle.truffle.api.interop.CanResolve; +import com.oracle.truffle.api.interop.MessageResolution; +import com.oracle.truffle.api.interop.TruffleObject; +import com.oracle.truffle.api.nodes.Node; +import com.oracle.truffle.r.engine.TruffleRLanguage; +import com.oracle.truffle.r.runtime.ffi.DLL; + +@MessageResolution(receiverType = DLL.DLLInfo.class, language = TruffleRLanguage.class) +public class DLLInfoMR { + @CanResolve + public abstract static class DLLInfolCheck extends Node { + + protected static boolean test(TruffleObject receiver) { + return receiver instanceof DLL.DLLInfo; + } + } + +} diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RExternalPtrMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RExternalPtrMR.java new file mode 100644 index 0000000000000000000000000000000000000000..3d21bccdf2f6a6d0a2b6dece2a5b38aa99b09598 --- /dev/null +++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RExternalPtrMR.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.r.engine.interop; + +import com.oracle.truffle.api.interop.CanResolve; +import com.oracle.truffle.api.interop.MessageResolution; +import com.oracle.truffle.api.interop.TruffleObject; +import com.oracle.truffle.api.nodes.Node; +import com.oracle.truffle.r.engine.TruffleRLanguage; +import com.oracle.truffle.r.runtime.data.RExternalPtr; + +@MessageResolution(receiverType = RExternalPtr.class, language = TruffleRLanguage.class) +public class RExternalPtrMR { + @CanResolve + public abstract static class RExternalPtrCheck extends Node { + + protected static boolean test(TruffleObject receiver) { + return receiver instanceof RExternalPtr; + } + } + +} 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 03f73455c63146019f8c9bb5a4ffdfead920049b..4e2a81101dde3a94799a5219af80a090d17c33e3 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,88 +22,250 @@ */ package com.oracle.truffle.r.engine.interop; +import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.Assumption; +import com.oracle.truffle.api.CompilerAsserts; +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; +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; 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.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.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; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; import com.oracle.truffle.r.runtime.env.REnvironment; +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 + * 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. + * + * 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 + * abstract classes. + * + */ 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}; + + 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; - private final ForeignAccess foreignAccess; /** - * {@link PolyglotEngine} checks the thread on a {@link 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. */ private final Thread thread; - private TableEntry(Class<? extends RTruffleObject> clazz, ForeignAccess foreignAccess) { - this.clazz = clazz; + private ForeignAccessState() { this.thread = Thread.currentThread(); - this.foreignAccess = foreignAccess; + 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)); + } + } } - } - TableEntry[] table = new TableEntry[32]; - int tableIndex; + private ForeignAccess get(RTruffleObject obj) { + Class<? extends RTruffleObject> clazz = obj.getClass(); + return get(clazz); + } - @Override - public ForeignAccess getForeignAccess(RTruffleObject obj) { - return get(obj); - } + private ForeignAccess get(Class<? extends RTruffleObject> clazz) { + int index = System.identityHashCode(clazz) & tableMask; + assert table[index].clazz == clazz; + return table[index].foreignAccess; + } + + static { + generatePrototypeTable(); + } - 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; + /** + * 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; + } } + tableMask = ts - 1; } - return createForeignAccess(objclazz); - } - @TruffleBoundary - private 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 (RAbstractVector.class.isAssignableFrom(clazz)) { - foreignAccess = ForeignAccess.create(RAbstractVector.class, new RAbstractVectorAccessFactory()); + @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 { - throw RInternalError.unimplemented("foreignAccess: " + name); + if (RAbstractVector.class.isAssignableFrom(clazz)) { + foreignAccess = ForeignAccess.create(RAbstractVector.class, new RAbstractVectorAccessFactory()); + } else { + throw RInternalError.unimplemented("foreignAccess: " + name); + } } + return foreignAccess; } - TableEntry te = new TableEntry(clazz, foreignAccess); - table[tableIndex++] = te; - return te.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; + } + @Override public Class<? extends TruffleLanguage<RContext>> getTruffleLanguage() { return TruffleRLanguage.class; } + } diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RSymbolMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RSymbolMR.java new file mode 100644 index 0000000000000000000000000000000000000000..2eb3cb9661492abbde68aa3821eeb7a614028ec9 --- /dev/null +++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RSymbolMR.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.r.engine.interop; + +import com.oracle.truffle.api.interop.CanResolve; +import com.oracle.truffle.api.interop.MessageResolution; +import com.oracle.truffle.api.interop.TruffleObject; +import com.oracle.truffle.api.nodes.Node; +import com.oracle.truffle.r.engine.TruffleRLanguage; +import com.oracle.truffle.r.runtime.data.RSymbol; + +@MessageResolution(receiverType = RSymbol.class, language = TruffleRLanguage.class) +public class RSymbolMR { + @CanResolve + public abstract static class RSymbolCheck extends Node { + + protected static boolean test(TruffleObject receiver) { + return receiver instanceof RSymbol; + } + } + +} diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RUnboundValueMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RUnboundValueMR.java new file mode 100644 index 0000000000000000000000000000000000000000..ff0c179f53dafceb6e7ea0ca17e89896190b0fd2 --- /dev/null +++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RUnboundValueMR.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.r.engine.interop; + +import com.oracle.truffle.api.interop.CanResolve; +import com.oracle.truffle.api.interop.MessageResolution; +import com.oracle.truffle.api.interop.Resolve; +import com.oracle.truffle.api.interop.TruffleObject; +import com.oracle.truffle.api.nodes.Node; +import com.oracle.truffle.r.engine.TruffleRLanguage; +import com.oracle.truffle.r.runtime.data.RUnboundValue; + +@MessageResolution(receiverType = RUnboundValue.class, language = TruffleRLanguage.class) +public class RUnboundValueMR { + @Resolve(message = "IS_BOXED") + public abstract static class RUnboundValueIsBoxedNode extends Node { + protected Object access(@SuppressWarnings("unused") RUnboundValue receiver) { + return false; + } + } + + @Resolve(message = "HAS_SIZE") + public abstract static class RUnboundValueHasSizeNode extends Node { + protected Object access(@SuppressWarnings("unused") RUnboundValue receiver) { + return false; + } + } + + @Resolve(message = "IS_NULL") + public abstract static class RUnboundValueIsNullNode extends Node { + protected Object access(@SuppressWarnings("unused") RUnboundValue receiver) { + return false; + } + } + + @CanResolve + public abstract static class RUnboundValueCheck extends Node { + + protected static boolean test(TruffleObject receiver) { + return receiver instanceof RUnboundValue; + } + } + +} diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/Slot.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/Slot.java index 201f0d7d149f0946c17019e73cdccd860f6f9cc5..03eb4418b5467abf60e79721eda6931383cef8da 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/Slot.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/Slot.java @@ -25,7 +25,7 @@ import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.Utils; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; -// Transcribed from src/library/methods/slot.c +// Transcribed from src/library/methods/src/slot.c public class Slot { diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/StandardGeneric.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/StandardGeneric.java index 08c9e57b8c1930c4216ba587f5665ef4a229bbc6..2a590e3749181816039b058a24c41352711c8f37 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/StandardGeneric.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/StandardGeneric.java @@ -53,7 +53,8 @@ import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.RStringVector; import com.oracle.truffle.r.runtime.env.REnvironment; -// transcribed from src/main/objects.c +// transcribed from /src/library/methods/src/methods_list_dispatch.c (R_dispatch_generic function) + @RBuiltin(name = "standardGeneric", visibility = CUSTOM, kind = PRIMITIVE, parameterNames = {"f", "fdef"}, behavior = COMPLEX) public abstract class StandardGeneric extends RBuiltinNode { diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/AccessSlotNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/AccessSlotNode.java index 50b84824a122ebfa9b012e38dfe7807e58e57518..e5307e12f2b19f3d435dc30d25e7b497556d3231 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/AccessSlotNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/AccessSlotNode.java @@ -21,7 +21,6 @@ import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.profiles.BranchProfile; import com.oracle.truffle.r.nodes.RASTUtils; import com.oracle.truffle.r.nodes.attributes.GetAttributeNode; -import com.oracle.truffle.r.nodes.attributes.GetFixedAttributeNode; import com.oracle.truffle.r.nodes.attributes.InitAttributesNode; import com.oracle.truffle.r.nodes.function.ClassHierarchyNode; import com.oracle.truffle.r.nodes.function.ClassHierarchyNodeGen; @@ -42,6 +41,8 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractVector; import com.oracle.truffle.r.runtime.env.REnvironment; import com.oracle.truffle.r.runtime.nodes.RNode; +// Transcribed from src/main/attrib.c file (R_do_slot function) + /** * Perform a slot access. This node represents the {@code @} operator in R. */ diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/UpdateSlotNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/UpdateSlotNode.java index c0b37f806041ee648bfecb8dccf76df73f04f3ec..22972c305937af31631bec8b43d876dadfb1b80f 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/UpdateSlotNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/UpdateSlotNode.java @@ -18,7 +18,6 @@ import com.oracle.truffle.api.dsl.NodeChild; import com.oracle.truffle.api.dsl.NodeChildren; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.r.nodes.RASTUtils; -import com.oracle.truffle.r.nodes.attributes.SetFixedAttributeNode; import com.oracle.truffle.r.nodes.attributes.InitAttributesNode; import com.oracle.truffle.r.nodes.attributes.SetAttributeNode; import com.oracle.truffle.r.runtime.RCaller; @@ -31,6 +30,8 @@ import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.env.REnvironment; import com.oracle.truffle.r.runtime.nodes.RNode; +// Transcribed from src/main/attrib.c file (R_do_slot_assign function) + @NodeChildren({@NodeChild(value = "object", type = RNode.class), @NodeChild(value = "name", type = RNode.class), @NodeChild(value = "value", type = RNode.class)}) public abstract class UpdateSlotNode extends RNode { diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/CollectGenericArgumentsNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/CollectGenericArgumentsNode.java index 9c9ffffb388f84c5819887d65e8721dc07ed7048..3acb958ef9701fc0229a07e17fafe3d69a94c9f3 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/CollectGenericArgumentsNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/CollectGenericArgumentsNode.java @@ -45,6 +45,8 @@ import com.oracle.truffle.r.runtime.data.RStringVector; import com.oracle.truffle.r.runtime.data.RSymbol; import com.oracle.truffle.r.runtime.nodes.RBaseNode; +// transcribed from /src/library/methods/src/methods_list_dispatch.c (R_dispatch_generic function) + /* * Used to collect arguments of the generic function for S4 method dispatch. Modeled after {@link CollectArgumentsNode}. */ diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/DispatchGeneric.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/DispatchGeneric.java index 733648fbaea8f503607b1b735e07275a000315ab..ea03075c9a6fe23cf2c4ba80440876339b94c4c8 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/DispatchGeneric.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/DispatchGeneric.java @@ -30,6 +30,7 @@ import com.oracle.truffle.r.runtime.data.RStringVector; import com.oracle.truffle.r.runtime.env.REnvironment; import com.oracle.truffle.r.runtime.nodes.RBaseNode; +// transcribed from /src/library/methods/src/methods_list_dispatch.c (R_dispatch_generic function) public abstract class DispatchGeneric extends RBaseNode { public abstract Object executeObject(VirtualFrame frame, REnvironment mtable, RStringVector classes, RFunction fdef, String fname); diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/GetPrimName.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/GetPrimName.java index 1e450fd0305ce0255954e667cf2816950dfce822..84229b57ef0d5313013909ec59ce9d622496bc0c 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/GetPrimName.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/GetPrimName.java @@ -17,7 +17,7 @@ import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.data.RFunction; -// transcribed from src/library/methods/utils.c +// transcribed from src/library/methods/src/utils.c public abstract class GetPrimName extends RExternalBuiltinNode.Arg1 { @Specialization(guards = "f.isBuiltin()") diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/LoadMethod.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/LoadMethod.java index 71ae3eef2b2593978101505c6d1e786b381b4e53..4be981a574ff0db8c4c8bfb736f99a60452b1748 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/LoadMethod.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/LoadMethod.java @@ -39,6 +39,7 @@ import com.oracle.truffle.r.runtime.env.REnvironment; import com.oracle.truffle.r.runtime.nodes.RBaseNode; import com.oracle.truffle.r.runtime.nodes.RSyntaxNode; +// transcribed from /src/library/methods/src/methods_list_dispatch.c (R_loadMethod function) abstract class LoadMethod extends RBaseNode { private static final ArgumentsSignature SIGNATURE = ArgumentsSignature.get("method", "fname", "envir"); diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RForeignAccessFactory.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RForeignAccessFactory.java index d05f96d5ec35693c48cbf238b01fdffe6f34d930..d5732acff89aa0c8213f3b1c59fe3220f4b677f3 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RForeignAccessFactory.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RForeignAccessFactory.java @@ -28,7 +28,13 @@ import com.oracle.truffle.r.runtime.data.RTruffleObject; public interface RForeignAccessFactory { - ForeignAccess getForeignAccess(RTruffleObject value); + /** + * Return the appropriate {@link ForeignAccess} instance for {@code obj}. + */ + ForeignAccess getForeignAccess(RTruffleObject obj); + /** + * Return the {@link TruffleLanguage} instance for R. (Project circularity workaround). + */ Class<? extends TruffleLanguage<RContext>> getTruffleLanguage(); }