protected void mergeHandler( Type type, T store, List<Pair<Type, String>> handlers, Map<String, T> stores) { for (Pair<Type, String> p : handlers) { Type handler = p.first(); if (Type.isSubtype(handler, type)) { T nstore = propagate(handler, store); merge(p.second(), nstore, stores); return; // completely subsumed } else if (Type.isSubtype(type, handler)) { T nstore = propagate(handler, store); merge(p.second(), nstore, stores); // not completely subsumed type = Type.intersect(type, Type.Negation(handler)); } } }
protected T propagate(int start, int end, T store, List<Pair<Type, String>> handlers) { for (int i = start; i < end; ++i) { Entry entry = block.get(i); try { Code code = entry.code; // First, check for a label which may have incoming information. if (code instanceof Code.Label) { Code.Label l = (Code.Label) code; T tmp = stores.get(l.label); if (tmp != null && store != null) { store = join(store, tmp); } else if (tmp != null) { store = tmp; } } T oldStore = store; if (store == null) { // this indicates dead-code has been reached. continue; } else if (code instanceof Code.Loop) { Code.Loop loop = (Code.Loop) code; Block.Entry nEntry = entry; int s = i; // Note, I could make this more efficient! while (++i < block.size()) { nEntry = block.get(i); if (nEntry.code instanceof Code.Label) { Code.Label l = (Code.Label) nEntry.code; if (l.label.equals(loop.target)) { // end of loop body found break; } } } store = propagate(s, i, loop, entry, store, handlers); continue; } else if (code instanceof Code.IfGoto) { Code.IfGoto ifgoto = (Code.IfGoto) code; Pair<T, T> r = propagate(i, ifgoto, entry, store); store = r.second(); merge(ifgoto.target, r.first(), stores); } else if (code instanceof Code.IfType) { Code.IfType ifgoto = (Code.IfType) code; Pair<T, T> r = propagate(i, ifgoto, entry, store); store = r.second(); merge(ifgoto.target, r.first(), stores); } else if (code instanceof Code.Switch) { Code.Switch sw = (Code.Switch) code; List<T> r = propagate(i, sw, entry, store); // assert r.second().size() == nsw.branches.size() Code.Switch nsw = (Code.Switch) entry.code; for (int j = 0; j != nsw.branches.size(); ++j) { String target = nsw.branches.get(j).second(); T nstore = r.get(j); merge(target, nstore, stores); } merge(sw.defaultTarget, store, stores); store = null; } else if (code instanceof Code.TryCatch) { Code.TryCatch sw = (Code.TryCatch) code; int s = i; // Note, I could make this more efficient! while (++i < block.size()) { entry = block.get(i); if (entry.code instanceof Code.Label) { Code.Label l = (Code.Label) entry.code; if (l.label.equals(sw.target)) { // end of loop body found break; } } } ArrayList<Pair<Type, String>> nhandlers = new ArrayList<Pair<Type, String>>(handlers); nhandlers.addAll(0, sw.catches); store = propagate(s + 1, i, store, nhandlers); i = i - 1; // this is necessary since last label of // try-catch is first label of catch handler } else if (code instanceof Code.Goto) { Code.Goto gto = (Code.Goto) entry.code; merge(gto.target, store, stores); store = null; } else { // This indicates a sequential statement was encountered. store = propagate(i, entry, store); if (entry.code instanceof Code.Return || entry.code instanceof Code.Throw) { store = null; } } mergeHandlers(i, code, oldStore, handlers, stores); } catch (SyntaxError se) { throw se; } catch (Throwable ex) { internalFailure("internal failure", filename, entry, ex); } } return store; }