/* * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package jdk.test.lib.jittester; // Production is base class for all elements of the IR-tree. import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Objects; import jdk.test.lib.jittester.loops.For; import jdk.test.lib.jittester.loops.DoWhile; import jdk.test.lib.jittester.loops.While; import jdk.test.lib.jittester.types.TypeKlass; import jdk.test.lib.jittester.visitors.Visitor; public abstract class IRNode { private IRNode parent; private final List children = new ArrayList<>(); protected TypeKlass owner; protected int level; private final Type resultType; protected IRNode(Type resultType) { this.resultType = resultType; } public Type getResultType() { return resultType; } //TODO //private boolean isCFDeviation; public abstract T accept(Visitor v); public void setOwner(TypeKlass owner) { this.owner = owner; if (Objects.isNull(owner)) { System.out.println(getClass().getName() + " null"); for (StackTraceElement s : Thread.currentThread().getStackTrace()) { System.out.println(s.toString()); } } } public void addChild(IRNode child) { if (Objects.nonNull(child)) { children.add(child); child.parent = this; } } public void addChildren(List ch) { if (Objects.nonNull(ch)) { ch.stream() .filter(c -> c != null) .forEach(this::addChild); } } public List getChildren() { return children; } public IRNode getChild(int i) { return i < children.size() ? children.get(i) : null; } public TypeKlass getOwner() { return owner; } public IRNode getParent() { return parent; } public void setChild(int index, IRNode child) { children.set(index, child); if (Objects.nonNull(child)) { child.parent = this; } } public boolean removeChild(IRNode l) { return children.remove(l); } public boolean removeSelf() { return parent.children.remove(this); } public void resizeUpChildren(int size) { for (int i = children.size(); i < size; ++i) { children.add(null); } } public void removeAllChildren() { children.clear(); } public String getTreeTextView(int indent) { StringBuilder sb = new StringBuilder(); if (level > 0) { for (int i = 0; i < indent; ++i) { sb.append("\t"); } sb.append(getName()) .append(" [") .append(level) .append("]") .append(System.lineSeparator()); } children.stream() .filter(ch -> !Objects.isNull(ch)) .forEach(ch -> sb.append(ch.getTreeTextView(indent + 1))); return sb.toString(); } protected IRNode evolve() { throw new Error("Not implemented"); } public int getLevel() { return level; } public long complexity() { return 0L; } @Override public final String toString() { return getName(); } public String getName() { return this.getClass().getName(); } public static long countDepth(Collection input) { return input.stream() .filter(Objects::nonNull) .mapToLong(IRNode::countDepth) .max().orElse(0L); } public long countDepth() { return IRNode.countDepth(children); } public List getStackableLeaves() { List result = new ArrayList<>(); children.stream() .filter(Objects::nonNull) .forEach(c -> { if (countDepth() == c.level && (c instanceof Block)) { result.add(c); } else { result.addAll(c.getStackableLeaves()); } }); return result; } public List getDeviantBlocks(long depth) { List result = new ArrayList<>(); children.stream() .filter(c -> !Objects.isNull(c)) .forEach(c -> { if (depth == c.level && c.isCFDeviation()) { result.add(c); } else { result.addAll(c.getDeviantBlocks(depth)); } }); return result; } public static long getModifiableNodesCount(List nodes) { return nodes.stream() .map(IRNode::getStackableLeaves) .mapToInt(List::size) .filter(i -> i > 0) .count(); } public static boolean tryToReduceNodesDepth(List nodes, int maxDepth) { boolean allSucceed = true; for (IRNode child : nodes) { for (IRNode leaf : child.getDeviantBlocks(Math.max(child.countDepth(), maxDepth + 1))) { if (child.countDepth() > maxDepth) { // doesn't remove control deviation block. Just some parts. leaf.removeSelf(); boolean successfull = child.countDepth() > maxDepth; allSucceed &= successfull; } else { break; } } } return allSucceed; } // TODO: add field instead this function public boolean isCFDeviation() { return this instanceof If || this instanceof Switch || this instanceof For || this instanceof While || this instanceof DoWhile || (this instanceof Block && this.parent instanceof Block); } }