Open msridhar opened 4 years ago
/cc @MadhuNimmo
Tried to debug this a bit. Consider this function:
function n() {
try {
return;
} finally {
m();
}
}
Here the bug appears, and we do not see a call from n()
to m()
in a call graph. However, for this version, the call graph is correct:
function n() {
try {
// return;
} finally {
m();
}
}
So I think it's the explicit return
statement in the try
block that is causing problems. The CAst for the body of n()
(with the return
statement) looks like:
157307626:BLOCK
BLOCK
TRY
SCOPE
BLOCK
RETURN
CATCH
"$$unwind1"
ASSIGN
VAR
"$$unwind0"
VAR
"$$unwind1"
SCOPE
BLOCK
CALL
VAR
"m"
"do"
VAR
"__WALA__int3rnal__global"
IF_STMT
BINARY_EXPR
"!="
VAR
"$$unwind0"
VAR
"$$undefined"
THROW
VAR
"$$unwind0"
I don't know semantics of CAst but I don't see anything indicating the fact that the call to m()
in the block after the TRY
block is always executed before control returns to the caller. Not immediately obvious to me what's an easy fix here.
The Java frontend uses an UNWIND
statement to handle try/finally
:
Not sure if JavaScript could do something similar.
My WIP branch attempting to fix this bug is here:
https://github.com/msridhar/WALA/tree/try-finally-bug-fix
Unfortunately I couldn't get it to fully work. I changed RhinoToAstTranslator
to use UNWIND
for try statements, and I'm pretty sure that yields correct CAst trees. But, it exposed a bug inside the translation from CAst to IR that I don't know how to fix. The modified complex_try_finally.js
file is the simplest I could make it while still exposing the bug. The code to translate from CAst to IR is quite complex, particularly this findOrCreateCode
method for generating copies of finally
blocks:
There is a bug in there somewhere leading to a block with a goto instruction and multiple successors, but I haven't been able to track it down.
Code:
When I generate IR for this method, I get:
The
console.log()
call in thefinally
block is missing, though it executes at runtime.