diff options
author | cparsons <cparsons@google.com> | 2018-07-25 15:16:12 -0700 |
---|---|---|
committer | Copybara-Service <copybara-piper@google.com> | 2018-07-25 15:17:45 -0700 |
commit | dc6f1cbe811fbd7f24dfa355e198a6bf8d173327 (patch) | |
tree | 74351c00f17ec09a2f7de52f680f2baef9a5e947 /src/main/java/com/google/devtools/build/lib/syntax/FuncallExpression.java | |
parent | 8e6a1b93a933300f1dd5d97184424f3b3062e603 (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.java | 99 |
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. |