From: jzhou Date: Thu, 21 Oct 2010 00:21:06 +0000 (+0000) Subject: Implement a more sorphisticated execution strategy for static blocks. Tested with... X-Git-Url: http://plrg.eecs.uci.edu/git/?a=commitdiff_plain;h=615ca89617f654b90f2c868f305b7c611b7631f2;p=IRC.git Implement a more sorphisticated execution strategy for static blocks. Tested with very simple example code. Static field initialization is not implemented yet. --- diff --git a/Robust/src/IR/ClassDescriptor.java b/Robust/src/IR/ClassDescriptor.java index 648173a3..b7862990 100644 --- a/Robust/src/IR/ClassDescriptor.java +++ b/Robust/src/IR/ClassDescriptor.java @@ -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; + } } diff --git a/Robust/src/IR/Flat/BuildCode.java b/Robust/src/IR/Flat/BuildCode.java index e433898f..d549aa3d 100644 --- a/Robust/src/IR/Flat/BuildCode.java +++ b/Robust/src/IR/Flat/BuildCode.java @@ -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" + 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 stopset, - PrintWriter output, boolean firstpass) { + Set 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)+";"); diff --git a/Robust/src/IR/Flat/BuildCodeMGC.java b/Robust/src/IR/Flat/BuildCodeMGC.java index dc115aea..b21d78d2 100644 --- a/Robust/src/IR/Flat/BuildCodeMGC.java +++ b/Robust/src/IR/Flat/BuildCodeMGC.java @@ -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"); + } } diff --git a/Robust/src/IR/MethodDescriptor.java b/Robust/src/IR/MethodDescriptor.java index 5e556cc9..cda2616d 100644 --- a/Robust/src/IR/MethodDescriptor.java +++ b/Robust/src/IR/MethodDescriptor.java @@ -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; diff --git a/Robust/src/IR/State.java b/Robust/src/IR/State.java index 2b849e80..cf367770 100644 --- a/Robust/src/IR/State.java +++ b/Robust/src/IR/State.java @@ -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. */ diff --git a/Robust/src/IR/Tree/BuildIR.java b/Robust/src/IR/Tree/BuildIR.java index 7e5c1929..2a34aaa4 100644 --- a/Robust/src/IR/Tree/BuildIR.java +++ b/Robust/src/IR/Tree/BuildIR.java @@ -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()))