Skip to content

Commit 3b8d756

Browse files
Merge pull request #2794 from jeannielynnmoulton/jeannie/DocumentRemoveExceptions
Adds summary for remove_exceptions [DOC-84]
2 parents cebfe56 + 00ede79 commit 3b8d756

File tree

1 file changed

+172
-2
lines changed

1 file changed

+172
-2
lines changed

jbmc/src/java_bytecode/README.md

Lines changed: 172 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -248,9 +248,179 @@ for(tmp_index = 0; tmp_index < dim_size; ++tmp_index)
248248

249249
`remove_java_new` is then recursively applied to the new `subarray`.
250250

251-
\section java-bytecode-remove-exceptions remove_exceptions
251+
\section java-bytecode-remove-exceptions Remove exceptions
252252

253-
To be documented.
253+
When \ref remove_exceptions is called on the \ref goto_modelt, the
254+
goto model contains complex instructions (\ref goto_program_instruction_typet)
255+
such as `CATCH-POP`, `CATCH-PUSH` and `THROW`. In order to analyze the goto
256+
model, the instructions must be simplified to use more basic instructions - this
257+
is called "lowering". This class lowers the `CATCH` and `THROW` instructions.
258+
259+
`THROW` instructions are replaced by assigning to `@inflight_exception` and a
260+
goto to end of the function. `CATCH` instructions are replaced by a check of
261+
the `@inflight_exception` and setting it to null.
262+
263+
\subsection throw THROW
264+
265+
Consider a simple method `testException(I)V`:
266+
267+
```java
268+
public class TestExceptions {
269+
int field;
270+
public void testException(int i) throws Exception {
271+
if (i < 0) {
272+
throw new Exception();
273+
}
274+
field = i;
275+
}
276+
}
277+
```
278+
279+
The goto for `testException(I)V` before `remove_exceptions` (removing comments
280+
and replacing irrelevant parts with `...`) is:
281+
282+
```
283+
TestExceptions.testException(int) /* java::TestExceptions.testException:(I)V */
284+
IF i >= 0 THEN GOTO 3
285+
struct java.lang.Exception *new_tmp0;
286+
new_tmp0 = new struct java.lang.Exception;
287+
IF !(new_tmp0 == null) THEN GOTO 1
288+
289+
...
290+
291+
1: SKIP
292+
new_tmp0 . java.lang.Exception.<init>:()V();
293+
294+
...
295+
296+
2: SKIP
297+
THROW: throw(new_tmp0)
298+
dead new_tmp0;
299+
300+
...
301+
302+
```
303+
where there is a `THROW` instruction to be replaced.
304+
305+
After passing the goto model through `remove_exceptions`, it is:
306+
307+
```
308+
TestExceptions.testException(int) /* java::TestExceptions.testException:(I)V */
309+
IF i >= 0 THEN GOTO 4
310+
struct java.lang.Exception *new_tmp0;
311+
new_tmp0 = new struct java.lang.Exception;
312+
IF !(new_tmp0 == null) THEN GOTO 1
313+
314+
...
315+
316+
1: new_tmp0 . java.lang.Exception.<init>:()V();
317+
IF @inflight_exception == null THEN GOTO 2 // it is because we've not used it yet
318+
319+
...
320+
321+
2: IF !(new_tmp0 == null) THEN GOTO 3
322+
323+
...
324+
325+
3: @inflight_exception = (void *)new_tmp0;
326+
dead new_tmp0;
327+
328+
...
329+
330+
```
331+
where now instead of the instruction `THROW`, the global variable
332+
`@inflight_exception` holds the thrown exception in a separate goto statement.
333+
334+
\subsection catch CATCH-PUSH, CATCH-POP and EXCEPTION LANDING PAD
335+
336+
Consider the method `catchSomething(I)V` that tries the above method
337+
`testException(I)V` and catches the exception:
338+
339+
```java
340+
public class TestExceptions {
341+
int field;
342+
public void testException(int i) throws Exception {
343+
if (i < 0) {
344+
throw new Exception();
345+
}
346+
field = i;
347+
}
348+
public void catchSomething(int i) {
349+
try {
350+
testException(i);
351+
} catch (Exception e) {
352+
}
353+
}
354+
}
355+
```
356+
357+
The goto model before `remove_exceptions` is:
358+
```
359+
TestExceptions.catchSomething(int) /* java::TestExceptions.catchSomething:(I)V */
360+
361+
...
362+
363+
CATCH-PUSH ->2
364+
365+
...
366+
367+
1: SKIP
368+
this . com.diffblue.regression.TestExceptions.testException:(I)V(i);
369+
CATCH-POP
370+
GOTO 3
371+
2: void *anonlocal::2a;
372+
struct java.lang.Exception *caught_exception_tmp0;
373+
EXCEPTION LANDING PAD (struct java.lang.Exception * caught_exception_tmp0)
374+
anonlocal::2a = (void *)caught_exception_tmp0;
375+
dead caught_exception_tmp0;
376+
dead anonlocal::2a;
377+
378+
...
379+
380+
```
381+
The `CATCH-PUSH` instruction signifies the start of the try block, the
382+
`CATCH-POP` instruction signifies the end of the try block, and the `EXCEPTION
383+
LANDING PAD` signifies beginning of the catch block.
384+
385+
After `remove_exceptions` the goto model is:
386+
387+
```
388+
TestExceptions.catchSomething(int) /* java::TestExceptions.catchSomething:(I)V */
389+
390+
...
391+
392+
this . com.diffblue.regression.TestExceptions.testException:(I)V(i);
393+
IF @inflight_exception == null THEN GOTO 3 // true if testException does not throw, method terminates normally
394+
IF !(@inflight_exception == null) THEN GOTO 1 // true if testException throws, enters catch block
395+
396+
...
397+
398+
1: __CPROVER_string class_identifier_tmp;
399+
class_identifier_tmp = ((struct java.lang.Object *)@inflight_exception)->@class_identifier;
400+
instanceof_result_tmp = class_identifier_tmp == "java::java.lang.Exception" || ... ; // TRUE
401+
dead class_identifier_tmp;
402+
2: IF instanceof_result_tmp THEN GOTO 4
403+
404+
...
405+
406+
3: ASSERT false // block 3
407+
GOTO 5
408+
4: void *anonlocal::2a; // The catch block
409+
struct java.lang.Exception *caught_exception_tmp0;
410+
ASSERT false // block 4
411+
caught_exception_tmp0 = (struct java.lang.Exception *)@inflight_exception;
412+
@inflight_exception = null;
413+
anonlocal::2a = (void *)caught_exception_tmp0;
414+
dead caught_exception_tmp0;
415+
dead anonlocal::2a;
416+
5: ASSERT false // block 5
417+
6: END_FUNCTION
418+
```
419+
where the `CATCH-PUSH` has been replaced by a check on the `@inflight_exception`
420+
variable and goto statements, the `CATCH-POP` replaced by a check on the class
421+
of the exception and a goto statement, and the `EXCEPTION LANDING PAD` replaced
422+
by a section that assigns the exception to a local variable and sets the
423+
`@inflight_exception` back to null.
254424

255425
\section java-bytecode-remove-instanceof Remove instanceof
256426

0 commit comments

Comments
 (0)