From bb67f8c14787116c0a412892947d2a14cb384123 Mon Sep 17 00:00:00 2001 From: Florian Angerer <florian.angerer@oracle.com> Date: Mon, 25 Sep 2017 18:05:44 +0200 Subject: [PATCH] Implemented functions 'R_has_slot' and 'CLOENV'. --- .../ffi/impl/common/JavaUpCallsRFFIImpl.java | 22 +- .../r/ffi/impl/nodes/DuplicateNodes.java | 46 +++ .../truffle/r/ffi/impl/nodes/MiscNodes.java | 48 +++ .../r/ffi/impl/upcalls/StdUpCallsRFFI.java | 8 + .../r/library/methods/SubstituteDirect.java | 7 +- .../fficall/src/common/rffi_upcalls.h | 4 +- .../fficall/src/common/rffi_upcallsindex.h | 320 +++++++++--------- .../Rinternals_truffle_common.h | 15 +- .../r/nodes/builtin/base/EnvFunctions.java | 16 +- .../r/nodes/builtin/base/List2Env.java | 2 +- .../r/nodes/builtin/base/RecordGraphics.java | 2 +- .../r/nodes/builtin/base/Substitute.java | 6 +- .../r/nodes/access/AccessSlotNode.java | 79 +---- .../r/nodes/access/BaseAccessSlotNode.java | 95 ++++++ .../truffle/r/nodes/access/HasSlotNode.java | 76 +++++ .../r/nodes/builtin/EnvironmentNodes.java | 77 +++++ .../r/nodes/builtin/RList2EnvNode.java | 67 ---- 17 files changed, 547 insertions(+), 343 deletions(-) create mode 100644 com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/DuplicateNodes.java create mode 100644 com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/BaseAccessSlotNode.java create mode 100644 com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/HasSlotNode.java create mode 100644 com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/EnvironmentNodes.java delete mode 100644 com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RList2EnvNode.java diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/JavaUpCallsRFFIImpl.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/JavaUpCallsRFFIImpl.java index a34050460a..23e1c21944 100644 --- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/JavaUpCallsRFFIImpl.java +++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/JavaUpCallsRFFIImpl.java @@ -85,7 +85,6 @@ import com.oracle.truffle.r.runtime.data.RObject; import com.oracle.truffle.r.runtime.data.RPairList; import com.oracle.truffle.r.runtime.data.RPromise; import com.oracle.truffle.r.runtime.data.RPromise.EagerPromise; -import com.oracle.truffle.r.runtime.data.RSequence; import com.oracle.truffle.r.runtime.data.RShareable; import com.oracle.truffle.r.runtime.data.RStringVector; import com.oracle.truffle.r.runtime.data.RSymbol; @@ -638,16 +637,7 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI { @Override @TruffleBoundary public Object Rf_duplicate(Object x, int deep) { - guarantee(x != null, "unexpected type: null instead of " + x.getClass().getSimpleName()); - guarantee(x instanceof RShareable || x instanceof RSequence || x instanceof RExternalPtr, - "unexpected type: " + x + " is " + x.getClass().getSimpleName() + " instead of RShareable or RExternalPtr"); - if (x instanceof RShareable) { - return deep == 1 ? ((RShareable) x).deepCopy() : ((RShareable) x).copy(); - } else if (x instanceof RSequence) { - return ((RSequence) x).materialize(); - } else { - return ((RExternalPtr) x).copy(); - } + throw implementedAsNode(); } @Override @@ -1770,4 +1760,14 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI { throw implementedAsNode(); } + @Override + public int R_has_slot(Object container, Object name) { + throw implementedAsNode(); + } + + @Override + public Object CLOENV(Object x) { + throw implementedAsNode(); + } + } diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/DuplicateNodes.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/DuplicateNodes.java new file mode 100644 index 0000000000..928e657a66 --- /dev/null +++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/DuplicateNodes.java @@ -0,0 +1,46 @@ +package com.oracle.truffle.r.ffi.impl.nodes; + +import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.r.ffi.impl.nodes.DuplicateNodesFactory.DuplicateNodeGen; +import com.oracle.truffle.r.runtime.data.RExternalPtr; +import com.oracle.truffle.r.runtime.data.RNull; +import com.oracle.truffle.r.runtime.data.RSequence; +import com.oracle.truffle.r.runtime.data.RShareable; +import com.oracle.truffle.r.runtime.data.RSymbol; +import com.oracle.truffle.r.runtime.env.REnvironment; + +public final class DuplicateNodes { + + public abstract static class DuplicateNode extends FFIUpCallNode.Arg2 { + + @Specialization + public Object duplicateShareable(RShareable x, int deep) { + assert !isReusableForDuplicate(x); + return deep == 1 ? x.deepCopy() : x.copy(); + } + + @Specialization + public Object duplicateSequence(RSequence x, @SuppressWarnings("unused") int deep) { + return x.materialize(); + } + + @Specialization + public Object duplicateExternalPtr(RExternalPtr x, @SuppressWarnings("unused") int deep) { + return x.copy(); + } + + @Specialization(guards = "isReusableForDuplicate(val)") + public Object returnReusable(Object val, @SuppressWarnings("unused") int deep) { + return val; + } + + protected static boolean isReusableForDuplicate(Object o) { + return o == RNull.instance || o instanceof REnvironment || o instanceof RSymbol; + } + + public static DuplicateNode create() { + return DuplicateNodeGen.create(); + } + } + +} diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/MiscNodes.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/MiscNodes.java index 515524a94b..9fed0338aa 100644 --- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/MiscNodes.java +++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/MiscNodes.java @@ -23,24 +23,30 @@ package com.oracle.truffle.r.ffi.impl.nodes; import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Fallback; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.dsl.TypeSystemReference; +import com.oracle.truffle.r.ffi.impl.nodes.MiscNodesFactory.GetFunctionEnvironmentNodeGen; import com.oracle.truffle.r.ffi.impl.nodes.MiscNodesFactory.LENGTHNodeGen; import com.oracle.truffle.r.ffi.impl.nodes.MiscNodesFactory.RDoNewObjectNodeGen; import com.oracle.truffle.r.ffi.impl.nodes.MiscNodesFactory.RDoSlotAssignNodeGen; import com.oracle.truffle.r.ffi.impl.nodes.MiscNodesFactory.RDoSlotNodeGen; +import com.oracle.truffle.r.ffi.impl.nodes.MiscNodesFactory.RHasSlotNodeGen; import com.oracle.truffle.r.nodes.access.AccessSlotNode; import com.oracle.truffle.r.nodes.access.AccessSlotNodeGen; +import com.oracle.truffle.r.nodes.access.HasSlotNode; import com.oracle.truffle.r.nodes.access.UpdateSlotNode; import com.oracle.truffle.r.nodes.access.UpdateSlotNodeGen; import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetNamesAttributeNode; import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctionsFactory.SetNamesAttributeNodeGen; +import com.oracle.truffle.r.nodes.builtin.EnvironmentNodes.GetFunctionEnvironmentNode; import com.oracle.truffle.r.nodes.objects.NewObject; import com.oracle.truffle.r.nodes.objects.NewObjectNodeGen; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.data.CharSXPWrapper; import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; +import com.oracle.truffle.r.runtime.data.RFunction; import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.RSymbol; import com.oracle.truffle.r.runtime.data.RTypes; @@ -184,6 +190,31 @@ public final class MiscNodes { } } + @TypeSystemReference(RTypes.class) + public abstract static class RHasSlotNode extends FFIUpCallNode.Arg2 { + + @Child private HasSlotNode hasSlotNode; + + RHasSlotNode() { + hasSlotNode = HasSlotNode.create(false); + } + + @Specialization + Object doSlot(Object o, RSymbol nameSym) { + return hasSlotNode.executeAccess(o, nameSym.getName()); + } + + @Fallback + @SuppressWarnings("unused") + Object doSlot(Object o, Object name) { + return false; + } + + public static RHasSlotNode create() { + return RHasSlotNodeGen.create(); + } + } + @TypeSystemReference(RTypes.class) public abstract static class NamesGetsNode extends FFIUpCallNode.Arg2 { @@ -204,4 +235,21 @@ public final class MiscNodes { } } + @TypeSystemReference(RTypes.class) + public abstract static class GetFunctionEnvironment extends FFIUpCallNode.Arg1 { + + /** + * Returns the environment that {@code func} was created in. + */ + @Specialization + protected Object environment(RFunction fun, + @Cached("create()") GetFunctionEnvironmentNode getEnvNode) { + return getEnvNode.getEnvironment(fun); + } + + public static GetFunctionEnvironment create() { + return GetFunctionEnvironmentNodeGen.create(); + } + } + } diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/StdUpCallsRFFI.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/StdUpCallsRFFI.java index ff460ed405..84f515f076 100644 --- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/StdUpCallsRFFI.java +++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/StdUpCallsRFFI.java @@ -31,6 +31,7 @@ import com.oracle.truffle.r.ffi.impl.nodes.AttributesAccessNodes.CopyMostAttrib; import com.oracle.truffle.r.ffi.impl.nodes.AttributesAccessNodes.TAG; import com.oracle.truffle.r.ffi.impl.nodes.CoerceNodes.CoerceVectorNode; import com.oracle.truffle.r.ffi.impl.nodes.CoerceNodes.VectorToPairListNode; +import com.oracle.truffle.r.ffi.impl.nodes.DuplicateNodes; import com.oracle.truffle.r.ffi.impl.nodes.ListAccessNodes.CADDRNode; import com.oracle.truffle.r.ffi.impl.nodes.ListAccessNodes.CADRNode; import com.oracle.truffle.r.ffi.impl.nodes.ListAccessNodes.CARNode; @@ -184,6 +185,7 @@ public interface StdUpCallsRFFI { int OBJECT(Object x); + @RFFIUpCallNode(DuplicateNodes.DuplicateNode.class) Object Rf_duplicate(Object x, int deep); long Rf_any_duplicated(Object x, int fromLast); @@ -366,4 +368,10 @@ public interface StdUpCallsRFFI { @RFFIUpCallNode(MatchNodes.NonNullStringMatchNode.class) Object Rf_NonNullStringMatch(Object s, Object t); + + @RFFIUpCallNode(MiscNodes.RHasSlotNode.class) + int R_has_slot(Object container, Object name); + + @RFFIUpCallNode(MiscNodes.GetFunctionEnvironment.class) + Object CLOENV(Object x); } diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/SubstituteDirect.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/SubstituteDirect.java index bbdcd3fd61..768892a9ea 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/SubstituteDirect.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/SubstituteDirect.java @@ -22,16 +22,17 @@ */ package com.oracle.truffle.r.library.methods; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.instanceOf; +import static com.oracle.truffle.r.runtime.RError.Message.INVALID_LIST_FOR_SUBSTITUTION; + import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Fallback; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.r.nodes.RASTUtils; -import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.instanceOf; +import com.oracle.truffle.r.nodes.builtin.EnvironmentNodes.RList2EnvNode; import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode; -import com.oracle.truffle.r.nodes.builtin.RList2EnvNode; import com.oracle.truffle.r.runtime.RError; -import static com.oracle.truffle.r.runtime.RError.Message.INVALID_LIST_FOR_SUBSTITUTION; import com.oracle.truffle.r.runtime.RSubstitute; import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RLanguage; diff --git a/com.oracle.truffle.r.native/fficall/src/common/rffi_upcalls.h b/com.oracle.truffle.r.native/fficall/src/common/rffi_upcalls.h index e48fc20e3c..948ff349e5 100644 --- a/com.oracle.truffle.r.native/fficall/src/common/rffi_upcalls.h +++ b/com.oracle.truffle.r.native/fficall/src/common/rffi_upcalls.h @@ -277,12 +277,10 @@ typedef double (*call_Rf_punif)(double a, double b, double c, int d, int e); typedef double (*call_Rf_runif)(double x, double y); typedef SEXP (*call_Rf_match)(SEXP itable, SEXP ix, int nmatch); typedef Rboolean (*call_Rf_NonNullStringMatch)(SEXP s, SEXP t); - typedef SEXP (*call_getvar)(); - typedef SEXP (*call_R_ParseVector)(SEXP text, int n, SEXP srcFile); - typedef SEXPTYPE (*call_Rf_str2type)(const char *s); +typedef SEXP (*call_CLOENV)(SEXP closure); // connections diff --git a/com.oracle.truffle.r.native/fficall/src/common/rffi_upcallsindex.h b/com.oracle.truffle.r.native/fficall/src/common/rffi_upcallsindex.h index a86b1d5693..681477a7f7 100644 --- a/com.oracle.truffle.r.native/fficall/src/common/rffi_upcallsindex.h +++ b/com.oracle.truffle.r.native/fficall/src/common/rffi_upcallsindex.h @@ -8,165 +8,167 @@ #define CAR_x 3 #define CDDR_x 4 #define CDR_x 5 -#define COMPLEX_x 6 -#define DUPLICATE_ATTRIB_x 7 -#define ENCLOS_x 8 -#define FASTR_getConnectionChar_x 9 -#define GetRNGstate_x 10 -#define INTEGER_x 11 -#define IS_S4_OBJECT_x 12 -#define LENGTH_x 13 -#define LOGICAL_x 14 -#define NAMED_x 15 -#define OBJECT_x 16 -#define PRCODE_x 17 -#define PRENV_x 18 -#define PRINTNAME_x 19 -#define PRSEEN_x 20 -#define PRVALUE_x 21 -#define PutRNGstate_x 22 -#define RAW_x 23 -#define RDEBUG_x 24 -#define REAL_x 25 -#define RSTEP_x 26 -#define R_BaseEnv_x 27 -#define R_BaseNamespace_x 28 -#define R_BindingIsLocked_x 29 -#define R_CHAR_x 30 -#define R_CleanUp_x 31 -#define R_ExternalPtrAddr_x 32 -#define R_ExternalPtrProtected_x 33 -#define R_ExternalPtrTag_x 34 -#define R_FindNamespace_x 35 -#define R_GetConnection_x 36 -#define R_GlobalContext_x 37 -#define R_GlobalEnv_x 38 -#define R_Home_x 39 -#define R_HomeDir_x 40 -#define R_Interactive_x 41 -#define R_MakeExternalPtr_x 42 -#define R_MethodsNamespace_x 43 -#define R_NamespaceRegistry_x 44 -#define R_NewHashedEnv_x 45 -#define R_ParseVector_x 46 -#define R_PreserveObject_x 47 -#define R_PromiseExpr_x 48 -#define R_ProtectWithIndex_x 49 -#define R_ReadConnection_x 50 -#define R_ReleaseObject_x 51 -#define R_Reprotect_x 52 -#define R_SetExternalPtrAddr_x 53 -#define R_SetExternalPtrProtected_x 54 -#define R_SetExternalPtrTag_x 55 -#define R_TempDir_x 56 -#define R_ToplevelExec_x 57 -#define R_WriteConnection_x 58 -#define R_alloc_x 59 -#define R_compute_identical_x 60 -#define R_do_MAKE_CLASS_x 61 -#define R_do_new_object_x 62 -#define R_do_slot_x 63 -#define R_do_slot_assign_x 64 -#define R_getClassDef_x 65 -#define R_getContextCall_x 66 -#define R_getContextEnv_x 67 -#define R_getContextFun_x 68 -#define R_getContextSrcRef_x 69 -#define R_getGlobalFunctionContext_x 70 -#define R_getParentFunctionContext_x 71 -#define R_insideBrowser_x 72 -#define R_isEqual_x 73 -#define R_isGlobal_x 74 -#define R_lsInternal3_x 75 -#define R_new_custom_connection_x 76 -#define R_tryEval_x 77 -#define Rf_GetOption1_x 78 -#define Rf_NonNullStringMatch_x 79 -#define Rf_PairToVectorList_x 80 -#define Rf_ScalarDouble_x 81 -#define Rf_ScalarInteger_x 82 -#define Rf_ScalarLogical_x 83 -#define Rf_ScalarString_x 84 -#define Rf_VectorToPairList_x 85 -#define Rf_allocArray_x 86 -#define Rf_allocMatrix_x 87 -#define Rf_allocVector_x 88 -#define Rf_any_duplicated_x 89 -#define Rf_asChar_x 90 -#define Rf_asCharacterFactor_x 91 -#define Rf_asInteger_x 92 -#define Rf_asLogical_x 93 -#define Rf_asReal_x 94 -#define Rf_classgets_x 95 -#define Rf_coerceVector_x 96 -#define Rf_cons_x 97 -#define Rf_copyListMatrix_x 98 -#define Rf_copyMatrix_x 99 -#define Rf_copyMostAttrib_x 100 -#define Rf_defineVar_x 101 -#define Rf_dunif_x 102 -#define Rf_duplicate_x 103 -#define Rf_error_x 104 -#define Rf_errorcall_x 105 -#define Rf_eval_x 106 -#define Rf_findFun_x 107 -#define Rf_findVar_x 108 -#define Rf_findVarInFrame_x 109 -#define Rf_findVarInFrame3_x 110 -#define Rf_getAttrib_x 111 -#define Rf_gsetVar_x 112 -#define Rf_inherits_x 113 -#define Rf_install_x 114 -#define Rf_installChar_x 115 -#define Rf_isNull_x 116 -#define Rf_isString_x 117 -#define Rf_lengthgets_x 118 -#define Rf_match_x 119 -#define Rf_mkCharLenCE_x 120 -#define Rf_namesgets_x 121 -#define Rf_ncols_x 122 -#define Rf_nrows_x 123 -#define Rf_protect_x 124 -#define Rf_punif_x 125 -#define Rf_qunif_x 126 -#define Rf_runif_x 127 -#define Rf_setAttrib_x 128 -#define Rf_str2type_x 129 -#define Rf_unprotect_x 130 -#define Rf_unprotect_ptr_x 131 -#define Rf_warning_x 132 -#define Rf_warningcall_x 133 -#define Rprintf_x 134 -#define SETCADR_x 135 -#define SETCAR_x 136 -#define SETCDR_x 137 -#define SET_NAMED_FASTR_x 138 -#define SET_RDEBUG_x 139 -#define SET_RSTEP_x 140 -#define SET_S4_OBJECT_x 141 -#define SET_STRING_ELT_x 142 -#define SET_SYMVALUE_x 143 -#define SET_TAG_x 144 -#define SET_TYPEOF_FASTR_x 145 -#define SET_VECTOR_ELT_x 146 -#define STRING_ELT_x 147 -#define SYMVALUE_x 148 -#define TAG_x 149 -#define TYPEOF_x 150 -#define UNSET_S4_OBJECT_x 151 -#define VECTOR_ELT_x 152 -#define forceSymbols_x 153 -#define getCCallable_x 154 -#define getConnectionClassString_x 155 -#define getOpenModeString_x 156 -#define getSummaryDescription_x 157 -#define isSeekable_x 158 -#define registerCCallable_x 159 -#define registerRoutines_x 160 -#define setDotSymbolValues_x 161 -#define unif_rand_x 162 -#define useDynamicSymbols_x 163 +#define CLOENV_x 6 +#define COMPLEX_x 7 +#define DUPLICATE_ATTRIB_x 8 +#define ENCLOS_x 9 +#define FASTR_getConnectionChar_x 10 +#define GetRNGstate_x 11 +#define INTEGER_x 12 +#define IS_S4_OBJECT_x 13 +#define LENGTH_x 14 +#define LOGICAL_x 15 +#define NAMED_x 16 +#define OBJECT_x 17 +#define PRCODE_x 18 +#define PRENV_x 19 +#define PRINTNAME_x 20 +#define PRSEEN_x 21 +#define PRVALUE_x 22 +#define PutRNGstate_x 23 +#define RAW_x 24 +#define RDEBUG_x 25 +#define REAL_x 26 +#define RSTEP_x 27 +#define R_BaseEnv_x 28 +#define R_BaseNamespace_x 29 +#define R_BindingIsLocked_x 30 +#define R_CHAR_x 31 +#define R_CleanUp_x 32 +#define R_ExternalPtrAddr_x 33 +#define R_ExternalPtrProtected_x 34 +#define R_ExternalPtrTag_x 35 +#define R_FindNamespace_x 36 +#define R_GetConnection_x 37 +#define R_GlobalContext_x 38 +#define R_GlobalEnv_x 39 +#define R_Home_x 40 +#define R_HomeDir_x 41 +#define R_Interactive_x 42 +#define R_MakeExternalPtr_x 43 +#define R_MethodsNamespace_x 44 +#define R_NamespaceRegistry_x 45 +#define R_NewHashedEnv_x 46 +#define R_ParseVector_x 47 +#define R_PreserveObject_x 48 +#define R_PromiseExpr_x 49 +#define R_ProtectWithIndex_x 50 +#define R_ReadConnection_x 51 +#define R_ReleaseObject_x 52 +#define R_Reprotect_x 53 +#define R_SetExternalPtrAddr_x 54 +#define R_SetExternalPtrProtected_x 55 +#define R_SetExternalPtrTag_x 56 +#define R_TempDir_x 57 +#define R_ToplevelExec_x 58 +#define R_WriteConnection_x 59 +#define R_alloc_x 60 +#define R_compute_identical_x 61 +#define R_do_MAKE_CLASS_x 62 +#define R_do_new_object_x 63 +#define R_do_slot_x 64 +#define R_do_slot_assign_x 65 +#define R_getClassDef_x 66 +#define R_getContextCall_x 67 +#define R_getContextEnv_x 68 +#define R_getContextFun_x 69 +#define R_getContextSrcRef_x 70 +#define R_getGlobalFunctionContext_x 71 +#define R_getParentFunctionContext_x 72 +#define R_has_slot_x 73 +#define R_insideBrowser_x 74 +#define R_isEqual_x 75 +#define R_isGlobal_x 76 +#define R_lsInternal3_x 77 +#define R_new_custom_connection_x 78 +#define R_tryEval_x 79 +#define Rf_GetOption1_x 80 +#define Rf_NonNullStringMatch_x 81 +#define Rf_PairToVectorList_x 82 +#define Rf_ScalarDouble_x 83 +#define Rf_ScalarInteger_x 84 +#define Rf_ScalarLogical_x 85 +#define Rf_ScalarString_x 86 +#define Rf_VectorToPairList_x 87 +#define Rf_allocArray_x 88 +#define Rf_allocMatrix_x 89 +#define Rf_allocVector_x 90 +#define Rf_any_duplicated_x 91 +#define Rf_asChar_x 92 +#define Rf_asCharacterFactor_x 93 +#define Rf_asInteger_x 94 +#define Rf_asLogical_x 95 +#define Rf_asReal_x 96 +#define Rf_classgets_x 97 +#define Rf_coerceVector_x 98 +#define Rf_cons_x 99 +#define Rf_copyListMatrix_x 100 +#define Rf_copyMatrix_x 101 +#define Rf_copyMostAttrib_x 102 +#define Rf_defineVar_x 103 +#define Rf_dunif_x 104 +#define Rf_duplicate_x 105 +#define Rf_error_x 106 +#define Rf_errorcall_x 107 +#define Rf_eval_x 108 +#define Rf_findFun_x 109 +#define Rf_findVar_x 110 +#define Rf_findVarInFrame_x 111 +#define Rf_findVarInFrame3_x 112 +#define Rf_getAttrib_x 113 +#define Rf_gsetVar_x 114 +#define Rf_inherits_x 115 +#define Rf_install_x 116 +#define Rf_installChar_x 117 +#define Rf_isNull_x 118 +#define Rf_isString_x 119 +#define Rf_lengthgets_x 120 +#define Rf_match_x 121 +#define Rf_mkCharLenCE_x 122 +#define Rf_namesgets_x 123 +#define Rf_ncols_x 124 +#define Rf_nrows_x 125 +#define Rf_protect_x 126 +#define Rf_punif_x 127 +#define Rf_qunif_x 128 +#define Rf_runif_x 129 +#define Rf_setAttrib_x 130 +#define Rf_str2type_x 131 +#define Rf_unprotect_x 132 +#define Rf_unprotect_ptr_x 133 +#define Rf_warning_x 134 +#define Rf_warningcall_x 135 +#define Rprintf_x 136 +#define SETCADR_x 137 +#define SETCAR_x 138 +#define SETCDR_x 139 +#define SET_NAMED_FASTR_x 140 +#define SET_RDEBUG_x 141 +#define SET_RSTEP_x 142 +#define SET_S4_OBJECT_x 143 +#define SET_STRING_ELT_x 144 +#define SET_SYMVALUE_x 145 +#define SET_TAG_x 146 +#define SET_TYPEOF_FASTR_x 147 +#define SET_VECTOR_ELT_x 148 +#define STRING_ELT_x 149 +#define SYMVALUE_x 150 +#define TAG_x 151 +#define TYPEOF_x 152 +#define UNSET_S4_OBJECT_x 153 +#define VECTOR_ELT_x 154 +#define forceSymbols_x 155 +#define getCCallable_x 156 +#define getConnectionClassString_x 157 +#define getOpenModeString_x 158 +#define getSummaryDescription_x 159 +#define isSeekable_x 160 +#define registerCCallable_x 161 +#define registerRoutines_x 162 +#define setDotSymbolValues_x 163 +#define unif_rand_x 164 +#define useDynamicSymbols_x 165 -#define UPCALLS_TABLE_SIZE 164 +#define UPCALLS_TABLE_SIZE 166 #endif // RFFI_UPCALLSINDEX_H diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_common/Rinternals_truffle_common.h b/com.oracle.truffle.r.native/fficall/src/truffle_common/Rinternals_truffle_common.h index 809858dbd9..cb21b7d402 100644 --- a/com.oracle.truffle.r.native/fficall/src/truffle_common/Rinternals_truffle_common.h +++ b/com.oracle.truffle.r.native/fficall/src/truffle_common/Rinternals_truffle_common.h @@ -406,14 +406,14 @@ SEXP Rf_setAttrib(SEXP vec, SEXP name, SEXP val) { } SEXP Rf_duplicate(SEXP x) { - TRACE0(); + TRACE(TARGp, x); SEXP result = ((call_Rf_duplicate) callbacks[Rf_duplicate_x])(x, 1); checkExitCall(); return result; } SEXP Rf_shallow_duplicate(SEXP x) { - TRACE0(); + TRACE(TARGp, x); SEXP result = ((call_Rf_duplicate) callbacks[Rf_duplicate_x])(x, 0); checkExitCall(); return result; @@ -770,8 +770,8 @@ SEXP BODY(SEXP x) { } SEXP CLOENV(SEXP x) { - TRACE0(); - return unimplemented("CLOENV"); + TRACE(TARGp, x); + return ((call_CLOENV) callbacks[CLOENV_x])(x); } int RDEBUG(SEXP x) { @@ -1496,9 +1496,10 @@ SEXP R_do_slot_assign(SEXP obj, SEXP name, SEXP value) { } int R_has_slot(SEXP obj, SEXP name) { - TRACE0(); - unimplemented("R_has_slot"); - return 0; + TRACE(TARGpp, obj, name); + SEXP result = ((call_R_has_slot) callbacks[R_has_slot_x])(obj, name); + checkExitCall(); + return result; } SEXP R_do_MAKE_CLASS(const char *what) { diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EnvFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EnvFunctions.java index 9c105a0af6..f79c4b8ee4 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EnvFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EnvFunctions.java @@ -53,8 +53,9 @@ import com.oracle.truffle.r.nodes.RRootNode; import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode; import com.oracle.truffle.r.nodes.attributes.GetFixedAttributeNode; import com.oracle.truffle.r.nodes.attributes.SetFixedAttributeNode; +import com.oracle.truffle.r.nodes.builtin.EnvironmentNodes.GetFunctionEnvironmentNode; +import com.oracle.truffle.r.nodes.builtin.EnvironmentNodes.RList2EnvNode; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; -import com.oracle.truffle.r.nodes.builtin.RList2EnvNode; import com.oracle.truffle.r.nodes.builtin.base.EnvFunctionsFactory.CopyNodeGen; import com.oracle.truffle.r.nodes.function.ClassHierarchyNode; import com.oracle.truffle.r.nodes.function.GetCallerFrameNode; @@ -361,17 +362,8 @@ public class EnvFunctions { */ @Specialization protected Object environment(RFunction fun, - @Cached("createBinaryProfile()") ConditionProfile noEnvProfile, - @Cached("createBinaryProfile()") ConditionProfile createProfile) { - Frame enclosing = fun.getEnclosingFrame(); - if (noEnvProfile.profile(enclosing == null)) { - return RNull.instance; - } - REnvironment env = RArguments.getEnvironment(enclosing); - if (createProfile.profile(env == null)) { - return REnvironment.createEnclosingEnvironments(enclosing.materialize()); - } - return env; + @Cached("create()") GetFunctionEnvironmentNode getEnv) { + return getEnv.getEnvironment(fun); } @Specialization diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/List2Env.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/List2Env.java index 60a62338d6..0217616485 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/List2Env.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/List2Env.java @@ -27,8 +27,8 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.r.nodes.builtin.EnvironmentNodes.RList2EnvNode; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; -import com.oracle.truffle.r.nodes.builtin.RList2EnvNode; import com.oracle.truffle.r.runtime.RError.Message; import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.data.model.RAbstractListVector; diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RecordGraphics.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RecordGraphics.java index 90b72ab45c..609b4ef0f0 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RecordGraphics.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RecordGraphics.java @@ -28,8 +28,8 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.r.nodes.builtin.EnvironmentNodes.RList2EnvNode; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; -import com.oracle.truffle.r.nodes.builtin.RList2EnvNode; import com.oracle.truffle.r.nodes.function.visibility.SetVisibilityNode; import com.oracle.truffle.r.runtime.RCaller; import com.oracle.truffle.r.runtime.builtins.RBuiltin; diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Substitute.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Substitute.java index a7744efb76..3c8732d922 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Substitute.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Substitute.java @@ -22,6 +22,8 @@ */ package com.oracle.truffle.r.nodes.builtin.base; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.instanceOf; +import static com.oracle.truffle.r.runtime.RError.Message.INVALID_ENVIRONMENT_SPECIFIED; import static com.oracle.truffle.r.runtime.builtins.RBehavior.COMPLEX; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; @@ -31,11 +33,9 @@ import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.r.library.methods.SubstituteDirect; import com.oracle.truffle.r.nodes.RASTUtils; -import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.instanceOf; +import com.oracle.truffle.r.nodes.builtin.EnvironmentNodes.RList2EnvNode; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; -import com.oracle.truffle.r.nodes.builtin.RList2EnvNode; import com.oracle.truffle.r.nodes.control.IfNode; -import static com.oracle.truffle.r.runtime.RError.Message.INVALID_ENVIRONMENT_SPECIFIED; import com.oracle.truffle.r.runtime.RSubstitute; import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.data.RLanguage; 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 c0f82b72ba..182e05aa0f 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 @@ -12,92 +12,35 @@ */ package com.oracle.truffle.r.nodes.access; -import com.oracle.truffle.api.CompilerDirectives; -import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Cached; 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.InitAttributesNode; import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetClassAttributeNode; -import com.oracle.truffle.r.nodes.function.ClassHierarchyNode; -import com.oracle.truffle.r.nodes.function.ClassHierarchyNodeGen; import com.oracle.truffle.r.nodes.function.ImplicitClassHierarchyNode; -import com.oracle.truffle.r.nodes.unary.TypeofNode; import com.oracle.truffle.r.runtime.RCaller; import com.oracle.truffle.r.runtime.RError; -import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.Utils; import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.data.RAttributable; import com.oracle.truffle.r.runtime.data.RFunction; import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.RStringVector; -import com.oracle.truffle.r.runtime.data.RSymbol; -import com.oracle.truffle.r.runtime.data.model.RAbstractVector; import com.oracle.truffle.r.runtime.env.REnvironment; -import com.oracle.truffle.r.runtime.nodes.RBaseNode; // Transcribed from src/main/attrib.c file (R_do_slot function) /** * Perform a slot access. This node represents the {@code @} operator in R. */ -public abstract class AccessSlotNode extends RBaseNode { - - public abstract Object executeAccess(Object o, String name); - - @Child private ClassHierarchyNode classHierarchy; - - private final BranchProfile noSlot = BranchProfile.create(); - private final BranchProfile symbolValue = BranchProfile.create(); - private final boolean asOperator; +public abstract class AccessSlotNode extends BaseAccessSlotNode { public AccessSlotNode(boolean asOperator) { - this.asOperator = asOperator; + super(asOperator); } - protected GetAttributeNode createAttrAccess() { - return GetAttributeNode.create(); - } - - private Object getSlotS4Internal(RAttributable object, String name, Object value, GetClassAttributeNode getClassNode) { - if (value == null) { - noSlot.enter(); - assert Utils.isInterned(name); - if (name == RRuntime.DOT_S3_CLASS) { - if (classHierarchy == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - classHierarchy = insert(ClassHierarchyNodeGen.create(true, false)); - } - return classHierarchy.execute(object); - } else if (name == RRuntime.DOT_DATA) { - // TODO: any way to cache it or use a mechanism similar to overrides? - REnvironment methodsNamespace = REnvironment.getRegisteredNamespace("methods"); - RFunction dataPart = getDataPartFunction(methodsNamespace); - return RContext.getEngine().evalFunction(dataPart, methodsNamespace.getFrame(), RCaller.create(null, RASTUtils.getOriginalCall(this)), true, null, object); - } else if (name == RRuntime.NAMES_ATTR_KEY && object instanceof RAbstractVector) { - assert false; // RS4Object can never be a vector? - return RNull.instance; - } - - CompilerDirectives.transferToInterpreter(); - RStringVector classAttr = getClassNode.getClassAttr(object); - if (classAttr == null) { - throw error(RError.Message.SLOT_CANNOT_GET, name, TypeofNode.getTypeof(object).getName()); - } else { - throw error(RError.Message.SLOT_NONE, name, classAttr.getLength() == 0 ? RRuntime.STRING_NA : classAttr.getDataAt(0)); - } - } - if (value instanceof RSymbol) { - symbolValue.enter(); - if (((RSymbol) value).getName() == RRuntime.PSEUDO_NULL.getName()) { - return RNull.instance; - } - } - return value; - } + public abstract Object executeAccess(Object o, String name); @Specialization protected Object getSlotS4(@SuppressWarnings("unused") RNull object, String name) { @@ -114,13 +57,6 @@ public abstract class AccessSlotNode extends RBaseNode { return getSlotS4Internal(object, internedName, value, getClassNode); } - @TruffleBoundary - private static RFunction getDataPartFunction(REnvironment methodsNamespace) { - String name = "getDataPart"; - Object f = methodsNamespace.findFunction(name); - return (RFunction) RContext.getRRuntimeASTAccess().forcePromise(name, f); - } - @Specialization(guards = {"!slotAccessAllowed(object)", "isDotData(name)"}) protected Object getSlotNonS4(RAttributable object, @SuppressWarnings("unused") String name) { // TODO: any way to cache it or use a mechanism similar to overrides? @@ -144,13 +80,4 @@ public abstract class AccessSlotNode extends RBaseNode { throw error(RError.Message.SLOT_NON_S4, name, classAttr.getDataAt(0)); } } - - protected boolean isDotData(String name) { - assert Utils.isInterned(name); - return name == RRuntime.DOT_DATA; - } - - protected boolean slotAccessAllowed(RAttributable object) { - return object.isS4() || !asOperator; - } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/BaseAccessSlotNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/BaseAccessSlotNode.java new file mode 100644 index 0000000000..6cabf34005 --- /dev/null +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/BaseAccessSlotNode.java @@ -0,0 +1,95 @@ +package com.oracle.truffle.r.nodes.access; + +import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +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.SpecialAttributesFunctions.GetClassAttributeNode; +import com.oracle.truffle.r.nodes.function.ClassHierarchyNode; +import com.oracle.truffle.r.nodes.function.ClassHierarchyNodeGen; +import com.oracle.truffle.r.nodes.unary.TypeofNode; +import com.oracle.truffle.r.runtime.RCaller; +import com.oracle.truffle.r.runtime.RError; +import com.oracle.truffle.r.runtime.RRuntime; +import com.oracle.truffle.r.runtime.Utils; +import com.oracle.truffle.r.runtime.context.RContext; +import com.oracle.truffle.r.runtime.data.RAttributable; +import com.oracle.truffle.r.runtime.data.RFunction; +import com.oracle.truffle.r.runtime.data.RNull; +import com.oracle.truffle.r.runtime.data.RStringVector; +import com.oracle.truffle.r.runtime.data.RSymbol; +import com.oracle.truffle.r.runtime.data.model.RAbstractVector; +import com.oracle.truffle.r.runtime.env.REnvironment; +import com.oracle.truffle.r.runtime.nodes.RBaseNode; + +public abstract class BaseAccessSlotNode extends RBaseNode { + + @Child private ClassHierarchyNode classHierarchy; + + private final BranchProfile noSlot = BranchProfile.create(); + private final BranchProfile symbolValue = BranchProfile.create(); + protected final boolean asOperator; + + protected BaseAccessSlotNode(boolean asOperator) { + this.asOperator = asOperator; + } + + @TruffleBoundary + protected static RFunction getDataPartFunction(REnvironment methodsNamespace) { + String name = "getDataPart"; + Object f = methodsNamespace.findFunction(name); + return (RFunction) RContext.getRRuntimeASTAccess().forcePromise(name, f); + } + + protected GetAttributeNode createAttrAccess() { + return GetAttributeNode.create(); + } + + protected Object getSlotS4Internal(RAttributable object, String name, Object value, GetClassAttributeNode getClassNode) { + if (value == null) { + noSlot.enter(); + assert Utils.isInterned(name); + if (name == RRuntime.DOT_S3_CLASS) { + if (classHierarchy == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + classHierarchy = insert(ClassHierarchyNodeGen.create(true, false)); + } + return classHierarchy.execute(object); + } else if (name == RRuntime.DOT_DATA) { + // TODO: any way to cache it or use a mechanism similar to overrides? + REnvironment methodsNamespace = REnvironment.getRegisteredNamespace("methods"); + RFunction dataPart = getDataPartFunction(methodsNamespace); + return RContext.getEngine().evalFunction(dataPart, methodsNamespace.getFrame(), RCaller.create(null, RASTUtils.getOriginalCall(this)), true, null, object); + } else if (name == RRuntime.NAMES_ATTR_KEY && object instanceof RAbstractVector) { + assert false; // RS4Object can never be a vector? + return RNull.instance; + } + + CompilerDirectives.transferToInterpreter(); + RStringVector classAttr = getClassNode.getClassAttr(object); + if (classAttr == null) { + throw error(RError.Message.SLOT_CANNOT_GET, name, TypeofNode.getTypeof(object).getName()); + } else { + throw error(RError.Message.SLOT_NONE, name, classAttr.getLength() == 0 ? RRuntime.STRING_NA : classAttr.getDataAt(0)); + } + } + if (value instanceof RSymbol) { + symbolValue.enter(); + if (((RSymbol) value).getName() == RRuntime.PSEUDO_NULL.getName()) { + return RNull.instance; + } + } + return value; + } + + protected boolean isDotData(String name) { + assert Utils.isInterned(name); + return name == RRuntime.DOT_DATA; + } + + protected boolean slotAccessAllowed(RAttributable object) { + return object.isS4() || !asOperator; + } + +} \ No newline at end of file diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/HasSlotNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/HasSlotNode.java new file mode 100644 index 0000000000..60ac13f14f --- /dev/null +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/HasSlotNode.java @@ -0,0 +1,76 @@ +/* + * This material is distributed under the GNU General Public License + * Version 2. You may review the terms of this license at + * http://www.gnu.org/licenses/gpl-2.0.html + * + * Copyright (c) 1995, 1996, 1997 Robert Gentleman and Ross Ihaka + * Copyright (c) 1995-2014, The R Core Team + * Copyright (c) 2002-2008, The R Foundation + * Copyright (c) 2015, 2017, Oracle and/or its affiliates + * + * All rights reserved. + */ +package com.oracle.truffle.r.nodes.access; + +import com.oracle.truffle.api.dsl.Cached; +import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.r.nodes.RASTUtils; +import com.oracle.truffle.r.nodes.attributes.GetAttributeNode; +import com.oracle.truffle.r.nodes.attributes.InitAttributesNode; +import com.oracle.truffle.r.runtime.RCaller; +import com.oracle.truffle.r.runtime.context.RContext; +import com.oracle.truffle.r.runtime.data.RAttributable; +import com.oracle.truffle.r.runtime.data.RFunction; +import com.oracle.truffle.r.runtime.data.RNull; +import com.oracle.truffle.r.runtime.env.REnvironment; + +// Transcribed from src/main/attrib.c file (R_has_slot function) + +/** + * Perform a check if the specified slot exists. This is almost like the {@code @} operator in R but + * does not raise an error if the slot does not exist. + */ +public abstract class HasSlotNode extends BaseAccessSlotNode { + + public HasSlotNode(boolean asOperator) { + super(asOperator); + } + + public abstract boolean executeAccess(Object o, String name); + + @Specialization + @SuppressWarnings("unused") + protected boolean getSlotS4(RNull object, String name) { + return false; + } + + @Specialization(guards = {"slotAccessAllowed(object)"}) + protected boolean getSlotS4Cached(RAttributable object, String name, + @Cached("createAttrAccess()") GetAttributeNode attrAccess, + @Cached("create()") InitAttributesNode initAttrNode) { + return attrAccess.execute(initAttrNode.execute(object), name) != null; + } + + @Specialization(guards = {"!slotAccessAllowed(object)", "isDotData(name)"}) + protected boolean getSlotNonS4(RAttributable object, @SuppressWarnings("unused") String name) { + // TODO: any way to cache it or use a mechanism similar to overrides? + REnvironment methodsNamespace = REnvironment.getRegisteredNamespace("methods"); + RFunction dataPart = getDataPartFunction(methodsNamespace); + + // TODO will throw an error if ".data" does not exists but should not + Object result = RContext.getEngine().evalFunction(dataPart, methodsNamespace.getFrame(), RCaller.create(null, RASTUtils.getOriginalCall(this)), true, null, object); + return result != null; + } + + // this is really a fallback specialization but @Fallback does not work here (because of the + // type of "object"?) + @Specialization(guards = {"!slotAccessAllowed(object)", "!isDotData(name)"}) + @SuppressWarnings("unused") + protected boolean getSlot(RAttributable object, String name) { + return false; + } + + public static HasSlotNode create(boolean asOperator) { + return HasSlotNodeGen.create(asOperator); + } +} diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/EnvironmentNodes.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/EnvironmentNodes.java new file mode 100644 index 0000000000..8640243b93 --- /dev/null +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/EnvironmentNodes.java @@ -0,0 +1,77 @@ +package com.oracle.truffle.r.nodes.builtin; + +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.frame.Frame; +import com.oracle.truffle.api.profiles.ConditionProfile; +import com.oracle.truffle.r.runtime.RArguments; +import com.oracle.truffle.r.runtime.RError; +import com.oracle.truffle.r.runtime.data.RFunction; +import com.oracle.truffle.r.runtime.data.RNull; +import com.oracle.truffle.r.runtime.data.RStringVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractListVector; +import com.oracle.truffle.r.runtime.env.REnvironment; +import com.oracle.truffle.r.runtime.nodes.RBaseNode; + +public final class EnvironmentNodes { + + /** + * Abstracted for use by other nodes that need to convert a list into an environment. + */ + public static final class RList2EnvNode extends RBaseNode { + private final boolean ignoreMissingNames; + + public RList2EnvNode() { + this(false); + } + + public RList2EnvNode(boolean ignoreMissingNames) { + this.ignoreMissingNames = ignoreMissingNames; + } + + @TruffleBoundary + public REnvironment execute(RAbstractListVector list, REnvironment env) { + if (list.getLength() == 0) { + return env; + } + RStringVector names = list.getNames(); + if (names == null) { + throw error(RError.Message.LIST_NAMES_SAME_LENGTH); + } + for (int i = list.getLength() - 1; i >= 0; i--) { + String name = names.getDataAt(i); + if (!ignoreMissingNames && name.length() == 0) { + throw error(RError.Message.ZERO_LENGTH_VARIABLE); + } + // in case of duplicates, last element in list wins + if (env.get(name) == null) { + env.safePut(name, list.getDataAt(i)); + } + } + return env; + } + } + + public static final class GetFunctionEnvironmentNode extends RBaseNode { + private final ConditionProfile noEnvProfile = ConditionProfile.createBinaryProfile(); + private final ConditionProfile createProfile = ConditionProfile.createBinaryProfile(); + + /** + * Returns the environment that {@code func} was created in. + */ + public Object getEnvironment(RFunction fun) { + Frame enclosing = fun.getEnclosingFrame(); + if (noEnvProfile.profile(enclosing == null)) { + return RNull.instance; + } + REnvironment env = RArguments.getEnvironment(enclosing); + if (createProfile.profile(env == null)) { + return REnvironment.createEnclosingEnvironments(enclosing.materialize()); + } + return env; + } + + public static GetFunctionEnvironmentNode create() { + return new GetFunctionEnvironmentNode(); + } + } +} diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RList2EnvNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RList2EnvNode.java deleted file mode 100644 index c7491ac86c..0000000000 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RList2EnvNode.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.r.nodes.builtin; - -import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.r.runtime.RError; -import com.oracle.truffle.r.runtime.data.RStringVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractListVector; -import com.oracle.truffle.r.runtime.env.REnvironment; -import com.oracle.truffle.r.runtime.nodes.RBaseNode; - -/** - * Abstracted for use by other nodes that need to convert a list into an environment. - */ -public final class RList2EnvNode extends RBaseNode { - private final boolean ignoreMissingNames; - - public RList2EnvNode() { - this(false); - } - - public RList2EnvNode(boolean ignoreMissingNames) { - this.ignoreMissingNames = ignoreMissingNames; - } - - @TruffleBoundary - public REnvironment execute(RAbstractListVector list, REnvironment env) { - if (list.getLength() == 0) { - return env; - } - RStringVector names = list.getNames(); - if (names == null) { - throw error(RError.Message.LIST_NAMES_SAME_LENGTH); - } - for (int i = list.getLength() - 1; i >= 0; i--) { - String name = names.getDataAt(i); - if (!ignoreMissingNames && name.length() == 0) { - throw error(RError.Message.ZERO_LENGTH_VARIABLE); - } - // in case of duplicates, last element in list wins - if (env.get(name) == null) { - env.safePut(name, list.getDataAt(i)); - } - } - return env; - } -} -- GitLab