Skip to content
Snippets Groups Projects
Commit fc208bbb authored by Florian Angerer's avatar Florian Angerer
Browse files

Implemented recursive materialization for FFI arguments.

parent bb67f8c1
No related branches found
No related tags found
No related merge requests found
......@@ -224,7 +224,7 @@ public class CallAndExternalFunctions {
public abstract static class DotCall extends LookupAdapter {
@Child CallRFFI.InvokeCallNode callRFFINode = RFFIFactory.getCallRFFI().createInvokeCallNode();
@Child MaterializeNode materializeNode = MaterializeNode.create();
@Child MaterializeNode materializeNode = MaterializeNode.create(true);
static {
Casts.noCasts(DotCall.class);
......
......@@ -22,28 +22,100 @@
*/
package com.oracle.truffle.r.runtime.data.nodes;
import com.oracle.truffle.api.CompilerAsserts;
import com.oracle.truffle.api.CompilerDirectives;
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;
import com.oracle.truffle.r.nodes.attributes.SetAttributeNode;
import com.oracle.truffle.r.runtime.data.RAttributable;
import com.oracle.truffle.r.runtime.data.RAttributesLayout.RAttribute;
import com.oracle.truffle.r.runtime.data.RList;
import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
public abstract class MaterializeNode extends Node {
protected static final int LIMIT = 10;
@Child private HasAttributesNode hasAttributes;
@Child private IterableAttributeNode attributesIt;
@Child private SetAttributeNode setAttributeNode;
@Child private MaterializeNode recursive;
@Child private MaterializeNode recursiveAttr;
private final boolean deep;
protected MaterializeNode(boolean deep) {
this.deep = deep;
if (deep) {
CompilerAsserts.neverPartOfCompilation();
hasAttributes = insert(HasAttributesNode.create());
}
}
public abstract Object execute(VirtualFrame frame, Object arg);
@Specialization
protected RList doList(VirtualFrame frame, RList vec) {
RList materialized = materializeContents(frame, vec);
materializeAttributes(frame, 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 RAbstractContainer doAbstractContainerCached(RAbstractContainer vec,
protected RAttributable doAbstractContainerCached(VirtualFrame frame, RAttributable vec,
@SuppressWarnings("unused") @Cached("vec.getClass()") Class<?> cachedClass) {
return vec.materialize();
if (vec instanceof RList) {
return doList(frame, (RList) vec);
} else if (vec instanceof RAbstractContainer) {
RAbstractContainer materialized = ((RAbstractContainer) vec).materialize();
materializeAttributes(frame, materialized);
return materialized;
}
materializeAttributes(frame, vec);
return vec;
}
@Specialization(replaces = "doAbstractContainerCached")
protected RAbstractContainer doAbstractContainer(RAbstractContainer vec) {
return vec.materialize();
protected RAttributable doAbstractContainer(VirtualFrame frame, RAttributable vec) {
if (vec instanceof RList) {
return doList(frame, (RList) vec);
} else if (vec instanceof RAbstractContainer) {
RAbstractContainer materialized = ((RAbstractContainer) vec).materialize();
materializeAttributes(frame, materialized);
return materialized;
}
materializeAttributes(frame, vec);
return vec;
}
@Fallback
......@@ -51,8 +123,30 @@ public abstract class MaterializeNode extends Node {
return o;
}
public static MaterializeNode create() {
return MaterializeNodeGen.create();
private void materializeAttributes(VirtualFrame frame, 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());
if (materializedAttr != attr.getValue()) {
if (setAttributeNode == null) {
CompilerDirectives.transferToInterpreterAndInvalidate();
setAttributeNode = insert(SetAttributeNode.create());
}
setAttributeNode.execute(materialized, attr.getName(), materializedAttr);
}
}
}
}
public static MaterializeNode create(boolean deep) {
return MaterializeNodeGen.create(deep);
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment