Implement a more sorphisticated execution strategy for static blocks. Tested with...
authorjzhou <jzhou>
Thu, 21 Oct 2010 00:21:06 +0000 (00:21 +0000)
committerjzhou <jzhou>
Thu, 21 Oct 2010 00:21:06 +0000 (00:21 +0000)
Robust/src/IR/ClassDescriptor.java
Robust/src/IR/Flat/BuildCode.java
Robust/src/IR/Flat/BuildCodeMGC.java
Robust/src/IR/MethodDescriptor.java
Robust/src/IR/State.java
Robust/src/IR/Tree/BuildIR.java

index 648173a3afcb8f36c1741815e55f882d7419b9fb..b7862990f118dde2cdc7562ff89ada5d430778a5 100644 (file)
@@ -17,7 +17,8 @@ public class ClassDescriptor extends Descriptor {
   SymbolTable flags;
   SymbolTable methods;
   
-  int numstaticblocks=0;
+  int numstaticblocks = 0;
+  int numstaticfields = 0;
 
   public ClassDescriptor(String classname) {
     this("", classname);
@@ -123,6 +124,9 @@ public class ClassDescriptor extends Descriptor {
       throw new Error(fd.getSymbol()+" already defined");
     fields.add(fd);
     fieldvec.add(fd);
+    if(fd.isStatic()) {
+      this.incStaticFields();
+    }
   }
 
   public void addMethod(MethodDescriptor md) {
@@ -156,4 +160,12 @@ public class ClassDescriptor extends Descriptor {
   public int getNumStaticBlocks() {
     return this.numstaticblocks;
   }
+  
+  public void incStaticFields() {
+    this.numstaticfields++;
+  }
+  
+  public int getNumStaticFields() {
+    return this.numstaticfields;
+  }
 }
index e433898fd501e85dd2e5edf897c4baa1103efc41..d549aa3d7e27d591a43857084c7f185dd610a594 100644 (file)
@@ -190,6 +190,9 @@ public class BuildCode {
     /* Build the virtual dispatch tables */
     buildVirtualTables(outvirtual);
 
+    /* Tag the methods that are invoked by static blocks */
+    tagMethodInvokedByStaticBlock();
+    
     /* Output includes */
     outmethodheader.println("#ifndef METHODHEADERS_H");
     outmethodheader.println("#define METHODHEADERS_H");
@@ -369,6 +372,44 @@ public class BuildCode {
     }  
   }
   
+  /* This method goes though the call graph and tag those methods that are 
+   * invoked inside static blocks
+   */
+  protected void tagMethodInvokedByStaticBlock() {
+    Iterator it_sclasses = this.state.getSClassSymbolTable().getDescriptorsIterator();
+    MethodDescriptor current_md=null;
+    HashSet tovisit=new HashSet();
+    HashSet visited=new HashSet();
+    
+    while(it_sclasses.hasNext()) {
+      ClassDescriptor cd = (ClassDescriptor)it_sclasses.next();
+      MethodDescriptor md = (MethodDescriptor)cd.getMethodTable().get("staticblocks");
+      tovisit.add(md);
+    }
+    
+    while(!tovisit.isEmpty()) {
+      current_md=(MethodDescriptor)tovisit.iterator().next();
+      tovisit.remove(current_md);
+      visited.add(current_md);
+      Iterator it_callee = this.callgraph.getCalleeSet(current_md).iterator();
+      while(it_callee.hasNext()) {
+        Descriptor d = (Descriptor)it_callee.next();
+        if(d instanceof MethodDescriptor) {
+          if(!visited.contains(d)) {
+            ((MethodDescriptor)d).setIsInvokedByStatic(true);
+            tovisit.add(d);
+          }
+        }
+      }
+    }
+  }
+  
+  /* This code generates code for each static block and static field 
+   * initialization.*/
+  protected void outputStaticBlocks(PrintWriter outmethod) {
+    //  execute all the static blocks and all the static field initializations
+    // TODO
+  }
 
   /* This code just generates the main C method for java programs.
    * The main C method packs up the arguments into a string array
@@ -377,6 +418,8 @@ public class BuildCode {
   protected void outputMainMethod(PrintWriter outmethod) {
     outmethod.println("int main(int argc, const char *argv[]) {");
     outmethod.println("  int i;");
+    
+    outputStaticBlocks(outmethod);
 
     if (state.MLP || state.OOOJAVA) {
 
@@ -1452,6 +1495,13 @@ public class BuildCode {
       }
     }
     Vector fields=(Vector)fieldorder.get(cn);
+    
+    if((cn.getNumStaticFields() != 0) || (cn.getNumStaticBlocks() != 0)) {
+      // this class has static fields/blocks, need to add a global flag to 
+      // indicate if its static fields have been initialized and/or if its
+      // static blocks have been executed
+      globaldefout.println("  int "+cn.getSafeSymbol()+"static_block_exe_flag;");
+    }
 
     for(int i=0; i<fields.size(); i++) {
       FieldDescriptor fd=(FieldDescriptor)fields.get(i);
@@ -1991,9 +2041,16 @@ public class BuildCode {
     }
     
     if(fm.getMethod().isStaticBlock()) {
-      // a static block
-    } else if((fm.getMethod().getReturnType() == null) && (cn != null)){
+      // a static block, check if it has been executed
+      output.println("  if(global_defs_p->" + cn.getSafeSymbol()+"static_block_exe_flag != 0) {");
+      output.println("    return;");
+      output.println("  }");
+      output.println("");
+    }
+    if((!fm.getMethod().isStaticBlock()) && (fm.getMethod().getReturnType() == null) && (cn != null)){
       // is a constructor, check and output initialization of the static fields
+      // here does not initialize the static fields of the class, instead it 
+      // redirect the corresponding fields in the object to the global_defs_p
       Vector fields=(Vector)fieldorder.get(cn);
 
       for(int i=0; i<fields.size(); i++) {
@@ -2537,8 +2594,9 @@ public class BuildCode {
   protected void generateCode(FlatNode first,
                               FlatMethod fm,
                               LocalityBinding lb,
-                             Set<FlatNode> stopset,
-                              PrintWriter output, boolean firstpass) {
+                              Set<FlatNode> stopset,
+                              PrintWriter output, 
+                              boolean firstpass) {
 
     /* Assign labels to FlatNode's if necessary.*/
 
@@ -2626,6 +2684,11 @@ public class BuildCode {
          assert fsxn.getFlatEnter().equals( fsen );
        }
        if (current_node.kind()!=FKind.FlatReturnNode) {
+      if((fm.getMethod() != null) && (fm.getMethod().isStaticBlock())) {
+        // a static block, check if it has been executed
+        output.println("  global_defs_p->" + fm.getMethod().getClassDesc().getSafeSymbol()+"static_block_exe_flag = 1;");
+        output.println("");
+      }
          output.println("   return;");
        }
        current_node=null;
@@ -4553,6 +4616,40 @@ public class BuildCode {
     MethodDescriptor md=fc.getMethod();
     ParamsObject objectparams=(ParamsObject)paramstable.get(lb!=null ? locality.getBinding(lb, fc) : md);
     ClassDescriptor cn=md.getClassDesc();
+    
+    // if the called method is a static block or a static method or a constructor
+    // need to check if it can be invoked inside some static block
+    if((md.isStatic() || md.isStaticBlock() || md.isConstructor()) && 
+        ((fm.getMethod().isStaticBlock()) || (fm.getMethod().isInvokedByStatic()))) {
+      if(!md.isInvokedByStatic()) {
+        System.err.println("Error: a method that is invoked inside a static block is not tagged!");
+      }
+      // is a static block or is invoked in some static block
+      ClassDescriptor cd = fm.getMethod().getClassDesc();
+      if(cd == cn) {
+        // the same class, do nothing
+        // TODO may want to invoke static field initialization here
+      } else {
+        if((cn.getNumStaticFields() != 0) || (cn.getNumStaticBlocks() != 0)) {
+          // need to check if the class' static fields have been initialized and/or
+          // its static blocks have been executed
+          output.println("#ifdef MGC_STATIC_INIT_CHECK");
+          output.println("if(global_defs_p->" + cn.getSafeSymbol()+"static_block_exe_flag == 0) {");
+          if(cn.getNumStaticFields() != 0) {
+            // TODO add static field initialization here
+          }
+          if(cn.getNumStaticBlocks() != 0) {
+            MethodDescriptor t_md = (MethodDescriptor)cn.getMethodTable().get("staticblocks");
+            output.println("  "+cn.getSafeSymbol()+t_md.getSafeSymbol()+"_"+t_md.getSafeMethodDescriptor()+"();");
+          } else {
+            output.println("  global_defs_p->" + cn.getSafeSymbol()+"static_block_exe_flag = 1;");
+          }
+          output.println("}");
+          output.println("#endif // MGC_STATIC_INIT_CHECK"); 
+        }
+      }
+    }
+    
     output.println("{");
     if ((GENERATEPRECISEGC) || (this.state.MULTICOREGC)) {
       if (lb!=null) {
@@ -4776,7 +4873,35 @@ public class BuildCode {
 // DEBUG               output.println("within((void*)"+generateTemp(fm,ffn.getSrc(),lb)+"->"+ ffn.getField().getSafeSymbol()+");");
 // DEBUG       } 
       if(ffn.getField().isStatic()) {
-        // static field, redirect to the global_defs_p structure
+        // static field
+        if((fm.getMethod().isStaticBlock()) || (fm.getMethod().isInvokedByStatic())) {
+          // is a static block or is invoked in some static block
+          ClassDescriptor cd = fm.getMethod().getClassDesc();
+          ClassDescriptor cn = ffn.getSrc().getType().getClassDesc();
+          if(cd == cn) {
+            // the same class, do nothing
+            // TODO may want to invoke static field initialization here
+          } else {
+            if((cn.getNumStaticFields() != 0) || (cn.getNumStaticBlocks() != 0)) {
+              // need to check if the class' static fields have been initialized and/or
+              // its static blocks have been executed
+              output.println("#ifdef MGC_STATIC_INIT_CHECK");
+              output.println("if(global_defs_p->" + cn.getSafeSymbol()+"static_block_exe_flag == 0) {");
+              if(cn.getNumStaticFields() != 0) {
+                // TODO add static field initialization here
+              }
+              if(cn.getNumStaticBlocks() != 0) {
+                MethodDescriptor t_md = (MethodDescriptor)cn.getMethodTable().get("staticblocks");
+                output.println("  "+cn.getSafeSymbol()+t_md.getSafeSymbol()+"_"+t_md.getSafeMethodDescriptor()+"();");
+              } else {
+                output.println("  global_defs_p->" + cn.getSafeSymbol()+"static_block_exe_flag = 1;");
+              }
+              output.println("}");
+              output.println("#endif // MGC_STATIC_INIT_CHECK"); 
+            }
+          }
+        }
+        // redirect to the global_defs_p structure
         if(ffn.getSrc().getType().isStatic()) {
           // reference to the static field with Class name
           output.println(generateTemp(fm, ffn.getDst(),lb)+"=global_defs_p->"+ ffn.getSrc().getType().getClassDesc().getSafeSymbol()+ffn.getField().getSafeSymbol()+";");
@@ -4889,7 +5014,35 @@ public class BuildCode {
 // DEBUG               output.println("within((void*)"+generateTemp(fm,fsfn.getSrc(),lb)+");");
 // DEBUG   }  
       if(fsfn.getField().isStatic()) {
-        // static field, redirect to the global_defs_p structure
+        // static field
+        if((fm.getMethod().isStaticBlock()) || (fm.getMethod().isInvokedByStatic())) {
+          // is a static block or is invoked in some static block
+          ClassDescriptor cd = fm.getMethod().getClassDesc();
+          ClassDescriptor cn = fsfn.getDst().getType().getClassDesc();
+          if(cd == cn) {
+            // the same class, do nothing
+            // TODO may want to invoke static field initialization here
+          } else {
+            if((cn.getNumStaticFields() != 0) || (cn.getNumStaticBlocks() != 0)) {
+              // need to check if the class' static fields have been initialized and/or
+              // its static blocks have been executed
+              output.println("#ifdef MGC_STATIC_INIT_CHECK");
+              output.println("if(global_defs_p->" + cn.getSafeSymbol()+"static_block_exe_flag == 0) {");
+              if(cn.getNumStaticFields() != 0) {
+                // TODO add static field initialization here
+              }
+              if(cn.getNumStaticBlocks() != 0) {
+                MethodDescriptor t_md = (MethodDescriptor)cn.getMethodTable().get("staticblocks");
+                output.println("  "+cn.getSafeSymbol()+t_md.getSafeSymbol()+"_"+t_md.getSafeMethodDescriptor()+"();");
+              } else {
+                output.println("  global_defs_p->" + cn.getSafeSymbol()+"static_block_exe_flag = 1;");
+              }
+              output.println("}");
+              output.println("#endif // MGC_STATIC_INIT_CHECK"); 
+            }
+          }
+        }
+        // redirect to the global_defs_p structure
         if(fsfn.getDst().getType().isStatic()) {
           // reference to the static field with Class name
           output.println("global_defs_p->" + fsfn.getDst().getType().getClassDesc().getSafeSymbol() + fsfn.getField().getSafeSymbol()+"="+ generateTemp(fm,fsfn.getSrc(),lb)+";");
@@ -5228,6 +5381,11 @@ public class BuildCode {
   }
 
   protected void generateFlatReturnNode(FlatMethod fm, LocalityBinding lb, FlatReturnNode frn, PrintWriter output) {
+    if((fm.getMethod() != null) && (fm.getMethod().isStaticBlock())) {
+      // a static block, check if it has been executed
+      output.println("  global_defs_p->" + fm.getMethod().getClassDesc().getSafeSymbol()+"static_block_exe_flag = 1;");
+      output.println("");
+    }
     if (frn.getReturnTemp()!=null) {
       if (frn.getReturnTemp().getType().isPtr())
        output.println("return (struct "+fm.getMethod().getReturnType().getSafeSymbol()+"*)"+generateTemp(fm, frn.getReturnTemp(), lb)+";");
index dc115aea69d2d09fbc104c3a6e54f14c12a37629..b21d78d2a8f28ccab9bc0ae2eae00d48b6903371 100644 (file)
@@ -68,6 +68,9 @@ public class BuildCodeMGC extends BuildCode {
 
     /* Build the virtual dispatch tables */
     super.buildVirtualTables(outvirtual);
+    
+    /* Tag the methods that are invoked by static blocks */
+    super.tagMethodInvokedByStaticBlock();
 
     /* Output includes */
     outmethodheader.println("#ifndef METHODHEADERS_H");
@@ -140,23 +143,7 @@ public class BuildCodeMGC extends BuildCode {
     outmethod.println("int mgc_main(int argc, const char *argv[]) {");
     outmethod.println("  int i;");
     
-    // execute all the static blocks in random order 
-    // TODO may need more careful about the execution order
-    SymbolTable sbt = this.state.getStaticBlockSymbolTable();
-    Iterator it_staticblocks = state.getStaticBlockSymbolTable().getDescriptorsIterator();
-    while(it_staticblocks.hasNext()) {
-      MethodDescriptor t_md = (MethodDescriptor) it_staticblocks.next();
-      ClassDescriptor t_cd = t_md.getClassDesc();
-      outmethod.println("   {");
-      if ((GENERATEPRECISEGC) || (this.state.MULTICOREGC)) {
-        outmethod.print("       struct "+t_cd.getSafeSymbol()+t_md.getSafeSymbol()+"_"+t_md.getSafeMethodDescriptor()+"_params __parameterlist__={");
-        outmethod.println("1, NULL};");
-        outmethod.println("     "+t_cd.getSafeSymbol()+t_md.getSafeSymbol()+"_"+t_md.getSafeMethodDescriptor()+"(& __parameterlist__);");
-      } else {
-        outmethod.println("     "+t_cd.getSafeSymbol()+t_md.getSafeSymbol()+"_"+t_md.getSafeMethodDescriptor()+"();");
-      }
-      outmethod.println("   }");
-    }
+    outputStaticBlocks(outmethod);
     
     if ((GENERATEPRECISEGC) || (this.state.MULTICOREGC)) {
       outmethod.println("  struct ArrayObject * stringarray=allocate_newarray(NULL, STRINGARRAYTYPE, argc-1);");
@@ -188,4 +175,25 @@ public class BuildCodeMGC extends BuildCode {
 
     outmethod.println("}");
   }
+  
+  protected void outputStaticBlocks(PrintWriter outmethod) {
+    outmethod.println("#define MGC_STATIC_INIT_CHECK");
+    // execute all the static blocks and all the static field initializations
+    SymbolTable sctbl = this.state.getSClassSymbolTable();
+    Iterator it_sclasses = sctbl.getDescriptorsIterator();
+    while(it_sclasses.hasNext()) {
+      ClassDescriptor t_cd = (ClassDescriptor)it_sclasses.next();
+      MethodDescriptor t_md = (MethodDescriptor)t_cd.getMethodTable().get("staticblocks");
+      outmethod.println("   {");
+      if ((GENERATEPRECISEGC) || (this.state.MULTICOREGC)) {
+        outmethod.print("       struct "+t_cd.getSafeSymbol()+t_md.getSafeSymbol()+"_"+t_md.getSafeMethodDescriptor()+"_params __parameterlist__={");
+        outmethod.println("1, NULL};");
+        outmethod.println("     "+t_cd.getSafeSymbol()+t_md.getSafeSymbol()+"_"+t_md.getSafeMethodDescriptor()+"(& __parameterlist__);");
+      } else {
+        outmethod.println("     "+t_cd.getSafeSymbol()+t_md.getSafeSymbol()+"_"+t_md.getSafeMethodDescriptor()+"();");
+      }
+      outmethod.println("   }");
+    }
+    outmethod.println("#undef MGC_STATIC_INIT_CHECK");
+  }
 }
index 5e556cc9a137c0534143238078aadfbc0e4612ba..cda2616d738b4472993ad9af8eb1100e4ec74a7d 100644 (file)
@@ -19,7 +19,8 @@ public class MethodDescriptor extends Descriptor {
   protected ClassDescriptor cd;
   protected VarDescriptor thisvd;
   protected boolean isglobal;
-  protected boolean isstaticblock;
+  protected boolean isstaticblock;  // flag to indicate if this is a static block
+  protected boolean isinvokedbystatic;  // flag to indicate if this method is invoked by some static block
 
   public MethodDescriptor(Modifiers m, TypeDescriptor rt, String identifier) {
     super(identifier);
@@ -85,6 +86,14 @@ public class MethodDescriptor extends Descriptor {
   public void setAsStaticBlock() {
     isstaticblock = true;
   }
+  
+  public boolean isInvokedByStatic() {
+    return this.isinvokedbystatic;
+  }
+  
+  public void setIsInvokedByStatic(boolean isinvokedbystatic) {
+    this.isinvokedbystatic = isinvokedbystatic;
+  }
 
   public void setThis(VarDescriptor vd) {
     thisvd=vd;
index 2b849e8045e6e3bfbd5bb58006405b82b6902e84..cf36777042903ba82e7c2bef4a5fa91a1cff910f 100644 (file)
@@ -11,7 +11,7 @@ public class State {
   public State() {
     this.classes=new SymbolTable();
     this.tasks=new SymbolTable();
-    this.staticblocks=new SymbolTable();
+    this.sclasses=new SymbolTable();
     this.treemethodmap=new Hashtable();
     this.flatmethodmap=new Hashtable();
     this.parsetrees=new HashSet();
@@ -167,7 +167,7 @@ public class State {
   public Vector classpath;
   public SymbolTable classes;
   public SymbolTable tasks;
-  public SymbolTable staticblocks;
+  public SymbolTable sclasses; // table of classes with static field/blocks
   public Set parsetrees;
   public Hashtable treemethodmap;
   public Hashtable flatmethodmap;
@@ -230,11 +230,9 @@ public class State {
       throw new Error("Class "+tdn.getSymbol()+" defined twice");
     classes.add(tdn);
     numclasses++;
-  }
-
-  public void addStaticBlock(MethodDescriptor sbn) {
-    staticblocks.add(sbn);
-    numstaticblocks++;
+    if((tdn.numstaticfields != 0) || (tdn.numstaticblocks != 0)) {
+      sclasses.add(tdn);
+    }
   }
   
   public int numClasses() {
@@ -261,8 +259,8 @@ public class State {
     return tasks;
   }
   
-  public SymbolTable getStaticBlockSymbolTable() {
-    return staticblocks;
+  public SymbolTable getSClassSymbolTable() {
+    return sclasses;
   }
 
   /** Returns Flat IR representation of MethodDescriptor md. */
index 7e5c1929f716234a6e3f6e4306623570f61113a4..2a34aaa4578b1617cc60ad3c526322f9d446bbcf 100644 (file)
@@ -1,5 +1,6 @@
 package IR.Tree;
 import IR.*;
+
 import java.util.*;
 
 
@@ -652,24 +653,41 @@ public class BuildIR {
   }
   
   private void parseStaticBlockDecl(ClassDescriptor cn, ParseNode pn) {
-    Modifiers m=new Modifiers();
-    m.addModifier(Modifiers.STATIC);
-    MethodDescriptor md=new MethodDescriptor(m, "staticblock"+cn.getNumStaticBlocks(), false);
-    //md.setClassDesc(cn);
-    md.setAsStaticBlock();
-    ParseNode bodyn=pn.getChild("body");;
-    cn.addMethod(md);
+    // Each class maintains one MethodDecscriptor which combines all its 
+    // static blocks in their declaration order
+    boolean isfirst = false;
+    MethodDescriptor md = (MethodDescriptor)cn.getMethodTable().get("staticblocks");
+    if(md == null) {
+      // the first static block for this class
+      Modifiers m=new Modifiers();
+      m.addModifier(Modifiers.STATIC);
+      md = new MethodDescriptor(m, "staticblocks", false);
+      md.setAsStaticBlock();
+      isfirst = true;
+    }
+    ParseNode bodyn=pn.getChild("body");
+    if(isfirst) {
+      cn.addMethod(md);
+    }
     cn.incStaticBlocks();
     BlockNode bn=null;
     if (bodyn!=null&&bodyn.getChild("block_statement_list")!=null)
       bn=parseBlock(bodyn);
     else
       bn=new BlockNode();
-    state.addTreeCode(md,bn);
-    state.addStaticBlock(md);
+    if(isfirst) {
+      state.addTreeCode(md,bn);
+    } else {
+      BlockNode obn = state.getMethodBody(md);
+      for(int i = 0; i < bn.size(); i++) {
+        BlockStatementNode bsn = bn.get(i);
+        obn.addBlockStatement(bsn);
+      }
+      //TODO state.addTreeCode(md, obn);
+      bn = null;
+    }
   }
 
-
   public BlockNode parseBlock(ParseNode pn) {
     this.m_taskexitnum = 0;
     if (pn==null||isEmpty(pn.getTerminal()))