2 import java.util.Hashtable;
4 import java.util.HashSet;
5 import java.util.Stack;
6 import java.util.Iterator;
7 import IR.ClassDescriptor;
11 import IR.MethodDescriptor;
13 public class Inliner {
14 public static void inlineAtomic(State state, TypeUtil typeutil, FlatMethod fm, int depth) {
15 Stack<FlatNode> toprocess=new Stack<FlatNode>();
16 HashSet<FlatNode> visited=new HashSet<FlatNode>();
17 Hashtable<FlatNode, Integer> atomictable=new Hashtable<FlatNode, Integer>();
18 HashSet<FlatNode> atomicset=new HashSet<FlatNode>();
22 atomictable.put(fm, new Integer(0));
23 while(!toprocess.isEmpty()) {
24 FlatNode fn=toprocess.pop();
25 int atomicval=atomictable.get(fn).intValue();
26 if (fn.kind()==FKind.FlatAtomicEnterNode)
28 else if(fn.kind()==FKind.FlatAtomicExitNode)
30 for(int i=0;i<fn.numNext();i++) {
31 FlatNode fnext=fn.getNext(i);
32 if (!visited.contains(fnext)) {
33 atomictable.put(fnext, new Integer(atomicval));
37 toprocess.push(fnext);
41 //make depth 0 be depth infinity
44 recursive(state, typeutil, atomicset, depth, new Stack<MethodDescriptor>());
48 public static void recursive(State state, TypeUtil typeutil, Set<FlatNode> fnset, int depth, Stack<MethodDescriptor> toexclude) {
49 for(Iterator<FlatNode> fnit=fnset.iterator();fnit.hasNext();) {
50 FlatNode fn=fnit.next();
51 if (fn.kind()==FKind.FlatCall) {
52 FlatCall fc=(FlatCall)fn;
53 MethodDescriptor md=fc.getMethod();
55 if (toexclude.contains(md))
58 Set<FlatNode> inlinefnset=inline(fc, typeutil, state);
61 recursive(state, typeutil, inlinefnset, depth-1, toexclude);
67 public static Set<FlatNode> inline(FlatCall fc, TypeUtil typeutil, State state) {
68 MethodDescriptor md=fc.getMethod();
69 /* Do we need to do virtual dispatch? */
70 if (md.isStatic()||md.getReturnType()==null||singleCall(typeutil, fc.getThis().getType().getClassDesc(),md)) {
71 //just reuse temps...makes problem with inlining recursion
72 TempMap clonemap=new TempMap();
73 Hashtable<FlatNode, FlatNode> flatmap=new Hashtable<FlatNode, FlatNode>();
74 TempDescriptor rettmp=fc.getReturnTemp();
75 FlatNode aftercallnode=fc.getNext(0);
76 aftercallnode.removePrev(fc);
78 FlatMethod fm=state.getMethodFlat(md);
80 Set<FlatNode> nodeset=fm.getNodeSet();
83 HashSet<FlatNode> newnodes=new HashSet<FlatNode>();
86 for(Iterator<FlatNode> fnit=nodeset.iterator();fnit.hasNext();) {
87 FlatNode fn=fnit.next();
88 if (fn.kind()==FKind.FlatReturnNode) {
89 //Convert FlatReturn node into move
90 TempDescriptor rtmp=((FlatReturnNode)fn).getReturnTemp();
92 FlatOpNode fon=new FlatOpNode(rettmp, rtmp, null, new Operation(Operation.ASSIGN));
95 flatmap.put(fn, aftercallnode);
98 FlatNode clone=fn.clone(clonemap);
100 flatmap.put(fn,clone);
103 //Build the move chain
104 FlatNode first=new FlatNop();;
109 if (fc.getThis()!=null) {
110 FlatOpNode fon=new FlatOpNode(fm.getParameter(i++), fc.getThis(), null, new Operation(Operation.ASSIGN));
115 for(int j=0;j<fc.numArgs();i++,j++) {
116 FlatOpNode fon=new FlatOpNode(fm.getParameter(i), fc.getArg(j), null, new Operation(Operation.ASSIGN));
124 for(Iterator<FlatNode> fnit=nodeset.iterator();fnit.hasNext();) {
125 FlatNode fn=fnit.next();
126 FlatNode fnclone=flatmap.get(fn);
128 if (fn.kind()!=FKind.FlatReturnNode) {
129 //don't build old edges out of a flat return node
130 for(int i=0;i<fn.numNext();i++) {
131 FlatNode fnnext=fn.getNext(i);
132 FlatNode fnnextclone=flatmap.get(fnnext);
133 fnclone.setNewNext(i, fnnextclone);
136 if (fnclone!=aftercallnode)
137 fnclone.addNext(aftercallnode);
141 //Add edges to beginning of move chain
142 for(int i=0;i<fc.numPrev();i++) {
143 FlatNode fnprev=fc.getPrev(i);
144 for(int j=0;j<fnprev.numNext();j++) {
145 if (fnprev.getNext(j)==fc) {
146 //doing setnewnext to avoid changing the node we are
148 fnprev.setNewNext(j, first);
154 //Add in the edge from move chain to callee
155 last.addNext(flatmap.get(fm.getNext(0)));
160 private static boolean singleCall(TypeUtil typeutil, ClassDescriptor thiscd, MethodDescriptor md) {
161 Set subclasses=typeutil.getSubClasses(thiscd);
162 if (subclasses==null)
164 for(Iterator classit=subclasses.iterator(); classit.hasNext();) {
165 ClassDescriptor cd=(ClassDescriptor)classit.next();
166 Set possiblematches=cd.getMethodTable().getSet(md.getSymbol());
167 for(Iterator matchit=possiblematches.iterator(); matchit.hasNext();) {
168 MethodDescriptor matchmd=(MethodDescriptor)matchit.next();
169 if (md.matches(matchmd))