comparison graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java @ 18984:0f462015296f

Truffle: Additions to NodeUtil to support optional "safe" AST node replacement (and diagnostics when unsafe)
author Michael Van De Vanter <michael.van.de.vanter@oracle.com>
date Tue, 27 Jan 2015 20:23:13 -0800
parents c46e268fd091
children 3bf612703773
comparison
equal deleted inserted replaced
18983:43baadc1913a 18984:0f462015296f
1 /* 1 /*
2 * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. 2 * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 * 4 *
5 * This code is free software; you can redistribute it and/or modify it 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 6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this 7 * published by the Free Software Foundation. Oracle designates this
360 360
361 public NodeField[] getChildrenFields() { 361 public NodeField[] getChildrenFields() {
362 return childrenFields; 362 return childrenFields;
363 } 363 }
364 364
365 public NodeField findField(long fieldOffset) {
366 for (NodeField field : getFields()) {
367 if (field.getOffset() == fieldOffset) {
368 return field;
369 }
370 }
371 return null;
372 }
373
365 @Override 374 @Override
366 public int hashCode() { 375 public int hashCode() {
367 return clazz.hashCode(); 376 return clazz.hashCode();
368 } 377 }
369 378
642 assert false : "Child class " + newValue.getClass().getName() + " is not assignable to field \"" + field.getName() + "\" of type " + field.getType().getName(); 651 assert false : "Child class " + newValue.getClass().getName() + " is not assignable to field \"" + field.getName() + "\" of type " + field.getType().getName();
643 return false; 652 return false;
644 } 653 }
645 } 654 }
646 throw new IllegalArgumentException(); 655 throw new IllegalArgumentException();
656 }
657
658 /**
659 * Finds the field in a parent node, if any, that holds a specified child node.
660 *
661 * @return the field (possibly an array) holding the child, {@code null} if not found.
662 */
663 public static NodeField findChildField(Node parent, Node child) {
664 assert child != null;
665 NodeClass parentNodeClass = NodeClass.get(parent.getClass());
666
667 for (NodeField field : parentNodeClass.getChildFields()) {
668 final long fieldOffset = field.getOffset();
669 if (unsafe.getObject(parent, fieldOffset) == child) {
670 return parentNodeClass.findField(fieldOffset);
671 }
672 }
673
674 for (NodeField field : parentNodeClass.getChildrenFields()) {
675 final long fieldOffset = field.getOffset();
676 Object arrayObject = unsafe.getObject(parent, fieldOffset);
677 if (arrayObject != null) {
678 Object[] array = (Object[]) arrayObject;
679 for (int i = 0; i < array.length; i++) {
680 if (array[i] == child) {
681 return parentNodeClass.findField(fieldOffset);
682 }
683 }
684 }
685 }
686 return null;
687 }
688
689 /**
690 * Determines whether a proposed child replacement would be type safe.
691 *
692 * @param parent non-null node
693 * @param oldChild non-null existing child of parent
694 * @param newChild non-null proposed replacement for existing child
695 */
696 public static boolean isReplacementSafe(Node parent, Node oldChild, Node newChild) {
697 assert newChild != null;
698 final NodeField field = findChildField(parent, oldChild);
699 if (field == null) {
700 throw new IllegalArgumentException();
701 }
702 switch (field.getKind()) {
703 case CHILD:
704 return field.getType().isAssignableFrom(newChild.getClass());
705 case CHILDREN:
706 return field.getType().getComponentType().isAssignableFrom(newChild.getClass());
707 default:
708 throw new IllegalArgumentException();
709 }
647 } 710 }
648 711
649 /** Returns all declared fields in the class hierarchy. */ 712 /** Returns all declared fields in the class hierarchy. */
650 private static Field[] getAllFields(Class<? extends Object> clazz) { 713 private static Field[] getAllFields(Class<? extends Object> clazz) {
651 Field[] declaredFields = clazz.getDeclaredFields(); 714 Field[] declaredFields = clazz.getDeclaredFields();