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 }