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