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 575c68930adf236a99572ec0b323f110a0106d19..c0e6de4901cceafa2019f46f0105cbbdd5a902f7 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
@@ -350,6 +350,7 @@ public class BasePackage extends RBuiltinPackage {
         add(Ls.class, LsNodeGen::create);
         add(MakeNames.class, MakeNamesNodeGen::create);
         add(MakeUnique.class, MakeUniqueNodeGen::create);
+        add(Mapply.class, MapplyNodeGen::create);
         add(MatMult.class, MatMultNodeGen::create);
         add(Match.class, MatchNodeGen::create);
         add(MatchFun.class, MatchFunNodeGen::create);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/InfixEmulationFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/InfixEmulationFunctions.java
index 80be14922b327c6e118f9c2612b01e6fd3064f99..2bed762f38e730e726beb4dee1ef0975af53899e 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/InfixEmulationFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/InfixEmulationFunctions.java
@@ -387,6 +387,8 @@ public class InfixEmulationFunctions {
 
         private static final String NAME = "[[";
 
+        public abstract Object execute(VirtualFrame frame, RAbstractContainer x, RArgsValuesAndNames inds, RAbstractLogicalVector exactVec, RAbstractLogicalVector dropVec);
+
         @Child private UseMethodInternalNode dcn;
 
         @Override
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Mapply.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Mapply.java
new file mode 100644
index 0000000000000000000000000000000000000000..5dd5f43d3f214c415e244bd841ed78eb64941144
--- /dev/null
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Mapply.java
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 2015, 2015, 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.base;
+
+import static com.oracle.truffle.r.runtime.RBuiltinKind.*;
+
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.r.nodes.*;
+import com.oracle.truffle.r.nodes.access.*;
+import com.oracle.truffle.r.nodes.access.WriteVariableNode.Mode;
+import com.oracle.truffle.r.nodes.access.variables.*;
+import com.oracle.truffle.r.nodes.builtin.*;
+import com.oracle.truffle.r.nodes.builtin.base.InfixEmulationFunctions.AccessArraySubscriptBuiltin;
+import com.oracle.truffle.r.nodes.builtin.base.MapplyNodeGen.MapplyInternalNodeGen;
+import com.oracle.truffle.r.nodes.function.*;
+import com.oracle.truffle.r.runtime.*;
+import com.oracle.truffle.r.runtime.data.*;
+import com.oracle.truffle.r.runtime.data.model.*;
+
+/**
+ * Multivariate lapply. Essentially invokes
+ * {@code fun(dots[0][X], dots[1][X], , dots[N][X], MoreArgs)} for {@code X=1..M} where {@code M} is
+ * the longest vector, with the usual recycling rule.
+ */
+@RBuiltin(name = "mapply", kind = INTERNAL, parameterNames = {"FUN", "dots", "MoreArgs"}, splitCaller = true)
+public abstract class Mapply extends RBuiltinNode {
+
+    protected static class ElementNode extends Node {
+        @Child Length lengthNode;
+        @Child AccessArraySubscriptBuiltin indexedLoadNode;
+        @Child WriteVariableNode writeVectorElementNode;
+        private final String vectorElementName;
+
+        ElementNode(String vectorElementName) {
+            this.vectorElementName = AnonymousFrameVariable.create(vectorElementName);
+            this.lengthNode = insert(LengthNodeGen.create(null, null, null));
+            this.indexedLoadNode = insert(InfixEmulationFunctionsFactory.AccessArraySubscriptBuiltinNodeGen.create(null, null, null));
+            this.writeVectorElementNode = insert(WriteVariableNode.createAnonymous(this.vectorElementName, null, Mode.REGULAR));
+        }
+    }
+
+    @Child private MapplyInternalNode mapply = MapplyInternalNodeGen.create(null, null, null);
+
+    @Specialization
+    protected Object mApply(VirtualFrame frame, RFunction fun, RList dots, RList moreArgs) {
+        if (moreArgs.getLength() > 0) {
+            throw RError.nyi(getEncapsulatingSourceSection(), "moreArgs");
+        }
+        Object[] result = mapply.execute(frame, dots, fun, moreArgs);
+        // set here else it gets overridden by the iterator evaluation
+        controlVisibility();
+        return RDataFactory.createList(result);
+    }
+
+    @SuppressWarnings("unused")
+    @Specialization
+    protected Object mApply(VirtualFrame frame, RFunction fun, RList dots, RNull moreArgs) {
+        return mApply(frame, fun, dots, RDataFactory.createList());
+    }
+
+    @NodeChildren({@NodeChild(type = RNode.class), @NodeChild(type = RNode.class), @NodeChild(type = RNode.class)})
+    protected abstract static class MapplyInternalNode extends RNode {
+
+        private static final String VECTOR_ELEMENT_PREFIX = "MAPPLY_VEC_ELEM_";
+        private static final RLogicalVector DROP = RDataFactory.createLogicalVectorFromScalar(true);
+        private static final RLogicalVector EXACT = RDataFactory.createLogicalVectorFromScalar(true);
+        private static final ArgumentsSignature I_INDEX = ArgumentsSignature.get("i");
+        private static final RArgsValuesAndNames[] INDEX_CACHE = new RArgsValuesAndNames[32];
+
+        static {
+            for (int i = 0; i < INDEX_CACHE.length; i++) {
+                INDEX_CACHE[i] = new RArgsValuesAndNames(new Object[]{i + 1}, I_INDEX);
+            }
+        }
+
+        public abstract Object[] execute(VirtualFrame frame, RList dots, RFunction function, RList additionalArguments);
+
+        @SuppressWarnings("unused")
+        @Specialization(limit = "5", guards = {"function.getTarget() == cachedTarget"})
+        protected Object[] cachedMApply(VirtualFrame frame, RList dots, RFunction function, RList moreArgs, @Cached("function.getTarget()") RootCallTarget cachedTarget,
+                        @Cached("createElementNodeArray(dots.getLength())") ElementNode[] cachedElementNodeArray,
+                        @Cached("createCallNode(cachedTarget, cachedElementNodeArray, moreArgs)") RCallNode callNode) {
+
+            int dotsLength = dots.getLength();
+            int[] lengths = new int[dotsLength];
+            int maxLength = -1;
+            for (int i = 0; i < dotsLength; i++) {
+                int length = cachedElementNodeArray[i].lengthNode.executeInt(frame, dots.getDataAt(i));
+                if (length > maxLength) {
+                    maxLength = length;
+                }
+                lengths[i] = length;
+            }
+            Object[] result = new Object[maxLength];
+            for (int i = 0; i < maxLength; i++) {
+                /* Evaluate and store the arguments */
+                for (int listIndex = 0; listIndex < dotsLength; listIndex++) {
+                    RAbstractContainer vec = (RAbstractContainer) dots.getDataAt(listIndex);
+                    int adjIndex = i % lengths[listIndex];
+                    RArgsValuesAndNames indexArg;
+                    if (adjIndex < INDEX_CACHE.length) {
+                        indexArg = INDEX_CACHE[adjIndex];
+                    } else {
+                        indexArg = new RArgsValuesAndNames(new Object[]{adjIndex + 1}, I_INDEX);
+                    }
+                    Object vecElement = cachedElementNodeArray[listIndex].indexedLoadNode.execute(frame, vec, indexArg, EXACT, DROP);
+                    cachedElementNodeArray[listIndex].writeVectorElementNode.execute(frame, vecElement);
+                }
+                /* Now call the function */
+                result[i] = callNode.execute(frame, function);
+            }
+            return result;
+        }
+
+        @SuppressWarnings("unused")
+        @Specialization(contains = "cachedMApply")
+        protected Object[] genericLApply(Object vector, RFunction function, RArgsValuesAndNames additionalArguments) {
+            throw RError.nyi(getSourceSection(), "generic mApply");
+        }
+
+        /**
+         * Creates the {@link RCallNode} for this target.
+         *
+         * TODO names and moreArgs
+         *
+         */
+        protected RCallNode createCallNode(RootCallTarget callTarget, ElementNode[] elementNodeArray, @SuppressWarnings("unused") RList moreArgs) {
+            @SuppressWarnings("unused")
+            FormalArguments formalArgs = ((RRootNode) callTarget.getRootNode()).getFormalArguments();
+
+            ReadVariableNode[] readVectorElementNodes = new ReadVariableNode[elementNodeArray.length];
+            for (int i = 0; i < readVectorElementNodes.length; i++) {
+                readVectorElementNodes[i] = ReadVariableNode.create(elementNodeArray[i].vectorElementName, false);
+            }
+            CallArgumentsNode argsNode = CallArgumentsNode.create(false, false, readVectorElementNodes, ArgumentsSignature.empty(readVectorElementNodes.length));
+            return RCallNode.createCall(null, null, argsNode, null);
+        }
+
+        protected ElementNode[] createElementNodeArray(int length) {
+            ElementNode[] elementNodes = new ElementNode[length];
+            for (int i = 0; i < length; i++) {
+                elementNodes[i] = insert(new ElementNode(VECTOR_ELEMENT_PREFIX + (i + 1)));
+            }
+            return elementNodes;
+        }
+    }
+
+}
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test
index cc9bab4b2ebd28ab9e5ebf5b4e037c9a54c99a4d..29ca14194082742d01518461ffb3adf9ba57348d 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test
@@ -26353,6 +26353,58 @@ character(0)
 #argv <- list(character(0), '.'); .Internal(make.unique(argv[[1]], argv[[2]]))
 character(0)
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_mapply.testmapply
+#mapply(function(x, y) seq_len(x) + y, c(a =  1, b = 2, c = 3),  c(A = 10, B = 0, C = -10))
+$a
+[1] 11
+
+$b
+[1] 1 2
+
+$c
+[1] -9 -8 -7
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_mapply.testmapply
+#mapply(rep, 1:4, 4:1)
+[[1]]
+[1] 1 1 1 1
+
+[[2]]
+[1] 2 2 2
+
+[[3]]
+[1] 3 3
+
+[[4]]
+[1] 4
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_mapply.testmapply
+#mapply(rep, times = 1:4, MoreArgs = list(x = 42))
+[[1]]
+[1] 42
+
+[[2]]
+[1] 42 42
+
+[[3]]
+[1] 42 42 42
+
+[[4]]
+[1] 42 42 42 42
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_mapply.testmapply
+#word <- function(C, k) paste(rep.int(C, k), collapse = ""); utils::str(mapply(word, LETTERS[1:6], 6:1, SIMPLIFY = FALSE))
+List of 6
+ $ A: chr "AAAAAA"
+ $ B: chr "BBBBB"
+ $ C: chr "CCCC"
+ $ D: chr "DDD"
+ $ E: chr "EE"
+ $ F: chr "F"
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_mapply.testmapply1
 #argv <- list(.Primitive('c'), list(list(), list(), list()), NULL); .Internal(mapply(argv[[1]], argv[[2]], argv[[3]]))
 list()
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_mapply.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_mapply.java
index dc9fe1d106ed218fe233227a106456b60bd56e58..9322ed77c87c16dbf8a8265c4b4915fde3a8fecc 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_mapply.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_mapply.java
@@ -19,6 +19,14 @@ public class TestBuiltin_mapply extends TestBase {
 
     @Test
     public void testmapply1() {
-        assertEval(Ignored.Unknown, "argv <- list(.Primitive('c'), list(list(), list(), list()), NULL); .Internal(mapply(argv[[1]], argv[[2]], argv[[3]]))");
+        assertEval("argv <- list(.Primitive('c'), list(list(), list(), list()), NULL); .Internal(mapply(argv[[1]], argv[[2]], argv[[3]]))");
+    }
+
+    @Test
+    public void testmapply() {
+        assertEval("mapply(rep, 1:4, 4:1)");
+        assertEval("mapply(function(x, y) seq_len(x) + y, c(a =  1, b = 2, c = 3),  c(A = 10, B = 0, C = -10))");
+        assertEval(Ignored.Unimplemented, "mapply(rep, times = 1:4, MoreArgs = list(x = 42))");
+        assertEval(Ignored.Unimplemented, "word <- function(C, k) paste(rep.int(C, k), collapse = \"\"); utils::str(mapply(word, LETTERS[1:6], 6:1, SIMPLIFY = FALSE))");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rpackages/TestRPackages.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rpackages/TestRPackages.java
index 67b6c651ae858311d125aa54ab9fdf59adb04791..8d68f81b8da76100083ca92870bb53b9161d4fac 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rpackages/TestRPackages.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rpackages/TestRPackages.java
@@ -66,17 +66,13 @@ public class TestRPackages extends TestBase {
 
         private boolean installPackage(String packageName) {
             Path packagePath = rpackagesDists.resolve(packageName).resolve("lib").resolve(packageName + ".tar");
-            String[] cmds;
+            String[] cmds = new String[4];
             if (generatingExpected()) {
                 // use GnuR
-                cmds = new String[4];
                 cmds[0] = "R";
             } else {
                 // use FastR
-                cmds = new String[5];
                 cmds[0] = FileSystems.getDefault().getPath(REnvVars.rHome(), "bin", "R").toString();
-                // TODO remove --no-help limitation when markdown parser functioning
-                cmds[3] = "--no-help";
             }
             cmds[1] = "CMD";
             cmds[2] = "INSTALL";