710 likes | 727 Views
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,
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