1 kkz 1.1 // WriteBarrierInserter.java, created Wed Jun 19 16:47:07 2002 by kkz 2 kkz 1.1 // Copyright (C) 2000 Karen Zee <kkz@tmi.lcs.mit.edu> 3 kkz 1.1 // Licensed under the terms of the GNU GPL; see COPYING for details. 4 kkz 1.1 package harpoon.Analysis.PreciseGC; 5 kkz 1.1 6 kkz 1.1 import harpoon.ClassFile.HClass; 7 kkz 1.1 import harpoon.ClassFile.HCode; 8 kkz 1.1 import harpoon.ClassFile.HCodeAndMaps; 9 kkz 1.1 import harpoon.ClassFile.HCodeFactory; 10 kkz 1.1 import harpoon.ClassFile.HMethod; 11 kkz 1.1 import harpoon.ClassFile.Linker; 12 kkz 1.1 import harpoon.IR.Quads.ASET; 13 kkz 1.1 import harpoon.IR.Quads.CALL; 14 kkz 1.1 import harpoon.IR.Quads.Code; 15 kkz 1.1 import harpoon.IR.Quads.CONST; 16 kkz 1.1 import harpoon.IR.Quads.Code; 17 kkz 1.1 import harpoon.IR.Quads.Edge; 18 kkz 1.1 import harpoon.IR.Quads.FOOTER; 19 kkz 1.1 import harpoon.IR.Quads.HEADER; 20 kkz 1.1 import harpoon.IR.Quads.Quad; 21 kkz 1.1 import harpoon.IR.Quads.QuadFactory; 22 kkz 1.1 import harpoon.IR.Quads.QuadVisitor; 23 kkz 1.1 import harpoon.IR.Quads.SET; 24 kkz 1.1 import harpoon.IR.Quads.THROW; 25 kkz 1.1 import harpoon.IR.Quads.Code; 26 kkz 1.1 import harpoon.Temp.Temp; 27 kkz 1.1 import harpoon.Temp.TempFactory; 28 kkz 1.1 29 kkz 1.1 import java.util.Collections; 30 kkz 1.1 import java.util.Map; 31 kkz 1.1 import java.util.Set; 32 kkz 1.1 33 kkz 1.1 /** 34 kkz 1.1 * <code>WriteBarrierInserter</code> takes code in Quad form and inserts 35 kkz 1.1 * write barriers for generational garbage collection. Write barriers are 36 kkz 1.1 * inserted before <code>SET</code>s of non-static <code>Object</code> and 37 kkz 1.1 * <code>ASET<code>s of <code>Object</code> arrays. 38 kkz 1.1 * 39 kkz 1.1 * The write barrier used is a call to a native implementation that may be 40 kkz 1.1 * replaced in later passes with a more efficient implementation. 41 kkz 1.1 * 42 kkz 1.1 * @author Karen Zee <kkz@tmi.lcs.mit.edu> 43 kkz 1.1 * @version $Id: WriteBarrierInserter.java,v 1.1 2002/06/25 18:16:22 kkz Exp $ 44 kkz 1.1 */ 45 kkz 1.1 public class WriteBarrierInserter extends 46 kkz 1.1 harpoon.Analysis.Transformation.MethodMutator { 47 kkz 1.1 private final HClass JLRF; 48 kkz 1.1 private final HMethod arrayWB; 49 kkz 1.1 private final HMethod fieldWB; 50 kkz 1.1 private final WriteBarrierAnalysis wba; 51 kkz 1.1 52 kkz 1.1 /** Creates a <code>WriteBarrierInserter</code>. */ 53 kkz 1.1 public WriteBarrierInserter(HCodeFactory parent, Linker linker, 54 kkz 1.1 WriteBarrierAnalysis wba) { 55 kkz 1.1 super(parent); 56 kkz 1.1 this.wba = wba; 57 kkz 1.1 HClass WBC = linker.forName("harpoon.Runtime.PreciseGC.WriteBarrier"); 58 kkz 1.1 HClass JLO = linker.forName("java.lang.Object"); 59 kkz 1.1 this.JLRF = linker.forName("java.lang.reflect.Field"); 60 kkz 1.1 this.arrayWB = WBC.getMethod("asc", new HClass[] 61 kkz 1.1 { JLO, HClass.Int, JLO, HClass.Int }); 62 kkz 1.1 this.fieldWB = WBC.getMethod("fsc", new HClass[] 63 kkz 1.1 { JLO, JLRF, JLO, HClass.Int }); 64 kkz 1.1 } 65 kkz 1.1 66 kkz 1.1 /** Creates a <code>WriteBarrierInserter</code> using a default 67 kkz 1.1 * no-analysis <code>WriteBarrierAnalysis</code>. 68 kkz 1.1 */ 69 kkz 1.1 public WriteBarrierInserter(HCodeFactory parent, Linker linker) { 70 kkz 1.1 this(parent, linker, DefaultWriteBarrierAnalysis.SINGLETON); 71 kkz 1.1 } 72 kkz 1.1 73 kkz 1.1 protected HCode mutateHCode(HCodeAndMaps input) { 74 kkz 1.1 Code hc = (Code) input.hcode(); 75 kkz 1.1 // we should not have to update derivation information 76 kkz 1.1 assert hc.getDerivation() == null: 77 kkz 1.1 "WriteBarrierInserter does not handle derivation information"; 78 kkz 1.1 HEADER header = (HEADER) hc.getRootElement(); 79 kkz 1.1 FOOTER footer = (FOOTER) header.footer(); 80 kkz 1.1 Set ignore = wba.getIgnoreSet(hc); 81 kkz 1.1 QuadVisitor qv = new WriteBarrierInserterVisitor 82 kkz 1.1 (footer, ignore, input.ancestorElementMap()); 83 kkz 1.1 // we put all elements in array to avoid screwing up 84 kkz 1.1 // the iterator as we mutate the quad graph in-place. 85 kkz 1.1 Quad[] allquads = (Quad[]) hc.getElements(); 86 kkz 1.1 for(int i = 0; i < allquads.length; i++) 87 kkz 1.1 allquads[i].accept(qv); 88 kkz 1.1 return hc; 89 kkz 1.1 } 90 kkz 1.1 91 kkz 1.1 private class WriteBarrierInserterVisitor extends QuadVisitor { 92 kkz 1.1 private FOOTER footer; 93 kkz 1.1 private final Set ignore; 94 kkz 1.1 private final Map quadM; 95 kkz 1.1 96 kkz 1.1 /** Creates a <code>WriteBarrierInserterVisitor</code>. */ 97 kkz 1.1 WriteBarrierInserterVisitor(FOOTER footer, Set ignore, Map quadM) { 98 kkz 1.1 this.footer = footer; 99 kkz 1.1 this.ignore = ignore; 100 kkz 1.1 this.quadM = quadM; 101 kkz 1.1 } 102 kkz 1.1 103 kkz 1.1 public void visit(Quad q) { /* do nothing */ } 104 kkz 1.1 105 kkz 1.1 /* insert write barrier before ASET, if needed. */ 106 kkz 1.1 public void visit(ASET q) { 107 kkz 1.1 // we are interested only in ASETs of arrays 108 kkz 1.1 // containing pointers not found in ignore 109 kkz 1.1 if (q.type().isPrimitive()) return; 110 kkz 1.1 if (ignore.contains(quadM.get(q))) return; 111 kkz 1.1 QuadFactory qf = (QuadFactory) q.getFactory(); 112 kkz 1.1 TempFactory tf = qf.tempFactory(); 113 kkz 1.1 // create needed Temps 114 kkz 1.1 Temp retex = new Temp(tf, "wbex"); 115 kkz 1.1 Temp id = new Temp(tf, "wbid"); 116 kkz 1.1 // create needed Quads 117 kkz 1.1 CONST idC = new CONST(qf, q, id, new Integer(0), HClass.Int); 118 kkz 1.1 CALL call = new CALL(qf, q, arrayWB, new Temp[] 119 kkz 1.1 { q.objectref(), q.index(), q.src(), id }, 120 kkz 1.1 null, retex, false, false, new Temp[0]); 121 kkz 1.1 THROW thr = new THROW(qf, q, retex); 122 kkz 1.1 // add CONST and CALL before ASET 123 kkz 1.1 splice(idC, q.prevEdge(0)); 124 kkz 1.1 splice(call, q.prevEdge(0)); 125 kkz 1.1 // add THROW after CALL 126 kkz 1.1 Quad.addEdge(call, 1, thr, 0); 127 kkz 1.1 footer = footer.attach(thr, 0); 128 kkz 1.1 } 129 kkz 1.1 130 kkz 1.1 /* inserts write barrier before SET, if needed. */ 131 kkz 1.1 public void visit(SET q) { 132 kkz 1.1 // we are interested only in SETs of non-static 133 kkz 1.1 // Object fields not found in ignore 134 kkz 1.1 if (q.isStatic()) return; 135 kkz 1.1 if (q.field().getType().isPrimitive()) return; 136 kkz 1.1 if (ignore.contains(quadM.get(q))) return; 137 kkz 1.1 QuadFactory qf = (QuadFactory)q.getFactory(); 138 kkz 1.1 TempFactory tf = qf.tempFactory(); 139 kkz 1.1 // create needed Temps 140 kkz 1.1 Temp field = new Temp(tf, "wbfield"); 141 kkz 1.1 Temp retex = new Temp(tf, "wbex"); 142 kkz 1.1 Temp id = new Temp(tf, "wbid"); 143 kkz 1.1 // create needed Quads 144 kkz 1.1 CONST idC = new CONST(qf, q, id, new Integer(0), HClass.Int); 145 kkz 1.1 CONST fieldC = new CONST(qf, q, field, q.field(), JLRF); 146 kkz 1.1 CALL call = new CALL(qf, q, fieldWB, new Temp[] 147 kkz 1.1 { q.objectref(), field, q.src(), id }, 148 kkz 1.1 null, retex, false, false, new Temp[0]); 149 kkz 1.1 THROW thr = new THROW(qf, q, retex); 150 kkz 1.1 // add CONSTs and CALL before SET 151 kkz 1.1 splice(idC, q.prevEdge(0)); 152 kkz 1.1 splice(fieldC, q.prevEdge(0)); 153 kkz 1.1 splice(call, q.prevEdge(0)); 154 kkz 1.1 // add THROW after CALL 155 kkz 1.1 Quad.addEdge(call, 1, thr, 0); 156 kkz 1.1 footer = footer.attach(thr, 0); 157 kkz 1.1 } 158 kkz 1.1 159 kkz 1.1 /* helper method inserts the given Quad on the given Edge. */ 160 kkz 1.1 private void splice(Quad q, Edge e) { 161 kkz 1.1 Quad.addEdge((Quad) e.from(), e.which_succ(), q, 0); 162 kkz 1.1 Quad.addEdge(q, 0, (Quad) e.to(), e.which_pred()); 163 kkz 1.1 } 164 kkz 1.1 } 165 kkz 1.1 166 kkz 1.1 /** A <code>WriteBarrierAnalysis</code> maps <code>Code</code>s 167 kkz 1.1 * to <code>Set</code>s of Quads for which write barriers have 168 kkz 1.1 * been deemed unnecessary. 169 kkz 1.1 */ 170 kkz 1.1 public interface WriteBarrierAnalysis { 171 kkz 1.1 172 kkz 1.1 /** returns a <code>Set</code> of <code>Quad</code>s for 173 kkz 1.1 * the given <code>Code</code> for which write barriers 174 kkz 1.1 * are not required. 175 kkz 1.1 */ 176 kkz 1.1 public Set getIgnoreSet(Code hc); 177 kkz 1.1 } 178 kkz 1.1 179 kkz 1.1 /** <code>DefaultWriteBarrierAnalysis</code> returns a no- 180 kkz 1.1 * analysis <code>WriteBarrierAnalysis</code> Object that 181 kkz 1.1 * assumes write barriers are needed for all SET and ASETs 182 kkz 1.1 * of object fields. 183 kkz 1.1 */ 184 kkz 1.1 public static class DefaultWriteBarrierAnalysis implements 185 kkz 1.1 WriteBarrierAnalysis { 186 kkz 1.1 187 kkz 1.1 /** A static instance of the singleton 188 kkz 1.1 * <code>DefaultWriteBarrierAnalysis</code>. 189 kkz 1.1 */ 190 kkz 1.1 public static final WriteBarrierAnalysis SINGLETON = 191 kkz 1.1 new DefaultWriteBarrierAnalysis(); 192 kkz 1.1 193 kkz 1.1 private DefaultWriteBarrierAnalysis() { } 194 kkz 1.1 195 kkz 1.1 /** returns the empty <code>Set</code> for all <code>Code<code>s. 196 kkz 1.1 */ 197 kkz 1.1 public Set getIgnoreSet(Code hc) { 198 kkz 1.1 return Collections.EMPTY_SET; 199 kkz 1.1 } 200 kkz 1.1 } 201 kkz 1.1 } 202 kkz 1.1