001/* 002 * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. 003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 004 * 005 * This code is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU General Public License version 2 only, as 007 * published by the Free Software Foundation. 008 * 009 * This code is distributed in the hope that it will be useful, but WITHOUT 010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 011 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 012 * version 2 for more details (a copy is included in the LICENSE file that 013 * accompanied this code). 014 * 015 * You should have received a copy of the GNU General Public License version 016 * 2 along with this work; if not, write to the Free Software Foundation, 017 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 018 * 019 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 020 * or visit www.oracle.com if you need additional information or have any 021 * questions. 022 */ 023package com.oracle.graal.virtual.phases.ea; 024 025import java.lang.reflect.*; 026import java.util.*; 027 028import jdk.internal.jvmci.common.*; 029import com.oracle.graal.debug.*; 030 031import com.oracle.graal.graph.*; 032import com.oracle.graal.nodes.*; 033 034/** 035 * An {@link EffectList} can be used to maintain a list of {@link Effect}s and backtrack to a 036 * previous state by truncating the list. 037 */ 038public class EffectList implements Iterable<EffectList.Effect> { 039 040 public interface Effect { 041 default boolean isVisible() { 042 return true; 043 } 044 045 default boolean isCfgKill() { 046 return false; 047 } 048 049 void apply(StructuredGraph graph, ArrayList<Node> obsoleteNodes); 050 } 051 052 public interface SimpleEffect extends Effect { 053 default void apply(StructuredGraph graph, ArrayList<Node> obsoleteNodes) { 054 apply(graph); 055 } 056 057 void apply(StructuredGraph graph); 058 } 059 060 private static final Effect[] EMPTY_ARRAY = new Effect[0]; 061 private static final String[] EMPTY_STRING_ARRAY = new String[0]; 062 063 private Effect[] effects = EMPTY_ARRAY; 064 private String[] names = EMPTY_STRING_ARRAY; 065 private int size; 066 067 private void enlarge(int elements) { 068 int length = effects.length; 069 if (size + elements > length) { 070 while (size + elements > length) { 071 length = Math.max(length * 2, 4); 072 } 073 effects = Arrays.copyOf(effects, length); 074 if (Debug.isEnabled()) { 075 names = Arrays.copyOf(names, length); 076 } 077 } 078 } 079 080 public void add(String name, SimpleEffect effect) { 081 add(name, (Effect) effect); 082 } 083 084 public void add(String name, Effect effect) { 085 assert effect != null; 086 enlarge(1); 087 if (Debug.isEnabled()) { 088 names[size] = name; 089 } 090 effects[size++] = effect; 091 } 092 093 public void addAll(EffectList list) { 094 enlarge(list.size); 095 System.arraycopy(list.effects, 0, effects, size, list.size); 096 if (Debug.isEnabled()) { 097 System.arraycopy(list.names, 0, names, size, list.size); 098 } 099 size += list.size; 100 } 101 102 public void insertAll(EffectList list, int position) { 103 assert position >= 0 && position <= size; 104 enlarge(list.size); 105 System.arraycopy(effects, position, effects, position + list.size, size - position); 106 System.arraycopy(list.effects, 0, effects, position, list.size); 107 if (Debug.isEnabled()) { 108 System.arraycopy(names, position, names, position + list.size, size - position); 109 System.arraycopy(list.names, 0, names, position, list.size); 110 } 111 size += list.size; 112 } 113 114 public int checkpoint() { 115 return size; 116 } 117 118 public int size() { 119 return size; 120 } 121 122 public void backtrack(int checkpoint) { 123 assert checkpoint <= size; 124 size = checkpoint; 125 } 126 127 @Override 128 public Iterator<Effect> iterator() { 129 return new Iterator<Effect>() { 130 131 int index; 132 final int listSize = EffectList.this.size; 133 134 @Override 135 public boolean hasNext() { 136 return index < listSize; 137 } 138 139 @Override 140 public Effect next() { 141 return effects[index++]; 142 } 143 144 @Override 145 public void remove() { 146 throw new UnsupportedOperationException(); 147 } 148 }; 149 } 150 151 public Effect get(int index) { 152 if (index >= size) { 153 throw new IndexOutOfBoundsException(); 154 } 155 return effects[index]; 156 } 157 158 public void clear() { 159 size = 0; 160 } 161 162 public boolean isEmpty() { 163 return size == 0; 164 } 165 166 public void apply(StructuredGraph graph, ArrayList<Node> obsoleteNodes, boolean cfgKills) { 167 for (int i = 0; i < size(); i++) { 168 Effect effect = effects[i]; 169 if (effect.isCfgKill() == cfgKills) { 170 try { 171 effect.apply(graph, obsoleteNodes); 172 } catch (Throwable t) { 173 StringBuilder str = new StringBuilder(); 174 toString(str, i); 175 throw new JVMCIError(t).addContext("effect", str); 176 } 177 if (effect.isVisible() && Debug.isLogEnabled()) { 178 StringBuilder str = new StringBuilder(); 179 toString(str, i); 180 Debug.log(" %s", str); 181 } 182 } 183 } 184 } 185 186 private void toString(StringBuilder str, int i) { 187 Effect effect = effects[i]; 188 str.append(getName(i)).append(" ["); 189 boolean first = true; 190 for (Field field : effect.getClass().getDeclaredFields()) { 191 try { 192 field.setAccessible(true); 193 Object object = field.get(effect); 194 if (object == this) { 195 // Inner classes could capture the EffectList itself. 196 continue; 197 } 198 str.append(first ? "" : ", ").append(format(object)); 199 first = false; 200 } catch (SecurityException | IllegalAccessException e) { 201 throw new RuntimeException(e); 202 } 203 } 204 str.append(']'); 205 } 206 207 private static String format(Object object) { 208 if (object != null && Object[].class.isAssignableFrom(object.getClass())) { 209 return Arrays.toString((Object[]) object); 210 } 211 return "" + object; 212 } 213 214 @Override 215 public String toString() { 216 StringBuilder str = new StringBuilder(); 217 for (int i = 0; i < size(); i++) { 218 Effect effect = get(i); 219 if (effect.isVisible()) { 220 toString(str, i); 221 str.append('\n'); 222 } 223 } 224 return str.toString(); 225 } 226 227 private String getName(int i) { 228 if (Debug.isEnabled()) { 229 return names[i]; 230 } else { 231 return ""; 232 } 233 } 234}