comparison truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/SpecializationGroup.java @ 21951:9c8c0937da41

Moving all sources into truffle subdirectory
author Jaroslav Tulach <jaroslav.tulach@oracle.com>
date Wed, 17 Jun 2015 10:58:08 +0200
parents graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/SpecializationGroup.java@18c0f02fa4d2
children dc83cc1f94f2
comparison
equal deleted inserted replaced
21950:2a5011c7e641 21951:9c8c0937da41
1 /*
2 * Copyright (c) 2012, 2012, 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.truffle.dsl.processor.parser;
24
25 import java.util.*;
26
27 import javax.lang.model.type.*;
28
29 import com.oracle.truffle.dsl.processor.model.*;
30 import com.oracle.truffle.dsl.processor.model.TemplateMethod.TypeSignature;
31
32 /**
33 * Class creates groups of specializations to optimize the layout of generated executeAndSpecialize
34 * and generic execute methods.
35 */
36 public final class SpecializationGroup {
37
38 private final List<TypeGuard> typeGuards;
39 private final List<GuardExpression> guards;
40
41 private final NodeData node;
42 private final SpecializationData specialization;
43 private final List<SpecializationGroup> children = new ArrayList<>();
44
45 private SpecializationGroup parent;
46
47 private SpecializationGroup(SpecializationData data) {
48 this.node = data.getNode();
49 this.typeGuards = new ArrayList<>();
50 this.guards = new ArrayList<>();
51 this.specialization = data;
52
53 TypeSignature sig = data.getTypeSignature();
54 for (int i = 1; i < sig.size(); i++) {
55 typeGuards.add(new TypeGuard(sig.get(i), i - 1));
56 }
57 this.guards.addAll(data.getGuards());
58 }
59
60 public SpecializationGroup(List<SpecializationGroup> children, List<TypeGuard> typeGuardsMatches, List<GuardExpression> guardMatches) {
61 assert !children.isEmpty() : "children must not be empty";
62 this.typeGuards = typeGuardsMatches;
63 this.guards = guardMatches;
64 this.node = children.get(0).node;
65 this.specialization = null;
66 updateChildren(children);
67 }
68
69 public List<TypeGuard> getAllGuards() {
70 List<TypeGuard> collectedGuards = new ArrayList<>();
71 collectedGuards.addAll(typeGuards);
72 if (parent != null) {
73 collectedGuards.addAll(parent.getAllGuards());
74 }
75 return collectedGuards;
76 }
77
78 public List<GuardExpression> findElseConnectableGuards() {
79 if (!getTypeGuards().isEmpty()) {
80 return Collections.emptyList();
81 }
82
83 if (getGuards().isEmpty()) {
84 return Collections.emptyList();
85 }
86
87 List<GuardExpression> elseConnectableGuards = new ArrayList<>();
88 int guardIndex = 0;
89 while (guardIndex < getGuards().size() && findNegatedGuardInPrevious(getGuards().get(guardIndex)) != null) {
90 elseConnectableGuards.add(getGuards().get(guardIndex));
91 guardIndex++;
92 }
93
94 return elseConnectableGuards;
95 }
96
97 private GuardExpression findNegatedGuardInPrevious(GuardExpression guard) {
98 SpecializationGroup previous = this.getPreviousGroup();
99 if (previous == null) {
100 return null;
101 }
102 List<GuardExpression> elseConnectedGuards = previous.findElseConnectableGuards();
103
104 if (previous == null || previous.getGuards().size() != elseConnectedGuards.size() + 1) {
105 return null;
106 }
107
108 /* Guard is else branch can be connected in previous specialization. */
109 if (elseConnectedGuards.contains(guard)) {
110 return guard;
111 }
112
113 GuardExpression previousGuard = previous.getGuards().get(elseConnectedGuards.size());
114 if (guard.equalsNegated(previousGuard)) {
115 return guard;
116 }
117 return null;
118 }
119
120 private void updateChildren(List<SpecializationGroup> childs) {
121 if (!children.isEmpty()) {
122 children.clear();
123 }
124 this.children.addAll(childs);
125 for (SpecializationGroup child : childs) {
126 child.parent = this;
127 }
128 }
129
130 public SpecializationGroup getParent() {
131 return parent;
132 }
133
134 public List<TypeGuard> getTypeGuards() {
135 return typeGuards;
136 }
137
138 public List<GuardExpression> getGuards() {
139 return guards;
140 }
141
142 public List<SpecializationGroup> getChildren() {
143 return children;
144 }
145
146 public SpecializationData getSpecialization() {
147 return specialization;
148 }
149
150 private static SpecializationGroup combine(List<SpecializationGroup> groups) {
151 if (groups.isEmpty()) {
152 throw new IllegalArgumentException("empty combinations");
153 }
154 if (groups.size() == 1) {
155 return null;
156 }
157
158 List<TypeGuard> typeGuardsMatches = new ArrayList<>();
159 List<GuardExpression> guardMatches = new ArrayList<>();
160
161 SpecializationGroup first = groups.get(0);
162 List<SpecializationGroup> others = groups.subList(1, groups.size());
163
164 outer: for (TypeGuard typeGuard : first.typeGuards) {
165 for (SpecializationGroup other : others) {
166 if (!other.typeGuards.contains(typeGuard)) {
167 // type guards can be combined unordered
168 continue outer;
169 }
170 }
171 typeGuardsMatches.add(typeGuard);
172 }
173
174 outer: for (GuardExpression guard : first.guards) {
175 for (SpecializationGroup other : others) {
176 if (!other.guards.contains(guard)) {
177 // we must break here. One guard may depend on the other.
178 break outer;
179 }
180 }
181 guardMatches.add(guard);
182 }
183
184 // check for guards for required type casts
185 for (Iterator<GuardExpression> iterator = guardMatches.iterator(); iterator.hasNext();) {
186 GuardExpression guardMatch = iterator.next();
187 if (!guardMatch.getExpression().findBoundVariables().isEmpty()) {
188 iterator.remove();
189 }
190 // TODO we need to be smarter here with bound parameters.
191 }
192
193 if (typeGuardsMatches.isEmpty() && guardMatches.isEmpty()) {
194 return null;
195 }
196
197 for (SpecializationGroup group : groups) {
198 group.typeGuards.removeAll(typeGuardsMatches);
199 group.guards.removeAll(guardMatches);
200 }
201
202 List<SpecializationGroup> newChildren = new ArrayList<>(groups);
203 return new SpecializationGroup(newChildren, typeGuardsMatches, guardMatches);
204 }
205
206 public static SpecializationGroup create(SpecializationData specialization) {
207 return new SpecializationGroup(specialization);
208 }
209
210 public static SpecializationGroup create(List<SpecializationData> specializations) {
211 List<SpecializationGroup> groups = new ArrayList<>();
212 for (SpecializationData specialization : specializations) {
213 groups.add(new SpecializationGroup(specialization));
214 }
215 return new SpecializationGroup(createCombinationalGroups(groups), Collections.<TypeGuard> emptyList(), Collections.<GuardExpression> emptyList());
216 }
217
218 @Override
219 public String toString() {
220 return "SpecializationGroup [typeGuards=" + typeGuards + ", guards=" + guards + "]";
221 }
222
223 private static List<SpecializationGroup> createCombinationalGroups(List<SpecializationGroup> groups) {
224 if (groups.size() <= 1) {
225 return groups;
226 }
227 List<SpecializationGroup> newGroups = new ArrayList<>();
228
229 int i = 0;
230 for (i = 0; i < groups.size();) {
231 SpecializationGroup combined = null;
232 for (int j = groups.size(); j > i + 1; j--) {
233 combined = combine(groups.subList(i, j));
234 if (combined != null) {
235 break;
236 }
237 }
238 SpecializationGroup newGroup;
239 if (combined == null) {
240 newGroup = groups.get(i);
241 i++;
242 } else {
243 newGroup = combined;
244 List<SpecializationGroup> originalGroups = new ArrayList<>(combined.children);
245 combined.updateChildren(createCombinationalGroups(originalGroups));
246 i += originalGroups.size();
247 }
248
249 newGroups.add(newGroup);
250
251 }
252
253 return newGroups;
254 }
255
256 public SpecializationGroup getPreviousGroup() {
257 if (parent == null || parent.children.isEmpty()) {
258 return null;
259 }
260 int index = parent.children.indexOf(this);
261 if (index <= 0) {
262 return null;
263 }
264 return parent.children.get(index - 1);
265 }
266
267 public int getUncheckedSpecializationIndex() {
268 int groupMaxIndex = getMaxSpecializationIndex();
269
270 int genericIndex = node.getSpecializations().indexOf(node.getGenericSpecialization());
271 if (groupMaxIndex >= genericIndex) {
272 // no minimum state check for an generic index
273 groupMaxIndex = -1;
274 }
275
276 if (groupMaxIndex > -1) {
277 // no minimum state check if already checked by parent group
278 int parentMaxIndex = -1;
279 if (getParent() != null) {
280 parentMaxIndex = getParent().getMaxSpecializationIndex();
281 }
282 if (groupMaxIndex == parentMaxIndex) {
283 groupMaxIndex = -1;
284 }
285 }
286 return groupMaxIndex;
287 }
288
289 public int getMaxSpecializationIndex() {
290 if (specialization != null) {
291 return specialization.getNode().getSpecializations().indexOf(specialization);
292 } else {
293 int max = Integer.MIN_VALUE;
294 for (SpecializationGroup childGroup : getChildren()) {
295 max = Math.max(max, childGroup.getMaxSpecializationIndex());
296 }
297 return max;
298 }
299 }
300
301 public static final class TypeGuard {
302
303 private final int signatureIndex;
304 private final TypeMirror type;
305
306 public TypeGuard(TypeMirror type, int signatureIndex) {
307 this.type = type;
308 this.signatureIndex = signatureIndex;
309 }
310
311 @Override
312 public int hashCode() {
313 final int prime = 31;
314 int result = 1;
315 result = prime * result + signatureIndex;
316 result = prime * result + type.hashCode();
317 return result;
318 }
319
320 @Override
321 public boolean equals(Object obj) {
322 if (this == obj) {
323 return true;
324 } else if (obj == null) {
325 return false;
326 } else if (getClass() != obj.getClass()) {
327 return false;
328 }
329
330 TypeGuard other = (TypeGuard) obj;
331 if (signatureIndex != other.signatureIndex) {
332 return false;
333 } else if (!type.equals(other.type)) {
334 return false;
335 }
336 return true;
337 }
338
339 public int getSignatureIndex() {
340 return signatureIndex;
341 }
342
343 public TypeMirror getType() {
344 return type;
345 }
346 }
347
348 public SpecializationGroup getPrevious() {
349 if (getParent() == null) {
350 return null;
351 }
352
353 List<SpecializationGroup> parentChildren = getParent().getChildren();
354 int index = parentChildren.indexOf(this);
355 if (index <= 0) {
356 return null;
357 }
358 return parentChildren.get(index - 1);
359 }
360 }