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 */ 23 package org.graalvm.compiler.phases; 24 25 import java.util.ArrayList; 26 import java.util.Collections; 27 import java.util.List; 28 import java.util.ListIterator; 29 30 import org.graalvm.compiler.nodes.StructuredGraph; 31 32 /** 33 * A compiler phase that can apply an ordered collection of phases to a graph. 34 */ 35 public 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 * Returns a {@link ListIterator} at the position of the first phase which is an instance of 76 * {@code phaseClass} or null if no such phase can be found. 77 * 78 * Calling {@link ListIterator#previous()} would return the phase that was found. 79 * 80 * @param phaseClass the type of phase to look for. 81 */ 82 public final ListIterator<BasePhase<? super C>> findPhase(Class<? extends BasePhase<? super C>> phaseClass) { 83 return findPhase(phaseClass, false); 84 } 85 86 /** 87 * Returns a {@link ListIterator} at the position of the first phase which is an instance of 88 * {@code phaseClass} or, if {@code recursive} is true, is a {@link PhaseSuite} containing a 89 * phase which is an instance of {@code phaseClass}. This method returns null if no such phase 90 * can be found. 91 * 92 * Calling {@link ListIterator#previous()} would return the phase or phase suite that was found. 93 * 94 * @param phaseClass the type of phase to look for 95 * @param recursive whether to recursively look into phase suites. 96 */ 97 public final ListIterator<BasePhase<? super C>> findPhase(Class<? extends BasePhase<? super C>> phaseClass, boolean recursive) { 98 ListIterator<BasePhase<? super C>> it = phases.listIterator(); 99 if (findNextPhase(it, phaseClass, recursive)) { 100 return it; 101 } else { 102 return null; 103 } 104 } 105 106 public static <C> boolean findNextPhase(ListIterator<BasePhase<? super C>> it, Class<? extends BasePhase<? super C>> phaseClass) { 107 return findNextPhase(it, phaseClass, false); 108 } 109 110 public static <C> boolean findNextPhase(ListIterator<BasePhase<? super C>> it, Class<? extends BasePhase<? super C>> phaseClass, boolean recursive) { 111 while (it.hasNext()) { 112 BasePhase<? super C> phase = it.next(); 113 if (phaseClass.isInstance(phase)) { 114 return true; 115 } else if (recursive && phase instanceof PhaseSuite) { 116 @SuppressWarnings("unchecked") 117 PhaseSuite<C> suite = (PhaseSuite<C>) phase; 118 if (suite.findPhase(phaseClass, true) != null) { 119 return true; 120 } 121 } 122 } 123 return false; 124 } 125 126 /** 127 * Removes the first instance of the given phase class, looking recursively into inner phase 128 * suites. 129 */ 130 public boolean removePhase(Class<? extends BasePhase<? super C>> phaseClass) { 131 ListIterator<BasePhase<? super C>> it = phases.listIterator(); 132 while (it.hasNext()) { 133 BasePhase<? super C> phase = it.next(); 134 if (phaseClass.isInstance(phase)) { 135 it.remove(); 136 return true; 137 } else if (phase instanceof PhaseSuite) { 138 @SuppressWarnings("unchecked") 139 PhaseSuite<C> innerSuite = (PhaseSuite<C>) phase; 140 if (innerSuite.removePhase(phaseClass)) { 141 if (innerSuite.phases.isEmpty()) { 142 it.remove(); 143 } 144 return true; 145 } 146 } 147 } 148 return false; 149 } 150 151 @Override 152 protected void run(StructuredGraph graph, C context) { 153 for (BasePhase<? super C> phase : phases) { 154 phase.apply(graph, context); 155 } 156 } 157 158 public PhaseSuite<C> copy() { 159 PhaseSuite<C> suite = new PhaseSuite<>(); 160 suite.phases.addAll(phases); 161 return suite; 162 } 163 }