== doSmth == fun doSmth() {} --------------------- L0: 1 2 mark({}) read (Unit) L1: 1 NEXT:[] error: PREV:[] sink: PREV:[, ] ===================== == doSmth1 == fun doSmth1() {} --------------------- L0: 1 2 mark({}) read (Unit) L1: 1 NEXT:[] error: PREV:[] sink: PREV:[, ] ===================== == doSmth2 == fun doSmth2() {} --------------------- L0: 1 2 mark({}) read (Unit) L1: 1 NEXT:[] error: PREV:[] sink: PREV:[, ] ===================== == cond == fun cond() {} --------------------- L0: 1 2 mark({}) read (Unit) L1: 1 NEXT:[] error: PREV:[] sink: PREV:[, ] ===================== == testCopy1 == fun testCopy1() : Int { try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { return 1 } } --------------------- L0: 1 2 mark({ try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { return 1 } }) mark(try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { return 1 }) jmp?(L2 [onException]) NEXT:[jmp?(L5 [catch 0]), jmp?(L3 [onExceptionToFinallyBlock])] jmp?(L3 [onExceptionToFinallyBlock]) NEXT:[mark({ return 1 }), mark({ doSmth() })] 3 mark({ doSmth() }) mark(doSmth()) call(doSmth(), doSmth) -> 2 jmp(L4 [afterCatches]) NEXT:[jmp(L6 [skipFinallyToErrorBlock])] L2 [onException]: jmp?(L5 [catch 0]) NEXT:[v(e: Exception), v(e: NullPointerException)] PREV:[jmp?(L2 [onException])] 3 v(e: NullPointerException) magic[FAKE_INITIALIZER](e: NullPointerException) -> w(e|) 4 mark({ doSmth1() }) mark(doSmth1()) call(doSmth1(), doSmth1) -> 3 jmp(L4 [afterCatches]) NEXT:[jmp(L6 [skipFinallyToErrorBlock])] L5 [catch 0]: v(e: Exception) PREV:[jmp?(L5 [catch 0])] magic[FAKE_INITIALIZER](e: Exception) -> w(e|) 4 mark({ doSmth2() }) mark(doSmth2()) call(doSmth2(), doSmth2) -> 3 jmp(L4 [afterCatches]) L4 [afterCatches]: 2 jmp(L6 [skipFinallyToErrorBlock]) NEXT:[mark({ return 1 })] PREV:[jmp(L4 [afterCatches]), jmp(L4 [afterCatches]), jmp(L4 [afterCatches])] L3 [onExceptionToFinallyBlock]: L7 [start finally]: 3 mark({ return 1 }) PREV:[jmp?(L3 [onExceptionToFinallyBlock])] r(1) -> ret(*|) L1 NEXT:[] L8 [finish finally]: - 2 jmp(error) NEXT:[] PREV:[] L6 [skipFinallyToErrorBlock]: 3 mark({ return 1 }) PREV:[jmp(L6 [skipFinallyToErrorBlock])] r(1) -> ret(*|) L1 NEXT:[] - 2 merge(try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { return 1 }|, , ) -> PREV:[] L1: 1 NEXT:[] PREV:[ret(*|) L1, ret(*|) L1] error: PREV:[] sink: PREV:[, ] ===================== == testCopy2 == fun testCopy2() { while (cond()) { try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { if (cond()) return else continue } } } --------------------- L0: 1 2 mark({ while (cond()) { try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { if (cond()) return else continue } } }) L2 [loop entry point]: L5 [condition entry point]: mark(cond()) PREV:[mark({ while (cond()) { try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { if (cond()) return else continue } } }), jmp(L2 [loop entry point]), jmp(L2 [loop entry point])] call(cond(), cond) -> mark(while (cond()) { try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { if (cond()) return else continue } }) jf(L3 [loop exit point]|) NEXT:[read (Unit), mark({ try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { if (cond()) return else continue } })] L4 [body entry point]: 3 mark({ try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { if (cond()) return else continue } }) mark(try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { if (cond()) return else continue }) jmp?(L6 [onException]) NEXT:[jmp?(L9 [catch 0]), jmp?(L7 [onExceptionToFinallyBlock])] jmp?(L7 [onExceptionToFinallyBlock]) NEXT:[mark({ if (cond()) return else continue }), mark({ doSmth() })] 4 mark({ doSmth() }) mark(doSmth()) call(doSmth(), doSmth) -> 3 jmp(L8 [afterCatches]) NEXT:[jmp(L10 [skipFinallyToErrorBlock])] L6 [onException]: jmp?(L9 [catch 0]) NEXT:[v(e: Exception), v(e: NullPointerException)] PREV:[jmp?(L6 [onException])] 4 v(e: NullPointerException) magic[FAKE_INITIALIZER](e: NullPointerException) -> w(e|) 5 mark({ doSmth1() }) mark(doSmth1()) call(doSmth1(), doSmth1) -> 4 jmp(L8 [afterCatches]) NEXT:[jmp(L10 [skipFinallyToErrorBlock])] L9 [catch 0]: v(e: Exception) PREV:[jmp?(L9 [catch 0])] magic[FAKE_INITIALIZER](e: Exception) -> w(e|) 5 mark({ doSmth2() }) mark(doSmth2()) call(doSmth2(), doSmth2) -> 4 jmp(L8 [afterCatches]) L8 [afterCatches]: 3 jmp(L10 [skipFinallyToErrorBlock]) NEXT:[mark({ if (cond()) return else continue })] PREV:[jmp(L8 [afterCatches]), jmp(L8 [afterCatches]), jmp(L8 [afterCatches])] L7 [onExceptionToFinallyBlock]: L11 [start finally]: 4 mark({ if (cond()) return else continue }) PREV:[jmp?(L7 [onExceptionToFinallyBlock])] mark(if (cond()) return else continue) mark(cond()) call(cond(), cond) -> jf(L12|) NEXT:[jmp(L2 [loop entry point]), ret L1] ret L1 NEXT:[] - jmp(L13) NEXT:[merge(if (cond()) return else continue|!, !) -> ] PREV:[] L12: jmp(L2 [loop entry point]) NEXT:[mark(cond())] PREV:[jf(L12|)] L13: - merge(if (cond()) return else continue|!, !) -> PREV:[] L14 [finish finally]: - 3 jmp(error) NEXT:[] PREV:[] L10 [skipFinallyToErrorBlock]: 4 mark({ if (cond()) return else continue }) PREV:[jmp(L10 [skipFinallyToErrorBlock])] mark(if (cond()) return else continue) mark(cond()) call(cond(), cond) -> jf(copy L12|) NEXT:[jmp(L2 [loop entry point]), ret L1] ret L1 NEXT:[] - jmp(copy L13) NEXT:[merge(if (cond()) return else continue|!, !) -> ] PREV:[] jmp(L2 [loop entry point]) NEXT:[mark(cond())] PREV:[jf(copy L12|)] - merge(if (cond()) return else continue|!, !) -> PREV:[] - 3 merge(try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { if (cond()) return else continue }|, , ) -> PREV:[] - 2 jmp(L2 [loop entry point]) NEXT:[mark(cond())] PREV:[] L3 [loop exit point]: read (Unit) PREV:[jf(L3 [loop exit point]|)] L1: 1 NEXT:[] PREV:[ret L1, ret L1, read (Unit)] error: PREV:[] sink: PREV:[, ] ===================== == testCopy3 == fun testCopy3() { try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { while (cond()); } } --------------------- L0: 1 2 mark({ try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { while (cond()); } }) mark(try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { while (cond()); }) jmp?(L2 [onException]) NEXT:[jmp?(L5 [catch 0]), jmp?(L3 [onExceptionToFinallyBlock])] jmp?(L3 [onExceptionToFinallyBlock]) NEXT:[mark({ while (cond()); }), mark({ doSmth() })] 3 mark({ doSmth() }) mark(doSmth()) call(doSmth(), doSmth) -> 2 jmp(L4 [afterCatches]) NEXT:[jmp(L6 [skipFinallyToErrorBlock])] L2 [onException]: jmp?(L5 [catch 0]) NEXT:[v(e: Exception), v(e: NullPointerException)] PREV:[jmp?(L2 [onException])] 3 v(e: NullPointerException) magic[FAKE_INITIALIZER](e: NullPointerException) -> w(e|) 4 mark({ doSmth1() }) mark(doSmth1()) call(doSmth1(), doSmth1) -> 3 jmp(L4 [afterCatches]) NEXT:[jmp(L6 [skipFinallyToErrorBlock])] L5 [catch 0]: v(e: Exception) PREV:[jmp?(L5 [catch 0])] magic[FAKE_INITIALIZER](e: Exception) -> w(e|) 4 mark({ doSmth2() }) mark(doSmth2()) call(doSmth2(), doSmth2) -> 3 jmp(L4 [afterCatches]) L4 [afterCatches]: 2 jmp(L6 [skipFinallyToErrorBlock]) NEXT:[mark({ while (cond()); })] PREV:[jmp(L4 [afterCatches]), jmp(L4 [afterCatches]), jmp(L4 [afterCatches])] L3 [onExceptionToFinallyBlock]: L7 [start finally]: 3 mark({ while (cond()); }) PREV:[jmp?(L3 [onExceptionToFinallyBlock])] L8 [loop entry point]: L11 [condition entry point]: mark(cond()) PREV:[mark({ while (cond()); }), jmp(L8 [loop entry point])] call(cond(), cond) -> mark(while (cond())) jf(L9 [loop exit point]|) NEXT:[read (Unit), jmp(L8 [loop entry point])] L10 [body entry point]: jmp(L8 [loop entry point]) NEXT:[mark(cond())] L9 [loop exit point]: read (Unit) PREV:[jf(L9 [loop exit point]|)] L12 [finish finally]: 2 jmp(error) NEXT:[] L6 [skipFinallyToErrorBlock]: 3 mark({ while (cond()); }) PREV:[jmp(L6 [skipFinallyToErrorBlock])] mark(cond()) PREV:[mark({ while (cond()); }), jmp(copy L8 [loop entry point])] call(cond(), cond) -> mark(while (cond())) jf(copy L9 [loop exit point]|) NEXT:[read (Unit), jmp(copy L8 [loop entry point])] jmp(copy L8 [loop entry point]) NEXT:[mark(cond())] read (Unit) PREV:[jf(copy L9 [loop exit point]|)] 2 merge(try { doSmth() } catch (e: NullPointerException) { doSmth1() } catch (e: Exception) { doSmth2() } finally { while (cond()); }|, , ) -> L1: 1 NEXT:[] error: PREV:[jmp(error)] sink: PREV:[, ] ===================== == doTestCopy4 == fun doTestCopy4(list: List?) : Int { try { doSmth() } finally { if(list != null) { } } } --------------------- L0: 1 v(list: List?) magic[FAKE_INITIALIZER](list: List?) -> w(list|) 2 mark({ try { doSmth() } finally { if(list != null) { } } }) mark(try { doSmth() } finally { if(list != null) { } }) jmp?(L2 [onExceptionToFinallyBlock]) NEXT:[mark({ if(list != null) { } }), mark({ doSmth() })] 3 mark({ doSmth() }) mark(doSmth()) call(doSmth(), doSmth) -> 2 jmp(L3 [skipFinallyToErrorBlock]) NEXT:[mark({ if(list != null) { } })] L2 [onExceptionToFinallyBlock]: L4 [start finally]: 3 mark({ if(list != null) { } }) PREV:[jmp?(L2 [onExceptionToFinallyBlock])] mark(if(list != null) { }) r(list) -> r(null) -> mark(list != null) call(list != null, equals|, ) -> jf(L5|) NEXT:[read (Unit), mark({ })] 4 mark({ }) read (Unit) 3 jmp(L6) NEXT:[merge(if(list != null) { }|!) -> ] L5: read (Unit) PREV:[jf(L5|)] L6: merge(if(list != null) { }|!) -> PREV:[jmp(L6), read (Unit)] L7 [finish finally]: 2 jmp(error) NEXT:[] L3 [skipFinallyToErrorBlock]: 3 mark({ if(list != null) { } }) PREV:[jmp(L3 [skipFinallyToErrorBlock])] mark(if(list != null) { }) r(list) -> r(null) -> mark(list != null) call(list != null, equals|, ) -> jf(copy L5|) NEXT:[read (Unit), mark({ })] 4 mark({ }) read (Unit) 3 jmp(copy L6) NEXT:[merge(if(list != null) { }|!) -> ] read (Unit) PREV:[jf(copy L5|)] merge(if(list != null) { }|!) -> PREV:[jmp(copy L6), read (Unit)] 2 merge(try { doSmth() } finally { if(list != null) { } }|) -> L1: 1 NEXT:[] error: PREV:[jmp(error)] sink: PREV:[, ] =====================