1 pnkfelix 1.1.2.1 // AppelRegAllocStd.java, created Sat Jul 7 16:36:00 2001 by pnkfelix 2 pnkfelix 1.1.2.1 // Copyright (C) 2000 Felix S. Klock II <pnkfelix@mit.edu> 3 pnkfelix 1.1.2.1 // Licensed under the terms of the GNU GPL; see COPYING for details. 4 pnkfelix 1.1.2.1 package harpoon.Analysis.Instr; 5 pnkfelix 1.1.2.1 6 pnkfelix 1.1.2.1 import harpoon.Backend.Generic.Code; 7 pnkfelix 1.1.2.1 import harpoon.IR.Assem.Instr; 8 pnkfelix 1.1.2.1 import harpoon.IR.Assem.InstrGroup; 9 pnkfelix 1.1.2.1 10 pnkfelix 1.1.2.1 import harpoon.Analysis.BasicBlock; 11 pnkfelix 1.1.2.1 12 pnkfelix 1.1.2.1 import harpoon.Temp.Temp; 13 pnkfelix 1.1.2.1 import harpoon.Util.Util; 14 pnkfelix 1.1.2.1 15 cananian 1.6 import java.util.AbstractCollection; 16 cananian 1.6 import java.util.Arrays; 17 pnkfelix 1.1.2.1 import java.util.Collection; 18 cananian 1.6 import java.util.Collections; 19 cananian 1.6 import java.util.HashMap; 20 cananian 1.6 import java.util.HashSet; 21 cananian 1.6 import java.util.Iterator; 22 cananian 1.6 import java.util.List; 23 cananian 1.6 import java.util.Map; 24 pnkfelix 1.1.2.1 import java.util.Set; 25 cananian 1.6 26 cananian 1.6 import net.cscott.jutil.FilterIterator; 27 cananian 1.6 import net.cscott.jutil.CombineIterator; 28 pnkfelix 1.1.2.1 29 pnkfelix 1.1.2.1 public class AppelRegAllocStd extends AppelRegAlloc { 30 pnkfelix 1.1.2.1 // Instr i -> Move m such m.instr = i 31 cananian 1.6 private Map<Instr,Move> instrToMove = new HashMap<Instr,Move>(); 32 pnkfelix 1.1.2.1 33 pnkfelix 1.1.2.1 // Web w -> Listof Node 34 cananian 1.6 private Map<Web,List<Node>> webToNodes = new HashMap<Web,List<Node>>(); 35 pnkfelix 1.1.2.1 36 pnkfelix 1.1.2.1 public AppelRegAllocStd(Code code) { 37 pnkfelix 1.1.2.1 super(code); 38 pnkfelix 1.1.2.1 } 39 pnkfelix 1.1.2.1 40 pnkfelix 1.1.2.1 protected void initializeSets() { 41 pnkfelix 1.1.2.1 super.initializeSets(); 42 pnkfelix 1.1.2.1 webToNodes.clear(); 43 pnkfelix 1.1.2.1 instrToMove.clear(); 44 pnkfelix 1.1.2.1 } 45 pnkfelix 1.1.2.1 46 cananian 1.6 protected List<Node> nodesFor( Web web ) { 47 pnkfelix 1.1.2.1 if (CHECK_INV) 48 cananian 1.3.2.1 assert webToNodes.containsKey( web ) : "! should have nodes for "+web; 49 cananian 1.6 return webToNodes.get( web ); 50 pnkfelix 1.1.2.1 } 51 pnkfelix 1.1.2.1 52 pnkfelix 1.1.2.1 53 pnkfelix 1.1.2.1 protected Node makePrecolored(Temp t) { 54 pnkfelix 1.1.2.1 Node n = super.makePrecolored(t); 55 cananian 1.6 webToNodes.put(n.web, Collections.singletonList(n)); 56 pnkfelix 1.1.2.1 return n; 57 pnkfelix 1.1.2.1 } 58 pnkfelix 1.1.2.1 59 pnkfelix 1.1.2.1 protected void makeInitial(Temp t) { 60 pnkfelix 1.1.2.1 Set assns = rfi().getRegAssignments(t); 61 pnkfelix 1.1.2.1 List assn = (List) assns.iterator().next(); 62 pnkfelix 1.1.2.1 63 cananian 1.6 for(Object webO : tempToWebs.getValues(t)){ 64 cananian 1.6 Web web = (Web) webO; 65 pnkfelix 1.1.2.1 Node[] nodes = new Node[ assn.size() ]; 66 pnkfelix 1.1.2.1 for(int i=0; i < nodes.length; i++) { 67 pnkfelix 1.1.2.1 Node n = new Node(initial, web); 68 pnkfelix 1.1.2.1 nodes[i] = n; 69 pnkfelix 1.1.2.1 } 70 pnkfelix 1.1.2.1 webToNodes.put( web, Arrays.asList( nodes )); 71 pnkfelix 1.1.2.1 } 72 pnkfelix 1.1.2.1 } 73 pnkfelix 1.1.2.1 74 pnkfelix 1.1.2.1 protected void checkDegreeInv() { 75 pnkfelix 1.1.2.1 // u isIn (simplifyWorklist \/ freezeWorklist \/ spillWorklist ) ==> 76 pnkfelix 1.1.2.1 // degree(u) = | adjList(u) /\ ( precolored \/ simplifyWorklist \/ 77 pnkfelix 1.1.2.1 // freezeWorklist \/ spillWorklist ) | 78 pnkfelix 1.1.2.1 // ( tranlates to ) 79 pnkfelix 1.1.2.1 // foreach u in (simplify U freeze U spill ) 80 pnkfelix 1.1.2.1 // degree(u) = | {n | n isIn adjList(u) && 81 pnkfelix 1.1.2.1 // n isIn precolored \/ simplify \/ 82 pnkfelix 1.1.2.1 // freeze \/ spill } | 83 pnkfelix 1.1.2.1 84 pnkfelix 1.1.2.1 HashSet outerSeen = new HashSet(); 85 pnkfelix 1.1.2.1 86 pnkfelix 1.1.2.1 NodeIter ni=combine(new NodeIter[]{simplify_worklist.iter(), 87 pnkfelix 1.1.2.1 freeze_worklist.iter(), 88 pnkfelix 1.1.2.1 spill_worklist.iter()}); 89 pnkfelix 1.1.2.1 while( ni.hasNext() ) { 90 pnkfelix 1.1.2.1 Node u = ni.next(); 91 pnkfelix 1.1.2.1 92 pnkfelix 1.1.2.1 if (CHECK_INV) 93 cananian 1.3.2.1 assert ! outerSeen.contains(u) : " already saw " + u; 94 pnkfelix 1.1.2.1 95 pnkfelix 1.1.2.1 outerSeen.add(u); 96 pnkfelix 1.1.2.1 97 pnkfelix 1.1.2.1 int deg = u.degree; 98 pnkfelix 1.1.2.1 for(NodeIter adj=adjacent(u); adj.hasNext();) { 99 pnkfelix 1.1.2.1 Node a = adj.next(); 100 pnkfelix 1.1.2.1 101 pnkfelix 1.1.2.1 if( a.isPrecolored() || 102 pnkfelix 1.1.2.1 a.isSimplifyWorkL() || 103 pnkfelix 1.1.2.1 a.isFreezeWorkL() || 104 pnkfelix 1.1.2.1 a.isSpillWorkL() ) { 105 pnkfelix 1.1.2.1 deg--; 106 pnkfelix 1.1.2.1 } 107 pnkfelix 1.1.2.1 } 108 cananian 1.3.2.1 assert deg == 0 : "degree inv. violated"; 109 pnkfelix 1.1.2.1 } 110 pnkfelix 1.1.2.1 } 111 pnkfelix 1.1.2.1 112 pnkfelix 1.1.2.1 protected void buildInterferenceGraph() { 113 pnkfelix 1.1.2.1 for(Iterator bbs=bbFact.blocksIterator(); bbs.hasNext();) { 114 pnkfelix 1.1.2.1 BasicBlock bb = (BasicBlock) bbs.next(); 115 pnkfelix 1.1.2.1 Set/*Node*/ live = liveOut(bb); 116 pnkfelix 1.1.2.1 117 pnkfelix 1.1.2.1 for(Instr i = lastStm(bb); !i.equals( firstStm(bb) ); i = pred(i)){ 118 pnkfelix 1.1.2.1 if( i.isMove() ){ 119 pnkfelix 1.1.2.1 live.removeAll( useCN( i ) ); 120 pnkfelix 1.1.2.1 for( NodeIter ni = usedef(i); ni.hasNext(); ){ 121 pnkfelix 1.1.2.1 Node n = ni.next(); 122 pnkfelix 1.1.2.1 n.moves.add( moveFor(i) ); 123 pnkfelix 1.1.2.1 } 124 pnkfelix 1.1.2.1 worklist_moves.add( moveFor(i) ); 125 pnkfelix 1.1.2.1 } 126 pnkfelix 1.1.2.1 127 pnkfelix 1.1.2.1 live.addAll( defCN(i) ); 128 pnkfelix 1.1.2.1 for( NodeIter di = def(i); di.hasNext(); ){ 129 pnkfelix 1.1.2.1 Node d = di.next(); 130 cananian 1.6 for(Object nO : live){ 131 cananian 1.6 Node n = (Node) nO; 132 pnkfelix 1.1.2.1 addEdge( n, d ); 133 pnkfelix 1.1.2.1 } 134 pnkfelix 1.1.2.1 } 135 pnkfelix 1.1.2.1 live.removeAll( defCN(i) ); 136 pnkfelix 1.1.2.1 live. addAll( useCN(i) ); 137 pnkfelix 1.1.2.1 } 138 pnkfelix 1.1.2.1 139 pnkfelix 1.1.2.1 } 140 pnkfelix 1.1.2.1 141 pnkfelix 1.1.2.1 } 142 pnkfelix 1.1.2.1 143 pnkfelix 1.1.2.1 protected void addEdge( Node u, Node v ) { 144 pnkfelix 1.1.2.1 // FSK: (6/27/01) adding because having these edges is dumb. 145 pnkfelix 1.1.2.1 // Shouldn't break anything. And yet... 146 pnkfelix 1.1.2.1 if (u.isPrecolored() && v.isPrecolored()) { 147 pnkfelix 1.1.2.1 return; 148 pnkfelix 1.1.2.1 } 149 pnkfelix 1.1.2.1 150 pnkfelix 1.1.2.1 if( ! adjSet.contains(u,v) && ! u.equals(v) ){ 151 pnkfelix 1.1.2.1 adjSet.add(u,v); 152 pnkfelix 1.1.2.1 adjSet.add(v,u); 153 pnkfelix 1.1.2.1 154 pnkfelix 1.1.2.1 if( ! u.isPrecolored() ){ 155 pnkfelix 1.1.2.1 u.neighbors.add(v); 156 pnkfelix 1.1.2.1 u.degree++; 157 pnkfelix 1.1.2.1 } 158 pnkfelix 1.1.2.1 if( ! v.isPrecolored() ){ 159 pnkfelix 1.1.2.1 v.neighbors.add(u); 160 pnkfelix 1.1.2.1 v.degree++; 161 pnkfelix 1.1.2.1 } 162 pnkfelix 1.1.2.1 } 163 pnkfelix 1.1.2.1 } 164 pnkfelix 1.1.2.1 165 pnkfelix 1.1.2.1 protected void decrementDegree( Node m, Node n ) { 166 pnkfelix 1.1.2.1 if (m.isPrecolored()) 167 pnkfelix 1.1.2.1 return; 168 pnkfelix 1.1.2.1 169 pnkfelix 1.1.2.1 int d = m.degree; 170 pnkfelix 1.1.2.1 m.degree--; 171 pnkfelix 1.1.2.1 if( d == K 172 pnkfelix 1.1.2.1 173 pnkfelix 1.1.2.1 // FSK: this clause isn't in the book, but it *is* in 174 pnkfelix 1.1.2.1 // FSK: CSAHack.RegAlloc.Color. Appel assumes that m is 175 pnkfelix 1.1.2.1 // FSK: in spillWorklist, but its possible for a node to 176 pnkfelix 1.1.2.1 // FSK: be in Freeze (and Simplify?), have its degree 177 pnkfelix 1.1.2.1 // FSK: incremented to K in Combine(u,v), and then this 178 pnkfelix 1.1.2.1 // FSK: method is called. So we explicitly check if m is 179 pnkfelix 1.1.2.1 // FSK: in spillWorklist first. 180 pnkfelix 1.1.2.1 // TODO: verify that this is the right behavior (intuitively, it should be...) 181 pnkfelix 1.1.2.1 && m.isSpillWorkL() 182 pnkfelix 1.1.2.1 183 pnkfelix 1.1.2.1 184 pnkfelix 1.1.2.1 ) { 185 pnkfelix 1.1.2.1 186 pnkfelix 1.1.2.1 enableMoves(m); 187 pnkfelix 1.1.2.1 enableMoves( adjacent(m) ); 188 pnkfelix 1.1.2.1 189 pnkfelix 1.1.2.1 spill_worklist.remove(m); 190 pnkfelix 1.1.2.1 if( moveRelated( m )) { 191 pnkfelix 1.1.2.1 freeze_worklist.add( m ); 192 pnkfelix 1.1.2.1 } else { 193 pnkfelix 1.1.2.1 simplify_worklist.add( m ); 194 pnkfelix 1.1.2.1 } 195 pnkfelix 1.1.2.1 } 196 pnkfelix 1.1.2.1 } 197 pnkfelix 1.1.2.1 198 pnkfelix 1.1.2.1 protected boolean conservative(Node u, Node v) { 199 pnkfelix 1.1.2.1 return conservative(adjacent(u), adjacent(v)); 200 pnkfelix 1.1.2.1 } 201 pnkfelix 1.1.2.1 // returns conservative( ni1 \/ ni2 ) 202 pnkfelix 1.1.2.1 // conservative coalescing heuristic due to Preston Briggs 203 pnkfelix 1.1.2.1 private boolean conservative(NodeIter ni1, NodeIter ni2) { 204 pnkfelix 1.1.2.1 NodeIter union; 205 pnkfelix 1.1.2.1 // [ FIXED, but am seeing signs that "conservation" is being broken. 206 pnkfelix 1.1.2.1 // could just be inherent heuristical effects though ] 207 pnkfelix 1.1.2.1 // FSK combine(...) is not a strict union. 208 pnkfelix 1.1.2.1 // union = combine( new NodeIter[]{ ni1, ni2 } ); 209 pnkfelix 1.1.2.1 union = union(ni1, ni2); 210 pnkfelix 1.1.2.1 211 pnkfelix 1.1.2.1 return conservative( union ); 212 pnkfelix 1.1.2.1 } 213 pnkfelix 1.1.2.1 private NodeIter union(NodeIter n1, NodeIter n2) { 214 pnkfelix 1.1.2.1 HashSet s = new HashSet(); 215 pnkfelix 1.1.2.1 while(n1.hasNext()){ s.add(n1.next()); } 216 pnkfelix 1.1.2.1 while(n2.hasNext()){ s.add(n2.next()); } 217 pnkfelix 1.1.2.1 return nodesIter( s.iterator() ); 218 pnkfelix 1.1.2.1 } 219 pnkfelix 1.1.2.1 220 pnkfelix 1.1.2.1 private boolean conservative(NodeIter nodes) { 221 pnkfelix 1.1.2.1 int k = 0; 222 pnkfelix 1.1.2.1 while( nodes.hasNext() ){ 223 pnkfelix 1.1.2.1 Node n = nodes.next(); 224 pnkfelix 1.1.2.1 if (n.degree >= K) 225 pnkfelix 1.1.2.1 k++; 226 pnkfelix 1.1.2.1 } 227 pnkfelix 1.1.2.1 return k < K; 228 pnkfelix 1.1.2.1 } 229 pnkfelix 1.1.2.1 230 pnkfelix 1.1.2.1 231 pnkfelix 1.1.2.1 protected void assignColors() { 232 pnkfelix 1.1.2.1 while( !select_stack.isEmpty() ){ 233 pnkfelix 1.1.2.1 Node n = select_stack.pop(); 234 pnkfelix 1.1.2.1 ColorSet okColors = new ColorSet(K); 235 pnkfelix 1.1.2.1 for( NodeIter adj=n.neighbors.iter(); adj.hasNext(); ) { 236 pnkfelix 1.1.2.1 Node w = adj.next(); w = getAlias(w); 237 pnkfelix 1.1.2.1 if( w.isColored() || 238 pnkfelix 1.1.2.1 w.isPrecolored() ){ 239 pnkfelix 1.1.2.1 okColors.remove( w.color[0] ); 240 pnkfelix 1.1.2.1 } 241 pnkfelix 1.1.2.1 } 242 pnkfelix 1.1.2.1 // TODO: Add code here to handle assigning a color to more 243 pnkfelix 1.1.2.1 // than one node at once, ala Brigg's multigraphs... 244 pnkfelix 1.1.2.1 if( okColors.isEmpty() ){ 245 pnkfelix 1.1.2.1 spilled_nodes.add(n); 246 pnkfelix 1.1.2.1 } else { 247 pnkfelix 1.1.2.1 colored_nodes.add(n); 248 pnkfelix 1.1.2.1 n.color[0] = okColors.available(); 249 pnkfelix 1.1.2.1 } 250 pnkfelix 1.1.2.1 } 251 pnkfelix 1.1.2.1 252 pnkfelix 1.1.2.1 for( NodeIter ni=coalesced_nodes.iter(); ni.hasNext(); ){ 253 pnkfelix 1.1.2.1 Node n = ni.next(); 254 pnkfelix 1.1.2.1 n.color[0] = getAlias(n).color[0]; 255 pnkfelix 1.1.2.1 } 256 pnkfelix 1.1.2.1 } 257 pnkfelix 1.1.2.1 258 pnkfelix 1.1.2.1 protected void performFinalAssignment(Temp[] regs) { 259 pnkfelix 1.1.2.1 for(Iterator instrs=code.getElementsI(); instrs.hasNext();){ 260 pnkfelix 1.1.2.1 Instr inst = (Instr) instrs.next(); 261 pnkfelix 1.1.2.1 262 pnkfelix 1.1.2.1 263 pnkfelix 1.1.2.1 // FSK: we're looking at the real deal here, not the 264 pnkfelix 1.1.2.1 // abstract InstrGroupings 265 pnkfelix 1.1.2.1 Iterator refs = new CombineIterator 266 pnkfelix 1.1.2.1 // ( useCT(inst).iterator(), defCT(inst).iterator() ); 267 pnkfelix 1.1.2.1 ( inst.useC().iterator(), inst.defC().iterator() ); 268 pnkfelix 1.1.2.1 269 pnkfelix 1.1.2.1 270 pnkfelix 1.1.2.1 while( refs.hasNext() ){ 271 pnkfelix 1.1.2.1 Temp t = (Temp) refs.next(); 272 pnkfelix 1.1.2.1 if (isRegister(t)) continue; 273 pnkfelix 1.1.2.1 if (null == bbFact.getBlock 274 pnkfelix 1.1.2.1 (inst.getEntry( InstrGroup.AGGREGATE ))){ 275 pnkfelix 1.1.2.1 System.err.println 276 pnkfelix 1.1.2.1 ("WARNING: code believed to be unreachable emitted"); 277 pnkfelix 1.1.2.1 code.assignRegister 278 pnkfelix 1.1.2.1 (inst,t,(List)rfi().getRegAssignments(t).iterator().next()); 279 pnkfelix 1.1.2.1 } else { 280 pnkfelix 1.1.2.1 Web w = webFor(t, inst); 281 pnkfelix 1.1.2.1 List nodes = nodesFor( w ); 282 pnkfelix 1.1.2.1 List regList = toRegList( nodes, regs ); 283 cananian 1.3.2.1 assert ! regList.isEmpty(); 284 pnkfelix 1.1.2.1 code.assignRegister( inst, t, regList ); 285 pnkfelix 1.1.2.1 } 286 pnkfelix 1.1.2.1 } 287 pnkfelix 1.1.2.1 } 288 pnkfelix 1.1.2.1 289 pnkfelix 1.1.2.1 fixupSpillCode(); 290 pnkfelix 1.1.2.1 291 pnkfelix 1.1.2.1 } 292 pnkfelix 1.1.2.1 293 pnkfelix 1.1.2.1 /** REQUIRES: i.isMove() 294 pnkfelix 1.1.2.1 returns a Move corresponding to Instr i. 295 pnkfelix 1.1.2.1 */ 296 pnkfelix 1.1.2.1 private Move moveFor(Instr i) { 297 cananian 1.3.2.1 assert i.isMove(); 298 pnkfelix 1.1.2.1 299 pnkfelix 1.1.2.1 if( instrToMove.containsKey(i) ) { 300 cananian 1.6 return instrToMove.get(i); 301 pnkfelix 1.1.2.1 } else { 302 pnkfelix 1.1.2.1 // TODO: Fix to assign collections, not first elems! 303 cananian 1.3.2.1 assert defCN(i).size() == 1; 304 cananian 1.3.2.1 assert useCN(i).size() == 1; 305 pnkfelix 1.1.2.1 Node dst = (Node) defCN(i).iterator().next(); 306 pnkfelix 1.1.2.1 Node src = (Node) useCN(i).iterator().next(); 307 pnkfelix 1.1.2.1 Move m = new Move(i, dst, src); 308 pnkfelix 1.1.2.1 instrToMove.put(i, m); 309 pnkfelix 1.1.2.1 return m; 310 pnkfelix 1.1.2.1 } 311 pnkfelix 1.1.2.1 } 312 pnkfelix 1.1.2.1 313 pnkfelix 1.1.2.1 private List toRegList(List nodes, Temp[] colorToReg) { 314 pnkfelix 1.1.2.1 Temp[] regs = new Temp[nodes.size()]; 315 pnkfelix 1.1.2.1 for(int i=0; i<regs.length; i++) { 316 pnkfelix 1.1.2.1 Node n = (Node)nodes.get(i); 317 pnkfelix 1.1.2.1 if (! (0 <= n.color[0] && n.color[0] < colorToReg.length) ) { 318 pnkfelix 1.1.2.1 code.printPreallocatedCode(); 319 pnkfelix 1.1.2.1 // printAllColors(); 320 pnkfelix 1.1.2.1 System.out.println(); 321 pnkfelix 1.1.2.1 System.out.println("node:"+n+" history:"+n.nodeSet_history); 322 cananian 1.3.2.1 assert false : ("node:"+n+" should have valid color, not:"+n.color[0]); 323 pnkfelix 1.1.2.1 } 324 pnkfelix 1.1.2.1 regs[i] = colorToReg[ n.color[0] ]; 325 pnkfelix 1.1.2.1 } 326 pnkfelix 1.1.2.1 return Arrays.asList( regs ); 327 pnkfelix 1.1.2.1 } 328 pnkfelix 1.1.2.1 329 pnkfelix 1.1.2.1 private Collection instrIDs(final Collection instrs) { 330 pnkfelix 1.1.2.1 return new AbstractCollection() { 331 pnkfelix 1.1.2.1 public int size() { return instrs.size(); } 332 pnkfelix 1.1.2.1 public Iterator iterator() 333 pnkfelix 1.1.2.1 { return new FilterIterator 334 pnkfelix 1.1.2.1 (instrs.iterator(), new FilterIterator.Filter() 335 pnkfelix 1.1.2.1 { public Object map(Object o) 336 pnkfelix 1.1.2.1 { return new Integer(((Instr)o).getID()); }}); }}; 337 pnkfelix 1.1.2.1 } 338 pnkfelix 1.1.2.1 private void printAllColors() { 339 cananian 1.6 for(Web w : webToNodes.keySet()){ 340 pnkfelix 1.1.2.1 String accum = 341 pnkfelix 1.1.2.1 "Temp:"+w.temp+ 342 pnkfelix 1.1.2.1 " defs:"+instrIDs(w.defs)+ 343 pnkfelix 1.1.2.1 " uses:"+instrIDs(w.uses)+ 344 pnkfelix 1.1.2.1 " colors:["; 345 cananian 1.6 for(Iterator<Node> nI=webToNodes.get(w).iterator(); nI.hasNext();){ 346 cananian 1.6 Node node = nI.next(); 347 pnkfelix 1.1.2.1 for(int i=0; i<node.color.length; i++) { 348 pnkfelix 1.1.2.1 accum += node.color[i] + ":"; 349 pnkfelix 1.1.2.1 } 350 pnkfelix 1.1.2.1 if (nI.hasNext()) { 351 pnkfelix 1.1.2.1 accum += ", "; 352 pnkfelix 1.1.2.1 } 353 pnkfelix 1.1.2.1 } 354 pnkfelix 1.1.2.1 accum += "]"; 355 pnkfelix 1.1.2.1 System.out.println(accum); 356 pnkfelix 1.1.2.1 } 357 pnkfelix 1.1.2.1 } 358 pnkfelix 1.1.2.1 359 pnkfelix 1.1.2.1 static class ColorSet { 360 pnkfelix 1.1.2.1 boolean[] colors; 361 pnkfelix 1.1.2.1 int size; 362 pnkfelix 1.1.2.1 public ColorSet(int numColors) { 363 pnkfelix 1.1.2.1 size = numColors; 364 pnkfelix 1.1.2.1 colors = new boolean[numColors]; 365 pnkfelix 1.1.2.1 for(int i=0; i < colors.length; i++) { 366 pnkfelix 1.1.2.1 colors[i] = true; 367 pnkfelix 1.1.2.1 } 368 pnkfelix 1.1.2.1 } 369 pnkfelix 1.1.2.1 /** requires: ! this.isEmpty() */ 370 pnkfelix 1.1.2.1 public int available() { 371 pnkfelix 1.1.2.1 for(int i=0; i<colors.length; i++) { 372 pnkfelix 1.1.2.1 if (colors[i]) 373 pnkfelix 1.1.2.1 return i; 374 pnkfelix 1.1.2.1 } 375 pnkfelix 1.1.2.1 throw new RuntimeException(); 376 pnkfelix 1.1.2.1 } 377 pnkfelix 1.1.2.1 public void remove(int color) { 378 pnkfelix 1.1.2.1 if (color < colors.length) { 379 pnkfelix 1.1.2.1 if ( colors[ color ] ) 380 pnkfelix 1.1.2.1 size--; 381 pnkfelix 1.1.2.1 colors[ color ] = false; 382 pnkfelix 1.1.2.1 } else { 383 pnkfelix 1.1.2.1 // removing an unused register-only color; NOP 384 pnkfelix 1.1.2.1 } 385 pnkfelix 1.1.2.1 } 386 pnkfelix 1.1.2.1 public boolean isEmpty() { return size == 0; } 387 pnkfelix 1.1.2.1 } 388 pnkfelix 1.1.2.1 389 cananian 1.2 }