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 cab4934525c42ab1be917f7f54f8c255d53f9b3d..c2b3d6e9517a0b66d9dcd7016c6648ad372f41c2 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
@@ -42,6 +42,8 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.frame.Frame;
 import com.oracle.truffle.api.frame.FrameInstance.FrameAccess;
 import com.oracle.truffle.api.frame.MaterializedFrame;
+import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.api.interop.java.JavaInterop;
 import com.oracle.truffle.api.object.DynamicObject;
 import com.oracle.truffle.api.source.Source;
 import com.oracle.truffle.api.source.SourceSection;
@@ -55,6 +57,7 @@ import com.oracle.truffle.r.runtime.REnvVars;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.RErrorHandling;
+import com.oracle.truffle.r.runtime.RErrorHandling.HandlerStacks;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.RSource;
@@ -912,7 +915,12 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI {
     @Override
     @TruffleBoundary
     public Object R_ToplevelExec() {
-        return RErrorHandling.resetAndGetHandlerStacks();
+        return RErrorHandling.resetAndGetHandlerStacks().handlerStack;
+    }
+
+    @Override
+    public void restoreHandlerStacks(Object savedHandlerStack) {
+        RErrorHandling.restoreHandlerStack(savedHandlerStack);
     }
 
     @Override
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 f8a81aab1f9996222b0b2c9522cdedce03a03b1d..cfc4c80acb4c40e4c78fa2b1e01174778b679ab3 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
@@ -275,6 +275,8 @@ public interface StdUpCallsRFFI {
 
     Object R_ToplevelExec();
 
+    void restoreHandlerStacks(Object savedHandlerStack);
+
     int RDEBUG(Object x);
 
     void SET_RDEBUG(Object x, int v);
diff --git a/com.oracle.truffle.r.native/fficall/src/common/rffi_upcalls.h b/com.oracle.truffle.r.native/fficall/src/common/rffi_upcalls.h
index f7f80924ca61a74e5e53154ff4eab6cb0ddea981..e5f5f5cfdce29cb59143a704c51cfeddb6ba2d74 100644
--- a/com.oracle.truffle.r.native/fficall/src/common/rffi_upcalls.h
+++ b/com.oracle.truffle.r.native/fficall/src/common/rffi_upcalls.h
@@ -202,7 +202,8 @@ typedef void (*call_DUPLICATE_ATTRIB)(SEXP to, SEXP from);
 typedef int (*call_IS_S4_OBJECT)(SEXP x);
 typedef void (*call_SET_S4_OBJECT)(SEXP x);
 typedef void (*call_UNSET_S4_OBJECT)(SEXP x);
-typedef Rboolean (*call_R_ToplevelExec)(void (*fun)(void *), void *data);
+typedef SEXP (*call_R_ToplevelExec)();
+typedef void (*call_restoreHandlerStack)(SEXP saved_handler_stack);
 typedef void (*call_R_RestoreHashCount)(SEXP rho);
 typedef Rboolean (*call_R_IsPackageEnv)(SEXP rho);
 typedef SEXP (*call_R_PackageEnvName)(SEXP rho);
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 8008fede3e7cc374695fea9e699d25b50020fb22..cc3ddaf77801fcbcf663e28e6f02d1be12094a4f 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
@@ -173,10 +173,11 @@
 #define octsize_x 168
 #define registerCCallable_x 169
 #define registerRoutines_x 170
-#define setDotSymbolValues_x 171
-#define unif_rand_x 172
-#define useDynamicSymbols_x 173
+#define restoreHandlerStacks_x 171
+#define setDotSymbolValues_x 172
+#define unif_rand_x 173
+#define useDynamicSymbols_x 174
 
-#define UPCALLS_TABLE_SIZE 174
+#define UPCALLS_TABLE_SIZE 175
 
 #endif // RFFI_UPCALLSINDEX_H
diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_common/Rinternals_truffle_common.h b/com.oracle.truffle.r.native/fficall/src/truffle_common/Rinternals_truffle_common.h
index c69fd861ca3255694cb9b8733dc4947d5be014af..c305453c283d0c934e99e13942a7399d78aabf1d 100644
--- a/com.oracle.truffle.r.native/fficall/src/truffle_common/Rinternals_truffle_common.h
+++ b/com.oracle.truffle.r.native/fficall/src/truffle_common/Rinternals_truffle_common.h
@@ -1253,7 +1253,16 @@ void UNSET_S4_OBJECT(SEXP x) {
 
 Rboolean R_ToplevelExec(void (*fun)(void *), void *data) {
     TRACE0();
-    return (Rboolean) unimplemented("R_ToplevelExec");
+
+    // reset handler stack
+    SEXP saved_handler_stack = ((call_R_ToplevelExec) callbacks[R_ToplevelExec_x])();
+    checkExitCall();
+    fun(data);
+    ((call_restoreHandlerStack) callbacks[restoreHandlerStacks_x])(saved_handler_stack);
+    checkExitCall();
+
+    // TODO detect errors
+    return TRUE;
 }
 
 SEXP R_ExecWithCleanup(SEXP (*fun)(void *), void *data,
diff --git a/com.oracle.truffle.r.native/version.source b/com.oracle.truffle.r.native/version.source
index 9e5feb5256930f3cae636754eef8a244ede164eb..abac1ea7b759d8258c9ad9e5b450f782aaa33374 100644
--- a/com.oracle.truffle.r.native/version.source
+++ b/com.oracle.truffle.r.native/version.source
@@ -1 +1 @@
-46
+47