| // Copyright (c) 2016, the R8 project authors. Please see the AUTHORS file | 
 | // for details. All rights reserved. Use of this source code is governed by a | 
 | // BSD-style license that can be found in the LICENSE file. | 
 | package com.android.tools.r8.graph; | 
 |  | 
 | /** | 
 |  * DexItems of this kind have cached hash values and quick equals check. | 
 |  */ | 
 | public abstract class CachedHashValueDexItem extends DexItem { | 
 |  | 
 |   private static final int NOT_COMPUTED_HASH_VALUE = -1; | 
 |   private static final int SENTINEL_HASH_VALUE = 0; | 
 |   private volatile int hash = NOT_COMPUTED_HASH_VALUE; | 
 |  | 
 |   protected abstract int computeHashCode(); | 
 |  | 
 |   protected abstract boolean computeEquals(Object other); | 
 |  | 
 |   @Override | 
 |   public final int hashCode() { | 
 |     int cache = hash; | 
 |     if (cache == NOT_COMPUTED_HASH_VALUE) { | 
 |       cache = computeHashCode(); | 
 |       if (cache == NOT_COMPUTED_HASH_VALUE) { | 
 |         cache = SENTINEL_HASH_VALUE; | 
 |       } | 
 |       hash = cache; | 
 |     } | 
 |     assert verifyHashCodeConsistent(cache); | 
 |     return cache; | 
 |   } | 
 |  | 
 |   private boolean verifyHashCodeConsistent(int computedValue) { | 
 |     int newComputedValue = computeHashCode(); | 
 |     if (newComputedValue == NOT_COMPUTED_HASH_VALUE) { | 
 |       newComputedValue = SENTINEL_HASH_VALUE; | 
 |     } | 
 |     assert computedValue == newComputedValue | 
 |         : "Hash code for " + this + " has changed from " + hash + " to " + newComputedValue; | 
 |     return true; | 
 |   } | 
 |  | 
 |   @Override | 
 |   public void flushCachedValues() { | 
 |     super.flushCachedValues(); | 
 |     hash = NOT_COMPUTED_HASH_VALUE; | 
 |   } | 
 |  | 
 |   @Override | 
 |   public final boolean equals(Object other) { | 
 |     return this == other || computeEquals(other); | 
 |   } | 
 | } |