| Index: dart/compiler/java/com/google/dart/compiler/common/NameFactory.java
|
| diff --git a/dart/compiler/java/com/google/dart/compiler/common/NameFactory.java b/dart/compiler/java/com/google/dart/compiler/common/NameFactory.java
|
| deleted file mode 100644
|
| index 1edfe141283847e11e45ee19a759b2a1b6c95c6e..0000000000000000000000000000000000000000
|
| --- a/dart/compiler/java/com/google/dart/compiler/common/NameFactory.java
|
| +++ /dev/null
|
| @@ -1,226 +0,0 @@
|
| -// Copyright (c) 2011, the Dart 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.google.dart.compiler.common;
|
| -
|
| -import com.google.common.annotations.VisibleForTesting;
|
| -import com.google.common.collect.MapMaker;
|
| -
|
| -import java.lang.ref.ReferenceQueue;
|
| -import java.lang.ref.WeakReference;
|
| -import java.util.Arrays;
|
| -import java.util.concurrent.ConcurrentMap;
|
| -
|
| -/**
|
| - * Manages the life cycle, uniqueness, and object identity invariants of
|
| - * {@link Name}.
|
| - */
|
| -final class NameFactory {
|
| - /*
|
| - * TODO: does this actually save memory in practice? For each interned Name,
|
| - * we use:
|
| - *
|
| - * 1) The data array (n bytes).
|
| - *
|
| - * 2) The Name object (2 fields)
|
| - *
|
| - * 3) The RealKey (1 field + 4 fields from Reference).
|
| - *
|
| - * 4) ConcurrentMap.Entry (4 fields)
|
| - *
|
| - * Of course, a Map is really much heavier than we need, all we really need is
|
| - * a Set where you can retrieve an object already in the Set. A bare linear
|
| - * probe hash table of RealKey would let us get rid of the Entry object.
|
| - */
|
| -
|
| - /**
|
| - * The whole point of this class is to cheaply create a light-weight key that
|
| - * doesn't need to make its own copy of the data. This object is constructed
|
| - * with equality semantics to {@link RealKey}, for doing cheap map lookups.
|
| - */
|
| - private static final class FakeKey {
|
| - private final char[] data;
|
| - private final int hashCode;
|
| - private final int length;
|
| - private final int offset;
|
| -
|
| - public FakeKey(char[] data, int hashCode) {
|
| - this(data, 0, data.length, hashCode);
|
| - }
|
| -
|
| - public FakeKey(char[] data, int offset, int length, int hashCode) {
|
| - this.data = data;
|
| - this.offset = offset;
|
| - this.length = length;
|
| - this.hashCode = hashCode;
|
| - }
|
| -
|
| - @Override
|
| - public boolean equals(Object obj) {
|
| - /*
|
| - * NOTE: this ONLY WORKS for comparisons to RealKey. But that's all we
|
| - * need since we only store real keys in the map.
|
| - */
|
| - Name name = ((RealKey) obj).get();
|
| - if (name == null) {
|
| - return false;
|
| - }
|
| - return equalsName(name);
|
| - }
|
| -
|
| - public boolean equalsName(Name name) {
|
| - if (this.length != name.data.length) {
|
| - return false;
|
| - }
|
| - int itMine = this.offset;
|
| - int itTheirs = 0;
|
| - int endMine = this.offset + this.length;
|
| - while (itMine < endMine) {
|
| - if (this.data[itMine++] != name.data[itTheirs++]) {
|
| - return false;
|
| - }
|
| - }
|
| - return true;
|
| - }
|
| -
|
| - @Override
|
| - public int hashCode() {
|
| - return hashCode;
|
| - }
|
| -
|
| - @Override
|
| - public String toString() {
|
| - return "FakeKey(" + String.valueOf(data, offset, length) + ")";
|
| - }
|
| - }
|
| -
|
| - /**
|
| - * Adapted from {@link com.google.common.collect.Interners#newWeakInterner()}.
|
| - */
|
| - private static final class RealKey extends WeakReference<Name> {
|
| - /**
|
| - * Must store the hashCode locally so we can be removed from
|
| - * {@link NameFactory#map} after our referent is cleared.
|
| - */
|
| - private final int hashCode;
|
| -
|
| - public RealKey(Name name, ReferenceQueue<Name> queue) {
|
| - super(name, queue);
|
| - hashCode = name.hashCode();
|
| - }
|
| -
|
| - @Override
|
| - public boolean equals(Object obj) {
|
| - if (obj == this) {
|
| - return true;
|
| - }
|
| - if (obj instanceof FakeKey) {
|
| - Name referent = get();
|
| - if (referent == null) {
|
| - return false;
|
| - }
|
| - return ((FakeKey) obj).equalsName(referent);
|
| - }
|
| - if (obj instanceof RealKey) {
|
| - Name referent = get();
|
| - if (referent == null) {
|
| - return false;
|
| - }
|
| - Name otherReferent = ((RealKey) obj).get();
|
| - if (otherReferent == null) {
|
| - return false;
|
| - }
|
| - return Arrays.equals(referent.data, otherReferent.data);
|
| - }
|
| - return false;
|
| - }
|
| -
|
| - @Override
|
| - public int hashCode() {
|
| - return hashCode;
|
| - }
|
| -
|
| - @Override
|
| - public String toString() {
|
| - Name referent = get();
|
| - return "RealKey(" + referent + ")";
|
| - }
|
| - }
|
| -
|
| - private final ConcurrentMap<Object, RealKey> map = new MapMaker().makeMap();
|
| - private final ReferenceQueue<Name> queue = new ReferenceQueue<Name>();
|
| -
|
| - /**
|
| - * Return the Name corresponding to the data. An internal reference to
|
| - * <code>data</code> may be kept.
|
| - */
|
| - public Name of(char[] data) {
|
| - cleanUp();
|
| - int hashCode = Name.computeHashCode(data, 0, data.length);
|
| - FakeKey fakeKey = new FakeKey(data, hashCode);
|
| - Name result = get(fakeKey);
|
| - if (result == null) {
|
| - result = put(new Name(data, hashCode));
|
| - }
|
| - return result;
|
| - }
|
| -
|
| - /**
|
| - * Return the Name corresponding to the data. An internal copy of the data is
|
| - * made.
|
| - */
|
| - public Name of(char[] data, int offset, int length) {
|
| - cleanUp();
|
| - int hashCode = Name.computeHashCode(data, offset, length);
|
| - FakeKey fakeKey = new FakeKey(data, offset, length, hashCode);
|
| - Name result = get(fakeKey);
|
| - if (result == null) {
|
| - char[] copy = new char[length];
|
| - System.arraycopy(data, offset, copy, 0, length);
|
| - result = put(new Name(copy, hashCode));
|
| - }
|
| - return result;
|
| - }
|
| -
|
| - @VisibleForTesting
|
| - void cleanUp() {
|
| - RealKey item;
|
| - while ((item = (RealKey) queue.poll()) != null) {
|
| - map.remove(item);
|
| - }
|
| - }
|
| -
|
| - @VisibleForTesting
|
| - WeakReference<Name> getRefFor(Name name) {
|
| - return map.get(new FakeKey(name.data, name.hashCode()));
|
| - }
|
| -
|
| - @VisibleForTesting
|
| - int numEntries() {
|
| - return map.size();
|
| - }
|
| -
|
| - private Name get(FakeKey fakeKey) {
|
| - RealKey realKey = map.get(fakeKey);
|
| - if (realKey != null) {
|
| - return realKey.get();
|
| - }
|
| - return null;
|
| - }
|
| -
|
| - private Name put(Name name) {
|
| - RealKey realKey = new RealKey(name, queue);
|
| - while (true) {
|
| - RealKey sneakyRef = map.putIfAbsent(realKey, realKey);
|
| - if (sneakyRef == null) {
|
| - return name;
|
| - } else {
|
| - Name canonical = sneakyRef.get();
|
| - if (canonical != null) {
|
| - return canonical;
|
| - }
|
| - }
|
| - }
|
| - }
|
| -}
|
|
|