Mercurial > hg > truffle
comparison graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/SpecializationData.java @ 16755:bd28da642eea
Truffle-DSL: Several new features implemented:
Implementation of a new code generation layout which shares code between generated nodes.
Declaration order of specializations is now used as specialization order.
Specializations do no longer perform fallthrough on respecialization, they now always respecialize from the first specialization.
Implemented support for contains relations between specializations.
Improved reachability error messages.
Preliminary support for @Implies.
author | Christian Humer <christian.humer@gmail.com> |
---|---|
date | Mon, 11 Aug 2014 15:53:05 +0200 |
parents | 8db6e76cb658 |
children |
comparison
equal
deleted
inserted
replaced
16754:55fd5be68a52 | 16755:bd28da642eea |
---|---|
22 */ | 22 */ |
23 package com.oracle.truffle.dsl.processor.node; | 23 package com.oracle.truffle.dsl.processor.node; |
24 | 24 |
25 import java.util.*; | 25 import java.util.*; |
26 | 26 |
27 import javax.lang.model.type.*; | |
28 | |
29 import com.oracle.truffle.api.dsl.*; | |
30 import com.oracle.truffle.dsl.processor.*; | 27 import com.oracle.truffle.dsl.processor.*; |
31 import com.oracle.truffle.dsl.processor.template.*; | 28 import com.oracle.truffle.dsl.processor.template.*; |
32 import com.oracle.truffle.dsl.processor.typesystem.*; | 29 import com.oracle.truffle.dsl.processor.typesystem.*; |
33 | 30 |
34 public class SpecializationData extends TemplateMethod { | 31 public final class SpecializationData extends TemplateMethod { |
35 | 32 |
36 public enum SpecializationKind { | 33 public enum SpecializationKind { |
37 UNINITIALIZED, | 34 UNINITIALIZED, |
38 SPECIALIZED, | 35 SPECIALIZED, |
39 POLYMORPHIC, | 36 POLYMORPHIC, |
40 GENERIC | 37 GENERIC |
41 } | 38 } |
42 | 39 |
43 private final NodeData node; | 40 private final NodeData node; |
44 private final int order; | |
45 private final SpecializationKind kind; | 41 private final SpecializationKind kind; |
46 private final List<SpecializationThrowsData> exceptions; | 42 private final List<SpecializationThrowsData> exceptions; |
47 private List<String> guardDefinitions = Collections.emptyList(); | 43 private List<GuardExpression> guards = Collections.emptyList(); |
48 private List<GuardData> guards = Collections.emptyList(); | |
49 private List<ShortCircuitData> shortCircuits; | 44 private List<ShortCircuitData> shortCircuits; |
50 private List<String> assumptions = Collections.emptyList(); | 45 private List<String> assumptions = Collections.emptyList(); |
46 private final Set<SpecializationData> contains = new TreeSet<>(); | |
47 private final Set<String> containsNames = new TreeSet<>(); | |
48 private final Set<SpecializationData> excludedBy = new TreeSet<>(); | |
49 private String insertBeforeName; | |
50 private SpecializationData insertBefore; | |
51 private boolean reachable; | 51 private boolean reachable; |
52 | 52 private int index; |
53 public SpecializationData(NodeData node, TemplateMethod template, SpecializationKind kind, int order, List<SpecializationThrowsData> exceptions) { | 53 |
54 public SpecializationData(NodeData node, TemplateMethod template, SpecializationKind kind, List<SpecializationThrowsData> exceptions) { | |
54 super(template); | 55 super(template); |
55 this.node = node; | 56 this.node = node; |
56 this.order = order; | |
57 this.kind = kind; | 57 this.kind = kind; |
58 this.exceptions = exceptions; | 58 this.exceptions = exceptions; |
59 this.index = template.getNaturalOrder(); | |
59 | 60 |
60 for (SpecializationThrowsData exception : exceptions) { | 61 for (SpecializationThrowsData exception : exceptions) { |
61 exception.setSpecialization(this); | 62 exception.setSpecialization(this); |
62 } | 63 } |
63 } | 64 } |
64 | 65 |
66 public void setInsertBefore(SpecializationData insertBefore) { | |
67 this.insertBefore = insertBefore; | |
68 } | |
69 | |
70 public void setInsertBeforeName(String insertBeforeName) { | |
71 this.insertBeforeName = insertBeforeName; | |
72 } | |
73 | |
74 public SpecializationData getInsertBefore() { | |
75 return insertBefore; | |
76 } | |
77 | |
78 public String getInsertBeforeName() { | |
79 return insertBeforeName; | |
80 } | |
81 | |
82 public Set<String> getContainsNames() { | |
83 return containsNames; | |
84 } | |
85 | |
65 public SpecializationData(NodeData node, TemplateMethod template, SpecializationKind kind) { | 86 public SpecializationData(NodeData node, TemplateMethod template, SpecializationKind kind) { |
66 this(node, template, kind, Specialization.DEFAULT_ORDER, new ArrayList<SpecializationThrowsData>()); | 87 this(node, template, kind, new ArrayList<SpecializationThrowsData>()); |
88 } | |
89 | |
90 public Set<SpecializationData> getContains() { | |
91 return contains; | |
92 } | |
93 | |
94 public Set<SpecializationData> getExcludedBy() { | |
95 return excludedBy; | |
67 } | 96 } |
68 | 97 |
69 public void setReachable(boolean reachable) { | 98 public void setReachable(boolean reachable) { |
70 this.reachable = reachable; | 99 this.reachable = reachable; |
71 } | 100 } |
83 List<MessageContainer> sinks = new ArrayList<>(); | 112 List<MessageContainer> sinks = new ArrayList<>(); |
84 if (exceptions != null) { | 113 if (exceptions != null) { |
85 sinks.addAll(exceptions); | 114 sinks.addAll(exceptions); |
86 } | 115 } |
87 if (guards != null) { | 116 if (guards != null) { |
88 sinks.addAll(guards); | 117 for (GuardExpression guard : guards) { |
118 if (guard.isResolved()) { | |
119 sinks.add(guard.getResolvedGuard()); | |
120 } | |
121 } | |
89 } | 122 } |
90 return sinks; | 123 return sinks; |
91 } | |
92 | |
93 public boolean isGenericSpecialization(ProcessorContext context) { | |
94 if (isGeneric()) { | |
95 return true; | |
96 } | |
97 if (hasRewrite(context)) { | |
98 return false; | |
99 } | |
100 | |
101 for (ActualParameter parameter : getSignatureParameters()) { | |
102 ActualParameter genericParameter = getNode().getGenericSpecialization().findParameter(parameter.getLocalName()); | |
103 if (!parameter.getTypeSystemType().equals(genericParameter.getTypeSystemType())) { | |
104 return false; | |
105 } | |
106 } | |
107 return true; | |
108 } | 124 } |
109 | 125 |
110 public boolean hasRewrite(ProcessorContext context) { | 126 public boolean hasRewrite(ProcessorContext context) { |
111 if (!getExceptions().isEmpty()) { | 127 if (!getExceptions().isEmpty()) { |
112 return true; | 128 return true; |
120 for (ActualParameter parameter : getSignatureParameters()) { | 136 for (ActualParameter parameter : getSignatureParameters()) { |
121 ExecutableTypeData type = parameter.getSpecification().getExecution().getChild().findExecutableType(context, parameter.getTypeSystemType()); | 137 ExecutableTypeData type = parameter.getSpecification().getExecution().getChild().findExecutableType(context, parameter.getTypeSystemType()); |
122 if (type.hasUnexpectedValue(context)) { | 138 if (type.hasUnexpectedValue(context)) { |
123 return true; | 139 return true; |
124 } | 140 } |
125 if (type.getReturnType().getTypeSystemType().needsCastTo(context, parameter.getTypeSystemType())) { | 141 if (type.getReturnType().getTypeSystemType().needsCastTo(parameter.getTypeSystemType())) { |
126 return true; | 142 return true; |
127 } | 143 } |
128 | 144 |
129 } | 145 } |
130 return false; | 146 return false; |
131 } | 147 } |
132 | 148 |
133 @Override | 149 @Override |
134 public int compareBySignature(TemplateMethod other) { | 150 public int compareTo(TemplateMethod other) { |
135 if (this == other) { | 151 if (this == other) { |
136 return 0; | 152 return 0; |
137 } else if (!(other instanceof SpecializationData)) { | 153 } else if (!(other instanceof SpecializationData)) { |
138 return super.compareBySignature(other); | 154 return super.compareTo(other); |
139 } | 155 } |
140 | |
141 SpecializationData m2 = (SpecializationData) other; | 156 SpecializationData m2 = (SpecializationData) other; |
142 | |
143 int kindOrder = kind.compareTo(m2.kind); | 157 int kindOrder = kind.compareTo(m2.kind); |
144 if (kindOrder != 0) { | 158 if (kindOrder != 0) { |
145 return kindOrder; | 159 return kindOrder; |
146 } | 160 } |
147 if (getOrder() != Specialization.DEFAULT_ORDER && m2.getOrder() != Specialization.DEFAULT_ORDER) { | 161 |
148 return getOrder() - m2.getOrder(); | 162 int compare = 0; |
163 int order1 = index; | |
164 int order2 = m2.index; | |
165 if (order1 != NO_NATURAL_ORDER && order2 != NO_NATURAL_ORDER) { | |
166 compare = Integer.compare(order1, order2); | |
167 if (compare != 0) { | |
168 return compare; | |
169 } | |
170 } | |
171 | |
172 return super.compareTo(other); | |
173 } | |
174 | |
175 public void setIndex(int order) { | |
176 this.index = order; | |
177 } | |
178 | |
179 public int getIndex() { | |
180 return index; | |
181 } | |
182 | |
183 public int compareByConcreteness(SpecializationData m2) { | |
184 int kindOrder = kind.compareTo(m2.kind); | |
185 if (kindOrder != 0) { | |
186 return kindOrder; | |
149 } | 187 } |
150 | 188 |
151 if (getTemplate() != m2.getTemplate()) { | 189 if (getTemplate() != m2.getTemplate()) { |
152 throw new UnsupportedOperationException("Cannot compare two specializations with different templates."); | 190 throw new UnsupportedOperationException("Cannot compare two specializations with different templates."); |
153 } | 191 } |
154 | 192 boolean intersects = intersects(m2); |
155 return super.compareBySignature(m2); | 193 int result = 0; |
194 if (intersects) { | |
195 if (this.contains(m2)) { | |
196 return 1; | |
197 } else if (m2.contains(this)) { | |
198 return -1; | |
199 } | |
200 } | |
201 | |
202 result = compareBySignature(m2); | |
203 if (result != 0) { | |
204 return result; | |
205 } | |
206 | |
207 result = compareGuards(getGuards(), m2.getGuards()); | |
208 if (result != 0) { | |
209 return result; | |
210 } | |
211 | |
212 result = compareAssumptions(getAssumptions(), m2.getAssumptions()); | |
213 if (result != 0) { | |
214 return result; | |
215 } | |
216 | |
217 result = compareParameter(node.getTypeSystem(), getReturnType().getType(), m2.getReturnType().getType()); | |
218 if (result != 0) { | |
219 return result; | |
220 } | |
221 | |
222 result = m2.getExceptions().size() - getExceptions().size(); | |
223 if (result != 0) { | |
224 return result; | |
225 } | |
226 | |
227 return result; | |
228 } | |
229 | |
230 public boolean contains(SpecializationData other) { | |
231 return getContains().contains(other); | |
232 } | |
233 | |
234 private int compareAssumptions(List<String> assumptions1, List<String> assumptions2) { | |
235 Iterator<String> iterator1 = assumptions1.iterator(); | |
236 Iterator<String> iterator2 = assumptions2.iterator(); | |
237 while (iterator1.hasNext() && iterator2.hasNext()) { | |
238 String a1 = iterator1.next(); | |
239 String a2 = iterator2.next(); | |
240 | |
241 int index1 = getNode().getAssumptions().indexOf(a1); | |
242 int index2 = getNode().getAssumptions().indexOf(a2); | |
243 int result = index1 - index2; | |
244 if (result != 0) { | |
245 return result; | |
246 } | |
247 } | |
248 if (iterator1.hasNext()) { | |
249 return -1; | |
250 } else if (iterator2.hasNext()) { | |
251 return 1; | |
252 } | |
253 return 0; | |
254 } | |
255 | |
256 public boolean isContainedBy(SpecializationData next) { | |
257 if (compareTo(next) > 0) { | |
258 // must be declared after the current specialization | |
259 return false; | |
260 } | |
261 | |
262 Iterator<ActualParameter> currentSignature = getSignatureParameters().iterator(); | |
263 Iterator<ActualParameter> nextSignature = next.getSignatureParameters().iterator(); | |
264 | |
265 while (currentSignature.hasNext() && nextSignature.hasNext()) { | |
266 TypeData currentType = currentSignature.next().getTypeSystemType(); | |
267 TypeData prevType = nextSignature.next().getTypeSystemType(); | |
268 | |
269 if (!currentType.isImplicitSubtypeOf(prevType)) { | |
270 return false; | |
271 } | |
272 } | |
273 | |
274 for (String nextAssumption : next.getAssumptions()) { | |
275 if (!getAssumptions().contains(nextAssumption)) { | |
276 return false; | |
277 } | |
278 } | |
279 | |
280 Iterator<GuardExpression> nextGuards = next.getGuards().iterator(); | |
281 while (nextGuards.hasNext()) { | |
282 GuardExpression nextGuard = nextGuards.next(); | |
283 boolean implied = false; | |
284 for (GuardExpression currentGuard : getGuards()) { | |
285 if (currentGuard.implies(nextGuard)) { | |
286 implied = true; | |
287 break; | |
288 } | |
289 } | |
290 if (!implied) { | |
291 return false; | |
292 } | |
293 } | |
294 | |
295 return true; | |
296 } | |
297 | |
298 public boolean intersects(SpecializationData other) { | |
299 return intersectsTypeGuards(other) || intersectsMethodGuards(other); | |
300 } | |
301 | |
302 private boolean intersectsTypeGuards(SpecializationData other) { | |
303 final TypeSystemData typeSystem = getTemplate().getTypeSystem(); | |
304 if (typeSystem != other.getTemplate().getTypeSystem()) { | |
305 throw new IllegalStateException("Cannot compare two methods with different type systems."); | |
306 } | |
307 | |
308 Iterator<ActualParameter> signature1 = getSignatureParameters().iterator(); | |
309 Iterator<ActualParameter> signature2 = other.getSignatureParameters().iterator(); | |
310 while (signature1.hasNext() && signature2.hasNext()) { | |
311 TypeData parameter1 = signature1.next().getTypeSystemType(); | |
312 TypeData parameter2 = signature2.next().getTypeSystemType(); | |
313 if (parameter1 == null || parameter2 == null) { | |
314 continue; | |
315 } | |
316 if (!parameter1.intersects(parameter2)) { | |
317 return false; | |
318 } | |
319 } | |
320 return true; | |
321 } | |
322 | |
323 private boolean intersectsMethodGuards(SpecializationData other) { | |
324 for (GuardExpression guard1 : getGuards()) { | |
325 for (GuardExpression guard2 : other.getGuards()) { | |
326 if (guard1.impliesNot(guard2) || guard2.impliesNot(guard1)) { | |
327 return false; | |
328 } | |
329 } | |
330 } | |
331 return true; | |
332 } | |
333 | |
334 private static int compareGuards(List<GuardExpression> guards1, List<GuardExpression> guards2) { | |
335 Iterator<GuardExpression> signature1 = guards1.iterator(); | |
336 Iterator<GuardExpression> signature2 = guards2.iterator(); | |
337 boolean allSame = true; | |
338 while (signature1.hasNext() && signature2.hasNext()) { | |
339 GuardExpression guard1 = signature1.next(); | |
340 GuardExpression guard2 = signature2.next(); | |
341 boolean g1impliesg2 = guard1.implies(guard2); | |
342 boolean g2impliesg1 = guard2.implies(guard1); | |
343 if (g1impliesg2 && g2impliesg1) { | |
344 continue; | |
345 } else if (g1impliesg2) { | |
346 return -1; | |
347 } else if (g2impliesg1) { | |
348 return 1; | |
349 } else { | |
350 allSame = false; | |
351 } | |
352 } | |
353 | |
354 if (allSame) { | |
355 if (signature1.hasNext()) { | |
356 return -1; | |
357 } else if (signature2.hasNext()) { | |
358 return 1; | |
359 } | |
360 } | |
361 | |
362 return 0; | |
363 } | |
364 | |
365 public String createReferenceName() { | |
366 StringBuilder b = new StringBuilder(); | |
367 | |
368 b.append(getMethodName()); | |
369 b.append("("); | |
370 | |
371 String sep = ""; | |
372 for (ActualParameter parameter : getParameters()) { | |
373 b.append(sep); | |
374 b.append(Utils.getSimpleName(parameter.getType())); | |
375 sep = ", "; | |
376 } | |
377 | |
378 b.append(")"); | |
379 return b.toString(); | |
156 } | 380 } |
157 | 381 |
158 public NodeData getNode() { | 382 public NodeData getNode() { |
159 return node; | 383 return node; |
160 } | 384 } |
161 | 385 |
162 public void setGuards(List<GuardData> guards) { | 386 public void setGuards(List<GuardExpression> guards) { |
163 this.guards = guards; | 387 this.guards = guards; |
164 } | |
165 | |
166 public void setGuardDefinitions(List<String> guardDefinitions) { | |
167 this.guardDefinitions = guardDefinitions; | |
168 } | |
169 | |
170 public int getOrder() { | |
171 return order; | |
172 } | 388 } |
173 | 389 |
174 public boolean isSpecialized() { | 390 public boolean isSpecialized() { |
175 return kind == SpecializationKind.SPECIALIZED; | 391 return kind == SpecializationKind.SPECIALIZED; |
176 } | 392 } |
185 | 401 |
186 public List<SpecializationThrowsData> getExceptions() { | 402 public List<SpecializationThrowsData> getExceptions() { |
187 return exceptions; | 403 return exceptions; |
188 } | 404 } |
189 | 405 |
190 public List<String> getGuardDefinitions() { | 406 public List<GuardExpression> getGuards() { |
191 return guardDefinitions; | |
192 } | |
193 | |
194 public List<GuardData> getGuards() { | |
195 return guards; | 407 return guards; |
196 } | 408 } |
197 | 409 |
198 public void setShortCircuits(List<ShortCircuitData> shortCircuits) { | 410 public void setShortCircuits(List<ShortCircuitData> shortCircuits) { |
199 this.shortCircuits = shortCircuits; | 411 this.shortCircuits = shortCircuits; |
207 return assumptions; | 419 return assumptions; |
208 } | 420 } |
209 | 421 |
210 void setAssumptions(List<String> assumptions) { | 422 void setAssumptions(List<String> assumptions) { |
211 this.assumptions = assumptions; | 423 this.assumptions = assumptions; |
212 } | |
213 | |
214 public SpecializationData findPreviousSpecialization() { | |
215 List<SpecializationData> specializations = node.getSpecializations(); | |
216 for (int i = 0; i < specializations.size() - 1; i++) { | |
217 if (specializations.get(i) == this && i > 0) { | |
218 return specializations.get(i - 1); | |
219 } | |
220 } | |
221 return null; | |
222 } | 424 } |
223 | 425 |
224 public SpecializationData findNextSpecialization() { | 426 public SpecializationData findNextSpecialization() { |
225 List<SpecializationData> specializations = node.getSpecializations(); | 427 List<SpecializationData> specializations = node.getSpecializations(); |
226 for (int i = 0; i < specializations.size() - 1; i++) { | 428 for (int i = 0; i < specializations.size() - 1; i++) { |
229 } | 431 } |
230 } | 432 } |
231 return null; | 433 return null; |
232 } | 434 } |
233 | 435 |
234 public boolean hasDynamicGuards() { | |
235 return !getGuards().isEmpty(); | |
236 } | |
237 | |
238 @Override | 436 @Override |
239 public String toString() { | 437 public String toString() { |
240 return String.format("%s [id = %s, method = %s, guards = %s, signature = %s]", getClass().getSimpleName(), getId(), getMethod(), getGuards(), getTypeSignature()); | 438 return String.format("%s [id = %s, method = %s, guards = %s, signature = %s]", getClass().getSimpleName(), getId(), getMethod(), getGuards(), getTypeSignature()); |
241 } | 439 } |
242 | 440 |
243 public void forceFrame(TypeMirror frameType) { | |
244 if (getParameters().isEmpty() || !Utils.typeEquals(getParameters().get(0).getType(), frameType)) { | |
245 ParameterSpec frameSpec = getSpecification().findParameterSpec("frame"); | |
246 if (frameSpec != null) { | |
247 getParameters().add(0, new ActualParameter(frameSpec, frameType, -1, -1)); | |
248 } | |
249 } | |
250 } | |
251 | |
252 public boolean equalsGuards(SpecializationData specialization) { | 441 public boolean equalsGuards(SpecializationData specialization) { |
253 if (assumptions.equals(specialization.getAssumptions()) && guards.equals(specialization.getGuards()) && getTypeSignature().equalsParameters(specialization.getTypeSignature())) { | 442 if (assumptions.equals(specialization.getAssumptions()) && guards.equals(specialization.getGuards()) && getTypeSignature().equalsParameters(specialization.getTypeSignature())) { |
254 return true; | 443 return true; |
255 } | 444 } |
256 return false; | 445 return false; |
263 } | 452 } |
264 } | 453 } |
265 return false; | 454 return false; |
266 } | 455 } |
267 | 456 |
457 public boolean isReachableAfter(SpecializationData prev) { | |
458 if (!prev.isSpecialized()) { | |
459 return true; | |
460 } | |
461 | |
462 if (!prev.getExceptions().isEmpty()) { | |
463 return true; | |
464 } | |
465 | |
466 Iterator<ActualParameter> currentSignature = getSignatureParameters().iterator(); | |
467 Iterator<ActualParameter> prevSignature = prev.getSignatureParameters().iterator(); | |
468 | |
469 while (currentSignature.hasNext() && prevSignature.hasNext()) { | |
470 TypeData currentType = currentSignature.next().getTypeSystemType(); | |
471 TypeData prevType = prevSignature.next().getTypeSystemType(); | |
472 | |
473 if (!currentType.isImplicitSubtypeOf(prevType)) { | |
474 return true; | |
475 } | |
476 } | |
477 | |
478 for (String prevAssumption : prev.getAssumptions()) { | |
479 if (!getAssumptions().contains(prevAssumption)) { | |
480 return true; | |
481 } | |
482 } | |
483 | |
484 Iterator<GuardExpression> prevGuards = prev.getGuards().iterator(); | |
485 Iterator<GuardExpression> currentGuards = getGuards().iterator(); | |
486 while (prevGuards.hasNext()) { | |
487 GuardExpression prevGuard = prevGuards.next(); | |
488 GuardExpression currentGuard = currentGuards.hasNext() ? currentGuards.next() : null; | |
489 if (currentGuard == null || !currentGuard.implies(prevGuard)) { | |
490 return true; | |
491 } | |
492 } | |
493 | |
494 return false; | |
495 } | |
268 } | 496 } |