From: jjenista Date: Tue, 10 May 2011 20:37:37 +0000 (+0000) Subject: New tool to check points-to results of a heap analysis against runtime pointers.... X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=a49872987651a8037fd84b193134e0818adda149;p=IRC.git New tool to check points-to results of a heap analysis against runtime pointers. Added an extension object system to BuildCode for this and future extensions. --- diff --git a/Robust/src/Analysis/Disjoint/DisjointAnalysis.java b/Robust/src/Analysis/Disjoint/DisjointAnalysis.java index 3c724f57..fae647f9 100644 --- a/Robust/src/Analysis/Disjoint/DisjointAnalysis.java +++ b/Robust/src/Analysis/Disjoint/DisjointAnalysis.java @@ -347,6 +347,11 @@ public class DisjointAnalysis implements HeapAnalysis { bw.close(); } + + + public Alloc getCmdLineArgsAlloc() { + return getAllocationSiteFromFlatNew( constructedCmdLineArgsNew ); + } /////////////////////////////////////////// // // end public interface @@ -538,10 +543,26 @@ public class DisjointAnalysis implements HeapAnalysis { static protected Hashtable fn2rgAtEnter = new Hashtable(); + static protected Hashtable fn2rgAtExit = + new Hashtable(); + + private Hashtable fc2enclosing; Accessible accessible; + + // we construct an entry method of flat nodes complete + // with a new allocation site to model the command line + // args creation just for the analysis, so remember that + // allocation site. Later in code gen we might want to + // know if something is pointing-to to the cmd line args + // and we can verify by checking the allocation site field. + protected FlatNew constructedCmdLineArgsNew; + + + + // allocate various structures that are not local // to a single class method--should be done once protected void allocateStructures() { @@ -1175,6 +1196,7 @@ public class DisjointAnalysis implements HeapAnalysis { System.out.println(" Generating reach graph for program point: "+fgrn.getGraphName() ); + rg.writeGraph("genReach"+fgrn.getGraphName(), true, // write labels (variables) true, // selectively hide intermediate temp vars @@ -1749,6 +1771,12 @@ public class DisjointAnalysis implements HeapAnalysis { mapBackEdgeToMonotone.put(fn, rg); } + + ReachGraph rgOnExit = new ReachGraph(); + rgOnExit.merge(rg); + fn2rgAtExit.put(fn, rgOnExit); + + // at this point rg should be the correct update // by an above transfer function, or untouched if // the flat node type doesn't affect the heap @@ -1943,7 +1971,6 @@ public class DisjointAnalysis implements HeapAnalysis { - // Take in source entry which is the program's compiled entry and // create a new analysis entry, a method that takes no parameters // and appears to allocate the command line arguments and call the @@ -1974,6 +2001,7 @@ public class DisjointAnalysis implements HeapAnalysis { cmdLineArgs, false // is global ); + this.constructedCmdLineArgsNew = fn; TempDescriptor[] sourceEntryArgs = new TempDescriptor[1]; sourceEntryArgs[0] = cmdLineArgs; @@ -2699,4 +2727,57 @@ public class DisjointAnalysis implements HeapAnalysis { } } + + + + public Set canPointToAt( TempDescriptor x, + FlatNode programPoint ) { + + ReachGraph rgAtEnter = fn2rgAtEnter.get( programPoint ); + if( rgAtEnter == null ) { + return null; + } + + return rgAtEnter.canPointTo( x ); + } + + + public Set canPointToAfter( TempDescriptor x, + FlatNode programPoint ) { + + ReachGraph rgAtExit = fn2rgAtExit.get( programPoint ); + if( rgAtExit == null ) { + return null; + } + + return rgAtExit.canPointTo( x ); + } + + + public Hashtable< Alloc, Set > canPointToAt( TempDescriptor x, + FieldDescriptor f, + FlatNode programPoint ) { + + ReachGraph rgAtEnter = fn2rgAtEnter.get( programPoint ); + if( rgAtEnter == null ) { + return null; + } + + return rgAtEnter.canPointTo( x, f.getSymbol() ); + } + + + public Hashtable< Alloc, Set > canPointToAtElement( TempDescriptor x, + FlatNode programPoint ) { + + ReachGraph rgAtEnter = fn2rgAtEnter.get( programPoint ); + if( rgAtEnter == null ) { + return null; + } + + assert x.getType() != null; + assert x.getType().isArray(); + + return rgAtEnter.canPointTo( x, arrayElementFieldName ); + } } diff --git a/Robust/src/Analysis/Disjoint/HeapAnalysis.java b/Robust/src/Analysis/Disjoint/HeapAnalysis.java index 8fd33252..aaee0c3f 100644 --- a/Robust/src/Analysis/Disjoint/HeapAnalysis.java +++ b/Robust/src/Analysis/Disjoint/HeapAnalysis.java @@ -1,8 +1,35 @@ package Analysis.Disjoint; + +import java.util.*; + +import IR.*; +import IR.Flat.TempDescriptor; +import IR.Flat.FlatNode; import IR.Flat.FlatNew; + public interface HeapAnalysis { public EffectsAnalysis getEffectsAnalysis(); public Alloc getAllocationSiteFromFlatNew(FlatNew node); + public Alloc getCmdLineArgsAlloc(); + + // Use these methods to find out what allocation sites + // the given pointer might point to at or after the + // given program point. In the case of a variable and + // a field or element dereference you get a hashtable + // where the keys are allocs for the variables and the + // values are from following the second hop + public Set canPointToAt( TempDescriptor x, + FlatNode programPoint ); + + public Set canPointToAfter( TempDescriptor x, + FlatNode programPoint ); + + public Hashtable< Alloc, Set > canPointToAt( TempDescriptor x, + FieldDescriptor f, + FlatNode programPoint ); + + public Hashtable< Alloc, Set > canPointToAtElement( TempDescriptor x, // x[i] + FlatNode programPoint ); } diff --git a/Robust/src/Analysis/Disjoint/ReachGraph.java b/Robust/src/Analysis/Disjoint/ReachGraph.java index f43df03a..6cd946f9 100644 --- a/Robust/src/Analysis/Disjoint/ReachGraph.java +++ b/Robust/src/Analysis/Disjoint/ReachGraph.java @@ -5189,4 +5189,77 @@ public class ReachGraph { public Set getInaccessibleVars() { return inaccessibleVars; } + + + + + public Set canPointTo( TempDescriptor x ) { + VariableNode vn = getVariableNodeNoMutation( x ); + if( vn == null ) { + return null; + } + + Set out = new HashSet(); + + Iterator edgeItr = vn.iteratorToReferencees(); + while( edgeItr.hasNext() ) { + HeapRegionNode hrn = edgeItr.next().getDst(); + + out.add( hrn.getAllocSite() ); + } + + return out; + } + + + + public Hashtable< Alloc, Set > canPointTo( TempDescriptor x, + String field ) { + + VariableNode vn = getVariableNodeNoMutation( x ); + if( vn == null ) { + return null; + } + + Hashtable< Alloc, Set > out = new Hashtable< Alloc, Set >(); + + Iterator edgeItr = vn.iteratorToReferencees(); + while( edgeItr.hasNext() ) { + HeapRegionNode hrn = edgeItr.next().getDst(); + + Alloc key = hrn.getAllocSite(); + + Set moreValues = new HashSet(); + Iterator edgeItr2 = hrn.iteratorToReferencees(); + while( edgeItr2.hasNext() ) { + RefEdge edge = edgeItr2.next(); + + if( field.equals( edge.getField() ) ) { + moreValues.add( edge.getDst().getAllocSite() ); + } + } + + if( out.containsKey( key ) ) { + out.get( key ).addAll( moreValues ); + } else { + out.put( key, moreValues ); + } + } + + return out; + } + + + + // for debugging + public TempDescriptor findVariableByName( String name ) { + + for( TempDescriptor td: td2vn.keySet() ) { + if( td.getSymbol().contains( name ) ) { + return td; + } + } + + return null; + } } diff --git a/Robust/src/Analysis/OoOJava/OoOJavaAnalysis.java b/Robust/src/Analysis/OoOJava/OoOJavaAnalysis.java index 709a2120..c361c747 100644 --- a/Robust/src/Analysis/OoOJava/OoOJavaAnalysis.java +++ b/Robust/src/Analysis/OoOJava/OoOJavaAnalysis.java @@ -85,7 +85,7 @@ public class OoOJavaAnalysis { return fm; } - public HeapAnalysis getDisjointAnalysis() { + public HeapAnalysis getHeapAnalysis() { return disjointAnalysisTaints; } diff --git a/Robust/src/Analysis/Pointer/Pointer.java b/Robust/src/Analysis/Pointer/Pointer.java index c38ae5a1..447d321e 100644 --- a/Robust/src/Analysis/Pointer/Pointer.java +++ b/Robust/src/Analysis/Pointer/Pointer.java @@ -2092,4 +2092,34 @@ nextdelta: } } } -} \ No newline at end of file + + + + + public Alloc getCmdLineArgsAlloc() { + return null; + } + + + + public Set canPointToAt( TempDescriptor x, + FlatNode programPoint ) { + return null; + } + + public Set canPointToAfter( TempDescriptor x, + FlatNode programPoint ) { + return null; + } + + public Hashtable< Alloc, Set > canPointToAt( TempDescriptor x, + FieldDescriptor f, + FlatNode programPoint ) { + return null; + } + + public Hashtable< Alloc, Set > canPointToAtElement( TempDescriptor x, + FlatNode programPoint ) { + return null; + } +} diff --git a/Robust/src/Benchmarks/oooJava/master-makefile b/Robust/src/Benchmarks/oooJava/master-makefile index b517a763..6f5622dd 100644 --- a/Robust/src/Benchmarks/oooJava/master-makefile +++ b/Robust/src/Benchmarks/oooJava/master-makefile @@ -32,16 +32,19 @@ USECOREPROF= #-coreprof $(COREPROFOVERFLOW) \ -coreprof-enable cpe_taskstallmem -USEOOO= -ooojava $(NUM_OOO_WORKERS) 2 -squeue #-ooodebug-disable-task-mem-pool +USEOOO= -ooojava $(NUM_OOO_WORKERS) 2 -squeue #-ooodebug-disable-task-mem-pool USERCR= -ooojava $(NUM_RCR_WORKERS) 2 -rcr -squeue -ooodebug OOODEBUG= -ooodebug -printlinenum RCRDEBUG= -rcr_debug -printlinenum RCRDEBUGV= -rcr_debug_verbose -printlinenum -BSFLAGS= -64bit -mainclass $(PROGRAM) -heapsize-mb 8000 -garbagestats -joptimize -noloop -optimize -nolock -debug #-nooptimize #src-after-pp +BSFLAGS= -64bit -mainclass $(PROGRAM) -heapsize-mb 5000 -garbagestats -joptimize -noloop -optimize -nolock -debug #-nooptimize #src-after-pp + + +CHECKPOINTSTO= -disjoint -pointsto-check-v-runtime DRELEASEMODE=-disjoint-release-mode -disjoint-dvisit-stack-callees-on-top -disjoint-alias-file aliases.txt tabbed -DISJOINT= -disjoint -disjoint-k 1 -enable-assertions $(DRELEASEMODE) #-disjoint-desire-determinism +DISJOINT= -disjoint -disjoint-k 1 -enable-assertions $(DRELEASEMODE) #-disjoint-desire-determinism ##################################### @@ -93,10 +96,19 @@ single-remake-c: rcr-remake-c: $(BUILDSCRIPT) -nojava $(BMFLAGS) $(BSFLAGS) $(USECOREPROF) $(USERCR) $(DISJOINT) -o $(PROGRAM)r -builddir rcr $(SOURCE_FILES) + single: $(PROGRAM)s.bin $(PROGRAM)s.bin: $(SOURCE_FILES) ../master-makefile - $(BUILDSCRIPT) -thread $(BMFLAGS) $(BSFLAGS) $(USECOREPROF) -o $(PROGRAM)s -builddir sing $(SOURCE_FILES) + $(BUILDSCRIPT) $(BMFLAGS) $(BSFLAGS) $(USECOREPROF) -o $(PROGRAM)s -builddir sing $(SOURCE_FILES) + + +check-pointsto: $(PROGRAM)c.bin + +$(PROGRAM)c.bin: $(SOURCE_FILES) ../master-makefile + $(BUILDSCRIPT) $(BMFLAGS) $(BSFLAGS) $(USECOREPROF) $(CHECKPOINTSTO) -o $(PROGRAM)c -builddir chk $(SOURCE_FILES) + + ooo: $(PROGRAM)p.bin diff --git a/Robust/src/IR/Flat/BCXPointsToCheckVRuntime.java b/Robust/src/IR/Flat/BCXPointsToCheckVRuntime.java new file mode 100644 index 00000000..ce47b099 --- /dev/null +++ b/Robust/src/IR/Flat/BCXPointsToCheckVRuntime.java @@ -0,0 +1,329 @@ +package IR.Flat; + +import Analysis.Disjoint.HeapAnalysis; +import Analysis.Disjoint.Alloc; +import IR.*; + +import java.io.*; +import java.util.*; + + +// This BuildCode Extension (BCX) takes a heap analysis +// with points-to information and generates checks at runtime +// verifies the allocation site of objects pointed-to. It +// doesn't fully verify an analysis but it can reveal bugs! + + +public class BCXPointsToCheckVRuntime implements BuildCodeExtension { + + protected BuildCode buildCode; + protected HeapAnalysis heapAnalysis; + + + public BCXPointsToCheckVRuntime( BuildCode buildCode, + HeapAnalysis heapAnalysis ) { + this.buildCode = buildCode; + this.heapAnalysis = heapAnalysis; + } + + + public void additionalIncludesMethodsHeader(PrintWriter outmethodheader) { + outmethodheader.println("#include \"assert.h\""); + } + + + public void additionalCodeAtTopFlatMethodBody(PrintWriter output, FlatMethod fm) { + + for( int i = 0; i < fm.numParameters(); ++i ) { + TempDescriptor td = fm.getParameter( i ); + TypeDescriptor type = td.getType(); + if( type.isPtr() ) { + genAssertRuntimePtrVsHeapResults( output, + fm, + td, + heapAnalysis.canPointToAfter( td, fm ) + ); + } + } + } + + + public void additionalCodePreNode(FlatMethod fm, FlatNode fn, PrintWriter output) { + + TempDescriptor lhs; + TempDescriptor rhs; + FieldDescriptor fld; + TempDescriptor idx; + TypeDescriptor type; + + + switch( fn.kind() ) { + + case FKind.FlatOpNode: { + FlatOpNode fon = (FlatOpNode) fn; + if( fon.getOp().getOp() == Operation.ASSIGN ) { + lhs = fon.getDest(); + rhs = fon.getLeft(); + + type = lhs.getType(); + if( type.isPtr() ) { + genAssertRuntimePtrVsHeapResults( output, + fm, + lhs, + heapAnalysis.canPointToAt( lhs, fn ) + ); + + genAssertRuntimePtrVsHeapResults( output, + fm, + rhs, + heapAnalysis.canPointToAt( rhs, fn ) + ); + } + } + } break; + + + case FKind.FlatCastNode: { + FlatCastNode fcn = (FlatCastNode) fn; + lhs = fcn.getDst(); + rhs = fcn.getSrc(); + + type = fcn.getType(); + if( type.isPtr() ) { + genAssertRuntimePtrVsHeapResults( output, + fm, + lhs, + heapAnalysis.canPointToAt( lhs, fn ) + ); + + genAssertRuntimePtrVsHeapResults( output, + fm, + rhs, + heapAnalysis.canPointToAt( rhs, fn ) + ); + } + } break; + + + case FKind.FlatFieldNode: { + FlatFieldNode ffn = (FlatFieldNode) fn; + lhs = ffn.getDst(); + rhs = ffn.getSrc(); + fld = ffn.getField(); + + type = lhs.getType(); + if( type.isPtr() ) { + genAssertRuntimePtrVsHeapResults( output, + fm, + lhs, + heapAnalysis.canPointToAt( lhs, fn ) + ); + + genAssertRuntimePtrVsHeapResults( output, + fm, + rhs, + fld, + null, + heapAnalysis.canPointToAt( rhs, fld, fn ) + ); + } + } break; + + + case FKind.FlatElementNode: { + FlatElementNode fen = (FlatElementNode) fn; + lhs = fen.getDst(); + rhs = fen.getSrc(); + idx = fen.getIndex(); + + type = lhs.getType(); + if( type.isPtr() ) { + genAssertRuntimePtrVsHeapResults( output, + fm, + lhs, + heapAnalysis.canPointToAt( lhs, fn ) + ); + + genAssertRuntimePtrVsHeapResults( output, + fm, + rhs, + null, + idx, + heapAnalysis.canPointToAtElement( rhs, fn ) + ); + } + } break; + + } + + } + + + public void additionalCodePostNode(FlatMethod fm, + FlatNode fn, + PrintWriter output) { + switch( fn.kind() ) { + case FKind.FlatCall: { + FlatCall fc = (FlatCall) fn; + TempDescriptor td = fc.getReturnTemp(); + + if( td != null ) { + TypeDescriptor type = td.getType(); + if( type.isPtr() ) { + genAssertRuntimePtrVsHeapResults( output, + fm, + td, + heapAnalysis.canPointToAfter( td, fn ) + ); + } + } + } break; + } + } + + + + protected void + genAssertRuntimePtrVsHeapResults( PrintWriter output, + FlatMethod context, + TempDescriptor x, + Set targetsByAnalysis ) { + + output.println( "" ); + output.println( "// asserts vs. heap results (DEBUG)" ); + + if( targetsByAnalysis == null || + targetsByAnalysis.isEmpty() ) { + output.println( "assert( "+ + buildCode.generateTemp( context, x )+ + " == NULL );\n" ); + + } else { + output.print( "assert( "+ + buildCode.generateTemp( context, x )+ + " == NULL || " ); + + Iterator aItr = targetsByAnalysis.iterator(); + while( aItr.hasNext() ) { + Alloc a = aItr.next(); + output.print( buildCode.generateTemp( context, x )+ + "->allocsite == "+ + a.getUniqueAllocSiteID() + ); + if( aItr.hasNext() ) { + output.print( " || " ); + } + } + + output.println( " );\n" ); + } + } + + + + protected void + genAssertRuntimePtrVsHeapResults( PrintWriter output, + FlatMethod context, + TempDescriptor x, + FieldDescriptor f, // this null OR + TempDescriptor i, // this null + Hashtable< Alloc, Set > targetsByAnalysis ) { + + assert f == null || i == null; + + output.println( "// asserts vs. heap results (DEBUG)" ); + + if( targetsByAnalysis == null || + targetsByAnalysis.isEmpty() ) { + output.println( "assert( "+ + buildCode.generateTemp( context, x )+ + " == NULL );\n" ); + } else { + output.println( "{" ); + + // if the ptr is null, that's ok, if not check allocsite + output.println( "if( "+ + buildCode.generateTemp( context, x )+ + " != NULL ) {" ); + + // precompute the allocsite, if any, of the object we will + // get from hopping through the first ptr + output.println( "int allocsiteOneHop = -1;" ); + output.println( buildCode.strObjType+"* objOneHop;" ); + + if( f != null ) { + output.println( "objOneHop = ("+buildCode.strObjType+"*) "+ + buildCode.generateTemp( context, x )+ + "->"+f.getSafeSymbol()+";"); + } else { + output.println( "objOneHop = ("+buildCode.strObjType+"*) "+ + "((struct "+x.getType().dereference().getSafeSymbol()+"**)"+ + "(((void*) &("+buildCode.generateTemp( context, x )+"->___length___))+sizeof(int)))"+ + "["+buildCode.generateTemp( context, i )+"];" ); + } + + output.println( "if( objOneHop != NULL ) { allocsiteOneHop = objOneHop->allocsite; }" ); + + output.println( "switch( "+ + buildCode.generateTemp( context, x )+ + "->allocsite ) {" ); + + Iterator kItr = targetsByAnalysis.keySet().iterator(); + while( kItr.hasNext() ) { + Alloc k = kItr.next(); + + output.print( "case "+ + k.getUniqueAllocSiteID()+ + ": assert( allocsiteOneHop == -1" ); + + Set hopTargets = targetsByAnalysis.get( k ); + if( hopTargets != null ) { + + if( !hopTargets.isEmpty() ) { + output.print( " || " ); + } + + Iterator aItr = hopTargets.iterator(); + while( aItr.hasNext() ) { + Alloc a = aItr.next(); + + output.print( "allocsiteOneHop == "+ + a.getUniqueAllocSiteID() ); + + if( aItr.hasNext() ) { + output.print( " || " ); + } + } + } + + output.println( " ); break;" ); + } + + output.println( " default: assert( 0 ); break;" ); + output.println( "}" ); + output.println( "}" ); + output.println( "}\n" ); + } + } + + + + + public void printExtraArrayFields(PrintWriter outclassdefs) {} + public void outputTransCode(PrintWriter output) {} + public void buildCodeSetup() {} + public void generateSizeArrayExtensions(PrintWriter outclassdefs) {} + public void preCodeGenInitialization() {} + public void postCodeGenCleanUp() {} + public void additionalClassObjectFields(PrintWriter outclassdefs) {} + public void additionalCodeGen(PrintWriter outmethodheader, + PrintWriter outstructs, + PrintWriter outmethod) {} + public void additionalCodeAtTopOfMain(PrintWriter outmethod) {} + public void additionalCodeForCommandLineArgs(PrintWriter outmethod, String argsVar) {} + public void additionalCodeAtBottomOfMain(PrintWriter outmethod) {} + public void additionalIncludesMethodsImplementation(PrintWriter outmethod) {} + public void additionalIncludesStructsHeader(PrintWriter outstructs) {} + public void additionalCodeAtTopMethodsImplementation(PrintWriter outmethod) {} + public void additionalCodeNewObject(PrintWriter outmethod, String dstVar, FlatNew flatNew) {} +} diff --git a/Robust/src/IR/Flat/BCXallocsiteObjectField.java b/Robust/src/IR/Flat/BCXallocsiteObjectField.java new file mode 100644 index 00000000..230b20a7 --- /dev/null +++ b/Robust/src/IR/Flat/BCXallocsiteObjectField.java @@ -0,0 +1,67 @@ +package IR.Flat; + +import Analysis.Disjoint.HeapAnalysis; +import Analysis.Disjoint.Alloc; +import IR.*; + +import java.io.*; +import java.util.*; + + +// This BuildCode Extension (BCX) takes a heap analysis +// with points-to information and adds a field to objects +// at runtime that specifies which allocation site it is +// from. This extension supports other extensions. + + +public class BCXallocsiteObjectField implements BuildCodeExtension { + + protected BuildCode buildCode; + protected HeapAnalysis heapAnalysis; + + + public BCXallocsiteObjectField( BuildCode buildCode, + HeapAnalysis heapAnalysis ) { + this.buildCode = buildCode; + this.heapAnalysis = heapAnalysis; + } + + + public void additionalClassObjectFields(PrintWriter outclassdefs) { + outclassdefs.println(" int allocsite;"); + } + + public void additionalCodeForCommandLineArgs(PrintWriter outmethod, String argsVar) { + outmethod.println(argsVar+"->allocsite = "+ + heapAnalysis.getCmdLineArgsAlloc().getUniqueAllocSiteID()+ + ";" + ); + } + + public void additionalCodeNewObject(PrintWriter outmethod, String dstVar, FlatNew flatNew) { + outmethod.println(dstVar+"->allocsite = "+ + heapAnalysis.getAllocationSiteFromFlatNew( flatNew ).getUniqueAllocSiteID()+ + ";" + ); + } + + + public void printExtraArrayFields(PrintWriter outclassdefs) {} + public void outputTransCode(PrintWriter output) {} + public void buildCodeSetup() {} + public void generateSizeArrayExtensions(PrintWriter outclassdefs) {} + public void preCodeGenInitialization() {} + public void postCodeGenCleanUp() {} + public void additionalCodeGen(PrintWriter outmethodheader, + PrintWriter outstructs, + PrintWriter outmethod) {} + public void additionalCodeAtTopOfMain(PrintWriter outmethod) {} + public void additionalCodeAtBottomOfMain(PrintWriter outmethod) {} + public void additionalIncludesMethodsImplementation(PrintWriter outmethod) {} + public void additionalIncludesStructsHeader(PrintWriter outstructs) {} + public void additionalCodeAtTopMethodsImplementation(PrintWriter outmethod) {} + public void additionalIncludesMethodsHeader(PrintWriter outmethodheader) {} + public void additionalCodeAtTopFlatMethodBody(PrintWriter output, FlatMethod fm) {} + public void additionalCodePreNode(FlatMethod fm, FlatNode fn, PrintWriter output) {} + public void additionalCodePostNode(FlatMethod fm, FlatNode fn, PrintWriter output) {} +} \ No newline at end of file diff --git a/Robust/src/IR/Flat/BuildCode.java b/Robust/src/IR/Flat/BuildCode.java index 0624b996..d61f5b55 100644 --- a/Robust/src/IR/Flat/BuildCode.java +++ b/Robust/src/IR/Flat/BuildCode.java @@ -54,6 +54,7 @@ public class BuildCode { int globaldefscount=0; boolean mgcstaticinit = false; JavaBuilder javabuilder; + String strObjType; int boundschknum = 0; @@ -83,6 +84,10 @@ public class BuildCode { State.logEvent("Virtual"); virtualcalls=new Virtual(state, null, callgraph); printedfieldstbl = new Hashtable(); + extensions = new Vector(); + this.strObjType = + "struct "+ + typeutil.getClass( TypeUtil.ObjectClass ).getSafeSymbol(); } /** The buildCode method outputs C code for all the methods. The Flat @@ -107,6 +112,10 @@ public class BuildCode { try { buildCodeSetup(); //EXTENSION POINT + for(BuildCodeExtension bcx: extensions) { + bcx.buildCodeSetup(); + } + outstructs=new CodePrinter(new FileOutputStream(PREFIX+"structdefs.h"), true); outmethodheader=new CodePrinter(new FileOutputStream(PREFIX+"methodheaders.h"), true); outclassdefs=new CodePrinter(new FileOutputStream(PREFIX+"classdefs.h"), true); @@ -149,6 +158,9 @@ public class BuildCode { } additionalIncludesMethodsHeader(outmethodheader); + for(BuildCodeExtension bcx: extensions) { + bcx.additionalIncludesMethodsHeader(outmethodheader); + } /* Output Structures */ outputStructs(outstructs); @@ -191,6 +203,9 @@ public class BuildCode { // an opportunity for subclasses to do extra // initialization preCodeGenInitialization(); + for(BuildCodeExtension bcx: extensions) { + bcx.preCodeGenInitialization(); + } State.logEvent("Start outputMethods"); /* Build the actual methods */ @@ -199,6 +214,10 @@ public class BuildCode { // opportunity for subclasses to gen extra code additionalCodeGen(outmethodheader, outstructs, outmethod); + for(BuildCodeExtension bcx: extensions) { + bcx.additionalCodeGen(outmethodheader, outstructs, outmethod); + } + if (state.TASK) { /* Output code for tasks */ @@ -234,6 +253,10 @@ public class BuildCode { outstructs.close(); postCodeGenCleanUp(); + for(BuildCodeExtension bcx: extensions) { + bcx.postCodeGenCleanUp(); + } + State.logEvent("End of buildCode"); } @@ -378,6 +401,9 @@ public class BuildCode { additionalCodeAtTopOfMain(outmethod); + for(BuildCodeExtension bcx: extensions) { + bcx.additionalCodeAtTopOfMain(outmethod); + } if ((GENERATEPRECISEGC) || (this.state.MULTICOREGC)) { @@ -396,6 +422,13 @@ public class BuildCode { outmethod.println(" ((void **)(((char *)& stringarray->___length___)+sizeof(int)))[i-1]=newstring;"); outmethod.println(" }"); + + additionalCodeForCommandLineArgs(outmethod, "stringarray"); + for(BuildCodeExtension bcx: extensions) { + bcx.additionalCodeForCommandLineArgs(outmethod, "stringarray"); + } + + MethodDescriptor md=typeutil.getMain(); ClassDescriptor cd=typeutil.getMainClass(); @@ -425,6 +458,10 @@ public class BuildCode { additionalCodeAtBottomOfMain(outmethod); + for(BuildCodeExtension bcx: extensions) { + bcx.additionalCodeAtBottomOfMain(outmethod); + } + outmethod.println("}"); } @@ -503,8 +540,10 @@ public class BuildCode { outmethod.println("#include \"checkers.h\""); } - additionalIncludesMethodsImplementation(outmethod); + for(BuildCodeExtension bcx: extensions) { + bcx.additionalIncludesMethodsImplementation(outmethod); + } outmethod.println("struct global_defs_t * global_defs_p;"); outmethod.println("struct global_defsprim_t * global_defsprim_p;"); @@ -519,6 +558,10 @@ public class BuildCode { additionalCodeAtTopMethodsImplementation(outmethod); + for(BuildCodeExtension bcx: extensions) { + bcx.additionalCodeAtTopMethodsImplementation(outmethod); + } + generateMethods(outmethod); } @@ -560,6 +603,9 @@ public class BuildCode { additionalIncludesStructsHeader(outstructs); + for(BuildCodeExtension bcx: extensions) { + bcx.additionalIncludesStructsHeader(outstructs); + } /* Output #defines that the runtime uses to determine type @@ -629,7 +675,11 @@ public class BuildCode { outclassdefs.println(" int type;"); outclassdefs.println(" int hashcode;"); + additionalClassObjectFields(outclassdefs); + for(BuildCodeExtension bcx: extensions) { + bcx.additionalClassObjectFields(outclassdefs); + } if (state.EVENTMONITOR) { @@ -669,7 +719,12 @@ public class BuildCode { printClassStruct(typeutil.getClass(TypeUtil.ObjectClass), outclassdefs, outglobaldefs, outglobaldefsprim); printedfieldstbl.clear(); + printExtraArrayFields(outclassdefs); + for(BuildCodeExtension bcx: extensions) { + bcx.printExtraArrayFields(outclassdefs); + } + if (state.ARRAYPAD) { outclassdefs.println(" int paddingforarray;"); } @@ -927,7 +982,11 @@ public class BuildCode { protected void generateSizeArray(PrintWriter outclassdefs) { outclassdefs.print("extern struct prefetchCountStats * evalPrefetch;\n"); + generateSizeArrayExtensions(outclassdefs); + for(BuildCodeExtension bcx: extensions) { + bcx.generateSizeArrayExtensions(outclassdefs); + } Iterator it=state.getClassSymbolTable().getDescriptorsIterator(); cdarray=new ClassDescriptor[state.numClasses()]; @@ -1574,6 +1633,9 @@ fldloop: classdefout.println(" int hashcode;"); additionalClassObjectFields(classdefout); + for(BuildCodeExtension bcx: extensions) { + bcx.additionalClassObjectFields(classdefout); + } if (state.EVENTMONITOR) { @@ -1965,6 +2027,9 @@ fldloop: } additionalCodeAtTopFlatMethodBody(output, fm); + for(BuildCodeExtension bcx: extensions) { + bcx.additionalCodeAtTopFlatMethodBody(output, fm); + } /* Check to see if we need to do a GC if this is a * multi-threaded program...*/ @@ -2020,6 +2085,9 @@ fldloop: } additionalCodeAtTopFlatMethodBody(output, fm); + for(BuildCodeExtension bcx: extensions) { + bcx.additionalCodeAtTopFlatMethodBody(output, fm); + } /* Check to see if we need to do a GC if this is a * multi-threaded program...*/ @@ -2207,7 +2275,11 @@ fldloop: protected void generateFlatNode(FlatMethod fm, FlatNode fn, PrintWriter output) { if(state.LINENUM) printSourceLineNumber(fm,fn,output); + additionalCodePreNode(fm, fn, output); + for(BuildCodeExtension bcx: extensions) { + bcx.additionalCodePreNode(fm, fn, output); + } switch(fn.kind()) { case FKind.FlatAtomicEnterNode: @@ -2320,6 +2392,10 @@ fldloop: } additionalCodePostNode(fm, fn, output); + for(BuildCodeExtension bcx: extensions) { + bcx.additionalCodePostNode(fm, fn, output); + } + } public void generateFlatBackEdge(FlatMethod fm, FlatBackEdge fn, PrintWriter output) { @@ -2829,6 +2905,8 @@ fldloop: protected void generateFlatNew(FlatMethod fm, FlatNew fn, PrintWriter output) { + String dst=generateTemp(fm,fn.getDst()); + if (fn.getType().isArray()) { int arrayid=state.getArrayNumber(fn.getType())+state.numClasses(); if ((GENERATEPRECISEGC) || (this.state.MULTICOREGC)) { @@ -2844,11 +2922,14 @@ fldloop: } } if (state.FASTCHECK) { - String dst=generateTemp(fm,fn.getDst()); output.println(dst+"->___localcopy___=(struct ___Object___*)1;"); output.println(dst+"->"+nextobjstr+"="+fcrevert+";"); output.println(fcrevert+"=(struct ___Object___ *)"+dst+";"); } + + for(BuildCodeExtension bcx: extensions) { + bcx.additionalCodeNewObject(output, dst, fn); + } } protected void generateFlatTagDeclaration(FlatMethod fm, FlatTagDeclaration fn, PrintWriter output) { @@ -3568,6 +3649,19 @@ fldloop: return l; } + + + // either create and register an extension object with buildcode + // or look at the following option of subclassing BuildCode + private Vector extensions; + + // note that extensions are invoked in the order they are added + // to BuildCode + public void registerExtension( BuildCodeExtension bcx ) { + extensions.add( bcx ); + } + + // override these methods in a subclass of BuildCode // to generate code for additional systems protected void printExtraArrayFields(PrintWriter outclassdefs) { @@ -3590,6 +3684,8 @@ fldloop: } protected void additionalCodeAtTopOfMain(PrintWriter outmethod) { } + protected void additionalCodeForCommandLineArgs(PrintWriter outmethod, String argsVar) { + } protected void additionalCodeAtBottomOfMain(PrintWriter outmethod) { } protected void additionalIncludesMethodsImplementation(PrintWriter outmethod) { diff --git a/Robust/src/IR/Flat/BuildCodeExtension.java b/Robust/src/IR/Flat/BuildCodeExtension.java new file mode 100644 index 00000000..e7f01333 --- /dev/null +++ b/Robust/src/IR/Flat/BuildCodeExtension.java @@ -0,0 +1,37 @@ +package IR.Flat; + +import java.io.*; + +// implement these methods and register the extension +// object with BuildCode. BuildCode will then invoke the +// methods below at the extension points. + +public interface BuildCodeExtension { + + public void printExtraArrayFields(PrintWriter outclassdefs); + public void outputTransCode(PrintWriter output); + public void buildCodeSetup(); + public void generateSizeArrayExtensions(PrintWriter outclassdefs); + + public void preCodeGenInitialization(); + public void postCodeGenCleanUp(); + + public void additionalCodeGen(PrintWriter outmethodheader, + PrintWriter outstructs, + PrintWriter outmethod); + + public void additionalIncludesMethodsHeader(PrintWriter outmethodheader); + public void additionalIncludesMethodsImplementation(PrintWriter outmethod); + public void additionalIncludesStructsHeader(PrintWriter outstructs); + + public void additionalClassObjectFields(PrintWriter outclassdefs); + + public void additionalCodeAtTopOfMain(PrintWriter outmethod); + public void additionalCodeForCommandLineArgs(PrintWriter outmethod, String argsVar); + public void additionalCodeAtBottomOfMain(PrintWriter outmethod); + public void additionalCodeAtTopMethodsImplementation(PrintWriter outmethod); + public void additionalCodeAtTopFlatMethodBody(PrintWriter output, FlatMethod fm); + public void additionalCodePreNode(FlatMethod fm, FlatNode fn, PrintWriter output); + public void additionalCodePostNode(FlatMethod fm, FlatNode fn, PrintWriter output); + public void additionalCodeNewObject(PrintWriter outmethod, String dstVar, FlatNew flatNew); +} diff --git a/Robust/src/IR/Flat/BuildOoOJavaCode.java b/Robust/src/IR/Flat/BuildOoOJavaCode.java index d1a60285..2acc6dca 100644 --- a/Robust/src/IR/Flat/BuildOoOJavaCode.java +++ b/Robust/src/IR/Flat/BuildOoOJavaCode.java @@ -17,16 +17,18 @@ import Analysis.Locality.*; public class BuildOoOJavaCode extends BuildCode { - OoOJavaAnalysis oooa; + protected OoOJavaAnalysis oooa; - String maxTaskRecSizeStr="__maxTaskRecSize___"; + protected String maxTaskRecSizeStr="__maxTaskRecSize___"; - String mlperrstr = + protected String mlperrstr = "if(status != 0) { "+ "sprintf(errmsg, \"MLP error at %s:%d\", __FILE__, __LINE__); "+ "perror(errmsg); exit(-1); }"; - RuntimeConflictResolver rcr = null; + protected RuntimeConflictResolver rcr = null; + + public BuildOoOJavaCode(State st, Hashtable temptovar, @@ -237,7 +239,6 @@ public class BuildOoOJavaCode extends BuildCode { protected void additionalClassObjectFields(PrintWriter outclassdefs) { outclassdefs.println(" int oid;"); - outclassdefs.println(" int allocsite;"); } @@ -266,37 +267,6 @@ public class BuildOoOJavaCode extends BuildCode { output.println(" SESEcommon* "+dynSrcVar+"_srcSESE = NULL;"); output.println(" INTPTR "+dynSrcVar+"_srcOffset = 0x1;"); } - - - // eom - set up related allocation sites's waiting queues - // TODO: we have to do a table-based thing here... - // jjenista, I THINK WE LOSE THIS ALTOGETHER! - /* - FlatSESEEnterNode callerSESEplaceholder = (FlatSESEEnterNode) fm.getNext( 0 ); - if(callerSESEplaceholder!= oooa.getMainSESE()){ - Analysis.OoOJava.ConflictGraph graph = oooa.getConflictGraph(callerSESEplaceholder); - if (graph != null && graph.hasConflictEdge()) { - output.println(" // set up waiting queues "); - output.println(" int numMemoryQueue=0;"); - output.println(" int memoryQueueItemID=0;"); - Set lockSet = oooa.getLockMappings(graph); - System.out.println("#lockSet="+lockSet.hashCode()); - System.out.println("lockset="+lockSet); - for (Iterator iterator = lockSet.iterator(); iterator.hasNext();) { - Analysis.OoOJava.SESELock seseLock = (Analysis.OoOJava.SESELock) iterator.next(); - System.out.println("id="+seseLock.getID()); - System.out.println("#="+seseLock); - } - System.out.println("size="+lockSet.size()); - if (lockSet.size() > 0) { - output.println(" numMemoryQueue=" + lockSet.size() + ";"); - output.println(" runningSESE->numMemoryQueue=numMemoryQueue;"); - output.println(" runningSESE->memoryQueueArray=mlpCreateMemoryQueueArray(numMemoryQueue);"); - output.println(); - } - } - } - */ } @@ -2039,7 +2009,7 @@ public class BuildOoOJavaCode extends BuildCode { "=allocate_newarray_mlp("+localsprefixaddr+ ", "+arrayid+", "+generateTemp(fm, fn.getSize())+ ", oid, "+ - oooa.getDisjointAnalysis().getAllocationSiteFromFlatNew(fn).getUniqueAllocSiteID()+ + oooa.getHeapAnalysis().getAllocationSiteFromFlatNew(fn).getUniqueAllocSiteID()+ ");"); output.println(" oid += oidIncrement;"); } else { @@ -2056,7 +2026,7 @@ public class BuildOoOJavaCode extends BuildCode { "=allocate_new_mlp("+localsprefixaddr+ ", "+fn.getType().getClassDesc().getId()+ ", oid, "+ - oooa.getDisjointAnalysis().getAllocationSiteFromFlatNew(fn).getUniqueAllocSiteID()+ + oooa.getHeapAnalysis().getAllocationSiteFromFlatNew(fn).getUniqueAllocSiteID()+ ");"); output.println(" oid += oidIncrement;"); } else { @@ -2134,4 +2104,5 @@ public class BuildOoOJavaCode extends BuildCode { return rtr; } + } diff --git a/Robust/src/IR/State.java b/Robust/src/IR/State.java index 51ba8d3a..f741debe 100644 --- a/Robust/src/IR/State.java +++ b/Robust/src/IR/State.java @@ -128,6 +128,10 @@ public class State { public boolean DISJOINTDEBUGSCHEDULING=false; + + public boolean POINTSTO_CHECK_V_RUNTIME=false; + + public boolean OOOJAVA=false; public boolean OOODEBUG=false; public boolean RCR=false; diff --git a/Robust/src/Main/Main.java b/Robust/src/Main/Main.java index b9934846..cfdbe051 100644 --- a/Robust/src/Main/Main.java +++ b/Robust/src/Main/Main.java @@ -15,12 +15,7 @@ import IR.Tree.ParseNode; import IR.Tree.BuildIR; import IR.Tree.JavaBuilder; import IR.Tree.SemanticCheck; -import IR.Flat.BuildCodeMultiCore; -import IR.Flat.BuildCodeMGC; -import IR.Flat.BuildFlat; -import IR.Flat.BuildCode; -import IR.Flat.BuildCodeTran; -import IR.Flat.BuildOoOJavaCode; +import IR.Flat.*; import IR.Flat.Inliner; import IR.ClassDescriptor; import IR.State; @@ -54,6 +49,7 @@ import Analysis.Loops.*; import Analysis.Liveness; import Analysis.ArrayReferencees; import Analysis.Pointer.Pointer; +import Analysis.Disjoint.HeapAnalysis; import IR.MethodDescriptor; import IR.Flat.FlatMethod; import Interface.*; @@ -75,7 +71,7 @@ public class Main { String outputdir = null; boolean isDistributeInfo = false; boolean isDisAll = false; - int startnum = 0; + int startnum = 0; for(int i=0; ioid=oid; - v->allocsite=allocsite; + // v->allocsite=allocsite; #endif return v; } diff --git a/Robust/src/buildscript b/Robust/src/buildscript index b6c03fd8..7abaee63 100755 --- a/Robust/src/buildscript +++ b/Robust/src/buildscript @@ -50,6 +50,8 @@ echo -disjoint-dvisit-stack-callees-on-top alternate stack strat echo -disjoint-dvisit-pqueue use prio. q strat to visit descriptors echo -disjoint-desire-determinism set above interproc for determinism echo -disjoint-debug-scheduling debug when methods are scheduled for analysis +echo +echo -pointsto-check-v-runtime check allocation site of pointer targets at runtime to help verify heap analysis results echo echo "-mlp build mlp code" echo -mlpdebug if mlp, report progress and interim results @@ -817,10 +819,11 @@ else then #threading java stuff JAVAOPTS="$JAVAOPTS -classlibrary $ROBUSTROOT/ClassLibrary/JavaThread" - fi - #base java stuff - JAVAOPTS="$JAVAOPTS -classlibrary $ROBUSTROOT/ClassLibrary/Java" + else + #base java stuff + JAVAOPTS="$JAVAOPTS -classlibrary $ROBUSTROOT/ClassLibrary/Java" + fi fi # everyone gets this except ssjava!