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 if (atomicset.isEmpty())
46 System.out.println("Inlining methods into "+fm.getMethod());
47 recursive(state, typeutil, atomicset, depth, new Stack<MethodDescriptor>());
51 public static void recursive(State state, TypeUtil typeutil, Set<FlatNode> fnset, int depth, Stack<MethodDescriptor> toexclude) {
52 for(Iterator<FlatNode> fnit=fnset.iterator();fnit.hasNext();) {
53 FlatNode fn=fnit.next();
54 if (fn.kind()==FKind.FlatCall) {
55 FlatCall fc=(FlatCall)fn;
56 MethodDescriptor md=fc.getMethod();
58 if (toexclude.contains(md))
61 Set<FlatNode> inlinefnset=inline(fc, typeutil, state);
62 if (inlinefnset==null)
67 recursive(state, typeutil, inlinefnset, depth-1, toexclude);
73 public static Set<FlatNode> inline(FlatCall fc, TypeUtil typeutil, State state) {
74 MethodDescriptor md=fc.getMethod();
75 if (md.getModifiers().isNative())
78 /* Do we need to do virtual dispatch? */
79 if (md.isStatic()||md.getReturnType()==null||singleCall(typeutil, fc.getThis().getType().getClassDesc(),md)) {
80 //just reuse temps...makes problem with inlining recursion
81 TempMap clonemap=new TempMap();
82 Hashtable<FlatNode, FlatNode> flatmap=new Hashtable<FlatNode, FlatNode>();
83 TempDescriptor rettmp=fc.getReturnTemp();
84 FlatNode aftercallnode=fc.getNext(0);
85 aftercallnode.removePrev(fc);
86 System.out.println("Inlining: "+md);
88 FlatMethod fm=state.getMethodFlat(md);
90 Set<FlatNode> nodeset=fm.getNodeSet();
93 HashSet<FlatNode> newnodes=new HashSet<FlatNode>();
96 for(Iterator<FlatNode> fnit=nodeset.iterator();fnit.hasNext();) {
97 FlatNode fn=fnit.next();
98 if (fn.kind()==FKind.FlatReturnNode) {
99 //Convert FlatReturn node into move
100 TempDescriptor rtmp=((FlatReturnNode)fn).getReturnTemp();
102 FlatOpNode fon=new FlatOpNode(rettmp, rtmp, null, new Operation(Operation.ASSIGN));
103 flatmap.put(fn, fon);
105 flatmap.put(fn, aftercallnode);
108 FlatNode clone=fn.clone(clonemap);
110 flatmap.put(fn,clone);
113 //Build the move chain
114 FlatNode first=new FlatNop();;
119 if (fc.getThis()!=null) {
120 FlatOpNode fon=new FlatOpNode(fm.getParameter(i++), fc.getThis(), null, new Operation(Operation.ASSIGN));
125 for(int j=0;j<fc.numArgs();i++,j++) {
126 FlatOpNode fon=new FlatOpNode(fm.getParameter(i), fc.getArg(j), null, new Operation(Operation.ASSIGN));
134 for(Iterator<FlatNode> fnit=nodeset.iterator();fnit.hasNext();) {
135 FlatNode fn=fnit.next();
136 FlatNode fnclone=flatmap.get(fn);
138 if (fn.kind()!=FKind.FlatReturnNode) {
139 //don't build old edges out of a flat return node
140 for(int i=0;i<fn.numNext();i++) {
141 FlatNode fnnext=fn.getNext(i);
142 FlatNode fnnextclone=flatmap.get(fnnext);
143 fnclone.setNewNext(i, fnnextclone);
146 if (fnclone!=aftercallnode)
147 fnclone.addNext(aftercallnode);
151 //Add edges to beginning of move chain
152 for(int i=0;i<fc.numPrev();i++) {
153 FlatNode fnprev=fc.getPrev(i);
154 for(int j=0;j<fnprev.numNext();j++) {
155 if (fnprev.getNext(j)==fc) {
156 //doing setnewnext to avoid changing the node we are
158 fnprev.setNewNext(j, first);
164 //Add in the edge from move chain to callee
165 last.addNext(flatmap.get(fm.getNext(0)));
170 private static boolean singleCall(TypeUtil typeutil, ClassDescriptor thiscd, MethodDescriptor md) {
171 Set subclasses=typeutil.getSubClasses(thiscd);
172 if (subclasses==null)
174 for(Iterator classit=subclasses.iterator(); classit.hasNext();) {
175 ClassDescriptor cd=(ClassDescriptor)classit.next();
176 Set possiblematches=cd.getMethodTable().getSet(md.getSymbol());
177 for(Iterator matchit=possiblematches.iterator(); matchit.hasNext();) {
178 MethodDescriptor matchmd=(MethodDescriptor)matchit.next();
179 if (md.matches(matchmd))