diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/BaseWriteVariableNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/BaseWriteVariableNode.java index 25dd64ff7977d1cae004fd2689f1500d9070ecc8..4803d069f7f944137fb0b2b03e91f2e4b72cd5f2 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/BaseWriteVariableNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/BaseWriteVariableNode.java @@ -23,6 +23,7 @@ package com.oracle.truffle.r.nodes.access; import com.oracle.truffle.api.CompilerAsserts; +import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.dsl.NodeChild; import com.oracle.truffle.api.frame.Frame; import com.oracle.truffle.api.frame.FrameSlot; @@ -32,7 +33,10 @@ import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.profiles.BranchProfile; import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.api.profiles.ValueProfile; +import com.oracle.truffle.r.nodes.function.call.RExplicitCallNode; +import com.oracle.truffle.r.runtime.ArgumentsSignature; import com.oracle.truffle.r.runtime.RInternalError; +import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; import com.oracle.truffle.r.runtime.data.RShareable; import com.oracle.truffle.r.runtime.env.frame.ActiveBinding; import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor; @@ -51,6 +55,8 @@ abstract class BaseWriteVariableNode extends WriteVariableNode { super(name); } + @Child private RExplicitCallNode writeActiveBinding; + private final ConditionProfile isObjectProfile = ConditionProfile.createBinaryProfile(); private final ConditionProfile isCurrentProfile = ConditionProfile.createBinaryProfile(); private final ConditionProfile isShareableProfile = ConditionProfile.createBinaryProfile(); @@ -178,7 +184,16 @@ abstract class BaseWriteVariableNode extends WriteVariableNode { } if (isActiveBindingProfile.profile(object != null && ActiveBinding.isActiveBinding(object))) { - return ((ActiveBinding) object).writeValue(value); + if (writeActiveBinding == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + writeActiveBinding = insert(RExplicitCallNode.create()); + } + ActiveBinding binding = (ActiveBinding) object; + try { + return writeActiveBinding.execute(execFrame, binding.getFunction(), new RArgsValuesAndNames(new Object[]{value}, ArgumentsSignature.empty(1))); + } finally { + binding.setInitialized(); + } } else { Object newValue = shareObjectValue(lookupFrame, frameSlot, storedObjectProfile.profile(value), mode, false); FrameSlotChangeMonitor.setObjectAndInvalidate(lookupFrame, frameSlot, newValue, false, invalidateProfile); diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/LocalReadVariableNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/LocalReadVariableNode.java index 12cbdee57697a38ca4988baeaebd72f4e6ab5d7c..f3e42feefcbbb14c573b303dd54de1c038a5905e 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/LocalReadVariableNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/LocalReadVariableNode.java @@ -35,7 +35,9 @@ import com.oracle.truffle.api.nodes.UnexpectedResultException; import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.api.profiles.ValueProfile; import com.oracle.truffle.r.nodes.function.PromiseHelperNode; +import com.oracle.truffle.r.nodes.function.call.RExplicitCallNode; import com.oracle.truffle.r.runtime.RError; +import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; import com.oracle.truffle.r.runtime.data.RMissing; import com.oracle.truffle.r.runtime.data.RPromise; import com.oracle.truffle.r.runtime.data.RTypesGen; @@ -45,6 +47,7 @@ import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor; public final class LocalReadVariableNode extends Node { @Child private PromiseHelperNode promiseHelper; + @Child private RExplicitCallNode readActiveBinding; private final Object identifier; private final boolean forceResult; @@ -120,7 +123,15 @@ public final class LocalReadVariableNode extends Node { } // special treatment for active binding: call bound function if (!containsNoActiveBindingAssumption.isValid() && ActiveBinding.isActiveBinding(result)) { - Object readValue = ((ActiveBinding) result).readValue(); + if (readActiveBinding == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + readActiveBinding = insert(RExplicitCallNode.create()); + } + ActiveBinding binding = (ActiveBinding) result; + if (binding.isHidden() && !binding.isInitialized()) { + return null; + } + Object readValue = readActiveBinding.execute(frame, binding.getFunction(), RArgsValuesAndNames.EMPTY); if (readValue == RMissing.instance) { return null; } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/ReadVariableNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/ReadVariableNode.java index 0eab69dc38f083cb4dbc5da0a296d49c41c87ecc..5a8268ee382dbd27746ed780b094ae0828bef458 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/ReadVariableNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/ReadVariableNode.java @@ -48,6 +48,7 @@ import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.api.profiles.ValueProfile; import com.oracle.truffle.api.source.SourceSection; import com.oracle.truffle.r.nodes.function.PromiseHelperNode; +import com.oracle.truffle.r.nodes.function.call.RExplicitCallNode; import com.oracle.truffle.r.nodes.function.visibility.SetVisibilityNode; import com.oracle.truffle.r.runtime.ArgumentsSignature; import com.oracle.truffle.r.runtime.FastROptions; @@ -107,8 +108,11 @@ final class LookupNode extends RSourceSectionNode implements RSyntaxNode, RSynta CompilerDirectives.transferToInterpreterAndInvalidate(); visibility = insert(SetVisibilityNode.create()); } - visibility.execute(frame, true); - return read.executeInternal(frame, frame); + try { + return read.executeInternal(frame, frame); + } finally { + visibility.execute(frame, true); + } } @Override @@ -180,6 +184,7 @@ public final class ReadVariableNode extends RBaseNode { @Child private PromiseHelperNode promiseHelper; @Child private CheckTypeNode checkTypeNode; + @Child private RExplicitCallNode readActiveBinding; @CompilationFinal private FrameLevel read; @CompilationFinal private boolean needsCopying; @@ -252,16 +257,25 @@ public final class ReadVariableNode extends RBaseNode { } } if (needsCopying && copyProfile.profile(result instanceof RAbstractVector)) { - result = ((RAbstractVector) result).copy(); + return ((RAbstractVector) result).copy(); } if (isPromiseProfile.profile(result instanceof RPromise)) { if (promiseHelper == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); promiseHelper = insert(new PromiseHelperNode()); } - result = promiseHelper.evaluate(frame, (RPromise) result); - } else if (isActiveBindingProfile.profile(ActiveBinding.isActiveBinding(result))) { - Object readValue = ((ActiveBinding) result).readValue(); + return promiseHelper.evaluate(frame, (RPromise) result); + } + if (isActiveBindingProfile.profile(ActiveBinding.isActiveBinding(result))) { + if (readActiveBinding == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + readActiveBinding = insert(RExplicitCallNode.create()); + } + ActiveBinding binding = (ActiveBinding) result; + if (binding.isHidden() && !binding.isInitialized()) { + throw error(mode == RType.Function ? RError.Message.UNKNOWN_FUNCTION : RError.Message.UNKNOWN_OBJECT, identifier); + } + Object readValue = readActiveBinding.execute(frame, binding.getFunction(), RArgsValuesAndNames.EMPTY); if (readValue == RMissing.instance) { throw error(mode == RType.Function ? RError.Message.UNKNOWN_FUNCTION : RError.Message.UNKNOWN_OBJECT, identifier); }