Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(394)

Side by Side Diff: compiler/java/com/google/dart/compiler/resolver/ElementMap.java

Issue 9373059: Multimap replacement (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file.
4
5 package com.google.dart.compiler.resolver;
6
7 import com.google.dart.compiler.ast.DartLabel;
8 import com.google.dart.compiler.ast.DartNode;
9 import com.google.dart.compiler.ast.Modifiers;
10 import com.google.dart.compiler.type.Type;
11
12 import java.util.ArrayList;
13 import java.util.List;
14
15 /**
16 * A more efficient version of {@link com.google.common.collect.Multimap} specif ically for
17 * {@link Element}
18 */
19 class ElementMap {
20
21 /**
22 * A synthetic place holder for an element where the name given to the element map does not match
23 * the value returned by {@link Element#getName()} or where there are multiple elements associated
24 * with the same name.
25 */
26 static class ElementHolder implements Element {
27 private static final String INTERNAL_ONLY_ERROR = "ElementHolder should not be accessed outside this class";
28
29 final String name;
30 final Element element;
31 ElementHolder nextHolder;
32
33 ElementHolder(String name, Element element) {
34 this.name = name;
35 this.element = element;
36 }
37
38 @Override
39 public EnclosingElement getEnclosingElement() {
40 throw new AssertionError(INTERNAL_ONLY_ERROR);
41 }
42
43 @Override
44 public ElementKind getKind() {
45 throw new AssertionError(INTERNAL_ONLY_ERROR);
46 }
47
48 @Override
49 public Modifiers getModifiers() {
50 throw new AssertionError(INTERNAL_ONLY_ERROR);
51 }
52
53 @Override
54 public String getName() {
55 return name;
56 }
57
58 @Override
59 public DartNode getNode() {
60 throw new AssertionError(INTERNAL_ONLY_ERROR);
61 }
62
63 @Override
64 public String getOriginalSymbolName() {
65 throw new AssertionError(INTERNAL_ONLY_ERROR);
66 }
67
68 @Override
69 public Type getType() {
70 throw new AssertionError(INTERNAL_ONLY_ERROR);
71 }
72
73 @Override
74 public boolean isDynamic() {
75 throw new AssertionError(INTERNAL_ONLY_ERROR);
76 }
77
78 @Override
79 public void setNode(DartLabel node) {
80 throw new AssertionError(INTERNAL_ONLY_ERROR);
81 }
82 }
83
84 // Array indexed by hashed name ... length is always power of 2
85 private Element[] elements;
86 private List<Element> ordered = new ArrayList<Element>();
87
88 ElementMap() {
89 clear();
90 }
91
92 /**
93 * Associate the specified element with the specified name. If the element is already associated
94 * with that name, do not associate it again.
95 */
96 void add(String name, Element element) {
97
98 // Most of the time name equals getName() thus holder == element
99 Element newHolder;
100 if (name.equals(element.getName())) {
101 newHolder = element;
102 } else {
103 newHolder = new ElementHolder(name, element);
104 }
105
106 // 75% fill rate which anecdotal evidence claims is a good threshold for gro wing
107 if ((elements.length >> 2) * 3 <= size()) {
108 grow();
109 }
110 int index = internalAdd(newHolder);
111 if (index == -1) {
112 ordered.add(element);
113 return;
114 }
115
116 // Handle existing element with the same name
117 Element existingHolder = elements[index];
118 if (existingHolder == element) {
119 return;
120 }
121 if (!(existingHolder instanceof ElementHolder)) {
122 existingHolder = new ElementHolder(name, existingHolder);
123 elements[index] = existingHolder;
124 }
125
126 // Check the list for a duplicate element entry, and append if none found
127 ElementHolder holder = (ElementHolder) existingHolder;
128 while (true) {
129 if (holder.element == element) {
130 return;
131 }
132 if (holder.nextHolder == null) {
133 holder.nextHolder = new ElementHolder(name, element);
134 ordered.add(element);
135 return;
136 }
137 holder = holder.nextHolder;
138 }
139 }
140
141 void clear() {
142 elements = new Element[16];
143 ordered.clear();
144 }
145
146 /**
147 * Answer the element last associated with the specified name.
148 *
149 * @return the element or <code>null</code> if none
150 */
151 Element get(String name) {
152 Element element = internalGet(name);
153 if (element instanceof ElementHolder) {
154 return ((ElementHolder) element).element;
155 } else {
156 return element;
157 }
158 }
159
160 /**
161 * Answer the element associated with the specified name and kind
162 *
163 * @return the element of that kind or <code>null</code> if none
164 */
165 Element get(String name, ElementKind kind) {
166 Element element = internalGet(name);
167 if (element instanceof ElementHolder) {
168 ElementHolder holder = (ElementHolder) element;
169 while (true) {
170 element = holder.element;
171 if (ElementKind.of(element).equals(kind)) {
172 return element;
173 }
174 holder = holder.nextHolder;
175 if (holder == null) {
176 break;
177 }
178 }
179 } else {
180 if (ElementKind.of(element).equals(kind)) {
181 return element;
182 }
183 }
184 return null;
185 }
186
187 boolean isEmpty() {
188 return ordered.isEmpty();
189 }
190
191 int size() {
192 return ordered.size();
193 }
194
195 List<Element> values() {
196 return ordered;
197 }
198
199 private void grow() {
200 Element[] old = elements;
201 elements = new Element[elements.length << 2];
202 for (Element element : old) {
203 if (element != null) {
204 if (internalAdd(element) != -1) {
205 // Every element in the array should have a unique name, so there shou ld not be any collision
206 throw new RuntimeException("Failed to grow: " + element.getName());
207 }
208 }
209 }
210 }
211
212 /**
213 * If an element with the given name does not exist in the array, then add the element and return
214 * -1 otherwise nothing is added and the index of the existing element returne d.
215 */
216 private int internalAdd(Element element) {
217 String name = element.getName();
218 int mask = elements.length - 1;
219 int probe = name.hashCode() & mask;
220 for (int i = probe; i < probe + mask + 1; i++) {
221 int index = i & mask;
222 Element current = elements[index];
223 if (current == null) {
224 elements[index] = element;
225 return -1;
226 }
227 if (current.getName().equals(name)) {
228 return index;
229 }
230 }
231 throw new AssertionError("overfilled array");
232 }
233
234 private Element internalGet(String name) {
235 Element element;
236 int mask = elements.length - 1;
237 int probe = name.hashCode() & mask;
238 for (int i = probe; i < probe + mask + 1; i++) {
239 element = elements[i & mask];
240 if (element == null || element.getName().equals(name)) {
241 return element;
242 }
243 }
244 throw new AssertionError("overfilled array");
245 }
246 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698