From 495ba3d286665b02221b3ae15dc1340e3f3136b1 Mon Sep 17 00:00:00 2001 From: Tomas Stupka <tomas.stupka@oracle.com> Date: Tue, 23 Jan 2018 20:11:28 +0100 Subject: [PATCH] handle guest language exceptions in interop calls --- .../r/nodes/builtin/base/BasePackage.java | 15 ++- .../r/nodes/builtin/fastr/FastRInterop.java | 97 +++++++++++++++++-- .../{FastRTry.java => FastRTestsTry.java} | 18 ++-- .../function/FunctionDefinitionNode.java | 6 +- .../truffle/r/nodes/function/RCallNode.java | 5 +- .../com/oracle/truffle/r/runtime/RError.java | 24 +++++ .../truffle/r/runtime/context/RContext.java | 5 +- .../interop/FastRInteropTryException.java | 39 ++++++++ .../interop/FastrInteropTryContextState.java | 57 +++++++++++ 9 files changed, 245 insertions(+), 21 deletions(-) rename com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/{FastRTry.java => FastRTestsTry.java} (86%) create mode 100644 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/interop/FastRInteropTryException.java create mode 100644 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/interop/FastrInteropTryContextState.java 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 e08c08bf7d..0a3cf0343b 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 @@ -108,7 +108,13 @@ import com.oracle.truffle.r.nodes.builtin.fastr.FastRIdentityNodeGen; import com.oracle.truffle.r.nodes.builtin.fastr.FastRInspect; import com.oracle.truffle.r.nodes.builtin.fastr.FastRInspectNodeGen; import com.oracle.truffle.r.nodes.builtin.fastr.FastRInterop; +import com.oracle.truffle.r.nodes.builtin.fastr.FastRInterop.FastRInteropClearException; +import com.oracle.truffle.r.nodes.builtin.fastr.FastRInterop.FastRInteropGetException; +import com.oracle.truffle.r.nodes.builtin.fastr.FastRInterop.FastRInteropTry; import com.oracle.truffle.r.nodes.builtin.fastr.FastRInteropFactory; +import com.oracle.truffle.r.nodes.builtin.fastr.FastRInteropFactory.FastRInteropClearExceptionNodeGen; +import com.oracle.truffle.r.nodes.builtin.fastr.FastRInteropFactory.FastRInteropGetExceptionNodeGen; +import com.oracle.truffle.r.nodes.builtin.fastr.FastRInteropFactory.FastRInteropTryNodeGen; import com.oracle.truffle.r.nodes.builtin.fastr.FastRLibPaths; import com.oracle.truffle.r.nodes.builtin.fastr.FastRLibPathsNodeGen; import com.oracle.truffle.r.nodes.builtin.fastr.FastROptionBuiltin; @@ -132,8 +138,8 @@ import com.oracle.truffle.r.nodes.builtin.fastr.FastRTree; import com.oracle.truffle.r.nodes.builtin.fastr.FastRTreeNodeGen; import com.oracle.truffle.r.nodes.builtin.fastr.FastRTreeStats; import com.oracle.truffle.r.nodes.builtin.fastr.FastRTreeStatsNodeGen; -import com.oracle.truffle.r.nodes.builtin.fastr.FastRTry; -import com.oracle.truffle.r.nodes.builtin.fastr.FastRTryNodeGen; +import com.oracle.truffle.r.nodes.builtin.fastr.FastRTestsTry; +import com.oracle.truffle.r.nodes.builtin.fastr.FastRTestsTryNodeGen; import com.oracle.truffle.r.nodes.builtin.fastr.FastrDqrls; import com.oracle.truffle.r.nodes.builtin.fastr.FastrDqrlsNodeGen; import com.oracle.truffle.r.nodes.builtin.fastr.memprof.FastRprofmem; @@ -437,7 +443,10 @@ public class BasePackage extends RBuiltinPackage { add(FastRHelpRd.class, FastRHelpRdNodeGen::create); add(FastRIdentity.class, FastRIdentityNodeGen::create); add(FastROptionBuiltin.class, FastROptionBuiltin::create); - add(FastRTry.class, FastRTryNodeGen::create); + add(FastRTestsTry.class, FastRTestsTryNodeGen::create); + add(FastRInteropTry.class, FastRInteropTryNodeGen::create); + add(FastRInteropGetException.class, FastRInteropGetExceptionNodeGen::create); + add(FastRInteropClearException.class, FastRInteropClearExceptionNodeGen::create); add(FastRInspect.class, FastRInspectNodeGen::create); add(FastRInterop.Eval.class, FastRInteropFactory.EvalNodeGen::create); add(FastRInterop.Export.class, FastRInteropFactory.ExportNodeGen::create); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRInterop.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRInterop.java index 8148f31c79..300ec8e7de 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRInterop.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRInterop.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2018, 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 @@ -24,18 +24,14 @@ package com.oracle.truffle.r.nodes.builtin.fastr; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.doubleValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.integerValue; -import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.logicalValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.notLogicalNA; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.rawValue; -import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.singleElement; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.typeName; import static com.oracle.truffle.r.runtime.RVisibility.CUSTOM; import static com.oracle.truffle.r.runtime.RVisibility.OFF; import static com.oracle.truffle.r.runtime.RVisibility.ON; -import static com.oracle.truffle.r.runtime.builtins.RBehavior.COMPLEX; -import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; import java.io.File; import java.io.IOException; @@ -47,6 +43,7 @@ import com.oracle.truffle.api.CompilerAsserts; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.Truffle; +import com.oracle.truffle.api.TruffleException; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Fallback; import com.oracle.truffle.api.dsl.ImportStatic; @@ -66,16 +63,25 @@ import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.api.source.Source; import com.oracle.truffle.api.source.Source.Builder; import com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.instanceOf; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.logicalValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.singleElement; +import com.oracle.truffle.r.nodes.builtin.NodeWithArgumentCasts; import com.oracle.truffle.r.nodes.builtin.NodeWithArgumentCasts.Casts; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; +import com.oracle.truffle.r.nodes.function.call.RExplicitCallNode; import com.oracle.truffle.r.nodes.function.visibility.SetVisibilityNode; import com.oracle.truffle.r.runtime.RError; +import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.RSource; +import static com.oracle.truffle.r.runtime.builtins.RBehavior.COMPLEX; import com.oracle.truffle.r.runtime.builtins.RBuiltin; +import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; import com.oracle.truffle.r.runtime.data.RDataFactory; +import com.oracle.truffle.r.runtime.data.RFunction; import com.oracle.truffle.r.runtime.data.RInteropScalar; import com.oracle.truffle.r.runtime.data.RInteropScalar.RInteropByte; import com.oracle.truffle.r.runtime.data.RInteropScalar.RInteropChar; @@ -94,6 +100,8 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; import com.oracle.truffle.r.runtime.data.nodes.GetReadonlyData; +import com.oracle.truffle.r.runtime.interop.FastRInteropTryException; +import com.oracle.truffle.r.runtime.interop.FastrInteropTryContextState; import com.oracle.truffle.r.runtime.interop.Foreign2R; import com.oracle.truffle.r.runtime.interop.ForeignArray2R; import com.oracle.truffle.r.runtime.interop.R2Foreign; @@ -610,7 +618,7 @@ public class FastRInterop { static { Casts casts = new Casts(ToJavaArray.class); - casts.arg("x").mustNotBeMissing(); + casts.arg("x").castForeignObjects(false).mustNotBeMissing(); casts.arg("className").allowMissing().mustBe(stringValue()).asStringVector().mustBe(Predef.singleElement()).findFirst(); casts.arg("flat").mapMissing(Predef.constant(RRuntime.LOGICAL_TRUE)).mustBe(logicalValue().or(Predef.nullValue())).asLogicalVector().mustBe(singleElement()).findFirst().mustBe( notLogicalNA()).map(Predef.toBoolean()); @@ -846,6 +854,8 @@ public class FastRInterop { } catch (IllegalStateException | SecurityException | IllegalArgumentException | UnsupportedTypeException | ArityException | UnsupportedMessageException e) { String msg = isTesting ? "error during Java object instantiation" : "error during Java object instantiation: " + e.getMessage(); throw error(RError.Message.GENERIC, msg); + } catch (RuntimeException e) { + throw RError.handleInteropException(this, e, clazz); } } @@ -948,4 +958,79 @@ public class FastRInterop { } } + @RBuiltin(name = ".fastr.interop.try", kind = PRIMITIVE, parameterNames = {"function", "check"}, behavior = COMPLEX) + public abstract static class FastRInteropTry extends RBuiltinNode.Arg2 { + @Node.Child private RExplicitCallNode call = RExplicitCallNode.create(); + + static { + Casts casts = new Casts(FastRInteropTry.class); + casts.arg("function").mustBe(instanceOf(RFunction.class)); + casts.arg("check").mustBe(logicalValue()).asLogicalVector().mustBe(singleElement()).findFirst(); + } + + @Specialization + public Object tryFunc(VirtualFrame frame, RFunction function, byte check) { + boolean isCheck = RRuntime.fromLogical(check); + getInteropTryState().stepIn(); + try { + return call.execute(frame, function, RArgsValuesAndNames.EMPTY); + } catch (FastRInteropTryException e) { + Throwable cause = e.getCause(); + CompilerDirectives.transferToInterpreter(); + if (cause instanceof TruffleException) { + cause = cause.getCause(); + if (isCheck) { + String causeName = cause.getClass().getName(); + String msg = cause.getMessage(); + msg = msg != null ? String.format("%s: %s", causeName, msg) : causeName; + throw RError.error(RError.SHOW_CALLER, RError.Message.GENERIC, msg); + } else { + getInteropTryState().lastException = cause; + } + } else { + RInternalError.reportError(e); + } + } finally { + getInteropTryState().stepOut(); + } + return RNull.instance; + } + + } + + @RBuiltin(name = ".fastr.interop.getTryException", kind = PRIMITIVE, parameterNames = {"clear"}, behavior = COMPLEX) + public abstract static class FastRInteropGetException extends RBuiltinNode.Arg1 { + static { + Casts casts = new Casts(FastRInteropGetException.class); + casts.arg("clear").mustBe(logicalValue()).asLogicalVector().mustBe(singleElement()).findFirst(); + } + + @Specialization + public Object getException(byte clear) { + Throwable ret = getInteropTryState().lastException; + if (RRuntime.fromLogical(clear)) { + getInteropTryState().lastException = null; + } + return ret != null ? JavaInterop.asTruffleObject(ret) : RNull.instance; + } + } + + @RBuiltin(name = ".fastr.interop.clearTryException", kind = PRIMITIVE, parameterNames = {}, behavior = COMPLEX) + public abstract static class FastRInteropClearException extends RBuiltinNode.Arg0 { + + static { + NodeWithArgumentCasts.Casts.noCasts(FastRInteropClearException.class); + } + + @Specialization + public Object clearException() { + getInteropTryState().lastException = null; + return RNull.instance; + } + } + + private static FastrInteropTryContextState getInteropTryState() { + return RContext.getInstance().stateInteropTry; + } + } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRTry.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRTestsTry.java similarity index 86% rename from com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRTry.java rename to com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRTestsTry.java index 1fb8fe48ae..7b7a63ecee 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRTry.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRTestsTry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2018, 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 @@ -22,18 +22,16 @@ */ package com.oracle.truffle.r.nodes.builtin.fastr; -import static com.oracle.truffle.r.runtime.builtins.RBehavior.COMPLEX; -import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; - import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.function.call.RExplicitCallNode; import com.oracle.truffle.r.runtime.RErrorHandling; -import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.RRuntime; +import static com.oracle.truffle.r.runtime.builtins.RBehavior.COMPLEX; import com.oracle.truffle.r.runtime.builtins.RBuiltin; +import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; import com.oracle.truffle.r.runtime.data.RFunction; @@ -41,13 +39,17 @@ import com.oracle.truffle.r.runtime.data.RFunction; * Allows to be 100% robust even in the case of FastR errors like runtime exceptions. The argument * must be a single parameter-less function. The return value is true on success, otherwise error * message. + * <p> + * <b>WARNING: For use in tests only! </b><br> + * There is no guarantee that after an error the internal FastR state will stay consistent. + * </p> */ -@RBuiltin(name = ".fastr.try", kind = PRIMITIVE, parameterNames = {""}, behavior = COMPLEX) -public abstract class FastRTry extends RBuiltinNode.Arg1 { +@RBuiltin(name = ".fastr.tests.try", kind = PRIMITIVE, parameterNames = {""}, behavior = COMPLEX) +public abstract class FastRTestsTry extends RBuiltinNode.Arg1 { @Child private RExplicitCallNode call = RExplicitCallNode.create(); static { - Casts.noCasts(FastRTry.class); + Casts.noCasts(FastRTestsTry.class); } @Specialization diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/FunctionDefinitionNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/FunctionDefinitionNode.java index 39fa33fc40..8001fc0100 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/FunctionDefinitionNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/FunctionDefinitionNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2018, 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 @@ -76,6 +76,7 @@ import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.RPairList; import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor; import com.oracle.truffle.r.runtime.env.frame.RFrameSlot; +import com.oracle.truffle.r.runtime.interop.FastRInteropTryException; import com.oracle.truffle.r.runtime.nodes.RCodeBuilder; import com.oracle.truffle.r.runtime.nodes.RNode; import com.oracle.truffle.r.runtime.nodes.RSyntaxCall; @@ -319,6 +320,9 @@ public final class FunctionDefinitionNode extends RRootNode implements RSyntaxNo CompilerDirectives.transferToInterpreter(); runOnExitHandlers = false; throw e; + } catch (FastRInteropTryException e) { + CompilerDirectives.transferToInterpreter(); + throw e; } catch (Throwable e) { CompilerDirectives.transferToInterpreter(); runOnExitHandlers = false; diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java index 523058ffd6..8fd61c7ef5 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2018, 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 @@ -31,7 +31,6 @@ import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.RootCallTarget; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Fallback; import com.oracle.truffle.api.dsl.NodeChild; @@ -641,6 +640,8 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS CompilerDirectives.transferToInterpreter(); RInternalError.reportError(e); throw RError.interopError(RError.findParentRBase(this), e, function); + } catch (RuntimeException e) { + throw RError.handleInteropException(this, e, function); } } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java index 3e62bfa253..26cb1c5f0f 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java @@ -23,7 +23,9 @@ import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.source.SourceSection; import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.builtins.RBuiltinKind; +import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.env.REnvironment.PutException; +import com.oracle.truffle.r.runtime.interop.FastRInteropTryException; import com.oracle.truffle.r.runtime.nodes.RBaseNode; import com.oracle.truffle.r.runtime.nodes.RSyntaxNode; @@ -189,6 +191,28 @@ public final class RError extends RuntimeException implements TruffleException { throw error0(node, RError.Message.GENERIC, "Foreign function failed: " + (e.getMessage() != null ? e.getMessage() : e.toString()) + " on object " + o); } + @TruffleBoundary + public static RError handleInteropException(Node node, RuntimeException e, TruffleObject o) { + if (e instanceof TruffleException) { + if (RContext.getInstance().stateInteropTry.isInTry()) { + // will be catched and handled in .fastr.interop.try builtin + throw new FastRInteropTryException(e); + } else { + Throwable cause = e.getCause(); + // TODO + // - e.getCause() seems to work for java, but how to inspect guest lang exceptions + // - stacktrace in log or console? + // Object eo = ((TruffleException) e).getExceptionObject() ? + + String clsName = cause.getClass().getName(); + String msg = cause.getMessage(); + msg = msg != null ? String.format("Foreign function failed: %s: %s", clsName, msg) : String.format("Foreign function failed: %s", clsName); + throw RError.error(findParentRBase(node), RError.Message.GENERIC, msg); + } + } + throw e; + } + @TruffleBoundary public static RError ioError(RBaseNode node, IOException ex) { throw error0(node, Message.GENERIC, ex.getMessage()); diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java index 28c057b810..add7d0383c 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2018, 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 @@ -102,6 +102,7 @@ import com.oracle.truffle.r.runtime.ffi.DLL; import com.oracle.truffle.r.runtime.ffi.RFFIContext; import com.oracle.truffle.r.runtime.ffi.RFFIFactory; import com.oracle.truffle.r.runtime.instrument.InstrumentationState; +import com.oracle.truffle.r.runtime.interop.FastrInteropTryContextState; import com.oracle.truffle.r.runtime.nodes.RCodeBuilder; import com.oracle.truffle.r.runtime.nodes.RSyntaxNode; import com.oracle.truffle.r.runtime.rng.RRNG; @@ -341,6 +342,7 @@ public final class RContext { public final ROptions.ContextStateImpl stateROptions; public final REnvironment.ContextStateImpl stateREnvironment; public final RErrorHandling.ContextStateImpl stateRErrorHandling; + public final FastrInteropTryContextState stateInteropTry; public final ConnectionSupport.ContextStateImpl stateRConnection; public final RRNG.ContextStateImpl stateRNG; public final RSerialize.ContextStateImpl stateRSerialize; @@ -444,6 +446,7 @@ public final class RContext { this.stateStdConnections = StdConnections.ContextStateImpl.newContextState(); this.stateREnvironment = REnvironment.ContextStateImpl.newContextState(this); this.stateRErrorHandling = RErrorHandling.ContextStateImpl.newContextState(); + this.stateInteropTry = FastrInteropTryContextState.newContextState(); this.stateRConnection = ConnectionSupport.ContextStateImpl.newContextState(); this.stateRNG = RRNG.ContextStateImpl.newContextState(); this.stateRSerialize = RSerialize.ContextStateImpl.newContextState(); diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/interop/FastRInteropTryException.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/interop/FastRInteropTryException.java new file mode 100644 index 0000000000..ac3429cb56 --- /dev/null +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/interop/FastRInteropTryException.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2018, 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.runtime.interop; + +/** + * Denotes a TruffleException coming from a foreign call. Supposed to be handled in the + * .fastr.interop.try builtin-s. + */ +@SuppressWarnings("serial") +public class FastRInteropTryException extends RuntimeException { + public FastRInteropTryException(RuntimeException cause) { + super(cause); + } + + @Override + public synchronized Throwable fillInStackTrace() { + return null; + } +} diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/interop/FastrInteropTryContextState.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/interop/FastrInteropTryContextState.java new file mode 100644 index 0000000000..4505048c89 --- /dev/null +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/interop/FastrInteropTryContextState.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2018, 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.runtime.interop; + +import com.oracle.truffle.r.runtime.context.RContext; + +/** + * Context-specific state relevant to the .fastr.interop.try builtins. + */ +@SuppressWarnings("serial") +public class FastrInteropTryContextState implements RContext.ContextState { + /** + * Values is either NULL or an RPairList, for {@code restarts}. + */ + public Throwable lastException = null; + /** + * Determines if in scope of a .fastr.interop.try builtin call. + */ + private int tryCounter = 0; + + public static FastrInteropTryContextState newContextState() { + return new FastrInteropTryContextState(); + } + + public void stepIn() { + tryCounter++; + } + + public void stepOut() { + tryCounter--; + assert tryCounter >= 0; + } + + public boolean isInTry() { + return tryCounter > 0; + } +} -- GitLab