From 00417db6b2dddabade50e6d990c0a903a3464382 Mon Sep 17 00:00:00 2001 From: Steven Date: Fri, 23 May 2014 18:01:33 +0200 Subject: [PATCH] getDefsOfAt local-change workaround --- src/soot/toolkits/scalar/SmartLocalDefs.java | 153 +++++++++---------- 1 file changed, 73 insertions(+), 80 deletions(-) diff --git a/src/soot/toolkits/scalar/SmartLocalDefs.java b/src/soot/toolkits/scalar/SmartLocalDefs.java index 38f3f3a6c4a..6c74861b6ca 100644 --- a/src/soot/toolkits/scalar/SmartLocalDefs.java +++ b/src/soot/toolkits/scalar/SmartLocalDefs.java @@ -22,7 +22,7 @@ import java.util.ArrayList; import java.util.BitSet; import java.util.Collection; -import java.util.IdentityHashMap; +import java.util.HashMap; import java.util.List; import java.util.Map; @@ -44,55 +44,75 @@ * Analysis that provides an implementation of the LocalDefs interface. */ public class SmartLocalDefs implements LocalDefs { - - protected static class StaticSingleAssignment implements LocalDefs { - private final Map> localToDefs; - - protected StaticSingleAssignment(List[] units, Local[] locals) { - assert units.length == locals.length; - - localToDefs = new IdentityHashMap>(units.length); - - for (int i = 0; i < units.length; i++) { - List list = units[i]; - if (!list.isEmpty()) { - assert list.size() == 1; - list = singletonList(list.get(0)); - localToDefs.put(locals[i], list); - } + + abstract static protected class Assignment implements LocalDefs { + protected static class Entry { + List units; + Local local; + + Entry(List units, Local local) { + this.units = units; + this.local = local; } } + + protected final Map resultValueBoxes; + + protected Assignment(int size) { + resultValueBoxes = new HashMap(size); + } @Override public List getDefsOfAt(Local l, Unit s) { for (ValueBox useBox : s.getUseBoxes()) { if (l == useBox.getValue()) { - return getDefsOfAt(useBox); + Entry e = resultValueBoxes.get(useBox); + // check if local was exchanged! + if (e != null && l == e.local) { + return e.units; + } } } - throw new RuntimeException(); + return emptyList(); + } + + public List getDefs(ValueBox valueBox) { + Entry e = resultValueBoxes.get(valueBox); + if (e == null) { + return emptyList(); + } + return e.units; } + } + + protected class StaticSingleAssignment extends Assignment { + protected StaticSingleAssignment(List[] unitList) { + // most of the units are like "a := b + c", + // or a invoke like "a := b.foo()" + super(g.size() * 3 + 1); + for (Unit s : g) { + for (ValueBox useBox : s.getUseBoxes()) { + Value v = useBox.getValue(); + if (v instanceof Local) { + Local l = (Local) v; + int lno = l.getNumber(); - public List getDefsOfAt(ValueBox valueBox) { - Value v = valueBox.getValue(); - if (v instanceof Local) { - List r = localToDefs.get(v); - if (r == null) { - return emptyList(); + List list = unitList[lno]; + if (!list.isEmpty()) { + list = singletonList(list.get(0)); + resultValueBoxes.put(useBox, new Entry(list, l)); + } + } } - return r; } - throw new RuntimeException(); } } - protected class DefaultAssignment implements LocalDefs { - private final Map> resultValueBoxes; - + protected class DefaultAssignment extends Assignment { protected DefaultAssignment(List[] unitList) { // most of the units are like "a := b + c", // or a invoke like "a := b.foo()" - resultValueBoxes = new IdentityHashMap>(g.size() * 3 + 1); + super(g.size() * 3 + 1); LocalDefsAnalysis reachingAnalysis = new LocalDefsAnalysis(); Unit[] buffer = new Unit[localRange[n]]; @@ -107,18 +127,17 @@ protected DefaultAssignment(List[] unitList) { int from = localRange[lno]; int to = localRange[lno + 1]; assert from <= to; - + if (from == to) { List list = unitList[lno]; if (!list.isEmpty()) { list = singletonList(list.get(0)); - resultValueBoxes.put(useBox, list); - } + resultValueBoxes.put(useBox, new Entry(list, l)); + } } else { int j = 0; BitSet reaching = reachingAnalysis.getFlowBefore(s); - for (int i = to; (i = reaching - .previousSetBit(i - 1)) >= from;) { + for (int i = to; (i = reaching.previousSetBit(i - 1)) >= from;) { buffer[j++] = units[i]; } @@ -126,37 +145,14 @@ protected DefaultAssignment(List[] unitList) { List list = (j == 1) ? singletonList(buffer[0]) : unmodifiableList(asList(copyOf(buffer, j))) - ; - - resultValueBoxes.put(useBox, list); - } - } + ; + resultValueBoxes.put(useBox, new Entry(list, l)); + } + } } } } } - - @Override - public List getDefsOfAt(Local l, Unit s) { - for (ValueBox useBox : s.getUseBoxes()) { - if (l == useBox.getValue()) { - return getDefsOfAt(useBox); - } - } - throw new RuntimeException(); - } - - public List getDefsOfAt(ValueBox valueBox) { - List r = resultValueBoxes.get(valueBox); - if (r == null) { - Value v = valueBox.getValue(); - if (v instanceof Local) { - return emptyList(); - } - throw new RuntimeException(); - } - return r; - } } private class LocalDefsAnalysis extends ForwardFlowAnalysis { @@ -178,24 +174,21 @@ protected void flowThrough(BitSet in, Unit unit, BitSet out) { out.and(in); } - if (unit.getDefBoxes().isEmpty()) { - return; - } - // reassign all definitions - Integer idx = indexOfUnit.get(unit); - if (idx != null) { - for (ValueBox vb : unit.getDefBoxes()) { - Value v = vb.getValue(); - if (v instanceof Local) { - int lno = ((Local) v).getNumber(); + for (ValueBox vb : unit.getDefBoxes()) { + Value v = vb.getValue(); + if (v instanceof Local) { + int lno = ((Local) v).getNumber(); - int from = localRange[lno]; - int to = localRange[lno + 1]; - assert from <= to; + int from = localRange[lno]; + int to = localRange[lno + 1]; + assert from <= to; - if (from < to) { - out.clear(from, to); + if (from < to) { + out.clear(from, to); + //only set range if the unit is live + Integer idx = indexOfUnit.get(unit); + if (idx != null) { out.set(idx); } } @@ -277,7 +270,7 @@ protected SmartLocalDefs(DirectedGraph graph, LiveLocals live, Local... lo @SuppressWarnings("unchecked") private void init(Local[] locals) { - indexOfUnit = new IdentityHashMap(g.size()); + indexOfUnit = new HashMap(g.size()); units = new Unit[g.size()]; localRange = new int[n + 1]; @@ -323,7 +316,7 @@ private void init(Local[] locals) { } localDefs = (localRange[n] == 0) - ? new StaticSingleAssignment(unitList, locals) + ? new StaticSingleAssignment(unitList) : new DefaultAssignment(unitList) ; }