Start to support for virtual calls
authorbdemsky <bdemsky>
Tue, 4 Apr 2006 22:09:53 +0000 (22:09 +0000)
committerbdemsky <bdemsky>
Tue, 4 Apr 2006 22:09:53 +0000 (22:09 +0000)
Robust/src/IR/Flat/BuildCode.java
Robust/src/IR/MethodDescriptor.java
Robust/src/IR/TypeDescriptor.java
Robust/src/IR/Virtual.java [new file with mode: 0644]

index 4302ab6bfd8a9e9203818f7b2e52b85049c8c40a..aee789840c1fb451e8ec0655da59de782fcaaff5 100644 (file)
@@ -8,17 +8,21 @@ public class BuildCode {
     Hashtable temptovar;
     Hashtable paramstable;
     Hashtable tempstable;
+    Hashtable fieldorder;
     int tag=0;
     String localsprefix="___locals___";
     String paramsprefix="___params___";
     public static boolean GENERATEPRECISEGC=false;
     public static String PREFIX="";
+    Virtual virtualcalls;
 
     public BuildCode(State st, Hashtable temptovar) {
        state=st;
        this.temptovar=temptovar;
        paramstable=new Hashtable();    
        tempstable=new Hashtable();
+       fieldorder=new Hashtable();
+       virtualcalls=new Virtual(state);
     }
 
     public void buildCode() {
@@ -27,6 +31,8 @@ public class BuildCode {
        PrintWriter outstructs=null;
        PrintWriter outmethodheader=null;
        PrintWriter outmethod=null;
+       PrintWriter outvirtual=null;
+
        try {
            OutputStream str=new FileOutputStream(PREFIX+"structdefs.h");
            outstructs=new java.io.PrintWriter(str, true);
@@ -36,10 +42,14 @@ public class BuildCode {
            outclassdefs=new java.io.PrintWriter(str, true);
            str=new FileOutputStream(PREFIX+"methods.c");
            outmethod=new java.io.PrintWriter(str, true);
+           str=new FileOutputStream(PREFIX+"virtualtable.h");
+           outvirtual=new java.io.PrintWriter(str, true);
        } catch (Exception e) {
            e.printStackTrace();
            System.exit(-1);
        }
+
+       buildVirtualTables(outvirtual);
        outstructs.println("#include \"classdefs.h\"");
        outmethodheader.println("#include \"structdefs.h\"");
 
@@ -61,6 +71,7 @@ public class BuildCode {
 
        /* Build the actual methods */
        outmethod.println("#include \"methodheaders.h\"");
+       outmethod.println("#include \"virtualtable.h\"");
        outmethod.println("#include <runtime.h>");
        Iterator classit=state.getClassSymbolTable().getDescriptorsIterator();
        while(classit.hasNext()) {
@@ -76,6 +87,58 @@ public class BuildCode {
        outmethod.close();
     }
 
+    private void buildVirtualTables(PrintWriter outvirtual) {
+       int numclasses=0;
+       int maxcount=0;
+       Iterator classit=state.getClassSymbolTable().getDescriptorsIterator();
+       while(classit.hasNext()) {
+           ClassDescriptor cd=(ClassDescriptor)classit.next();
+           if (virtualcalls.getMethodCount(cd)>maxcount)
+               maxcount=virtualcalls.getMethodCount(cd);
+           numclasses++;
+       }
+       MethodDescriptor[][] virtualtable=new MethodDescriptor[numclasses][maxcount];
+
+       /* Fill in virtual table */
+       classit=state.getClassSymbolTable().getDescriptorsIterator();
+       while(classit.hasNext()) {
+           ClassDescriptor cd=(ClassDescriptor)classit.next();
+           fillinRow(cd, virtualtable, cd.getId());
+       }
+       outvirtual.print("void * virtualtable[]={");
+       boolean needcomma=false;
+       for(int i=0;i<numclasses;i++) {
+           for(int j=0;j<maxcount;j++) {
+               if (needcomma)
+                   outvirtual.print(", ");
+               if (virtualtable[i][j]!=null) {
+                   MethodDescriptor md=virtualtable[i][j];
+                   outvirtual.print("& "+md.getClassDesc().getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor());
+               } else {
+                   outvirtual.print("0");
+               }
+               needcomma=true;
+           }
+           outvirtual.println("");
+       }
+       outvirtual.println("};");
+       outvirtual.close();
+    }
+
+    private void fillinRow(ClassDescriptor cd, MethodDescriptor[][] virtualtable, int rownum) {
+       /* Get inherited methods */
+       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;
+       }
+    }
+
     private void generateTempStructs(FlatMethod fm) {
        MethodDescriptor md=fm.getMethod();
        ParamsObject objectparams=new ParamsObject(md,tag++);
@@ -104,19 +167,39 @@ public class BuildCode {
            }
        }
     }
+    
+    /* Force consistent field ordering between inherited classes */
+    private void printClassStruct(ClassDescriptor cn, PrintWriter classdefout) {
+       ClassDescriptor sp=cn.getSuperDesc();
+       if (sp!=null)
+           printClassStruct(sp, classdefout);
+       
+       if (!fieldorder.containsKey(cn)) {
+           Vector fields=new Vector();
+           fieldorder.put(cn,fields);
+           Iterator fieldit=cn.getFields();
+           while(fieldit.hasNext()) {
+               FieldDescriptor fd=(FieldDescriptor)fieldit.next();
+               if (sp==null||!sp.getFieldTable().contains(fd.getSymbol()))
+                   fields.add(fd);
+           }
+       }
+       Vector fields=(Vector)fieldorder.get(cn);
 
-    private void generateCallStructs(ClassDescriptor cn, PrintWriter classdefout, PrintWriter output, PrintWriter headersout) {
-       /* Output class structure */
-       Iterator fieldit=cn.getFields();
-       classdefout.println("struct "+cn.getSafeSymbol()+" {");
-       classdefout.println("  int type;");
-       while(fieldit.hasNext()) {
-           FieldDescriptor fd=(FieldDescriptor)fieldit.next();
+       for(int i=0;i<fields.size();i++) {
+           FieldDescriptor fd=(FieldDescriptor)fields.get(i);
            if (fd.getType().isClass())
                classdefout.println("  struct "+fd.getType().getSafeSymbol()+" * "+fd.getSafeSymbol()+";");
            else 
                classdefout.println("  "+fd.getType().getSafeSymbol()+" "+fd.getSafeSymbol()+";");
        }
+    }
+
+    private void generateCallStructs(ClassDescriptor cn, PrintWriter classdefout, PrintWriter output, PrintWriter headersout) {
+       /* Output class structure */
+       classdefout.println("struct "+cn.getSafeSymbol()+" {");
+       classdefout.println("  int type;");
+       printClassStruct(cn, classdefout);
        classdefout.println("};\n");
 
        /* Cycle through methods */
@@ -203,7 +286,6 @@ public class BuildCode {
        for(int i=0;i<objecttemp.numPrimitives();i++) {
            TempDescriptor td=objecttemp.getPrimitive(i);
            TypeDescriptor type=td.getType();
-           System.out.println(td.getSafeSymbol());
            if (type.isNull())
                output.println("   void * "+td.getSafeSymbol()+";");
            else if (type.isClass())
index ae040bb57eacddf98a6145611996050057ada917..211448f976ca0aaae62a7f71f86e0758af7f4236 100644 (file)
@@ -32,6 +32,21 @@ public class MethodDescriptor extends Descriptor {
        thisvd=null;
     }
 
+    public boolean matches(MethodDescriptor md) {
+       /* Check the name */
+       if (!identifier.equals(md.identifier))
+           return false;
+       if (numParameters()!=md.numParameters())
+           return false;
+       for(int i=0;i<numParameters();i++) {
+           TypeDescriptor td1=getParameter(i).getType();
+           TypeDescriptor td2=md.getParameter(i).getType();
+           if (!td1.equals(td2))
+               return false;
+       }
+       return true;
+    }
+
     public MethodDescriptor(Modifiers m, String identifier) {
        super(identifier);
        this.modifier=m;
index 4a880e2ac13e37bf5c7c0c966db80e5fadd15717..0114421dc81e3fd55a63c850d8a0a877f73abb1c 100644 (file)
@@ -24,6 +24,19 @@ public class TypeDescriptor extends Descriptor {
     int type;
     ClassDescriptor class_desc;
 
+    public boolean equals(Object o) {
+       if (o instanceof TypeDescriptor) {
+           TypeDescriptor t=(TypeDescriptor)o;
+           if (t.type!=type)
+               return false;
+           if ((type==CLASS)&&(t.class_desc!=class_desc))
+               return false;
+           return true;
+       }
+       return false;
+    }
+
+
     public String getSafeSymbol() {
        if (isClass())
            return class_desc.getSafeSymbol();
diff --git a/Robust/src/IR/Virtual.java b/Robust/src/IR/Virtual.java
new file mode 100644 (file)
index 0000000..11d027b
--- /dev/null
@@ -0,0 +1,65 @@
+package IR;
+import java.util.*;
+
+public class Virtual {
+    State state;
+    Hashtable methodnumber;
+    Hashtable classmethodcount;
+      
+    public int getMethodNumber(MethodDescriptor md) {
+       return ((Integer)methodnumber.get(md)).intValue();
+    }
+
+    public int getMethodCount(ClassDescriptor md) {
+       return ((Integer)classmethodcount.get(md)).intValue();
+    }
+
+    public Virtual(State state) {
+       this.state=state;
+       methodnumber=new Hashtable();
+       classmethodcount=new Hashtable();
+       doAnalysis();
+    }
+
+    private void doAnalysis() {
+       Iterator classit=state.getClassSymbolTable().getDescriptorsIterator();
+       while(classit.hasNext()) {
+           ClassDescriptor cd=(ClassDescriptor)classit.next();
+           numberMethods(cd);
+       }
+    }
+
+    private int numberMethods(ClassDescriptor cd) {
+       if (classmethodcount.containsKey(cd))
+           return ((Integer)classmethodcount.get(cd)).intValue();
+       ClassDescriptor superdesc=cd.getSuperDesc();
+       int start=0;
+       if (superdesc!=null)
+           start=numberMethods(superdesc);
+       for(Iterator it=cd.getMethods();it.hasNext();) {
+           MethodDescriptor md=(MethodDescriptor)it.next();
+           if (md.isStatic()||md.getReturnType()==null)
+               continue;
+           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));
+                       foundmatch=true;
+                       break;
+                   }
+               }
+               if (!foundmatch)
+                   methodnumber.put(md, new Integer(start++));
+           } else {
+               methodnumber.put(md, new Integer(start++));
+           }
+       }
+       classmethodcount.put(cd, new Integer(start));
+       return start;
+    }
+}
+