From: jzhou Date: Fri, 4 Mar 2011 02:30:57 +0000 (+0000) Subject: Fix bugs for interfaces. \n\nFor methods declared in interfaces, there always need... X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=2ee44b1800a2a89d578a8440433c5f37ae204787;p=IRC.git Fix bugs for interfaces. \n\nFor methods declared in interfaces, there always need virtual dispatch.\n\n The other bug is that previously the method numbering strategy always start from 0 when numbering a class'es method. When there are no interfaces, all classes form a tree with Object as the root and the numbering works fine. But with interfaces, the inherit hierachy would no longer be a tree and there will have serious problems. #0 would be always assigned to some method of Object and every interfaces. If a Class implements any interfaces, it would have at least two methods with #0 and it would only be able to access one of it and lose the others. Also we need to make sure that each method of a interface should have a distinguished number so that when a class implements multiple interfaces, it would not lose access of any of the methods defined in the interfaces. So when numbering the methods in Virtual, we first numbering all the methods in the interfaces and give them a distinguished number. Then we numbering the classes and start from the following number. As interfaces could have methods with the same name, a method in a class could match multiple entries in its super interfaces/classes. We record all these entries in order to fill in the virtual table correctly --- diff --git a/Robust/src/ClassLibrary/Integer.java b/Robust/src/ClassLibrary/Integer.java index 74055276..3a8d4b06 100644 --- a/Robust/src/ClassLibrary/Integer.java +++ b/Robust/src/ClassLibrary/Integer.java @@ -109,4 +109,11 @@ public class Integer { return false; return true; } + + public int compareTo(Integer i) { + if (value == i.value) + return 0; + // Returns just -1 or 1 on inequality; doing math might overflow. + return value > i.value ? 1 : -1; + } } diff --git a/Robust/src/ClassLibrary/MGC/gnu/TreeMap.java b/Robust/src/ClassLibrary/MGC/gnu/TreeMap.java index 809e64fa..62a38418 100644 --- a/Robust/src/ClassLibrary/MGC/gnu/TreeMap.java +++ b/Robust/src/ClassLibrary/MGC/gnu/TreeMap.java @@ -412,6 +412,7 @@ public class TreeMap// extends AbstractMap */ public Object put(Object key, Object value) { + System.out.println("TreeMap.put() " + (String)root.key); TreeNode current = root; TreeNode parent = nil; int comparison = 0; @@ -449,6 +450,7 @@ public class TreeMap// extends AbstractMap // Rebalance after insert. insertFixup(n); + System.out.println("==== " + (String)root.key); return null; } @@ -766,13 +768,11 @@ public class TreeMap// extends AbstractMap final int compare(Object o1, Object o2) { if((o1 instanceof Integer) && (o2 instanceof Integer)) { - if(((Integer)o1).intValue() > ((Integer)o2).intValue()) { - return 1; - } else if(((Integer)o1).intValue() > ((Integer)o2).intValue()) { - return 0; - } else { - return -1; - } + return ((Integer)o1).compareTo((Integer)o2); + } else if((o1 instanceof Long) && (o2 instanceof Long)) { + return ((Long)o1).compareTo((Long)o2); + } else if((o1 instanceof String) && (o2 instanceof String)) { + return ((String)o1).compareTo((String)o2); } System.println("Compare non-int values in TreeMap.compare(Object, Object)"); return 0; @@ -1022,6 +1022,7 @@ public class TreeMap// extends AbstractMap */ final TreeNode lowestGreaterThan(Object key, boolean first, boolean equal) { + System.out.println("TreeMap.lowestGreaterThan(Object, boolean, boolean)() " + (String)key + " " + (String)root.key); if (key == nil) return first ? firstNode() : nil; @@ -1031,8 +1032,10 @@ public class TreeMap// extends AbstractMap while (current != nil) { + System.out.println("AAAA"); last = current; comparison = compare(key, current.key); + System.out.println(comparison); if (comparison > 0) current = current.right; else if (comparison < 0) diff --git a/Robust/src/ClassLibrary/MGC/gnu/TreeSubMap.java b/Robust/src/ClassLibrary/MGC/gnu/TreeSubMap.java index 4489e379..51a2089e 100644 --- a/Robust/src/ClassLibrary/MGC/gnu/TreeSubMap.java +++ b/Robust/src/ClassLibrary/MGC/gnu/TreeSubMap.java @@ -29,12 +29,16 @@ public final class TreeSubMap throw new /*IllegalArgument*/Exception("IllegalArgumentException: fromKey > toKey"); this.minKey = minKey; this.maxKey = maxKey; + System.out.println("TreeSubMap() " + (String)this.minKey + " " + (String)this.maxKey); } public int size() { + System.out.println("TreeSubMap.size() " + (String)this.minKey + " " + (String)this.maxKey); TreeNode node = map.lowestGreaterThan(minKey, true); TreeNode max = map.lowestGreaterThan(maxKey, false); + System.out.println((String)node.key); + System.out.println((String)max.key); int count = 0; while (node != max) { diff --git a/Robust/src/IR/Flat/BuildCode.java b/Robust/src/IR/Flat/BuildCode.java index 9760db04..95645565 100644 --- a/Robust/src/IR/Flat/BuildCode.java +++ b/Robust/src/IR/Flat/BuildCode.java @@ -911,20 +911,23 @@ public class BuildCode { protected void fillinRow(ClassDescriptor cd, MethodDescriptor[][] virtualtable, int rownum) { /* Get inherited methods */ - if (cd.getSuperDesc()!=null) - fillinRow(cd.getSuperDesc(), virtualtable, rownum); Iterator it_sifs = cd.getSuperInterfaces(); while(it_sifs.hasNext()) { ClassDescriptor superif = (ClassDescriptor)it_sifs.next(); fillinRow(superif, virtualtable, rownum); } + if (cd.getSuperDesc()!=null) + fillinRow(cd.getSuperDesc(), virtualtable, rownum); /* Override them with our methods */ for(Iterator it=cd.getMethods(); it.hasNext(); ) { MethodDescriptor md=(MethodDescriptor)it.next(); if (md.isStatic()||md.getReturnType()==null) continue; - int methodnum=virtualcalls.getMethodNumber(md); - virtualtable[rownum][methodnum]=md; + Vector numvec = virtualcalls.getMethodNumber(md); + for(int i = 0; i < numvec.size(); i++) { + int methodnum = numvec.elementAt(i).intValue(); + virtualtable[rownum][methodnum]=md; + } } } @@ -2375,7 +2378,7 @@ public class BuildCode { } - output.print("))virtualtable["+generateTemp(fm,fc.getThis())+"->type*"+maxcount+"+"+virtualcalls.getMethodNumber(md)+"])"); + output.print("))virtualtable["+generateTemp(fm,fc.getThis())+"->type*"+maxcount+"+"+virtualcalls.getMethodNumber(md).elementAt(0)+"])"); } output.print("("); @@ -2426,6 +2429,10 @@ public class BuildCode { } protected boolean singleCall(ClassDescriptor thiscd, MethodDescriptor md) { + if(thiscd.isInterface()) { + // for interfaces, always need virtual dispatch + return false; + } else { Set subclasses=typeutil.getSubClasses(thiscd); if (subclasses==null) return true; @@ -2438,6 +2445,7 @@ public class BuildCode { return false; } } + } return true; } diff --git a/Robust/src/IR/Virtual.java b/Robust/src/IR/Virtual.java index efcf2c2d..a46b6ad3 100644 --- a/Robust/src/IR/Virtual.java +++ b/Robust/src/IR/Virtual.java @@ -7,12 +7,15 @@ import Analysis.Locality.LocalityAnalysis; public class Virtual { State state; LocalityAnalysis locality; - Hashtable methodnumber; + Hashtable> methodnumber; Hashtable classmethodcount; Hashtable localitynumber; + + // for interfaces + int if_starts; - public int getMethodNumber(MethodDescriptor md) { - return methodnumber.get(md).intValue(); + public Vector getMethodNumber(MethodDescriptor md) { + return methodnumber.get(md); } public int getMethodCount(ClassDescriptor md) { @@ -26,16 +29,22 @@ public class Virtual { public Virtual(State state, LocalityAnalysis locality) { this.state=state; this.locality=locality; + this.if_starts = 0; classmethodcount=new Hashtable(); if (state.DSM||state.SINGLETM) localitynumber=new Hashtable(); else - methodnumber=new Hashtable(); + methodnumber=new Hashtable>(); doAnalysis(); } private void doAnalysis() { Iterator classit=state.getClassSymbolTable().getDescriptorsIterator(); + while(classit.hasNext()) { + ClassDescriptor cd=(ClassDescriptor)classit.next(); + numberMethodsIF(cd); + } + classit=state.getClassSymbolTable().getDescriptorsIterator(); while(classit.hasNext()) { ClassDescriptor cd=(ClassDescriptor)classit.next(); if (state.DSM||state.SINGLETM) @@ -43,6 +52,14 @@ public class Virtual { else numberMethods(cd); } + classit=state.getClassSymbolTable().getDescriptorsIterator(); + while(classit.hasNext()) { + ClassDescriptor cd=(ClassDescriptor)classit.next(); + if(!cd.isInterface()) { + int count = classmethodcount.get(cd).intValue(); + classmethodcount.put(cd, new Integer(count+this.if_starts)); + } + } } private int numberLocality(ClassDescriptor cd) { @@ -89,65 +106,108 @@ public class Virtual { classmethodcount.put(cd, new Integer(start)); return start; } + + private int numberMethodsIF(ClassDescriptor cd) { + if(!cd.isInterface()) { + return 0; + } + int start = 0; + if (classmethodcount.containsKey(cd)) + return classmethodcount.get(cd).intValue(); + // check the inherited interfaces + Iterator it_sifs = cd.getSuperInterfaces(); + while(it_sifs.hasNext()) { + ClassDescriptor superif = (ClassDescriptor)it_sifs.next(); + start += numberMethodsIF(superif); + } + for(Iterator it=cd.getMethods(); it.hasNext();) { + MethodDescriptor md=(MethodDescriptor)it.next(); + if (md.isStatic()||md.getReturnType()==null) + continue; + boolean foundmatch=false; + // check if there is a matched method in inherited interfaces + it_sifs = cd.getSuperInterfaces(); + while(it_sifs.hasNext() && !foundmatch) { + ClassDescriptor superif = (ClassDescriptor)it_sifs.next(); + Set possiblematches_if=superif.getMethodTable().getSet(md.getSymbol()); + for(Iterator matchit=possiblematches_if.iterator(); matchit.hasNext();) { + MethodDescriptor matchmd=(MethodDescriptor)matchit.next(); + if (md.matches(matchmd)) { + Vector num=methodnumber.get(matchmd); + if(!methodnumber.containsKey(md)) { + methodnumber.put(md, new Vector()); + } + Vector toadd = methodnumber.get(md); + toadd.addAll(num); + foundmatch=true; + } + } + } + if(!foundmatch) { + Vector vec = new Vector(); + vec.add(new Integer(if_starts++)); + methodnumber.put(md, vec); + start++; + } + } + classmethodcount.put(cd, new Integer(start)); + return start; + } private int numberMethods(ClassDescriptor cd) { if (classmethodcount.containsKey(cd)) return classmethodcount.get(cd).intValue(); ClassDescriptor superdesc=cd.getSuperDesc(); - int start=0; - if (superdesc!=null) - start=numberMethods(superdesc); - { - // check the inherited interfaces - Iterator it_sifs = cd.getSuperInterfaces(); - while(it_sifs.hasNext()) { - ClassDescriptor superif = (ClassDescriptor)it_sifs.next(); - start += numberMethods(superif); // TODO Can there be duplicated methods from multiple ancestors? - } + int start=if_starts; + int mnum = 0; + if (superdesc!=null) { + mnum = numberMethods(superdesc); + start += mnum; } for(Iterator it=cd.getMethods(); it.hasNext();) { MethodDescriptor md=(MethodDescriptor)it.next(); if (md.isStatic()||md.getReturnType()==null) continue; + boolean foundmatch=false; if (superdesc!=null) { Set possiblematches=superdesc.getMethodTable().getSet(md.getSymbol()); - boolean foundmatch=false; for(Iterator matchit=possiblematches.iterator(); matchit.hasNext();) { MethodDescriptor matchmd=(MethodDescriptor)matchit.next(); if (md.matches(matchmd)) { - int num=((Integer)methodnumber.get(matchmd)).intValue(); - methodnumber.put(md, new Integer(num)); + Vector num = methodnumber.get(matchmd); + methodnumber.put(md, num); foundmatch=true; break; } } - { - if(!foundmatch) { - // check if there is a matched method in inherited interfaces - Iterator it_sifs = cd.getSuperInterfaces(); - while(it_sifs.hasNext() && !foundmatch) { - ClassDescriptor superif = (ClassDescriptor)it_sifs.next(); - Set possiblematches_if=superif.getMethodTable().getSet(md.getSymbol()); - for(Iterator matchit=possiblematches_if.iterator(); matchit.hasNext();) { - MethodDescriptor matchmd=(MethodDescriptor)matchit.next(); - if (md.matches(matchmd)) { - int num=((Integer)methodnumber.get(matchmd)).intValue(); - methodnumber.put(md, new Integer(num)); - foundmatch=true; - break; - } - } + } + // check if there is a matched method in inherited interfaces + Iterator it_sifs = cd.getSuperInterfaces(); + while(it_sifs.hasNext()) { + ClassDescriptor superif = (ClassDescriptor)it_sifs.next(); + Set possiblematches_if=superif.getMethodTable().getSet(md.getSymbol()); + for(Iterator matchit=possiblematches_if.iterator(); matchit.hasNext();) { + MethodDescriptor matchmd=(MethodDescriptor)matchit.next(); + if (md.matches(matchmd)) { + Vector num = methodnumber.get(matchmd); + if(!methodnumber.containsKey(md)) { + methodnumber.put(md, new Vector()); } + Vector toadd = methodnumber.get(md); + toadd.addAll(num); + foundmatch=true; } } - if (!foundmatch) - methodnumber.put(md, new Integer(start++)); - } else { - methodnumber.put(md, new Integer(start++)); + } + if (!foundmatch) { + Vector vec = new Vector(); + vec.add(new Integer(start++)); + methodnumber.put(md, vec); + mnum++; } } - classmethodcount.put(cd, new Integer(start)); - return start; + classmethodcount.put(cd, new Integer(mnum)); + return mnum; } }