diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Combine.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Combine.java index aa454c0002d8a29000c90055b468fb1ee87c8f77..eac4155fc6ef9de92adcbeb290f9d4c86f671876 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Combine.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Combine.java @@ -37,6 +37,7 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; 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.dsl.Cached; import com.oracle.truffle.api.dsl.NodeChild; @@ -44,6 +45,7 @@ import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.nodes.ExplodeLoop; 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.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.builtin.base.CombineNodeGen.CombineInputCastNodeGen; import com.oracle.truffle.r.nodes.unary.CastComplexNodeGen; @@ -55,7 +57,6 @@ import com.oracle.truffle.r.nodes.unary.CastNode; import com.oracle.truffle.r.nodes.unary.CastRawNodeGen; import com.oracle.truffle.r.nodes.unary.CastStringNodeGen; import com.oracle.truffle.r.nodes.unary.CastToVectorNode; -import com.oracle.truffle.r.nodes.unary.CastToVectorNodeGen; import com.oracle.truffle.r.nodes.unary.PrecedenceNode; import com.oracle.truffle.r.nodes.unary.PrecedenceNodeGen; import com.oracle.truffle.r.runtime.ArgumentsSignature; @@ -86,10 +87,19 @@ public abstract class Combine extends RBuiltinNode { protected static final int COMBINE_CACHED_LIMIT = PrecedenceNode.NUMBER_OF_PRECEDENCES; + private static final int MAX_PROFILES = 4; + @Child private PrecedenceNode precedenceNode = PrecedenceNodeGen.create(); @Child private CombineInputCast inputCast = CombineInputCastNodeGen.create(null); @Child private CastToVectorNode castVector; + private final RAttributeProfiles attrProfiles = RAttributeProfiles.create(); + private final BranchProfile naBranch = BranchProfile.create(); + private final NACheck naCheck = NACheck.create(); + private final ConditionProfile fastNamesMerge = ConditionProfile.createBinaryProfile(); + private final ConditionProfile isAbstractVectorProfile = ConditionProfile.createBinaryProfile(); + private final ConditionProfile hasNewNamesProfile = ConditionProfile.createBinaryProfile(); + @CompilationFinal private final ValueProfile[] argProfiles = new ValueProfile[MAX_PROFILES]; public abstract Object executeCombine(Object value); @@ -107,9 +117,7 @@ public abstract class Combine extends RBuiltinNode { @Cached("args.getSignature()") ArgumentsSignature cachedSignature, // @Cached("precedence( args, cachedSignature.getLength())") int cachedPrecedence, // @Cached("createCast(cachedPrecedence)") CastNode cast, // - @Cached("create()") BranchProfile naBranch, // @Cached("create()") BranchProfile naNameBranch, // - @Cached("create()") NACheck naCheck, // @Cached("create()") NACheck naNameCheck, // @Cached("createBinaryProfile()") ConditionProfile hasNamesProfile) { CompilerAsserts.partialEvaluationConstant(cachedSignature); @@ -121,13 +129,15 @@ public abstract class Combine extends RBuiltinNode { // perform all the casts Object[] elements = new Object[cachedSignature.getLength()]; - int size = prepareElements(args.getArguments(), cachedSignature, cast, cachedPrecedence, elements); + int size = prepareElements(args.getArguments(), cast, cachedPrecedence, elements); // prepare the names (if there are any) - RStringVector namesVector = hasNamesProfile.profile(hasNames(elements)) ? foldNames(naNameBranch, naNameCheck, elements, size) : null; + boolean signatureHasNames = signatureHasNames(cachedSignature); + CompilerAsserts.partialEvaluationConstant(signatureHasNames); + RStringVector namesVector = hasNamesProfile.profile(signatureHasNames || hasNames(elements)) ? foldNames(naNameBranch, naNameCheck, elements, size, cachedSignature) : null; // get the actual contents of the result - RVector result = foldContents(cachedPrecedence, naBranch, naCheck, elements, size, namesVector); + RVector result = foldContents(cachedPrecedence, elements, size, namesVector); RNode.reportWork(this, size); @@ -139,13 +149,17 @@ public abstract class Combine extends RBuiltinNode { } @ExplodeLoop - private int prepareElements(Object[] args, ArgumentsSignature signature, CastNode cast, int precedence, Object[] elements) { - boolean signatureHasNames = signatureHasNames(signature); - CompilerAsserts.partialEvaluationConstant(signatureHasNames); - + private int prepareElements(Object[] args, CastNode cast, int precedence, Object[] elements) { int size = 0; for (int i = 0; i < elements.length; i++) { - Object element = readAndCast(cast, args, signature, i, precedence, signatureHasNames); + Object element = readAndCast(cast, args[i], precedence); + if (i < argProfiles.length) { + if (argProfiles[i] == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + argProfiles[i] = ValueProfile.createClassProfile(); + } + element = argProfiles[i].profile(element); + } elements[i] = element; size += getElementSize(element); } @@ -165,7 +179,11 @@ public abstract class Combine extends RBuiltinNode { @ExplodeLoop private boolean hasNames(Object[] elements) { - for (Object element : elements) { + for (int i = 0; i < elements.length; i++) { + Object element = elements[i]; + if (i < argProfiles.length) { + element = argProfiles[i].profile(element); + } if (element instanceof RAbstractVector) { RAbstractVector vector = (RAbstractVector) element; if (vector.getNames(attrProfiles) != null) { @@ -177,22 +195,36 @@ public abstract class Combine extends RBuiltinNode { } @ExplodeLoop - private RStringVector foldNames(BranchProfile naNameBranch, NACheck naNameCheck, Object[] elements, int size) { + private RStringVector foldNames(BranchProfile naNameBranch, NACheck naNameCheck, Object[] elements, int size, ArgumentsSignature signature) { RStringVector result = RDataFactory.createStringVector(new String[size], true); result.incRefCount(); int pos = 0; - for (Object element : elements) { - pos += processNamesElement(naNameBranch, naNameCheck, result, pos, element); + for (int i = 0; i < elements.length; i++) { + Object element = elements[i]; + if (i < argProfiles.length) { + element = argProfiles[i].profile(element); + } + pos += processNamesElement(naNameBranch, naNameCheck, result, pos, element, i, signature); } return result; } - private int processNamesElement(BranchProfile naNameBranch, NACheck naNameCheck, RStringVector result, int pos, Object element) { + private int processNamesElement(BranchProfile naNameBranch, NACheck naNameCheck, RStringVector result, int pos, Object element, int index, ArgumentsSignature signature) { + String signatureName = signature.getName(index); if (element instanceof RAbstractVector) { RAbstractVector v = (RAbstractVector) element; + int length = v.getLength(); + RStringVector newNames = v.getNames(attrProfiles); - if (newNames != null) { - for (int i1 = 0; i1 < newNames.getLength(); i1++) { + if (signatureName != null && length > 0) { + if (fastNamesMerge.profile(length == 1 && newNames == null)) { + newNames = RDataFactory.createStringVector(new String[]{signatureName}, true); + } else { + newNames = RDataFactory.createStringVector(mergeNamesSlow(length, signatureName, newNames), true); + } + } + if (hasNewNamesProfile.profile(newNames != null)) { + for (int i1 = 0; i1 < length; i1++) { result.transferElementSameType(pos + i1, newNames, i1); } if (!newNames.isComplete()) { @@ -200,7 +232,7 @@ public abstract class Combine extends RBuiltinNode { result.setComplete(false); } } else { - for (int i1 = 0; i1 < v.getLength(); i1++) { + for (int i1 = 0; i1 < length; i1++) { result.updateDataAt(pos + i1, RRuntime.NAMES_ATTR_EMPTY_VALUE, naNameCheck); } } @@ -209,23 +241,24 @@ public abstract class Combine extends RBuiltinNode { // nothing to do - NULL elements are skipped return 0; } else { - result.updateDataAt(pos, RRuntime.NAMES_ATTR_EMPTY_VALUE, naNameCheck); + String name = signatureName != null ? signatureName : RRuntime.NAMES_ATTR_EMPTY_VALUE; + result.updateDataAt(pos, name, naNameCheck); return 1; } } @ExplodeLoop - private static RVector foldContents(int cachedPrecedence, BranchProfile naBranch, NACheck naCheck, Object[] elements, int size, RStringVector namesVector) { + private RVector foldContents(int cachedPrecedence, Object[] elements, int size, RStringVector namesVector) { RVector result = createResultVector(cachedPrecedence, size, namesVector); int pos = 0; for (Object element : elements) { - pos += processContentElement(naBranch, naCheck, result, pos, element); + pos += processContentElement(result, pos, element); } return result; } - private static int processContentElement(BranchProfile naBranch, NACheck naCheck, RVector result, int pos, Object element) { - if (element instanceof RAbstractVector) { + private int processContentElement(RVector result, int pos, Object element) { + if (isAbstractVectorProfile.profile(element instanceof RAbstractVector)) { RAbstractVector v = (RAbstractVector) element; for (int i = 0; i < v.getLength(); i++) { result.transferElementSameType(pos + i, v, i); @@ -254,12 +287,10 @@ public abstract class Combine extends RBuiltinNode { protected Object combine(RArgsValuesAndNames args, // @Cached("precedence(args, args.getLength())") int cachedPrecedence, // @Cached("createCast(cachedPrecedence)") CastNode cast, // - @Cached("create()") BranchProfile naBranch, // @Cached("create()") BranchProfile naNameBranch, // - @Cached("create()") NACheck naCheck, // @Cached("create()") NACheck naNameCheck, // @Cached("createBinaryProfile()") ConditionProfile hasNamesProfile) { - return combineCached(args, args.getSignature(), cachedPrecedence, cast, naBranch, naNameBranch, naCheck, naNameCheck, hasNamesProfile); + return combineCached(args, args.getSignature(), cachedPrecedence, cast, naNameBranch, naNameCheck, hasNamesProfile); } @Specialization(guards = "!isArguments(args)") @@ -267,39 +298,11 @@ public abstract class Combine extends RBuiltinNode { return combine.executeCombine(new RArgsValuesAndNames(new Object[]{args}, EMPTY_SIGNATURE)); } - private Object readAndCast(CastNode castNode, Object[] values, ArgumentsSignature signature, int index, int precedence, boolean hasNames) { - Object value = inputCast.execute(values[index]); - if (hasNames) { - value = namesMerge(castVector(value), signature.getName(index)); - } + private Object readAndCast(CastNode castNode, Object arg, int precedence) { + Object value = inputCast.execute(arg); return (precedence == EXPRESSION_PRECEDENCE && value instanceof RLanguage) ? value : castNode.execute(value); } - private RAbstractVector namesMerge(RAbstractVector vector, String name) { - RStringVector orgNamesObject = vector.getNames(attrProfiles); - if (name == null) { - return vector; - } - if (vector.getLength() == 0) { - return vector; - } - return mergeNamesSlow(vector, name, orgNamesObject); - } - - private RAbstractVector castVector(Object value) { - if (castVector == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - castVector = insert(CastToVectorNodeGen.create(false)); - } - RVector resultVector = ((RAbstractVector) castVector.execute(value)).materialize(); - // need to copy if vector is shared in case the same variable is used in combine, e.g. : - // x <- 1:2 ; names(x) <- c("A",NA) ; c(x,test=x) - if (resultVector.isShared()) { - resultVector = resultVector.copy(); - } - return resultVector; - } - protected int precedence(RArgsValuesAndNames args) { int precedence = NO_PRECEDENCE; Object[] array = args.getArguments(); @@ -376,37 +379,30 @@ public abstract class Combine extends RBuiltinNode { } @TruffleBoundary - private static RAbstractVector mergeNamesSlow(RAbstractVector vector, String name, RStringVector orgNames) { - /* - * TODO (chumer) we should reuse some node for this to concat a RStringVector with a String. - */ - RVector v = vector.materialize(); - RStringVector newNames; + private static String[] mergeNamesSlow(int length, String name, RStringVector orgNames) { + String[] names = new String[length]; if (orgNames == null) { assert (name != null); assert (!name.equals(RRuntime.NAMES_ATTR_EMPTY_VALUE)); - if (v.getLength() == 1) { + if (length == 1) { // single value - just use the name - newNames = RDataFactory.createStringVector(new String[]{name}, true); + names[0] = name; } else { // multiple values - prepend name to the index of a given value - String[] names = new String[v.getLength()]; for (int i = 0; i < names.length; i++) { names[i] = name + (i + 1); } - newNames = RDataFactory.createStringVector(names, true); + return names; } } else { - if (vector.getLength() == 1) { - // single value - // prepend name to the original name + if (length == 1) { + // single value - prepend name to the original name assert (!name.equals(RRuntime.NAMES_ATTR_EMPTY_VALUE)); String orgName = orgNames.getDataAt(0); - newNames = RDataFactory.createStringVector(new String[]{orgName.equals(RRuntime.NAMES_ATTR_EMPTY_VALUE) ? name : name + "." + orgName}, true); + names[0] = orgName.equals(RRuntime.NAMES_ATTR_EMPTY_VALUE) ? name : name + "." + orgName; } else { // multiple values - prepend name to the index of a given value or to the original // name - String[] names = new String[v.getLength()]; for (int i = 0; i < names.length; i++) { if (name == null) { names[i] = orgNames.getDataAt(i); @@ -416,11 +412,9 @@ public abstract class Combine extends RBuiltinNode { names[i] = orgName.equals(RRuntime.NAMES_ATTR_EMPTY_VALUE) ? name + (i + 1) : name + "." + orgName; } } - newNames = RDataFactory.createStringVector(names, true); } } - v.setNames(newNames); - return v; + return names; } @NodeChild diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Repeat.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Repeat.java index ba423dae3cbafc423b481033a8fb9b51cba8348a..fc26c8e3365e813b31cdb70fa6f5e27f2844690e 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Repeat.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Repeat.java @@ -22,7 +22,9 @@ */ package com.oracle.truffle.r.nodes.builtin.base; -import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.*; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.abstractVectorValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.size; import static com.oracle.truffle.r.runtime.RDispatch.INTERNAL_GENERIC; import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; @@ -30,9 +32,12 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; import java.util.Arrays; import java.util.function.Function; +import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.profiles.BranchProfile; import com.oracle.truffle.api.profiles.ConditionProfile; +import com.oracle.truffle.r.nodes.attributes.InitAttributesNode; +import com.oracle.truffle.r.nodes.attributes.PutAttributeNode; import com.oracle.truffle.r.nodes.builtin.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.runtime.RError; @@ -142,39 +147,44 @@ public abstract class Repeat extends RBuiltinNode { } @Specialization(guards = {"each > 1", "hasNames(x)"}) - protected RAbstractVector repEachNames(RAbstractVector x, RAbstractIntVector times, int lengthOut, int each) { + protected RAbstractVector repEachNames(RAbstractVector x, RAbstractIntVector times, int lengthOut, int each, + @Cached("create()") InitAttributesNode initAttributes, + @Cached("createNames()") PutAttributeNode putNames) { if (times.getLength() > 1) { errorBranch.enter(); throw invalidTimes(); } RAbstractVector input = handleEach(x, each); RStringVector names = (RStringVector) handleEach(x.getNames(attrProfiles), each); + RVector r; if (lengthOutOrTimes.profile(!RRuntime.isNA(lengthOut))) { names = (RStringVector) handleLengthOut(names, lengthOut, false); - RVector r = handleLengthOut(input, lengthOut, false); - r.setNames(names); - return r; + r = handleLengthOut(input, lengthOut, false); } else { names = (RStringVector) handleTimes(names, times, false); - RVector r = handleTimes(input, times, false); - r.setNames(names); - return r; + r = handleTimes(input, times, false); } + putNames.execute(initAttributes.execute(r), names); + r.setInternalNames(names); + return r; } @Specialization(guards = {"each <= 1", "hasNames(x)"}) - protected RAbstractVector repNoEachNames(RAbstractVector x, RAbstractIntVector times, int lengthOut, @SuppressWarnings("unused") int each) { + protected RAbstractVector repNoEachNames(RAbstractVector x, RAbstractIntVector times, int lengthOut, @SuppressWarnings("unused") int each, + @Cached("create()") InitAttributesNode initAttributes, + @Cached("createNames()") PutAttributeNode putNames) { + RStringVector names; + RVector r; if (lengthOutOrTimes.profile(!RRuntime.isNA(lengthOut))) { - RStringVector names = (RStringVector) handleLengthOut(x.getNames(attrProfiles), lengthOut, true); - RVector r = handleLengthOut(x, lengthOut, true); - r.setNames(names); - return r; + names = (RStringVector) handleLengthOut(x.getNames(attrProfiles), lengthOut, true); + r = handleLengthOut(x, lengthOut, true); } else { - RStringVector names = (RStringVector) handleTimes(x.getNames(attrProfiles), times, true); - RVector r = handleTimes(x, times, true); - r.setNames(names); - return r; + names = (RStringVector) handleTimes(x.getNames(attrProfiles), times, true); + r = handleTimes(x, times, true); } + putNames.execute(initAttributes.execute(r), names); + r.setInternalNames(names); + return r; } /** diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/AccessArgumentNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/AccessArgumentNode.java index 02dbbaf855144c918ced61076866063bb38648c5..15d687d6799438879e7d85a67c0a1d1ff06a3f96 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/AccessArgumentNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/AccessArgumentNode.java @@ -138,10 +138,7 @@ public final class AccessArgumentNode extends RNode { private Object doArgument(VirtualFrame frame, Object arg) { if (hasDefaultArg) { - if (isMissingProfile.profile(arg == RMissing.instance)) { - return doArgumentInternal(frame); - } - if (isEmptyProfile.profile(arg == REmpty.instance)) { + if (isMissingProfile.profile(arg == RMissing.instance) || isEmptyProfile.profile(arg == REmpty.instance)) { return doArgumentInternal(frame); } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/BaseWriteVariableNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/BaseWriteVariableNode.java index b880d98d8649d7eb23de404bc596058810cec6e5..3a16da932dbf428b19a5f0f79ca1918b07115766 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/BaseWriteVariableNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/BaseWriteVariableNode.java @@ -51,7 +51,7 @@ abstract class BaseWriteVariableNode extends WriteVariableNode { private final ConditionProfile isCurrentProfile = ConditionProfile.createBinaryProfile(); private final ConditionProfile isShareableProfile = ConditionProfile.createBinaryProfile(); private final ConditionProfile isSharedProfile = ConditionProfile.createBinaryProfile(); - private final ConditionProfile isRefCountUpdateable = ConditionProfile.createBinaryProfile(); + private final ConditionProfile isSharedPermanent = ConditionProfile.createBinaryProfile(); private final BranchProfile initialSetKindProfile = BranchProfile.create(); @@ -96,11 +96,11 @@ abstract class BaseWriteVariableNode extends WriteVariableNode { if (mode == Mode.COPY) { return rShareable.copy(); } else { - if (isRefCountUpdateable.profile(!rShareable.isSharedPermanent())) { + if (!isSharedPermanent.profile(rShareable.isSharedPermanent())) { if (isSuper) { // if non-local assignment, increment conservatively rShareable.incRefCount(); - } else if (isSharedProfile.profile(!rShareable.isShared())) { + } else if (!isSharedProfile.profile(rShareable.isShared())) { // don't increment if already shared - will not get "unshared" until // this function exits anyway rShareable.incRefCount(); diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedExtractVectorNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedExtractVectorNode.java index 6a304222baf4f22bbbf5296aebfe8f0c4d54ef28..8fc53aa127bc467060511104f8de4db53746de28 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedExtractVectorNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedExtractVectorNode.java @@ -28,7 +28,6 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.nodes.ExplodeLoop; import com.oracle.truffle.api.nodes.Node; -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.vector.CachedExtractVectorNodeFactory.SetNamesNodeGen; @@ -274,6 +273,8 @@ final class CachedExtractVectorNode extends CachedVectorNode { private final ConditionProfile dimNamesNull = ConditionProfile.createBinaryProfile(); private final ValueProfile foundDimNamesProfile = ValueProfile.createClassProfile(); private final ConditionProfile selectPositionsProfile = ConditionProfile.createBinaryProfile(); + private final ConditionProfile originalDimNamesPRofile = ConditionProfile.createBinaryProfile(); + private final ConditionProfile foundNamesProfile = ConditionProfile.createBinaryProfile(); @ExplodeLoop private void applyDimensions(RAbstractContainer originalTarget, RVector extractedTarget, int extractedTargetLength, PositionProfile[] positionProfile, Object[] positions) { @@ -311,9 +312,9 @@ final class CachedExtractVectorNode extends CachedVectorNode { if (newDimNames != null) { extractedTarget.setDimNames(RDataFactory.createList(newDimNames)); } - } else if (newDimNames != null && originalDimNames.getLength() > 0) { + } else if (newDimNames != null && originalDimNamesPRofile.profile(originalDimNames.getLength() > 0)) { RAbstractStringVector foundNames = translateDimNamesToNames(positionProfile, originalDimNames, extractedTargetLength, positions); - if (foundNames != null) { + if (foundNamesProfile.profile(foundNames != null)) { foundNames = foundDimNamesProfile.profile(foundNames); if (foundNames.getLength() > 0) { metadataApplied.enter(); @@ -323,7 +324,7 @@ final class CachedExtractVectorNode extends CachedVectorNode { } } - private final BranchProfile droppedDimensionProfile = BranchProfile.create(); + private final ConditionProfile droppedDimensionProfile = ConditionProfile.createBinaryProfile(); @ExplodeLoop private int countDimensions(PositionProfile[] boundsProfile) { @@ -331,8 +332,7 @@ final class CachedExtractVectorNode extends CachedVectorNode { int dimCount = numberOfDimensions; for (int i = 0; i < numberOfDimensions; i++) { int selectedPositionsCount = boundsProfile[i].selectedPositionsCount; - if (selectedPositionsCount == 1) { - droppedDimensionProfile.enter(); + if (droppedDimensionProfile.profile(selectedPositionsCount == 1)) { dimCount--; } } @@ -342,6 +342,8 @@ final class CachedExtractVectorNode extends CachedVectorNode { } } + private final ConditionProfile srcNamesProfile = ConditionProfile.createBinaryProfile(); + private final ValueProfile srcNamesValueProfile = ValueProfile.createClassProfile(); private final ConditionProfile newNamesProfile = ConditionProfile.createBinaryProfile(); @ExplodeLoop @@ -353,8 +355,8 @@ final class CachedExtractVectorNode extends CachedVectorNode { continue; } - Object srcNames = originalDimNames.getDataAt(currentDimIndex); - if (srcNames != RNull.instance) { + Object srcNames = srcNamesValueProfile.profile(originalDimNames.getDataAt(currentDimIndex)); + if (srcNamesProfile.profile(srcNames != RNull.instance)) { Object position = positions[currentDimIndex]; Object newNames = extractNames((RAbstractStringVector) RRuntime.asAbstractVector(srcNames), new Object[]{position}, new PositionProfile[]{profile}, currentDimIndex, diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/CopyAttributesNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/CopyAttributesNode.java index bfca64f94be16909d1fb4165563a0acb693e9a32..79c34d928574bbcfd5679d9990cc84cbb7e5746c 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/CopyAttributesNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/CopyAttributesNode.java @@ -107,19 +107,20 @@ public abstract class CopyAttributesNode extends RBaseNode { @Specialization(guards = {"leftLength == rightLength", "containsMetadata(left, attrLeftProfiles) || containsMetadata(right, attrRightProfiles)"}) protected RAbstractVector copySameLength(RAbstractVector target, RAbstractVector left, @SuppressWarnings("unused") int leftLength, RAbstractVector right, - @SuppressWarnings("unused") int rightLength, // - @Cached("create()") CopyOfRegAttributesNode copyOfRegLeft, // - @Cached("create()") CopyOfRegAttributesNode copyOfRegRight, // - @Cached("createDim()") RemoveAttributeNode removeDim, // - @Cached("createDimNames()") RemoveAttributeNode removeDimNames, // - @Cached("create()") InitAttributesNode initAttributes, // - @Cached("createNames()") PutAttributeNode putNames, // - @Cached("createDim()") PutAttributeNode putDim, // - @Cached("create()") BranchProfile leftHasDimensions, // - @Cached("create()") BranchProfile rightHasDimensions, // - @Cached("create()") BranchProfile noDimensions, // - @Cached("createBinaryProfile()") ConditionProfile hasNamesLeft, // - @Cached("createBinaryProfile()") ConditionProfile hasNamesRight, // + @SuppressWarnings("unused") int rightLength, + @Cached("create()") CopyOfRegAttributesNode copyOfRegLeft, + @Cached("create()") CopyOfRegAttributesNode copyOfRegRight, + @Cached("createBinaryProfile()") ConditionProfile hasAttributes, + @Cached("createDim()") RemoveAttributeNode removeDim, + @Cached("createDimNames()") RemoveAttributeNode removeDimNames, + @Cached("create()") InitAttributesNode initAttributes, + @Cached("createNames()") PutAttributeNode putNames, + @Cached("createDim()") PutAttributeNode putDim, + @Cached("create()") BranchProfile leftHasDimensions, + @Cached("create()") BranchProfile rightHasDimensions, + @Cached("create()") BranchProfile noDimensions, + @Cached("createBinaryProfile()") ConditionProfile hasNamesLeft, + @Cached("createBinaryProfile()") ConditionProfile hasNamesRight, @Cached("createBinaryProfile()") ConditionProfile hasDimNames) { if (LOG) { log("copyAttributes: =="); @@ -141,7 +142,7 @@ public abstract class CopyAttributesNode extends RBaseNode { if (newDimensions == null) { noDimensions.enter(); RAttributes attributes = result.getAttributes(); - if (attributes != null) { + if (hasAttributes.profile(attributes != null)) { removeDim.execute(attributes); removeDimNames.execute(attributes); result.setInternalDimNames(null); diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/CopyOfRegAttributesNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/CopyOfRegAttributesNode.java index b066be22af2ab3675b97b82ef6d48ff6029d2223..de60064a28a74110e61b45178f375df86982aeb0 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/CopyOfRegAttributesNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/CopyOfRegAttributesNode.java @@ -23,6 +23,7 @@ package com.oracle.truffle.r.nodes.attributes; import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.data.RAttributes; import com.oracle.truffle.r.runtime.data.RAttributes.RAttribute; @@ -37,6 +38,8 @@ import com.oracle.truffle.r.runtime.nodes.RBaseNode; */ public abstract class CopyOfRegAttributesNode extends RBaseNode { + private final ConditionProfile sizeOneProfile = ConditionProfile.createBinaryProfile(); + public abstract void execute(RAbstractVector source, RVector target); public static CopyOfRegAttributesNode create() { @@ -60,9 +63,9 @@ public abstract class CopyOfRegAttributesNode extends RBaseNode { // nothing to do } - protected static final boolean onlyDimAttribute(RAbstractVector source) { + protected final boolean onlyDimAttribute(RAbstractVector source) { RAttributes attributes = source.getAttributes(); - return attributes != null && attributes.size() == 1 && attributes.getNameAtIndex(0) == RRuntime.DIM_ATTR_KEY; + return attributes != null && sizeOneProfile.profile(attributes.size() == 1) && attributes.getNameAtIndex(0) == RRuntime.DIM_ATTR_KEY; } @SuppressWarnings("unused") @@ -71,9 +74,9 @@ public abstract class CopyOfRegAttributesNode extends RBaseNode { // nothing to do } - protected static final boolean onlyNamesAttribute(RAbstractVector source) { + protected final boolean onlyNamesAttribute(RAbstractVector source) { RAttributes attributes = source.getAttributes(); - return attributes != null && attributes.size() == 1 && attributes.getNameAtIndex(0) == RRuntime.NAMES_ATTR_KEY; + return attributes != null && sizeOneProfile.profile(attributes.size() == 1) && attributes.getNameAtIndex(0) == RRuntime.NAMES_ATTR_KEY; } @SuppressWarnings("unused") @@ -82,9 +85,9 @@ public abstract class CopyOfRegAttributesNode extends RBaseNode { // nothing to do } - protected static final boolean onlyClassAttribute(RAbstractVector source) { + protected final boolean onlyClassAttribute(RAbstractVector source) { RAttributes attributes = source.getAttributes(); - return attributes != null && attributes.size() == 1 && attributes.getNameAtIndex(0) == RRuntime.CLASS_ATTR_KEY; + return attributes != null && sizeOneProfile.profile(attributes.size() == 1) && attributes.getNameAtIndex(0) == RRuntime.CLASS_ATTR_KEY; } @Specialization(guards = "onlyClassAttribute(source)") 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 ee4d814f981084f26fe209474fdbb1a721e4da9b..f85dd66cf16c803f762481530663d5a3d08f5703 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 @@ -839,7 +839,7 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS FormalArguments formals = root.getFormalArguments(); if (root instanceof RBuiltinRootNode) { RBuiltinRootNode builtinRoot = (RBuiltinRootNode) root; - return new BuiltinCallNode(RBuiltinNode.inline(builtinRoot.getBuiltin(), null), builtinRoot.getBuiltin(), formals, originalCall); + return new BuiltinCallNode(RBuiltinNode.inline(builtinRoot.getBuiltin(), null), builtinRoot.getBuiltin(), formals, originalCall, explicitArgs); } else { return new DispatchedCallNode(cachedTarget, originalCall); } @@ -928,36 +928,54 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS private static final class BuiltinCallNode extends LeafCallNode { @Child private RBuiltinNode builtin; - @Child private PromiseCheckHelperNode promiseHelper; + @Child private PromiseCheckHelperNode varArgsPromiseHelper; + @Children private final PromiseHelperNode[] promiseHelpers; @Children private final CastNode[] casts; @Child private SetVisibilityNode visibility = SetVisibilityNode.create(); - private final BranchProfile emptyProfile = BranchProfile.create(); - private final BranchProfile varArgsProfile = BranchProfile.create(); - private final ConditionProfile wrapProfile = ConditionProfile.createBinaryProfile(); + // not using profiles to save overhead + private final boolean[] argEmptySeen; + private final boolean[] varArgSeen; + private final boolean[] nonWrapSeen; + private final boolean[] wrapSeen; + private final FormalArguments formals; private final RBuiltinDescriptor builtinDescriptor; + private boolean explicitArgs; - BuiltinCallNode(RBuiltinNode builtin, RBuiltinDescriptor builtinDescriptor, FormalArguments formalArguments, RCallNode originalCall) { + BuiltinCallNode(RBuiltinNode builtin, RBuiltinDescriptor builtinDescriptor, FormalArguments formalArguments, RCallNode originalCall, boolean explicitArgs) { super(originalCall); this.builtin = builtin; this.builtinDescriptor = builtinDescriptor; + this.explicitArgs = explicitArgs; this.casts = builtin.getCasts(); this.formals = formalArguments; + promiseHelpers = new PromiseHelperNode[formals.getLength()]; + argEmptySeen = new boolean[formals.getLength()]; + varArgSeen = new boolean[formals.getLength()]; + nonWrapSeen = new boolean[formals.getLength()]; + wrapSeen = new boolean[formals.getLength()]; } @ExplodeLoop public Object[] castArguments(VirtualFrame frame, Object[] args) { int argCount = formals.getLength(); + int varArgIndex = formals.getSignature().getVarArgIndex(); Object[] result = new Object[argCount]; for (int i = 0; i < argCount; i++) { Object arg = args[i]; - if (arg == REmpty.instance) { - emptyProfile.enter(); + if (explicitArgs && arg == REmpty.instance) { + if (!argEmptySeen[i]) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + argEmptySeen[i] = true; + } arg = formals.getInternalDefaultArgumentAt(i); } - if (arg instanceof RArgsValuesAndNames) { - varArgsProfile.enter(); + if (varArgIndex == i && arg instanceof RArgsValuesAndNames) { + if (!varArgSeen[i]) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + varArgSeen[i] = true; + } RArgsValuesAndNames varArgs = (RArgsValuesAndNames) arg; if (builtinDescriptor.evaluatesArg(i)) { forcePromises(frame, varArgs); @@ -967,12 +985,11 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS } else { if (builtinDescriptor.evaluatesArg(i)) { if (arg instanceof RPromise) { - if (promiseHelper == null) { + if (promiseHelpers[i] == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); - promiseHelper = insert(new PromiseCheckHelperNode()); + promiseHelpers[i] = insert(new PromiseHelperNode()); } - arg = promiseHelper.checkEvaluate(frame, arg); - + arg = promiseHelpers[i].evaluate(frame, (RPromise) arg); } if (i < casts.length && casts[i] != null) { assert builtinDescriptor.evaluatesArg(i); @@ -980,7 +997,16 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS } } else { assert casts.length <= i || casts[i] == null : "no casts allowed on non-evaluated arguments"; - if (wrapProfile.profile(!(arg instanceof RPromise || arg instanceof RMissing))) { + if (arg instanceof RPromise || arg instanceof RMissing) { + if (!nonWrapSeen[i]) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + nonWrapSeen[i] = true; + } + } else { + if (!wrapSeen[i]) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + wrapSeen[i] = true; + } arg = createPromise(arg); } } @@ -993,11 +1019,11 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS private void forcePromises(VirtualFrame frame, RArgsValuesAndNames varArgs) { Object[] array = varArgs.getArguments(); for (int i = 0; i < array.length; i++) { - if (promiseHelper == null) { + if (varArgsPromiseHelper == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); - promiseHelper = insert(new PromiseCheckHelperNode()); + varArgsPromiseHelper = insert(new PromiseCheckHelperNode()); } - array[i] = promiseHelper.checkEvaluate(frame, array[i]); + array[i] = varArgsPromiseHelper.checkEvaluate(frame, array[i]); } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/primitive/BinaryMapNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/primitive/BinaryMapNode.java index 9cb4f0d2939053290bf23227eea5ed16281774fb..90437a0a43800871bbf1f9b5a22fe67c73bbe10d 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/primitive/BinaryMapNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/primitive/BinaryMapNode.java @@ -22,6 +22,7 @@ */ package com.oracle.truffle.r.nodes.primitive; +import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.profiles.BranchProfile; @@ -73,7 +74,7 @@ public final class BinaryMapNode extends RBaseNode { private final ConditionProfile maxLengthProfile; private final ConditionProfile leftIsNAProfile = ConditionProfile.createBinaryProfile(); private final ConditionProfile rightIsNAProfile = ConditionProfile.createBinaryProfile(); - private final BranchProfile seenEmpty = BranchProfile.create(); + private final ConditionProfile seenEmpty = ConditionProfile.createBinaryProfile(); private final ConditionProfile shareLeft; private final ConditionProfile shareRight; private final RType argumentType; @@ -229,16 +230,16 @@ public final class BinaryMapNode extends RBaseNode { private Object applyVectorized(RAbstractVector left, RAbstractVector leftCast, int leftLength, RAbstractVector right, RAbstractVector rightCast, int rightLength) { if (mayContainMetadata && (dimensionsProfile.profile(left.hasDimensions() && right.hasDimensions()))) { if (differentDimensions(left, right)) { + CompilerDirectives.transferToInterpreter(); throw RError.error(this, RError.Message.NON_CONFORMABLE_ARRAYS); } } - if (leftLength == 0 || rightLength == 0) { + if (seenEmpty.profile(leftLength == 0 || rightLength == 0)) { /* * It is safe to skip attribute handling here as they are never copied if length is 0 of * either side. Note that dimension check still needs to be performed. */ - seenEmpty.enter(); return resultType.getEmpty(); } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ArgumentsSignature.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ArgumentsSignature.java index 9132ef16228f3fa65e5b00ad550e40a32032a94e..7c3def09aa07d436b25b8cdbfdc7a4c5f13bff1a 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ArgumentsSignature.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ArgumentsSignature.java @@ -46,8 +46,6 @@ public final class ArgumentsSignature implements Iterable<String> { public static final String VARARG_NAME = "..."; public static final int NO_VARARG = -1; - private static final String VARARG_GETTER_PREFIX = ".."; - @CompilationFinal private static final ArgumentsSignature[] EMPTY_SIGNATURES = new ArgumentsSignature[32]; public static final ArgumentsSignature INVALID_SIGNATURE = new ArgumentsSignature(new String[]{"<<invalid>>"}); @@ -78,7 +76,7 @@ public final class ArgumentsSignature implements Iterable<String> { @CompilationFinal private final String[] names; @CompilationFinal private final int[] varArgIndexes; @CompilationFinal private final boolean[] isVarArg; - @CompilationFinal private final boolean[] isVarArgGetter; + private final int varArgIndex; private final int nonNullCount; private ArgumentsSignature(String[] names) { @@ -88,7 +86,6 @@ public final class ArgumentsSignature implements Iterable<String> { int index = NO_VARARG; int count = 0; this.isVarArg = new boolean[names.length]; - this.isVarArgGetter = new boolean[names.length]; for (int i = 0; i < names.length; i++) { String name = names[i]; if (name != null) { @@ -98,8 +95,6 @@ public final class ArgumentsSignature implements Iterable<String> { if (index != NO_VARARG) { index = i; } - } else if (name.startsWith(VARARG_GETTER_PREFIX)) { - this.isVarArgGetter[i] = true; } } } @@ -110,6 +105,7 @@ public final class ArgumentsSignature implements Iterable<String> { varArgIndexes[pos++] = i; } } + this.varArgIndex = varArgIndexes.length == 0 ? NO_VARARG : varArgIndexes[0]; } public boolean isEmpty() { @@ -126,7 +122,7 @@ public final class ArgumentsSignature implements Iterable<String> { public int getVarArgIndex() { assert varArgIndexes.length <= 1 : "cannot ask for _the_ vararg index if there are multiple varargs"; - return varArgIndexes.length == 0 ? NO_VARARG : varArgIndexes[0]; + return varArgIndex; } public int getVarArgCount() { @@ -207,7 +203,7 @@ public final class ArgumentsSignature implements Iterable<String> { * methods {@link #isVarArgsIndex(long)}, {@link #extractVarArgsArgumentIndex(long)} and * {@link #extractVarArgsArgumentIndex(long)} to access the data packed in the {@code long} * value. This method also removes arguments that are marked as 'unmatched' in the signature. - * + * * @param argListSize length of the result -- sum of lengths of all varargs contained within * varArgSignatures minus any unmatched arguments. */