diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/fastpaths/IntersectFastPath.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/fastpaths/IntersectFastPath.java index e0f1161c1d5415edda8156fef193ab9269f7bafa..611cf68d898d0ed50f0630d15a1059eee1cf0174 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/fastpaths/IntersectFastPath.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/fastpaths/IntersectFastPath.java @@ -36,35 +36,43 @@ import com.oracle.truffle.r.runtime.nodes.RNode; public abstract class IntersectFastPath extends RFastPathNode { + protected static final int TYPE_LIMIT = 2; + private static final int[] EMPTY_INT_ARRAY = new int[0]; - @Specialization(guards = {"x.getLength() > 0", "y.getLength() > 0"}) - protected RAbstractIntVector intersect(RAbstractIntVector x, RAbstractIntVector y, // - @Cached("createBinaryProfile()") ConditionProfile isXSortedProfile, // - @Cached("createBinaryProfile()") ConditionProfile isYSortedProfile, // + @Specialization(limit = "TYPE_LIMIT", guards = {"x.getLength() > 0", "y.getLength() > 0", "x.getClass() == xClass", "y.getClass() == yClass"}) + protected RAbstractIntVector intersect(RAbstractIntVector x, RAbstractIntVector y, + @Cached("x.getClass()") Class<? extends RAbstractIntVector> xClass, + @Cached("y.getClass()") Class<? extends RAbstractIntVector> yClass, + @Cached("createBinaryProfile()") ConditionProfile isXSortedProfile, + @Cached("createBinaryProfile()") ConditionProfile isYSortedProfile, @Cached("createBinaryProfile()") ConditionProfile resultLengthMatchProfile) { - int xLength = x.getLength(); - int yLength = y.getLength(); + // apply the type profiles: + RAbstractIntVector profiledX = xClass.cast(x); + RAbstractIntVector profiledY = yClass.cast(y); + + int xLength = profiledX.getLength(); + int yLength = profiledY.getLength(); RNode.reportWork(this, xLength + yLength); int count = 0; int[] result = EMPTY_INT_ARRAY; int maxResultLength = Math.min(xLength, yLength); - if (isXSortedProfile.profile(isSorted(x))) { + if (isXSortedProfile.profile(isSorted(profiledX))) { RAbstractIntVector tempY; - if (!isYSortedProfile.profile(isSorted(y))) { + if (isYSortedProfile.profile(isSorted(profiledY))) { + tempY = profiledY; + } else { int[] temp = new int[yLength]; for (int i = 0; i < yLength; i++) { - temp[i] = y.getDataAt(i); + temp[i] = profiledY.getDataAt(i); } sort(temp); - tempY = RDataFactory.createIntVector(temp, y.isComplete()); - } else { - tempY = y; + tempY = RDataFactory.createIntVector(temp, profiledY.isComplete()); } int xPos = 0; int yPos = 0; - int xValue = x.getDataAt(xPos); + int xValue = profiledX.getDataAt(xPos); int yValue = tempY.getDataAt(yPos); while (true) { if (xValue == yValue) { @@ -77,7 +85,7 @@ public abstract class IntersectFastPath extends RFastPathNode { if (xPos >= xLength - 1) { break; } - int nextValue = x.getDataAt(xPos + 1); + int nextValue = profiledX.getDataAt(xPos + 1); if (xValue != nextValue) { break; } @@ -87,13 +95,13 @@ public abstract class IntersectFastPath extends RFastPathNode { if (++xPos >= xLength || ++yPos >= yLength) { break; } - xValue = x.getDataAt(xPos); + xValue = profiledX.getDataAt(xPos); yValue = tempY.getDataAt(yPos); } else if (xValue < yValue) { if (++xPos >= xLength) { break; } - xValue = x.getDataAt(xPos); + xValue = profiledX.getDataAt(xPos); } else { if (++yPos >= yLength) { break; @@ -105,12 +113,12 @@ public abstract class IntersectFastPath extends RFastPathNode { int[] temp = new int[yLength]; boolean[] used = new boolean[yLength]; for (int i = 0; i < yLength; i++) { - temp[i] = y.getDataAt(i); + temp[i] = profiledY.getDataAt(i); } sort(temp); for (int i = 0; i < xLength; i++) { - int value = x.getDataAt(i); + int value = profiledX.getDataAt(i); int pos = Arrays.binarySearch(temp, value); if (pos >= 0 && !used[pos]) { used[pos] = true; @@ -121,7 +129,7 @@ public abstract class IntersectFastPath extends RFastPathNode { } } } - return RDataFactory.createIntVector(resultLengthMatchProfile.profile(count == result.length) ? result : Arrays.copyOf(result, count), x.isComplete() | y.isComplete()); + return RDataFactory.createIntVector(resultLengthMatchProfile.profile(count == result.length) ? result : Arrays.copyOf(result, count), profiledX.isComplete() | profiledY.isComplete()); } private static boolean isSorted(RAbstractIntVector vector) { diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentStatePush.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentStatePush.java index a45022312ca4653b6c161b8c0734e45354ef3108..f600dd260b59b01622b64f07457435d412e2974c 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentStatePush.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentStatePush.java @@ -65,49 +65,51 @@ public abstract class ArgumentStatePush extends Node { public void transitionState(VirtualFrame frame, RShareable shareable) { if (isRefCountUpdateable.profile(!shareable.isSharedPermanent())) { shareable.incRefCount(); - } - if (!FastROptions.RefCountIncrementOnly.getBooleanValue()) { - if (mask == 0) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - if (shareable instanceof RAbstractContainer) { - if (shareable instanceof RLanguage || ((RAbstractContainer) shareable).getLength() < REF_COUNT_SIZE_THRESHOLD) { - // don't decrement ref count for small objects or language objects- this is - // pretty conservative and can be further finessed + if (!FastROptions.RefCountIncrementOnly.getBooleanValue()) { + if (mask == 0) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + if (shareable instanceof RAbstractContainer) { + if (shareable instanceof RLanguage || ((RAbstractContainer) shareable).getLength() < REF_COUNT_SIZE_THRESHOLD) { + // don't decrement ref count for small objects or language objects- this + // is + // pretty conservative and can be further finessed + mask = -1; + return; + } + } + RFunction fun = RArguments.getFunction(frame); + if (fun == null) { mask = -1; return; } + Object root = fun.getRootNode(); + if (!(root instanceof FunctionDefinitionNode)) { + // root is RBuiltinRootNode + mask = -1; + return; + } + FunctionDefinitionNode fdn = (FunctionDefinitionNode) root; + PostProcessArgumentsNode postProcessNode = fdn.getArgPostProcess(); + if (postProcessNode == null) { + // arguments to this function are not to be reference counted + mask = -1; + return; + } + // this is needed for when FunctionDefinitionNode is split by the Truffle + // runtime + postProcessNode = postProcessNode.getActualNode(); + if (index >= Math.min(postProcessNode.getLength(), MAX_COUNTED_ARGS)) { + mask = -1; + return; + } + mask = 1 << index; + int transArgsBitSet = postProcessNode.transArgsBitSet; + postProcessNode.transArgsBitSet = transArgsBitSet | mask; + writeArgNode = insert(WriteLocalFrameVariableNode.createForRefCount(Integer.valueOf(mask))); } - RFunction fun = RArguments.getFunction(frame); - if (fun == null) { - mask = -1; - return; - } - Object root = fun.getRootNode(); - if (!(root instanceof FunctionDefinitionNode)) { - // root is RBuiltinRootNode - mask = -1; - return; - } - FunctionDefinitionNode fdn = (FunctionDefinitionNode) root; - PostProcessArgumentsNode postProcessNode = fdn.getArgPostProcess(); - if (postProcessNode == null) { - // arguments to this function are not to be reference counted - mask = -1; - return; - } - // this is needed for when FunctionDefinitionNode is split by the Truffle runtime - postProcessNode = postProcessNode.getActualNode(); - if (index >= Math.min(postProcessNode.getLength(), MAX_COUNTED_ARGS)) { - mask = -1; - return; + if (mask != -1) { + writeArgNode.execute(frame, shareable); } - mask = 1 << index; - int transArgsBitSet = postProcessNode.transArgsBitSet; - postProcessNode.transArgsBitSet = transArgsBitSet | mask; - writeArgNode = insert(WriteLocalFrameVariableNode.createForRefCount(Integer.valueOf(mask))); - } - if (mask != -1) { - writeArgNode.execute(frame, shareable); } } } @@ -135,8 +137,7 @@ public abstract class ArgumentStatePush extends Node { // this is expected to be used in rare cases where no RNode is easily available if (o instanceof RShareable) { RShareable shareable = (RShareable) o; - // it's never decremented so no point in incrementing past shared state - if (!shareable.isShared()) { + if (!shareable.isSharedPermanent()) { shareable.incRefCount(); } } 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 b26a5aca8397d77862132affd87663c5c274bbe6..52c81b0097da24334ee814cd0ebeadc4c0875a90 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 @@ -34,7 +34,6 @@ import com.oracle.truffle.api.dsl.Cached; 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.FrameSlot; import com.oracle.truffle.api.frame.FrameSlotTypeException; import com.oracle.truffle.api.frame.MaterializedFrame; import com.oracle.truffle.api.frame.VirtualFrame; @@ -45,7 +44,6 @@ import com.oracle.truffle.api.nodes.ExplodeLoop; import com.oracle.truffle.api.nodes.Node; 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.nodes.UnexpectedResultException; import com.oracle.truffle.api.profiles.BranchProfile; @@ -312,7 +310,7 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS } protected RNode createDispatchArgument(int index) { - return new ForcePromiseNode(NodeUtil.cloneNode(arguments[index].asRNode())); + return new ForcePromiseNode(RASTUtils.cloneNode(arguments[index].asRNode())); } /** @@ -339,7 +337,7 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS @Cached("createBinaryProfile()") ConditionProfile resultIsBuiltinProfile) { RBuiltinDescriptor builtin = builtinProfile.profile(function.getRBuiltin()); Object dispatchObject = dispatchArgument.execute(frame); - FrameSlot slot = dispatchTempSlot.initialize(frame, dispatchObject, () -> internalDispatchCall = null); + dispatchTempSlot.initialize(frame, dispatchObject, () -> internalDispatchCall = null); try { RStringVector type = classHierarchyNode.execute(dispatchObject); S3Args s3Args; @@ -362,7 +360,7 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS } return internalDispatchCall.execute(frame, resultFunction, lookupVarArgs(frame), s3Args, null); } finally { - dispatchTempSlot.cleanup(frame, slot); + dispatchTempSlot.cleanup(frame, dispatchObject); } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/TemporarySlotNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/TemporarySlotNode.java index 56c0751202f6e38fef94f115bb4dcf895ce01efc..cab3f3c4da90b28fb840338a03006ebcd7bb9b31 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/TemporarySlotNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/TemporarySlotNode.java @@ -23,50 +23,53 @@ package com.oracle.truffle.r.nodes.function; import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; 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.VirtualFrame; import com.oracle.truffle.api.nodes.Node; -import com.oracle.truffle.r.nodes.access.FrameSlotNode; import com.oracle.truffle.r.runtime.RInternalError; public final class TemporarySlotNode extends Node { private static final Object[] defaultTempIdentifiers = new Object[]{new Object(), new Object(), new Object(), new Object(), new Object(), new Object(), new Object(), new Object()}; - @Child private FrameSlotNode tempSlot; + @CompilationFinal private FrameSlot tempSlot; private int tempIdentifier; private Object identifier; - public FrameSlot initialize(VirtualFrame frame, Object value, Runnable invalidate) { + public void initialize(VirtualFrame frame, Object value, Runnable invalidate) { if (tempSlot == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); - tempSlot = insert(FrameSlotNode.createInitialized(frame.getFrameDescriptor(), identifier = defaultTempIdentifiers[0], true)); + tempSlot = frame.getFrameDescriptor().findOrAddFrameSlot(identifier = defaultTempIdentifiers[0], FrameSlotKind.Object); invalidate.run(); } - FrameSlot slot = tempSlot.executeFrameSlot(frame); try { - if (frame.isObject(slot) && frame.getObject(slot) != null) { + if (frame.getObject(tempSlot) != null) { CompilerDirectives.transferToInterpreterAndInvalidate(); // keep the complete loop in the slow path do { tempIdentifier++; identifier = tempIdentifier < defaultTempIdentifiers.length ? defaultTempIdentifiers[tempIdentifier] : new Object(); - tempSlot.replace(FrameSlotNode.createInitialized(frame.getFrameDescriptor(), identifier, true)); + tempSlot = frame.getFrameDescriptor().findOrAddFrameSlot(identifier, FrameSlotKind.Object); invalidate.run(); - slot = tempSlot.executeFrameSlot(frame); - } while (frame.isObject(slot) && frame.getObject(slot) != null); + } while (frame.getObject(tempSlot) != null); } } catch (FrameSlotTypeException e) { + CompilerDirectives.transferToInterpreter(); throw RInternalError.shouldNotReachHere(); } - frame.setObject(slot, value); - return slot; + frame.setObject(tempSlot, value); } - @SuppressWarnings("static-method") - public void cleanup(VirtualFrame frame, FrameSlot slot) { - frame.setObject(slot, null); + public void cleanup(VirtualFrame frame, Object object) { + try { + assert frame.getObject(tempSlot) == object; + } catch (FrameSlotTypeException e) { + throw RInternalError.shouldNotReachHere(); + } + frame.setObject(tempSlot, null); } public Object getIdentifier() {