diff --git a/ci.hocon b/ci.hocon
index 1372299472405eec9b504a4625d8c2575d2e2f07..14a118d4bce34232d3b76025d0022397ec46127b 100644
--- a/ci.hocon
+++ b/ci.hocon
@@ -185,7 +185,7 @@ builds = [
   ${gateTestNoSpecialsLinux}  {capabilities : [linux, amd64, fast],  targets : [gate], name: "gate-test-linux-amd64-nospecials"}
   ${gateTestDarwin}           {capabilities : [darwin, amd64], targets : [gate], name: "gate-test-darwin-amd64"}
   ${gateStyle}                {capabilities : [linux, amd64],  targets : [gate], name: "gate-style-linux-amd64"}
-#  ${rbcheck}                  {capabilities : [linux, amd64],  targets : [gate], name: "gate-rbcheck-linux-amd64"}
+  ${rbcheck}                  {capabilities : [linux, amd64],  targets : [gate], name: "gate-rbcheck-linux-amd64"}
   ${internalPkgtest}          {capabilities : [linux, amd64],  targets : [gate], name: "gate-internal-pkgtest-linux-amd64"}
   ${gateTestManagedLinux}     {capabilities : [linux, amd64, fast],  targets : [gate], name: "gate-test-managed-linux-amd64"}
   ${gateTestJava9Linux}       {capabilities : [linux, amd64, fast],  targets : [gate], name: "gate-test-java9-linux-amd64"}
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/RBuiltinPackage.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/RBuiltinPackage.java
index 060ba197e499a9e08aed02966e032efdfc013454..7718503513539ace7444d0777c02d1ca02f0d0f4 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/RBuiltinPackage.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/RBuiltinPackage.java
@@ -146,18 +146,28 @@ public abstract class RBuiltinPackage {
         }
     }
 
