aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build/lib/syntax/FuncallExpression.java
diff options
context:
space:
mode:
authorGravatar cparsons <cparsons@google.com>2018-07-25 15:16:12 -0700
committerGravatar Copybara-Service <copybara-piper@google.com>2018-07-25 15:17:45 -0700
commitdc6f1cbe811fbd7f24dfa355e198a6bf8d173327 (patch)
tree74351c00f17ec09a2f7de52f680f2baef9a5e947 /src/main/java/com/google/devtools/build/lib/syntax/FuncallExpression.java
parent8e6a1b93a933300f1dd5d97184424f3b3062e603 (diff)
Cache default parameter values for skylark methods, and compute types of Param annotations only once.
This change has been manually verified to greatly reduce analysis time (~50%) on very large builds, as it mitigates a previous regression brought on by the migration of @SkylarkSignature to @SkylarkCallable. RELNOTES: None. PiperOrigin-RevId: 206063684
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/syntax/FuncallExpression.java')
-rw-r--r--src/main/java/com/google/devtools/build/lib/syntax/FuncallExpression.java99
1 files changed, 71 insertions, 28 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/FuncallExpression.java b/src/main/java/com/google/devtools/build/lib/syntax/FuncallExpression.java
index 53b892dc37..fefcf70355 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/FuncallExpression.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/FuncallExpression.java
@@ -58,18 +58,77 @@ import javax.annotation.Nullable;
public final class FuncallExpression extends Expression {
/**
- * A value class to store Methods with their corresponding SkylarkCallable annotations.
- * This is needed because the annotation is sometimes in a superclass.
+ * A tuple of Param annotation to the skylark type it represents. While the type can be
+ * inferred completely by the Param annotation, this tuple allows for the type of a given
+ * parameter to be determined only once, as it is an expensive operation.
+ */
+ private static final class ParamInfo {
+ private final Param param;
+ private final SkylarkType type;
+
+ public ParamInfo(Param param) {
+ this.param = param;
+ this.type = getSkylarkType(param);
+ }
+
+ private static SkylarkType getSkylarkType(Param param) {
+ SkylarkType result = SkylarkType.BOTTOM;
+ if (param.allowedTypes().length > 0) {
+ Preconditions.checkState(Object.class.equals(param.type()));
+ for (ParamType paramType : param.allowedTypes()) {
+ SkylarkType t =
+ paramType.generic1() != Object.class
+ ? SkylarkType.of(paramType.type(), paramType.generic1())
+ : SkylarkType.of(paramType.type());
+ result = SkylarkType.Union.of(result, t);
+ }
+ } else {
+ result =
+ param.generic1() != Object.class
+ ? SkylarkType.of(param.type(), param.generic1())
+ : SkylarkType.of(param.type());
+ }
+
+ if (param.noneable()) {
+ result = SkylarkType.Union.of(result, SkylarkType.NONE);
+ }
+ return result;
+ }
+
+ public Param getParam() {
+ return param;
+ }
+
+ public SkylarkType getType() {
+ return type;
+ }
+ }
+
+ /**
+ * A value class to store Methods with their corresponding SkylarkCallable annotations and some
+ * information about the method.
*/
public static final class MethodDescriptor {
+
private final Method method;
+ private final ParamInfo[] methodParams;
private final SkylarkCallable annotation;
private MethodDescriptor(Method method, SkylarkCallable annotation) {
this.method = method;
+ this.methodParams = methodParams(annotation);
this.annotation = annotation;
}
+ private static ParamInfo[] methodParams(SkylarkCallable annotation) {
+ Param[] annotationParameters = annotation.parameters();
+ ParamInfo[] paramInfoArr = new ParamInfo[annotationParameters.length];
+ for (int i = 0; i < paramInfoArr.length; i++) {
+ paramInfoArr[i] = new ParamInfo(annotationParameters[i]);
+ }
+ return paramInfoArr;
+ }
+
Method getMethod() {
return method;
}
@@ -80,6 +139,13 @@ public final class FuncallExpression extends Expression {
public SkylarkCallable getAnnotation() {
return annotation;
}
+
+ /**
+ * Returns an array of objects describing the parameters of this method.
+ */
+ public ParamInfo[] getMethodParams() {
+ return methodParams;
+ }
}
private static final LoadingCache<Class<?>, Optional<MethodDescriptor>> selfCallCache =
@@ -541,30 +607,6 @@ public final class FuncallExpression extends Expression {
return matchingMethod;
}
- private static SkylarkType getType(Param param) {
- SkylarkType result = SkylarkType.BOTTOM;
- if (param.allowedTypes().length > 0) {
- Preconditions.checkState(Object.class.equals(param.type()));
- for (ParamType paramType : param.allowedTypes()) {
- SkylarkType t =
- paramType.generic1() != Object.class
- ? SkylarkType.of(paramType.type(), paramType.generic1())
- : SkylarkType.of(paramType.type());
- result = SkylarkType.Union.of(result, t);
- }
- } else {
- result =
- param.generic1() != Object.class
- ? SkylarkType.of(param.type(), param.generic1())
- : SkylarkType.of(param.type());
- }
-
- if (param.noneable()) {
- result = SkylarkType.Union.of(result, SkylarkType.NONE);
- }
- return result;
- }
-
private static boolean isParamNamed(Param param) {
return param.named() || param.legacyNamed();
}
@@ -622,8 +664,9 @@ public final class FuncallExpression extends Expression {
// Positional parameters are always enumerated before non-positional parameters,
// And default-valued positional parameters are always enumerated after other positional
// parameters. These invariants are validated by the SkylarkCallable annotation processor.
- for (Param param : callable.parameters()) {
- SkylarkType type = getType(param);
+ for (ParamInfo paramInfo : method.getMethodParams()) {
+ SkylarkType type = paramInfo.getType();
+ Param param = paramInfo.getParam();
Object value = null;
if (argIndex < args.size() && param.positional()) { // Positional args and params remain.