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