diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RArgsValuesAndNamesMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RArgsValuesAndNamesMR.java
index 9e60cc21fd4caeab36ffe79306617ecc27d1c8ea..2ee572ca4c6ee226ad4f84b4165a4976ce428747 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RArgsValuesAndNamesMR.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RArgsValuesAndNamesMR.java
@@ -71,7 +71,12 @@ public class RArgsValuesAndNamesMR {
     @Resolve(message = "KEYS")
     public abstract static class RArgsValuesAndNamesKeysNode extends Node {
         protected Object access(RArgsValuesAndNames receiver) {
-            return RDataFactory.createStringVector(receiver.getSignature().getNames(), RDataFactory.COMPLETE_VECTOR);
+            ArgumentsSignature signature = receiver.getSignature();
+            String[] names = signature.getNames();
+            if (names == null) {
+                return RDataFactory.createStringVector(new String[signature.getLength()], RDataFactory.COMPLETE_VECTOR);
+            }
+            return RDataFactory.createStringVector(names, RDataFactory.COMPLETE_VECTOR).makeSharedPermanent();
         }
     }
 
@@ -112,6 +117,10 @@ public class RArgsValuesAndNamesMR {
         protected Object access(RArgsValuesAndNames receiver, String identifier) {
             ArgumentsSignature sig = receiver.getSignature();
             String[] names = sig.getNames();
+            if (names == null) {
+                throw UnknownIdentifierException.raise("" + identifier);
+            }
+
             int idx = -1;
             for (int i = 0; i < names.length; i++) {
                 if (names[i].equals(identifier)) {
@@ -150,6 +159,9 @@ public class RArgsValuesAndNamesMR {
         protected Object access(RArgsValuesAndNames receiver, String identifier) {
             ArgumentsSignature sig = receiver.getSignature();
             String[] names = sig.getNames();
+            if (names == null) {
+                return 0;
+            }
             int idx = -1;
             for (int i = 0; i < names.length; i++) {
                 if (names[i].equals(identifier)) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/FortranAndCFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/FortranAndCFunctions.java
index 7fd4ccfd8cf47d00c8c5de672a6d7075b7954e36..9fdfeb7214524061323e7a79b66264f6bdb34de4 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/FortranAndCFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/FortranAndCFunctions.java
@@ -16,6 +16,7 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
 import java.nio.charset.Charset;
 import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
 
 import com.oracle.truffle.api.CompilerAsserts;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
@@ -331,12 +332,16 @@ public class FortranAndCFunctions {
                 namesProfile.enter();
                 String[] argNames = sig.getNames();
                 String[] names = new String[sig.getLength()];
-                for (int i = 0; i < sig.getLength(); i++) {
-                    String argName = argNames[i];
-                    if (argName == null) {
-                        names[i] = "";
-                    } else {
-                        names[i] = argName;
+                if (argNames == null) {
+                    Arrays.fill(names, "");
+                } else {
+                    for (int i = 0; i < sig.getLength(); i++) {
+                        String argName = argNames[i];
+                        if (argName == null) {
+                            names[i] = "";
+                        } else {
+                            names[i] = argName;
+                        }
                     }
                 }
                 namesSetter.execute(result, RDataFactory.createStringVector(names, true));
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ArgumentsSignature.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ArgumentsSignature.java
index ae22e9d513dfb264e7b2d91fd4d0bbdf6d7afa11..ecd287b87b5bdf9a1c120d634bc935e074af3c8c 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ArgumentsSignature.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ArgumentsSignature.java
@@ -45,6 +45,7 @@ public final class ArgumentsSignature implements Iterable<String> {
      */
     public static final String UNMATCHED = new String();
     public static final String VARARG_NAME = "...";
+    public static final int[] EMPTY_VARARGS_INDEXES = new int[0];
     public static final int NO_VARARG = -1;
 
     @CompilationFinal(dimensions = 1) private static final ArgumentsSignature[] EMPTY_SIGNATURES = new ArgumentsSignature[32];
@@ -89,46 +90,58 @@ public final class ArgumentsSignature implements Iterable<String> {
     @CompilationFinal(dimensions = 1) private final String[] names;
     @CompilationFinal(dimensions = 1) private final int[] varArgIndexes;
     @CompilationFinal(dimensions = 1) private final boolean[] isVarArg;
+    private final int length;
     private final int varArgIndex;
     private final int nonNullCount;
 
     private ArgumentsSignature(String[] names, boolean convertEmpty) {
-        this.names = new String[names.length];
+        this.length = names.length;
+        String[] localNames = null;
         int nonNull = 0;
         for (int i = 0; i < names.length; i++) {
             String s = names[i];
             if (s == null || (s.isEmpty() && convertEmpty)) {
-                this.names[i] = null;
                 continue;
+            } else if (localNames == null) {
+                localNames = new String[names.length];
             }
             nonNull++;
-            this.names[i] = s == UNMATCHED ? s : s.intern();
+            localNames[i] = s == UNMATCHED ? s : s.intern();
         }
+        this.names = localNames;
         this.nonNullCount = nonNull;
 
-        int index = NO_VARARG;
-        int count = 0;
-        this.isVarArg = new boolean[names.length];
-        for (int i = 0; i < names.length; i++) {
-            String name = names[i];
-            if (name != null) {
-                if (VARARG_NAME.equals(name)) {
-                    this.isVarArg[i] = true;
-                    count++;
-                    if (index != NO_VARARG) {
-                        index = i;
+        int varArgsCount = 0;
+        boolean[] isVarArgsLocal = null;
+        if (localNames != null) {
+            for (int i = 0; i < names.length; i++) {
+                String name = names[i];
+                if (name != null) {
+                    if (VARARG_NAME.equals(name)) {
+                        if (isVarArgsLocal == null) {
+                            isVarArgsLocal = new boolean[names.length];
+                        }
+                        isVarArgsLocal[i] = true;
+                        varArgsCount++;
                     }
                 }
             }
         }
-        int pos = 0;
-        this.varArgIndexes = new int[count];
-        for (int i = 0; i < names.length; i++) {
-            if (isVarArg[i]) {
-                varArgIndexes[pos++] = i;
+        this.isVarArg = isVarArgsLocal;
+
+        if (isVarArgsLocal == null) {
+            this.varArgIndexes = EMPTY_VARARGS_INDEXES;
+            this.varArgIndex = NO_VARARG;
+        } else {
+            int pos = 0;
+            this.varArgIndexes = new int[varArgsCount];
+            for (int i = 0; i < names.length; i++) {
+                if (isVarArgsLocal[i]) {
+                    varArgIndexes[pos++] = i;
+                }
             }
+            this.varArgIndex = varArgIndexes[0];
         }
-        this.varArgIndex = varArgIndexes.length == 0 ? NO_VARARG : varArgIndexes[0];
     }
 
     public boolean isEmpty() {
@@ -136,7 +149,7 @@ public final class ArgumentsSignature implements Iterable<String> {
     }
 
     public int getLength() {
-        return names.length;
+        return length;
     }
 
     public int getNonNullCount() {
@@ -157,6 +170,9 @@ public final class ArgumentsSignature implements Iterable<String> {
     }
 
     public String getName(int index) {
+        if (names == null) {
+            return null;
+        }
         return names[index] == UNMATCHED ? null : names[index];
     }
 
@@ -169,11 +185,11 @@ public final class ArgumentsSignature implements Iterable<String> {
      * {@link #getName(int)} returns {@code null} in either case.
      */
     public boolean isUnmatched(int index) {
-        return names[index] == UNMATCHED;
+        return names != null && names[index] == UNMATCHED;
     }
 
     public boolean isVarArg(int index) {
-        return this.isVarArg[index];
+        return this.isVarArg != null && this.isVarArg[index];
     }
 
     /**
@@ -181,6 +197,9 @@ public final class ArgumentsSignature implements Iterable<String> {
      * interned string.
      */
     public int indexOfName(String find) {
+        if (names == null) {
+            return -1;
+        }
         for (int i = 0; i < names.length; i++) {
             if (names[i] == find) {
                 return i;
@@ -191,7 +210,7 @@ public final class ArgumentsSignature implements Iterable<String> {
 
     @Override
     public int hashCode() {
-        return Arrays.hashCode(names);
+        return Arrays.hashCode(names) ^ length;
     }
 
     @Override
@@ -212,11 +231,13 @@ public final class ArgumentsSignature implements Iterable<String> {
     @Override
     public Iterator<String> iterator() {
         CompilerAsserts.neverPartOfCompilation();
-        return Arrays.asList(names).iterator();
+        String[] namesLocal = names == null ? new String[length] : names;
+        return Arrays.asList(namesLocal).iterator();
     }
 
     @Override
     public String toString() {
-        return "Signature " + Arrays.toString(names);
+        String value = names == null ? length + " times null" : Arrays.toString(names);
+        return "Signature " + value;
     }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/RScope.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/RScope.java
index 3d0ebeeded4794001e641a87ef5fb5bd729c9423..24685419efb0e382b59e3599281dfcabb4d94d6e 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/RScope.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/RScope.java
@@ -292,11 +292,14 @@ public final class RScope extends AbstractScope {
                 assert RArguments.isRFrame(env.getFrame());
                 RFunction f = RArguments.getFunction(env.getFrame());
                 if (f != null) {
-                    return RContext.getRRuntimeASTAccess().getArgumentsSignature(f).getNames();
+                    ArgumentsSignature signature = RContext.getRRuntimeASTAccess().getArgumentsSignature(f);
+                    String[] names = signature.getNames();
+                    return names == null ? new String[signature.getLength()] : names;
                 } else {
                     ArgumentsSignature suppliedSignature = RArguments.getSuppliedSignature(env.getFrame());
                     if (suppliedSignature != null) {
-                        return suppliedSignature.getNames();
+                        String[] names = suppliedSignature.getNames();
+                        return names == null ? new String[suppliedSignature.getLength()] : names;
                     }
                 }
             }