Precompute hash code in `AspectValueKey` and `AbstractSkyKey`.
All instances of these classes are interned.
PiperOrigin-RevId: 371412973
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/AspectValueKey.java b/src/main/java/com/google/devtools/build/lib/skyframe/AspectValueKey.java
index 63f284d..1d73b1c 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/AspectValueKey.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/AspectValueKey.java
@@ -82,40 +82,39 @@
@Nullable BuildConfiguration targetConfiguration,
Label starlarkFileLabel,
String starlarkExportName) {
- StarlarkAspectLoadingKey key =
- new StarlarkAspectLoadingKey(
- targetLabel,
- aspectConfiguration == null ? null : BuildConfigurationValue.key(aspectConfiguration),
- ConfiguredTargetKey.builder()
- .setLabel(targetLabel)
- .setConfiguration(targetConfiguration)
- .build(),
- starlarkFileLabel,
- starlarkExportName);
-
- return starlarkAspectKeyInterner.intern(key);
+ return StarlarkAspectLoadingKey.createInternal(
+ targetLabel,
+ aspectConfiguration == null ? null : BuildConfigurationValue.key(aspectConfiguration),
+ ConfiguredTargetKey.builder()
+ .setLabel(targetLabel)
+ .setConfiguration(targetConfiguration)
+ .build(),
+ starlarkFileLabel,
+ starlarkExportName);
}
// Specific subtypes of aspect keys.
- /** A base class for a key representing an aspect applied to a particular target. */
+ /** Represents an aspect applied to a particular target. */
@AutoCodec
- public static class AspectKey extends AspectValueKey {
+ public static final class AspectKey extends AspectValueKey {
+ private final ConfiguredTargetKey baseConfiguredTargetKey;
private final ImmutableList<AspectKey> baseKeys;
@Nullable private final BuildConfigurationValue.Key aspectConfigurationKey;
- private final ConfiguredTargetKey baseConfiguredTargetKey;
private final AspectDescriptor aspectDescriptor;
- private int hashCode;
+ private final int hashCode;
private AspectKey(
- @Nullable BuildConfigurationValue.Key aspectConfigurationKey,
ConfiguredTargetKey baseConfiguredTargetKey,
ImmutableList<AspectKey> baseKeys,
- AspectDescriptor aspectDescriptor) {
+ AspectDescriptor aspectDescriptor,
+ @Nullable BuildConfigurationValue.Key aspectConfigurationKey,
+ int hashCode) {
this.baseKeys = baseKeys;
this.aspectConfigurationKey = aspectConfigurationKey;
this.baseConfiguredTargetKey = baseConfiguredTargetKey;
this.aspectDescriptor = aspectDescriptor;
+ this.hashCode = hashCode;
}
@AutoCodec.VisibleForSerialization
@@ -127,7 +126,12 @@
@Nullable BuildConfigurationValue.Key aspectConfigurationKey) {
return aspectKeyInterner.intern(
new AspectKey(
- aspectConfigurationKey, baseConfiguredTargetKey, baseKeys, aspectDescriptor));
+ baseConfiguredTargetKey,
+ baseKeys,
+ aspectDescriptor,
+ aspectConfigurationKey,
+ Objects.hashCode(
+ baseConfiguredTargetKey, baseKeys, aspectDescriptor, aspectConfigurationKey)));
}
@Override
@@ -169,8 +173,8 @@
return String.format("%s of %s",
aspectDescriptor.getAspectClass().getName(), getLabel());
} else {
- return String.format("%s on top of %s",
- aspectDescriptor.getAspectClass().getName(), baseKeys.toString());
+ return String.format(
+ "%s on top of %s", aspectDescriptor.getAspectClass().getName(), baseKeys);
}
}
@@ -205,33 +209,7 @@
@Override
public int hashCode() {
- // We use the hash code caching strategy employed by java.lang.String. There are three subtle
- // things going on here:
- //
- // (1) We use a value of 0 to indicate that the hash code hasn't been computed and cached yet.
- // Yes, this means that if the hash code is really 0 then we will "recompute" it each time.
- // But this isn't a problem in practice since a hash code of 0 should be rare.
- //
- // (2) Since we have no synchronization, multiple threads can race here thinking there are the
- // first one to compute and cache the hash code.
- //
- // (3) Moreover, since 'hashCode' is non-volatile, the cached hash code value written from one
- // thread may not be visible by another.
- //
- // All three of these issues are benign from a correctness perspective; in the end we have no
- // overhead from synchronization, at the cost of potentially computing the hash code more than
- // once.
- int h = hashCode;
- if (h == 0) {
- h = computeHashCode();
- hashCode = h;
- }
- return h;
- }
-
- private int computeHashCode() {
- return Objects.hashCode(
- baseKeys, aspectConfigurationKey, baseConfiguredTargetKey, aspectDescriptor);
+ return hashCode;
}
@Override
@@ -239,13 +217,12 @@
if (this == other) {
return true;
}
-
if (!(other instanceof AspectKey)) {
return false;
}
-
AspectKey that = (AspectKey) other;
- return Objects.equal(baseKeys, that.baseKeys)
+ return hashCode == that.hashCode
+ && Objects.equal(baseKeys, that.baseKeys)
&& Objects.equal(aspectConfigurationKey, that.aspectConfigurationKey)
&& Objects.equal(baseConfiguredTargetKey, that.baseConfiguredTargetKey)
&& Objects.equal(aspectDescriptor, that.aspectDescriptor);
@@ -256,10 +233,7 @@
return "null";
}
- String baseKeysString =
- baseKeys.isEmpty()
- ? ""
- : String.format(" (over %s)", baseKeys.toString());
+ String baseKeysString = baseKeys.isEmpty() ? "" : String.format(" (over %s)", baseKeys);
return String.format(
"%s with aspect %s%s",
getLabel(), aspectDescriptor.getAspectClass().getName(), baseKeysString);
@@ -296,26 +270,51 @@
}
/** The key for a Starlark aspect. */
- public static class StarlarkAspectLoadingKey extends AspectValueKey {
-
+ @AutoCodec
+ public static final class StarlarkAspectLoadingKey extends AspectValueKey {
private final Label targetLabel;
private final BuildConfigurationValue.Key aspectConfigurationKey;
private final ConfiguredTargetKey baseConfiguredTargetKey;
private final Label starlarkFileLabel;
private final String starlarkValueName;
- private int hashCode;
+ private final int hashCode;
+
+ @AutoCodec.Instantiator
+ @AutoCodec.VisibleForSerialization
+ static StarlarkAspectLoadingKey createInternal(
+ Label targetLabel,
+ BuildConfigurationValue.Key aspectConfigurationKey,
+ ConfiguredTargetKey baseConfiguredTargetKey,
+ Label starlarkFileLabel,
+ String starlarkValueName) {
+ return starlarkAspectKeyInterner.intern(
+ new StarlarkAspectLoadingKey(
+ targetLabel,
+ aspectConfigurationKey,
+ baseConfiguredTargetKey,
+ starlarkFileLabel,
+ starlarkValueName,
+ Objects.hashCode(
+ targetLabel,
+ aspectConfigurationKey,
+ baseConfiguredTargetKey,
+ starlarkFileLabel,
+ starlarkValueName)));
+ }
private StarlarkAspectLoadingKey(
Label targetLabel,
BuildConfigurationValue.Key aspectConfigurationKey,
ConfiguredTargetKey baseConfiguredTargetKey,
Label starlarkFileLabel,
- String starlarkFunctionName) {
+ String starlarkValueName,
+ int hashCode) {
this.targetLabel = targetLabel;
this.aspectConfigurationKey = aspectConfigurationKey;
this.baseConfiguredTargetKey = baseConfiguredTargetKey;
this.starlarkFileLabel = starlarkFileLabel;
- this.starlarkValueName = starlarkFunctionName;
+ this.starlarkValueName = starlarkValueName;
+ this.hashCode = hashCode;
}
@Override
@@ -361,37 +360,7 @@
@Override
public int hashCode() {
- // We use the hash code caching strategy employed by java.lang.String. There are three subtle
- // things going on here:
- //
- // (1) We use a value of 0 to indicate that the hash code hasn't been computed and cached yet.
- // Yes, this means that if the hash code is really 0 then we will "recompute" it each time.
- // But this isn't a problem in practice since a hash code of 0 should be rare.
- //
- // (2) Since we have no synchronization, multiple threads can race here thinking there are the
- // first one to compute and cache the hash code.
- //
- // (3) Moreover, since 'hashCode' is non-volatile, the cached hash code value written from one
- // thread may not be visible by another.
- //
- // All three of these issues are benign from a correctness perspective; in the end we have no
- // overhead from synchronization, at the cost of potentially computing the hash code more than
- // once.
- int h = hashCode;
- if (h == 0) {
- h = computeHashCode();
- hashCode = h;
- }
- return h;
- }
-
- private int computeHashCode() {
- return Objects.hashCode(
- targetLabel,
- aspectConfigurationKey,
- baseConfiguredTargetKey,
- starlarkFileLabel,
- starlarkValueName);
+ return hashCode;
}
@Override
@@ -399,12 +368,12 @@
if (o == this) {
return true;
}
-
if (!(o instanceof StarlarkAspectLoadingKey)) {
return false;
}
StarlarkAspectLoadingKey that = (StarlarkAspectLoadingKey) o;
- return Objects.equal(targetLabel, that.targetLabel)
+ return hashCode == that.hashCode
+ && Objects.equal(targetLabel, that.targetLabel)
&& Objects.equal(aspectConfigurationKey, that.aspectConfigurationKey)
&& Objects.equal(baseConfiguredTargetKey, that.baseConfiguredTargetKey)
&& Objects.equal(starlarkFileLabel, that.starlarkFileLabel)