Mercurial > hg > graal-compiler
comparison graal/com.oracle.jvmci.meta/src/com/oracle/jvmci/meta/Assumptions.java @ 21556:48c1ebd24120
renamed com.oracle.graal.api[meta|code] modules to com.oracle.jvmci.[meta|code] (JBS:GRAAL-53)
author | Doug Simon <doug.simon@oracle.com> |
---|---|
date | Wed, 27 May 2015 00:36:16 +0200 |
parents | graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Assumptions.java@082417ac43e4 |
children |
comparison
equal
deleted
inserted
replaced
21555:d12eaef9af72 | 21556:48c1ebd24120 |
---|---|
1 /* | |
2 * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. | |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
4 * | |
5 * This code is free software; you can redistribute it and/or modify it | |
6 * under the terms of the GNU General Public License version 2 only, as | |
7 * published by the Free Software Foundation. | |
8 * | |
9 * This code is distributed in the hope that it will be useful, but WITHOUT | |
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 * version 2 for more details (a copy is included in the LICENSE file that | |
13 * accompanied this code). | |
14 * | |
15 * You should have received a copy of the GNU General Public License version | |
16 * 2 along with this work; if not, write to the Free Software Foundation, | |
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 * | |
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
20 * or visit www.oracle.com if you need additional information or have any | |
21 * questions. | |
22 */ | |
23 package com.oracle.jvmci.meta; | |
24 | |
25 import java.lang.invoke.*; | |
26 import java.util.*; | |
27 | |
28 /** | |
29 * Class for recording assumptions made during compilation. | |
30 */ | |
31 public final class Assumptions implements Iterable<Assumptions.Assumption> { | |
32 | |
33 /** | |
34 * Abstract base class for assumptions. An assumption assumes a property of the runtime that may | |
35 * be invalidated by subsequent execution (e.g., that a class has no subclasses implementing | |
36 * {@link NoFinalizableSubclass Object.finalize()}). | |
37 */ | |
38 public abstract static class Assumption { | |
39 } | |
40 | |
41 /** | |
42 * A class for providing information that is only valid in association with a set of | |
43 * {@link Assumption}s. | |
44 * | |
45 * @param <T> | |
46 */ | |
47 public static class AssumptionResult<T> { | |
48 Assumption[] assumptions; | |
49 final T result; | |
50 | |
51 private static final Assumption[] EMPTY = new Assumption[0]; | |
52 | |
53 public AssumptionResult(T result, Assumption... assumptions) { | |
54 this.result = result; | |
55 this.assumptions = assumptions; | |
56 } | |
57 | |
58 public AssumptionResult(T result) { | |
59 this(result, EMPTY); | |
60 } | |
61 | |
62 public T getResult() { | |
63 return result; | |
64 } | |
65 | |
66 public boolean isAssumptionFree() { | |
67 return assumptions.length == 0; | |
68 } | |
69 | |
70 public void add(AssumptionResult<T> other) { | |
71 Assumption[] newAssumptions = Arrays.copyOf(this.assumptions, this.assumptions.length + other.assumptions.length); | |
72 System.arraycopy(other.assumptions, 0, newAssumptions, this.assumptions.length, other.assumptions.length); | |
73 this.assumptions = newAssumptions; | |
74 } | |
75 } | |
76 | |
77 /** | |
78 * An assumption that a given class has no subclasses implementing {@link Object#finalize()}). | |
79 */ | |
80 public static final class NoFinalizableSubclass extends Assumption { | |
81 | |
82 private ResolvedJavaType receiverType; | |
83 | |
84 public NoFinalizableSubclass(ResolvedJavaType receiverType) { | |
85 this.receiverType = receiverType; | |
86 } | |
87 | |
88 @Override | |
89 public int hashCode() { | |
90 return 31 + receiverType.hashCode(); | |
91 } | |
92 | |
93 @Override | |
94 public boolean equals(Object obj) { | |
95 if (obj instanceof NoFinalizableSubclass) { | |
96 NoFinalizableSubclass other = (NoFinalizableSubclass) obj; | |
97 return other.receiverType.equals(receiverType); | |
98 } | |
99 return false; | |
100 } | |
101 | |
102 @Override | |
103 public String toString() { | |
104 return "NoFinalizableSubclass[receiverType=" + receiverType.toJavaName() + "]"; | |
105 } | |
106 | |
107 } | |
108 | |
109 /** | |
110 * An assumption that a given abstract or interface type has one direct concrete subtype. There | |
111 * is no requirement that the subtype is a leaf type. | |
112 */ | |
113 public static final class ConcreteSubtype extends Assumption { | |
114 | |
115 /** | |
116 * Type the assumption is made about. | |
117 */ | |
118 public final ResolvedJavaType context; | |
119 | |
120 /** | |
121 * Assumed concrete sub-type of the context type. | |
122 */ | |
123 public final ResolvedJavaType subtype; | |
124 | |
125 public ConcreteSubtype(ResolvedJavaType context, ResolvedJavaType subtype) { | |
126 this.context = context; | |
127 this.subtype = subtype; | |
128 assert context.isAbstract(); | |
129 assert subtype.isConcrete() || context.isInterface() : subtype.toString() + " : " + context.toString(); | |
130 assert !subtype.isArray() || subtype.getElementalType().isFinal() : subtype.toString() + " : " + context.toString(); | |
131 } | |
132 | |
133 @Override | |
134 public int hashCode() { | |
135 final int prime = 31; | |
136 int result = 1; | |
137 result = prime * result + context.hashCode(); | |
138 result = prime * result + subtype.hashCode(); | |
139 return result; | |
140 } | |
141 | |
142 @Override | |
143 public boolean equals(Object obj) { | |
144 if (obj instanceof ConcreteSubtype) { | |
145 ConcreteSubtype other = (ConcreteSubtype) obj; | |
146 return other.context.equals(context) && other.subtype.equals(subtype); | |
147 } | |
148 return false; | |
149 } | |
150 | |
151 @Override | |
152 public String toString() { | |
153 return "ConcreteSubtype[context=" + context.toJavaName() + ", subtype=" + subtype.toJavaName() + "]"; | |
154 } | |
155 } | |
156 | |
157 /** | |
158 * An assumption that a given type has no subtypes. | |
159 */ | |
160 public static final class LeafType extends Assumption { | |
161 | |
162 /** | |
163 * Type the assumption is made about. | |
164 */ | |
165 public final ResolvedJavaType context; | |
166 | |
167 public LeafType(ResolvedJavaType context) { | |
168 this.context = context; | |
169 } | |
170 | |
171 @Override | |
172 public int hashCode() { | |
173 final int prime = 31; | |
174 int result = 1; | |
175 result = prime * result + context.hashCode(); | |
176 return result; | |
177 } | |
178 | |
179 @Override | |
180 public boolean equals(Object obj) { | |
181 if (obj instanceof LeafType) { | |
182 LeafType other = (LeafType) obj; | |
183 return other.context.equals(context); | |
184 } | |
185 return false; | |
186 } | |
187 | |
188 @Override | |
189 public String toString() { | |
190 return "LeafSubtype[context=" + context.toJavaName() + "]"; | |
191 } | |
192 } | |
193 | |
194 /** | |
195 * An assumption that a given virtual method has a given unique implementation. | |
196 */ | |
197 public static final class ConcreteMethod extends Assumption { | |
198 | |
199 /** | |
200 * A virtual (or interface) method whose unique implementation for the receiver type in | |
201 * {@link #context} is {@link #impl}. | |
202 */ | |
203 public final ResolvedJavaMethod method; | |
204 | |
205 /** | |
206 * A receiver type. | |
207 */ | |
208 public final ResolvedJavaType context; | |
209 | |
210 /** | |
211 * The unique implementation of {@link #method} for {@link #context}. | |
212 */ | |
213 public final ResolvedJavaMethod impl; | |
214 | |
215 public ConcreteMethod(ResolvedJavaMethod method, ResolvedJavaType context, ResolvedJavaMethod impl) { | |
216 this.method = method; | |
217 this.context = context; | |
218 this.impl = impl; | |
219 } | |
220 | |
221 @Override | |
222 public int hashCode() { | |
223 final int prime = 31; | |
224 int result = 1; | |
225 result = prime * result + method.hashCode(); | |
226 result = prime * result + context.hashCode(); | |
227 result = prime * result + impl.hashCode(); | |
228 return result; | |
229 } | |
230 | |
231 @Override | |
232 public boolean equals(Object obj) { | |
233 if (obj instanceof ConcreteMethod) { | |
234 ConcreteMethod other = (ConcreteMethod) obj; | |
235 return other.method.equals(method) && other.context.equals(context) && other.impl.equals(impl); | |
236 } | |
237 return false; | |
238 } | |
239 | |
240 @Override | |
241 public String toString() { | |
242 return "ConcreteMethod[method=" + method.format("%H.%n(%p)%r") + ", context=" + context.toJavaName() + ", impl=" + impl.format("%H.%n(%p)%r") + "]"; | |
243 } | |
244 } | |
245 | |
246 /** | |
247 * An assumption that a given call site's method handle did not change. | |
248 */ | |
249 public static final class CallSiteTargetValue extends Assumption { | |
250 | |
251 public final CallSite callSite; | |
252 public final MethodHandle methodHandle; | |
253 | |
254 public CallSiteTargetValue(CallSite callSite, MethodHandle methodHandle) { | |
255 this.callSite = callSite; | |
256 this.methodHandle = methodHandle; | |
257 } | |
258 | |
259 @Override | |
260 public int hashCode() { | |
261 final int prime = 31; | |
262 int result = 1; | |
263 result = prime * result + callSite.hashCode(); | |
264 result = prime * result + methodHandle.hashCode(); | |
265 return result; | |
266 } | |
267 | |
268 @Override | |
269 public boolean equals(Object obj) { | |
270 if (obj instanceof CallSiteTargetValue) { | |
271 CallSiteTargetValue other = (CallSiteTargetValue) obj; | |
272 return callSite.equals(other.callSite) && methodHandle.equals(other.methodHandle); | |
273 } | |
274 return false; | |
275 } | |
276 | |
277 @Override | |
278 public String toString() { | |
279 return "CallSiteTargetValue[callSite=" + callSite + ", methodHandle=" + methodHandle + "]"; | |
280 } | |
281 } | |
282 | |
283 private final Set<Assumption> assumptions = new HashSet<>(); | |
284 | |
285 /** | |
286 * Returns whether any assumptions have been registered. | |
287 * | |
288 * @return {@code true} if at least one assumption has been registered, {@code false} otherwise. | |
289 */ | |
290 public boolean isEmpty() { | |
291 return assumptions.isEmpty(); | |
292 } | |
293 | |
294 @Override | |
295 public int hashCode() { | |
296 throw new UnsupportedOperationException("hashCode"); | |
297 } | |
298 | |
299 @Override | |
300 public boolean equals(Object obj) { | |
301 if (this == obj) { | |
302 return true; | |
303 } | |
304 if (obj instanceof Assumptions) { | |
305 Assumptions that = (Assumptions) obj; | |
306 if (!this.assumptions.equals(that.assumptions)) { | |
307 return false; | |
308 } | |
309 return true; | |
310 } | |
311 return false; | |
312 } | |
313 | |
314 @Override | |
315 public Iterator<Assumption> iterator() { | |
316 return assumptions.iterator(); | |
317 } | |
318 | |
319 /** | |
320 * Records an assumption that the specified type has no finalizable subclasses. | |
321 * | |
322 * @param receiverType the type that is assumed to have no finalizable subclasses | |
323 */ | |
324 public void recordNoFinalizableSubclassAssumption(ResolvedJavaType receiverType) { | |
325 record(new NoFinalizableSubclass(receiverType)); | |
326 } | |
327 | |
328 /** | |
329 * Records that {@code subtype} is the only concrete subtype in the class hierarchy below | |
330 * {@code context}. | |
331 * | |
332 * @param context the root of the subtree of the class hierarchy that this assumptions is about | |
333 * @param subtype the one concrete subtype | |
334 */ | |
335 public void recordConcreteSubtype(ResolvedJavaType context, ResolvedJavaType subtype) { | |
336 record(new ConcreteSubtype(context, subtype)); | |
337 } | |
338 | |
339 /** | |
340 * Records that {@code impl} is the only possible concrete target for a virtual call to | |
341 * {@code method} with a receiver of type {@code context}. | |
342 * | |
343 * @param method a method that is the target of a virtual call | |
344 * @param context the receiver type of a call to {@code method} | |
345 * @param impl the concrete method that is the only possible target for the virtual call | |
346 */ | |
347 public void recordConcreteMethod(ResolvedJavaMethod method, ResolvedJavaType context, ResolvedJavaMethod impl) { | |
348 record(new ConcreteMethod(method, context, impl)); | |
349 } | |
350 | |
351 public void record(AssumptionResult<?> result) { | |
352 for (Assumption assumption : result.assumptions) { | |
353 record(assumption); | |
354 } | |
355 } | |
356 | |
357 public void record(Assumption assumption) { | |
358 assumptions.add(assumption); | |
359 } | |
360 | |
361 /** | |
362 * Gets a copy of the assumptions recorded in this object as an array. | |
363 */ | |
364 public Assumption[] toArray() { | |
365 return assumptions.toArray(new Assumption[assumptions.size()]); | |
366 } | |
367 | |
368 /** | |
369 * Copies assumptions recorded by another {@link Assumptions} object into this object. | |
370 */ | |
371 public void record(Assumptions other) { | |
372 assert other != this; | |
373 assumptions.addAll(other.assumptions); | |
374 } | |
375 | |
376 @Override | |
377 public String toString() { | |
378 return "Assumptions[" + assumptions + "]"; | |
379 } | |
380 } |