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 9c4e145a41dd500dab242778170308909adcf06d..ee6cfa04ba10a06beecd23d466dbb4d6a18914ac 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
@@ -257,6 +257,14 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI {
         return RUnboundValue.instance;
     }
 
+    @Override
+    public Object ATTRIB(Object obj) {
+        if (obj instanceof RAttributable) {
+            return ((RAttributable) obj).getAttributes();
+        }
+        return RNull.instance;
+    }
+
     @Override
     public Object Rf_getAttrib(Object obj, Object name) {
         Object result = RNull.instance;
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/TracingUpCallsRFFIImpl.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/TracingUpCallsRFFIImpl.java
index ec15934f16e9525aeb68a973b38add783339169e..2fb1c91b4c5da517ca6e13b03fbe8a46c8ace852 100644
--- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/TracingUpCallsRFFIImpl.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/TracingUpCallsRFFIImpl.java
@@ -141,6 +141,12 @@ final class TracingUpCallsRFFIImpl implements UpCallsRFFI {
         return delegate.Rf_findVarInFrame3(envArg, symbolArg, doGet);
     }
 
+    @Override
+    public Object ATTRIB(Object obj) {
+        RFFIUtils.traceUpCall("ATTRIB");
+        return delegate.ATTRIB(obj);
+    }
+
     @Override
     public Object Rf_getAttrib(Object obj, Object name) {
         RFFIUtils.traceUpCall("Rf_getAttrib", obj, name);
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 5606335c7c8f3260f672993a069d6f616243b0bb..34e5920142774fa21726f9a4860beb1745c1bf96 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
@@ -90,6 +90,8 @@ public interface StdUpCallsRFFI {
 
     Object Rf_findVarInFrame3(Object envArg, Object symbolArg, int doGet);
 
+    Object ATTRIB(Object obj);
+
     Object Rf_getAttrib(Object obj, Object name);
 
     int /* void */ Rf_setAttrib(Object obj, Object name, Object val);
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 3f335946c1e0d7c77472eea4abdfb9a28e5a3c95..daea8d65adb8c25faa2273b2776c465dbe42bdd7 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
@@ -2,141 +2,142 @@
 #ifndef RFFI_UPCALLSINDEX_H
 #define RFFI_UPCALLSINDEX_H
 
-#define CADDR_x 0
-#define CADR_x 1
-#define CAR_x 2
-#define CDDR_x 3
-#define CDR_x 4
-#define DUPLICATE_ATTRIB_x 5
-#define ENCLOS_x 6
-#define GetRNGstate_x 7
-#define INTEGER_x 8
-#define IS_S4_OBJECT_x 9
-#define LENGTH_x 10
-#define LOGICAL_x 11
-#define NAMED_x 12
-#define OBJECT_x 13
-#define PRCODE_x 14
-#define PRENV_x 15
-#define PRINTNAME_x 16
-#define PRSEEN_x 17
-#define PRVALUE_x 18
-#define PutRNGstate_x 19
-#define RAW_x 20
-#define RDEBUG_x 21
-#define REAL_x 22
-#define RSTEP_x 23
-#define R_BaseEnv_x 24
-#define R_BaseNamespace_x 25
-#define R_BindingIsLocked_x 26
-#define R_CHAR_x 27
-#define R_CleanUp_x 28
-#define R_ExternalPtrAddr_x 29
-#define R_ExternalPtrProtected_x 30
-#define R_ExternalPtrTag_x 31
-#define R_FindNamespace_x 32
-#define R_GetConnection_x 33
-#define R_GlobalContext_x 34
-#define R_GlobalEnv_x 35
-#define R_Home_x 36
-#define R_HomeDir_x 37
-#define R_Interactive_x 38
-#define R_MakeExternalPtr_x 39
-#define R_MethodsNamespace_x 40
-#define R_NamespaceRegistry_x 41
-#define R_NewHashedEnv_x 42
-#define R_ParseVector_x 43
-#define R_PromiseExpr_x 44
-#define R_ReadConnection_x 45
-#define R_SetExternalPtrAddr_x 46
-#define R_SetExternalPtrProtected_x 47
-#define R_SetExternalPtrTag_x 48
-#define R_TempDir_x 49
-#define R_ToplevelExec_x 50
-#define R_WriteConnection_x 51
-#define R_compute_identical_x 52
-#define R_do_MAKE_CLASS_x 53
-#define R_do_new_object_x 54
-#define R_do_slot_x 55
-#define R_do_slot_assign_x 56
-#define R_getContextCall_x 57
-#define R_getContextEnv_x 58
-#define R_getContextFun_x 59
-#define R_getContextSrcRef_x 60
-#define R_getGlobalFunctionContext_x 61
-#define R_getParentFunctionContext_x 62
-#define R_insideBrowser_x 63
-#define R_isEqual_x 64
-#define R_isGlobal_x 65
-#define R_lsInternal3_x 66
-#define R_new_custom_connection_x 67
-#define R_tryEval_x 68
-#define Rf_GetOption1_x 69
-#define Rf_PairToVectorList_x 70
-#define Rf_ScalarDouble_x 71
-#define Rf_ScalarInteger_x 72
-#define Rf_ScalarLogical_x 73
-#define Rf_ScalarString_x 74
-#define Rf_allocArray_x 75
-#define Rf_allocMatrix_x 76
-#define Rf_allocVector_x 77
-#define Rf_any_duplicated_x 78
-#define Rf_asChar_x 79
-#define Rf_asInteger_x 80
-#define Rf_asLogical_x 81
-#define Rf_asReal_x 82
-#define Rf_classgets_x 83
-#define Rf_coerceVector_x 84
-#define Rf_cons_x 85
-#define Rf_copyListMatrix_x 86
-#define Rf_copyMatrix_x 87
-#define Rf_defineVar_x 88
-#define Rf_duplicate_x 89
-#define Rf_error_x 90
-#define Rf_eval_x 91
-#define Rf_findFun_x 92
-#define Rf_findVar_x 93
-#define Rf_findVarInFrame_x 94
-#define Rf_findVarInFrame3_x 95
-#define Rf_getAttrib_x 96
-#define Rf_gsetVar_x 97
-#define Rf_inherits_x 98
-#define Rf_install_x 99
-#define Rf_installChar_x 100
-#define Rf_isNull_x 101
-#define Rf_isString_x 102
-#define Rf_lengthgets_x 103
-#define Rf_mkCharLenCE_x 104
-#define Rf_ncols_x 105
-#define Rf_nrows_x 106
-#define Rf_setAttrib_x 107
-#define Rf_str2type_x 108
-#define Rf_warning_x 109
-#define Rf_warningcall_x 110
-#define Rprintf_x 111
-#define SETCADR_x 112
-#define SETCAR_x 113
-#define SETCDR_x 114
-#define SET_RDEBUG_x 115
-#define SET_RSTEP_x 116
-#define SET_S4_OBJECT_x 117
-#define SET_STRING_ELT_x 118
-#define SET_SYMVALUE_x 119
-#define SET_TAG_x 120
-#define SET_TYPEOF_FASTR_x 121
-#define SET_VECTOR_ELT_x 122
-#define STRING_ELT_x 123
-#define SYMVALUE_x 124
-#define TAG_x 125
-#define TYPEOF_x 126
-#define UNSET_S4_OBJECT_x 127
-#define VECTOR_ELT_x 128
-#define getConnectionClassString_x 129
-#define getOpenModeString_x 130
-#define getSummaryDescription_x 131
-#define isSeekable_x 132
-#define unif_rand_x 133
+#define ATTRIB_x 0
+#define CADDR_x 1
+#define CADR_x 2
+#define CAR_x 3
+#define CDDR_x 4
+#define CDR_x 5
+#define DUPLICATE_ATTRIB_x 6
+#define ENCLOS_x 7
+#define GetRNGstate_x 8
+#define INTEGER_x 9
+#define IS_S4_OBJECT_x 10
+#define LENGTH_x 11
+#define LOGICAL_x 12
+#define NAMED_x 13
+#define OBJECT_x 14
+#define PRCODE_x 15
+#define PRENV_x 16
+#define PRINTNAME_x 17
+#define PRSEEN_x 18
+#define PRVALUE_x 19
+#define PutRNGstate_x 20
+#define RAW_x 21
+#define RDEBUG_x 22
+#define REAL_x 23
+#define RSTEP_x 24
+#define R_BaseEnv_x 25
+#define R_BaseNamespace_x 26
+#define R_BindingIsLocked_x 27
+#define R_CHAR_x 28
+#define R_CleanUp_x 29
+#define R_ExternalPtrAddr_x 30
+#define R_ExternalPtrProtected_x 31
+#define R_ExternalPtrTag_x 32
+#define R_FindNamespace_x 33
+#define R_GetConnection_x 34
+#define R_GlobalContext_x 35
+#define R_GlobalEnv_x 36
+#define R_Home_x 37
+#define R_HomeDir_x 38
+#define R_Interactive_x 39
+#define R_MakeExternalPtr_x 40
+#define R_MethodsNamespace_x 41
+#define R_NamespaceRegistry_x 42
+#define R_NewHashedEnv_x 43
+#define R_ParseVector_x 44
+#define R_PromiseExpr_x 45
+#define R_ReadConnection_x 46
+#define R_SetExternalPtrAddr_x 47
+#define R_SetExternalPtrProtected_x 48
+#define R_SetExternalPtrTag_x 49
+#define R_TempDir_x 50
+#define R_ToplevelExec_x 51
+#define R_WriteConnection_x 52
+#define R_compute_identical_x 53
+#define R_do_MAKE_CLASS_x 54
+#define R_do_new_object_x 55
+#define R_do_slot_x 56
+#define R_do_slot_assign_x 57
+#define R_getContextCall_x 58
+#define R_getContextEnv_x 59
+#define R_getContextFun_x 60
+#define R_getContextSrcRef_x 61
+#define R_getGlobalFunctionContext_x 62
+#define R_getParentFunctionContext_x 63
+#define R_insideBrowser_x 64
+#define R_isEqual_x 65
+#define R_isGlobal_x 66
+#define R_lsInternal3_x 67
+#define R_new_custom_connection_x 68
+#define R_tryEval_x 69
+#define Rf_GetOption1_x 70
+#define Rf_PairToVectorList_x 71
+#define Rf_ScalarDouble_x 72
+#define Rf_ScalarInteger_x 73
+#define Rf_ScalarLogical_x 74
+#define Rf_ScalarString_x 75
+#define Rf_allocArray_x 76
+#define Rf_allocMatrix_x 77
+#define Rf_allocVector_x 78
+#define Rf_any_duplicated_x 79
+#define Rf_asChar_x 80
+#define Rf_asInteger_x 81
+#define Rf_asLogical_x 82
+#define Rf_asReal_x 83
+#define Rf_classgets_x 84
+#define Rf_coerceVector_x 85
+#define Rf_cons_x 86
+#define Rf_copyListMatrix_x 87
+#define Rf_copyMatrix_x 88
+#define Rf_defineVar_x 89
+#define Rf_duplicate_x 90
+#define Rf_error_x 91
+#define Rf_eval_x 92
+#define Rf_findFun_x 93
+#define Rf_findVar_x 94
+#define Rf_findVarInFrame_x 95
+#define Rf_findVarInFrame3_x 96
+#define Rf_getAttrib_x 97
+#define Rf_gsetVar_x 98
+#define Rf_inherits_x 99
+#define Rf_install_x 100
+#define Rf_installChar_x 101
+#define Rf_isNull_x 102
+#define Rf_isString_x 103
+#define Rf_lengthgets_x 104
+#define Rf_mkCharLenCE_x 105
+#define Rf_ncols_x 106
+#define Rf_nrows_x 107
+#define Rf_setAttrib_x 108
+#define Rf_str2type_x 109
+#define Rf_warning_x 110
+#define Rf_warningcall_x 111
+#define Rprintf_x 112
+#define SETCADR_x 113
+#define SETCAR_x 114
+#define SETCDR_x 115
+#define SET_RDEBUG_x 116
+#define SET_RSTEP_x 117
+#define SET_S4_OBJECT_x 118
+#define SET_STRING_ELT_x 119
+#define SET_SYMVALUE_x 120
+#define SET_TAG_x 121
+#define SET_TYPEOF_FASTR_x 122
+#define SET_VECTOR_ELT_x 123
+#define STRING_ELT_x 124
+#define SYMVALUE_x 125
+#define TAG_x 126
+#define TYPEOF_x 127
+#define UNSET_S4_OBJECT_x 128
+#define VECTOR_ELT_x 129
+#define getConnectionClassString_x 130
+#define getOpenModeString_x 131
+#define getSummaryDescription_x 132
+#define isSeekable_x 133
+#define unif_rand_x 134
 
-#define UPCALLS_TABLE_SIZE 134
+#define UPCALLS_TABLE_SIZE 135
 
 #endif // RFFI_UPCALLSINDEX_H
diff --git a/com.oracle.truffle.r.native/fficall/src/jni/Rinternals.c b/com.oracle.truffle.r.native/fficall/src/jni/Rinternals.c
index 659eff9e47d07a510f25a19dadb27a9fcef2f430..4c7e18dfa9c8d156a6a2c893f089b01c5a2369ff 100644
--- a/com.oracle.truffle.r.native/fficall/src/jni/Rinternals.c
+++ b/com.oracle.truffle.r.native/fficall/src/jni/Rinternals.c
@@ -49,6 +49,7 @@ static jmethodID Rf_defineVarMethodID;
 static jmethodID Rf_findVarMethodID;
 static jmethodID Rf_findVarInFrameMethodID;
 static jmethodID Rf_findVarInFrame3MethodID;
+static jmethodID ATTRIBMethodID;
 static jmethodID Rf_getAttribMethodID;
 static jmethodID Rf_setAttribMethodID;
 static jmethodID Rf_isStringMethodID;
@@ -161,6 +162,7 @@ void init_internals(JNIEnv *env) {
 	Rf_findVarMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_findVar", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", 0);
 	Rf_findVarInFrameMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_findVarInFrame", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", 0);
 	Rf_findVarInFrame3MethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_findVarInFrame3", "(Ljava/lang/Object;Ljava/lang/Object;I)Ljava/lang/Object;", 0);
+	ATTRIBMethodID = checkGetMethodID(env, UpCallsRFFIClass, "ATTRIB", "(Ljava/lang/Object;)Ljava/lang/Object;", 0);
 	Rf_getAttribMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_getAttrib", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", 0);
 	Rf_setAttribMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_setAttrib", "(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)I", 0);
 	Rf_isStringMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_isString", "(Ljava/lang/Object;)I", 0);
@@ -1207,9 +1209,11 @@ int TYPEOF(SEXP x) {
 	return (*thisenv)->CallIntMethod(thisenv, UpCallsRFFIObject, TYPEOF_MethodID, x);
 }
 
-SEXP ATTRIB(SEXP x){
-    unimplemented("ATTRIB");
-    return NULL;
+SEXP ATTRIB(SEXP x) {
+    TRACE(TARGp, x);
+    JNIEnv *thisenv = getEnv();
+    SEXP result = (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, ATTRIBMethodID, x);
+    return checkRef(thisenv, result);
 }
 
 int OBJECT(SEXP x){
@@ -1582,4 +1586,3 @@ void Rf_copyMatrix(SEXP s, SEXP t, Rboolean byrow) {
     JNIEnv *thisenv = getEnv();
     (*thisenv)->CallIntMethod(thisenv, UpCallsRFFIObject, Rf_copyMatrixMethodID, s, t, byrow);
 }
-
diff --git a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/R/testrffi.R b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/R/testrffi.R
index 40cac74b4cd4b8607c439f01070fdc27e5ddcce7..5d51f5d3711b65d5e774f4face20217fe92d6fb6 100644
--- a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/R/testrffi.R
+++ b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/R/testrffi.R
@@ -157,6 +157,10 @@ rffi.coerceVector <- function(x, mode) {
 	.Call("test_coerceVector", x, mode)
 }
 
+rffi.ATTRIB <- function(x) {
+    .Call('test_ATTRIB', x);
+}
+
 rffi.getStringNA <- function() {
     .Call("test_stringNA")
 }
diff --git a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/init.c b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/init.c
index a941525ea445ef111b6227741a59932b32a4f96f..cc10d16e70de109316ec99eab9712bc97c69295c 100644
--- a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/init.c
+++ b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/init.c
@@ -72,6 +72,7 @@ static const R_CallMethodDef CallEntries[] = {
         CALLDEF(test_CDR, 1),
         CALLDEF(test_LENGTH, 1),
         CALLDEF(test_coerceVector, 2),
+        CALLDEF(test_ATTRIB, 1),
         CALLDEF(test_stringNA, 0),
         {NULL, NULL, 0}
 };
diff --git a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/testrffi.c b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/testrffi.c
index 45c678f52bd528c8d476ec5a5d67bb3b36d13b24..373d444e6d296fbbf4de95ce0e7e5c8e17f356ca 100644
--- a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/testrffi.c
+++ b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/testrffi.c
@@ -323,6 +323,10 @@ SEXP test_coerceVector(SEXP x, SEXP mode) {
     return Rf_coerceVector(x, intMode);
 }
 
+SEXP test_ATTRIB(SEXP x) {
+    return ATTRIB(x);
+}
+
 SEXP test_stringNA(void) {
     SEXP x = allocVector(STRSXP, 1);
     SET_STRING_ELT(x, 0, NA_STRING);
diff --git a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/testrffi.h b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/testrffi.h
index b873c407f8b90c00341a4ffa064b839aa37b6cc9..5c9f89bc762c1bfde1d9a734dfd634e94b1d194f 100644
--- a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/testrffi.h
+++ b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/testrffi.h
@@ -88,4 +88,6 @@ extern SEXP test_LENGTH(SEXP x);
 
 extern SEXP test_coerceVector(SEXP x, SEXP mode);
 
+extern SEXP test_ATTRIB(SEXP);
+
 extern SEXP test_stringNA(void);
diff --git a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/tests/simpleTests.R b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/tests/simpleTests.R
index 54340283c53af0f704df8f2c118bb15242dd9c28..652761e3bb2592f41724c0235a45af0de18313e7 100644
--- a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/tests/simpleTests.R
+++ b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/tests/simpleTests.R
@@ -26,5 +26,10 @@ x <- "12345"; rffi.char_length(x)
 strVec <- rffi.getStringNA();
 stopifnot(anyNA(strVec))
 
+x <- list(1)
+attribute(x, 'myattr') <- 'hello';
+attrs <- ATTRIB(x)
+stopifnot(attrs[[1]] == 'hello')
+
 # loess invokes loess_raw native function passing in string value as argument and that is what we test here.
 loess(dist ~ speed, cars);