comparison graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java @ 16513:d86f948268da

Merge with f0f4402a4f65bc5456feeb4d78e6b4843ec23d8c
author Michael Van De Vanter <michael.van.de.vanter@oracle.com>
date Mon, 14 Jul 2014 17:06:32 -0700
parents aee02665e505 9fa5872291c1
children a3b0a2d61e62
comparison
equal deleted inserted replaced
16512:abe7128ca473 16513:d86f948268da
155 /** 155 /**
156 * Information about a {@link Node} class. A single instance of this class is allocated for 156 * Information about a {@link Node} class. A single instance of this class is allocated for
157 * every subclass of {@link Node} that is used. 157 * every subclass of {@link Node} that is used.
158 */ 158 */
159 public static final class NodeClass { 159 public static final class NodeClass {
160 160 private static final ClassValue<NodeClass> nodeClasses = new ClassValue<NodeClass>() {
161 private static final Map<Class<?>, NodeClass> nodeClasses = new IdentityHashMap<>(); 161 @SuppressWarnings("unchecked")
162 @Override
163 protected NodeClass computeValue(Class<?> clazz) {
164 assert Node.class.isAssignableFrom(clazz);
165 return new NodeClass((Class<? extends Node>) clazz, unsafeFieldOffsetProvider);
166 }
167 };
162 168
163 // The comprehensive list of all fields. 169 // The comprehensive list of all fields.
164 private final NodeField[] fields; 170 private final NodeField[] fields;
165 // Separate arrays for the frequently accessed field offsets. 171 // Separate arrays for the frequently accessed field offsets.
166 private final long parentOffset; 172 private final long parentOffset;
167 private final long[] childOffsets; 173 private final long[] childOffsets;
168 private final long[] childrenOffsets; 174 private final long[] childrenOffsets;
175 private final Class<? extends Node> clazz;
169 176
170 public static NodeClass get(Class<? extends Node> clazz) { 177 public static NodeClass get(Class<? extends Node> clazz) {
171 NodeClass nodeClass = nodeClasses.get(clazz); 178 return nodeClasses.get(clazz);
172 if (nodeClass == null) {
173 nodeClass = new NodeClass(clazz, unsafeFieldOffsetProvider);
174 nodeClasses.put(clazz, nodeClass);
175 }
176 return nodeClass;
177 } 179 }
178 180
179 public NodeClass(Class<? extends Node> clazz, FieldOffsetProvider fieldOffsetProvider) { 181 public NodeClass(Class<? extends Node> clazz, FieldOffsetProvider fieldOffsetProvider) {
180 List<NodeField> fieldsList = new ArrayList<>(); 182 List<NodeField> fieldsList = new ArrayList<>();
181 List<Long> parentOffsetsList = new ArrayList<>(); 183 List<Long> parentOffsetsList = new ArrayList<>();
207 this.fields = fieldsList.toArray(new NodeField[fieldsList.size()]); 209 this.fields = fieldsList.toArray(new NodeField[fieldsList.size()]);
208 assert parentOffsetsList.size() == 1 : "must have exactly one parent field"; 210 assert parentOffsetsList.size() == 1 : "must have exactly one parent field";
209 this.parentOffset = parentOffsetsList.get(0); 211 this.parentOffset = parentOffsetsList.get(0);
210 this.childOffsets = toLongArray(childOffsetsList); 212 this.childOffsets = toLongArray(childOffsetsList);
211 this.childrenOffsets = toLongArray(childrenOffsetsList); 213 this.childrenOffsets = toLongArray(childrenOffsetsList);
214 this.clazz = clazz;
212 } 215 }
213 216
214 public NodeField[] getFields() { 217 public NodeField[] getFields() {
215 return fields; 218 return fields;
216 } 219 }
239 return Arrays.equals(fields, other.fields) && Arrays.equals(childOffsets, other.childOffsets) && Arrays.equals(childrenOffsets, other.childrenOffsets) && 242 return Arrays.equals(fields, other.fields) && Arrays.equals(childOffsets, other.childOffsets) && Arrays.equals(childrenOffsets, other.childrenOffsets) &&
240 parentOffset == other.parentOffset; 243 parentOffset == other.parentOffset;
241 } 244 }
242 return false; 245 return false;
243 } 246 }
244 } 247
245 248 public Iterator<Node> makeIterator(Node node) {
246 static class NodeIterator implements Iterator<Node> { 249 assert clazz.isInstance(node);
247 250 return new NodeIterator(node);
248 private final Node node; 251 }
249 private final NodeClass nodeClass; 252
250 private final int childrenCount; 253 private final class NodeIterator implements Iterator<Node> {
251 private int index; 254 private final Node node;
252 255 private int fieldIndex;
253 protected NodeIterator(Node node) { 256 private int arrayIndex;
254 this.node = node; 257
255 this.index = 0; 258 protected NodeIterator(Node node) {
256 this.nodeClass = NodeClass.get(node.getClass()); 259 this.node = node;
257 this.childrenCount = childrenCount(); 260 }
258 } 261
259 262 private void forward() {
260 private int childrenCount() { 263 if (fieldIndex < childOffsets.length) {
261 int nodeCount = nodeClass.childOffsets.length; 264 fieldIndex++;
262 for (long fieldOffset : nodeClass.childrenOffsets) { 265 } else if (fieldIndex < childOffsets.length + childrenOffsets.length) {
263 Node[] children = ((Node[]) unsafe.getObject(node, fieldOffset)); 266 if (arrayIndex + 1 < currentChildrenArrayLength()) {
264 if (children != null) { 267 arrayIndex++;
265 nodeCount += children.length; 268 } else {
266 } 269 arrayIndex = 0;
267 } 270 do {
268 return nodeCount; 271 fieldIndex++;
269 } 272 } while (fieldIndex < childOffsets.length + childrenOffsets.length && currentChildrenArrayLength() == 0);
270
271 private Node nodeAt(int idx) {
272 int nodeCount = nodeClass.childOffsets.length;
273 if (idx < nodeCount) {
274 return (Node) unsafe.getObject(node, nodeClass.childOffsets[idx]);
275 } else {
276 for (long fieldOffset : nodeClass.childrenOffsets) {
277 Node[] nodeArray = (Node[]) unsafe.getObject(node, fieldOffset);
278 if (idx < nodeCount + nodeArray.length) {
279 return nodeArray[idx - nodeCount];
280 } 273 }
281 nodeCount += nodeArray.length; 274 }
282 } 275 }
283 } 276
284 return null; 277 public boolean hasNext() {
285 } 278 return fieldIndex < childOffsets.length || (fieldIndex < childOffsets.length + childrenOffsets.length && arrayIndex < currentChildrenArrayLength());
286 279 }
287 private void forward() { 280
288 if (index < childrenCount) { 281 private Node[] currentChildrenArray() {
289 index++; 282 assert fieldIndex >= childOffsets.length && fieldIndex < childOffsets.length + childrenOffsets.length;
290 } 283 return (Node[]) unsafe.getObject(node, childrenOffsets[fieldIndex - childOffsets.length]);
291 } 284 }
292 285
293 @Override 286 private int currentChildrenArrayLength() {
294 public boolean hasNext() { 287 Node[] childrenArray = currentChildrenArray();
295 return index < childrenCount; 288 return childrenArray != null ? childrenArray.length : 0;
296 } 289 }
297 290
298 @Override 291 public Node next() {
299 public Node next() { 292 Node next;
300 try { 293 if (fieldIndex < childOffsets.length) {
301 return nodeAt(index); 294 next = (Node) unsafe.getObject(node, childOffsets[fieldIndex]);
302 } finally { 295 } else if (fieldIndex < childOffsets.length + childrenOffsets.length) {
296 next = currentChildrenArray()[arrayIndex];
297 } else {
298 throw new NoSuchElementException();
299 }
303 forward(); 300 forward();
304 } 301 return next;
305 } 302 }
306 303
307 @Override 304 public void remove() {
308 public void remove() { 305 throw new UnsupportedOperationException();
309 throw new UnsupportedOperationException(); 306 }
310 } 307 }
308 }
309
310 static Iterator<Node> makeIterator(Node node) {
311 return NodeClass.get(node.getClass()).makeIterator(node);
311 } 312 }
312 313
313 private static long[] toLongArray(List<Long> list) { 314 private static long[] toLongArray(List<Long> list) {
314 long[] array = new long[list.size()]; 315 long[] array = new long[list.size()];
315 for (int i = 0; i < list.size(); i++) { 316 for (int i = 0; i < list.size(); i++) {
540 } 541 }
541 } 542 }
542 return null; 543 return null;
543 } 544 }
544 545
545 public static <T extends Node> List<T> findAllNodeInstances(final Node root, final Class<T> clazz) { 546 public static <T> List<T> findAllNodeInstances(final Node root, final Class<T> clazz) {
546 final List<T> nodeList = new ArrayList<>(); 547 final List<T> nodeList = new ArrayList<>();
547 root.accept(new NodeVisitor() { 548 root.accept(new NodeVisitor() {
548
549 @SuppressWarnings("unchecked")
550 @Override
551 public boolean visit(Node node) { 549 public boolean visit(Node node) {
552 if (clazz.isInstance(node)) { 550 if (clazz.isInstance(node)) {
553 nodeList.add((T) node); 551 nodeList.add(clazz.cast(node));
554 } 552 }
555 return true; 553 return true;
556 } 554 }
557 }); 555 });
558 return nodeList; 556 return nodeList;
559 } 557 }
560 558
561 // Don't visit found node instances. 559 /**
562 public static <T extends Node> List<T> findNodeInstancesShallow(final Node root, final Class<T> clazz) { 560 * Like {@link #findAllNodeInstances(Node, Class)} but do not visit children of found nodes.
561 */
562 public static <T> List<T> findNodeInstancesShallow(final Node root, final Class<T> clazz) {
563 final List<T> nodeList = new ArrayList<>(); 563 final List<T> nodeList = new ArrayList<>();
564 root.accept(new NodeVisitor() { 564 root.accept(new NodeVisitor() {
565
566 @SuppressWarnings("unchecked")
567 @Override
568 public boolean visit(Node node) { 565 public boolean visit(Node node) {
569 if (clazz.isInstance(node)) { 566 if (clazz.isInstance(node)) {
570 nodeList.add((T) node); 567 nodeList.add(clazz.cast(node));
571 return false;
572 }
573 return true;
574 }
575 });
576 return nodeList;
577 }
578
579 /** Find node instances within current function only (not in nested functions). */
580 public static <T extends Node> List<T> findNodeInstancesInFunction(final Node root, final Class<T> clazz) {
581 final List<T> nodeList = new ArrayList<>();
582 root.accept(new NodeVisitor() {
583
584 @SuppressWarnings("unchecked")
585 @Override
586 public boolean visit(Node node) {
587 if (clazz.isInstance(node)) {
588 nodeList.add((T) node);
589 } else if (node instanceof RootNode && node != root) {
590 return false;
591 }
592 return true;
593 }
594 });
595 return nodeList;
596 }
597
598 public static <I> List<I> findNodeInstancesInFunctionInterface(final Node root, final Class<I> clazz) {
599 final List<I> nodeList = new ArrayList<>();
600 root.accept(new NodeVisitor() {
601
602 @SuppressWarnings("unchecked")
603 @Override
604 public boolean visit(Node node) {
605 if (clazz.isInstance(node)) {
606 nodeList.add((I) node);
607 } else if (node instanceof RootNode && node != root) {
608 return false; 568 return false;
609 } 569 }
610 return true; 570 return true;
611 } 571 }
612 }); 572 });
892 } 852 }
893 853
894 private static String toStringWithClass(Object obj) { 854 private static String toStringWithClass(Object obj) {
895 return obj == null ? "null" : obj + "(" + obj.getClass().getName() + ")"; 855 return obj == null ? "null" : obj + "(" + obj.getClass().getName() + ")";
896 } 856 }
857
858 static void traceRewrite(Node oldNode, Node newNode, CharSequence reason) {
859 if (TruffleOptions.TraceRewritesFilterFromCost != null) {
860 if (filterByKind(oldNode, TruffleOptions.TraceRewritesFilterFromCost)) {
861 return;
862 }
863 }
864
865 if (TruffleOptions.TraceRewritesFilterToCost != null) {
866 if (filterByKind(newNode, TruffleOptions.TraceRewritesFilterToCost)) {
867 return;
868 }
869 }
870
871 String filter = TruffleOptions.TraceRewritesFilterClass;
872 Class<? extends Node> from = oldNode.getClass();
873 Class<? extends Node> to = newNode.getClass();
874 if (filter != null && (filterByContainsClassName(from, filter) || filterByContainsClassName(to, filter))) {
875 return;
876 }
877
878 final SourceSection reportedSourceSection = oldNode.getEncapsulatingSourceSection();
879
880 PrintStream out = System.out;
881 out.printf("[truffle] rewrite %-50s |From %-40s |To %-40s |Reason %s%s%n", oldNode.toString(), formatNodeInfo(oldNode), formatNodeInfo(newNode),
882 reason != null && reason.length() > 0 ? reason : "unknown", reportedSourceSection != null ? " at " + reportedSourceSection.getShortDescription() : "");
883 }
884
885 private static String formatNodeInfo(Node node) {
886 String cost = "?";
887 switch (node.getCost()) {
888 case NONE:
889 cost = "G";
890 break;
891 case MONOMORPHIC:
892 cost = "M";
893 break;
894 case POLYMORPHIC:
895 cost = "P";
896 break;
897 case MEGAMORPHIC:
898 cost = "G";
899 break;
900 default:
901 cost = "?";
902 break;
903 }
904 return cost + " " + node.getClass().getSimpleName();
905 }
906
907 private static boolean filterByKind(Node node, NodeCost cost) {
908 return node.getCost() == cost;
909 }
910
911 private static boolean filterByContainsClassName(Class<? extends Node> from, String filter) {
912 Class<?> currentFrom = from;
913 while (currentFrom != null) {
914 if (currentFrom.getName().contains(filter)) {
915 return false;
916 }
917 currentFrom = currentFrom.getSuperclass();
918 }
919 return true;
920 }
897 } 921 }