diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java index d1d2b58ef79d253bb9b8b16e53db020ce812e26a..64b4b0f6136b8399ccf3ef6f7075b5f849e41e77 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java @@ -236,10 +236,10 @@ public class CallAndExternalFunctions { return new Object[]{RMissing.instance, RArgsValuesAndNames.EMPTY, RMissing.instance}; } - private Object[] materializeArgs(VirtualFrame frame, Object[] args) { + private Object[] materializeArgs(Object[] args) { Object[] materializedArgs = new Object[args.length]; for (int i = 0; i < args.length; i++) { - materializedArgs[i] = materializeNode.execute(frame, args[i]); + materializedArgs[i] = materializeNode.execute(args[i]); } return materializedArgs; } @@ -666,38 +666,37 @@ public class CallAndExternalFunctions { */ @SuppressWarnings("unused") @Specialization(limit = "2", guards = {"cached == symbol", "builtin == null"}) - protected Object callNamedFunction(VirtualFrame frame, RList symbol, RArgsValuesAndNames args, Object packageName, + protected Object callNamedFunction(RList symbol, RArgsValuesAndNames args, Object packageName, @Cached("symbol") RList cached, @Cached("lookupBuiltin(symbol)") RExternalBuiltinNode builtin, @Cached("new()") ExtractNativeCallInfoNode extractSymbolInfo, @Cached("extractSymbolInfo.execute(symbol)") NativeCallInfo nativeCallInfo) { - return callRFFINode.dispatch(nativeCallInfo, materializeArgs(frame, args.getArguments())); + return callRFFINode.dispatch(nativeCallInfo, materializeArgs(args.getArguments())); } /** * For some reason, the list instance may change, although it carries the same info. For * such cases there is this generic version. */ - @SuppressWarnings("unused") @Specialization(replaces = {"callNamedFunction", "doExternal"}) - protected Object callNamedFunctionGeneric(VirtualFrame frame, RList symbol, RArgsValuesAndNames args, Object packageName, + protected Object callNamedFunctionGeneric(RList symbol, RArgsValuesAndNames args, @SuppressWarnings("unused") Object packageName, @Cached("new()") ExtractNativeCallInfoNode extractSymbolInfo) { RExternalBuiltinNode builtin = lookupBuiltin(symbol); if (builtin != null) { throw RInternalError.shouldNotReachHere("Cache for .Calls with FastR reimplementation (lookupBuiltin(...) != null) exceeded the limit"); } NativeCallInfo nativeCallInfo = extractSymbolInfo.execute(symbol); - return callRFFINode.dispatch(nativeCallInfo, materializeArgs(frame, args.getArguments())); + return callRFFINode.dispatch(nativeCallInfo, materializeArgs(args.getArguments())); } /** * {@code .NAME = string}, no package specified. */ @Specialization - protected Object callNamedFunction(VirtualFrame frame, String symbol, RArgsValuesAndNames args, @SuppressWarnings("unused") RMissing packageName, + protected Object callNamedFunction(String symbol, RArgsValuesAndNames args, @SuppressWarnings("unused") RMissing packageName, @Cached("createRegisteredNativeSymbol(CallNST)") DLL.RegisteredNativeSymbol rns, @Cached("create()") DLL.RFindSymbolNode findSymbolNode) { - return callNamedFunctionWithPackage(frame, symbol, args, null, rns, findSymbolNode); + return callNamedFunctionWithPackage(symbol, args, null, rns, findSymbolNode); } /** @@ -705,19 +704,19 @@ public class CallAndExternalFunctions { * define that symbol. */ @Specialization - protected Object callNamedFunctionWithPackage(VirtualFrame frame, String symbol, RArgsValuesAndNames args, String packageName, + protected Object callNamedFunctionWithPackage(String symbol, RArgsValuesAndNames args, String packageName, @Cached("createRegisteredNativeSymbol(CallNST)") DLL.RegisteredNativeSymbol rns, @Cached("create()") DLL.RFindSymbolNode findSymbolNode) { DLL.SymbolHandle func = findSymbolNode.execute(symbol, packageName, rns); if (func == DLL.SYMBOL_NOT_FOUND) { throw error(RError.Message.SYMBOL_NOT_IN_TABLE, symbol, "Call", packageName); } - return callRFFINode.dispatch(new NativeCallInfo(symbol, func, rns.getDllInfo()), materializeArgs(frame, args.getArguments())); + return callRFFINode.dispatch(new NativeCallInfo(symbol, func, rns.getDllInfo()), materializeArgs(args.getArguments())); } @Specialization - protected Object callNamedFunctionWithPackage(VirtualFrame frame, RExternalPtr symbol, RArgsValuesAndNames args, @SuppressWarnings("unused") RMissing packageName) { - return callRFFINode.dispatch(new NativeCallInfo("", symbol.getAddr(), null), materializeArgs(frame, args.getArguments())); + protected Object callNamedFunctionWithPackage(RExternalPtr symbol, RArgsValuesAndNames args, @SuppressWarnings("unused") RMissing packageName) { + return callRFFINode.dispatch(new NativeCallInfo("", symbol.getAddr(), null), materializeArgs(args.getArguments())); } @SuppressWarnings("unused") diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/helpers/MaterializeNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/helpers/MaterializeNode.java index 26f99e343d3a5f7f48e3445aa881b2fcd10b772d..c762b1d26b3acd70fb21ccfb88f908a327c34ebb 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/helpers/MaterializeNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/helpers/MaterializeNode.java @@ -24,10 +24,10 @@ package com.oracle.truffle.r.nodes.helpers; import com.oracle.truffle.api.CompilerAsserts; import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Fallback; import com.oracle.truffle.api.dsl.Specialization; -import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.r.nodes.attributes.HasAttributesNode; import com.oracle.truffle.r.nodes.attributes.IterableAttributeNode; @@ -45,9 +45,6 @@ public abstract class MaterializeNode extends Node { @Child private IterableAttributeNode attributesIt; @Child private SetAttributeNode setAttributeNode; - @Child private MaterializeNode recursive; - @Child private MaterializeNode recursiveAttr; - private final boolean deep; protected MaterializeNode(boolean deep) { @@ -58,63 +55,39 @@ public abstract class MaterializeNode extends Node { } } - public abstract Object execute(VirtualFrame frame, Object arg); + public abstract Object execute(Object arg); @Specialization - protected RList doList(VirtualFrame frame, RList vec) { - RList materialized = materializeContents(frame, vec); - materializeAttributes(frame, materialized); + protected RList doList(RList vec) { + RList materialized = materializeContents(vec); + materializeAttributes(materialized); return materialized; } - private RList materializeContents(VirtualFrame frame, RList list) { - boolean changed = false; - RList materializedContents = null; - for (int i = 0; i < list.getLength(); i++) { - if (recursive == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - recursive = insert(MaterializeNode.create(deep)); - } - Object element = list.getDataAt(i); - Object materializedElem = recursive.execute(frame, element); - if (materializedElem != element) { - materializedContents = (RList) list.copy(); - changed = true; - } - if (changed && materializedElem != element) { - materializedContents.setDataAt(i, materializedElem); - } - } - if (changed) { - return materializedContents; - } - return list; - } - @Specialization(limit = "LIMIT", guards = {"vec.getClass() == cachedClass"}) - protected RAttributable doAbstractContainerCached(VirtualFrame frame, RAttributable vec, + protected RAttributable doAbstractContainerCached(RAttributable vec, @SuppressWarnings("unused") @Cached("vec.getClass()") Class<?> cachedClass) { if (vec instanceof RList) { - return doList(frame, (RList) vec); + return doList((RList) vec); } else if (vec instanceof RAbstractContainer) { RAbstractContainer materialized = ((RAbstractContainer) vec).materialize(); - materializeAttributes(frame, materialized); + materializeAttributes(materialized); return materialized; } - materializeAttributes(frame, vec); + materializeAttributes(vec); return vec; } @Specialization(replaces = "doAbstractContainerCached") - protected RAttributable doAbstractContainer(VirtualFrame frame, RAttributable vec) { + protected RAttributable doAbstractContainer(RAttributable vec) { if (vec instanceof RList) { - return doList(frame, (RList) vec); + return doList((RList) vec); } else if (vec instanceof RAbstractContainer) { RAbstractContainer materialized = ((RAbstractContainer) vec).materialize(); - materializeAttributes(frame, materialized); + materializeAttributes(materialized); return materialized; } - materializeAttributes(frame, vec); + materializeAttributes(vec); return vec; } @@ -123,17 +96,35 @@ public abstract class MaterializeNode extends Node { return o; } - private void materializeAttributes(VirtualFrame frame, RAttributable materialized) { + private RList materializeContents(RList list) { + boolean changed = false; + RList materializedContents = null; + for (int i = 0; i < list.getLength(); i++) { + Object element = list.getDataAt(i); + Object materializedElem = doGenericSlowPath(element); + if (materializedElem != element) { + materializedContents = (RList) list.copy(); + changed = true; + } + if (changed && materializedElem != element) { + materializedContents.setDataAt(i, materializedElem); + } + } + if (changed) { + return materializedContents; + } + return list; + } + + private void materializeAttributes(RAttributable materialized) { // TODO we could further optimize by first checking for fixed/special attributes if (deep && hasAttributes.execute(materialized)) { if (attributesIt == null) { - assert recursiveAttr == null; CompilerDirectives.transferToInterpreterAndInvalidate(); attributesIt = insert(IterableAttributeNode.create()); - recursiveAttr = insert(MaterializeNode.create(deep)); } for (RAttribute attr : attributesIt.execute(materialized)) { - Object materializedAttr = recursiveAttr.execute(frame, attr.getValue()); + Object materializedAttr = doGenericSlowPath(attr.getValue()); if (materializedAttr != attr.getValue()) { if (setAttributeNode == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); @@ -145,6 +136,14 @@ public abstract class MaterializeNode extends Node { } } + @TruffleBoundary + private Object doGenericSlowPath(Object element) { + if (element instanceof RAttributable) { + return doAbstractContainer((RAttributable) element); + } + return element; + } + public static MaterializeNode create(boolean deep) { return MaterializeNodeGen.create(deep); }