internal CCNodeOpcode Propagate(int addr2, CCNodeOpcode node, CCStack nstack, CCLocals nlocals) { if (node == null) { node = GetNode(addr2); } node.MergeStack(nstack); node.MergeLocals(nlocals); return(node); }
internal static CCLocals Merge(CCLocals l1, CCLocals l2) { string err; CCLocals ccl = MergeNF(l1, l2, out err); if (ccl == null) { throw new Exception(err); } return(ccl); }
internal CCLocals Set(int index, CCTypeSet cts) { CCTypeSet octs = locals[index]; if (!cts.IsSubsetOf(octs)) { CCLocals r = new CCLocals(locals.Length); Array.Copy(locals, 0, r.locals, 0, locals.Length); r.locals[index] = cts; return(r); } else { return(this); } }
internal void MergeLocals(CCLocals locals2) { if (Locals == null) { Locals = locals2; MarkUpdate(); } else { CCLocals nlocals = CCLocals.Merge(Locals, locals2); if (Locals != nlocals) { Locals = nlocals; MarkUpdate(); } } }
internal static CCNodeEntry EnterFunction(FunctionInterpreted fi, CCStack stack, CCNodeEntry parent, CCNode next) { if (Compiler.PrintFunctions != null) { fi.Print(Compiler.PrintFunctions, 1); } CCLocals locals = new CCLocals(fi.numLocalFieldsCoalesced); CCFunctionInterpreted cfi = new CCFunctionInterpreted(fi, next); CCNodeEntry node = new CCNodeEntry(parent, cfi); cfi.SetNode(0, node); node.MergeStack(stack); node.MergeLocals(locals); /* * All instances allocated locally by this function must * have instantiable types. */ foreach (XType xt in fi.localEmbedTypes) { xt.Close(); } /* * Infinite recursion detection: if the same function is * already present several times in the ancestry, * complains. (TODO: make the threshold configurable) */ int rc = 0; for (CCNodeEntry e = parent; e != null; e = e.parent) { if (e.cfi.fi == fi) { if (++rc >= 5) { throw new Exception(string.Format("possible infinite recursion on function {0}", fi.DebugName)); } } } return(node); }
internal void PropagateBranch(int disp, CCStack nstack, CCLocals nlocals) { branch = Propagate(addr + 1 + disp, branch, nstack, nlocals); }
internal void PropagateBranch(int disp, CCLocals nlocals) { PropagateBranch(disp, Stack, nlocals); }
internal void PropagateNext(CCStack nstack, CCLocals nlocals) { next = Propagate(addr + 1, next, nstack, nlocals); }
internal void PropagateNext(CCLocals nlocals) { PropagateNext(Stack, nlocals); }
internal static CCLocals MergeNF( CCLocals l1, CCLocals l2, out string err) { err = null; if (object.ReferenceEquals(l1, l2)) { return(l1); } int n = l1.locals.Length; if (n != l2.locals.Length) { err = string.Format("internal error: mismatch on number of locals ({0} / {1})", n, l2.locals.Length); return(null); } /* * Merge entries one by one. The destination is lazily * updated to avoid allocation when not needed. */ bool r1ok = true, r2ok = true; CCTypeSet[] nlocals = null; for (int i = 0; i < n; i++) { CCTypeSet cts1 = l1.locals[i]; CCTypeSet cts2 = l2.locals[i]; if (cts1.Equals(cts2)) { if (nlocals != null) { nlocals[i] = cts1; } } else if (cts1.IsSubsetOf(cts2)) { r1ok = false; if (r2ok) { continue; } if (nlocals != null) { nlocals[i] = cts2; } } else if (cts2.IsSubsetOf(cts1)) { r2ok = false; if (r1ok) { continue; } if (nlocals != null) { nlocals[i] = cts1; } } else { if (nlocals == null) { r1ok = false; r2ok = false; nlocals = new CCTypeSet[n]; Array.Copy(l1.locals, 0, nlocals, 0, i); } CCTypeSet cts = CCTypeSet.MergeNF( cts1, cts2, out err); if (cts == null) { return(null); } nlocals[i] = cts; } } if (r1ok) { return(l1); } if (r2ok) { return(l2); } return(new CCLocals(nlocals)); }