A method for handling methods
Christian Gram Kalhauge
Why are method calls complicated?
Why would you use context sensitive analysis?
What is the drawback of a context sensitive analysis?
int id(int i) {
return i; // Where to return to?
}
int main() {
int x = id(1);
int y = id(0);
return x + y;
}int id(int i) {
return i; // Where to return to?
}
int main() {
int x = id(1);
int y = id(0);
return x + y;
}int main() {
return 1 + 0;
}The call stack. Notice how the return address is stored secretly among the local variables. By R. S. Shaw (modified) - Own work, Public Domain link
Abstract Call Plumbing
int id(int i) {
// { main:1} x {+}
return i;
// updates the results of main:1 with {+}
}
int main() {
int x = id(1); // result {+}
int y = id(0); // yet not computed
return x + y; // yet not computed
}int id(int i) {
// { main:1, main:2} x {0, +}
return i;
// updates the results of main:1 and main:2 with {0, +}
}
int main() {
int x = id(1); // result {0, +}
int y = id(0); // result {0, +}
return x + y; // result {+}
}Nigthmare!
int id(int i) {
// { main:1, main:2} x {0, +}
return i;
// updates the results of main:1 and main:2 with {0, +}
}
int main() {
int x = id(1); // result {0, +}
int y = id(0); // result {0, +}
return x / y; // result BUG!
}int main() {
int x = id(0); // main:1 -> {} x {0}
int y = id(1); // not yet computed
return x / y; // not yet computed
}
int id(int x) {
// main:1,id:1 -> {main:1} x { 0 }
return x
}int main() {
int x = id(0); // main:1 -> {} x {0}
int y = id(1); // main:1 -> {} x {+}
return x / y; // main:1 -> {} x {0}
}
int id(int x) {
// Now we keep two state:
// main:1,id:1 -> {main:1} x { 0 }
// main:2,id:1 -> {main:2} x { + }
return x
}Exponential Blow-out!
Recursive Functions!
Only keep the last call-sites
is often enough.
Why are method calls complicated?
Why would you use context sensitive analysis?
What is the drawback of a context sensitive analysis?