+    protected void add(Class<?> builtinMetaClass, Class<?> builtinClass,
+                    Supplier<RBuiltinNode> constructor) {
+        add(builtinMetaClass, builtinClass, constructor, null);
+    }
+
     protected void add(Class<?> builtinClass,
                     Supplier<RBuiltinNode> constructor) {
         add(builtinClass, constructor, null);
     }
 
     protected void add(Class<?> builtinClass, Supplier<RBuiltinNode> constructor, RSpecialFactory specialCall) {
-        RBuiltin annotation = builtinClass.getAnnotation(RBuiltin.class);
+        add(builtinClass, builtinClass, constructor, specialCall);
+    }
+
+    protected void add(Class<?> builtinMetaClass, Class<?> builtinClass, Supplier<RBuiltinNode> constructor, RSpecialFactory specialCall) {
+        RBuiltin annotation = builtinMetaClass.getAnnotation(RBuiltin.class);
         String[] parameterNames = annotation.parameterNames();
         parameterNames = Arrays.stream(parameterNames).map(n -> n.isEmpty() ? null : n).toArray(String[]::new);
         ArgumentsSignature signature = ArgumentsSignature.get(parameterNames);
 
-        putBuiltin(new RBuiltinFactory(annotation.name(), builtinClass, annotation.visibility(), annotation.aliases(), annotation.kind(), signature, annotation.nonEvalArgs(), annotation.splitCaller(),
+        putBuiltin(new RBuiltinFactory(annotation.name(), builtinMetaClass, builtinClass, annotation.visibility(), annotation.aliases(), annotation.kind(), signature, annotation.nonEvalArgs(),
+                        annotation.splitCaller(),
                         annotation.alwaysSplit(), annotation.dispatch(), annotation.genericName(), constructor, annotation.behavior(), specialCall));
     }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java
index 6ba9613400206e89970195051155f012593c57bb..a39e3956bcf4d3a8172cb6a7e96c251fd32868b9 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java
@@ -333,8 +333,8 @@ public class BasePackage extends RBuiltinPackage {
         add(ConnectionFunctions.IsIncomplete.class, ConnectionFunctionsFactory.IsIncompleteNodeGen::create);
         add(Contributors.class, ContributorsNodeGen::create);
         add(CopyDFAttr.class, CopyDFAttrNodeGen::create);
-        add(CrossprodCommon.TCrossprod.class, CrossprodCommon::createTCrossprod);
-        add(CrossprodCommon.Crossprod.class, CrossprodCommon::createCrossprod);
+        add(CrossprodCommon.TCrossprod.class, CrossprodCommon.class, CrossprodCommon::createTCrossprod);
+        add(CrossprodCommon.Crossprod.class, CrossprodCommon.class, CrossprodCommon::createCrossprod);
         add(CRC64.class, CRC64NodeGen::create);
         add(CumMax.class, CumMaxNodeGen::create);
         add(CumMin.class, CumMinNodeGen::create);
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/CastUtils.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/CastUtils.java
index 5480da712a35eec8b8dee79aba852242d7f1ed58..fda59988b92dd86d2a049a7d8f417642bbde717b 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/CastUtils.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/CastUtils.java
@@ -36,6 +36,7 @@ import java.util.Set;
 import java.util.function.Predicate;
 import java.util.stream.Collectors;
 
+import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.RType;
@@ -393,7 +394,7 @@ public class CastUtils {
         }
 
         public static Casts createCastNodeCasts(Class<?> castNodeClass) {
-            return createCastsFromMethods(castNodeClass, Specialization.class);
+            return createCastsFromMethods(castNodeClass, Specialization.class, Fallback.class);
         }
 
         public static Casts createImplicitCasts() {
@@ -408,8 +409,9 @@ public class CastUtils {
             return new Casts(cs);
         }
 
-        public static Casts createCastsFromMethods(Class<?> clazz, Class<? extends Annotation> annotClass) {
-            List<Method> specs = getAnnotatedMethods(clazz, annotClass);
+        @SafeVarargs
+        public static Casts createCastsFromMethods(Class<?> clazz, Class<? extends Annotation>... annotClasses) {
+            List<Method> specs = getAnnotatedMethods(clazz, annotClasses);
             return new Casts(specs.stream().map(s -> new Cast(s.getParameterTypes()[0], s.getReturnType(), Cast.Coverage.full)).filter(c -> c.rt != Object.class).collect(Collectors.toList()));
         }
 
@@ -450,13 +452,22 @@ public class CastUtils {
         }
     }
 
-    public static List<Method> getAnnotatedMethods(Class<?> clazz, Class<? extends Annotation> annotClass) {
+    @SafeVarargs
+    public static List<Method> getAnnotatedMethods(Class<?> clazz, Class<? extends Annotation>... annotClasses) {
+        List<Method> annotMethList = new ArrayList<>();
+        for (Class<? extends Annotation> annotClass : annotClasses) {
+            annotMethList.addAll(getMethodsAnnotatedBy(clazz, annotClass));
+        }
+        return annotMethList;
+    }
+
+    private static List<Method> getMethodsAnnotatedBy(Class<?> clazz, Class<? extends Annotation> annotClass) {
         List<Method> annotMethList = new ArrayList<>(Arrays.asList(clazz.getDeclaredMethods()).stream().filter(dm -> {
             return dm.getAnnotation(annotClass) != null;
         }).collect(Collectors.toList()));
 
         if (clazz.getSuperclass() != Object.class) {
-            annotMethList.addAll(getAnnotatedMethods(clazz.getSuperclass(), annotClass));
+            annotMethList.addAll(getMethodsAnnotatedBy(clazz.getSuperclass(), annotClass));
         }
 
         return annotMethList;
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/Not.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/Not.java
index 28d9ff8fff17fa4111c989f2922807e5896b068c..e0a147f0510293357274b01bd11dfa0116b55805 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/Not.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/Not.java
@@ -74,7 +74,6 @@ public final class Not<T> implements Type, TypeAndInstanceCheck {
         if (isNegative(t)) {
             return getPositiveType(t);
         } else {
-            assert t instanceof Class;
             return new Not<>(t);
         }
     }
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/TypeAndInstanceCheck.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/TypeAndInstanceCheck.java
index e5b115a5532ef8067afba1a5de1bbdc17c4e479b..1c28c4fcd60055d913306a25b94ffbe3b7e2569b 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/TypeAndInstanceCheck.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/TypeAndInstanceCheck.java
@@ -49,9 +49,6 @@ public interface TypeAndInstanceCheck {
     Type normalize();
 
     static Coverage coverage(Type from, Type to, boolean includeImplicits) {
-        assert (from instanceof Not || from instanceof Class);
-        assert (to instanceof Not || to instanceof Class);
-
         if (Not.negateType(to).equals(from)) {
             return Coverage.none;
         }
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/UpperBoundsConjunction.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/UpperBoundsConjunction.java
index f7475baa48f56cf224f344fb83d2ef52f56e4cbd..e4c03aa42f6a7a6c94816f336c0e7d94b12512c3 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/UpperBoundsConjunction.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/UpperBoundsConjunction.java
@@ -117,7 +117,6 @@ public final class UpperBoundsConjunction implements WildcardType, TypeAndInstan
     }
 
     public Coverage coverageTo(Type to, boolean includeImplicits) {
-        assert to instanceof Not || to instanceof Class;
         return adjustCoverageTo(upperBounds.stream().map(ubt -> {
             return TypeAndInstanceCheck.coverage(ubt, to, includeImplicits);
         }).reduce((res, cvg) -> res == Coverage.none || cvg == Coverage.none ? Coverage.none : cvg.or(res)).orElse(Coverage.none));
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/castsTests/ResultTypesAnalyserTest.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/castsTests/ResultTypesAnalyserTest.java
index 85f11a3b1d14ee85e26a22ab081fb7ab713378a2..7fb9a908ee5f754a5e25af009431bb1a7ecfeaad 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/castsTests/ResultTypesAnalyserTest.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/castsTests/ResultTypesAnalyserTest.java
@@ -120,7 +120,7 @@ public class ResultTypesAnalyserTest {
     @Test
     public void testAsIntegerVector() {
         arg.asIntegerVector();
-        assertTypes(RNull.class, RMissing.class, int.class, RIntSequence.class, RIntVector.class);
+        assertTypes(RNull.class, RMissing.class, int.class, RIntSequence.class, RIntVector.class, RAbstractIntVector.class);
     }
 
     @Test
@@ -436,7 +436,7 @@ public class ResultTypesAnalyserTest {
     @Test
     public void testReturnIf2() {
         arg.returnIf(nullValue(), emptyIntegerVector()).returnIf(missingValue(), emptyIntegerVector()).asIntegerVector();
-        assertTypes(atom(int.class).or(atom(RIntSequence.class)).or(atom(RIntVector.class)), true);
+        assertTypes(atom(int.class).or(atom(RAbstractIntVector.class)).or(atom(RIntSequence.class)).or(atom(RIntVector.class)), true);
     }
 
     @Test
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/ChimneySweeping.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/ChimneySweeping.java
index 809bf71bdebc1e335c4e84b0003c4ee3940b5730..bd4a571e6d9cffc765558f12e16526f9634a202e 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/ChimneySweeping.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/ChimneySweeping.java
@@ -227,7 +227,7 @@ class ChimneySweeping extends SingleBuiltinDiagnostics {
 
         this.castNodes = builtinFactory.getCastNodes();
 
-        print(0, "\n*** Chimney-sweeping of '" + builtinName + "' (" + builtinFactory.getBuiltinNodeClass().getName() + ") ***");
+        print(0, "\n*** Chimney-sweeping of '" + builtinName + "' (" + builtinFactory.getBuiltinMetaClass().getName() + ") ***");
 
         this.validArgsList = extractValidArgsForBuiltin();
         this.argSamples = createSamples();
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/RBuiltinDiagnostics.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/RBuiltinDiagnostics.java
index 2fce7678ee125b824b806395b3ff792a41d5ca73..d506977abe0a328aba1da5c13af73c4c5ffbfb02 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/RBuiltinDiagnostics.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/RBuiltinDiagnostics.java
@@ -38,6 +38,7 @@ import java.util.Set;
 import java.util.function.Predicate;
 import java.util.stream.Collectors;
 
+import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.GeneratedBy;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.frame.Frame;
@@ -252,7 +253,7 @@ public class RBuiltinDiagnostics {
     }
 
     private static RBuiltinFactory findBuiltInFactory(Class<?> bltnCls, BasePackage bp) {
-        Optional<RBuiltinFactory> bltnFact = bp.getBuiltins().values().stream().filter(bf -> bf.getBuiltinNodeClass().isAssignableFrom(bltnCls)).findFirst();
+        Optional<RBuiltinFactory> bltnFact = bp.getBuiltins().values().stream().filter(bf -> bf.getBuiltinMetaClass().isAssignableFrom(bltnCls)).findFirst();
         if (bltnFact.isPresent()) {
             return bltnFact.get();
         } else {
@@ -359,24 +360,26 @@ public class RBuiltinDiagnostics {
         }
 
         SingleBuiltinDiagnostics init() throws Throwable {
-            String builtinClassName = builtinFactory.getBuiltinNodeClass().getName();
+            String builtinMetaClassName = builtinFactory.getBuiltinMetaClass().getName();
             // causes the invocation of the static initializer in the builtin node class
+            Class<?> bltnMetaCls = NodeWithArgumentCasts.Casts.getBuiltinClass(Class.forName(builtinMetaClassName));
+            String builtinClassName = builtinFactory.getBuiltinNodeClass().getName();
             Class<?> bltnCls = NodeWithArgumentCasts.Casts.getBuiltinClass(Class.forName(builtinClassName));
 
             try {
                 this.casts = builtinFactory.getCasts();
             } catch (RInternalError e) {
                 // It will be converted into an error after all builtins are fixed
-                throw new WarningException("Builtin " + builtinClassName + " should declare argument casts or use Casts.noCasts(" + bltnCls.getSimpleName() + ".class)");
+                throw new WarningException("Builtin " + builtinMetaClassName + " should declare argument casts or use Casts.noCasts(" + bltnMetaCls.getSimpleName() + ".class)");
             }
 
             if (this.casts == null || this.casts.declaresNoCasts()) {
-                throw new InfoException("Builtin " + builtinClassName + " has no-casts");
+                throw new InfoException("Builtin " + builtinMetaClassName + " has no-casts");
             }
 
             argResultSets = createArgResultSets();
 
-            List<Method> specs = CastUtils.getAnnotatedMethods(builtinFactory.getBuiltinNodeClass(), Specialization.class);
+            List<Method> specs = CastUtils.getAnnotatedMethods(bltnCls, Specialization.class, Fallback.class);
             this.specMethods = new ArrayList<>(specs);
             // N.B. The fallback method cannot be found by the Fallback annotation since
             // this annotation has the CLASS retention policy. Nonetheless, the fallback method can
@@ -459,7 +462,7 @@ public class RBuiltinDiagnostics {
             if (!headerPrinted && level <= diagSuite.diagConfig.outputMaxLevel) {
                 diagSuite.print(level, "\n");
                 diagSuite.print(level, "****************************************************************************");
-                diagSuite.print(level, "Builtin: " + builtinName + " (" + builtinFactory.getBuiltinNodeClass().getCanonicalName() + ")");
+                diagSuite.print(level, "Builtin: " + builtinName + " (" + builtinFactory.getBuiltinMetaClass().getCanonicalName() + ")");
                 diagSuite.print(level, "****************************************************************************");
                 headerPrinted = true;
                 diagSuite.reportedBuiltinsCounter++;
@@ -654,6 +657,8 @@ public class RBuiltinDiagnostics {
 
         Class<?> getBuiltinNodeClass();
 
+        Class<?> getBuiltinMetaClass();
+
         String[] getParameterNames();
 
         Object[] getDefaultParameterValues();
@@ -687,13 +692,18 @@ public class RBuiltinDiagnostics {
             return fact.getBuiltinNodeClass();
         }
 
+        @Override
+        public Class<?> getBuiltinMetaClass() {
+            return fact.getBuiltinMetaClass();
+        }
+
         public RBuiltinKind getBuiltinKind() {
             return fact.getKind();
         }
 
         @Override
         public String[] getParameterNames() {
-            RBuiltin annotation = fact.getBuiltinNodeClass().getAnnotation(RBuiltin.class);
+            RBuiltin annotation = fact.getBuiltinMetaClass().getAnnotation(RBuiltin.class);
             String[] pn = annotation.parameterNames();
             return Arrays.stream(pn).map(n -> n.isEmpty() ? null : n).toArray(String[]::new);
         }
@@ -705,7 +715,11 @@ public class RBuiltinDiagnostics {
 
         @Override
         public NodeWithArgumentCasts.Casts getCasts() {
-            return NodeWithArgumentCasts.Casts.getCasts(fact.getBuiltinNodeClass());
+            try {
+                return NodeWithArgumentCasts.Casts.getCasts(fact.getBuiltinMetaClass());
+            } catch (RInternalError e) {
+                return NodeWithArgumentCasts.Casts.getCasts(fact.getBuiltinNodeClass());
+            }
         }
 
         @Override
@@ -759,6 +773,11 @@ public class RBuiltinDiagnostics {
             return nodeClass;
         }
 
+        @Override
+        public Class<?> getBuiltinMetaClass() {
+            return nodeClass;
+        }
+
         @Override
         public String[] getParameterNames() {
             return parameterNames;
@@ -775,7 +794,7 @@ public class RBuiltinDiagnostics {
 
         @Override
         public NodeWithArgumentCasts.Casts getCasts() {
-            return NodeWithArgumentCasts.Casts.getCasts(getBuiltinNodeClass());
+            return NodeWithArgumentCasts.Casts.getCasts(getBuiltinMetaClass());
         }
 
         @Override
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinFactory.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinFactory.java
index 90e34ba0ecdbde856e17300a70ec6a40eea09bce..bccdcb3119d398dc1f845849cb69260d43682f20 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinFactory.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinFactory.java
@@ -36,9 +36,10 @@ public final class RBuiltinFactory extends RBuiltinDescriptor {
 
     private final Supplier<RBuiltinNode> constructor;
 
-    RBuiltinFactory(String name, Class<?> builtinNodeClass, RVisibility visibility, String[] aliases, RBuiltinKind kind, ArgumentsSignature signature, int[] nonEvalArgs, boolean splitCaller,
+    RBuiltinFactory(String name, Class<?> builtinMetaClass, Class<?> builtinNodeClass, RVisibility visibility, String[] aliases, RBuiltinKind kind, ArgumentsSignature signature, int[] nonEvalArgs,
+                    boolean splitCaller,
                     boolean alwaysSplit, RDispatch dispatch, String genericName, Supplier<RBuiltinNode> constructor, RBehavior behavior, RSpecialFactory specialCall) {
-        super(name, builtinNodeClass, visibility, aliases, kind, signature, nonEvalArgs, splitCaller, alwaysSplit, dispatch, genericName, behavior, specialCall);
+        super(name, builtinMetaClass, builtinNodeClass, visibility, aliases, kind, signature, nonEvalArgs, splitCaller, alwaysSplit, dispatch, genericName, behavior, specialCall);
         this.constructor = constructor;
     }
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/builtins/RBuiltinDescriptor.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/builtins/RBuiltinDescriptor.java
index 925e003fe787f28ce2f02cdcdd555db486ceb6ad..07ede76bbdf97724f7aa50ca9aa2e717b3d552c4 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/builtins/RBuiltinDescriptor.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/builtins/RBuiltinDescriptor.java
@@ -35,6 +35,7 @@ public abstract class RBuiltinDescriptor {
     private static int primitiveMethodCount;
 
     private final String name;
+    private final Class<?> builtinMetaClass;
     private final Class<?> builtinNodeClass;
     private final RVisibility visibility;
     private final String[] aliases;
@@ -51,10 +52,12 @@ public abstract class RBuiltinDescriptor {
     private final int primitiveMethodIndex;
     @CompilationFinal(dimensions = 1) private final boolean[] evaluatesArgument;
 
-    public RBuiltinDescriptor(String name, Class<?> builtinNodeClass, RVisibility visibility, String[] aliases, RBuiltinKind kind, ArgumentsSignature signature, int[] nonEvalArgs, boolean splitCaller,
+    public RBuiltinDescriptor(String name, Class<?> builtinMetaClass, Class<?> builtinNodeClass, RVisibility visibility, String[] aliases, RBuiltinKind kind, ArgumentsSignature signature,
+                    int[] nonEvalArgs, boolean splitCaller,
                     boolean alwaysSplit, RDispatch dispatch, String genericName, RBehavior behavior, RSpecialFactory specialCall) {
         this.specialCall = specialCall;
         this.name = name.intern();
+        this.builtinMetaClass = builtinMetaClass;
         this.builtinNodeClass = builtinNodeClass;
         this.visibility = visibility;
         this.aliases = aliases;
@@ -132,6 +135,10 @@ public abstract class RBuiltinDescriptor {
         return visibility;
     }
 
+    public Class<?> getBuiltinMetaClass() {
+        return builtinMetaClass;
+    }
+
     public Class<?> getBuiltinNodeClass() {
         return builtinNodeClass;
     }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tools/RBuiltinCheck.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tools/RBuiltinCheck.java
index 033e8eee68e2b490c38c891776c6ac0ff95ea061..bc922bc30ec184e30a7417afbb5b182ca0e4e9fe 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tools/RBuiltinCheck.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tools/RBuiltinCheck.java
@@ -269,7 +269,7 @@ public final class RBuiltinCheck {
         BasePackage base = new BasePackage();
         Map<String, BuiltinInfo> result = new TreeMap<>();
         for (Map.Entry<String, RBuiltinFactory> builtin : base.getBuiltins().entrySet()) {
-            Class<?> clazz = builtin.getValue().getBuiltinNodeClass();
+            Class<?> clazz = builtin.getValue().getBuiltinMetaClass();
             RBuiltin annotation = clazz.getAnnotation(RBuiltin.class);
             result.put(builtin.getKey(), new BuiltinInfo(
                             builtin.getValue().getVisibility(),