Skip to content
Snippets Groups Projects
Commit 9b07655b authored by Lukas Stadler's avatar Lukas Stadler
Browse files

better profiling and specialization in list builtin

parent 6d1a2075
Branches
No related tags found
No related merge requests found
......@@ -22,128 +22,121 @@
*/
package com.oracle.truffle.r.nodes.builtin.base;
import static com.oracle.truffle.r.runtime.RBuiltinKind.*;
import com.oracle.truffle.api.dsl.*;
import com.oracle.truffle.api.utilities.*;
import com.oracle.truffle.r.nodes.builtin.*;
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 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.dsl.Cached;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.nodes.ExplodeLoop;
import com.oracle.truffle.api.utilities.BranchProfile;
import com.oracle.truffle.api.utilities.ConditionProfile;
import com.oracle.truffle.api.utilities.ValueProfile;
import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
import com.oracle.truffle.r.runtime.ArgumentsSignature;
import com.oracle.truffle.r.runtime.FastROptions;
import com.oracle.truffle.r.runtime.RBuiltin;
import com.oracle.truffle.r.runtime.RRuntime;
import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
import com.oracle.truffle.r.runtime.data.RDataFactory;
import com.oracle.truffle.r.runtime.data.RList;
import com.oracle.truffle.r.runtime.data.RMissing;
import com.oracle.truffle.r.runtime.data.RShareable;
import com.oracle.truffle.r.runtime.data.RStringVector;
@RBuiltin(name = "list", kind = PRIMITIVE, parameterNames = {"..."})
// TODO Is it really worth having all the individual specializations given that we have to have one
// for *every* type
// and the code is essentially equivalent for each one?
public abstract class ListBuiltin extends RBuiltinNode {
protected static final int CACHE_LIMIT = 2;
protected static final int MAX_PROFILES = 4;
@CompilationFinal private final ValueProfile[] valueProfiles = new ValueProfile[MAX_PROFILES];
private final ConditionProfile namesNull = ConditionProfile.createBinaryProfile();
private final BranchProfile shareable = BranchProfile.create();
private final BranchProfile temporary = BranchProfile.create();
private RList listArgs(ArgumentsSignature suppliedSignature, Object[] args) {
controlVisibility();
for (int i = 0; i < args.length; i++) {
Object value = args[i];
if (value instanceof RShareable) {
shareable.enter();
if (FastROptions.NewStateTransition.getBooleanValue()) {
if (((RShareable) value).isTemporary()) {
temporary.enter();
((RShareable) value).incRefCount();
}
} else {
((RShareable) value).makeShared();
@CompilationFinal private RStringVector suppliedSignatureArgNames;
protected RStringVector argNameVector(ArgumentsSignature signature) {
if (namesNull.profile(signature.getNonNullCount() == 0)) {
return null;
}
String[] names = new String[signature.getLength()];
for (int i = 0; i < names.length; i++) {
String orgName = signature.getName(i);
names[i] = (orgName == null ? RRuntime.NAMES_ATTR_EMPTY_VALUE : orgName);
}
return RDataFactory.createStringVector(names, RDataFactory.COMPLETE_VECTOR);
}
private void shareListElement(Object value) {
if (value instanceof RShareable) {
shareable.enter();
if (FastROptions.NewStateTransition.getBooleanValue()) {
if (((RShareable) value).isTemporary()) {
temporary.enter();
((RShareable) value).incRefCount();
}
} else {
((RShareable) value).makeShared();
}
}
return RDataFactory.createList(args, argNameVector(suppliedSignature));
}
private RList listArgs(Object... args) {
return listArgs(getSuppliedSignature(), args);
/**
* This specialization unrolls the loop that shares the list elements, uses value profiles for
* each element, and keeps a cached version of the name vector.
*/
@Specialization(limit = "CACHE_LIMIT", guards = {"!args.isEmpty()", //
"args.getLength() <= MAX_PROFILES", //
"cachedLength == args.getLength()", //
"cachedSignature == args.getSignature()"})
@ExplodeLoop
protected RList listCached(RArgsValuesAndNames args, //
@Cached("args.getLength()") int cachedLength, //
@SuppressWarnings("unused") @Cached("args.getSignature()") ArgumentsSignature cachedSignature, //
@Cached("argNameVector(cachedSignature)") RStringVector cachedArgNames) {
Object[] argArray = args.getArguments();
controlVisibility();
for (int i = 0; i < cachedLength; i++) {
if (valueProfiles[i] == null) {
CompilerDirectives.transferToInterpreterAndInvalidate();
valueProfiles[i] = ValueProfile.createClassProfile();
}
shareListElement(valueProfiles[i].profile(argArray[i]));
}
return RDataFactory.createList(argArray, cachedArgNames);
}
@Specialization(guards = "!missing(args)")
@Specialization(guards = "!args.isEmpty()")
protected RList list(RArgsValuesAndNames args) {
return listArgs(args.getSignature(), args.getArguments());
}
@Specialization
protected RList list(@SuppressWarnings("unused") RMissing missing) {
Object[] argArray = args.getArguments();
controlVisibility();
return RDataFactory.createList(new Object[]{});
}
@Specialization
protected RList list(byte value) {
return listArgs(value);
}
@Specialization
protected RList list(int value) {
return listArgs(value);
}
@Specialization
protected RList list(double value) {
return listArgs(value);
}
@Specialization
protected RList list(RRaw value) {
return listArgs(value);
}
@Specialization
protected RList list(RComplex value) {
return listArgs(value);
}
@Specialization
protected RList list(String value) {
return listArgs(value);
}
@Specialization
protected RList list(RAbstractVector value) {
return listArgs(value);
for (int i = 0; i < argArray.length; i++) {
shareListElement(argArray[i]);
}
return RDataFactory.createList(argArray, argNameVector(args.getSignature()));
}
@Specialization(guards = "missing(args)")
@Specialization(guards = "args.isEmpty()")
protected RList listMissing(@SuppressWarnings("unused") RArgsValuesAndNames args) {
return list(RMissing.instance);
return listMissing(RMissing.instance);
}
@Specialization
protected RList list(RNull value) {
return listArgs(value);
}
@Specialization
protected RList list(REnvironment value) {
return listArgs(value);
}
@Specialization
protected RList list(RFunction value) {
return listArgs(value);
protected RList listMissing(@SuppressWarnings("unused") RMissing missing) {
controlVisibility();
return RDataFactory.createList(new Object[]{});
}
private RStringVector argNameVector(ArgumentsSignature signature) {
if (namesNull.profile(signature.getNonNullCount() == 0)) {
return null;
}
String[] names = new String[signature.getLength()];
for (int i = 0; i < names.length; i++) {
String orgName = signature.getName(i);
names[i] = (orgName == null ? RRuntime.NAMES_ATTR_EMPTY_VALUE : orgName);
@Specialization(guards = {"!isRArgsValuesAndNames(value)", "!isRMissing(value)"})
protected RList listSingleElement(Object value) {
controlVisibility();
shareListElement(value);
if (suppliedSignatureArgNames == null) {
CompilerDirectives.transferToInterpreterAndInvalidate();
suppliedSignatureArgNames = argNameVector(getSuppliedSignature());
}
return RDataFactory.createStringVector(names, RDataFactory.COMPLETE_VECTOR);
}
protected boolean missing(RArgsValuesAndNames args) {
return args.isEmpty();
return RDataFactory.createList(new Object[]{value}, suppliedSignatureArgNames);
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment