diff options
Diffstat (limited to 'chapter28b/src/main/java/com/seaofnodes')
5 files changed, 72 insertions, 133 deletions
diff --git a/chapter28b/src/main/java/com/seaofnodes/simple/codegen/ClassInitDependencies.java b/chapter28b/src/main/java/com/seaofnodes/simple/codegen/ClassInitDependencies.java index d95f55f2..9a544685 100644 --- a/chapter28b/src/main/java/com/seaofnodes/simple/codegen/ClassInitDependencies.java +++ b/chapter28b/src/main/java/com/seaofnodes/simple/codegen/ClassInitDependencies.java @@ -150,16 +150,6 @@ public class ClassInitDependencies { return null; } - // A condition-producing helper outside the SCC can eliminate a cycle. - // Before reporting one, restore the full-IR precision of the original check. - // Called only after check() has found a cycle. - Ary<CompUnit> cycleImports() { - Ary<CompUnit> units = new Ary<>(CompUnit.class); - for( FunNode fun : _code._linker ) - if( fun!=null && fun.summary()!=null && units.find(fun._compunit)==-1 ) units.add(fun._compunit); - return units; - } - // Every internal edge of an SCC belongs to a cycle. Print all of them: // stack order is not a path, and enumerating all cycle paths can explode. // This bookkeeping and formatting are only needed on an error. diff --git a/chapter28b/src/main/java/com/seaofnodes/simple/codegen/CodeGen.java b/chapter28b/src/main/java/com/seaofnodes/simple/codegen/CodeGen.java index ddcdba3c..e56068e7 100644 --- a/chapter28b/src/main/java/com/seaofnodes/simple/codegen/CodeGen.java +++ b/chapter28b/src/main/java/com/seaofnodes/simple/codegen/CodeGen.java @@ -523,28 +523,9 @@ public class CodeGen { } // TypeCheck saves its successful analysis for Serialize. Loading bodies - // or entering another graph-changing phase discards it; no stale edges - // survive a later Iter/FinalizeIR/TypeCheck sequence. + // or entering another graph-changing phase discards it. ClassInitDependencies _classInitDependencies; - ClassInitDependencies resolveInitCycles() { - while( true ) { - ClassInitDependencies deps = new ClassInitDependencies(this); - String cycle = deps.check(); - if( cycle==null ) return deps; - Ary<CompUnit> units = deps.cycleImports(); - if( units.isEmpty() ) throw Parser.error(cycle,null); - for( CompUnit cu : units ) ParseAll.loadCompUnit(this,cu); - Phase prior = _phase; - try { - _phase=Phase.IterPostOpto; - _iter.iterate(this); - _phase=Phase.FinalizeIR; - FinalizeIR.run(this); - } finally { _phase=prior; } - } - } - public CodeGen finalizeIR() { return phase(Phase.FinalizeIR, _phase==Phase.IterPostOpto, () -> FinalizeIR.run(this)); } // Cross-phase `keep()`s belong here! We have a few nodes which we can diff --git a/chapter28b/src/main/java/com/seaofnodes/simple/codegen/Serialize.java b/chapter28b/src/main/java/com/seaofnodes/simple/codegen/Serialize.java index 3e4adf5f..32027cb5 100644 --- a/chapter28b/src/main/java/com/seaofnodes/simple/codegen/Serialize.java +++ b/chapter28b/src/main/java/com/seaofnodes/simple/codegen/Serialize.java @@ -450,113 +450,76 @@ public class Serialize { String[] strs = tread.strs(); GlobalBits fileAliases = tread.fileAliases(); - CodeGen.Phase prior = code._phase; - code._phase=CodeGen.Phase.Parse; // Constructors must tolerate an incomplete graph. - try { - // D - Read the nodes - - // Number of nodes - int num = bais.packed4(); - // Packed array of nodes - Ary<Node> nodes = new Ary<>(Node.class); - CompUnit cu = null; - for( int i = 0; i<num; i++ ) { - Node.Tag tag = Node.Tag.VALS[bais.packed1()]; - Type t = types[bais.packed2()]; - Node n = tag.make(bais,strs,types,fileAliases,aliases); - n._type = t; - nodes.push(n); - // A little extra for FunNodes - if( n instanceof StartCUNode startcu ) { - cu = code._compunits.get(startcu._fname==null ? (code._srcName==null ? "Test" : code._srcName) : startcu._fname); - assert cu != null; - } - if( n instanceof StopCUNode stopcu ) { - cu = null; - } - if( n instanceof FunNode fun ) { - assert cu != null; - fun._compunit = cu; - if( fun._name==null || fun._name.isEmpty() ) fun._name=fidxs.symbol(fun.sig().fidx()); - } - if( n instanceof ExternNode ext && ext._con instanceof TypeFunPtr tfp && tfp.isConstant() ) { - String old = code.externFunc(tfp.fidx()); - if( old == null ) - code.externFunc(tfp.fidx(), ext._extern); - else - assert old.equals(ext._extern); - } + // D - Read the nodes + + // Number of nodes + int num = bais.packed4(); + // Packed array of nodes + Ary<Node> nodes = new Ary<>(Node.class); + CompUnit cu = null; + for( int i = 0; i<num; i++ ) { + Node.Tag tag = Node.Tag.VALS[bais.packed1()]; + Type t = types[bais.packed2()]; + Node n = tag.make(bais,strs,types,fileAliases,aliases); + n._type = t; + nodes.push(n); + // A little extra for FunNodes + if( n instanceof StartCUNode startcu ) { + cu = code._compunits.get(startcu._fname==null ? (code._srcName==null ? "Test" : code._srcName) : startcu._fname); + assert cu != null; + } + if( n instanceof StopCUNode stopcu ) { + cu = null; + } + if( n instanceof FunNode fun ) { + assert cu != null; + fun._compunit = cu; + if( fun._name==null || fun._name.isEmpty() ) fun._name=fidxs.symbol(fun.sig().fidx()); + } + if( n instanceof ExternNode ext && ext._con instanceof TypeFunPtr tfp && tfp.isConstant() ) { + String old = code.externFunc(tfp.fidx()); + if( old == null ) + code.externFunc(tfp.fidx(), ext._extern); + else + assert old.equals(ext._extern); } + } - // Node edges - for( Node n : nodes ) { - int len = n.nIns(); - for( int i = 0; i<len; i++ ) { - int idx = bais.packed2(); - Node def = idx==0 ? null : nodes.at(idx-1); - // MemMerge precise aliases are encoded by their input slot. - // Remap populated file-local slots into this compilation's - // local alias numbering; null holes carry no identity. - int local = i; - if( n instanceof MemMergeNode && i >= GlobalBits.RESERVED ) { - if( def == null ) continue; - local = aliases.map(fileAliases,i); - } - n.setDefX(local,def); - // Call's output[0] is always the CallEnd - if( n instanceof CallEndNode cend && i==0 ) { - var outs = cend.call()._outputs; - outs.swap(0,outs._len-1); - } + // Node edges + for( Node n : nodes ) { + int len = n.nIns(); + for( int i = 0; i<len; i++ ) { + int idx = bais.packed2(); + Node def = idx==0 ? null : nodes.at(idx-1); + // MemMerge precise aliases are encoded by their input slot. + // Remap populated file-local slots into this compilation's + // local alias numbering; null holes carry no identity. + int local = i; + if( n instanceof MemMergeNode && i >= GlobalBits.RESERVED ) { + if( def == null ) continue; + local = aliases.map(fileAliases,i); } - // A little extra for FunNodes - if( n instanceof FunNode fun ) { - // Return is hooked like an edge - ReturnNode ret = (ReturnNode)nodes.at(bais.packed2()-1); - fun.setRet(ret); - ret._fun = fun; + n.setDefX(local,def); + // Call's output[0] is always the CallEnd + if( n instanceof CallEndNode cend && i==0 ) { + var outs = cend.call()._outputs; + outs.swap(0,outs._len-1); } } - // Add edge from Start to Stop - StartNode start = (StartNode)nodes.at(0); - StopNode stop = (StopNode)nodes.last(); - start.setDef(1,stop); - - // A body materialized after SCCP joins a different analysis context. - // Its saved types are reset and checked by the ensuing fixed-point solve. - assert prior!=CodeGen.Phase.Parse || check(code,nodes); - elf._nodes = nodes; - } finally { code._phase=prior; } - } - - // Check loaded types and nodes are consistent - private static boolean check( CodeGen code, Ary<Node> nodes ) { - // Loaded nodes are complete, unlike nodes still being built by the - // parser. Recompute them with post-parse semantics. The compilation- - // unit Stop is the exception: its escape type depends on the complete - // program's public interface, which ParseAll freezes only after every - // compilation unit has been loaded. - boolean good = true; - CodeGen.Phase phase = code._phase; - code._phase = CodeGen.Phase.Opto; - try { - for( Node n : nodes ) { - if( n instanceof StopCUNode && !code.publicInterfaceFrozen() ) - continue; - // Cross-object calls are relinked only after every body has - // loaded. Their saved return types cannot be recomputed yet. - if( n instanceof CallEndNode end && end.call().fptr()._type instanceof TypeFunPtr fp && - end.nIns()<=fp.nfcns() ) continue; - Type nval = n.compute(); - if( nval != n._type ) { - System.err.println("Node "+n+" read in as "+n._type+" but computes as "+nval); - good = false; - } + // A little extra for FunNodes + if( n instanceof FunNode fun ) { + // Return is hooked like an edge + ReturnNode ret = (ReturnNode)nodes.at(bais.packed2()-1); + fun.setRet(ret); + ret._fun = fun; } - } finally { - code._phase = phase; } - return good; + // Add edge from Start to Stop + StartNode start = (StartNode)nodes.at(0); + StopNode stop = (StopNode)nodes.last(); + start.setDef(1,stop); + + elf._nodes = nodes; } // -------------------------------------------------- diff --git a/chapter28b/src/main/java/com/seaofnodes/simple/codegen/TypeCheck.java b/chapter28b/src/main/java/com/seaofnodes/simple/codegen/TypeCheck.java index 78794096..a5eaa5ca 100644 --- a/chapter28b/src/main/java/com/seaofnodes/simple/codegen/TypeCheck.java +++ b/chapter28b/src/main/java/com/seaofnodes/simple/codegen/TypeCheck.java @@ -10,8 +10,12 @@ import com.seaofnodes.simple.util.Ary; abstract class TypeCheck { static void run(CodeGen code) { // Check for class-init cycles first; such a cycle can prevent other - // things from resolving types. Serialize can reuse the final graph. - code._classInitDependencies = code.resolveInitCycles(); + // things from resolving types. Use the graph and summaries left by + // optimization; do not load more bodies to disprove a possible cycle. + ClassInitDependencies deps = new ClassInitDependencies(code); + String cycle = deps.check(); + if( cycle!=null ) throw Parser.error(cycle,null); + code._classInitDependencies = deps; // Serialize reuses this checked graph. Ary<Node> errs = new Ary<>(Node.class); code._stop.walk( n -> { diff --git a/chapter28b/src/main/java/com/seaofnodes/simple/node/StopNode.java b/chapter28b/src/main/java/com/seaofnodes/simple/node/StopNode.java index a7e52563..6d453324 100644 --- a/chapter28b/src/main/java/com/seaofnodes/simple/node/StopNode.java +++ b/chapter28b/src/main/java/com/seaofnodes/simple/node/StopNode.java @@ -15,7 +15,8 @@ public class StopNode extends CFGNode { public StopNode() { super(); - _type = compute(); + // Edges may still be missing, including when loading a StopCU. + _type = TypeTuple.STATE; } public StopNode(StopNode stop) { super(stop); } @Override public Tag serialTag() { return Tag.Stop; } |
