From 87917c5e77bad3e0560297e9b211b6930341e46a Mon Sep 17 00:00:00 2001 From: stepan <stepan.sindelar@oracle.com> Date: Fri, 23 Feb 2018 12:13:36 +0100 Subject: [PATCH] RfEvalNode: environment may be (R_)NULL, use global in such case --- .../truffle/r/ffi/impl/nodes/RfEvalNode.java | 37 +++++++++++++++---- .../r/ffi/impl/upcalls/FFIUnwrapNode.java | 6 +++ .../truffle/r/runtime/env/REnvironment.java | 9 ++++- 3 files changed, 44 insertions(+), 8 deletions(-) diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/RfEvalNode.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/RfEvalNode.java index 8a12776808..c94ad969ea 100644 --- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/RfEvalNode.java +++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/RfEvalNode.java @@ -26,12 +26,15 @@ import static com.oracle.truffle.r.runtime.RError.Message.ARGUMENT_NOT_ENVIRONME import static com.oracle.truffle.r.runtime.RError.Message.ARGUMENT_NOT_FUNCTION; import static com.oracle.truffle.r.runtime.RError.Message.UNKNOWN_OBJECT; +import org.graalvm.polyglot.Value; + import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Fallback; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.profiles.ConditionProfile; +import com.oracle.truffle.api.profiles.ValueProfile; import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode; import com.oracle.truffle.r.nodes.function.PromiseHelperNode; import com.oracle.truffle.r.runtime.ArgumentsSignature; @@ -51,11 +54,18 @@ import com.oracle.truffle.r.runtime.env.REnvironment; public abstract class RfEvalNode extends FFIUpCallNode.Arg2 { @Child private PromiseHelperNode promiseHelper; + private final ConditionProfile envIsNullProfile = ConditionProfile.createBinaryProfile(); public static RfEvalNode create() { return RfEvalNodeGen.create(); } + @Specialization + @TruffleBoundary + Object handlePromise(RPromise expr, @SuppressWarnings("unused") RNull nulLEnv) { + return getPromiseHelper().evaluate(null, expr); + } + @Specialization @TruffleBoundary Object handlePromise(RPromise expr, @SuppressWarnings("unused") REnvironment env) { @@ -64,20 +74,21 @@ public abstract class RfEvalNode extends FFIUpCallNode.Arg2 { @Specialization @TruffleBoundary - Object handleExpression(RExpression expr, REnvironment env) { - return RContext.getEngine().eval(expr, env, null); + Object handleExpression(RExpression expr, Object envArg) { + return RContext.getEngine().eval(expr, getEnv(envArg), null); } @Specialization @TruffleBoundary - Object handleLanguage(RLanguage expr, REnvironment env) { - return RContext.getEngine().eval(expr, env, null); + Object handleLanguage(RLanguage expr, Object envArg) { + return RContext.getEngine().eval(expr, getEnv(envArg), null); } @Specialization @TruffleBoundary - Object handleSymbol(RSymbol expr, REnvironment env) { - Object result = ReadVariableNode.lookupAny(expr.getName(), env.getFrame(), false); + Object handleSymbol(RSymbol expr, Object envArg, + @Cached("createClassProfile()") ValueProfile accessProfile) { + Object result = ReadVariableNode.lookupAny(expr.getName(), getEnv(envArg).getFrame(accessProfile), false); if (result == null) { throw RError.error(RError.NO_CALLER, UNKNOWN_OBJECT, expr.getName()); } @@ -85,7 +96,7 @@ public abstract class RfEvalNode extends FFIUpCallNode.Arg2 { } @Specialization - Object handlePairList(RPairList l, REnvironment env, + Object handlePairList(RPairList l, Object envArg, @Cached("createBinaryProfile()") ConditionProfile isPromiseProfile, @Cached("createBinaryProfile()") ConditionProfile noArgsProfile) { Object car = l.car(); @@ -101,6 +112,7 @@ public abstract class RfEvalNode extends FFIUpCallNode.Arg2 { } Object args = l.cdr(); + REnvironment env = getEnv(envArg); if (noArgsProfile.profile(args == RNull.instance)) { return evalFunction(f, env, null); } else { @@ -119,10 +131,21 @@ public abstract class RfEvalNode extends FFIUpCallNode.Arg2 { if (env instanceof REnvironment) { return expr; } else { + CompilerDirectives.transferToInterpreter(); throw RError.error(RError.NO_CALLER, ARGUMENT_NOT_ENVIRONMENT); } } + private REnvironment getEnv(Object envArg) { + if (envIsNullProfile.profile(envArg == RNull.instance)) { + return REnvironment.globalEnv(RContext.getInstance()); + } else if (envArg instanceof REnvironment) { + return (REnvironment) envArg; + } + CompilerDirectives.transferToInterpreter(); + throw RError.error(RError.NO_CALLER, ARGUMENT_NOT_ENVIRONMENT); + } + private PromiseHelperNode getPromiseHelper() { if (promiseHelper == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/FFIUnwrapNode.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/FFIUnwrapNode.java index 4d5aafa461..40a3f13e3f 100644 --- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/FFIUnwrapNode.java +++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/FFIUnwrapNode.java @@ -32,6 +32,7 @@ import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.profiles.BranchProfile; import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.data.NativeDataAccess; +import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.RTruffleObject; /** @@ -64,6 +65,11 @@ public final class FFIUnwrapNode extends Node { } try { long address = ForeignAccess.sendAsPointer(asPointer, xTo); + if (address == 0) { + // Users are expected to use R_NULL, but at least when embedding, GNU R + // seems to be tolerant to NULLs. + return RNull.instance; + } return NativeDataAccess.lookup(address); } catch (UnsupportedMessageException e) { if (isPointerNode == null) { diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/REnvironment.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/REnvironment.java index 6f6fc75678..1253a0a809 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/REnvironment.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/REnvironment.java @@ -267,7 +267,14 @@ public abstract class REnvironment extends RAttributeStorage { * Value returned by {@code globalenv()}. */ public static REnvironment globalEnv() { - return RContext.getInstance().stateREnvironment.getGlobalEnv(); + return globalEnv(RContext.getInstance()); + } + + /** + * Value returned by {@code globalenv()}. + */ + public static REnvironment globalEnv(RContext ctx) { + return ctx.stateREnvironment.getGlobalEnv(); } /** -- GitLab