PhaseSuite.java revision 13264:48566d838608
1/* 2 * Copyright (c) 2013, 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 */ 23package org.graalvm.compiler.phases; 24 25import java.util.ArrayList; 26import java.util.Collections; 27import java.util.List; 28import java.util.ListIterator; 29 30import org.graalvm.compiler.nodes.StructuredGraph; 31 32/** 33 * A compiler phase that can apply an ordered collection of phases to a graph. 34 */ 35public class PhaseSuite<C> extends BasePhase<C> { 36 37 private List<BasePhase<? super C>> phases; 38 private boolean immutable; 39 40 public PhaseSuite() { 41 this.phases = new ArrayList<>(); 42 } 43 44 @Override 45 public boolean checkContract() { 46 return false; 47 } 48 49 public boolean isImmutable() { 50 return immutable; 51 } 52 53 public synchronized void setImmutable() { 54 if (!immutable) { 55 phases = Collections.unmodifiableList(phases); 56 immutable = true; 57 } 58 } 59 60 /** 61 * Add a new phase at the beginning of this suite. 62 */ 63 public final void prependPhase(BasePhase<? super C> phase) { 64 phases.add(0, phase); 65 } 66 67 /** 68 * Add a new phase at the end of this suite. 69 */ 70 public final void appendPhase(BasePhase<? super C> phase) { 71 phases.add(phase); 72 } 73 74 /** 75 * Inserts a phase before the last phase in the suite. If the suite contains no phases the new 76 * phase will be inserted as the first phase. 77 */ 78 public final void addBeforeLast(BasePhase<? super C> phase) { 79 ListIterator<BasePhase<? super C>> last = findLastPhase(); 80 if (last.hasPrevious()) { 81 last.previous(); 82 } 83 last.add(phase); 84 } 85 86 /** 87 * Returns a {@link ListIterator} at the position of the last phase in the suite. If the suite 88 * has no phases then it will return an empty iterator. 89 */ 90 private ListIterator<BasePhase<? super C>> findLastPhase() { 91 ListIterator<BasePhase<? super C>> it = phases.listIterator(); 92 while (it.hasNext()) { 93 it.next(); 94 } 95 return it; 96 } 97 98 /** 99 * Returns a {@link ListIterator} at the position of the first phase which is an instance of 100 * {@code phaseClass} or null if no such phase can be found. 101 * 102 * Calling {@link ListIterator#previous()} would return the phase that was found. 103 * 104 * @param phaseClass the type of phase to look for. 105 */ 106 public final ListIterator<BasePhase<? super C>> findPhase(Class<? extends BasePhase<? super C>> phaseClass) { 107 return findPhase(phaseClass, false); 108 } 109 110 /** 111 * Returns a {@link ListIterator} at the position of the first phase which is an instance of 112 * {@code phaseClass} or, if {@code recursive} is true, is a {@link PhaseSuite} containing a 113 * phase which is an instance of {@code phaseClass}. This method returns null if no such phase 114 * can be found. 115 * 116 * Calling {@link ListIterator#previous()} would return the phase or phase suite that was found. 117 * 118 * @param phaseClass the type of phase to look for 119 * @param recursive whether to recursively look into phase suites. 120 */ 121 public final ListIterator<BasePhase<? super C>> findPhase(Class<? extends BasePhase<? super C>> phaseClass, boolean recursive) { 122 ListIterator<BasePhase<? super C>> it = phases.listIterator(); 123 if (findNextPhase(it, phaseClass, recursive)) { 124 return it; 125 } else { 126 return null; 127 } 128 } 129 130 public static <C> boolean findNextPhase(ListIterator<BasePhase<? super C>> it, Class<? extends BasePhase<? super C>> phaseClass) { 131 return findNextPhase(it, phaseClass, false); 132 } 133 134 public static <C> boolean findNextPhase(ListIterator<BasePhase<? super C>> it, Class<? extends BasePhase<? super C>> phaseClass, boolean recursive) { 135 while (it.hasNext()) { 136 BasePhase<? super C> phase = it.next(); 137 if (phaseClass.isInstance(phase)) { 138 return true; 139 } else if (recursive && phase instanceof PhaseSuite) { 140 @SuppressWarnings("unchecked") 141 PhaseSuite<C> suite = (PhaseSuite<C>) phase; 142 if (suite.findPhase(phaseClass, true) != null) { 143 return true; 144 } 145 } 146 } 147 return false; 148 } 149 150 /** 151 * Removes the first instance of the given phase class, looking recursively into inner phase 152 * suites. 153 */ 154 public boolean removePhase(Class<? extends BasePhase<? super C>> phaseClass) { 155 ListIterator<BasePhase<? super C>> it = phases.listIterator(); 156 while (it.hasNext()) { 157 BasePhase<? super C> phase = it.next(); 158 if (phaseClass.isInstance(phase)) { 159 it.remove(); 160 return true; 161 } else if (phase instanceof PhaseSuite) { 162 @SuppressWarnings("unchecked") 163 PhaseSuite<C> innerSuite = (PhaseSuite<C>) phase; 164 if (innerSuite.removePhase(phaseClass)) { 165 if (innerSuite.phases.isEmpty()) { 166 it.remove(); 167 } 168 return true; 169 } 170 } 171 } 172 return false; 173 } 174 175 /** 176 * Removes the first instance of the given phase class, looking recursively into inner phase 177 * suites. 178 */ 179 public boolean replacePhase(Class<? extends BasePhase<? super C>> phaseClass, BasePhase<? super C> newPhase) { 180 ListIterator<BasePhase<? super C>> it = phases.listIterator(); 181 while (it.hasNext()) { 182 BasePhase<? super C> phase = it.next(); 183 if (phaseClass.isInstance(phase)) { 184 it.set(newPhase); 185 return true; 186 } else if (phase instanceof PhaseSuite) { 187 @SuppressWarnings("unchecked") 188 PhaseSuite<C> innerSuite = (PhaseSuite<C>) phase; 189 if (innerSuite.removePhase(phaseClass)) { 190 if (innerSuite.phases.isEmpty()) { 191 it.set(newPhase); 192 } 193 return true; 194 } 195 } 196 } 197 return false; 198 } 199 200 @Override 201 protected void run(StructuredGraph graph, C context) { 202 for (BasePhase<? super C> phase : phases) { 203 phase.apply(graph, context); 204 } 205 } 206 207 public PhaseSuite<C> copy() { 208 PhaseSuite<C> suite = new PhaseSuite<>(); 209 suite.phases.addAll(phases); 210 return suite; 211 } 212} 213