From c82168eea66609bd0fc3acbc02e837f6a65c3b1b Mon Sep 17 00:00:00 2001 From: Googler Date: Wed, 22 Mar 2023 17:50:33 -0700 Subject: [PATCH] Avoid storing `LateBoundDefault` attribute values in `Rule`. The change that produces the desired effect is to compare the attribute value with `Attribute#getDefaultValueUnchecked`. The unchecked method returns `LateBoundDefault`, not its default value. This allows the optimization added in https://github.com/bazelbuild/bazel/commit/1d03d53b56f90d26818186158fd31d41f67c2508 to also work for `LateBoundDefault`. Rename `getRawAttrValue` to `getAttrIfStored` to better reflect that it does not fall back to the default value. PiperOrigin-RevId: 518720504 Change-Id: I3141a1d731aaede8ff81b46ebc819cdb6af0fa0a --- .../packages/AggregatingAttributeMapper.java | 4 +- .../devtools/build/lib/packages/Rule.java | 20 ++-- .../packages/RuleAttributeStorageTest.java | 102 ++++++++++++------ 3 files changed, 86 insertions(+), 40 deletions(-) diff --git a/src/main/java/com/google/devtools/build/lib/packages/AggregatingAttributeMapper.java b/src/main/java/com/google/devtools/build/lib/packages/AggregatingAttributeMapper.java index 96d5ab52919b62..39cf61b8c88790 100644 --- a/src/main/java/com/google/devtools/build/lib/packages/AggregatingAttributeMapper.java +++ b/src/main/java/com/google/devtools/build/lib/packages/AggregatingAttributeMapper.java @@ -115,7 +115,7 @@ private void visitLabels( if (type.getLabelClass() == LabelClass.NONE) { // The only way for LabelClass.NONE to contain labels is in select keys. if (includeSelectKeys && attr.isConfigurable()) { - rawVal = rule.getRawAttrValue(i); + rawVal = rule.getAttrIfStored(i); if (rawVal instanceof SelectorList) { visitLabelsInSelect( (SelectorList) rawVal, @@ -128,7 +128,7 @@ private void visitLabels( } return; } - rawVal = rule.getRawAttrValue(i); + rawVal = rule.getAttrIfStored(i); if (rawVal == null) { // Frozen rules don't store computed defaults. if (!attr.hasComputedDefault() || rule.isFrozen()) { diff --git a/src/main/java/com/google/devtools/build/lib/packages/Rule.java b/src/main/java/com/google/devtools/build/lib/packages/Rule.java index a931906337f734..ea4a8e307f9021 100644 --- a/src/main/java/com/google/devtools/build/lib/packages/Rule.java +++ b/src/main/java/com/google/devtools/build/lib/packages/Rule.java @@ -505,7 +505,7 @@ public Object getAttr(String attrName, Type type) { */ @Nullable private Object getAttrWithIndex(int attrIndex) { - Object value = getRawAttrValue(attrIndex); + Object value = getAttrIfStored(attrIndex); if (value != null) { return value; } @@ -519,6 +519,11 @@ private Object getAttrWithIndex(int attrIndex) { // compute the value. return isFrozen() ? attr.getDefaultValue() : null; } + if (attr.isLateBound()) { + // Frozen rules don't store late bound defaults. + checkState(isFrozen(), "Mutable rule missing LateBoundDefault"); + return attr.getLateBoundDefault(); + } switch (attr.getName()) { case GENERATOR_FUNCTION: return callstack.size() > 1 ? callstack.getFrame(1).name : ""; @@ -536,7 +541,7 @@ private Object getAttrWithIndex(int attrIndex) { *

Unlike {@link #getAttr}, does not fall back to the default value. */ @Nullable - Object getRawAttrValue(int attrIndex) { + Object getAttrIfStored(int attrIndex) { checkPositionIndex(attrIndex, attrCount() - 1); switch (getAttrState()) { case MUTABLE: @@ -642,8 +647,9 @@ private void checkAttrType(String attrName, Type requestedType, Attribute att * Returns {@code true} if this rule's attributes are immutable. * *

Frozen rules optimize for space by omitting storage for non-explicit attribute values that - * match the {@link Attribute} default. If {@link #getRawAttrValue} returns {@code null}, the - * value should be taken from {@link Attribute#getDefaultValue}, even for computed defaults. + * match the {@link Attribute} default. If {@link #getAttrIfStored} returns {@code null}, the + * value should be taken from either {@link Attribute#getLateBoundDefault} for late-bound defaults + * or {@link Attribute#getDefaultValue} for all other attributes (including computed defaults). * *

Mutable rules have no such optimization. During rule creation, this allows for * distinguishing whether a computed default (which may depend on other unset attributes) is @@ -667,7 +673,7 @@ void freeze() { } if (!getExplicitBit(i)) { Attribute attr = ruleClass.getAttribute(i); - if (value.equals(attr.getDefaultValue())) { + if (value.equals(attr.getDefaultValueUnchecked())) { // Non-explicit value matches the attribute's default. Save space by omitting storage. continue; } @@ -774,7 +780,7 @@ public BuildType.SelectorList getSelectorList(String attributeName, Type< if (index == null) { return null; } - Object attrValue = getRawAttrValue(index); + Object attrValue = getAttrIfStored(index); if (!(attrValue instanceof BuildType.SelectorList)) { return null; } @@ -1108,7 +1114,7 @@ private List