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 12ba9db3e2243e0fba60f880c019c10299616e8b..289e049b082d60bafa210a567f341f4c93019d83 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
@@ -170,7 +170,7 @@ public class EnvFunctions {
         @Specialization
         protected Object asEnvironment(RS4Object obj) {
             // generic dispatch tried already
-            Object xData = obj.getAttribute(RRuntime.DOT_XDATA);
+            Object xData = obj.getAttr(RRuntime.DOT_XDATA);
             if (xData == null || !(xData instanceof REnvironment)) {
                 throw RError.error(this, RError.Message.S4OBJECT_NX_ENVIRONMENT);
             } else {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/BrowserInteractNode.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/BrowserInteractNode.java
index 34b9ab3141c55b3c626ea9f0f4e9730a52c8a580..cbfb84aa0fbfd4c31bff273cdec73584d94342c2 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/BrowserInteractNode.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/BrowserInteractNode.java
@@ -147,10 +147,10 @@ public abstract class BrowserInteractNode extends RNode {
     }
 
     private static String getSrcinfo(RStringVector element) {
-        Object srcref = element.getAttribute(RRuntime.R_SRCREF);
+        Object srcref = element.getAttr(RRuntime.R_SRCREF);
         if (srcref != null) {
             RIntVector lloc = (RIntVector) srcref;
-            Object srcfile = lloc.getAttribute(RRuntime.R_SRCFILE);
+            Object srcfile = lloc.getAttr(RRuntime.R_SRCFILE);
             if (srcfile != null) {
                 REnvironment env = (REnvironment) srcfile;
                 return " at " + RRuntime.asString(env.get(RSrcref.SrcrefFields.filename.name())) + "#" + lloc.getDataAt(0);
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java
index 4c52f4046f06685a7c1b5d115a6edf7722ccc236..0170418e8750de357de02f54e8f30a3f681d8d01 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java
@@ -600,7 +600,7 @@ public class RDeparse {
                     append(')');
                 } else if (value instanceof RS4Object) {
                     RS4Object s4Obj = (RS4Object) value;
-                    Object clazz = s4Obj.getAttribute("class");
+                    Object clazz = s4Obj.getAttr("class");
                     String className = clazz == null ? "S4" : RRuntime.toString(RRuntime.asStringLengthOne(clazz));
                     append("new(\"").append(className).append('\"');
                     try (C c = indent()) {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RAttributable.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RAttributable.java
index 609aef238392dc5b3b57b0678104620c299cdc3a..8510ddcb141e26d106c7318327bab504413d39e3 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RAttributable.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RAttributable.java
@@ -23,7 +23,6 @@
 package com.oracle.truffle.r.runtime.data;
 
 import com.oracle.truffle.r.runtime.RRuntime;
-import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.env.REnvironment;
 
 /**
@@ -33,6 +32,7 @@ import com.oracle.truffle.r.runtime.env.REnvironment;
  * {@link RAttributable} is implemented by the {@link RAttributes} class.
  */
 public interface RAttributable extends RTypedValue {
+
     /**
      * If the attribute set is not initialized, then initialize it.
      *
@@ -49,16 +49,21 @@ public interface RAttributable extends RTypedValue {
     RAttributes getAttributes();
 
     /**
-     * Returns the value of the {@code class} attribute.
+     * Returns the value of the {@code class} attribute or empty {@link RStringVector} if
+     * class attribute is not set.
      */
-    RStringVector getClassHierarchy();
+    default RStringVector getClassHierarchy() {
+        Object v = getAttr(RRuntime.CLASS_ATTR_KEY);
+        RStringVector result = v instanceof RStringVector ? (RStringVector) v : getImplicitClass();
+        return result != null ? result : RDataFactory.createEmptyStringVector();
+    }
 
     /**
      * Returns {@code true} if the {@code class} attribute is set to {@link RStringVector} whose
      * first element equals to the given className.
      */
     default boolean hasClass(String className) {
-        RAbstractStringVector v = getClassHierarchy();
+        RStringVector v = getClassHierarchy();
         for (int i = 0; i < v.getLength(); ++i) {
             if (v.getDataAt(i).equals(className)) {
                 return true;
@@ -81,6 +86,14 @@ public interface RAttributable extends RTypedValue {
         }
     }
 
+    /**
+     * Get the value of an attribute. Returns {@code null} if not set.
+     */
+    default Object getAttr(String name) {
+        RAttributes attr = getAttributes();
+        return attr == null ? null : attr.get(name);
+    }
+
     /**
      * Set the attribute {@code name} to {@code value}, overwriting any existing value. This is
      * generic; a class may need to override this to handle certain attributes specially.
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RAttributeStorage.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RAttributeStorage.java
index c8950954a78e352fca4739d8a680cdf5297ae29a..44cf397f6e5f2c585b25d3eebb4613ded89fba98 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RAttributeStorage.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RAttributeStorage.java
@@ -22,8 +22,6 @@
  */
 package com.oracle.truffle.r.runtime.data;
 
-import com.oracle.truffle.r.runtime.RRuntime;
-
 /**
  * An adaptor class for the several R types that are attributable. Only useful for classes that
  * don't already inherit from another class, otherwise just cut and paste this code.
@@ -50,21 +48,6 @@ public abstract class RAttributeStorage extends RBaseObject implements RAttribut
         this.attributes = newAttributes;
     }
 
-    public final Object getAttribute(String name) {
-        RAttributes attr = attributes;
-        return attr == null ? null : attr.get(name);
-    }
-
     @Override
     public abstract RStringVector getImplicitClass();
-
-    @Override
-    public final RStringVector getClassHierarchy() {
-        RStringVector v = (RStringVector) getAttribute(RRuntime.CLASS_ATTR_KEY);
-        if (v == null) {
-            return getImplicitClass();
-        } else {
-            return v;
-        }
-    }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RExpression.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RExpression.java
index ba4747180593c6b1052530889c88cd5abf7eeb34..a365680d20d128c48ab93657ad3970982033a771 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RExpression.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RExpression.java
@@ -158,7 +158,7 @@ public class RExpression implements RShareable, RAbstractContainer {
 
     @Override
     public final RStringVector getClassHierarchy() {
-        RStringVector v = (RStringVector) data.getAttribute(RRuntime.CLASS_ATTR_KEY);
+        RStringVector v = (RStringVector) data.getAttr(RRuntime.CLASS_ATTR_KEY);
         if (v == null) {
             return getImplicitClass();
         } else {