1 kkz 1.1.2.1 // WriteBarrierTreePass.java, created Tue Aug 21 20:20:44 2001 by kkz 2 kkz 1.1.2.1 // Copyright (C) 2000 Karen Zee <kkz@tmi.lcs.mit.edu> 3 kkz 1.1.2.1 // Licensed under the terms of the GNU GPL; see COPYING for details. 4 kkz 1.1.2.1 package harpoon.Analysis.PreciseGC; 5 kkz 1.1.2.1 6 kkz 1.1.2.1 import harpoon.Analysis.ClassHierarchy; 7 kkz 1.1.2.1 import harpoon.Analysis.Tree.Canonicalize; 8 kkz 1.1.2.1 import harpoon.Backend.Generic.Frame; 9 kkz 1.1.2.1 import harpoon.Backend.Generic.Runtime; 10 kkz 1.1.2.1 import harpoon.Backend.Generic.Runtime.TreeBuilder; 11 kkz 1.1.2.1 import harpoon.Backend.Maps.NameMap; 12 kkz 1.1.2.1 import harpoon.ClassFile.HClass; 13 kkz 1.1.2.1 import harpoon.ClassFile.HCode; 14 kkz 1.1.2.1 import harpoon.ClassFile.HCodeElement; 15 kkz 1.1.2.1 import harpoon.ClassFile.HCodeFactory; 16 kkz 1.1.2.1 import harpoon.ClassFile.HField; 17 kkz 1.1.2.1 import harpoon.ClassFile.HMethod; 18 kkz 1.1.2.1 import harpoon.ClassFile.Linker; 19 kkz 1.1.2.1 import harpoon.IR.Properties.CFGrapher; 20 kkz 1.1.2.1 import harpoon.IR.Tree.BINOP; 21 kkz 1.1.2.1 import harpoon.IR.Tree.Bop; 22 kkz 1.1.2.1 import harpoon.IR.Tree.CALL; 23 kkz 1.1.2.1 import harpoon.IR.Tree.CanonicalTreeCode; 24 kkz 1.1.2.1 import harpoon.IR.Tree.CONST; 25 kkz 1.1.2.1 import harpoon.IR.Tree.DATUM; 26 kkz 1.1.2.1 import harpoon.IR.Tree.DerivationGenerator; 27 kkz 1.1.2.1 import harpoon.IR.Tree.Exp; 28 kkz 1.1.2.1 import harpoon.IR.Tree.ExpList; 29 kkz 1.1.2.1 import harpoon.IR.Tree.LABEL; 30 kkz 1.1.2.1 import harpoon.IR.Tree.METHOD; 31 kkz 1.1.2.1 import harpoon.IR.Tree.NAME; 32 kkz 1.1.2.1 import harpoon.IR.Tree.NATIVECALL; 33 kkz 1.1.2.1 import harpoon.IR.Tree.Print; 34 kkz 1.1.2.1 import harpoon.IR.Tree.SEGMENT; 35 kkz 1.1.2.1 import harpoon.IR.Tree.SEQ; 36 kkz 1.1.2.1 import harpoon.IR.Tree.Stm; 37 kkz 1.1.2.1 import harpoon.IR.Tree.Tree; 38 kkz 1.1.2.1 import harpoon.IR.Tree.TreeFactory; 39 kkz 1.1.2.1 import harpoon.IR.Tree.TEMP; 40 kkz 1.1.2.1 import harpoon.IR.Tree.Translation; 41 kkz 1.1.2.1 import harpoon.IR.Tree.Type; 42 kkz 1.1.2.1 import harpoon.Temp.Label; 43 kkz 1.1.2.1 import harpoon.Util.Util; 44 kkz 1.1.2.1 45 kkz 1.1.2.1 import java.util.Arrays; 46 kkz 1.1.2.1 import java.util.HashMap; 47 kkz 1.1.2.1 import java.util.Iterator; 48 kkz 1.1.2.1 import java.util.List; 49 kkz 1.1.2.1 import java.util.Map; 50 kkz 1.1.2.1 /** 51 kkz 1.1.2.1 * <code>WriteBarrierTreePass</code> performs some low-level 52 kkz 1.1.2.1 * transformations to the output of <code>WriteBarrierQuadPass</code> 53 kkz 1.1.2.1 * which cannot be done in the quad form on which 54 kkz 1.1.2.1 * <code>WriteBarrierQuadPass</code> operates. 55 kkz 1.1.2.1 * <code>>WriteBarrierTreePass</code> works on tree form. 56 kkz 1.1.2.1 * <p> 57 kkz 1.1.2.1 * This pass is invoked by 58 kkz 1.1.2.1 * <code>WriteBarrierQuadPass.treeCodeFactory()</code>. 59 kkz 1.1.2.1 * 60 kkz 1.1.2.1 * 61 kkz 1.1.2.1 * @author Karen Zee <kkz@tmi.lcs.mit.edu> 62 cananian 1.6 * @version $Id: WriteBarrierTreePass.java,v 1.6 2003/03/11 19:15:42 cananian Exp $ 63 kkz 1.1.2.1 */ 64 kkz 1.1.2.1 public abstract class WriteBarrierTreePass extends 65 kkz 1.1.2.1 harpoon.Analysis.Tree.Simplification { 66 kkz 1.1.2.1 67 kkz 1.1.2.1 // hide constructor 68 kkz 1.1.2.1 private WriteBarrierTreePass() { } 69 kkz 1.1.2.1 70 kkz 1.1.2.1 /** Code factory for applying <code>WriteBarrierTreePass</code> 71 kkz 1.1.2.1 * to a canonical tree. Clones the tree before doing 72 kkz 1.1.2.1 * transformation in-place. */ 73 kkz 1.5 static public HCodeFactory codeFactory(final HCodeFactory parent, 74 kkz 1.5 final Frame f, 75 kkz 1.5 final ClassHierarchy ch, 76 kkz 1.5 final Linker linker) { 77 kkz 1.5 HClass WBC = linker.forName("harpoon.Runtime.PreciseGC.WriteBarrier"); 78 kkz 1.5 HClass JLO = linker.forName("java.lang.Object"); 79 kkz 1.5 HClass JLRF = linker.forName("java.lang.reflect.Field"); 80 kkz 1.5 final HMethod arrayHM = WBC.getMethod("asc", new HClass[] 81 kkz 1.5 {JLO,HClass.Int,JLO,HClass.Int}); 82 kkz 1.5 final HMethod fieldHM = WBC.getMethod("fsc", new HClass[] 83 kkz 1.5 {JLO,JLRF,JLO,HClass.Int}); 84 cananian 1.3.2.1 assert parent.getCodeName().equals(CanonicalTreeCode.codename); 85 kkz 1.1.2.1 return Canonicalize.codeFactory(new HCodeFactory() { 86 kkz 1.1.2.1 public HCode convert(HMethod m) { 87 kkz 1.1.2.1 HCode hc = parent.convert(m); 88 kkz 1.1.2.1 if (hc!=null) { 89 kkz 1.1.2.1 harpoon.IR.Tree.Code code = (harpoon.IR.Tree.Code) hc; 90 kkz 1.1.2.1 // clone code... 91 kkz 1.1.2.1 code = (harpoon.IR.Tree.Code) code.clone(m).hcode(); 92 kkz 1.1.2.1 DerivationGenerator dg = null; 93 kkz 1.1.2.1 try { 94 kkz 1.1.2.1 dg = (DerivationGenerator) code.getTreeDerivation(); 95 kkz 1.1.2.1 } catch (ClassCastException ex) { /* i guess not */ } 96 kkz 1.1.2.1 // ...do analysis and modify cloned code in-place. 97 kkz 1.1.2.1 simplify((Stm)code.getRootElement(), dg, 98 kkz 1.1.2.1 HCE_RULES(f, ch, arrayHM, fieldHM)); 99 kkz 1.1.2.1 hc = code; 100 kkz 1.1.2.1 } 101 kkz 1.1.2.1 return hc; 102 kkz 1.1.2.1 } 103 kkz 1.1.2.1 public String getCodeName() { return parent.getCodeName(); } 104 kkz 1.1.2.1 public void clear(HMethod m) { parent.clear(m); } 105 kkz 1.1.2.1 }); 106 kkz 1.1.2.1 } 107 kkz 1.1.2.1 108 cananian 1.6 private static List<Rule> HCE_RULES(final Frame f, 109 kkz 1.1.2.1 final ClassHierarchy ch, 110 kkz 1.1.2.1 final HMethod arrayHM, 111 kkz 1.1.2.1 final HMethod fieldHM) { 112 kkz 1.1.2.1 final NameMap nm = f.getRuntime().getNameMap(); 113 kkz 1.1.2.1 final Label LarrayHM = nm.label(arrayHM); 114 kkz 1.1.2.1 final Label LfieldHM = nm.label(fieldHM); 115 cananian 1.6 final Map<Label,HField> fieldMap = new HashMap<Label,HField>(); 116 cananian 1.6 for(Iterator<HClass> it = ch.classes().iterator(); it.hasNext(); ) { 117 cananian 1.6 HField[] fields = it.next().getFields(); 118 kkz 1.1.2.1 for(int i = 0; i < fields.length; i++) { 119 kkz 1.1.2.1 fieldMap.put(nm.label(fields[i], "obj"), fields[i]); 120 kkz 1.1.2.1 } 121 kkz 1.1.2.1 } 122 kkz 1.1.2.1 final Label cfunc = 123 kkz 1.1.2.1 new Label(nm.c_function_name("generational_write_barrier")); 124 kkz 1.1.2.1 // now make rules 125 kkz 1.1.2.1 return Arrays.asList(new Rule[] { 126 kkz 1.1.2.1 new Rule("replaceArraySC") { 127 kkz 1.1.2.1 public boolean match(Stm stm) { 128 kkz 1.1.2.1 if (!contains(_KIND(stm), _CALL)) return false; 129 kkz 1.1.2.1 CALL call = (CALL) stm; 130 kkz 1.1.2.1 if (!contains(_KIND(call.getFunc()), _NAME)) return false; 131 kkz 1.1.2.1 return ((NAME) call.getFunc()).label.equals(LarrayHM); 132 kkz 1.1.2.1 } 133 kkz 1.1.2.1 public Stm apply(TreeFactory tf, Stm stm, 134 kkz 1.1.2.1 DerivationGenerator dg) { 135 kkz 1.1.2.2 //System.out.println(Print.print(stm)); 136 kkz 1.1.2.1 Runtime runtime = tf.getFrame().getRuntime(); 137 kkz 1.1.2.1 TreeBuilder tb = runtime.getTreeBuilder(); 138 kkz 1.1.2.1 final NAME func = new NAME(tf, stm, cfunc); 139 kkz 1.1.2.1 if (dg != null) dg.putType(func, HClass.Void); 140 kkz 1.1.2.1 // extract arguments 141 kkz 1.1.2.1 ExpList explist = ((CALL) stm).getArgs(); 142 kkz 1.1.2.1 // first argument 143 kkz 1.1.2.1 TEMP objectref = (TEMP) explist.head; 144 kkz 1.1.2.1 explist = explist.tail; 145 kkz 1.1.2.2 // second argument is the array index 146 kkz 1.1.2.2 // after constant propagation, this 147 kkz 1.1.2.2 // may be either a TEMP or a CONST 148 kkz 1.1.2.2 Exp index = explist.head; 149 kkz 1.1.2.1 // ignore last 2 arguments 150 kkz 1.1.2.1 explist = explist.tail.tail; 151 kkz 1.1.2.1 // no more arguments 152 cananian 1.3.2.1 assert explist.tail == null; 153 kkz 1.1.2.1 // get array type from derivation 154 cananian 1.3.2.1 assert dg != null; 155 kkz 1.1.2.1 HClass arrayType = dg.typeMap(objectref); 156 cananian 1.3.2.1 assert arrayType != null; 157 kkz 1.1.2.1 return new NATIVECALL 158 kkz 1.1.2.1 (tf, stm, null, func, new ExpList 159 kkz 1.1.2.1 (new BINOP 160 kkz 1.1.2.1 (tf, stm, Type.POINTER, Bop.ADD, 161 kkz 1.1.2.1 tb.arrayBase 162 kkz 1.1.2.1 (tf, stm, dg, new Translation.Ex 163 kkz 1.1.2.1 (objectref)).unEx(tf), 164 kkz 1.1.2.1 tb.arrayOffset 165 kkz 1.1.2.1 (tf, stm, dg, arrayType, new Translation.Ex 166 kkz 1.1.2.1 (index)).unEx(tf)), 167 kkz 1.1.2.1 null)); 168 kkz 1.1.2.1 } 169 kkz 1.1.2.1 }, 170 kkz 1.1.2.1 new Rule("replaceFieldSC") { 171 kkz 1.1.2.1 public boolean match(Stm stm) { 172 kkz 1.1.2.1 if (!contains(_KIND(stm), _CALL)) return false; 173 kkz 1.1.2.1 CALL call = (CALL) stm; 174 kkz 1.1.2.1 if (!contains(_KIND(call.getFunc()), _NAME)) return false; 175 kkz 1.1.2.1 return ((NAME) call.getFunc()).label.equals(LfieldHM); 176 kkz 1.1.2.1 } 177 kkz 1.1.2.1 public Stm apply(TreeFactory tf, Stm stm, 178 kkz 1.1.2.1 DerivationGenerator dg) { 179 kkz 1.1.2.1 Runtime runtime = tf.getFrame().getRuntime(); 180 kkz 1.1.2.1 TreeBuilder tb = runtime.getTreeBuilder(); 181 kkz 1.1.2.1 final NAME func = 182 kkz 1.1.2.1 new NAME(tf, stm, 183 kkz 1.1.2.1 new Label(runtime.getNameMap().c_function_name 184 kkz 1.1.2.1 ("generational_write_barrier"))); 185 kkz 1.1.2.1 if (dg != null) dg.putType(func, HClass.Void); 186 kkz 1.1.2.1 // extract arguments 187 kkz 1.1.2.1 ExpList explist = ((CALL) stm).getArgs(); 188 kkz 1.1.2.1 // first argument 189 kkz 1.1.2.1 TEMP objectref = (TEMP) explist.head; 190 kkz 1.1.2.1 explist = explist.tail; 191 kkz 1.1.2.1 // second argument 192 kkz 1.1.2.1 NAME name = (NAME) explist.head; 193 kkz 1.1.2.1 // ignore last 2 arguments 194 kkz 1.1.2.1 explist = explist.tail.tail; 195 kkz 1.1.2.1 // no more arguments 196 cananian 1.3.2.1 assert explist.tail == null; 197 kkz 1.1.2.1 // get HField from fieldMap 198 cananian 1.6 HField field = fieldMap.get(name.label); 199 cananian 1.3.2.1 assert field != null; 200 kkz 1.1.2.1 return new NATIVECALL 201 kkz 1.1.2.1 (tf, stm, null, func, new ExpList 202 kkz 1.1.2.1 (new BINOP 203 kkz 1.1.2.1 (tf, stm, Type.POINTER, Bop.ADD, tb.fieldBase 204 kkz 1.1.2.1 (tf, stm, dg, new Translation.Ex 205 kkz 1.1.2.1 (objectref)).unEx(tf), tb.fieldOffset 206 kkz 1.1.2.1 (tf, stm, dg, field).unEx(tf)), 207 kkz 1.1.2.1 null)); 208 kkz 1.1.2.1 } 209 kkz 1.1.2.1 } 210 kkz 1.1.2.1 }); 211 kkz 1.1.2.1 } 212 kkz 1.1.2.1 } 213 cananian 1.2