diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/REngine.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/REngine.java index d8a9b08e1d65070421b6f68f3c75b93add39e594..649f4d84aa04ea9937d99cfd4e68f2924c6b3321 100644 --- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/REngine.java +++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/REngine.java @@ -158,7 +158,7 @@ final class REngine implements Engine, Engine.Timings { private void initializeShared() { suppressWarnings = true; - MaterializedFrame baseFrame = RRuntime.createNonFunctionFrame().materialize(); + MaterializedFrame baseFrame = RRuntime.createNonFunctionFrame("base"); REnvironment.baseInitialize(baseFrame, globalFrame); RBuiltinPackages.loadBase(baseFrame); RGraphics.initialize(); @@ -489,7 +489,7 @@ final class REngine implements Engine, Engine.Timings { fbn = new BodyNode(body); } FrameDescriptor descriptor = new FrameDescriptor(); - FrameSlotChangeMonitor.initializeFunctionFrameDescriptor(descriptor); + FrameSlotChangeMonitor.initializeFunctionFrameDescriptor("<eval>", descriptor); FunctionDefinitionNode rootNode = new FunctionDefinitionNode(sourceSection, descriptor, fbn, FormalArguments.NO_ARGS, description, true, true, null); RootCallTarget callTarget = Truffle.getRuntime().createCallTarget(rootNode); return callTarget; diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/RRuntimeASTAccessImpl.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/RRuntimeASTAccessImpl.java index 444300b2e745820bd51faba406013d3c0577642a..e806f440e4b6142e02d36ee44d9e8ca2d3506efb 100644 --- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/RRuntimeASTAccessImpl.java +++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/RRuntimeASTAccessImpl.java @@ -123,7 +123,7 @@ public class RRuntimeASTAccessImpl implements RRuntimeASTAccess { // obj is RSymbol or a primitive value. // A symbol needs to be converted back to a ReadVariableNode if (obj instanceof RSymbol) { - return ReadVariableNode.create(((RSymbol) obj).getName(), false); + return ReadVariableNode.create(((RSymbol) obj).getName()); } else { return ConstantNode.create(obj); } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsFunction.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsFunction.java index 1103c240c2ed417c17dfcaf2ef43750c300ba42b..ea3ee7e70305219cc47a8bed5922cc6345fd33bc 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsFunction.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsFunction.java @@ -115,7 +115,8 @@ public abstract class AsFunction extends RBuiltinNode { } FrameDescriptor descriptor = new FrameDescriptor(); - FrameSlotChangeMonitor.initializeFunctionFrameDescriptor(descriptor); + FrameSlotChangeMonitor.initializeFunctionFrameDescriptor("<as.function.default>", descriptor); + FrameSlotChangeMonitor.initializeEnclosingFrame(descriptor, envir.getFrame()); FunctionDefinitionNode rootNode = new FunctionDefinitionNode(sourceSection, descriptor, fbn, formals, "from AsFunction", false, null); RootCallTarget callTarget = Truffle.getRuntime().createCallTarget(rootNode); boolean containsDispatch = ((FunctionDefinitionNode) callTarget.getRootNode()).containsDispatch(); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EnvFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EnvFunctions.java index 2089de76caf6795195eee644529605ca0b613427..4f1006826fdd376be23177ac68256d60249bfdaa 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EnvFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EnvFunctions.java @@ -22,23 +22,56 @@ */ package com.oracle.truffle.r.nodes.builtin.base; -import static com.oracle.truffle.r.runtime.RBuiltinKind.*; +import static com.oracle.truffle.r.runtime.RBuiltinKind.INTERNAL; +import static com.oracle.truffle.r.runtime.RBuiltinKind.PRIMITIVE; -import com.oracle.truffle.api.*; +import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.api.dsl.*; -import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.RootCallTarget; +import com.oracle.truffle.api.Truffle; +import com.oracle.truffle.api.dsl.Fallback; +import com.oracle.truffle.api.dsl.NodeChild; +import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.frame.Frame; import com.oracle.truffle.api.frame.FrameInstance.FrameAccess; -import com.oracle.truffle.api.profiles.*; -import com.oracle.truffle.r.nodes.builtin.*; +import com.oracle.truffle.api.frame.MaterializedFrame; +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.r.nodes.RRootNode; +import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; +import com.oracle.truffle.r.nodes.builtin.RInvisibleBuiltinNode; import com.oracle.truffle.r.nodes.builtin.base.EnvFunctionsFactory.CopyNodeGen; -import com.oracle.truffle.r.nodes.function.*; +import com.oracle.truffle.r.nodes.function.FunctionDefinitionNode; +import com.oracle.truffle.r.nodes.function.PromiseHelperNode; import com.oracle.truffle.r.nodes.function.PromiseHelperNode.PromiseDeoptimizeFrameNode; -import com.oracle.truffle.r.runtime.*; -import com.oracle.truffle.r.runtime.data.*; -import com.oracle.truffle.r.runtime.data.model.*; -import com.oracle.truffle.r.runtime.env.*; -import com.oracle.truffle.r.runtime.nodes.*; +import com.oracle.truffle.r.runtime.RArguments; +import com.oracle.truffle.r.runtime.RBuiltin; +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.Utils; +import com.oracle.truffle.r.runtime.VirtualEvalFrame; +import com.oracle.truffle.r.runtime.data.RAttributable; +import com.oracle.truffle.r.runtime.data.RAttributeProfiles; +import com.oracle.truffle.r.runtime.data.RDataFactory; +import com.oracle.truffle.r.runtime.data.RFunction; +import com.oracle.truffle.r.runtime.data.RLanguage; +import com.oracle.truffle.r.runtime.data.RList; +import com.oracle.truffle.r.runtime.data.RMissing; +import com.oracle.truffle.r.runtime.data.RNull; +import com.oracle.truffle.r.runtime.data.RPromise; +import com.oracle.truffle.r.runtime.data.RStringVector; +import com.oracle.truffle.r.runtime.data.RSymbol; +import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractVector; +import com.oracle.truffle.r.runtime.env.REnvironment; +import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor; +import com.oracle.truffle.r.runtime.nodes.RBaseNode; +import com.oracle.truffle.r.runtime.nodes.RNode; /** * Encapsulates all the builtins related to R environments as nested static classes. @@ -169,7 +202,6 @@ public class EnvFunctions { env.setParent(parent); return env; } - } @RBuiltin(name = "is.environment", kind = PRIMITIVE, parameterNames = {"x"}) @@ -235,8 +267,14 @@ public class EnvFunctions { @Specialization @TruffleBoundary protected Object updateEnvironment(RFunction fun, REnvironment env) { - fun.setEnclosingFrame(env.getFrame()); - return fun; + MaterializedFrame enclosingFrame = env.getFrame(); + assert !(enclosingFrame instanceof VirtualEvalFrame); + + RRootNode root = (RRootNode) fun.getTarget().getRootNode(); + root = root.duplicateWithNewFrameDescriptor(); + RootCallTarget target = Truffle.getRuntime().createCallTarget(root); + FrameSlotChangeMonitor.initializeEnclosingFrame(target.getRootNode().getFrameDescriptor(), enclosingFrame); + return RDataFactory.createFunction(fun.getName(), target, null, enclosingFrame, fun.getFastPath(), ((FunctionDefinitionNode) target.getRootNode()).containsDispatch()); } @SuppressWarnings("unused") @@ -293,15 +331,11 @@ public class EnvFunctions { } @Specialization + @TruffleBoundary protected REnvironment newEnv(byte hash, REnvironment parent, int size) { controlVisibility(); - return createEnvironment(parent, RRuntime.fromLogical(hash), size); - } - - @TruffleBoundary - private static REnvironment createEnvironment(REnvironment parent, boolean hash, int size) { - REnvironment env = RDataFactory.createNewEnv(null, hash, size); - env.setParent(parent); + REnvironment env = RDataFactory.createNewEnv(null, RRuntime.fromLogical(hash), size); + RArguments.initializeEnclosingFrame(env.getFrame(), parent.getFrame()); return env; } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Identical.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Identical.java index dd1e5027457cb5d0f91fc0740836053e714cfd24..68f75c9d98b62dea975c220f8c92a37e9de3d75a 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Identical.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Identical.java @@ -188,7 +188,6 @@ public abstract class Identical extends RBuiltinNode { return RRuntime.LOGICAL_TRUE; } - @SuppressWarnings("unused") @Specialization protected byte doInternalIdenticalGeneric(RList x, RList y, byte numEq, byte singleNA, byte attribAsSet, byte ignoreBytecode, byte ignoreEnvironment) { if (!recursive) { @@ -241,7 +240,6 @@ public abstract class Identical extends RBuiltinNode { return RRuntime.LOGICAL_FALSE; } - @SuppressWarnings("unused") @Specialization protected byte doInternalIdenticalGeneric(RS4Object x, RS4Object y, Object numEq, Object singleNA, Object attribAsSet, Object ignoreBytecode, Object ignoreEnvironment) { if (!recursive) { diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Lapply.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Lapply.java index 19e003c76728be88674da6ce224893a0272908de..533e7ba147f617f1c01ef12c2ba008bfc3689369 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Lapply.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Lapply.java @@ -107,7 +107,7 @@ public abstract class Lapply extends RBuiltinNode { throw RInternalError.shouldNotReachHere(); } REnvironment env = RDataFactory.createInternalEnv(); - env.safePut("i", RDataFactory.createLanguage(ReadVariableNode.create(INDEX_NAME, false))); + env.safePut("i", RDataFactory.createLanguage(ReadVariableNode.create(INDEX_NAME))); return indexNode.substitute(env).asRNode(); } @@ -128,7 +128,7 @@ public abstract class Lapply extends RBuiltinNode { readVectorElementName = null; } - ReadVariableNode readVector = ReadVariableNode.createAnonymous(VECTOR_ELEMENT); + ReadVariableNode readVector = ReadVariableNode.create(VECTOR_ELEMENT); // The remaining parameters are passed from {@code ...}. The call node will take // care of matching. diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Mapply.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Mapply.java index 316dfbb8dba268a774712b26a743dec107ba08d3..4feef08b251d28d0d3a69b55a560591aaa3153f4 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Mapply.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Mapply.java @@ -161,7 +161,7 @@ public abstract class Mapply extends RBuiltinNode { RSyntaxNode[] readVectorElementNodes = new RSyntaxNode[elementNodeArray.length]; for (int i = 0; i < readVectorElementNodes.length; i++) { - readVectorElementNodes[i] = ReadVariableNode.create(elementNodeArray[i].vectorElementName, false); + readVectorElementNodes[i] = ReadVariableNode.create(elementNodeArray[i].vectorElementName); } ArgumentsSignature argsSig = ArgumentsSignature.empty(readVectorElementNodes.length); // Errors can be thrown from the modified call so a SourceSection is required diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PrintFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PrintFunctions.java index 652ae4b0820b31737d58a4cbc5610c3b230eae37..8548085db3135f95c5df12601582e4ec9c254c9f 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PrintFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PrintFunctions.java @@ -33,12 +33,10 @@ import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.nodes.DirectCallNode; import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode; -import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode.ReadKind; import com.oracle.truffle.r.nodes.builtin.RInvisibleBuiltinNode; import com.oracle.truffle.r.runtime.RBuiltin; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RRuntime; -import com.oracle.truffle.r.runtime.RType; import com.oracle.truffle.r.runtime.Utils; import com.oracle.truffle.r.runtime.conn.StdConnections; import com.oracle.truffle.r.runtime.context.RContext; @@ -80,7 +78,7 @@ public class PrintFunctions { } ReadVariableNode createShowFind() { - return ReadVariableNode.create("show", RType.Function, ReadKind.Normal); + return ReadVariableNode.createFunctionLookup(null, "show"); } RFunction createShowFunction(ReadVariableNode showFind) { diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Recall.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Recall.java index 8a6c435abd7eec1c265949a08e22a233c2622c51..274768e590f4a14695fc31382a580b7e0f258863 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Recall.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Recall.java @@ -22,18 +22,23 @@ */ package com.oracle.truffle.r.nodes.builtin.base; -import static com.oracle.truffle.r.runtime.RBuiltinKind.*; +import static com.oracle.truffle.r.runtime.RBuiltinKind.INTERNAL; -import com.oracle.truffle.api.dsl.*; -import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.frame.Frame; import com.oracle.truffle.api.frame.FrameInstance.FrameAccess; -import com.oracle.truffle.api.profiles.*; -import com.oracle.truffle.r.nodes.access.variables.*; -import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode.*; -import com.oracle.truffle.r.nodes.builtin.*; -import com.oracle.truffle.r.nodes.function.*; -import com.oracle.truffle.r.runtime.*; -import com.oracle.truffle.r.runtime.data.*; +import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.api.profiles.BranchProfile; +import com.oracle.truffle.r.nodes.access.variables.LocalReadVariableNode; +import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; +import com.oracle.truffle.r.nodes.function.CallMatcherNode; +import com.oracle.truffle.r.runtime.ArgumentsSignature; +import com.oracle.truffle.r.runtime.RArguments; +import com.oracle.truffle.r.runtime.RBuiltin; +import com.oracle.truffle.r.runtime.RError; +import com.oracle.truffle.r.runtime.Utils; +import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; +import com.oracle.truffle.r.runtime.data.RFunction; /** * The {@code Recall} {@code .Internal}. @@ -43,7 +48,7 @@ public abstract class Recall extends RBuiltinNode { private final BranchProfile errorProfile = BranchProfile.create(); - @Child private ReadVariableNode readArgs = ReadVariableNode.create(ArgumentsSignature.VARARG_NAME, RType.Any, ReadKind.UnforcedSilentLocal); + @Child private LocalReadVariableNode readArgs = LocalReadVariableNode.create(ArgumentsSignature.VARARG_NAME, false); @Child private CallMatcherNode call = CallMatcherNode.create(false, false); @Specialization diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/S3DispatchFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/S3DispatchFunctions.java index 5cd047cdbefb7c375f272fc42194adbdcd0a883c..591ef9b77327ad4ed98de103c0195e5622545c0c 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/S3DispatchFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/S3DispatchFunctions.java @@ -24,8 +24,7 @@ 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.access.variables.ReadVariableNode; -import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode.ReadKind; +import com.oracle.truffle.r.nodes.access.variables.LocalReadVariableNode; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.function.CallMatcherNode; import com.oracle.truffle.r.nodes.function.ClassHierarchyNode; @@ -44,7 +43,6 @@ import com.oracle.truffle.r.runtime.RArguments.S3Args; import com.oracle.truffle.r.runtime.RBuiltin; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RRuntime; -import com.oracle.truffle.r.runtime.RType; import com.oracle.truffle.r.runtime.ReturnException; import com.oracle.truffle.r.runtime.Utils; import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; @@ -158,11 +156,11 @@ public abstract class S3DispatchFunctions extends RBuiltinNode { @RBuiltin(name = "NextMethod", kind = SUBSTITUTE, parameterNames = {"generic", "object", "..."}) public abstract static class NextMethod extends S3DispatchFunctions { - @Child private ReadVariableNode rvnGroup = ReadVariableNode.create(RRuntime.RDotGroup, RType.Character, ReadKind.UnforcedSilentLocal); - @Child private ReadVariableNode rvnClass = ReadVariableNode.create(RRuntime.RDotClass, RType.Character, ReadKind.UnforcedSilentLocal); - @Child private ReadVariableNode rvnGeneric = ReadVariableNode.create(RRuntime.RDotGeneric, RType.Character, ReadKind.UnforcedSilentLocal); - @Child private ReadVariableNode rvnCall = ReadVariableNode.create(RRuntime.RDotGenericCallEnv, RType.Any, ReadKind.UnforcedSilentLocal); - @Child private ReadVariableNode rvnDef = ReadVariableNode.create(RRuntime.RDotGenericDefEnv, RType.Any, ReadKind.UnforcedSilentLocal); + @Child private LocalReadVariableNode rvnGroup = LocalReadVariableNode.create(RRuntime.RDotGroup, false); + @Child private LocalReadVariableNode rvnClass = LocalReadVariableNode.create(RRuntime.RDotClass, false); + @Child private LocalReadVariableNode rvnGeneric = LocalReadVariableNode.create(RRuntime.RDotGeneric, false); + @Child private LocalReadVariableNode rvnCall = LocalReadVariableNode.create(RRuntime.RDotGenericCallEnv, false); + @Child private LocalReadVariableNode rvnDef = LocalReadVariableNode.create(RRuntime.RDotGenericDefEnv, false); @Child private CombineSignaturesNode combineSignatures; @Child private CollectArgumentsNode collectArguments = CollectArgumentsNodeGen.create(); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/StandardGeneric.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/StandardGeneric.java index 106fbfccff203153f69dcd6662677bd13477744c..097062b22e2c2456b3765376d19babb967b89459 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/StandardGeneric.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/StandardGeneric.java @@ -12,22 +12,22 @@ */ package com.oracle.truffle.r.nodes.builtin.base; -import static com.oracle.truffle.r.runtime.RBuiltinKind.*; +import static com.oracle.truffle.r.runtime.RBuiltinKind.PRIMITIVE; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.Truffle; -import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.frame.MaterializedFrame; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.nodes.DirectCallNode; import com.oracle.truffle.api.profiles.BranchProfile; import com.oracle.truffle.api.profiles.ConditionProfile; +import com.oracle.truffle.r.nodes.access.variables.LocalReadVariableNode; import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode; -import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode.ReadKind; import com.oracle.truffle.r.nodes.attributes.AttributeAccess; import com.oracle.truffle.r.nodes.attributes.AttributeAccessNodeGen; -import com.oracle.truffle.r.nodes.builtin.*; +import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.function.signature.RArgumentsNode; import com.oracle.truffle.r.nodes.objects.CollectGenericArgumentsNode; import com.oracle.truffle.r.nodes.objects.CollectGenericArgumentsNodeGen; @@ -36,10 +36,23 @@ import com.oracle.truffle.r.nodes.objects.DispatchGenericNodeGen; import com.oracle.truffle.r.nodes.unary.CastIntegerScalarNode; import com.oracle.truffle.r.nodes.unary.CastStringScalarNode; import com.oracle.truffle.r.nodes.unary.CastStringScalarNodeGen; -import com.oracle.truffle.r.runtime.*; +import com.oracle.truffle.r.runtime.ArgumentsSignature; +import com.oracle.truffle.r.runtime.RArguments; +import com.oracle.truffle.r.runtime.RBuiltin; +import com.oracle.truffle.r.runtime.RCaller; +import com.oracle.truffle.r.runtime.RError; +import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.context.RContext; -import com.oracle.truffle.r.runtime.data.*; -import com.oracle.truffle.r.runtime.data.model.*; +import com.oracle.truffle.r.runtime.data.RAttributable; +import com.oracle.truffle.r.runtime.data.RAttributeProfiles; +import com.oracle.truffle.r.runtime.data.RAttributes; +import com.oracle.truffle.r.runtime.data.RDataFactory; +import com.oracle.truffle.r.runtime.data.RFunction; +import com.oracle.truffle.r.runtime.data.RList; +import com.oracle.truffle.r.runtime.data.RMissing; +import com.oracle.truffle.r.runtime.data.RNull; +import com.oracle.truffle.r.runtime.data.RStringVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; import com.oracle.truffle.r.runtime.env.REnvironment; import com.oracle.truffle.r.runtime.nodes.RNode; @@ -52,11 +65,11 @@ public abstract class StandardGeneric extends RBuiltinNode { @Child private AttributeAccess genericAttrAccess; @Child private FrameFunctions.SysFunction sysFunction; @Child private CastStringScalarNode castStringScalar = CastStringScalarNodeGen.create(); - @Child private ReadVariableNode readMTableFirst = ReadVariableNode.create(RRuntime.DOT_ALL_MTABLE, RType.Any, ReadKind.SilentLocal); - @Child private ReadVariableNode readMTableSecond = ReadVariableNode.create(RRuntime.DOT_ALL_MTABLE, RType.Any, ReadKind.SilentLocal); - @Child private ReadVariableNode readSigLength = ReadVariableNode.create(RRuntime.DOT_SIG_LENGTH, RType.Any, ReadKind.SilentLocal); - @Child private ReadVariableNode readSigARgs = ReadVariableNode.create(RRuntime.DOT_SIG_ARGS, RType.Any, ReadKind.SilentLocal); - @Child private ReadVariableNode getMethodsTableFind = ReadVariableNode.create(".getMethodsTable", RType.Function, ReadKind.Normal); + @Child private LocalReadVariableNode readMTableFirst = LocalReadVariableNode.create(RRuntime.DOT_ALL_MTABLE, true); + @Child private LocalReadVariableNode readMTableSecond = LocalReadVariableNode.create(RRuntime.DOT_ALL_MTABLE, true); + @Child private LocalReadVariableNode readSigLength = LocalReadVariableNode.create(RRuntime.DOT_SIG_LENGTH, true); + @Child private LocalReadVariableNode readSigARgs = LocalReadVariableNode.create(RRuntime.DOT_SIG_ARGS, true); + @Child private ReadVariableNode getMethodsTableFind = ReadVariableNode.createFunctionLookup(null, ".getMethodsTable"); @Child private DirectCallNode getMethodsTableCall; @Child private RArgumentsNode argsNode = RArgumentsNode.create(); @Child private CastIntegerScalarNode castIntScalar = CastIntegerScalarNode.create(); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateSlot.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateSlot.java index a2c946ae120a024be18e96fed7ea7187c3c71adc..d94f0cbbfec8ec32bbe0e02619a62e6a14a57b6e 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateSlot.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateSlot.java @@ -16,21 +16,25 @@ package com.oracle.truffle.r.nodes.builtin.base; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.Truffle; -import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.nodes.DirectCallNode; import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.r.nodes.access.ConstantNode; import com.oracle.truffle.r.nodes.access.UpdateSlotNode; import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode; -import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode.ReadKind; -import com.oracle.truffle.r.nodes.builtin.*; +import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.function.ClassHierarchyNode; import com.oracle.truffle.r.nodes.function.ClassHierarchyNodeGen; import com.oracle.truffle.r.nodes.function.RCallNode; import com.oracle.truffle.r.nodes.function.WrapArgumentNode; import com.oracle.truffle.r.nodes.function.signature.RArgumentsNode; -import com.oracle.truffle.r.runtime.*; +import com.oracle.truffle.r.runtime.ArgumentsSignature; +import com.oracle.truffle.r.runtime.RArguments; +import com.oracle.truffle.r.runtime.RBuiltin; +import com.oracle.truffle.r.runtime.RBuiltinKind; +import com.oracle.truffle.r.runtime.RCaller; +import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RFunction; @@ -45,7 +49,7 @@ public abstract class UpdateSlot extends RBuiltinNode { @Child private ClassHierarchyNode objClassHierarchy; @Child private ClassHierarchyNode valClassHierarchy; @Child UpdateSlotNode updateSlotNode = com.oracle.truffle.r.nodes.access.UpdateSlotNodeGen.create(null, null, null); - @Child ReadVariableNode checkAtAssignmentFind = ReadVariableNode.create("checkAtAssignment", RType.Function, ReadKind.Normal); + @Child ReadVariableNode checkAtAssignmentFind = ReadVariableNode.createFunctionLookup(null, "checkAtAssignment"); @Child DirectCallNode checkAtAssignmentCall; @Child private RArgumentsNode argsNode = RArgumentsNode.create(); private final ConditionProfile cached = ConditionProfile.createBinaryProfile(); diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RASTUtils.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RASTUtils.java index 857e18ba40803c684a626e865c367ffbbf043235..07a443120adb8d89796e7f3058c9a51481a22c4c 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RASTUtils.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RASTUtils.java @@ -73,7 +73,7 @@ public class RASTUtils { */ @TruffleBoundary public static ReadVariableNode createReadVariableNode(String name) { - return ReadVariableNode.createForced(null, name, RType.Any); + return ReadVariableNode.create(name); } /** @@ -131,7 +131,7 @@ public class RASTUtils { public static Object checkForRSymbol(Object expr) { if (expr instanceof RSymbol) { String symbolName = ((RSymbol) expr).getName(); - return RDataFactory.createLanguage(ReadVariableNode.create(symbolName, false)); + return RDataFactory.createLanguage(ReadVariableNode.create(symbolName)); } else { return expr; } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RRootNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RRootNode.java index 5e4b1a989927b250228ee2b80c10ab9c550d866b..ad0e414d0dae7279dc743c1f22d7876290822008 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RRootNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RRootNode.java @@ -22,17 +22,19 @@ */ package com.oracle.truffle.r.nodes; -import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.api.frame.*; -import com.oracle.truffle.api.nodes.*; -import com.oracle.truffle.api.source.*; -import com.oracle.truffle.api.profiles.*; -import com.oracle.truffle.r.nodes.builtin.*; -import com.oracle.truffle.r.nodes.function.*; -import com.oracle.truffle.r.runtime.*; -import com.oracle.truffle.r.runtime.context.*; -import com.oracle.truffle.r.runtime.env.frame.*; +import com.oracle.truffle.api.frame.FrameDescriptor; +import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.api.nodes.RootNode; +import com.oracle.truffle.api.profiles.ConditionProfile; +import com.oracle.truffle.api.source.SourceSection; +import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; +import com.oracle.truffle.r.nodes.function.FormalArguments; +import com.oracle.truffle.r.nodes.function.FunctionDefinitionNode; +import com.oracle.truffle.r.runtime.ArgumentsSignature; +import com.oracle.truffle.r.runtime.HasSignature; +import com.oracle.truffle.r.runtime.RArguments; +import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.nodes.RSyntaxNode; /** @@ -41,7 +43,6 @@ import com.oracle.truffle.r.runtime.nodes.RSyntaxNode; */ public abstract class RRootNode extends RootNode implements HasSignature { - @CompilationFinal protected boolean checkSingletonFrame = true; private final ConditionProfile irregularFrameProfile = ConditionProfile.createBinaryProfile(); /** @@ -62,12 +63,10 @@ public abstract class RRootNode extends RootNode implements HasSignature { } } + public abstract RRootNode duplicateWithNewFrameDescriptor(); + protected void verifyEnclosingAssumptions(VirtualFrame vf) { RArguments.setIsIrregular(vf, irregularFrameProfile.profile(RArguments.getIsIrregular(vf))); - - if (checkSingletonFrame) { - checkSingletonFrame = FrameSlotChangeMonitor.checkSingletonFrame(vf); - } } /** diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RTruffleVisitor.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RTruffleVisitor.java index d5f01e14e6ce7f60437106ee5a48e5449ad17dee..cdfd9d7a27620f3ded27be7a3ac9a6d9ee6b9732 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RTruffleVisitor.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RTruffleVisitor.java @@ -91,7 +91,6 @@ import com.oracle.truffle.r.runtime.FastROptions; import com.oracle.truffle.r.runtime.RGroupGenerics; import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.RRuntime; -import com.oracle.truffle.r.runtime.RType; import com.oracle.truffle.r.runtime.data.FastPathFactory; import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.REmpty; @@ -110,6 +109,7 @@ public final class RTruffleVisitor extends BasicVisitor<RSyntaxNode> { public RFunction transformFunction(String name, Function func, MaterializedFrame enclosingFrame) { RootCallTarget callTarget = createFunctionCallTarget(func); FastPathFactory fastPath = EvaluatedArgumentsVisitor.process(func); + FrameSlotChangeMonitor.initializeEnclosingFrame(callTarget.getRootNode().getFrameDescriptor(), enclosingFrame); return RDataFactory.createFunction(name, callTarget, null, enclosingFrame, fastPath, ((FunctionDefinitionNode) callTarget.getRootNode()).containsDispatch()); } @@ -188,7 +188,7 @@ public final class RTruffleVisitor extends BasicVisitor<RSyntaxNode> { return GroupDispatchNode.create(callName, callSource, signature, nodes); } SourceSection varSource = ASTNode.adjustedSource(callSource, callSource.getCharIndex(), callName.length()); - lhs = ReadVariableNode.createForced(varSource, callName, RType.Function); + lhs = ReadVariableNode.createForcedFunctionLookup(varSource, callName); } else { lhs = call.getLhsNode().accept(this).asRNode(); } @@ -273,8 +273,8 @@ public final class RTruffleVisitor extends BasicVisitor<RSyntaxNode> { } FrameDescriptor descriptor = new FrameDescriptor(); - FrameSlotChangeMonitor.initializeFunctionFrameDescriptor(descriptor); String description = getFunctionDescription(func); + FrameSlotChangeMonitor.initializeFunctionFrameDescriptor(description != null && !description.isEmpty() ? description : "<function>", descriptor); FunctionDefinitionNode rootNode = new FunctionDefinitionNode(func.getSource(), descriptor, new FunctionBodyNode(saveArguments, statements), formals, description, false, argPostProcess); return Truffle.getRuntime().createCallTarget(rootNode); } @@ -357,7 +357,7 @@ public final class RTruffleVisitor extends BasicVisitor<RSyntaxNode> { nodes[nodes.length - 1] = rhs; names[nodes.length - 1] = "value"; - return RCallNode.createCallNotSyntax(ReadVariableNode.createForced(null, isSubset ? "[<-" : "[[<-", RType.Function), ArgumentsSignature.get(names), nodes); + return RCallNode.createCallNotSyntax(ReadVariableNode.createForcedFunctionLookup(null, isSubset ? "[<-" : "[[<-"), ArgumentsSignature.get(names), nodes); } private int tempNamesCount; @@ -560,12 +560,12 @@ public final class RTruffleVisitor extends BasicVisitor<RSyntaxNode> { public RSyntaxNode visit(FieldAccess access) { SourceSection callSource = access.getSource(); RSyntaxNode lhs = access.getLhs().accept(this); - ReadVariableNode function = ReadVariableNode.createForced(callSource, access.isAt() ? "@" : "$", RType.Function); + ReadVariableNode function = ReadVariableNode.createForcedFunctionLookup(callSource, access.isAt() ? "@" : "$"); return RCallNode.createCall(callSource, function, ArgumentsSignature.empty(2), lhs, ConstantNode.create(callSource, access.getFieldName())); } private static RCallNode createFieldUpdate(SourceSection source, RSyntaxNode receiver, RSyntaxNode rhs, String fieldName, boolean at) { - ReadVariableNode function = ReadVariableNode.createForced(source, at ? "@<-" : "$<-", RType.Function); + ReadVariableNode function = ReadVariableNode.createForcedFunctionLookup(source, at ? "@<-" : "$<-"); return RCallNode.createCall(source, function, ArgumentsSignature.empty(3), receiver, ConstantNode.create(source, fieldName), rhs); } @@ -584,7 +584,7 @@ public final class RTruffleVisitor extends BasicVisitor<RSyntaxNode> { argNodes[i] = visit(arguments.get(i)); } argNodes[arguments.size()] = rhs; - ReadVariableNode function = ReadVariableNode.createForced(null, funName, RType.Function); + ReadVariableNode function = ReadVariableNode.createForcedFunctionLookup(null, funName); return RCallNode.createCall(null, function, ArgumentsSignature.get(names), argNodes); } @@ -601,8 +601,8 @@ public final class RTruffleVisitor extends BasicVisitor<RSyntaxNode> { String tmpSymbol = createTempName(); String rhsSymbol = createTempName(); - ReadVariableNode rhsAccess = ReadVariableNode.createAnonymous(rhsSymbol); - ReadVariableNode tmpVarAccess = ReadVariableNode.createAnonymous(tmpSymbol); + ReadVariableNode rhsAccess = ReadVariableNode.create(rhsSymbol); + ReadVariableNode tmpVarAccess = ReadVariableNode.create(tmpSymbol); RSyntaxNode updateOp = updateFunction.apply(tmpVarAccess, rhsAccess); RNode assignFromTemp = WriteVariableNode.createAnonymous(vSymbol, updateOp.asRNode(), WriteVariableNode.Mode.INVISIBLE, isSuper); diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/AccessEnclosingFrameNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/AccessEnclosingFrameNode.java index 129161a0b2f79fb6990f5eb9aec19cff4258bb73..65b7e9f903c0cfa52e7785f2e7eb7db3f12e87c5 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/AccessEnclosingFrameNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/AccessEnclosingFrameNode.java @@ -22,17 +22,15 @@ */ package com.oracle.truffle.r.nodes.access; -import com.oracle.truffle.api.dsl.*; -import com.oracle.truffle.api.frame.*; -import com.oracle.truffle.r.runtime.*; -import com.oracle.truffle.r.runtime.nodes.*; +import com.oracle.truffle.api.frame.MaterializedFrame; +import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.api.nodes.Node; +import com.oracle.truffle.r.runtime.RArguments; -public abstract class AccessEnclosingFrameNode extends RNode { +public final class AccessEnclosingFrameNode extends Node { - public abstract MaterializedFrame executeMaterializedFrame(VirtualFrame frame); - - @Specialization - protected MaterializedFrame doMaterializedFrame(VirtualFrame frame) { + @SuppressWarnings("static-method") + public MaterializedFrame execute(VirtualFrame frame) { return RArguments.getEnclosingFrame(frame); } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/FrameSlotNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/FrameSlotNode.java index 94239a4ecdc4ec0ac015d8b4ba359168580b2027..efd6559640699bdb625b38f0b2194f7b697fce40 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/FrameSlotNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/FrameSlotNode.java @@ -65,7 +65,7 @@ public abstract class FrameSlotNode extends RBaseNode { FrameSlotNode newNode; FrameSlot frameSlot; if (createIfAbsent) { - frameSlot = findOrAddFrameSlot(frameDescriptor, identifier); + frameSlot = findOrAddFrameSlot(frameDescriptor, identifier, FrameSlotKind.Illegal); } else { frameSlot = frameDescriptor.findFrameSlot(identifier); } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/ReadVariadicComponentNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/ReadVariadicComponentNode.java index 5d88c4f1b3d61d0969934cc1bf21f007c38341df..7d10c1dd1e42962d4eb318c7b564741a439837f1 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/ReadVariadicComponentNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/ReadVariadicComponentNode.java @@ -22,25 +22,31 @@ */ package com.oracle.truffle.r.nodes.access; -import com.oracle.truffle.api.*; -import com.oracle.truffle.api.frame.*; -import com.oracle.truffle.api.source.*; -import com.oracle.truffle.api.profiles.*; -import com.oracle.truffle.r.nodes.access.variables.*; -import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode.ReadKind; -import com.oracle.truffle.r.nodes.function.*; -import com.oracle.truffle.r.runtime.*; +import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.api.profiles.BranchProfile; +import com.oracle.truffle.api.source.SourceSection; +import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode; +import com.oracle.truffle.r.nodes.function.PromiseHelperNode; +import com.oracle.truffle.r.runtime.ArgumentsSignature; import com.oracle.truffle.r.runtime.RDeparse.State; -import com.oracle.truffle.r.runtime.data.*; -import com.oracle.truffle.r.runtime.env.*; -import com.oracle.truffle.r.runtime.nodes.*; +import com.oracle.truffle.r.runtime.RError; +import com.oracle.truffle.r.runtime.RInternalError; +import com.oracle.truffle.r.runtime.RType; +import com.oracle.truffle.r.runtime.VisibilityController; +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.env.REnvironment; +import com.oracle.truffle.r.runtime.nodes.RNode; +import com.oracle.truffle.r.runtime.nodes.RSyntaxNode; /** * An {@link RNode} that handles accesses to components of the variadic argument (..1, ..2, etc.). */ -public class ReadVariadicComponentNode extends RNode implements RSyntaxNode { +public class ReadVariadicComponentNode extends RNode implements RSyntaxNode, VisibilityController { - @Child private ReadVariableNode lookup = ReadVariableNode.create(ArgumentsSignature.VARARG_NAME, RType.Any, ReadKind.Silent); + @Child private ReadVariableNode lookup = ReadVariableNode.createSilent(ArgumentsSignature.VARARG_NAME, RType.Any); @Child private PromiseHelperNode promiseHelper; private final int index; @@ -55,6 +61,8 @@ public class ReadVariadicComponentNode extends RNode implements RSyntaxNode { @Override public Object execute(VirtualFrame frame) { + controlVisibility(); + Object args = lookup.execute(frame); if (args == null) { errorBranch.enter(); diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteLocalFrameVariableNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteLocalFrameVariableNode.java index 62dacb8c91350f0160d49aeb9cebad595472f579..6661538c78d0e09294cb713a8f28b95f94ff11e9 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteLocalFrameVariableNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteLocalFrameVariableNode.java @@ -84,7 +84,7 @@ public abstract class WriteLocalFrameVariableNode extends BaseWriteVariableNode private void resolveAndSet(VirtualFrame frame, Object value, FrameSlotKind initialKind) { CompilerDirectives.transferToInterpreterAndInvalidate(); - // it's slow path (unconditional replace) so toStrin() is fine as well + // it's slow path (unconditional replace) so toString() is fine as well if (getName().toString().isEmpty()) { throw RError.error(this, RError.Message.ZERO_LENGTH_VARIABLE); } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteSuperFrameVariableNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteSuperFrameVariableNode.java index 540cb609f97f4f13c6190ea2ef9eea443e33e0c7..34a9fc76e2ed3b46acb245323f6389be11586780 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteSuperFrameVariableNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteSuperFrameVariableNode.java @@ -114,11 +114,12 @@ public abstract class WriteSuperFrameVariableNode extends WriteSuperFrameVariabl final WriteSuperFrameVariableNodeHelper writeNode; if (REnvironment.isGlobalEnvFrame(enclosingFrame)) { /* - * we've reached the global scope, do unconditional write // if this is the first - * node in the chain, needs the rhs and enclosingFrame // nodes + * we've reached the global scope, do unconditional write. if this is the first node + * in the chain, needs the rhs and enclosingFrame nodes */ - AccessEnclosingFrameNode enclosingFrameNode = RArguments.getEnclosingFrame(frame) == enclosingFrame ? AccessEnclosingFrameNodeGen.create() : null; - writeNode = WriteSuperFrameVariableNodeGen.create(getRhs(), enclosingFrameNode, FrameSlotNode.create(findOrAddFrameSlot(enclosingFrame.getFrameDescriptor(), symbol)), getName(), mode); + AccessEnclosingFrameNode enclosingFrameNode = RArguments.getEnclosingFrame(frame) == enclosingFrame ? new AccessEnclosingFrameNode() : null; + writeNode = WriteSuperFrameVariableNodeGen.create(getRhs(), enclosingFrameNode, + FrameSlotNode.create(findOrAddFrameSlot(enclosingFrame.getFrameDescriptor(), symbol, FrameSlotKind.Illegal)), getName(), mode); } else { WriteSuperFrameVariableNode actualWriteNode = WriteSuperFrameVariableNodeGen.create(null, null, FrameSlotNode.create(symbol), this.getName(), mode); writeNode = new WriteSuperFrameVariableConditionalNode(actualWriteNode, new UnresolvedWriteSuperFrameVariableNode(symbol, null, mode), getRhs()); 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 new file mode 100644 index 0000000000000000000000000000000000000000..21d2bd4a966e6d3a5ade7cee1686b1bad7c480bf --- /dev/null +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/LocalReadVariableNode.java @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2013, 2015, 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.access.variables; + +import com.oracle.truffle.api.Assumption; +import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; +import com.oracle.truffle.api.frame.Frame; +import com.oracle.truffle.api.frame.FrameSlot; +import com.oracle.truffle.api.frame.FrameSlotKind; +import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.api.nodes.InvalidAssumptionException; +import com.oracle.truffle.api.nodes.Node; +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.runtime.RError; +import com.oracle.truffle.r.runtime.data.RMissing; +import com.oracle.truffle.r.runtime.data.RPromise; + +public final class LocalReadVariableNode extends Node { + + @Child private PromiseHelperNode promiseHelper; + + private final Object identifier; + private final boolean forceResult; + + @CompilationFinal private boolean[] seenValueKinds; + @CompilationFinal private ValueProfile valueProfile; + @CompilationFinal private ConditionProfile isNullProfile; + @CompilationFinal private ConditionProfile isMissingProfile; + @CompilationFinal private ConditionProfile isPromiseProfile; + + @CompilationFinal private FrameSlot frameSlot; + @CompilationFinal private Assumption notInFrame; + + public static LocalReadVariableNode create(Object identifier, boolean forceResult) { + return new LocalReadVariableNode(identifier, forceResult); + } + + private LocalReadVariableNode(Object identifier, boolean forceResult) { + this.identifier = identifier; + this.forceResult = forceResult; + } + + public Object getIdentifier() { + return identifier; + } + + public Object execute(VirtualFrame frame) { + return execute(frame, frame); + } + + public Object execute(VirtualFrame frame, Frame variableFrame) { + if (frameSlot == null && notInFrame == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + if (identifier.toString().isEmpty()) { + throw RError.error(RError.NO_NODE, RError.Message.ZERO_LENGTH_VARIABLE); + } + frameSlot = variableFrame.getFrameDescriptor().findFrameSlot(identifier); + notInFrame = frameSlot == null ? variableFrame.getFrameDescriptor().getNotInFrameAssumption(identifier) : null; + } + // check if the slot is missing / wrong type in current frame + if (frameSlot == null) { + try { + notInFrame.check(); + } catch (InvalidAssumptionException e) { + frameSlot = variableFrame.getFrameDescriptor().findFrameSlot(identifier); + notInFrame = frameSlot == null ? variableFrame.getFrameDescriptor().getNotInFrameAssumption(identifier) : null; + } + } + if (frameSlot == null) { + return null; + } + Object result = null; + if (isMissingProfile == null) { + seenValueKinds = new boolean[FrameSlotKind.values().length]; + valueProfile = ValueProfile.createClassProfile(); + isNullProfile = ConditionProfile.createBinaryProfile(); + isMissingProfile = ConditionProfile.createBinaryProfile(); + } + result = valueProfile.profile(ReadVariableNode.profiledGetValue(seenValueKinds, variableFrame, frameSlot)); + if (isNullProfile.profile(result == null) || isMissingProfile.profile(result == RMissing.instance)) { + return null; + } + if (forceResult) { + if (isPromiseProfile == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + isPromiseProfile = ConditionProfile.createBinaryProfile(); + } + if (isPromiseProfile.profile(result instanceof RPromise)) { + if (promiseHelper == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + promiseHelper = insert(new PromiseHelperNode()); + } + result = promiseHelper.evaluate(frame, (RPromise) result); + } + } + return result; + } +} 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 118ab397931e3ad8fca6f4cf764fae28117cbd48..32e5dfd5096bd8f0b5beda499470abb251322cc3 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 @@ -22,23 +22,55 @@ */ package com.oracle.truffle.r.nodes.access.variables; -import java.util.*; +import java.util.ArrayList; -import com.oracle.truffle.api.*; +import com.oracle.truffle.api.Assumption; +import com.oracle.truffle.api.CompilerAsserts; +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.frame.*; -import com.oracle.truffle.api.nodes.*; -import com.oracle.truffle.api.source.*; -import com.oracle.truffle.api.profiles.*; -import com.oracle.truffle.r.nodes.*; -import com.oracle.truffle.r.nodes.function.*; -import com.oracle.truffle.r.runtime.*; -import com.oracle.truffle.r.runtime.data.*; -import com.oracle.truffle.r.runtime.data.model.*; -import com.oracle.truffle.r.runtime.env.*; -import com.oracle.truffle.r.runtime.env.frame.*; -import com.oracle.truffle.r.runtime.nodes.*; +import com.oracle.truffle.api.frame.Frame; +import com.oracle.truffle.api.frame.FrameDescriptor; +import com.oracle.truffle.api.frame.FrameSlot; +import com.oracle.truffle.api.frame.FrameSlotKind; +import com.oracle.truffle.api.frame.FrameSlotTypeException; +import com.oracle.truffle.api.frame.MaterializedFrame; +import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.api.nodes.ExplodeLoop; +import com.oracle.truffle.api.nodes.InvalidAssumptionException; +import com.oracle.truffle.api.nodes.NodeUtil; +import com.oracle.truffle.api.nodes.SlowPathException; +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.api.source.SourceSection; +import com.oracle.truffle.r.nodes.RASTUtils; +import com.oracle.truffle.r.nodes.function.PromiseHelperNode; +import com.oracle.truffle.r.runtime.AnonymousFrameVariable; +import com.oracle.truffle.r.runtime.ArgumentsSignature; +import com.oracle.truffle.r.runtime.FastROptions; +import com.oracle.truffle.r.runtime.RArguments; +import com.oracle.truffle.r.runtime.RDeparse; +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.RSerialize; +import com.oracle.truffle.r.runtime.RType; +import com.oracle.truffle.r.runtime.StableValue; +import com.oracle.truffle.r.runtime.VisibilityController; +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.RMissing; +import com.oracle.truffle.r.runtime.data.RNull; +import com.oracle.truffle.r.runtime.data.RPromise; +import com.oracle.truffle.r.runtime.data.model.RAbstractVector; +import com.oracle.truffle.r.runtime.env.REnvironment; +import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor; +import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor.FrameAndSlotLookupResult; +import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor.LookupResult; +import com.oracle.truffle.r.runtime.nodes.RNode; +import com.oracle.truffle.r.runtime.nodes.RSyntaxNode; /** * This node is used to read a variable from the local or enclosing environments. It specializes to @@ -47,73 +79,49 @@ import com.oracle.truffle.r.runtime.nodes.*; */ public final class ReadVariableNode extends RNode implements RSyntaxNode, VisibilityController { - public static enum ReadKind { + private static final int MAX_INVALIDATION_COUNT = 2; + + private enum ReadKind { Normal, - Unforced, // return null (instead of throwing an error) if not found Silent, // copy semantics Copying, // start the lookup in the enclosing frame Super, - // lookup only within the current frame - SilentLocal, - UnforcedSilentLocal, - // whether a promise should be forced to check its type or not + // whether a promise should be forced to check its type or not during lookup ForcedTypeCheck; } - public static ReadVariableNode create(String name, RType mode, ReadKind kind) { - return new ReadVariableNode(name, mode, kind, true); - } - - public static ReadVariableNode create(String name, boolean shouldCopyValue) { - return new ReadVariableNode(name, RType.Any, shouldCopyValue ? ReadKind.Copying : ReadKind.Normal, true); + public static ReadVariableNode create(String name) { + return new ReadVariableNode(name, RType.Any, ReadKind.Normal); } public static ReadVariableNode create(SourceSection src, String name, boolean shouldCopyValue) { - ReadVariableNode rvn = new ReadVariableNode(name, RType.Any, shouldCopyValue ? ReadKind.Copying : ReadKind.Normal, true); + ReadVariableNode rvn = new ReadVariableNode(name, RType.Any, shouldCopyValue ? ReadKind.Copying : ReadKind.Normal); rvn.assignSourceSection(src); return rvn; } - public static ReadVariableNode createForRefCount(Object name) { - return new ReadVariableNode(name, RType.Any, ReadKind.UnforcedSilentLocal, false); + public static ReadVariableNode createSilent(String name, RType mode) { + return new ReadVariableNode(name, mode, ReadKind.Silent); } - public static ReadVariableNode createAnonymous(String name) { - return new ReadVariableNode(name, RType.Any, ReadKind.Normal, true); + public static ReadVariableNode createSuperLookup(SourceSection src, String name) { + ReadVariableNode rvn = new ReadVariableNode(name, RType.Any, ReadKind.Super); + rvn.assignSourceSection(src); + return rvn; } - /** - * Creates a function lookup for the given identifier. - */ public static ReadVariableNode createFunctionLookup(SourceSection src, String identifier) { - ReadVariableNode result = new ReadVariableNode(identifier, RType.Function, ReadKind.Normal, true); + ReadVariableNode result = new ReadVariableNode(identifier, RType.Function, ReadKind.Normal); result.assignSourceSection(src); return result; } - public static ReadVariableNode createSuperLookup(SourceSection src, String name) { - ReadVariableNode rvn = new ReadVariableNode(name, RType.Any, ReadKind.Super, true); - rvn.assignSourceSection(src); - return rvn; - } - - /** - * Creates every {@link ReadVariableNode} out there. - * - * @param src A {@link SourceSection} for the variable - * @param name The symbol the {@link ReadVariableNode} is meant to resolve - * @param mode The mode of the variable - * - * @return The appropriate implementation of {@link ReadVariableNode} - */ - public static ReadVariableNode createForced(SourceSection src, String name, RType mode) { - ReadVariableNode result = new ReadVariableNode(name, mode, ReadKind.ForcedTypeCheck, true); - if (src != null) { - result.assignSourceSection(src); - } + public static ReadVariableNode createForcedFunctionLookup(SourceSection src, String name) { + ReadVariableNode result = new ReadVariableNode(name, RType.Function, ReadKind.ForcedTypeCheck); + result.assignSourceSection(src); return result; } @@ -121,30 +129,26 @@ public final class ReadVariableNode extends RNode implements RSyntaxNode, Visibi @CompilationFinal private FrameLevel read; @CompilationFinal private boolean needsCopying; - private final ConditionProfile isPromiseProfile; + private final ConditionProfile isPromiseProfile = ConditionProfile.createBinaryProfile(); private final ConditionProfile copyProfile; private final BranchProfile unexpectedMissingProfile = BranchProfile.create(); private final ValueProfile superEnclosingFrameProfile = ValueProfile.createClassProfile(); - private final ConditionProfile isNullValueProfile = ConditionProfile.createBinaryProfile(); - private final ValueProfile valueProfile = ValueProfile.createClassProfile(); private final Object identifier; private final String identifierAsString; private final RType mode; private final ReadKind kind; - private final boolean visibilityChange; + private int invalidationCount; @CompilationFinal private final boolean[] seenValueKinds = new boolean[FrameSlotKind.values().length]; - private ReadVariableNode(Object identifier, RType mode, ReadKind kind, boolean visibilityChange) { + private ReadVariableNode(Object identifier, RType mode, ReadKind kind) { this.identifier = identifier; this.identifierAsString = identifier.toString().intern(); this.mode = mode; this.kind = kind; - this.visibilityChange = visibilityChange; - isPromiseProfile = kind == ReadKind.UnforcedSilentLocal && mode == RType.Any ? null : ConditionProfile.createBinaryProfile(); - copyProfile = kind != ReadKind.Copying ? null : ConditionProfile.createBinaryProfile(); + this.copyProfile = kind != ReadKind.Copying ? null : ConditionProfile.createBinaryProfile(); } public String getIdentifier() { @@ -155,14 +159,6 @@ public final class ReadVariableNode extends RNode implements RSyntaxNode, Visibi return mode; } - public ReadKind getKind() { - return kind; - } - - private boolean seenValueKind(FrameSlotKind slotKind) { - return seenValueKinds[slotKind.ordinal()]; - } - @Override public void deparseImpl(RDeparse.State state) { state.startNodeDeparse(this); @@ -218,7 +214,7 @@ public final class ReadVariableNode extends RNode implements RSyntaxNode, Visibi } private Object executeInternal(VirtualFrame frame, Frame variableFrame) { - if (visibilityChange) { + if (kind != ReadKind.Silent) { controlVisibility(); } @@ -237,7 +233,7 @@ public final class ReadVariableNode extends RNode implements RSyntaxNode, Visibi result = read.execute(frame, variableFrame); } catch (InvalidAssumptionException | LayoutChangedException | FrameSlotTypeException e2) { if (iterations > 10) { - throw new RInternalError("too many iterations during RVN initialization"); + throw new RInternalError("too many iterations during RVN initialization: " + identifier); } continue; } @@ -247,7 +243,7 @@ public final class ReadVariableNode extends RNode implements RSyntaxNode, Visibi if (needsCopying && copyProfile.profile(result instanceof RAbstractVector)) { result = ((RAbstractVector) result).copy(); } - if (kind != ReadKind.UnforcedSilentLocal && kind != ReadKind.Unforced && isPromiseProfile.profile(result instanceof RPromise)) { + if (isPromiseProfile.profile(result instanceof RPromise)) { if (promiseHelper == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); promiseHelper = insert(new PromiseHelperNode()); @@ -289,17 +285,14 @@ public final class ReadVariableNode extends RNode implements RSyntaxNode, Visibi private final FrameSlot slot; private final ConditionProfile isNullProfile = ConditionProfile.createBinaryProfile(); - public Mismatch(FrameLevel next, FrameSlot slot) { + private Mismatch(FrameLevel next, FrameSlot slot) { this.next = next; this.slot = slot; } @Override public Object execute(VirtualFrame frame, Frame variableFrame) throws InvalidAssumptionException, LayoutChangedException, FrameSlotTypeException { - Object value = profiledGetValue(variableFrame, slot); - if ((kind == ReadKind.UnforcedSilentLocal || kind == ReadKind.SilentLocal) && value == RMissing.instance) { - return null; - } + Object value = profiledGetValue(seenValueKinds, variableFrame, slot); if (checkType(frame, value, isNullProfile)) { CompilerDirectives.transferToInterpreterAndInvalidate(); throw new LayoutChangedException(); @@ -318,7 +311,7 @@ public final class ReadVariableNode extends RNode implements RSyntaxNode, Visibi private final Assumption assumption; private final Object value; - public DescriptorStableMatch(Assumption assumption, Object value) { + private DescriptorStableMatch(Assumption assumption, Object value) { this.assumption = assumption; this.value = value; } @@ -340,16 +333,13 @@ public final class ReadVariableNode extends RNode implements RSyntaxNode, Visibi private final FrameSlot slot; private final ConditionProfile isNullProfile = ConditionProfile.createBinaryProfile(); - public Match(FrameSlot slot) { + private Match(FrameSlot slot) { this.slot = slot; } @Override public Object execute(VirtualFrame frame, Frame variableFrame) throws LayoutChangedException, FrameSlotTypeException { - Object value = profiledGetValue(variableFrame, slot); - if ((kind == ReadKind.UnforcedSilentLocal || kind == ReadKind.SilentLocal) && value == RMissing.instance) { - return null; - } + Object value = profiledGetValue(seenValueKinds, variableFrame, slot); if (!checkType(frame, value, isNullProfile)) { throw new LayoutChangedException(); } @@ -366,7 +356,7 @@ public final class ReadVariableNode extends RNode implements RSyntaxNode, Visibi @Override public Object execute(VirtualFrame frame) { - if (kind == ReadKind.Silent || kind == ReadKind.SilentLocal || kind == ReadKind.UnforcedSilentLocal) { + if (kind == ReadKind.Silent) { return null; } else { throw RError.error(RError.NO_NODE, mode == RType.Function ? RError.Message.UNKNOWN_FUNCTION : RError.Message.UNKNOWN_OBJECT, identifier); @@ -379,20 +369,19 @@ public final class ReadVariableNode extends RNode implements RSyntaxNode, Visibi } } - private static final class NextFrameFromDescriptorLevel extends DescriptorLevel { + private static final class SingletonFrameLevel extends DescriptorLevel { private final FrameLevel next; - private final StableValue<MaterializedFrame> enclosingFrameAssumption; + private final MaterializedFrame singletonFrame; - public NextFrameFromDescriptorLevel(FrameLevel next, StableValue<MaterializedFrame> enclosingFrameAssumption) { + private SingletonFrameLevel(FrameLevel next, MaterializedFrame singletonFrame) { this.next = next; - this.enclosingFrameAssumption = enclosingFrameAssumption; + this.singletonFrame = singletonFrame; } @Override public Object execute(VirtualFrame frame) throws InvalidAssumptionException, LayoutChangedException, FrameSlotTypeException { - enclosingFrameAssumption.getAssumption().check(); - return next.execute(frame, enclosingFrameAssumption.getValue()); + return next.execute(frame, singletonFrame); } @Override @@ -407,7 +396,7 @@ public final class ReadVariableNode extends RNode implements RSyntaxNode, Visibi private final FrameDescriptor nextDescriptor; private final ValueProfile frameProfile = ValueProfile.createClassProfile(); - public NextFrameLevel(FrameLevel next, FrameDescriptor nextDescriptor) { + private NextFrameLevel(FrameLevel next, FrameDescriptor nextDescriptor) { this.next = next; this.nextDescriptor = nextDescriptor; } @@ -442,7 +431,7 @@ public final class ReadVariableNode extends RNode implements RSyntaxNode, Visibi private final FrameLevel next; @CompilationFinal private final Assumption[] assumptions; - public MultiAssumptionLevel(FrameLevel next, Assumption[] assumptions) { + private MultiAssumptionLevel(FrameLevel next, Assumption... assumptions) { this.next = next; this.assumptions = assumptions; } @@ -462,135 +451,214 @@ public final class ReadVariableNode extends RNode implements RSyntaxNode, Visibi } } - private FrameLevel initialize(VirtualFrame frame, Frame variableFrame) { - if (identifier.toString().isEmpty()) { - throw RError.error(RError.NO_NODE, RError.Message.ZERO_LENGTH_VARIABLE); - } - - class ReadVariableLevel { - public final FrameDescriptor descriptor; - public final FrameSlot slot; - public final StableValue<Object> valueAssumption; - - public final StableValue<FrameDescriptor> enclosingDescriptorAssumption; - public final StableValue<MaterializedFrame> enclosingFrameAssumption; - - public final MaterializedFrame nextFrame; + private final class Polymorphic extends FrameLevel { - public ReadVariableLevel(FrameDescriptor descriptor, FrameSlot slot, StableValue<Object> valueAssumption, StableValue<FrameDescriptor> enclosingDescriptorAssumption, - StableValue<MaterializedFrame> enclosingFrameAssumption, MaterializedFrame nextFrame) { - this.descriptor = descriptor; - this.slot = slot; - this.valueAssumption = valueAssumption; - this.enclosingDescriptorAssumption = enclosingDescriptorAssumption; - this.enclosingFrameAssumption = enclosingFrameAssumption; - this.nextFrame = nextFrame; - } + private final ConditionProfile isNullProfile = ConditionProfile.createBinaryProfile(); + @CompilationFinal private FrameSlot frameSlot; + @CompilationFinal private Assumption notInFrame; - public FrameDescriptor nextDescriptor() { - return nextFrame == null ? null : nextFrame.getFrameDescriptor(); - } + private Polymorphic(Frame variableFrame) { + frameSlot = variableFrame.getFrameDescriptor().findFrameSlot(identifier); + notInFrame = frameSlot == null ? variableFrame.getFrameDescriptor().getNotInFrameAssumption(identifier) : null; } - ArrayList<ReadVariableLevel> levels = new ArrayList<>(); - - Frame current = variableFrame; - FrameDescriptor currentDescriptor = current.getFrameDescriptor(); - boolean match = false; - do { - // see if the current frame has a value of the given name - FrameSlot frameSlot = currentDescriptor.findFrameSlot(identifier); - StableValue<Object> valueAssumption = null; + @Override + public Object execute(VirtualFrame frame, Frame variableFrame) throws LayoutChangedException, FrameSlotTypeException { + // check if the slot is missing / wrong type in current frame + if (frameSlot == null) { + try { + notInFrame.check(); + } catch (InvalidAssumptionException e) { + frameSlot = variableFrame.getFrameDescriptor().findFrameSlot(identifier); + notInFrame = frameSlot == null ? variableFrame.getFrameDescriptor().getNotInFrameAssumption(identifier) : null; + } + } if (frameSlot != null) { - Object value = getValue(current, frameSlot); - valueAssumption = FrameSlotChangeMonitor.getStableValueAssumption(currentDescriptor, frameSlot, value); - if ((kind == ReadKind.UnforcedSilentLocal || kind == ReadKind.SilentLocal) && value == RMissing.instance) { - match = false; - } else { - match = checkTypeSlowPath(frame, value); + Object value = variableFrame.getValue(frameSlot); + if (checkType(frame, value, isNullProfile)) { + return value; } } - - // figure out how to get to the next frame or descriptor - MaterializedFrame next = RArguments.getEnclosingFrame(current); - FrameDescriptor nextDescriptor = next == null ? null : next.getFrameDescriptor(); - StableValue<MaterializedFrame> enclosingFrameAssumption = FrameSlotChangeMonitor.getOrInitializeEnclosingFrameAssumption(current, currentDescriptor, null, next); - StableValue<FrameDescriptor> enclosingDescriptorAssumption = FrameSlotChangeMonitor.getOrInitializeEnclosingFrameDescriptorAssumption(current, currentDescriptor, nextDescriptor); - - levels.add(new ReadVariableLevel(currentDescriptor, frameSlot, valueAssumption, enclosingDescriptorAssumption, enclosingFrameAssumption, next)); - - current = next; - currentDescriptor = nextDescriptor; - } while (kind != ReadKind.UnforcedSilentLocal && kind != ReadKind.SilentLocal && current != null && !match); - - FrameLevel lastLevel = null; - - boolean complex = false; - ListIterator<ReadVariableLevel> iter = levels.listIterator(levels.size()); - if (match) { - ReadVariableLevel level = levels.get(levels.size() - 1); - if (level.valueAssumption != null) { - Assumption assumption = level.valueAssumption.getAssumption(); - Object value = level.valueAssumption.getValue(); - if (kind != ReadKind.UnforcedSilentLocal && value instanceof RPromise) { - RPromise promise = (RPromise) value; - Object promiseValue = PromiseHelperNode.evaluateSlowPath(frame, promise); - if (promiseValue instanceof RFunction) { - value = promiseValue; - } + // search enclosing frames if necessary + MaterializedFrame current = RArguments.getEnclosingFrame(variableFrame); + while (current != null) { + Object value = getValue(current); + if (checkType(frame, value, isNullProfile)) { + return value; } - lastLevel = new DescriptorStableMatch(assumption, value); + current = RArguments.getEnclosingFrame(current); + } + if (kind == ReadKind.Silent) { + return null; } else { - complex = true; - lastLevel = new Match(level.slot); + throw RError.error(RError.NO_NODE, mode == RType.Function ? RError.Message.UNKNOWN_FUNCTION : RError.Message.UNKNOWN_OBJECT, identifier); } - iter.previous(); - } else { - lastLevel = new Unknown(); } - ArrayList<Assumption> assumptions = new ArrayList<>(); - while (iter.hasPrevious()) { - ReadVariableLevel level = iter.previous(); - if (lastLevel instanceof DescriptorLevel) { - if (level.enclosingDescriptorAssumption != null) { - assumptions.add(level.enclosingDescriptorAssumption.getAssumption()); - } else { - complex = true; - lastLevel = new NextFrameLevel(lastLevel, level.nextDescriptor()); - } + @TruffleBoundary + private Object getValue(MaterializedFrame current) { + FrameSlot slot = current.getFrameDescriptor().findFrameSlot(identifier); + return slot == null ? null : current.getValue(slot); + } + + @Override + public String toString() { + return "P"; + } + } + + private final class LookupLevel extends DescriptorLevel { + + private final LookupResult lookup; + + private LookupLevel(LookupResult lookup) { + this.lookup = lookup; + } + + @Override + public Object execute(VirtualFrame frame) throws InvalidAssumptionException, LayoutChangedException, FrameSlotTypeException { + Object value; + if (lookup instanceof FrameAndSlotLookupResult) { + FrameAndSlotLookupResult frameAndSlotLookupResult = (FrameAndSlotLookupResult) lookup; + value = profiledGetValue(seenValueKinds, frameAndSlotLookupResult.getFrame(), frameAndSlotLookupResult.getSlot()); } else { - if (level.enclosingFrameAssumption != null) { - lastLevel = new NextFrameFromDescriptorLevel(lastLevel, level.enclosingFrameAssumption); - } else { - complex = true; - lastLevel = new NextFrameLevel(lastLevel, level.nextDescriptor()); - } + value = lookup.getValue(); } + if (kind != ReadKind.Silent && value == null) { + throw RError.error(RError.NO_NODE, mode == RType.Function ? RError.Message.UNKNOWN_FUNCTION : RError.Message.UNKNOWN_OBJECT, identifier); + } + return value; + } + } - if (level.slot == null) { - if (lastLevel instanceof DescriptorLevel) { - assumptions.add(level.descriptor.getNotInFrameAssumption(identifier)); - } else { - assumptions.add(level.descriptor.getNotInFrameAssumption(identifier)); + private FrameLevel initialize(VirtualFrame frame, Frame variableFrame) { + if (identifier.toString().isEmpty()) { + throw RError.error(RError.NO_NODE, RError.Message.ZERO_LENGTH_VARIABLE); + } + + /* + * Check whether we need to go to the polymorphic case, which will not rely on any frame + * descriptor assumptions (apart from the first frame). + */ + if (++invalidationCount > MAX_INVALIDATION_COUNT) { + RError.performanceWarning("polymorphic (slow path) lookup of symbol \"" + identifier + "\""); + return new Polymorphic(variableFrame); + } + + /* + * Check whether we can fulfill the lookup by only looking at the current frame, and thus + * without additional dependencies on frame descriptor layouts. + */ + FrameSlot localSlot = variableFrame.getFrameDescriptor().findFrameSlot(identifier); + // non-local reads can only be handled in a simple way if they are successful + if (localSlot != null && checkTypeSlowPath(frame, getValue(seenValueKinds, variableFrame, localSlot))) { + return new Match(localSlot); + } + + /* + * Check whether the frame descriptor information available in FrameSlotChangeMonitor is + * enough to handle this lookup. This has the advantage of not depending on a specific + * "enclosing frame descriptor" chain, so that attaching/detaching environments does not + * necessarily invalidate lookups. + */ + LookupResult lookup = FrameSlotChangeMonitor.lookup(variableFrame, identifier); + if (lookup != null) { + try { + if (lookup.getValue() == null) { + return new LookupLevel(lookup); } - } else { - if (level.valueAssumption != null && lastLevel instanceof DescriptorLevel) { - assumptions.add(level.valueAssumption.getAssumption()); - } else { - complex = true; - lastLevel = new Mismatch(lastLevel, level.slot); + if (checkTypeSlowPath(frame, lookup.getValue())) { + return new LookupLevel(lookup); } + } catch (InvalidAssumptionException e) { + // immediately invalidated... } } + + /* + * If everything else fails: build the lookup from scratch, by recursively building + * assumptions and checks. + */ + ArrayList<Assumption> assumptions = new ArrayList<>(); + FrameLevel lastLevel = createLevels(frame, variableFrame, assumptions); if (!assumptions.isEmpty()) { lastLevel = new MultiAssumptionLevel(lastLevel, assumptions.toArray(new Assumption[assumptions.size()])); } - if (FastROptions.PrintComplexLookups.getBooleanValue() && levels.size() > 1 && complex) { + if (FastROptions.PrintComplexLookups.getBooleanValue()) { System.out.println(identifier + " " + lastLevel); } + return lastLevel; + } + /** + * This function returns a "recipe" to find the value of this lookup, starting at varibleFrame. + * It may record assumptions into the given ArrayList of assumptions. The result will be a + * linked list of {@link FrameLevel} instances. + */ + private FrameLevel createLevels(VirtualFrame frame, Frame variableFrame, ArrayList<Assumption> assumptions) { + if (variableFrame == null) { + // this means that we've arrived at the empty env during lookup + return new Unknown(); + } + // see if the current frame has a value of the given name + FrameDescriptor currentDescriptor = variableFrame.getFrameDescriptor(); + FrameSlot frameSlot = currentDescriptor.findFrameSlot(identifier); + if (frameSlot != null) { + Object value = getValue(seenValueKinds, variableFrame, frameSlot); + if (checkTypeSlowPath(frame, value)) { + StableValue<Object> valueAssumption = FrameSlotChangeMonitor.getStableValueAssumption(currentDescriptor, frameSlot, value); + if (valueAssumption != null) { + Assumption assumption = valueAssumption.getAssumption(); + assert value == valueAssumption.getValue() || value.equals(valueAssumption.getValue()) : value + " vs. " + valueAssumption.getValue(); + if (value instanceof RPromise) { + RPromise promise = (RPromise) value; + Object promiseValue = PromiseHelperNode.evaluateSlowPath(frame, promise); + if (promiseValue instanceof RFunction) { + value = promiseValue; + } + } + return new DescriptorStableMatch(assumption, value); + } else { + return new Match(frameSlot); + } + } + } + + // the identifier wasn't found in the current frame: try the next one + MaterializedFrame next = RArguments.getEnclosingFrame(variableFrame); + FrameLevel lastLevel = createLevels(frame, next, assumptions); + + /* + * Here we look at the type of the recursive lookup result, to see if we need only a + * specific FrameDescriptor (DescriptorLevel) or the actual frame (FrameLevel). + */ + + if (!(lastLevel instanceof DescriptorLevel)) { + MaterializedFrame singleton = FrameSlotChangeMonitor.getSingletonFrame(next.getFrameDescriptor()); + if (singleton != null) { + // use singleton frames to get from a frame descriptor to an actual frame + lastLevel = new SingletonFrameLevel(lastLevel, singleton); + } + } + + StableValue<FrameDescriptor> enclosingDescriptorAssumption = FrameSlotChangeMonitor.getEnclosingFrameDescriptorAssumption(currentDescriptor); + if (lastLevel instanceof DescriptorLevel && enclosingDescriptorAssumption != null) { + assumptions.add(enclosingDescriptorAssumption.getAssumption()); + } else { + lastLevel = new NextFrameLevel(lastLevel, next == null ? null : next.getFrameDescriptor()); + } + + if (frameSlot == null) { + assumptions.add(currentDescriptor.getNotInFrameAssumption(identifier)); + } else { + StableValue<Object> valueAssumption = FrameSlotChangeMonitor.getStableValueAssumption(currentDescriptor, frameSlot, getValue(seenValueKinds, variableFrame, frameSlot)); + if (valueAssumption != null && lastLevel instanceof DescriptorLevel) { + assumptions.add(valueAssumption.getAssumption()); + } else { + lastLevel = new Mismatch(lastLevel, frameSlot); + } + } return lastLevel; } @@ -653,7 +721,7 @@ public final class ReadVariableNode extends RNode implements RSyntaxNode, Visibi return null; } - private Object getValue(Frame variableFrame, FrameSlot frameSlot) { + private static Object getValue(boolean[] seenValueKinds, Frame variableFrame, FrameSlot frameSlot) { Object value = variableFrame.getValue(frameSlot); if (variableFrame.isObject(frameSlot)) { seenValueKinds[FrameSlotKind.Object.ordinal()] = true; @@ -667,18 +735,23 @@ public final class ReadVariableNode extends RNode implements RSyntaxNode, Visibi return value; } - private Object profiledGetValue(Frame variableFrame, FrameSlot frameSlot) throws FrameSlotTypeException { - if (seenValueKind(FrameSlotKind.Object) && variableFrame.isObject(frameSlot)) { - Object result = variableFrame.getObject(frameSlot); - return isNullValueProfile.profile(result == null) ? null : valueProfile.profile(result); - } else if (seenValueKind(FrameSlotKind.Byte) && variableFrame.isByte(frameSlot)) { - return variableFrame.getByte(frameSlot); - } else if (seenValueKind(FrameSlotKind.Int) && variableFrame.isInt(frameSlot)) { - return variableFrame.getInt(frameSlot); - } else if (seenValueKind(FrameSlotKind.Double) && variableFrame.isDouble(frameSlot)) { - return variableFrame.getDouble(frameSlot); - } else { - throw new FrameSlotTypeException(); + static Object profiledGetValue(boolean[] seenValueKinds, Frame variableFrame, FrameSlot frameSlot) { + try { + if (seenValueKinds[FrameSlotKind.Object.ordinal()] && variableFrame.isObject(frameSlot)) { + return variableFrame.getObject(frameSlot); + } else if (seenValueKinds[FrameSlotKind.Byte.ordinal()] && variableFrame.isByte(frameSlot)) { + return variableFrame.getByte(frameSlot); + } else if (seenValueKinds[FrameSlotKind.Int.ordinal()] && variableFrame.isInt(frameSlot)) { + return variableFrame.getInt(frameSlot); + } else if (seenValueKinds[FrameSlotKind.Double.ordinal()] && variableFrame.isDouble(frameSlot)) { + return variableFrame.getDouble(frameSlot); + } else { + CompilerDirectives.transferToInterpreterAndInvalidate(); + // re-profile to widen the set of expected types + return getValue(seenValueKinds, variableFrame, frameSlot); + } + } catch (FrameSlotTypeException e) { + throw new RInternalError(e, "unexpected frame slot type mismatch"); } } @@ -773,4 +846,8 @@ public final class ReadVariableNode extends RNode implements RSyntaxNode, Visibi public static String getSlowPathEvaluationName() { return slowPathEvaluationName.get(); } + + public boolean isForceForTypeCheck() { + return kind == ReadKind.ForcedTypeCheck; + } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinNode.java index abf25dc6adbd826251d160da2e1c18edb93431b7..8a5f58ec773d5c847ec6dd085519c8875b97f1df 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinNode.java @@ -218,7 +218,7 @@ public abstract class RBuiltinNode extends RNode implements RSyntaxNode, Visibil // Setup FrameDescriptor frameDescriptor = new FrameDescriptor(); RBuiltinRootNode root = new RBuiltinRootNode(node, formals, frameDescriptor); - FrameSlotChangeMonitor.initializeFunctionFrameDescriptor(frameDescriptor); + FrameSlotChangeMonitor.initializeFunctionFrameDescriptor(builtin.getName(), frameDescriptor); return Truffle.getRuntime().createCallTarget(root); } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinRootNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinRootNode.java index c1b14a97dde3c78597f7cb39b107597e8158d206..4964dbb441a3b501b716a5aabc44010b06151e75 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinRootNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinRootNode.java @@ -30,6 +30,7 @@ import com.oracle.truffle.r.nodes.function.*; import com.oracle.truffle.r.runtime.*; import com.oracle.truffle.r.runtime.RDeparse.State; import com.oracle.truffle.r.runtime.env.REnvironment; +import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor; import com.oracle.truffle.r.runtime.nodes.*; public final class RBuiltinRootNode extends RRootNode implements RSyntaxNode { @@ -41,6 +42,13 @@ public final class RBuiltinRootNode extends RRootNode implements RSyntaxNode { this.builtin = builtin; } + @Override + public RRootNode duplicateWithNewFrameDescriptor() { + FrameDescriptor frameDescriptor = new FrameDescriptor(); + FrameSlotChangeMonitor.initializeFunctionFrameDescriptor(builtin.getBuiltin().getName(), frameDescriptor); + return new RBuiltinRootNode((RBuiltinNode) builtin.deepCopy(), getFormalArguments(), frameDescriptor); + } + @Override public Object execute(VirtualFrame frame) { verifyEnclosingAssumptions(frame); diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ForNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ForNode.java index 79d514333e01ca9fdb437c183737f695d9f851b8..2daa99a8d845f2f32b5b54c263b03d9a201baa07 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ForNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ForNode.java @@ -54,7 +54,7 @@ public final class ForNode extends AbstractLoopNode implements VisibilityControl this.writeIndexNode = WriteVariableNode.createAnonymous(indexName, null, Mode.REGULAR); this.writeRangeNode = WriteVariableNode.createAnonymous(rangeName, range, Mode.REGULAR); - this.writeLengthNode = WriteVariableNode.createAnonymous(lengthName, RLengthNodeGen.create(ReadVariableNode.create(rangeName, false)), Mode.REGULAR); + this.writeLengthNode = WriteVariableNode.createAnonymous(lengthName, RLengthNodeGen.create(ReadVariableNode.create(rangeName)), Mode.REGULAR); this.loopNode = Truffle.getRuntime().createLoopNode(new ForRepeatingNode(this, cvar, body, indexName, lengthName, rangeName)); } @@ -174,8 +174,8 @@ public final class ForNode extends AbstractLoopNode implements VisibilityControl this.writeElementNode = cvar; this.body = body; - this.readIndexNode = ReadVariableNode.createAnonymous(indexName); - this.readLengthNode = ReadVariableNode.createAnonymous(lengthName); + this.readIndexNode = ReadVariableNode.create(indexName); + this.readLengthNode = ReadVariableNode.create(lengthName); this.writeIndexNode = WriteVariableNode.createAnonymous(indexName, null, Mode.REGULAR); this.loadElement = createIndexedLoad(indexName, rangeName); // pre-initialize the profile so that loop exits to not deoptimize @@ -190,8 +190,8 @@ public final class ForNode extends AbstractLoopNode implements VisibilityControl throw RInternalError.shouldNotReachHere(); } REnvironment env = RDataFactory.createInternalEnv(); - env.safePut("i", RDataFactory.createLanguage(ReadVariableNode.createAnonymous(indexName))); - env.safePut("x", RDataFactory.createLanguage(ReadVariableNode.createAnonymous(rangeName))); + env.safePut("i", RDataFactory.createLanguage(ReadVariableNode.create(indexName))); + env.safePut("x", RDataFactory.createLanguage(ReadVariableNode.create(rangeName))); return indexNode.substitute(env).asRNode(); } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ClassHierarchyNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ClassHierarchyNode.java index b7eea96f781c65101f1b815deafccf178422a2ad..2adf0b11b54d51d7e8714ab8591e6e424a8967cb 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ClassHierarchyNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ClassHierarchyNode.java @@ -22,18 +22,36 @@ */ package com.oracle.truffle.r.nodes.function; -import com.oracle.truffle.api.*; +import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.api.dsl.*; +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.interop.TruffleObject; -import com.oracle.truffle.api.profiles.*; +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.access.variables.ReadVariableNode; -import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode.ReadKind; -import com.oracle.truffle.r.nodes.attributes.*; -import com.oracle.truffle.r.nodes.unary.*; -import com.oracle.truffle.r.runtime.*; +import com.oracle.truffle.r.nodes.attributes.AttributeAccess; +import com.oracle.truffle.r.nodes.attributes.AttributeAccessNodeGen; +import com.oracle.truffle.r.nodes.unary.CastToVectorNode; +import com.oracle.truffle.r.nodes.unary.UnaryNode; +import com.oracle.truffle.r.runtime.RInternalError; +import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.context.RContext; -import com.oracle.truffle.r.runtime.data.*; +import com.oracle.truffle.r.runtime.data.RAttributable; +import com.oracle.truffle.r.runtime.data.RAttributeStorage; +import com.oracle.truffle.r.runtime.data.RAttributes; +import com.oracle.truffle.r.runtime.data.RComplex; +import com.oracle.truffle.r.runtime.data.RComplexVector; +import com.oracle.truffle.r.runtime.data.RDataFactory; +import com.oracle.truffle.r.runtime.data.RDoubleVector; +import com.oracle.truffle.r.runtime.data.RFunction; +import com.oracle.truffle.r.runtime.data.RIntVector; +import com.oracle.truffle.r.runtime.data.RLogicalVector; +import com.oracle.truffle.r.runtime.data.RNull; +import com.oracle.truffle.r.runtime.data.RStringVector; +import com.oracle.truffle.r.runtime.data.RTypedValue; import com.oracle.truffle.r.runtime.env.REnvironment; import com.oracle.truffle.r.runtime.nodes.RBaseNode; @@ -141,7 +159,7 @@ abstract class S4Class extends RBaseNode { public abstract RStringVector executeRStringVector(String classAttr); - @Child private ReadVariableNode sExtendsForS3Find = ReadVariableNode.create(".extendsForS3", RType.Function, ReadKind.Normal); + @Child private ReadVariableNode sExtendsForS3Find = ReadVariableNode.createFunctionLookup(null, ".extendsForS3"); @Child private CastToVectorNode castToVector = CastToVectorNode.create(); @TruffleBoundary 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 72a6e114e8f9519d668baf8679c0ff6a9c5a9289..b59153173da7e361a83bbbca7f01c7750d4849fc 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 @@ -115,18 +115,26 @@ public final class FunctionDefinitionNode extends RRootNode implements RSyntaxNo public FunctionDefinitionNode(SourceSection src, FrameDescriptor frameDesc, BodyNode body, FormalArguments formals, String description, boolean substituteFrame, boolean skipExit, PostProcessArgumentsNode argPostProcess) { super(src, formals, frameDesc); + assert FrameSlotChangeMonitor.isValidFrameDescriptor(frameDesc); this.body = body; this.uninitializedBody = body; this.description = description; this.substituteFrame = substituteFrame; this.onExitSlot = skipExit ? null : FrameSlotNode.createInitialized(frameDesc, RFrameSlot.OnExit, false); this.uuid = FunctionUIDFactory.get().createUID(); - this.checkSingletonFrame = !substituteFrame; this.needsSplitting = needsAnyBuiltinSplitting(); this.containsDispatch = containsAnyDispatch(body); this.argPostProcess = argPostProcess; } + @Override + public RRootNode duplicateWithNewFrameDescriptor() { + FrameDescriptor frameDesc = new FrameDescriptor(); + FrameSlotChangeMonitor.initializeFunctionFrameDescriptor(description != null && !description.isEmpty() ? description : "<function>", frameDesc); + return new FunctionDefinitionNode(getSourceSection(), frameDesc, (BodyNode) body.deepCopy(), getFormalArguments(), description, substituteFrame, argPostProcess == null ? null + : (PostProcessArgumentsNode) argPostProcess.deepCopy()); + } + private static boolean containsAnyDispatch(BodyNode body) { NodeCountFilter dispatchingMethodsFilter = node -> { if (node instanceof ReadVariableNode) { @@ -332,10 +340,6 @@ public final class FunctionDefinitionNode extends RRootNode implements RSyntaxNo return description == null ? "<no source>" : description; } - public String parentToString() { - return super.toString(); - } - @Override public boolean isCloningAllowed() { return !substituteFrame; @@ -373,7 +377,10 @@ public final class FunctionDefinitionNode extends RRootNode implements RSyntaxNo @Override public RSyntaxNode substituteImpl(REnvironment env) { - return new FunctionDefinitionNode(null, new FrameDescriptor(), (BodyNode) body.substitute(env).asRNode(), getFormalArguments(), null, substituteFrame, argPostProcess); + FrameDescriptor frameDesc = new FrameDescriptor(); + + FrameSlotChangeMonitor.initializeFunctionFrameDescriptor("<substituted function>", frameDesc); + return new FunctionDefinitionNode(null, frameDesc, (BodyNode) body.substitute(env).asRNode(), getFormalArguments(), null, substituteFrame, argPostProcess); } /** diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/FunctionExpressionNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/FunctionExpressionNode.java index 9658e8317b3d2ecde6ab2e95b8e1b440ca7fcf81..780327236e7ba103c1cf1f5954340fb711439e0a 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/FunctionExpressionNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/FunctionExpressionNode.java @@ -22,20 +22,27 @@ */ package com.oracle.truffle.r.nodes.function; -import com.oracle.truffle.api.*; +import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; -import com.oracle.truffle.api.frame.*; -import com.oracle.truffle.api.nodes.*; -import com.oracle.truffle.api.source.*; +import com.oracle.truffle.api.RootCallTarget; +import com.oracle.truffle.api.Truffle; +import com.oracle.truffle.api.frame.MaterializedFrame; +import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.api.source.SourceSection; import com.oracle.truffle.r.nodes.function.PromiseHelperNode.PromiseDeoptimizeFrameNode; -import com.oracle.truffle.r.nodes.function.opt.*; -import com.oracle.truffle.r.nodes.instrument.*; -import com.oracle.truffle.r.runtime.*; -import com.oracle.truffle.r.runtime.data.*; -import com.oracle.truffle.r.runtime.env.*; -import com.oracle.truffle.r.runtime.env.frame.*; -import com.oracle.truffle.r.runtime.gnur.*; -import com.oracle.truffle.r.runtime.nodes.*; +import com.oracle.truffle.r.nodes.function.opt.EagerEvalHelper; +import com.oracle.truffle.r.nodes.instrument.RInstrument; +import com.oracle.truffle.r.runtime.RDeparse; +import com.oracle.truffle.r.runtime.RInternalError; +import com.oracle.truffle.r.runtime.RSerialize; +import com.oracle.truffle.r.runtime.data.FastPathFactory; +import com.oracle.truffle.r.runtime.data.RDataFactory; +import com.oracle.truffle.r.runtime.data.RFunction; +import com.oracle.truffle.r.runtime.env.REnvironment; +import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor; +import com.oracle.truffle.r.runtime.gnur.SEXPTYPE; +import com.oracle.truffle.r.runtime.nodes.RNode; +import com.oracle.truffle.r.runtime.nodes.RSyntaxNode; public final class FunctionExpressionNode extends RNode implements RSyntaxNode { @@ -47,17 +54,13 @@ public final class FunctionExpressionNode extends RNode implements RSyntaxNode { private final PromiseDeoptimizeFrameNode deoptFrameNode; private final FastPathFactory fastPath; - @CompilationFinal private StableValue<MaterializedFrame> enclosingFrameAssumption; - @CompilationFinal private StableValue<FrameDescriptor> enclosingFrameDescriptorAssumption; + @CompilationFinal private boolean initialized = false; private FunctionExpressionNode(SourceSection src, RootCallTarget callTarget, FastPathFactory fastPath) { this.fastPath = fastPath; assignSourceSection(src); this.callTarget = callTarget; this.deoptFrameNode = EagerEvalHelper.optExprs() || EagerEvalHelper.optVars() || EagerEvalHelper.optDefault() ? new PromiseDeoptimizeFrameNode() : null; - - this.enclosingFrameAssumption = FrameSlotChangeMonitor.getEnclosingFrameAssumption(callTarget.getRootNode().getFrameDescriptor()); - this.enclosingFrameDescriptorAssumption = FrameSlotChangeMonitor.getEnclosingFrameDescriptorAssumption(callTarget.getRootNode().getFrameDescriptor()); } @Override @@ -65,37 +68,6 @@ public final class FunctionExpressionNode extends RNode implements RSyntaxNode { return executeFunction(frame); } - protected void verifyEnclosingAssumptions(VirtualFrame enclosingFrame, FrameDescriptor descriptor) { - if (enclosingFrameAssumption != null) { - try { - enclosingFrameAssumption.getAssumption().check(); - } catch (InvalidAssumptionException e) { - enclosingFrameAssumption = FrameSlotChangeMonitor.getEnclosingFrameAssumption(descriptor); - } - if (enclosingFrameAssumption != null) { - if (enclosingFrameAssumption.getValue() != enclosingFrame) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - enclosingFrameAssumption = FrameSlotChangeMonitor.getOrInitializeEnclosingFrameAssumption(null, descriptor, enclosingFrameAssumption, enclosingFrame.materialize()); - } - } - } - if (enclosingFrameDescriptorAssumption != null) { - try { - enclosingFrameDescriptorAssumption.getAssumption().check(); - } catch (InvalidAssumptionException e) { - enclosingFrameDescriptorAssumption = FrameSlotChangeMonitor.getEnclosingFrameDescriptorAssumption(descriptor); - } - if (enclosingFrameDescriptorAssumption != null) { - FrameDescriptor enclosingFrameDescriptor = enclosingFrame.getFrameDescriptor(); - if (enclosingFrameDescriptorAssumption.getValue() != enclosingFrameDescriptor) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - enclosingFrameDescriptorAssumption.getAssumption().invalidate(); - enclosingFrameDescriptorAssumption = FrameSlotChangeMonitor.getOrInitializeEnclosingFrameDescriptorAssumption(null, descriptor, enclosingFrameDescriptor); - } - } - } - } - @Override public RFunction executeFunction(VirtualFrame frame) { MaterializedFrame matFrame = frame.materialize(); @@ -103,7 +75,11 @@ public final class FunctionExpressionNode extends RNode implements RSyntaxNode { // Deoptimize every promise which is now in this frame, as it might leave it's stack deoptFrameNode.deoptimizeFrame(matFrame); } - verifyEnclosingAssumptions(frame, callTarget.getRootNode().getFrameDescriptor()); + if (!initialized) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + FrameSlotChangeMonitor.initializeEnclosingFrame(callTarget.getRootNode().getFrameDescriptor(), frame); + initialized = true; + } boolean containsDispatch = ((FunctionDefinitionNode) callTarget.getRootNode()).containsDispatch(); RFunction func = RDataFactory.createFunction(RFunction.NO_NAME, callTarget, null, matFrame, fastPath, containsDispatch); if (RInstrument.instrumentingEnabled()) { diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/GroupDispatchNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/GroupDispatchNode.java index a4066e46f3ad54313dc1551ce0fe38dc864e2abd..1e55e597b6353013691ce7b30e738d5b3048f4e3 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/GroupDispatchNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/GroupDispatchNode.java @@ -16,12 +16,11 @@ import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.nodes.UnexpectedResultException; -import com.oracle.truffle.api.source.SourceSection; import com.oracle.truffle.api.profiles.ConditionProfile; +import com.oracle.truffle.api.source.SourceSection; import com.oracle.truffle.r.nodes.RASTUtils; import com.oracle.truffle.r.nodes.access.ConstantNode; import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode; -import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode.ReadKind; import com.oracle.truffle.r.nodes.function.S3FunctionLookupNode.NoGenericMethodException; import com.oracle.truffle.r.nodes.function.S3FunctionLookupNode.Result; import com.oracle.truffle.r.nodes.runtime.RASTDeparse; @@ -165,7 +164,7 @@ public final class GroupDispatchNode extends RNode implements RSyntaxNode { if (callArgsNode.containsVarArgsSymbol()) { if (lookupVarArgs == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); - lookupVarArgs = insert(ReadVariableNode.create(ArgumentsSignature.VARARG_NAME, RType.Any, ReadKind.Silent)); + lookupVarArgs = insert(ReadVariableNode.createSilent(ArgumentsSignature.VARARG_NAME, RType.Any)); } try { varArgs = lookupVarArgs.executeRArgsValuesAndNames(frame); diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PostProcessArgumentsNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PostProcessArgumentsNode.java index ef4850ed07dbe617c041311e14947f04a8530eeb..d06ae676833dc376872a2e2ad16dd46ac3c014db 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PostProcessArgumentsNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PostProcessArgumentsNode.java @@ -22,14 +22,17 @@ */ package com.oracle.truffle.r.nodes.function; -import com.oracle.truffle.api.*; +import com.oracle.truffle.api.CompilerAsserts; +import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; -import com.oracle.truffle.api.frame.*; -import com.oracle.truffle.api.nodes.*; -import com.oracle.truffle.api.profiles.*; -import com.oracle.truffle.r.nodes.access.variables.*; -import com.oracle.truffle.r.runtime.data.*; -import com.oracle.truffle.r.runtime.nodes.*; +import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.api.nodes.ExplodeLoop; +import com.oracle.truffle.api.nodes.Node; +import com.oracle.truffle.api.profiles.ConditionProfile; +import com.oracle.truffle.r.nodes.access.variables.LocalReadVariableNode; +import com.oracle.truffle.r.runtime.data.RNull; +import com.oracle.truffle.r.runtime.data.RShareable; +import com.oracle.truffle.r.runtime.nodes.RNode; /** * Encapsulates the nodes that decrement reference count incremented when the argument node is @@ -37,7 +40,7 @@ import com.oracle.truffle.r.runtime.nodes.*; */ public final class PostProcessArgumentsNode extends RNode { - @Children protected final ReadVariableNode[] sequence; + @Children protected final LocalReadVariableNode[] sequence; @Child private PostProcessArgumentsNode nextOptPostProccessArgNode; @CompilationFinal public int transArgsBitSet; // the first time this node is cloned (via FunctionDefinitionNode) it's from the trufflerizer - @@ -46,7 +49,7 @@ public final class PostProcessArgumentsNode extends RNode { @CompilationFinal private boolean createClone; private final ConditionProfile isRefCountUpdateable = ConditionProfile.createBinaryProfile(); - private PostProcessArgumentsNode(ReadVariableNode[] sequence) { + private PostProcessArgumentsNode(LocalReadVariableNode[] sequence) { this.sequence = sequence; this.createClone = false; this.transArgsBitSet = 0; @@ -54,9 +57,9 @@ public final class PostProcessArgumentsNode extends RNode { public static PostProcessArgumentsNode create(int length) { int maxLength = Math.min(length, ArgumentStatePush.MAX_COUNTED_ARGS); - ReadVariableNode[] argReadNodes = new ReadVariableNode[maxLength]; + LocalReadVariableNode[] argReadNodes = new LocalReadVariableNode[maxLength]; for (int i = 0; i < maxLength; i++) { - argReadNodes[i] = ReadVariableNode.createForRefCount(Integer.valueOf(1 << i)); + argReadNodes[i] = LocalReadVariableNode.create(Integer.valueOf(1 << i), false); } return new PostProcessArgumentsNode(argReadNodes); } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PromiseNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PromiseNode.java index 52a6a597ccfba2534927dc325e7a92d1a696a4d8..e8b7167d331d7dd450416aebac61c81eee502f46 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PromiseNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PromiseNode.java @@ -39,7 +39,6 @@ import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.r.nodes.RASTUtils; import com.oracle.truffle.r.nodes.access.ConstantNode; import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode; -import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode.ReadKind; import com.oracle.truffle.r.nodes.function.PromiseHelperNode.PromiseCheckHelperNode; import com.oracle.truffle.r.nodes.function.opt.OptConstantPromiseNode; import com.oracle.truffle.r.nodes.function.opt.OptForcedEagerPromiseNode; @@ -299,7 +298,7 @@ public abstract class PromiseNode extends RNode { public RArgsValuesAndNames getVarargsAndNames(VirtualFrame frame) { if (lookupVarArgs == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); - lookupVarArgs = insert(ReadVariableNode.create(ArgumentsSignature.VARARG_NAME, RType.Any, ReadKind.Silent)); + lookupVarArgs = insert(ReadVariableNode.createSilent(ArgumentsSignature.VARARG_NAME, RType.Any)); } RArgsValuesAndNames varArgsAndNames; try { 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 9ccc7b3ec224e6977b1f317a8e7c7e2ab62eea7d..1e540bf587491570f0a27295724e02614536eb63 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 @@ -22,32 +22,75 @@ */ package com.oracle.truffle.r.nodes.function; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; -import com.oracle.truffle.api.*; +import com.oracle.truffle.api.CallTarget; +import com.oracle.truffle.api.CompilerAsserts; +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.frame.*; -import com.oracle.truffle.api.interop.*; -import com.oracle.truffle.api.nodes.*; -import com.oracle.truffle.api.source.*; -import com.oracle.truffle.api.profiles.*; -import com.oracle.truffle.r.nodes.*; -import com.oracle.truffle.r.nodes.access.*; -import com.oracle.truffle.r.nodes.access.variables.*; -import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode.ReadKind; -import com.oracle.truffle.r.nodes.builtin.*; +import com.oracle.truffle.api.RootCallTarget; +import com.oracle.truffle.api.Truffle; +import com.oracle.truffle.api.frame.Frame; +import com.oracle.truffle.api.frame.FrameSlot; +import com.oracle.truffle.api.frame.FrameSlotTypeException; +import com.oracle.truffle.api.frame.MaterializedFrame; +import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.api.interop.ForeignAccess; +import com.oracle.truffle.api.interop.Message; +import com.oracle.truffle.api.interop.TruffleObject; +import com.oracle.truffle.api.nodes.DirectCallNode; +import com.oracle.truffle.api.nodes.IndirectCallNode; +import com.oracle.truffle.api.nodes.Node; +import com.oracle.truffle.api.nodes.NodeCloneable; +import com.oracle.truffle.api.nodes.NodeCost; +import com.oracle.truffle.api.nodes.NodeInfo; +import com.oracle.truffle.api.nodes.NodeUtil; +import com.oracle.truffle.api.nodes.RootNode; +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.api.source.SourceSection; +import com.oracle.truffle.r.nodes.RASTUtils; +import com.oracle.truffle.r.nodes.RRootNode; +import com.oracle.truffle.r.nodes.access.ConstantNode; +import com.oracle.truffle.r.nodes.access.FrameSlotNode; +import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode; +import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; +import com.oracle.truffle.r.nodes.builtin.RBuiltinRootNode; import com.oracle.truffle.r.nodes.function.MatchedArguments.MatchedArgumentsNode; import com.oracle.truffle.r.nodes.function.S3FunctionLookupNode.Result; -import com.oracle.truffle.r.nodes.function.signature.*; -import com.oracle.truffle.r.nodes.runtime.*; -import com.oracle.truffle.r.runtime.*; +import com.oracle.truffle.r.nodes.function.signature.RArgumentsNode; +import com.oracle.truffle.r.nodes.runtime.RASTDeparse; +import com.oracle.truffle.r.runtime.Arguments; +import com.oracle.truffle.r.runtime.ArgumentsSignature; +import com.oracle.truffle.r.runtime.RArguments; import com.oracle.truffle.r.runtime.RArguments.S3Args; +import com.oracle.truffle.r.runtime.RBuiltinKind; +import com.oracle.truffle.r.runtime.RCaller; +import com.oracle.truffle.r.runtime.RDeparse; import com.oracle.truffle.r.runtime.RDeparse.Func; -import com.oracle.truffle.r.runtime.data.*; -import com.oracle.truffle.r.runtime.env.*; -import com.oracle.truffle.r.runtime.gnur.*; -import com.oracle.truffle.r.runtime.nodes.*; +import com.oracle.truffle.r.runtime.RDispatch; +import com.oracle.truffle.r.runtime.RError; +import com.oracle.truffle.r.runtime.RInternalError; +import com.oracle.truffle.r.runtime.RSerialize; +import com.oracle.truffle.r.runtime.RType; +import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; +import com.oracle.truffle.r.runtime.data.RBuiltinDescriptor; +import com.oracle.truffle.r.runtime.data.RDataFactory; +import com.oracle.truffle.r.runtime.data.RFunction; +import com.oracle.truffle.r.runtime.data.RNull; +import com.oracle.truffle.r.runtime.data.RPromise; +import com.oracle.truffle.r.runtime.data.RStringVector; +import com.oracle.truffle.r.runtime.data.RSymbol; +import com.oracle.truffle.r.runtime.data.RTypedValue; +import com.oracle.truffle.r.runtime.env.REnvironment; +import com.oracle.truffle.r.runtime.gnur.SEXPTYPE; +import com.oracle.truffle.r.runtime.nodes.RBaseNode; +import com.oracle.truffle.r.runtime.nodes.RFastPathNode; +import com.oracle.truffle.r.runtime.nodes.RNode; +import com.oracle.truffle.r.runtime.nodes.RSyntaxNode; /** * This class denotes a call site to a function,e.g.: @@ -86,12 +129,12 @@ import com.oracle.truffle.r.runtime.nodes.*; * U = {@link UninitializedCallNode}: Forms the uninitialized end of the function PIC * D = {@link DispatchedCallNode}: Function fixed, no varargs * G = {@link GenericCallNode}: Function arbitrary - * + * * UV = {@link UninitializedCallNode} with varargs, * UVC = {@link UninitializedVarArgsCacheCallNode} with varargs, for varargs cache * DV = {@link DispatchedVarArgsCallNode}: Function fixed, with cached varargs * DGV = {@link DispatchedGenericVarArgsCallNode}: Function fixed, with arbitrary varargs (generic case) - * + * * (RB = {@link RBuiltinNode}: individual functions that are builtins are represented by this node * which is not aware of caching). Due to {@link CachedCallNode} (see below) this is transparent to * the cache and just behaves like a D/DGV) @@ -104,11 +147,11 @@ import com.oracle.truffle.r.runtime.nodes.*; * non varargs, max depth: * | * D-D-D-U - * + * * no varargs, generic (if max depth is exceeded): * | * D-D-D-D-G - * + * * varargs: * | * DV-DV-UV <- function call target identity level cache @@ -116,7 +159,7 @@ import com.oracle.truffle.r.runtime.nodes.*; * DV * | * UVC <- varargs signature level cache - * + * * varargs, max varargs depth exceeded: * | * DV-DV-UV @@ -128,7 +171,7 @@ import com.oracle.truffle.r.runtime.nodes.*; * DV * | * DGV - * + * * varargs, max function depth exceeded: * | * DV-DV-DV-DV-GV @@ -936,7 +979,7 @@ public final class RCallNode extends RNode implements RSyntaxNode { */ private abstract static class VarArgsCacheCallNode extends LeafCallNode { - @Child private ReadVariableNode lookupVarArgs = ReadVariableNode.create(ArgumentsSignature.VARARG_NAME, RType.Any, ReadKind.Silent); + @Child private ReadVariableNode lookupVarArgs = ReadVariableNode.createSilent(ArgumentsSignature.VARARG_NAME, RType.Any); @Override public final Object execute(VirtualFrame frame, RFunction function, S3Args s3Args) { diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/S3FunctionLookupNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/S3FunctionLookupNode.java index 7e40c71d6d7d340a9ce315de59387c929f715c47..62aec3a72afc2e078d247d511561a33dcb2c6873 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/S3FunctionLookupNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/S3FunctionLookupNode.java @@ -10,22 +10,41 @@ */ package com.oracle.truffle.r.nodes.function; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; -import com.oracle.truffle.api.*; +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.CompilerDirectives.ValueType; -import com.oracle.truffle.api.frame.*; -import com.oracle.truffle.api.nodes.*; -import com.oracle.truffle.api.profiles.*; -import com.oracle.truffle.r.nodes.access.variables.*; -import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode.ReadKind; -import com.oracle.truffle.r.runtime.*; -import com.oracle.truffle.r.runtime.context.*; -import com.oracle.truffle.r.runtime.data.*; -import com.oracle.truffle.r.runtime.env.*; -import com.oracle.truffle.r.runtime.nodes.*; +import com.oracle.truffle.api.frame.Frame; +import com.oracle.truffle.api.frame.FrameSlot; +import com.oracle.truffle.api.frame.FrameSlotTypeException; +import com.oracle.truffle.api.frame.MaterializedFrame; +import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.api.nodes.ControlFlowException; +import com.oracle.truffle.api.nodes.ExplodeLoop; +import com.oracle.truffle.api.nodes.NodeCost; +import com.oracle.truffle.api.nodes.NodeInfo; +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.access.variables.LocalReadVariableNode; +import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode; +import com.oracle.truffle.r.runtime.ArgumentsSignature; +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.RType; +import com.oracle.truffle.r.runtime.context.RContext; +import com.oracle.truffle.r.runtime.data.RDataFactory; +import com.oracle.truffle.r.runtime.data.RFunction; +import com.oracle.truffle.r.runtime.data.RNull; +import com.oracle.truffle.r.runtime.data.RPromise; +import com.oracle.truffle.r.runtime.data.RStringVector; +import com.oracle.truffle.r.runtime.env.REnvironment; +import com.oracle.truffle.r.runtime.nodes.RBaseNode; public abstract class S3FunctionLookupNode extends RBaseNode { protected static final int MAX_CACHE_DEPTH = 3; @@ -146,23 +165,31 @@ public abstract class S3FunctionLookupNode extends RBaseNode { private static UseMethodFunctionLookupCachedNode specialize(String genericName, RStringVector type, String group, MaterializedFrame callerFrame, MaterializedFrame genericDefFrame, S3FunctionLookupNode next) { ArrayList<ReadVariableNode> unsuccessfulReadsCaller = new ArrayList<>(); - ArrayList<ReadVariableNode> unsuccessfulReadsTable = new ArrayList<>(); + ArrayList<LocalReadVariableNode> unsuccessfulReadsTable = new ArrayList<>(); class SuccessfulReads { ReadVariableNode successfulRead; - boolean successfulReadIsTable; - ReadVariableNode methodsTableRead; + LocalReadVariableNode successfulReadTable; + LocalReadVariableNode methodsTableRead; } SuccessfulReads reads = new SuccessfulReads(); LookupOperation op = (lookupFrame, name, inMethodsTable) -> { - ReadVariableNode read = ReadVariableNode.create(name, RType.Function, inMethodsTable ? ReadKind.SilentLocal : ReadKind.Silent); - Object result = read.execute(null, lookupFrame); - if (result == null) { - (inMethodsTable ? unsuccessfulReadsTable : unsuccessfulReadsCaller).add(read); + Object result; + if (inMethodsTable) { + LocalReadVariableNode read = LocalReadVariableNode.create(name, true); + result = read.execute(null, lookupFrame); + if (result == null) { + unsuccessfulReadsTable.add(read); + } else { + reads.successfulReadTable = read; + } } else { - reads.successfulRead = read; - if (inMethodsTable) { - reads.successfulReadIsTable = true; + ReadVariableNode read = ReadVariableNode.createSilent(name, RType.Function); + result = read.execute(null, lookupFrame); + if (result == null) { + unsuccessfulReadsCaller.add(read); + } else { + reads.successfulRead = read; } } return result; @@ -170,7 +197,7 @@ public abstract class S3FunctionLookupNode extends RBaseNode { GetMethodsTable getTable = () -> { if (genericDefFrame != null) { - reads.methodsTableRead = ReadVariableNode.create(RRuntime.RS3MethodsTable, RType.Any, ReadKind.SilentLocal); + reads.methodsTableRead = LocalReadVariableNode.create(RRuntime.RS3MethodsTable, true); return reads.methodsTableRead.execute(null, genericDefFrame); } else { return null; @@ -183,11 +210,11 @@ public abstract class S3FunctionLookupNode extends RBaseNode { if (result != null) { cachedNode = new UseMethodFunctionLookupCachedNode(next.throwsError, next.nextMethod, genericName, type, group, null, unsuccessfulReadsCaller, unsuccessfulReadsTable, - reads.methodsTableRead, reads.successfulRead, reads.successfulReadIsTable, result.function, result.clazz, result.targetFunctionName, result.groupMatch, next); + reads.methodsTableRead, reads.successfulRead, reads.successfulReadTable, result.function, result.clazz, result.targetFunctionName, result.groupMatch, next); } else { RFunction builtin = next.throwsError ? builtin = RContext.lookupBuiltin(genericName) : null; cachedNode = new UseMethodFunctionLookupCachedNode(next.throwsError, next.nextMethod, genericName, type, group, builtin, unsuccessfulReadsCaller, unsuccessfulReadsTable, - reads.methodsTableRead, null, false, null, null, null, false, next); + reads.methodsTableRead, null, null, null, null, null, false, next); } return cachedNode; } @@ -218,10 +245,11 @@ public abstract class S3FunctionLookupNode extends RBaseNode { @CompilationFinal private final String[] cachedTypeContents; @Children private final ReadVariableNode[] unsuccessfulReadsCallerFrame; - @Child private ReadVariableNode readS3MethodsTable; - @Children private final ReadVariableNode[] unsuccessfulReadsDefFrame; + @Child private LocalReadVariableNode readS3MethodsTable; + @Children private final LocalReadVariableNode[] unsuccessfulReadsTable; // if unsuccessfulReadsDefFrame != null, then this read will go to the def frame @Child private ReadVariableNode successfulRead; + @Child private LocalReadVariableNode successfulReadTable; private final String cachedGenericName; private final RStringVector cachedType; @@ -236,11 +264,10 @@ public abstract class S3FunctionLookupNode extends RBaseNode { private final ValueProfile methodsTableProfile = ValueProfile.createIdentityProfile(); private final String cachedGroup; private final RFunction builtin; - private final boolean successfulReadIsTable; public UseMethodFunctionLookupCachedNode(boolean throwsError, boolean nextMethod, String genericName, RStringVector type, String group, RFunction builtin, - List<ReadVariableNode> unsuccessfulReadsCaller, List<ReadVariableNode> unsuccessfulReadsDef, ReadVariableNode readS3MethodsTable, ReadVariableNode successfulRead, - boolean successfulReadIsTable, RFunction function, Object clazz, String targetFunctionName, boolean groupMatch, S3FunctionLookupNode next) { + List<ReadVariableNode> unsuccessfulReadsCaller, List<LocalReadVariableNode> unsuccessfulReadsTable, LocalReadVariableNode readS3MethodsTable, ReadVariableNode successfulRead, + LocalReadVariableNode successfulReadTable, RFunction function, Object clazz, String targetFunctionName, boolean groupMatch, S3FunctionLookupNode next) { super(throwsError, nextMethod); this.cachedGenericName = genericName; this.cachedGroup = group; @@ -250,9 +277,9 @@ public abstract class S3FunctionLookupNode extends RBaseNode { this.cachedType = type; this.cachedTypeContents = type.getDataCopy(); this.unsuccessfulReadsCallerFrame = unsuccessfulReadsCaller.toArray(new ReadVariableNode[unsuccessfulReadsCaller.size()]); - this.unsuccessfulReadsDefFrame = unsuccessfulReadsDef.toArray(new ReadVariableNode[unsuccessfulReadsDef.size()]); + this.unsuccessfulReadsTable = unsuccessfulReadsTable.toArray(new LocalReadVariableNode[unsuccessfulReadsTable.size()]); this.successfulRead = successfulRead; - this.successfulReadIsTable = successfulReadIsTable; + this.successfulReadTable = successfulReadTable; this.result = new Result(genericName, function != null ? function : builtin, clazz, targetFunctionName, groupMatch); } @@ -270,12 +297,13 @@ public abstract class S3FunctionLookupNode extends RBaseNode { methodsTable = null; } else { methodsTable = (REnvironment) methodsTableProfile.profile(readS3MethodsTable.execute(frame, genericDefFrame)); - if (methodsTable != null && !executeReads(unsuccessfulReadsDefFrame, methodsTable.getFrame())) { + if (methodsTable != null && !executeReads(unsuccessfulReadsTable, methodsTable.getFrame())) { break; } } - if (successfulRead != null) { - Object actualFunction = successfulRead.execute(null, successfulReadIsTable ? methodsTable.getFrame() : callerFrame); + if (successfulRead != null || successfulReadTable != null) { + + Object actualFunction = successfulRead != null ? successfulRead.execute(null, callerFrame) : successfulReadTable.execute(null, methodsTable.getFrame()); if (actualFunction != result.function) { break; } @@ -305,6 +333,17 @@ public abstract class S3FunctionLookupNode extends RBaseNode { return true; } + @ExplodeLoop + private static boolean executeReads(LocalReadVariableNode[] reads, Frame callerFrame) { + for (LocalReadVariableNode read : reads) { + if (read.execute(null, callerFrame) != null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + return false; + } + } + return true; + } + private boolean isEqualType(RStringVector type) { if (sameIdentityProfile.profile(type == cachedType)) { return true; diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/opt/EagerEvalHelper.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/opt/EagerEvalHelper.java index 5af9151a4461c3a8cb8ea692deb69e3cf526c608..ce780741f73df59b4d840ebb955eb72746ab15b3 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/opt/EagerEvalHelper.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/opt/EagerEvalHelper.java @@ -22,13 +22,18 @@ */ package com.oracle.truffle.r.nodes.function.opt; -import com.oracle.truffle.r.nodes.access.*; -import com.oracle.truffle.r.nodes.access.variables.*; -import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode.ReadKind; -import com.oracle.truffle.r.nodes.function.*; -import com.oracle.truffle.r.runtime.*; -import com.oracle.truffle.r.runtime.data.*; -import com.oracle.truffle.r.runtime.nodes.*; +import com.oracle.truffle.r.nodes.access.AccessArgumentNode; +import com.oracle.truffle.r.nodes.access.ConstantNode; +import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode; +import com.oracle.truffle.r.nodes.function.ArgumentStatePush; +import com.oracle.truffle.r.nodes.function.PromiseNode; +import com.oracle.truffle.r.nodes.function.RCallNode; +import com.oracle.truffle.r.runtime.FastROptions; +import com.oracle.truffle.r.runtime.data.RDataFactory; +import com.oracle.truffle.r.runtime.data.RStringVector; +import com.oracle.truffle.r.runtime.nodes.RBaseNode; +import com.oracle.truffle.r.runtime.nodes.RNode; +import com.oracle.truffle.r.runtime.nodes.RSyntaxNode; /** * Provides small helper function for eager evaluation of arguments for the use in @@ -121,7 +126,7 @@ public class EagerEvalHelper { public static boolean isVariableArgument(RBaseNode expr) { // Do NOT try to optimize anything that might force a Promise, as this might be arbitrary // complex (time and space)! - return expr instanceof ReadVariableNode && ((ReadVariableNode) expr).getKind() != ReadKind.ForcedTypeCheck; + return expr instanceof ReadVariableNode && !((ReadVariableNode) expr).isForceForTypeCheck(); } private static boolean isCheapExpressionArgument(@SuppressWarnings("unused") RNode expr) { diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/opt/OptVariablePromiseBaseNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/opt/OptVariablePromiseBaseNode.java index 91bb53698d06e63c459219b92f9757615a7ef2bc..502f824a5e83954dad2d1249b4799a444905ef6f 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/opt/OptVariablePromiseBaseNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/opt/OptVariablePromiseBaseNode.java @@ -22,33 +22,38 @@ */ package com.oracle.truffle.r.nodes.function.opt; -import com.oracle.truffle.api.*; -import com.oracle.truffle.api.frame.*; -import com.oracle.truffle.api.nodes.*; -import com.oracle.truffle.r.nodes.access.*; -import com.oracle.truffle.r.nodes.access.variables.*; -import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode.ReadKind; -import com.oracle.truffle.r.nodes.function.*; -import com.oracle.truffle.r.runtime.*; -import com.oracle.truffle.r.runtime.data.*; +import com.oracle.truffle.api.Assumption; +import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.frame.FrameSlot; +import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.api.nodes.InvalidAssumptionException; +import com.oracle.truffle.r.nodes.access.FrameSlotNode; +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.PromiseNode; +import com.oracle.truffle.r.runtime.RArguments; +import com.oracle.truffle.r.runtime.RType; +import com.oracle.truffle.r.runtime.data.RPromise; import com.oracle.truffle.r.runtime.data.RPromise.EagerFeedback; import com.oracle.truffle.r.runtime.data.RPromise.RPromiseFactory; -import com.oracle.truffle.r.runtime.env.frame.*; -import com.oracle.truffle.r.runtime.nodes.*; +import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor; +import com.oracle.truffle.r.runtime.nodes.RNode; +import com.oracle.truffle.r.runtime.nodes.RSyntaxNode; public abstract class OptVariablePromiseBaseNode extends PromiseNode implements EagerFeedback { protected final ReadVariableNode originalRvn; @Child private FrameSlotNode frameSlotNode; @Child private RNode fallback = null; - @Child private ReadVariableNode readNode; + @Child private LocalReadVariableNode readNode; private final int wrapIndex; public OptVariablePromiseBaseNode(RPromiseFactory factory, ReadVariableNode rvn, int wrapIndex) { super(factory); - assert rvn.getKind() != ReadKind.ForcedTypeCheck; // Should be caught by optimization check + // Should be caught by optimization check + assert !rvn.isForceForTypeCheck() && rvn.getMode() == RType.Any; this.originalRvn = rvn; this.frameSlotNode = FrameSlotNode.create(rvn.getIdentifier(), false); - this.readNode = ReadVariableNode.create(rvn.getIdentifier(), rvn.getMode(), ReadKind.UnforcedSilentLocal); + this.readNode = LocalReadVariableNode.create(rvn.getIdentifier(), false); this.wrapIndex = wrapIndex; } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/signature/CollectArgumentsNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/signature/CollectArgumentsNode.java index 10f38006443d9c40705c3871cab6d1e761dff47e..9dc6863b819ecf07851fed0935f3835cff4ae9c3 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/signature/CollectArgumentsNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/signature/CollectArgumentsNode.java @@ -23,16 +23,22 @@ package com.oracle.truffle.r.nodes.function.signature; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.api.dsl.*; -import com.oracle.truffle.api.frame.*; -import com.oracle.truffle.api.nodes.*; -import com.oracle.truffle.api.profiles.*; -import com.oracle.truffle.r.nodes.access.*; -import com.oracle.truffle.r.nodes.access.variables.*; -import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode.ReadKind; -import com.oracle.truffle.r.runtime.*; -import com.oracle.truffle.r.runtime.data.*; -import com.oracle.truffle.r.runtime.nodes.*; +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.FrameSlot; +import com.oracle.truffle.api.frame.MaterializedFrame; +import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.api.nodes.ExplodeLoop; +import com.oracle.truffle.api.nodes.Node; +import com.oracle.truffle.api.profiles.ConditionProfile; +import com.oracle.truffle.r.nodes.access.ConstantNode; +import com.oracle.truffle.r.nodes.access.variables.LocalReadVariableNode; +import com.oracle.truffle.r.runtime.ArgumentsSignature; +import com.oracle.truffle.r.runtime.RArguments; +import com.oracle.truffle.r.runtime.data.RMissing; +import com.oracle.truffle.r.runtime.data.RPromise; +import com.oracle.truffle.r.runtime.nodes.RBaseNode; public abstract class CollectArgumentsNode extends RBaseNode { @@ -42,14 +48,14 @@ public abstract class CollectArgumentsNode extends RBaseNode { public abstract Object[] execute(VirtualFrame frame, ArgumentsSignature signature); - protected RNode[] createArgs(ArgumentsSignature signature, VirtualFrame frame) { - RNode[] reads = new RNode[signature.getLength()]; + protected Node[] createArgs(ArgumentsSignature signature, VirtualFrame frame) { + Node[] reads = new Node[signature.getLength()]; for (int i = 0; i < signature.getLength(); i++) { Object arg = RArguments.getArgument(frame, i); if (arg instanceof RPromise && ((RPromise) arg).isDefault()) { reads[i] = ConstantNode.create(RMissing.instance); } else { - reads[i] = ReadVariableNode.create(signature.getName(i), RType.Any, ReadKind.UnforcedSilentLocal); + reads[i] = LocalReadVariableNode.create(signature.getName(i), false); } } return reads; @@ -58,10 +64,10 @@ public abstract class CollectArgumentsNode extends RBaseNode { @SuppressWarnings("unused") @ExplodeLoop @Specialization(limit = "CACHE_LIMIT", guards = {"cachedSignature == signature"}) - protected Object[] combineCached(VirtualFrame frame, ArgumentsSignature signature, @Cached("signature") ArgumentsSignature cachedSignature, @Cached("createArgs(signature, frame)") RNode[] reads) { + protected Object[] combineCached(VirtualFrame frame, ArgumentsSignature signature, @Cached("signature") ArgumentsSignature cachedSignature, @Cached("createArgs(signature, frame)") Node[] reads) { Object[] result = new Object[reads.length]; for (int i = 0; i < reads.length; i++) { - Object value = reads[i].execute(frame); + Object value = reads[i] instanceof ConstantNode ? ((ConstantNode) reads[i]).getValue() : ((LocalReadVariableNode) reads[i]).execute(frame); result[i] = valueMissingProfile.profile(value == null) ? RMissing.instance : value; } return result; diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/CollectGenericArgumentsNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/CollectGenericArgumentsNode.java index 6222a4005e947c6fe976abe1e7b4334c89d06739..f356ac072b518b6746479d52e84ec86bef14008e 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/CollectGenericArgumentsNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/CollectGenericArgumentsNode.java @@ -24,17 +24,20 @@ package com.oracle.truffle.r.nodes.objects; import com.oracle.truffle.api.CompilerAsserts; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.api.dsl.*; -import com.oracle.truffle.api.frame.*; -import com.oracle.truffle.api.nodes.*; -import com.oracle.truffle.api.profiles.*; -import com.oracle.truffle.r.nodes.access.variables.*; -import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode.ReadKind; +import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.frame.FrameDescriptor; +import com.oracle.truffle.api.frame.FrameSlot; +import com.oracle.truffle.api.frame.MaterializedFrame; +import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.api.nodes.ExplodeLoop; +import com.oracle.truffle.api.nodes.SlowPathException; +import com.oracle.truffle.api.profiles.ConditionProfile; +import com.oracle.truffle.r.nodes.access.variables.LocalReadVariableNode; import com.oracle.truffle.r.nodes.function.ClassHierarchyScalarNode; import com.oracle.truffle.r.nodes.function.ClassHierarchyScalarNodeGen; -import com.oracle.truffle.r.runtime.*; -import com.oracle.truffle.r.runtime.data.*; -import com.oracle.truffle.r.runtime.nodes.*; +import com.oracle.truffle.r.runtime.data.RList; +import com.oracle.truffle.r.runtime.data.RSymbol; +import com.oracle.truffle.r.runtime.nodes.RBaseNode; /* * Used to collect arguments of the generic function for S4 method dispatch. Modeled after {@link CollectArgumentsNode}. @@ -43,7 +46,7 @@ public abstract class CollectGenericArgumentsNode extends RBaseNode { // TODO: re-do with a multi-element cache? (list comparison will have some cost, though) - @Children private final ReadVariableNode[] argReads; + @Children private final LocalReadVariableNode[] argReads; @Children private final ClassHierarchyScalarNode[] classHierarchyNodes; @Child private ClassHierarchyScalarNode classHierarchyNodeSlowPath; @@ -52,11 +55,11 @@ public abstract class CollectGenericArgumentsNode extends RBaseNode { public abstract String[] execute(VirtualFrame frame, RList arguments, int argLength); protected CollectGenericArgumentsNode(Object[] arguments, int argLength) { - ReadVariableNode[] reads = new ReadVariableNode[argLength]; + LocalReadVariableNode[] reads = new LocalReadVariableNode[argLength]; ClassHierarchyScalarNode[] hierarchyNodes = new ClassHierarchyScalarNode[argLength]; for (int i = 0; i < argLength; i++) { RSymbol s = (RSymbol) arguments[i]; - reads[i] = ReadVariableNode.create(s.getName(), RType.Any, ReadKind.SilentLocal); + reads[i] = LocalReadVariableNode.create(s.getName(), true); hierarchyNodes[i] = ClassHierarchyScalarNodeGen.create(); } argReads = insert(reads); @@ -71,9 +74,9 @@ public abstract class CollectGenericArgumentsNode extends RBaseNode { } String[] result = new String[argReads.length]; for (int i = 0; i < argReads.length; i++) { - String cachedId = argReads[i].getIdentifier(); + Object cachedId = argReads[i].getIdentifier(); String id = ((RSymbol) (arguments.getDataAt(0))).getName(); - assert cachedId == cachedId.intern() && id == id.intern(); + assert cachedId instanceof String && cachedId == ((String) cachedId).intern() && id == id.intern(); if (cachedId != id) { throw new SlowPathException(); } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/DispatchGeneric.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/DispatchGeneric.java index 54d4e381e4d07e392a63a8e6e3caa9461962ae3d..3320fd394af480e41c9cc24d12b710c0afffe9e2 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/DispatchGeneric.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/DispatchGeneric.java @@ -16,16 +16,21 @@ 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.Truffle; -import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.api.dsl.Cached; +import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.nodes.DirectCallNode; import com.oracle.truffle.api.profiles.ConditionProfile; +import com.oracle.truffle.r.nodes.access.variables.LocalReadVariableNode; import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode; -import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode.ReadKind; import com.oracle.truffle.r.nodes.function.signature.RArgumentsNode; -import com.oracle.truffle.r.runtime.*; +import com.oracle.truffle.r.runtime.ArgumentsSignature; +import com.oracle.truffle.r.runtime.RArguments; +import com.oracle.truffle.r.runtime.RCaller; import com.oracle.truffle.r.runtime.context.RContext; -import com.oracle.truffle.r.runtime.data.*; +import com.oracle.truffle.r.runtime.data.RDataFactory; +import com.oracle.truffle.r.runtime.data.RFunction; +import com.oracle.truffle.r.runtime.data.RStringVector; import com.oracle.truffle.r.runtime.env.REnvironment; import com.oracle.truffle.r.runtime.nodes.RBaseNode; @@ -63,8 +68,8 @@ public abstract class DispatchGeneric extends RBaseNode { } } - protected ReadVariableNode createTableRead(String dispatchString) { - return ReadVariableNode.create(dispatchString, RType.Any, ReadKind.SilentLocal); + protected LocalReadVariableNode createTableRead(String dispatchString) { + return LocalReadVariableNode.create(dispatchString, true); } private Object dispatchInternal(VirtualFrame frame, REnvironment methodsEnv, REnvironment mtable, RStringVector classes, RFunction fdef, String fname, RFunction f) { @@ -72,7 +77,7 @@ public abstract class DispatchGeneric extends RBaseNode { if (method == null) { if (inheritForDispatchFind == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); - inheritForDispatchFind = insert(ReadVariableNode.create(".InheritForDispatch", RType.Function, ReadKind.Normal)); + inheritForDispatchFind = insert(ReadVariableNode.createFunctionLookup(null, ".InheritForDispatch")); inheritForDispatchFunction = (RFunction) inheritForDispatchFind.execute(null, methodsEnv.getFrame()); inheritForDispatchCall = insert(Truffle.getRuntime().createDirectCallNode(inheritForDispatchFunction.getTarget())); @@ -96,7 +101,7 @@ public abstract class DispatchGeneric extends RBaseNode { @Specialization(guards = "equalClasses(classes, cachedClasses)") protected Object dispatchCached(VirtualFrame frame, REnvironment methodsEnv, REnvironment mtable, RStringVector classes, RFunction fdef, String fname, @Cached("classes") RStringVector cachedClasses, @Cached("createDispatchString(cachedClasses)") String dispatchString, - @Cached("createTableRead(dispatchString)") ReadVariableNode tableRead) { + @Cached("createTableRead(dispatchString)") LocalReadVariableNode tableRead) { RFunction method = (RFunction) tableRead.execute(null, mtable.getFrame()); return dispatchInternal(frame, methodsEnv, mtable, classes, fdef, fname, method); } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/ExecuteMethod.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/ExecuteMethod.java index d2fc54d4d8f18de86b217857384d2ef6a2b98d52..7664b6065da5a7fbe47b876721b83f9bc409d03b 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/ExecuteMethod.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/ExecuteMethod.java @@ -14,21 +14,24 @@ package com.oracle.truffle.r.nodes.objects; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.Truffle; -import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.frame.FrameDescriptor; import com.oracle.truffle.api.frame.FrameSlot; import com.oracle.truffle.api.frame.FrameSlotKind; import com.oracle.truffle.api.frame.MaterializedFrame; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.r.nodes.RRootNode; -import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode; -import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode.ReadKind; +import com.oracle.truffle.r.nodes.access.variables.LocalReadVariableNode; import com.oracle.truffle.r.nodes.function.FormalArguments; import com.oracle.truffle.r.nodes.function.RMissingHelper; import com.oracle.truffle.r.nodes.function.signature.RArgumentsNode; -import com.oracle.truffle.r.runtime.*; +import com.oracle.truffle.r.runtime.ArgumentsSignature; +import com.oracle.truffle.r.runtime.RArguments; +import com.oracle.truffle.r.runtime.RInternalError; +import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.context.RContext; -import com.oracle.truffle.r.runtime.data.*; +import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; +import com.oracle.truffle.r.runtime.data.RFunction; import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor; import com.oracle.truffle.r.runtime.nodes.RBaseNode; @@ -36,11 +39,11 @@ public abstract class ExecuteMethod extends RBaseNode { public abstract Object executeObject(VirtualFrame frame, RFunction fdef); - @Child private ReadVariableNode readDefined = ReadVariableNode.create(RRuntime.R_DOT_DEFINED, RType.Any, ReadKind.SilentLocal); - @Child private ReadVariableNode readMethod = ReadVariableNode.create(RRuntime.RDotMethod, RType.Any, ReadKind.SilentLocal); - @Child private ReadVariableNode readTarget = ReadVariableNode.create(RRuntime.R_DOT_TARGET, RType.Any, ReadKind.SilentLocal); - @Child private ReadVariableNode readGeneric = ReadVariableNode.create(RRuntime.RDotGeneric, RType.Any, ReadKind.SilentLocal); - @Child private ReadVariableNode readMethods = ReadVariableNode.create(RRuntime.R_DOT_METHODS, RType.Any, ReadKind.SilentLocal); + @Child private LocalReadVariableNode readDefined = LocalReadVariableNode.create(RRuntime.R_DOT_DEFINED, true); + @Child private LocalReadVariableNode readMethod = LocalReadVariableNode.create(RRuntime.RDotMethod, true); + @Child private LocalReadVariableNode readTarget = LocalReadVariableNode.create(RRuntime.R_DOT_TARGET, true); + @Child private LocalReadVariableNode readGeneric = LocalReadVariableNode.create(RRuntime.RDotGeneric, true); + @Child private LocalReadVariableNode readMethods = LocalReadVariableNode.create(RRuntime.R_DOT_METHODS, true); @Child private RArgumentsNode argsNode = RArgumentsNode.create(); @Specialization @@ -50,7 +53,8 @@ public abstract class ExecuteMethod extends RBaseNode { RArguments.getSignature(frame), null); MaterializedFrame newFrame = Truffle.getRuntime().createMaterializedFrame(args); FrameDescriptor desc = newFrame.getFrameDescriptor(); - FrameSlotChangeMonitor.initializeFunctionFrameDescriptor(desc); + FrameSlotChangeMonitor.initializeFunctionFrameDescriptor("<executeMethod>", desc); + FrameSlotChangeMonitor.initializeEnclosingFrame(newFrame, RArguments.getFunction(frame).getEnclosingFrame()); FormalArguments formals = ((RRootNode) fdef.getRootNode()).getFormalArguments(); if (formals != null) { ArgumentsSignature signature = formals.getSignature(); diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/LoadMethod.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/LoadMethod.java index 43935e34f9a83ba7196e00794597a8440ba14c26..6bc7bc3189f6162df8a66c3461ef8ef637dcc97b 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/LoadMethod.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/LoadMethod.java @@ -15,19 +15,23 @@ package com.oracle.truffle.r.nodes.objects; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.Truffle; -import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.nodes.DirectCallNode; import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.r.nodes.access.WriteLocalFrameVariableNode; import com.oracle.truffle.r.nodes.access.WriteVariableNode; import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode; -import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode.ReadKind; import com.oracle.truffle.r.nodes.function.signature.RArgumentsNode; -import com.oracle.truffle.r.runtime.*; +import com.oracle.truffle.r.runtime.ArgumentsSignature; +import com.oracle.truffle.r.runtime.RArguments; +import com.oracle.truffle.r.runtime.RCaller; +import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.context.RContext; -import com.oracle.truffle.r.runtime.data.*; +import com.oracle.truffle.r.runtime.data.RAttributable; import com.oracle.truffle.r.runtime.data.RAttributes.RAttribute; +import com.oracle.truffle.r.runtime.data.RDataFactory; +import com.oracle.truffle.r.runtime.data.RFunction; import com.oracle.truffle.r.runtime.env.REnvironment; import com.oracle.truffle.r.runtime.nodes.RBaseNode; @@ -79,7 +83,7 @@ public abstract class LoadMethod extends RBaseNode { if (moreAttributes.profile(found < fdef.getAttributes().size())) { if (loadMethodFind == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); - loadMethodFind = insert(ReadVariableNode.create("loadMethod", RType.Function, ReadKind.Normal)); + loadMethodFind = insert(ReadVariableNode.createFunctionLookup(null, "loadMethod")); loadMethodFunction = (RFunction) loadMethodFind.execute(null, methodsEnv.getFrame()); loadMethodCall = insert(Truffle.getRuntime().createDirectCallNode(loadMethodFunction.getTarget())); diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/CallRFFIHelper.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/CallRFFIHelper.java index d587c6940c49dc206a322379f39e23ac4ee3586e..7bf81a338f2f873408e41c6cd432173b1fe094c3 100644 --- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/CallRFFIHelper.java +++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/CallRFFIHelper.java @@ -563,7 +563,7 @@ public class CallRFFIHelper { static REnvironment Rf_createNewEnv(REnvironment parent, String name, boolean hashed, int initialSize) { REnvironment env = RDataFactory.createNewEnv(name, hashed, initialSize); - env.setParent(parent); + RArguments.initializeEnclosingFrame(env.getFrame(), parent.getFrame()); return env; } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RArguments.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RArguments.java index a5758daeee6fc5b42c922533577817898fa22928..0e215243f0b60c8fd50d6f80911db3c73069c8fd 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RArguments.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RArguments.java @@ -268,7 +268,15 @@ public final class RArguments { Object[] arguments = frame.getArguments(); MaterializedFrame oldEnclosingFrame = (MaterializedFrame) arguments[INDEX_ENCLOSING_FRAME]; arguments[INDEX_ENCLOSING_FRAME] = newEnclosingFrame; - FrameSlotChangeMonitor.invalidateEnclosingFrame(frame); + FrameSlotChangeMonitor.setEnclosingFrame(frame, newEnclosingFrame, oldEnclosingFrame); + } + + public static void initializeEnclosingFrame(Frame frame, MaterializedFrame newEnclosingFrame) { + CompilerAsserts.neverPartOfCompilation(); + Object[] arguments = frame.getArguments(); + assert arguments[INDEX_ENCLOSING_FRAME] == null; + arguments[INDEX_ENCLOSING_FRAME] = newEnclosingFrame; + FrameSlotChangeMonitor.initializeEnclosingFrame(frame, newEnclosingFrame); } /** @@ -283,8 +291,7 @@ public final class RArguments { Object[] newArguments = newEnclosingFrame.getArguments(); newArguments[INDEX_ENCLOSING_FRAME] = oldEnclosingFrame; arguments[INDEX_ENCLOSING_FRAME] = newEnclosingFrame; - FrameSlotChangeMonitor.invalidateEnclosingFrame(newEnclosingFrame); - FrameSlotChangeMonitor.invalidateEnclosingFrame(frame); + FrameSlotChangeMonitor.attach(frame, newEnclosingFrame); } /** @@ -297,7 +304,7 @@ public final class RArguments { MaterializedFrame encl = (MaterializedFrame) arguments[INDEX_ENCLOSING_FRAME]; Object[] enclArguments = encl.getArguments(); arguments[INDEX_ENCLOSING_FRAME] = enclArguments[INDEX_ENCLOSING_FRAME]; - FrameSlotChangeMonitor.invalidateEnclosingFrame(frame); + FrameSlotChangeMonitor.detach(frame); } /** diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java index 312d655519fd4b1a5ea5ad845b809ef56e7c076e..3edcbcab78a9b1cfa03ec4a2bbe09b99bfa736c4 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java @@ -172,10 +172,11 @@ public class RRuntime { * Create an {@link VirtualFrame} for a non-function environment, e.g., a package frame or the * global environment. */ - public static VirtualFrame createNonFunctionFrame() { + public static MaterializedFrame createNonFunctionFrame(String name) { FrameDescriptor frameDescriptor = new FrameDescriptor(); - FrameSlotChangeMonitor.initializeNonFunctionFrameDescriptor(frameDescriptor, false); - return Truffle.getRuntime().createVirtualFrame(RArguments.createUnitialized(), frameDescriptor); + MaterializedFrame frame = Truffle.getRuntime().createMaterializedFrame(RArguments.createUnitialized(), frameDescriptor); + FrameSlotChangeMonitor.initializeNonFunctionFrameDescriptor(name, frame); + return frame; } public static RComplex createComplexNA() { diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSerialize.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSerialize.java index 5d7bde0495d8ef094cf37f0573ee31e667b1d016..1c67585506a6fbb8b8ee55b0b0a7c3bdce67e28e 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSerialize.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSerialize.java @@ -415,7 +415,7 @@ public class RSerialize { Object enclos = readItem(); REnvironment enclosing = enclos == RNull.instance ? REnvironment.baseEnv() : (REnvironment) enclos; final REnvironment.NewEnv env = RDataFactory.createNewEnv(null); - env.setParent(enclosing); + RArguments.initializeEnclosingFrame(env.getFrame(), enclosing.getFrame()); /* * We update the env reference as soon as possible, in case the contents of an * environment contain a reference to the env itself. diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDataFactory.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDataFactory.java index e13ed0bcd29d93c9e631b65c0d5b234a191061c0..f50154eed01375953438b9bac0452b60dd3160a3 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDataFactory.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDataFactory.java @@ -23,6 +23,7 @@ package com.oracle.truffle.r.runtime.data; import java.util.*; +import java.util.concurrent.atomic.AtomicInteger; import com.oracle.truffle.api.*; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; @@ -436,16 +437,18 @@ public final class RDataFactory { return traceDataCreated(new RFunction(name, target, builtin, enclosingFrame, fastPath, containsDispatch)); } + private static final AtomicInteger environmentCount = new AtomicInteger(); + public static REnvironment createInternalEnv() { - return traceDataCreated(new REnvironment.NewEnv(RRuntime.createNonFunctionFrame().materialize(), REnvironment.UNNAMED)); + return traceDataCreated(new REnvironment.NewEnv(RRuntime.createNonFunctionFrame("<internal-env-" + environmentCount.incrementAndGet() + ">"), REnvironment.UNNAMED)); } public static REnvironment.NewEnv createNewEnv(String name) { - return traceDataCreated(new REnvironment.NewEnv(RRuntime.createNonFunctionFrame().materialize(), name)); + return traceDataCreated(new REnvironment.NewEnv(RRuntime.createNonFunctionFrame("<new-env-" + environmentCount.incrementAndGet() + ">"), name)); } public static REnvironment createNewEnv(String name, boolean hashed, int initialSize) { - REnvironment.NewEnv env = new REnvironment.NewEnv(RRuntime.createNonFunctionFrame().materialize(), name); + REnvironment.NewEnv env = new REnvironment.NewEnv(RRuntime.createNonFunctionFrame("<new-env-" + environmentCount.incrementAndGet() + ">"), name); env.setHashed(hashed); env.setInitialSize(initialSize); return traceDataCreated(env); diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RFunction.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RFunction.java index 89af3038071ddaeec86f364003533250435ca4e3..f3632b1d57f423a2f878bbb363ecf5f7cdc01c29 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RFunction.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RFunction.java @@ -22,14 +22,15 @@ */ package com.oracle.truffle.r.runtime.data; -import com.oracle.truffle.api.*; -import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; -import com.oracle.truffle.api.frame.*; -import com.oracle.truffle.api.interop.*; -import com.oracle.truffle.api.nodes.*; -import com.oracle.truffle.r.runtime.*; -import com.oracle.truffle.r.runtime.context.*; -import com.oracle.truffle.r.runtime.env.frame.*; +import com.oracle.truffle.api.RootCallTarget; +import com.oracle.truffle.api.frame.MaterializedFrame; +import com.oracle.truffle.api.interop.ForeignAccess; +import com.oracle.truffle.api.interop.TruffleObject; +import com.oracle.truffle.api.nodes.RootNode; +import com.oracle.truffle.r.runtime.RBuiltin; +import com.oracle.truffle.r.runtime.RType; +import com.oracle.truffle.r.runtime.VirtualEvalFrame; +import com.oracle.truffle.r.runtime.context.RContext; /** * An instance of {@link RFunction} represents a function defined in R. The properties of a function @@ -46,6 +47,7 @@ import com.oracle.truffle.r.runtime.env.frame.*; public final class RFunction extends RAttributeStorage implements RTypedValue, TruffleObject { public static final String NO_NAME = new String(""); + private String name; private final RootCallTarget target; private final RBuiltinDescriptor builtin; @@ -53,7 +55,7 @@ public final class RFunction extends RAttributeStorage implements RTypedValue, T private FastPathFactory fastPath; - @CompilationFinal private MaterializedFrame enclosingFrame; + private final MaterializedFrame enclosingFrame; RFunction(String name, RootCallTarget target, RBuiltinDescriptor builtin, MaterializedFrame enclosingFrame, FastPathFactory fastPath, boolean containsDispatch) { this.target = target; @@ -101,17 +103,6 @@ public final class RFunction extends RAttributeStorage implements RTypedValue, T return enclosingFrame; } - /** - * Used by the {@code environment<-} builtin. - */ - public void setEnclosingFrame(MaterializedFrame enclosingFrame) { - assert !(enclosingFrame instanceof VirtualEvalFrame); - this.enclosingFrame = enclosingFrame; - FrameDescriptor descriptor = target.getRootNode().getFrameDescriptor(); - FrameSlotChangeMonitor.getOrInitializeEnclosingFrameAssumption(null, descriptor, null, enclosingFrame); - FrameSlotChangeMonitor.getOrInitializeEnclosingFrameDescriptorAssumption(null, descriptor, enclosingFrame.getFrameDescriptor()); - } - private static final RStringVector implicitClass = RDataFactory.createStringVectorFromScalar(RType.Function.getName()); @Override 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 50bb7b6818cf393117c9cabfb1e7c7ef4f59e390..3725f8e90c4eb3b3c6bb38d5ab5d9210b388c7c3 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 @@ -153,7 +153,7 @@ public abstract class REnvironment extends RAttributeStorage implements RTypedVa } public static ContextStateImpl newContext(RContext context) { - return createContext(context, RRuntime.createNonFunctionFrame().materialize()); + return createContext(context, RRuntime.createNonFunctionFrame("global")); } } @@ -278,7 +278,7 @@ public abstract class REnvironment extends RAttributeStorage implements RTypedVa namespaceRegistry.safePut("base", baseEnv.namespaceEnv); Global globalEnv = new Global(initialGlobalFrame); - globalEnv.setParent(baseEnv); + RArguments.initializeEnclosingFrame(initialGlobalFrame, baseFrame); state.setBaseEnv(baseEnv); state.setSearchPath(initSearchList(globalEnv)); } @@ -326,7 +326,7 @@ public abstract class REnvironment extends RAttributeStorage implements RTypedVa REnvironment e = parentSearchPath.get(1).cloneEnv(globalFrame); // create the new Global with clone top as parent Global newGlobalEnv = new Global(globalFrame); - newGlobalEnv.setParent(e); + RArguments.initializeEnclosingFrame(globalFrame, e.getFrame()); // create new namespaceRegistry and populate it while locating "base" REnvironment newNamespaceRegistry = RDataFactory.createInternalEnv(); Base newBaseEnv = null; @@ -397,7 +397,7 @@ public abstract class REnvironment extends RAttributeStorage implements RTypedVa } // N.B. Base overrides this method, so we only get here for package environments REnvironment newEnv = RDataFactory.createNewEnv(getName()); - newEnv.setParent(parentClone); + RArguments.initializeEnclosingFrame(newEnv.getFrame(), parentClone.getFrame()); if (attributes != null) { newEnv.attributes = attributes.copy(); } @@ -588,13 +588,6 @@ public abstract class REnvironment extends RAttributeStorage implements RTypedVa throw new DetachException(message); } - /** - * Specifically for {@code ls()}, we don't care about the parent, as the use is transient. - */ - public static REnvironment createLsCurrent(MaterializedFrame frame) { - return new Function(frame); - } - /** * Converts a {@link Frame} to an {@link REnvironment}, which necessarily requires the frame to * be materialized. @@ -633,7 +626,7 @@ public abstract class REnvironment extends RAttributeStorage implements RTypedVa @TruffleBoundary public static REnvironment createFromList(RAttributeProfiles attrProfiles, RList list, REnvironment parent) { REnvironment result = RDataFactory.createNewEnv(null); - result.setParent(parent); + RArguments.initializeEnclosingFrame(result.getFrame(), parent.getFrame()); RStringVector names = list.getNames(attrProfiles); for (int i = 0; i < list.getLength(); i++) { try { @@ -918,7 +911,7 @@ public abstract class REnvironment extends RAttributeStorage implements RTypedVa @Override protected REnvironment cloneEnv(MaterializedFrame globalFrame) { - Base newBase = new Base(RRuntime.createNonFunctionFrame().materialize(), globalFrame); + Base newBase = new Base(RRuntime.createNonFunctionFrame("base"), globalFrame); this.copyBindings(newBase); return newBase; } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/FrameSlotChangeMonitor.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/FrameSlotChangeMonitor.java index e6394089b36434c38da87a2d2511fdbf6071d453..23b37d8a2a7a6d357813ab84158b75560036f5ac 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/FrameSlotChangeMonitor.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/FrameSlotChangeMonitor.java @@ -22,45 +22,401 @@ */ package com.oracle.truffle.r.runtime.env.frame; -import java.util.*; - -import com.oracle.truffle.api.*; +import java.lang.ref.WeakReference; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.WeakHashMap; + +import com.oracle.truffle.api.Assumption; +import com.oracle.truffle.api.CompilerAsserts; +import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; -import com.oracle.truffle.api.frame.*; -import com.oracle.truffle.api.profiles.*; -import com.oracle.truffle.r.runtime.*; -import com.oracle.truffle.r.runtime.data.*; +import com.oracle.truffle.api.Truffle; +import com.oracle.truffle.api.frame.Frame; +import com.oracle.truffle.api.frame.FrameDescriptor; +import com.oracle.truffle.api.frame.FrameSlot; +import com.oracle.truffle.api.frame.FrameSlotKind; +import com.oracle.truffle.api.frame.MaterializedFrame; +import com.oracle.truffle.api.nodes.InvalidAssumptionException; +import com.oracle.truffle.api.profiles.BranchProfile; +import com.oracle.truffle.r.runtime.RArguments; +import com.oracle.truffle.r.runtime.RInternalError; +import com.oracle.truffle.r.runtime.StableValue; /** - * This is meant to monitor updates performed on {@link FrameSlot}. Each {@link FrameSlot} holds an - * {@link Assumption} in it's "info" field; it is valid as long as no non-local update has ever - * taken place.<br/> - * The background to this rather strange assumption is that non-local reads are very hard to keep - * track of thanks to R powerful language features. To keep the maintenance for the assumption as - * cheap as possible, it checks only local reads - which is fast - and does a more costly check on - * "<<-" but invalidates the assumption as soon as "eval" and the like comes into play.<br/> + * This class maintains information about the current hierarchy of environments in the system. This + * information is described as assumptions that will be invalidated if the layout changes, and thus + * make sure that code is properly deoptimized. */ public final class FrameSlotChangeMonitor { - private static final int MAX_FUNCTION_INVALIDATION_COUNT = 2; - private static final int MAX_INVALIDATION_COUNT = 1; + /* + * The following classes describe the result of a previous lookup that successfully delivered a + * result based on the system's knowledge about the hierarchy of environments and the stable + * values of certain bindings. Most function lookups can be answered based only on this + * information. + * + * These lookups are stored for caching and invalidation, i.e., to save on repeated lookups and + * to invalidate lookups in case the environment hierarchy changes. + */ + + public abstract static class LookupResult { + protected final Assumption assumption; + + private LookupResult(String identifier) { + this.assumption = Truffle.getRuntime().createAssumption("lookup \"" + identifier + "\" (" + this.getClass().getSimpleName() + ")"); + } + + public boolean isValid() { + return assumption.isValid(); + } + + public abstract Object getValue() throws InvalidAssumptionException; + + public void invalidate() { + assumption.invalidate(); + } + } + + public static final class StableValueLookupResult extends LookupResult { + private final StableValue<Object> value; + + private StableValueLookupResult(String identifier, StableValue<Object> value) { + super(identifier); + this.value = value; + } + + @Override + public boolean isValid() { + return super.isValid() && value.getAssumption().isValid(); + } + + @Override + public Object getValue() throws InvalidAssumptionException { + assumption.check(); + StableValue<Object> result = value; + result.getAssumption().check(); + return result.getValue(); + } + } + + public static final class MissingLookupResult extends LookupResult { + + private MissingLookupResult(String identifier) { + super(identifier); + } + + @Override + public Object getValue() throws InvalidAssumptionException { + assumption.check(); + return null; + } + } + + public static final class FrameAndSlotLookupResult extends LookupResult { + private final MaterializedFrame frame; + private final FrameSlot slot; + + private FrameAndSlotLookupResult(String identifier, MaterializedFrame frame, FrameSlot slot) { + super(identifier); + this.frame = frame; + this.slot = slot; + } + + @Override + public Object getValue() { + // fast path execution should use getFrame / getSlot + CompilerAsserts.neverPartOfCompilation("FrameAndSlotLookupResult.getValue() should not be used in fast path execution"); + return frame.getValue(slot); + } + + public MaterializedFrame getFrame() throws InvalidAssumptionException { + assumption.check(); + return frame; + } + + public FrameSlot getSlot() throws InvalidAssumptionException { + assumption.check(); + return slot; + } + } + + /** + * Every frame descriptor in the system will be associated with a FrameDescriptorMetaData + * object. For function environments, one frame descriptor corresponds to many actual + * environments, while for manually created environment, there is always one frame descriptor + * for one environment. + */ + private static final class FrameDescriptorMetaData { + private final String name; // name for debug purposes + private final WeakReference<MaterializedFrame> singletonFrame; + private final Set<FrameDescriptor> subDescriptors = Collections.newSetFromMap(new WeakHashMap<>()); + + /** + * This set contains all lookups that have been performed "across" this frame descriptor. If + * a binding with one of these names is modified, then the lookups in this frame descriptor + * and all child frame descriptors need to be checked. + */ + private final Set<Object> previousLookups = new HashSet<>(); + /** + * A set of all lookups that started in this frame descriptor. + */ + private final WeakHashMap<Object, LookupResult> lookupResults = new WeakHashMap<>(); + + private StableValue<FrameDescriptor> enclosingFrameDescriptor = new StableValue<>(null, "initial (empty) enclosing frame"); + + private FrameDescriptorMetaData(String name, MaterializedFrame singletonFrame) { + this.name = name; + this.singletonFrame = singletonFrame == null ? null : new WeakReference<>(singletonFrame); + } + + public void updateEnclosingFrameDescriptor(FrameDescriptor newEnclosingDescriptor) { + enclosingFrameDescriptor.getAssumption().invalidate(); + enclosingFrameDescriptor = new StableValue<>(newEnclosingDescriptor, "enclosing frame"); + } + } + + private static final WeakHashMap<FrameDescriptor, FrameDescriptorMetaData> frameDescriptors = new WeakHashMap<>(); + + /** + * This function tries to fulfill the lookup for the given name in the given frame based only on + * the static knowledge about the frame descriptor hierarchy and stable bindings. Returns + * {@code null} in case this was not possible. + */ + public static synchronized LookupResult lookup(Frame frame, Object identifier) { + FrameDescriptorMetaData metaData = getMetaData(frame); + LookupResult result = metaData.lookupResults.get(identifier); + if (result != null && result.isValid()) { + return result; + } + Frame current = frame; + while (true) { + FrameSlot slot = current.getFrameDescriptor().findFrameSlot(identifier); + if (slot != null) { + LookupResult lookupResult; + StableValue<Object> stableValue = getFrameSlotInfo(slot).stableValue; + if (stableValue != null) { + lookupResult = new StableValueLookupResult(identifier.toString(), stableValue); + } else { + FrameDescriptorMetaData currentMetaData = getMetaData(current); + if (currentMetaData.singletonFrame == null) { + return null; + } else { + assert currentMetaData.singletonFrame.get() != null; + lookupResult = new FrameAndSlotLookupResult(identifier.toString(), currentMetaData.singletonFrame.get(), slot); + } + } + addPreviousLookups(frame, current, identifier); + metaData.lookupResults.put(identifier, lookupResult); + return lookupResult; + } + Frame next = RArguments.getEnclosingFrame(current); + assert isEnclosingFrameDescriptor(current, next) : "the enclosing frame descriptor assumptions do not match the actual enclosing frame descriptor: " + getMetaData(current).name + " -> " + + getMetaData(next).name; + if (next == null) { + // leave "current" if we hit the empty env + break; + } + current = next; + } + // not frame slot found: missing value + addPreviousLookups(frame, current, identifier); + LookupResult lookupResult = new MissingLookupResult(identifier.toString()); + metaData.lookupResults.put(identifier, lookupResult); + return lookupResult; + } + + private static void addPreviousLookups(Frame from, Frame to, Object identifier) { + Frame mark = from; + while (true) { + FrameDescriptorMetaData lookupMetaData = getMetaData(mark); + lookupMetaData.previousLookups.add(identifier); + if (mark == to) { + break; + } + mark = RArguments.getEnclosingFrame(mark); + } + } + + private static boolean isEnclosingFrameDescriptor(Frame current, Frame next) { + assert current != null; + FrameDescriptorMetaData metaData = getMetaData(current); + FrameDescriptor nextDesc = next == null ? null : handleBaseNamespaceEnv(next); + return metaData.enclosingFrameDescriptor.getValue() == nextDesc; + } + + private static synchronized void invalidateNames(FrameDescriptorMetaData metaData, Collection<Object> identifiers) { + if (metaData.previousLookups.removeAll(identifiers)) { + for (Object identifier : identifiers) { + LookupResult result = metaData.lookupResults.remove(identifier); + if (result != null) { + result.invalidate(); + } + } + for (FrameDescriptor descriptor : metaData.subDescriptors) { + FrameDescriptorMetaData sub = getMetaData(descriptor); + invalidateNames(sub, identifiers); + } + } + } + + /** + * Special handling (return a marker frame descriptor) for the namespace:base environment. + */ + private static FrameDescriptor handleBaseNamespaceEnv(Frame frame) { + return frame == null ? null : frame instanceof NSBaseMaterializedFrame ? ((NSBaseMaterializedFrame) frame).getMarkerFrameDescriptor() : frame.getFrameDescriptor(); + } + + private static FrameDescriptorMetaData getMetaData(FrameDescriptor descriptor) { + FrameDescriptorMetaData result = frameDescriptors.get(descriptor); + assert result != null : "null metadata for " + descriptor; + return result; + } + + private static FrameDescriptorMetaData getMetaData(Frame frame) { + return getMetaData(handleBaseNamespaceEnv(frame)); + } + + public static synchronized void initializeEnclosingFrame(FrameDescriptor descriptor, Frame newEnclosingFrame) { + CompilerAsserts.neverPartOfCompilation(); + assert descriptor != null : "initializing enclosing of null descriptor"; + FrameDescriptorMetaData target = getMetaData(descriptor); + assert target != null : "frame descriptor wasn't registered properly"; + + FrameDescriptor newEnclosingDescriptor = handleBaseNamespaceEnv(newEnclosingFrame); + + // this function can be called multiple times with the same enclosing descriptor + assert target.enclosingFrameDescriptor.getAssumption().isValid(); + if (target.enclosingFrameDescriptor.getValue() != newEnclosingDescriptor) { + assert target.enclosingFrameDescriptor.getValue() == null : "existing enclosing descriptor while initializing " + target.name; + assert target.lookupResults.isEmpty() : "existing lookup results while initializing " + target.name; + + target.updateEnclosingFrameDescriptor(newEnclosingDescriptor); + if (newEnclosingDescriptor != null) { + FrameDescriptorMetaData newEnclosing = getMetaData(newEnclosingDescriptor); + newEnclosing.subDescriptors.add(descriptor); + } + } + } + + public static synchronized void initializeEnclosingFrame(Frame frame, Frame newEnclosingFrame) { + initializeEnclosingFrame(handleBaseNamespaceEnv(frame), newEnclosingFrame); + } + + public static synchronized void setEnclosingFrame(FrameDescriptor descriptor, MaterializedFrame newEnclosingFrame, MaterializedFrame oldEnclosingFrame) { + CompilerAsserts.neverPartOfCompilation(); + FrameDescriptorMetaData target = getMetaData(descriptor); + assert target != null : "frame descriptor wasn't registered properly for " + descriptor; + + // invalidate existing lookups + invalidateAllNames(target); + + FrameDescriptor oldEnclosingDescriptor = target.enclosingFrameDescriptor.getValue(); + assert (oldEnclosingDescriptor == null) == (oldEnclosingFrame == null) : "mismatch " + oldEnclosingDescriptor + " / " + oldEnclosingFrame; + + if (oldEnclosingDescriptor != null) { + assert oldEnclosingDescriptor == oldEnclosingFrame.getFrameDescriptor() : "mismatch " + oldEnclosingDescriptor + " / " + oldEnclosingFrame.getFrameDescriptor(); + FrameDescriptorMetaData oldEnclosing = getMetaData(oldEnclosingDescriptor); + oldEnclosing.subDescriptors.remove(descriptor); + } + FrameDescriptor newEnclosingDescriptor = handleBaseNamespaceEnv(newEnclosingFrame); + target.updateEnclosingFrameDescriptor(newEnclosingDescriptor); + + if (newEnclosingDescriptor != null) { + FrameDescriptorMetaData newEnclosing = getMetaData(newEnclosingDescriptor); + assert !newEnclosing.name.equals("global") || !target.name.equals("base"); + newEnclosing.subDescriptors.add(descriptor); + } + } + + public static synchronized void setEnclosingFrame(Frame frame, MaterializedFrame newEnclosingFrame, MaterializedFrame oldEnclosingFrame) { + setEnclosingFrame(handleBaseNamespaceEnv(frame), newEnclosingFrame, oldEnclosingFrame); + } + + private static void invalidateAllNames(FrameDescriptorMetaData target) { + for (Map.Entry<Object, LookupResult> entry : target.lookupResults.entrySet()) { + entry.getValue().invalidate(); + } + target.lookupResults.clear(); + target.previousLookups.clear(); + for (FrameDescriptor sub : target.subDescriptors) { + invalidateAllNames(getMetaData(sub)); + } + } + + public static synchronized void detach(Frame frame) { + CompilerAsserts.neverPartOfCompilation(); + FrameDescriptorMetaData position = getMetaData(frame); + FrameDescriptor oldEnclosingDescriptor = position.enclosingFrameDescriptor.getValue(); + FrameDescriptorMetaData oldEnclosing = getMetaData(oldEnclosingDescriptor); + FrameDescriptor newEnclosingDescriptor = oldEnclosing.enclosingFrameDescriptor.getValue(); + FrameDescriptorMetaData newEnclosing = getMetaData(newEnclosingDescriptor); + + assert position.enclosingFrameDescriptor.getAssumption().isValid() && oldEnclosing.enclosingFrameDescriptor.getAssumption().isValid(); + + invalidateNames(oldEnclosing, oldEnclosingDescriptor.getIdentifiers()); + + position.updateEnclosingFrameDescriptor(newEnclosingDescriptor); + oldEnclosing.updateEnclosingFrameDescriptor(null); + oldEnclosing.subDescriptors.remove(frame.getFrameDescriptor()); + newEnclosing.subDescriptors.remove(oldEnclosingDescriptor); + newEnclosing.subDescriptors.add(frame.getFrameDescriptor()); + } + + public static synchronized void attach(Frame frame, Frame newEnclosingFrame) { + CompilerAsserts.neverPartOfCompilation(); + FrameDescriptorMetaData position = getMetaData(frame); + FrameDescriptorMetaData newEnclosing = getMetaData(newEnclosingFrame); + assert position.enclosingFrameDescriptor.getAssumption().isValid(); + FrameDescriptor oldEnclosingDescriptor = position.enclosingFrameDescriptor.getValue(); + FrameDescriptorMetaData oldEnclosing = getMetaData(oldEnclosingDescriptor); + + invalidateAllNames(newEnclosing); + invalidateNames(position, newEnclosingFrame.getFrameDescriptor().getIdentifiers()); + + position.enclosingFrameDescriptor.getAssumption().invalidate(); + position.enclosingFrameDescriptor = new StableValue<>(newEnclosingFrame.getFrameDescriptor(), "enclosing frame"); + newEnclosing.enclosingFrameDescriptor.getAssumption().invalidate(); + newEnclosing.enclosingFrameDescriptor = new StableValue<>(oldEnclosingDescriptor, "enclosing frame"); + assert frame.getFrameDescriptor() == handleBaseNamespaceEnv(frame); + assert !newEnclosing.name.equals("global") || !position.name.equals("base"); + newEnclosing.subDescriptors.add(frame.getFrameDescriptor()); + oldEnclosing.subDescriptors.remove(frame.getFrameDescriptor()); + oldEnclosing.subDescriptors.add(newEnclosingFrame.getFrameDescriptor()); + } + + private static final int MAX_INVALIDATION_COUNT = 2; + private static final int MAX_GLOBAL_ENV_INVALIDATION_COUNT = 1; @SuppressWarnings("unused") private static void out(String format, Object... args) { -// System.out.println(String.format(format, args)); + // System.out.println(String.format(format, args)); } private static final class FrameSlotInfoImpl { - @CompilationFinal private StableValue<Object> stableValue; + /** + * This is meant to monitor updates performed on {@link FrameSlot}. Each {@link FrameSlot} + * holds an {@link Assumption} in it's "info" field; it is valid as long as no non-local + * update has ever taken place.<br/> + * The background to this rather strange assumption is that non-local reads are very hard to + * keep track of thanks to R powerful language features. To keep the maintenance for the + * assumption as cheap as possible, it checks only local reads - which is fast - and does a + * more costly check on "<<-" but invalidates the assumption as soon as "eval" and the like + * comes into play.<br/> + */ private final Assumption nonLocalModifiedAssumption = Truffle.getRuntime().createAssumption(); - private final Object identifier; + + @CompilationFinal private StableValue<Object> stableValue; private int invalidationCount; - public FrameSlotInfoImpl(boolean isSingletonFrame, Object identifier) { - this.identifier = identifier; + public FrameSlotInfoImpl(boolean isSingletonFrame, boolean isGlobalEnv, Object identifier) { if (isSingletonFrame) { stableValue = new StableValue<>(null, identifier.toString()); - invalidationCount = 0; + invalidationCount = isGlobalEnv ? MAX_GLOBAL_ENV_INVALIDATION_COUNT : MAX_INVALIDATION_COUNT; } else { stableValue = null; } @@ -70,37 +426,26 @@ public final class FrameSlotChangeMonitor { return stableValue != null; } - public void setValue(Object value) { + public void setValue(Object value, FrameSlot slot) { if (stableValue != null && stableValue.getValue() != value) { CompilerDirectives.transferToInterpreterAndInvalidate(); stableValue.getAssumption().invalidate(); - int maxInvalidationCount = value instanceof RFunction ? MAX_FUNCTION_INVALIDATION_COUNT : MAX_INVALIDATION_COUNT; - if (invalidationCount++ < maxInvalidationCount) { - out("setting singleton value %s = %s", identifier, value.getClass()); - stableValue = new StableValue<>(value, identifier.toString()); + if (invalidationCount > 0) { + invalidationCount--; + out("setting singleton value %s = %s", slot.getIdentifier(), value == null ? "null" : value.getClass()); + stableValue = new StableValue<>(value, String.valueOf(slot.getIdentifier())); } else { - out("setting non-singleton value %s", identifier); + out("setting non-singleton value %s", slot.getIdentifier()); stableValue = null; } } } - public void invalidateValue() { - if (stableValue != null) { - stableValue.getAssumption().invalidate(); - stableValue = null; - } - } - public StableValue<Object> getStableValue() { return stableValue; } } - private static final WeakHashMap<FrameDescriptor, StableValue<MaterializedFrame>> descriptorEnclosingFrameAssumptions = new WeakHashMap<>(); - private static final WeakHashMap<FrameDescriptor, Boolean> descriptorSingletonAssumptions = new WeakHashMap<>(); - private static final WeakHashMap<FrameDescriptor, StableValue<FrameDescriptor>> descriptorEnclosingDescriptorAssumptions = new WeakHashMap<>(); - /** * Retrieves the not-changed-locally {@link Assumption} for the given frame slot. * @@ -114,26 +459,23 @@ public final class FrameSlotChangeMonitor { Object info = slot.getInfo(); if (!(info instanceof FrameSlotInfoImpl)) { CompilerDirectives.transferToInterpreter(); - throw RInternalError.shouldNotReachHere("Each FrameSlot should hold a FrameSlotInfo in it's info field!"); + throw RInternalError.shouldNotReachHere("Each FrameSlot should hold a FrameSlotInfo in its info field!"); } return (FrameSlotInfoImpl) info; } - // method for creating new frame slots - - public static FrameSlot addFrameSlot(FrameDescriptor fd, Object identifier, FrameSlotKind kind) { - boolean isSingletonFrame = descriptorSingletonAssumptions.containsKey(fd); - return fd.addFrameSlot(identifier, new FrameSlotInfoImpl(isSingletonFrame, identifier), kind); - } - - public static FrameSlot findOrAddFrameSlot(FrameDescriptor fd, Object identifier) { - FrameSlot frameSlot = fd.findFrameSlot(identifier); - return frameSlot != null ? frameSlot : addFrameSlot(fd, identifier, FrameSlotKind.Illegal); - } + // methods for creating new frame slots public static FrameSlot findOrAddFrameSlot(FrameDescriptor fd, Object identifier, FrameSlotKind initialKind) { + CompilerAsserts.neverPartOfCompilation(); FrameSlot frameSlot = fd.findFrameSlot(identifier); - return frameSlot != null ? frameSlot : addFrameSlot(fd, identifier, initialKind); + if (frameSlot != null) { + return frameSlot; + } else { + FrameDescriptorMetaData metaData = getMetaData(fd); + invalidateNames(metaData, Arrays.asList(identifier)); + return fd.addFrameSlot(identifier, new FrameSlotInfoImpl(metaData.singletonFrame != null, "global".equals(metaData.name), identifier), initialKind); + } } // methods for changing frame slot contents @@ -146,8 +488,12 @@ public final class FrameSlotChangeMonitor { * {@link RInternalError} otherwise * @param invalidateProfile Used to guard the invalidation code. */ - private static void checkAndInvalidate(Frame curFrame, FrameSlot slot, boolean isNonLocal, BranchProfile invalidateProfile) { + private static void checkAndInvalidate(Frame curFrame, FrameSlot slot, boolean isNonLocal, Object newValue, BranchProfile invalidateProfile) { assert curFrame.getFrameDescriptor() == slot.getFrameDescriptor(); + FrameSlotInfoImpl info = getFrameSlotInfo(slot); + if (info.needsInvalidation()) { + info.setValue(newValue, slot); + } if (getNotChangedNonLocallyAssumption(slot).isValid()) { // Check whether current frame is used outside a regular stack @@ -164,169 +510,57 @@ public final class FrameSlotChangeMonitor { public static void setByteAndInvalidate(Frame frame, FrameSlot frameSlot, byte newValue, boolean isNonLocal, BranchProfile invalidateProfile) { frame.setByte(frameSlot, newValue); - FrameSlotInfoImpl info = getFrameSlotInfo(frameSlot); - if (info.needsInvalidation()) { - info.setValue(newValue); - } - checkAndInvalidate(frame, frameSlot, isNonLocal, invalidateProfile); + checkAndInvalidate(frame, frameSlot, isNonLocal, newValue, invalidateProfile); } public static void setIntAndInvalidate(Frame frame, FrameSlot frameSlot, int newValue, boolean isNonLocal, BranchProfile invalidateProfile) { frame.setInt(frameSlot, newValue); - FrameSlotInfoImpl info = getFrameSlotInfo(frameSlot); - if (info.needsInvalidation()) { - info.setValue(newValue); - } - checkAndInvalidate(frame, frameSlot, isNonLocal, invalidateProfile); + checkAndInvalidate(frame, frameSlot, isNonLocal, newValue, invalidateProfile); } public static void setDoubleAndInvalidate(Frame frame, FrameSlot frameSlot, double newValue, boolean isNonLocal, BranchProfile invalidateProfile) { frame.setDouble(frameSlot, newValue); - FrameSlotInfoImpl info = getFrameSlotInfo(frameSlot); - if (info.needsInvalidation()) { - info.setValue(newValue); - } - checkAndInvalidate(frame, frameSlot, isNonLocal, invalidateProfile); + checkAndInvalidate(frame, frameSlot, isNonLocal, newValue, invalidateProfile); } public static void setObjectAndInvalidate(Frame frame, FrameSlot frameSlot, Object newValue, boolean isNonLocal, BranchProfile invalidateProfile) { frame.setObject(frameSlot, newValue); - FrameSlotInfoImpl info = getFrameSlotInfo(frameSlot); - if (info.needsInvalidation()) { - info.setValue(newValue); - } - checkAndInvalidate(frame, frameSlot, isNonLocal, invalidateProfile); - } - - // update enclosing frames - - public static void invalidateEnclosingFrame(Frame frame) { - CompilerAsserts.neverPartOfCompilation(); - MaterializedFrame enclosingFrame = RArguments.getEnclosingFrame(frame); - getOrInitializeEnclosingFrameAssumption(frame, frame.getFrameDescriptor(), null, enclosingFrame); - getOrInitializeEnclosingFrameDescriptorAssumption(frame, frame.getFrameDescriptor(), enclosingFrame == null ? null : enclosingFrame.getFrameDescriptor()); + checkAndInvalidate(frame, frameSlot, isNonLocal, newValue, invalidateProfile); } /** * Initializes the internal data structures for a newly created frame descriptor that is * intended to be used for a non-function frame (and thus will only ever be used for one frame). - * - * The namespace:base environment needs to be handled specially, because it shares a frame (and - * thus, also a frame descriptor) with the package:base environment. */ - public static synchronized void initializeNonFunctionFrameDescriptor(FrameDescriptor frameDescriptor, boolean isNamespaceBase) { - descriptorEnclosingFrameAssumptions.put(frameDescriptor, StableValue.invalidated()); - descriptorEnclosingDescriptorAssumptions.put(frameDescriptor, StableValue.invalidated()); - if (!isNamespaceBase) { - descriptorSingletonAssumptions.put(frameDescriptor, Boolean.FALSE); - } - } - - public static synchronized void initializeFunctionFrameDescriptor(FrameDescriptor frameDescriptor) { - descriptorEnclosingFrameAssumptions.put(frameDescriptor, StableValue.invalidated()); - descriptorEnclosingDescriptorAssumptions.put(frameDescriptor, StableValue.invalidated()); + public static synchronized void initializeNonFunctionFrameDescriptor(String name, MaterializedFrame frame) { + frameDescriptors.put(handleBaseNamespaceEnv(frame), new FrameDescriptorMetaData(name, frame)); } - public static synchronized StableValue<MaterializedFrame> getEnclosingFrameAssumption(FrameDescriptor descriptor) { - return descriptorEnclosingFrameAssumptions.get(descriptor); + public static synchronized void initializeFunctionFrameDescriptor(String name, FrameDescriptor frameDescriptor) { + frameDescriptors.put(frameDescriptor, new FrameDescriptorMetaData(name, null)); } public static synchronized StableValue<FrameDescriptor> getEnclosingFrameDescriptorAssumption(FrameDescriptor descriptor) { - return descriptorEnclosingDescriptorAssumptions.get(descriptor); - } - - /** - * Special handling (return a marker frame) for the namespace:base environment. - */ - private static FrameDescriptor handleBaseNamespaceEnv(Frame frame, FrameDescriptor originalFrameDescriptor) { - return frame instanceof NSBaseMaterializedFrame ? ((NSBaseMaterializedFrame) frame).getMarkerFrameDescriptor() : originalFrameDescriptor; - } - - public static synchronized StableValue<FrameDescriptor> getOrInitializeEnclosingFrameDescriptorAssumption(Frame frame, FrameDescriptor originalFrameDescriptor, FrameDescriptor newValue) { - CompilerAsserts.neverPartOfCompilation(); - FrameDescriptor frameDescriptor = handleBaseNamespaceEnv(frame, originalFrameDescriptor); - StableValue<FrameDescriptor> currentValue = descriptorEnclosingDescriptorAssumptions.get(frameDescriptor); - if (currentValue.getAssumption().isValid()) { - if (currentValue.getValue() == newValue) { - return currentValue; - } else { - currentValue.getAssumption().invalidate(); - } - } - currentValue = new StableValue<>(newValue, "enclosing frame descriptor"); - descriptorEnclosingDescriptorAssumptions.put(frameDescriptor, currentValue); - return currentValue; - } - - public static synchronized StableValue<MaterializedFrame> getOrInitializeEnclosingFrameAssumption(Frame frame, FrameDescriptor originalFrameDescriptor, StableValue<MaterializedFrame> value, - MaterializedFrame newValue) { - CompilerAsserts.neverPartOfCompilation(); - FrameDescriptor frameDescriptor = handleBaseNamespaceEnv(frame, originalFrameDescriptor); - if (value != null) { - value.getAssumption().invalidate(); - } - StableValue<MaterializedFrame> currentValue = descriptorEnclosingFrameAssumptions.get(frameDescriptor); - if (currentValue == null) { - return null; - } - if (currentValue.getAssumption().isValid()) { - if (currentValue.getValue() == newValue) { - return currentValue; - } else { - currentValue.getAssumption().invalidate(); - } - } - if (currentValue == StableValue.<MaterializedFrame> invalidated()) { - currentValue = new StableValue<>(newValue, "enclosing frame"); - descriptorEnclosingFrameAssumptions.put(frameDescriptor, currentValue); - return currentValue; - } else { - descriptorEnclosingFrameAssumptions.remove(frameDescriptor); - return null; - } - } - - public static boolean checkSingletonFrame(VirtualFrame vf) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - return checkSingletonFrameInternal(vf); - } - - private static synchronized boolean checkSingletonFrameInternal(VirtualFrame vf) { - Boolean value = descriptorSingletonAssumptions.get(vf.getFrameDescriptor()); - if (value == null) { - return false; - } else if (value == Boolean.FALSE) { - out("marking frame descriptor %s as singleton", vf.getFrameDescriptor()); - descriptorSingletonAssumptions.put(vf.getFrameDescriptor(), Boolean.TRUE); - return true; - } else { - out("marking frame descriptor %s as non-singleton", vf.getFrameDescriptor()); - for (FrameSlot slot : vf.getFrameDescriptor().getSlots()) { - if (getFrameSlotInfo(slot).needsInvalidation()) { - getFrameSlotInfo(slot).invalidateValue(); - out(" invalidating singleton slot %s", slot.getIdentifier()); - } - } - descriptorSingletonAssumptions.remove(vf.getFrameDescriptor()); - return false; - } + return frameDescriptors.get(descriptor).enclosingFrameDescriptor; } public static synchronized StableValue<Object> getStableValueAssumption(FrameDescriptor descriptor, FrameSlot frameSlot, Object value) { CompilerAsserts.neverPartOfCompilation(); StableValue<Object> stableValue = getFrameSlotInfo(frameSlot).getStableValue(); if (stableValue != null) { - assert descriptorSingletonAssumptions.containsKey(descriptor) : "single frame slot within non-singleton descriptor"; + assert getMetaData(descriptor).singletonFrame != null : "single frame slot within non-singleton descriptor"; assert stableValue.getValue() == value || (stableValue.getValue() != null && (stableValue.getValue().equals(value) || !stableValue.getAssumption().isValid())) : stableValue.getValue() + " vs. " + value; } return stableValue; } - public static void updateValue(FrameSlot slot, Object value) { - FrameSlotInfoImpl info = getFrameSlotInfo(slot); - if (info.needsInvalidation()) { - info.setValue(value); - } + public static synchronized MaterializedFrame getSingletonFrame(FrameDescriptor descriptor) { + WeakReference<MaterializedFrame> singleton = getMetaData(descriptor).singletonFrame; + return singleton == null ? null : singleton.get(); + } + + public static boolean isValidFrameDescriptor(FrameDescriptor frameDesc) { + return getMetaData(frameDesc) != null; } } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/NSBaseMaterializedFrame.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/NSBaseMaterializedFrame.java index ef3392887ec3f89e3a78bdad9bd3f757288148f4..642a9da9ef22f883b1be193a4428bd90d7577fa1 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/NSBaseMaterializedFrame.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/NSBaseMaterializedFrame.java @@ -45,13 +45,12 @@ public final class NSBaseMaterializedFrame implements MaterializedFrame { this.packageBaseFrame = packageBaseFrame; this.arguments = Arrays.copyOf(packageBaseFrame.getArguments(), packageBaseFrame.getArguments().length); this.markerFrameDescriptor = new FrameDescriptor(); - FrameSlotChangeMonitor.initializeNonFunctionFrameDescriptor(markerFrameDescriptor, true); - RArguments.setEnclosingFrame(this, globalFrame); + FrameSlotChangeMonitor.initializeNonFunctionFrameDescriptor("namespace:base", this); + RArguments.initializeEnclosingFrame(this, globalFrame); } public void updateGlobalFrame(MaterializedFrame globalFrame) { RArguments.setEnclosingFrame(this, globalFrame); - FrameSlotChangeMonitor.invalidateEnclosingFrame(this); } public FrameDescriptor getMarkerFrameDescriptor() { diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/REnvTruffleFrameAccess.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/REnvTruffleFrameAccess.java index 7eb94f4ddb8aa2286992545f043ff567f7b313e8..943bba2586594b0c95096f9e00ec2211a742cc2e 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/REnvTruffleFrameAccess.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/REnvTruffleFrameAccess.java @@ -75,21 +75,16 @@ public final class REnvTruffleFrameAccess extends REnvFrameAccess { if (lockedBindings != null && lockedBindings.contains(key)) { throw new PutException(RError.Message.ENV_CHANGE_BINDING, key); } - FrameDescriptor fd = frame.getFrameDescriptor(); - FrameSlot slot = fd.findFrameSlot(key); - FrameSlotKind valueSlotKind = RRuntime.getSlotKind(value); + FrameDescriptor fd = frame.getFrameDescriptor(); + FrameSlot slot = FrameSlotChangeMonitor.findOrAddFrameSlot(fd, key, valueSlotKind); - // Handle all other values - if (slot == null) { - slot = FrameSlotChangeMonitor.addFrameSlot(fd, key, valueSlotKind); - } else { - if (valueSlotKind != slot.getKind()) { - // we must not toggle between slot kinds, so go to Object - valueSlotKind = FrameSlotKind.Object; - slot.setKind(valueSlotKind); - } + if (valueSlotKind != slot.getKind()) { + // we must not toggle between slot kinds, so go to Object + valueSlotKind = FrameSlotKind.Object; + slot.setKind(valueSlotKind); } + switch (valueSlotKind) { case Byte: FrameSlotChangeMonitor.setByteAndInvalidate(frame, slot, (byte) value, false, null); diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test index 84c1ffe516f66125b0648162f28629e3a4896794..f6880d4a82f9d94c583dd9311592551b1e298d19 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test @@ -17460,6 +17460,10 @@ Error in environment(e1) <- 3 : replacement object is not an environment ##com.oracle.truffle.r.test.builtins.TestBuiltin_environmentassign.testenvironmentassign1 #{ e1 <- new.env(); environment(e1) <- NULL } +##com.oracle.truffle.r.test.builtins.TestBuiltin_environmentassign.testenvironmentassign1 +#{ f <- function() x; f2 <- f; e <- new.env(); assign('x', 2, envir=e); x <- 1; environment(f) <- e; c(f(), f2())} +[1] 2 1 + ##com.oracle.truffle.r.test.builtins.TestBuiltin_environmentassign.testenvironmentassign1 #{ f <- function() {}; e1 <- new.env(); environment(f) <- e1 } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestS4.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestS4.java index c63df2532b2b6d9af4ae81b7867e80801aaf4097..c67c5169556fe3b15f489216c410db35215c98e1 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestS4.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestS4.java @@ -74,8 +74,7 @@ public class TestS4 extends TestBase { @Test public void testAllocation() { assertEval("{ new(\"numeric\") }"); - // output slightly different from GNU R even though we use R's "show" method to print it - assertEval(Ignored.OutputFormatting, "{ setClass(\"foo\", representation(j=\"numeric\")); new(\"foo\", j=42) }"); + assertEval(Ignored.Unknown, "{ setClass(\"foo\", representation(j=\"numeric\")); new(\"foo\", j=42) }"); } @Test diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_attributes.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_attributes.java index 7c14cc20416f6cb267d541c6585cdf18d428088d..de15156ae3ea2966f5c7c62472e61a25c99bc924 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_attributes.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_attributes.java @@ -50,7 +50,7 @@ public class TestBuiltin_attributes extends TestBase { @Test public void testattributes7() { - assertEval(Ignored.Unknown, "argv <- list(NULL);attributes(argv[[1]]);"); + assertEval("argv <- list(NULL);attributes(argv[[1]]);"); } @Test diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_environmentassign.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_environmentassign.java index 9d2f7b7c947aa142a8cd9b47d09ea1c74e4584da..c96618819e1bb81de79c103a91ddb84579ca8cfb 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_environmentassign.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_environmentassign.java @@ -24,5 +24,6 @@ public class TestBuiltin_environmentassign extends TestBase { assertEval(Output.ContainsError, "{ e1 <- new.env(); environment(e1) <- 3 }"); assertEval("{ f <- function() {}; e1 <- new.env(); environment(f) <- e1 }"); + assertEval("{ f <- function() x; f2 <- f; e <- new.env(); assign('x', 2, envir=e); x <- 1; environment(f) <- e; c(f(), f2())}"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_identical.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_identical.java index 1addac815536b6a329ff06e3bdd6e95ae3fcf0fc..fd95b5d695f19e87b43daf2cf408c4ec8fcd6da6 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_identical.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_identical.java @@ -39,8 +39,7 @@ public class TestBuiltin_identical extends TestBase { @Test public void testidentical5() { - assertEval(Ignored.Unknown, - "argv <- list(structure(list(a = 1), .Dim = 1L, .Dimnames = list('a')), structure(list(a = 1), .Dim = 1L, .Dimnames = list('a')), TRUE, TRUE, TRUE, TRUE, FALSE); .Internal(identical(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]]))"); + assertEval("argv <- list(structure(list(a = 1), .Dim = 1L, .Dimnames = list('a')), structure(list(a = 1), .Dim = 1L, .Dimnames = list('a')), TRUE, TRUE, TRUE, TRUE, FALSE); .Internal(identical(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]]))"); } @Test @@ -55,8 +54,7 @@ public class TestBuiltin_identical extends TestBase { @Test public void testidentical8() { - assertEval(Ignored.Unknown, - "argv <- list(structure(list(a = 1), .Names = 'a', .Tsp = c(1, 1, 1), class = 'ts'), structure(list(a = 1), .Names = 'a', .Tsp = c(1, 1, 1), class = 'ts'), TRUE, TRUE, TRUE, TRUE, FALSE); .Internal(identical(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]]))"); + assertEval("argv <- list(structure(list(a = 1), .Names = 'a', .Tsp = c(1, 1, 1), class = 'ts'), structure(list(a = 1), .Names = 'a', .Tsp = c(1, 1, 1), class = 'ts'), TRUE, TRUE, TRUE, TRUE, FALSE); .Internal(identical(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]]))"); } @Test @@ -137,8 +135,7 @@ public class TestBuiltin_identical extends TestBase { @Test public void testidentical24() { - assertEval(Ignored.Unknown, - "argv <- list(list(c('r1', 'r3', 'r4', 'r5', 'r6', 'r7', 'r8', 'r9', 'r10', 'r11', 'r12', 'r13', 'r14', 'r15', 'r16', 'r17', 'r18', 'r19', 'r20', 'r21', 'r22', 'r23', 'r24', 'r25', 'r26', 'r27', 'r28', 'r29', 'r30', 'r31', 'r32', 'r33', 'r34', 'r35', 'r36', 'r37', 'r38', 'r39', 'r40'), c('c1', 'c2', 'c3', 'c4', 'c5', 'c6', 'c7', 'c8', 'c9', 'c10', 'c11', 'c12', 'c13', 'c14', 'c15', 'c16', 'c17', 'c18', 'c19', 'c20')), list(character(0), character(0)), TRUE, TRUE, TRUE, TRUE, FALSE); .Internal(identical(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]]))"); + assertEval("argv <- list(list(c('r1', 'r3', 'r4', 'r5', 'r6', 'r7', 'r8', 'r9', 'r10', 'r11', 'r12', 'r13', 'r14', 'r15', 'r16', 'r17', 'r18', 'r19', 'r20', 'r21', 'r22', 'r23', 'r24', 'r25', 'r26', 'r27', 'r28', 'r29', 'r30', 'r31', 'r32', 'r33', 'r34', 'r35', 'r36', 'r37', 'r38', 'r39', 'r40'), c('c1', 'c2', 'c3', 'c4', 'c5', 'c6', 'c7', 'c8', 'c9', 'c10', 'c11', 'c12', 'c13', 'c14', 'c15', 'c16', 'c17', 'c18', 'c19', 'c20')), list(character(0), character(0)), TRUE, TRUE, TRUE, TRUE, FALSE); .Internal(identical(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]]))"); } @Test @@ -214,8 +211,8 @@ public class TestBuiltin_identical extends TestBase { assertEval("{ x <- 1 ; attr(x, \"hello\") <- 2 ; attr(x, \"my\") <- 10; attr(x, \"hello\") <- NULL ; y <- 1 ; attr(y, \"my\") <- 10 ; identical(x,y) }"); assertEval("{ identical(0/0,1[2]) }"); - assertEval(Ignored.Unknown, "{ identical(list(1, list(2)), list(list(1), 1)) }"); - assertEval(Ignored.Unknown, "{ identical(list(1, list(2)), list(1, list(2))) }"); + assertEval("{ identical(list(1, list(2)), list(list(1), 1)) }"); + assertEval("{ identical(list(1, list(2)), list(1, list(2))) }"); assertEval(Ignored.Unknown, "{ x <- 1 ; attr(x, \"my\") <- 10; identical(x, 1) }"); assertEval(Ignored.Unknown, "{ x <- 1 ; attr(x, \"my\") <- 10; y <- 1 ; attr(y, \"my\") <- 11 ; identical(x,y) }"); diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_primUntrace.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_primUntrace.java index 05bfe99ab50167d83724a76a1973942567d66df6..6bedb37ca92c8d737857dae3e1ef46f78a1285b2 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_primUntrace.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_primUntrace.java @@ -19,6 +19,6 @@ public class TestBuiltin_primUntrace extends TestBase { @Test public void testprimUntrace1() { - assertEval(Ignored.Unknown, "argv <- list(.Primitive('sum'));.primUntrace(argv[[1]]);"); + assertEval("argv <- list(.Primitive('sum'));.primUntrace(argv[[1]]);"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_storagemodeassign_.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_storagemodeassign_.java index 474ed87bd3338f13634bd9cd90fcf2edb7b4738e..c7ead89da5361fdc85beb84f0ba84547a862dfc5 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_storagemodeassign_.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_storagemodeassign_.java @@ -20,7 +20,6 @@ public class TestBuiltin_storagemodeassign_ extends TestBase { @Test public void teststoragemodeassign_1() { - assertEval(Ignored.Unknown, "argv <- structure(list(structure(c(0, 1, 2), .Dim = c(3L, 1L)), value = 'integer'), .Names = c('', 'value'));do.call('storage.mode<-', argv)"); + assertEval("argv <- structure(list(structure(c(0, 1, 2), .Dim = c(3L, 1L)), value = 'integer'), .Names = c('', 'value'));do.call('storage.mode<-', argv)"); } - }