710 likes | 731 Views
Explore the use of program slicing and sliding techniques in software maintenance, debugging, and refactoring for improved efficiency. Learn how to isolate and compose program slices effectively. Examples and insights provided.
E N D
Program Sliding Ran Ettinger, IBM Research – Haifa Advanced Software Tools Seminar Tel Aviv University 28 May 2012
Programmers use slices (not only) when debugging • Program slicing was invented, by Mark Weiser, • for “times when only a portion of a program’s behavior is of interest” [ICSE81] • and with the observation that “programmers use slices when debugging” [CACM82] • According to Weiser: • slicing is a “method of program decomposition” • that “is applied to programs after they are written, and is therefore useful in maintenance rather than design” [ICSE81] • Is this still true? • What about re-design, refactoring, for supporting incremental and iterative development methodologies?
Program Sliding • A slice-motion transformation • Isolates a slice, making it contiguous • Identify the complementary slice (co-slice) • A sequential (re-)composition of the slice and co-slice • Preserves semantics for all variables
for (i = 0, ceil = this.extra[0].length > 3 ? 3 : this.extra[0].length; i < ceil; i++) { pot += "," + this.extra[1][i]; //$NON-NLS-1$ } int i, ceil; for (i = 0, ceil = this.extra[0].length > 3 ? 3 : this.extra[0].length; i < ceil; i++) { def += "," + this.extra[0][i]; //$NON-NLS-1$ }
int i, ceil; for (i = 0, ceil = this.extra[0].length > 3 ? 3 : this.extra[0].length; i < ceil; i++) { def += "," + this.extra[0][i]; //$NON-NLS-1$ } for (i = 0, ceil = this.extra[0].length > 3 ? 3 : this.extra[0].length; i < ceil; i++) { pot += "," + this.extra[1][i]; //$NON-NLS-1$ }
String pot = "], pot:[" + this.potentialInits; //$NON-NLS-1$ for (i = 0, ceil = this.extra[0].length > 3 ?3 : this.extra[0].length; i < ceil; i++) { pot += "," + this.extra[1][i]; //$NON-NLS-1$ } if (ceil < this.extra[0].length) { pot += ",..."; //$NON-NLS-1$ } return def + pot + "], reachable:" + ((this.tagBits & UNREACHABLE) == 0) //$NON-NLS-1$ + ", no null info>"; //$NON-NLS-1$ String def = "FlowInfo<def:[" + this.definiteInits; //$NON-NLS-1$ int i, ceil; for (i = 0, ceil = this.extra[0].length > 3 ?3 : this.extra[0].length; i < ceil; i++) { def += "," + this.extra[0][i]; //$NON-NLS-1$ } if (ceil < this.extra[0].length) { def += ",..."; //$NON-NLS-1$ }
String def = "FlowInfo<def:[" + this.definiteInits; //$NON-NLS-1$ int i, ceil; for (i = 0, ceil = this.extra[0].length > 3 ?3 : this.extra[0].length; i < ceil; i++) { def += "," + this.extra[0][i]; //$NON-NLS-1$ } if (ceil < this.extra[0].length) { def += ",..."; //$NON-NLS-1$ } String pot = "], pot:[" + this.potentialInits; //$NON-NLS-1$ for (i = 0, ceil = this.extra[0].length > 3 ?3 : this.extra[0].length; i < ceil; i++) { pot += "," + this.extra[1][i]; //$NON-NLS-1$ } if (ceil < this.extra[0].length) { pot += ",..."; //$NON-NLS-1$ } return def + pot + "], reachable:" + ((this.tagBits & UNREACHABLE) == 0) //$NON-NLS-1$ + ", no null info>"; //$NON-NLS-1$
method_body: { int length = this.keyTable.length,index = CharOperation.hashCode(key) % length; while (this.keyTable[index] != null) { if (CharOperation.equals(this.keyTable[index], key)) { break method_body; } if (++index == length) { // faster than modulo index = 0; } } this.keyTable[index] = key; this.valueTable[index] = value; // assumes the threshold is never equal to the size of the table if (++this.elementSize > this.threshold) rehash(); } method_body: { int length = this.keyTable.length,index = CharOperation.hashCode(key) % length; while (this.keyTable[index] != null) { if (CharOperation.equals(this.keyTable[index], key)) {result = this.valueTable[index]; break method_body; } if (++index == length) { // faster than modulo index = 0; } } result = -value;// negative when added (value is assumed to be > 0) }
String def = "FlowInfo<def:[" + this.definiteInits; //$NON-NLS-1$ int i, ceil; for (i = 0, ceil = this.extra[0].length > 3 ?3 : this.extra[0].length; i < ceil; i++) { def += "," + this.extra[0][i]; //$NON-NLS-1$ } if (ceil < this.extra[0].length) { def += ",..."; //$NON-NLS-1$ } String pot = "], pot:[" + this.potentialInits; //$NON-NLS-1$ for (i = 0, ceil = this.extra[0].length > 3 ?3 : this.extra[0].length; i < ceil; i++) { pot += "," + this.extra[1][i]; //$NON-NLS-1$ } if (ceil < this.extra[0].length) { pot += ",..."; //$NON-NLS-1$ } return def + pot + "], reachable:" + ((this.tagBits & UNREACHABLE) == 0) //$NON-NLS-1$ + ", no null info>"; //$NON-NLS-1$
key1Value =this.nameAndTypeCacheForFieldsAndMethods.get(key1); if (key1Value == null) { CachedIndexEntry cachedIndexEntry = new CachedIndexEntry(key2, value); this.nameAndTypeCacheForFieldsAndMethods.put(key1, cachedIndexEntry); } elseif (key1Value instanceof CachedIndexEntry) { CachedIndexEntry entry = (CachedIndexEntry) key1Value; if (CharOperation.equals(key2, entry.signature)) { } else { CharArrayCache charArrayCache = new CharArrayCache(); charArrayCache.putIfAbsent(entry.signature, entry.index); charArrayCache.putIfAbsent(key2, value); this.nameAndTypeCacheForFieldsAndMethods.put(key1, charArrayCache); } } else { CharArrayCache charArrayCache = (CharArrayCache) key1Value; charArrayCache.putIfAbsent(key2, value); } Object key1Value =this.nameAndTypeCacheForFieldsAndMethods.get(key1); if (key1Value == null) { index = -value; } elseif (key1Value instanceof CachedIndexEntry) { CachedIndexEntry entry = (CachedIndexEntry) key1Value; if (CharOperation.equals(key2, entry.signature)) { index = entry.index; } else { CharArrayCache charArrayCache = new CharArrayCache(); charArrayCache.putIfAbsent(entry.signature, entry.index); index = charArrayCache.putIfAbsent(key2, value); } } else { CharArrayCache charArrayCache = (CharArrayCache) key1Value; index = charArrayCache.putIfAbsent(key2, value); }
Object key1Value =this.nameAndTypeCacheForFieldsAndMethods.get(key1); if (key1Value == null) { index = -value; } elseif (key1Value instanceof CachedIndexEntry) { CachedIndexEntry entry = (CachedIndexEntry) key1Value; if (CharOperation.equals(key2, entry.signature)) { index = entry.index; } else { CharArrayCache charArrayCache = new CharArrayCache(); charArrayCache.putIfAbsent(entry.signature, entry.index); index = charArrayCache.putIfAbsent(key2, value); } } else { CharArrayCache charArrayCache = (CharArrayCache) key1Value; index = charArrayCache.putIfAbsent(key2, value); } key1Value =this.nameAndTypeCacheForFieldsAndMethods.get(key1); if (key1Value == null) { CachedIndexEntry cachedIndexEntry = new CachedIndexEntry(key2, value); this.nameAndTypeCacheForFieldsAndMethods.put(key1, cachedIndexEntry); } elseif (key1Value instanceof CachedIndexEntry) { CachedIndexEntry entry = (CachedIndexEntry) key1Value; if (CharOperation.equals(key2, entry.signature)) { } else { CharArrayCache charArrayCache = new CharArrayCache(); charArrayCache.putIfAbsent(entry.signature, entry.index); charArrayCache.putIfAbsent(key2, value); this.nameAndTypeCacheForFieldsAndMethods.put(key1, charArrayCache); } } else { CharArrayCache charArrayCache = (CharArrayCache) key1Value; charArrayCache.putIfAbsent(key2, value); }
key1Value =this.nameAndTypeCacheForFieldsAndMethods.get(key1); if (key1Value == null) { CachedIndexEntry cachedIndexEntry = new CachedIndexEntry(key2, value); this.nameAndTypeCacheForFieldsAndMethods.put(key1, cachedIndexEntry); } elseif (key1Value instanceof CachedIndexEntry) { CachedIndexEntry entry = (CachedIndexEntry) key1Value; if (CharOperation.equals(key2, entry.signature)) { } else { CharArrayCache charArrayCache = new CharArrayCache(); charArrayCache.putIfAbsent(entry.signature, entry.index); charArrayCache.putIfAbsent(key2, value); this.nameAndTypeCacheForFieldsAndMethods.put(key1, charArrayCache); } } Object key1Value =this.nameAndTypeCacheForFieldsAndMethods.get(key1); if (key1Value == null) { index = -value; } elseif (key1Value instanceof CachedIndexEntry) { CachedIndexEntry entry = (CachedIndexEntry) key1Value; if (CharOperation.equals(key2, entry.signature)) { index = entry.index; } else { CharArrayCache charArrayCache = new CharArrayCache(); charArrayCache.putIfAbsent(entry.signature, entry.index); index = charArrayCache.putIfAbsent(key2, value); } } else { CharArrayCache charArrayCache = (CharArrayCache) key1Value; index = charArrayCache.putIfAbsent(key2, value); }
Object key1Value =this.nameAndTypeCacheForFieldsAndMethods.get(key1); if (key1Value == null) { index = -value; } elseif (key1Value instanceof CachedIndexEntry) { CachedIndexEntry entry = (CachedIndexEntry) key1Value; if (CharOperation.equals(key2, entry.signature)) { index = entry.index; } else { CharArrayCache charArrayCache = new CharArrayCache(); charArrayCache.putIfAbsent(entry.signature, entry.index); index = charArrayCache.putIfAbsent(key2, value); } } else { CharArrayCache charArrayCache = (CharArrayCache) key1Value; index = charArrayCache.putIfAbsent(key2, value); } key1Value =this.nameAndTypeCacheForFieldsAndMethods.get(key1); if (key1Value == null) { CachedIndexEntry cachedIndexEntry = new CachedIndexEntry(key2, value); this.nameAndTypeCacheForFieldsAndMethods.put(key1, cachedIndexEntry); } elseif (key1Value instanceof CachedIndexEntry) { CachedIndexEntry entry = (CachedIndexEntry) key1Value; if (CharOperation.equals(key2, entry.signature)) { } else { CharArrayCache charArrayCache = new CharArrayCache(); charArrayCache.putIfAbsent(entry.signature, entry.index); charArrayCache.putIfAbsent(key2, value); this.nameAndTypeCacheForFieldsAndMethods.put(key1, charArrayCache); } }
if (key1Value == null) { CachedIndexEntry cachedIndexEntry = new CachedIndexEntry(key2, value); this.nameAndTypeCacheForFieldsAndMethods.put(key1, cachedIndexEntry); } elseif (key1Value instanceof CachedIndexEntry) { CachedIndexEntry entry = (CachedIndexEntry) key1Value; if (CharOperation.equals(key2, entry.signature)) { } else { CharArrayCache charArrayCache = new CharArrayCache(); charArrayCache.putIfAbsent(entry.signature, entry.index); charArrayCache.putIfAbsent(key2, value); this.nameAndTypeCacheForFieldsAndMethods.put(key1, charArrayCache); } } Object key1Value =this.nameAndTypeCacheForFieldsAndMethods.get(key1); if (key1Value == null) { index = -value; } elseif (key1Value instanceof CachedIndexEntry) { CachedIndexEntry entry = (CachedIndexEntry) key1Value; if (CharOperation.equals(key2, entry.signature)) { index = entry.index; } else { CharArrayCache charArrayCache = new CharArrayCache(); charArrayCache.putIfAbsent(entry.signature, entry.index); index = charArrayCache.putIfAbsent(key2, value); } } else { CharArrayCache charArrayCache = (CharArrayCache) key1Value; index = charArrayCache.putIfAbsent(key2, value); }
Object key1Value =this.nameAndTypeCacheForFieldsAndMethods.get(key1); if (key1Value == null) { index = -value; } elseif (key1Value instanceof CachedIndexEntry) { CachedIndexEntry entry = (CachedIndexEntry) key1Value; if (CharOperation.equals(key2, entry.signature)) { index = entry.index; } else { CharArrayCache charArrayCache = new CharArrayCache(); charArrayCache.putIfAbsent(entry.signature, entry.index); index = charArrayCache.putIfAbsent(key2, value); } } else { CharArrayCache charArrayCache = (CharArrayCache) key1Value; index = charArrayCache.putIfAbsent(key2, value); } if (key1Value == null) { CachedIndexEntry cachedIndexEntry = new CachedIndexEntry(key2, value); this.nameAndTypeCacheForFieldsAndMethods.put(key1, cachedIndexEntry); } elseif (key1Value instanceof CachedIndexEntry) { CachedIndexEntry entry = (CachedIndexEntry) key1Value; if (CharOperation.equals(key2, entry.signature)) { } else { CharArrayCache charArrayCache = new CharArrayCache(); charArrayCache.putIfAbsent(entry.signature, entry.index); charArrayCache.putIfAbsent(key2, value); this.nameAndTypeCacheForFieldsAndMethods.put(key1, charArrayCache); } }
Sliding {index,key1Value} after a step of SQfM on CharArrayCache.putIfAbsent()
if (key1Value == null) { CachedIndexEntry cachedIndexEntry = new CachedIndexEntry(key2, value); this.nameAndTypeCacheForFieldsAndMethods.put(key1, cachedIndexEntry); } elseif (key1Value instanceof CachedIndexEntry) { CachedIndexEntry entry = (CachedIndexEntry) key1Value; if (CharOperation.equals(key2, entry.signature)) { } else { CharArrayCache charArrayCache = new CharArrayCache(); charArrayCache.putIfAbsent(entry.signature, entry.index); charArrayCache.putIfAbsent(key2, value); this.nameAndTypeCacheForFieldsAndMethods.put(key1, charArrayCache); } } else { CharArrayCache charArrayCache = (CharArrayCache) key1Value; charArrayCache.putIfAbsent(key2, value); } Object key1Value =this.nameAndTypeCacheForFieldsAndMethods.get(key1); if (key1Value == null) { index = -value; } elseif (key1Value instanceof CachedIndexEntry) { CachedIndexEntry entry = (CachedIndexEntry) key1Value; if (CharOperation.equals(key2, entry.signature)) { index = entry.index; } else { CharArrayCache charArrayCache = new CharArrayCache(); charArrayCache.putIfAbsent(entry.signature, entry.index); index = charArrayCache.negativeValueIfAbsent(key2, value); } } else { CharArrayCache charArrayCache = (CharArrayCache) key1Value; index = charArrayCache.negativeValueIfAbsent(key2, value); }
Object key1Value =this.nameAndTypeCacheForFieldsAndMethods.get(key1); if (key1Value == null) { index = -value; } elseif (key1Value instanceof CachedIndexEntry) { CachedIndexEntry entry = (CachedIndexEntry) key1Value; if (CharOperation.equals(key2, entry.signature)) { index = entry.index; } else { CharArrayCache charArrayCache = new CharArrayCache(); charArrayCache.putIfAbsent(entry.signature, entry.index); index = charArrayCache.negativeValueIfAbsent(key2, value); } } else { CharArrayCache charArrayCache = (CharArrayCache) key1Value; index = charArrayCache.negativeValueIfAbsent(key2, value); } if (key1Value == null) { CachedIndexEntry cachedIndexEntry = new CachedIndexEntry(key2, value); this.nameAndTypeCacheForFieldsAndMethods.put(key1, cachedIndexEntry); } elseif (key1Value instanceof CachedIndexEntry) { CachedIndexEntry entry = (CachedIndexEntry) key1Value; if (CharOperation.equals(key2, entry.signature)) { } else { CharArrayCache charArrayCache = new CharArrayCache(); charArrayCache.putIfAbsent(entry.signature, entry.index); charArrayCache.putIfAbsent(key2, value); this.nameAndTypeCacheForFieldsAndMethods.put(key1, charArrayCache); } } else { CharArrayCache charArrayCache = (CharArrayCache) key1Value; charArrayCache.putIfAbsent(key2, value); }
Sliding {index,key1Value,entry, charArrayCache, charArrayCache.*} after a step of de-localization
if (key1Value == null) { CachedIndexEntry cachedIndexEntry = new CachedIndexEntry(key2, value); this.nameAndTypeCacheForFieldsAndMethods.put(key1, cachedIndexEntry); } elseif (key1Value instanceof CachedIndexEntry) { if (CharOperation.equals(key2, entry.signature)) { } else { this.nameAndTypeCacheForFieldsAndMethods.put(key1, charArrayCache); } } Object key1Value =this.nameAndTypeCacheForFieldsAndMethods.get(key1); if (key1Value == null) { index = -value; } elseif (key1Value instanceof CachedIndexEntry) { CachedIndexEntry entry = (CachedIndexEntry) key1Value; if (CharOperation.equals(key2, entry.signature)) { index = entry.index; } else { CharArrayCache charArrayCache = new CharArrayCache(); charArrayCache.putIfAbsent(entry.signature, entry.index); index = charArrayCache.putIfAbsent(key2, value); } } else { CharArrayCache charArrayCache = (CharArrayCache) key1Value; index = charArrayCache.putIfAbsent(key2, value); }
Object key1Value =this.nameAndTypeCacheForFieldsAndMethods.get(key1); if (key1Value == null) { index = -value; } elseif (key1Value instanceof CachedIndexEntry) { CachedIndexEntry entry = (CachedIndexEntry) key1Value; if (CharOperation.equals(key2, entry.signature)) { index = entry.index; } else { CharArrayCache charArrayCache = new CharArrayCache(); charArrayCache.putIfAbsent(entry.signature, entry.index); index = charArrayCache.putIfAbsent(key2, value); } } else { CharArrayCache charArrayCache = (CharArrayCache) key1Value; index = charArrayCache.putIfAbsent(key2, value); } if (key1Value == null) { CachedIndexEntry cachedIndexEntry = new CachedIndexEntry(key2, value); this.nameAndTypeCacheForFieldsAndMethods.put(key1, cachedIndexEntry); } elseif (key1Value instanceof CachedIndexEntry) { if (CharOperation.equals(key2, entry.signature)) { } else { this.nameAndTypeCacheForFieldsAndMethods.put(key1, charArrayCache); } }
+ + + ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ if (key1Value == null) { this.nameAndTypeCacheForFieldsAndMethods.put(key1, cachedIndexEntry); } elseif (key1Value instanceof CachedIndexEntry) { if (CharOperation.equals(key2, entry.signature)) { } else { this.nameAndTypeCacheForFieldsAndMethods.put(key1, charArrayCache); } } Object key1Value =this.nameAndTypeCacheForFieldsAndMethods.get(key1); if (key1Value == null) { CachedIndexEntry cachedIndexEntry = new CachedIndexEntry(key2, value); index = -value; } elseif (key1Value instanceof CachedIndexEntry) { CachedIndexEntry entry = (CachedIndexEntry) key1Value; if (CharOperation.equals(key2, entry.signature)) { index = entry.index; } else { CharArrayCache charArrayCache = new CharArrayCache(); charArrayCache.putIfAbsent(entry.signature, entry.index); index = charArrayCache.putIfAbsent(key2, value); } } else { CharArrayCache charArrayCache = (CharArrayCache) key1Value; index = charArrayCache.putIfAbsent(key2, value); }
++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ Object key1Value =this.nameAndTypeCacheForFieldsAndMethods.get(key1); if (key1Value == null) { CachedIndexEntry cachedIndexEntry = new CachedIndexEntry(key2, value); index = -value; } elseif (key1Value instanceof CachedIndexEntry) { CachedIndexEntry entry = (CachedIndexEntry) key1Value; if (CharOperation.equals(key2, entry.signature)) { index = entry.index; } else { CharArrayCache charArrayCache = new CharArrayCache(); charArrayCache.putIfAbsent(entry.signature, entry.index); index = charArrayCache.putIfAbsent(key2, value); } } else { CharArrayCache charArrayCache = (CharArrayCache) key1Value; index = charArrayCache.putIfAbsent(key2, value); } + + + if (key1Value == null) { this.nameAndTypeCacheForFieldsAndMethods.put(key1, cachedIndexEntry); } elseif (key1Value instanceof CachedIndexEntry) { if (CharOperation.equals(key2, entry.signature)) { } else { this.nameAndTypeCacheForFieldsAndMethods.put(key1, charArrayCache); } }
Sliding-Based Split Loop • Perform sliding on the loop fragment choosing a subset V of the loop’s results • Avoid unnecessary code duplication by adding to V all loop results whose addition will not increase the size of the first resulting loop • If sliding fails update the code to avoid the failure and repeat this step, or choose a different loop to split • Compile and test
String def = "FlowInfo<def:[" + this.definiteInits; //$NON-NLS-1$ String pot = "], pot:[" + this.potentialInits; //$NON-NLS-1$ int i, ceil; for (i = 0, ceil = this.extra[0].length > 3 ?3 : this.extra[0].length; i < ceil; i++) { def += "," + this.extra[0][i]; //$NON-NLS-1$ pot += "," + this.extra[1][i]; //$NON-NLS-1$ } if (ceil < this.extra[0].length) { def += ",..."; //$NON-NLS-1$ pot += ",..."; //$NON-NLS-1$ } return def + pot + "], reachable:" + ((this.tagBits & UNREACHABLE) == 0) //$NON-NLS-1$ + ", no null info>"; //$NON-NLS-1$
int i, ceil; for (i = 0, ceil = this.extra[0].length > 3 ?3 : this.extra[0].length; i < ceil; i++) { def += "," + this.extra[0][i]; //$NON-NLS-1$ } for (i = 0, ceil = this.extra[0].length > 3 ?3 : this.extra[0].length; i < ceil; i++) { pot += "," + this.extra[1][i]; //$NON-NLS-1$ }
int i, ceil; for (i = 0, ceil = this.extra[0].length > 3 ?3 : this.extra[0].length; i < ceil; i++) { def += "," + this.extra[0][i]; //$NON-NLS-1$ } for (i = 0, ceil = this.extra[0].length > 3 ?3 : this.extra[0].length; i < ceil; i++) { pot += "," + this.extra[1][i]; //$NON-NLS-1$ }
entry for (…) def+= … {def} pot+= … {pot} exit {pot} {def} {def,pot}
entry for (…) def+= … {def} pot+= … {pot} exit {pot} {def} {def,pot}
entry for (…) def+= … exit entry for (…) def+= … {def} pot+= … {pot} exit {pot} {def} {def,pot}
entry for (…) def+= … {def} pot+= … {pot} exit {pot} {def} {def,pot}
entry entry for (…) for (…) def+= … {def} pot+= … pot+= … {pot} exit exit {pot} {def} {def,pot}
A Sliding-Based RTwQ Example • Sliding (isolate the full slice of def) • Extract Method (turn the slice of def into a method and invoke it to initialize def • Inline Temp (replace references to def with calls to the new method)
String def = "FlowInfo<def:[" + this.definiteInits; //$NON-NLS-1$ String pot = "], pot:[" + this.potentialInits; //$NON-NLS-1$ int i, ceil; for (i = 0, ceil = this.extra[0].length > 3 ?3 : this.extra[0].length; i < ceil; i++) { def += "," + this.extra[0][i]; //$NON-NLS-1$ pot += "," + this.extra[1][i]; //$NON-NLS-1$ } if (ceil < this.extra[0].length) { def += ",..."; //$NON-NLS-1$ pot += ",..."; //$NON-NLS-1$ } return def + pot + "], reachable:" + ((this.tagBits & UNREACHABLE) == 0) //$NON-NLS-1$ + ", no null info>"; //$NON-NLS-1$
String def = "FlowInfo<def:[" + this.definiteInits; //$NON-NLS-1$ int i, ceil; for (i = 0, ceil = this.extra[0].length > 3 ?3 : this.extra[0].length; i < ceil; i++) { def += "," + this.extra[0][i]; //$NON-NLS-1$ } if (ceil < this.extra[0].length) { def += ",..."; //$NON-NLS-1$ } String pot = "], pot:[" + this.potentialInits; //$NON-NLS-1$ for (i = 0, ceil = this.extra[0].length > 3 ?3 : this.extra[0].length; i < ceil; i++) { pot += "," + this.extra[1][i]; //$NON-NLS-1$ } if (ceil < this.extra[0].length) { pot += ",..."; //$NON-NLS-1$ } return def + pot + "], reachable:" + ((this.tagBits & UNREACHABLE) == 0) //$NON-NLS-1$ + ", no null info>"; //$NON-NLS-1$
entry {def} def=… pot=… for (…) {def} def+= … pot+= … if (…) def+= … {def} pot+= … {retval} return … exit
entry {def} def=… pot=… for (…) {def} def+= … pot+= … if (…) def+= … {def} pot+= … {retval} return … exit
entry def=… for (…) def+= … if (…) def+= … exit entry {def} def=… pot=… for (…) {def} def+= … pot+= … if (…) def+= … {def} pot+= … {retval} return … exit
entry def=… for (…) def+= … if (…) def+= … exit
entry {def} def=… pot=… for (…) {def} def+= … pot+= … if (…) def+= … {def} pot+= … {retval} return … exit
entry pot=… for (…) pot+= … if (…) pot+= … return … exit entry {def} def=… pot=… for (…) {def} def+= … pot+= … if (…) def+= … {def} pot+= … {retval} return … exit
entry pot=… for (…) pot+= … if (…) pot+= … return … exit