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 84d164a23a5ab3c62cd9473e71a32fa5955e93cf..16ba409614756338d6683f0af586e408ccc5eff2 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 @@ -69,6 +69,8 @@ import com.oracle.truffle.r.nodes.function.call.CallRFunctionNode; import com.oracle.truffle.r.nodes.function.call.PrepareArguments; import com.oracle.truffle.r.nodes.function.visibility.SetVisibilityNode; import com.oracle.truffle.r.nodes.helpers.AccessListField; +import com.oracle.truffle.r.nodes.helpers.GetFromEnvironment; +import com.oracle.truffle.r.nodes.helpers.GetFromEnvironmentNodeGen; import com.oracle.truffle.r.nodes.profile.TruffleBoundaryNode; import com.oracle.truffle.r.nodes.profile.VectorLengthProfile; import com.oracle.truffle.r.runtime.Arguments; @@ -154,7 +156,26 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS // needed for INTERNAL_GENERIC calls: @Child private FunctionDispatch internalDispatchCall; - @Child private AccessListField accessListField; + @Child private GetBasicFunction getBasicFunction; + + private static final class GetBasicFunction extends RBaseNode { + @Child private AccessListField accessListField = AccessListField.create(); + @Child private GetFromEnvironment getMethods = GetFromEnvironmentNodeGen.create(); + @Child private GetFromEnvironment getBasicFunsList = GetFromEnvironmentNodeGen.create(); + + Object execute(VirtualFrame frame, String functionName) { + REnvironment namespaceRegistry = REnvironment.getNamespaceRegistry(); + Object methods = getMethods.execute(frame, namespaceRegistry, "methods"); + if (!(methods instanceof REnvironment)) { + throw error(RError.Message.GENERIC, "methods namespace not found on search list"); + } + Object basicFunsList = getBasicFunsList.execute(frame, (REnvironment) methods, ".BasicFunsList"); + if (!(basicFunsList instanceof RList)) { + throw error(RError.Message.GENERIC, ".BasicFunsList not found in methods namespace"); + } + return accessListField.execute((RList) basicFunsList, functionName); + } + } protected RCaller createCaller(VirtualFrame frame, RFunction function) { if (explicitArgs == null) { @@ -287,8 +308,7 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS @Cached("createBinaryProfile()") ConditionProfile isAttributableProfile, @Cached("createBinaryProfile()") ConditionProfile resultIsBuiltinProfile, @Cached("create()") GetBaseEnvFrameNode getBaseEnvFrameNode, - @Cached("createBinaryProfile()") ConditionProfile isS4Profile, - @Cached("new()") PromiseCheckHelperNode promiseHelper) { + @Cached("createBinaryProfile()") ConditionProfile isS4Profile) { RBuiltinDescriptor builtin = builtinProfile.profile(function.getRBuiltin()); Object dispatchObject = dispatchArgument.execute(frame); @@ -305,12 +325,11 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS } if (isAttributableProfile.profile(dispatchObject instanceof RAttributeStorage) && isS4Profile.profile(((RAttributeStorage) dispatchObject).isS4())) { - RList list = (RList) promiseHelper.checkEvaluate(frame, REnvironment.getRegisteredNamespace("methods").get(".BasicFunsList")); - if (accessListField == null) { + if (getBasicFunction == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); - accessListField = insert(AccessListField.create()); + getBasicFunction = insert(new GetBasicFunction()); } - Object basicFun = accessListField.execute(list, builtin.getName()); + Object basicFun = getBasicFunction.execute(frame, builtin.getName()); if (basicFun != null) { Object result = internalDispatchCall.execute(frame, (RFunction) basicFun, lookupVarArgs(frame), null, null); if (result != RRuntime.DEFERRED_DEFAULT_MARKER) { diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/helpers/GetFromEnvironment.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/helpers/GetFromEnvironment.java new file mode 100644 index 0000000000000000000000000000000000000000..f1d2f0e0adda4fd5ed246fa0d24f8a9671610405 --- /dev/null +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/helpers/GetFromEnvironment.java @@ -0,0 +1,90 @@ +/* + * 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.nodes.helpers; + +import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; +import com.oracle.truffle.api.dsl.Cached; +import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.frame.FrameDescriptor; +import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.api.profiles.ValueProfile; +import com.oracle.truffle.r.nodes.access.variables.LocalReadVariableNode; +import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode; +import com.oracle.truffle.r.nodes.function.PromiseHelperNode; +import com.oracle.truffle.r.runtime.data.RPromise; +import com.oracle.truffle.r.runtime.env.REnvironment; +import com.oracle.truffle.r.runtime.nodes.RBaseNode; + +public abstract class GetFromEnvironment extends RBaseNode { + + public static GetFromEnvironment create() { + return GetFromEnvironmentNodeGen.create(); + } + + protected final ValueProfile frameAccessProfile = ValueProfile.createClassProfile(); + protected final ValueProfile frameProfile = ValueProfile.createClassProfile(); + + @Child private PromiseHelperNode promiseHelper; + + @CompilationFinal private boolean firstExecution = true; + + protected Object checkPromise(VirtualFrame frame, Object r, String identifier) { + if (r instanceof RPromise) { + if (firstExecution) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + firstExecution = false; + return ReadVariableNode.evalPromiseSlowPathWithName(identifier, frame, (RPromise) r); + } + if (promiseHelper == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + promiseHelper = insert(new PromiseHelperNode()); + } + return promiseHelper.evaluate(frame, (RPromise) r); + } else { + return r; + } + } + + public abstract Object execute(VirtualFrame frame, REnvironment env, String name); + + protected static LocalReadVariableNode createRead(String name) { + return LocalReadVariableNode.create(name, true); + } + + protected FrameDescriptor getFrameDescriptor(REnvironment env) { + return frameProfile.profile(env.getFrame(frameAccessProfile)).getFrameDescriptor(); + } + + @Specialization(guards = {"getFrameDescriptor(env) == envDesc", "read.getIdentifier().equals(name)"}) + protected Object getCached(VirtualFrame frame, REnvironment env, @SuppressWarnings("unused") String name, + @Cached("env.getFrame().getFrameDescriptor()") @SuppressWarnings("unused") FrameDescriptor envDesc, + @Cached("createRead(name)") LocalReadVariableNode read) { + return read.execute(frame, frameProfile.profile(env.getFrame(frameAccessProfile))); + } + + @Specialization(replaces = "getCached") + protected Object get(VirtualFrame frame, REnvironment env, String name) { + return checkPromise(frame, env.get(name), name); + } +}