{"payload":{"feedbackUrl":"https://github.com/orgs/community/discussions/53140","repo":{"id":169876900,"defaultBranch":"master","name":"LoweredCodeUtils.jl","ownerLogin":"JuliaDebug","currentUserCanPush":false,"isFork":false,"isEmpty":false,"createdAt":"2019-02-09T14:47:59.000Z","ownerAvatar":"https://avatars.githubusercontent.com/u/46803805?v=4","public":true,"private":false,"isOrgOwned":true},"refInfo":{"name":"","listCacheKey":"v0:1726030213.0","currentOid":""},"activityList":{"items":[{"before":"9ff8976f5044ab63f2c6c6898ea862103cdb8e06","after":"62cba63a3ddfd0799733edb0a39e8d612bfb1966","ref":"refs/heads/gh-pages","pushedAt":"2024-09-19T07:31:17.000Z","pushType":"push","commitsCount":1,"pusher":{"login":"timholy","name":"Tim Holy","path":"/timholy","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/1525481?s=80&v=4"},"commit":{"message":"build based on 68e96c6","shortMessageHtmlLink":"build based on 68e96c6"}},{"before":"475dc906c130a01ca42c480c79aec01773d70a7a","after":"cef292f49b763531d218497f0d56720df6e4b27b","ref":"refs/heads/avi/implicit-return","pushedAt":"2024-09-19T07:29:00.000Z","pushType":"force_push","commitsCount":0,"pusher":{"login":"aviatesk","name":"Shuhei Kadowaki","path":"/aviatesk","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/40514306?s=80&v=4"},"commit":{"message":"proper termination, take 2\n\nThis PR is an alternative to JuliaDebug/LoweredCodeUtils.jl#99.\nThis is built on top of JuliaDebug/LoweredCodeUtils.jl#116.\n\nWith this PR, the following test cases now pass correctly:\n```julia\n # Final block is not a `return`: Need to use `config::SelectiveEvalRecurse` explicitly\n ex = quote\n x = 1\n yy = 7\n @label loop\n x += 1\n x < 5 || return yy\n @goto loop\n end\n frame = Frame(ModSelective, ex)\n src = frame.framecode.src\n edges = CodeEdges(ModSelective, src)\n config = SelectiveEvalRecurse()\n isrequired = lines_required(GlobalRef(ModSelective, :x), src, edges, config)\n selective_eval_fromstart!(config, frame, isrequired, true)\n @test ModSelective.x == 5\n @test !isdefined(ModSelective, :yy)\n```\n\nThe basic approach is overloading `JuliaInterpreter.step_expr!` and\n`LoweredCodeUtils.next_or_nothing!` for the new `SelectiveEvalController`\ntype, as described below, to perform correct selective execution.\n\nWhen `SelectiveEvalController` is passed as the `recurse` argument of\n`selective_eval!`, the selective execution is adjusted as follows:\n\n- **Implicit return**: In Julia's IR representation (`CodeInfo`), the\n final block does not necessarily return and may `goto` another block.\n And if the `return` statement is not included in the slice in such\n cases, it is necessary to terminate `selective_eval!` when execution\n reaches such implicit return statements. `controller.implicit_returns`\n records the PCs of such return statements, and `selective_eval!` will\n return when reaching those statements.\n This is the core part of the fix for the test cases in\n JuliaDebug/LoweredCodeUtils.jl#99.\n\n- **CFG short-cut**: When the successors of a conditional branch are\n inactive, and it is safe to move the program counter from the\n conditional branch to the nearest common post-dominator of those\n successors, this short-cut is taken. This short-cut is not merely an\n optimization but is actually essential for the correctness of the\n selective execution. This is because, in `CodeInfo`, even if we simply\n fall-through dead blocks (i.e., increment the program counter without\n executing the statements of those blocks), it does not necessarily\n lead to the nearest common post-dominator block.\n\nAnd now [`lines_required`](@ref) or [`lines_required!`](@ref) will\nupdate the `SelectiveEvalController` passed as their argument to be\nappropriate for the program slice generated.\n\nOne thing to note is that currently, the `controller` is not be recursed.\nThat said, in Revise, which is the main consumer of LCU, there is no\nneed for recursive selective execution, and so `selective_eval!` does\nnot provide a system for inter-procedural selective evaluation.\nAccordingly `SelectiveEvalController` does not recurse too, but this can\nbe left as a future extension.","shortMessageHtmlLink":"proper termination, take 2"}},{"before":"bcdb816b3ea60c0e58e4333f3e97699bacca9641","after":"9ff8976f5044ab63f2c6c6898ea862103cdb8e06","ref":"refs/heads/gh-pages","pushedAt":"2024-09-17T17:11:14.000Z","pushType":"push","commitsCount":1,"pusher":{"login":"timholy","name":"Tim Holy","path":"/timholy","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/1525481?s=80&v=4"},"commit":{"message":"build based on 6aa0fd6","shortMessageHtmlLink":"build based on 6aa0fd6"}},{"before":"82b95143ba2f8315397615df186945496a0deddc","after":"6aa0fd6b48adb3c255e6459913770d0e59b9e809","ref":"refs/heads/master","pushedAt":"2024-09-17T17:08:59.000Z","pushType":"push","commitsCount":1,"pusher":{"login":"aviatesk","name":"Shuhei Kadowaki","path":"/aviatesk","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/40514306?s=80&v=4"},"commit":{"message":"remove `\\n\\n\\n`","shortMessageHtmlLink":"remove \\n\\n\\n"}},{"before":"f57af09cade44379257adc7a8d77fd09fc1e61ff","after":"bcdb816b3ea60c0e58e4333f3e97699bacca9641","ref":"refs/heads/gh-pages","pushedAt":"2024-09-11T04:52:38.000Z","pushType":"push","commitsCount":1,"pusher":{"login":"timholy","name":"Tim Holy","path":"/timholy","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/1525481?s=80&v=4"},"commit":{"message":"build based on 82b9514","shortMessageHtmlLink":"build based on 82b9514"}},{"before":"736616944ce96760d45b726b7b6c3d653f5addc0","after":"f57af09cade44379257adc7a8d77fd09fc1e61ff","ref":"refs/heads/gh-pages","pushedAt":"2024-09-11T04:50:24.000Z","pushType":"push","commitsCount":1,"pusher":{"login":"timholy","name":"Tim Holy","path":"/timholy","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/1525481?s=80&v=4"},"commit":{"message":"build based on d71ce8c","shortMessageHtmlLink":"build based on d71ce8c"}},{"before":"78c2db7260913d9b50ae64681d08097b70d3aa96","after":"475dc906c130a01ca42c480c79aec01773d70a7a","ref":"refs/heads/avi/implicit-return","pushedAt":"2024-09-11T04:48:24.000Z","pushType":"force_push","commitsCount":0,"pusher":{"login":"aviatesk","name":"Shuhei Kadowaki","path":"/aviatesk","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/40514306?s=80&v=4"},"commit":{"message":"proper termination, take 2\n\nThis PR is an alternative to JuliaDebug/LoweredCodeUtils.jl#99.\nThis is built on top of JuliaDebug/LoweredCodeUtils.jl#116.\n\nWith this PR, the following test cases now pass correctly:\n```julia\n # Final block is not a `return`: Need to use `config::SelectiveEvalRecurse` explicitly\n ex = quote\n x = 1\n yy = 7\n @label loop\n x += 1\n x < 5 || return yy\n @goto loop\n end\n frame = Frame(ModSelective, ex)\n src = frame.framecode.src\n edges = CodeEdges(ModSelective, src)\n config = SelectiveEvalRecurse()\n isrequired = lines_required(GlobalRef(ModSelective, :x), src, edges, config)\n selective_eval_fromstart!(config, frame, isrequired, true)\n @test ModSelective.x == 5\n @test !isdefined(ModSelective, :yy)\n```\n\nThe basic approach is overloading `JuliaInterpreter.step_expr!` and\n`LoweredCodeUtils.next_or_nothing!` for the new `SelectiveEvalController`\ntype, as described below, to perform correct selective execution.\n\nWhen `SelectiveEvalController` is passed as the `recurse` argument of\n`selective_eval!`, the selective execution is adjusted as follows:\n\n- **Implicit return**: In Julia's IR representation (`CodeInfo`), the\n final block does not necessarily return and may `goto` another block.\n And if the `return` statement is not included in the slice in such\n cases, it is necessary to terminate `selective_eval!` when execution\n reaches such implicit return statements. `controller.implicit_returns`\n records the PCs of such return statements, and `selective_eval!` will\n return when reaching those statements.\n This is the core part of the fix for the test cases in\n JuliaDebug/LoweredCodeUtils.jl#99.\n\n- **CFG short-cut**: When the successors of a conditional branch are\n inactive, and it is safe to move the program counter from the\n conditional branch to the nearest common post-dominator of those\n successors, this short-cut is taken. This short-cut is not merely an\n optimization but is actually essential for the correctness of the\n selective execution. This is because, in `CodeInfo`, even if we simply\n fall-through dead blocks (i.e., increment the program counter without\n executing the statements of those blocks), it does not necessarily\n lead to the nearest common post-dominator block.\n\nAnd now [`lines_required`](@ref) or [`lines_required!`](@ref) will\nupdate the `SelectiveEvalController` passed as their argument to be\nappropriate for the program slice generated.\n\nOne thing to note is that currently, the `controller` is not be recursed.\nThat said, in Revise, which is the main consumer of LCU, there is no\nneed for recursive selective execution, and so `selective_eval!` does\nnot provide a system for inter-procedural selective evaluation.\nAccordingly `SelectiveEvalController` does not recurse too, but this can\nbe left as a future extension.","shortMessageHtmlLink":"proper termination, take 2"}},{"before":"5360b20996ed585cd4d385361a544fdcd4637cb8","after":"736616944ce96760d45b726b7b6c3d653f5addc0","ref":"refs/heads/gh-pages","pushedAt":"2024-09-11T04:38:56.000Z","pushType":"push","commitsCount":1,"pusher":{"login":"timholy","name":"Tim Holy","path":"/timholy","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/1525481?s=80&v=4"},"commit":{"message":"build based on 82b9514","shortMessageHtmlLink":"build based on 82b9514"}},{"before":"e7ab8b60248f52223818d2baa0c63e613d1a008a","after":"5360b20996ed585cd4d385361a544fdcd4637cb8","ref":"refs/heads/gh-pages","pushedAt":"2024-09-11T04:38:05.000Z","pushType":"push","commitsCount":1,"pusher":{"login":"timholy","name":"Tim Holy","path":"/timholy","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/1525481?s=80&v=4"},"commit":{"message":"build based on 38aed5d","shortMessageHtmlLink":"build based on 38aed5d"}},{"before":"969e7c9be89327af9b9c3b3e0240094d03d573ba","after":"82b95143ba2f8315397615df186945496a0deddc","ref":"refs/heads/master","pushedAt":"2024-09-11T04:36:33.000Z","pushType":"push","commitsCount":1,"pusher":{"login":"aviatesk","name":"Shuhei Kadowaki","path":"/aviatesk","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/40514306?s=80&v=4"},"commit":{"message":"version 3.0.2","shortMessageHtmlLink":"version 3.0.2"}},{"before":"e92ca7362337b163080d41e274677e0c9060ae3b","after":"78c2db7260913d9b50ae64681d08097b70d3aa96","ref":"refs/heads/avi/implicit-return","pushedAt":"2024-09-11T04:35:58.000Z","pushType":"force_push","commitsCount":0,"pusher":{"login":"aviatesk","name":"Shuhei Kadowaki","path":"/aviatesk","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/40514306?s=80&v=4"},"commit":{"message":"proper termination, take 2\n\nThis PR is an alternative to JuliaDebug/LoweredCodeUtils.jl#99.\nThis is built on top of JuliaDebug/LoweredCodeUtils.jl#116.\n\nWith this PR, the following test cases now pass correctly:\n```julia\n # Final block is not a `return`: Need to use `config::SelectiveEvalRecurse` explicitly\n ex = quote\n x = 1\n yy = 7\n @label loop\n x += 1\n x < 5 || return yy\n @goto loop\n end\n frame = Frame(ModSelective, ex)\n src = frame.framecode.src\n edges = CodeEdges(ModSelective, src)\n config = SelectiveEvalRecurse()\n isrequired = lines_required(GlobalRef(ModSelective, :x), src, edges, config)\n selective_eval_fromstart!(config, frame, isrequired, true)\n @test ModSelective.x == 5\n @test !isdefined(ModSelective, :yy)\n```\n\nThe basic approach is overloading `JuliaInterpreter.step_expr!` and\n`LoweredCodeUtils.next_or_nothing!` for the new `SelectiveEvalController`\ntype, as described below, to perform correct selective execution.\n\nWhen `SelectiveEvalController` is passed as the `recurse` argument of\n`selective_eval!`, the selective execution is adjusted as follows:\n\n- **Implicit return**: In Julia's IR representation (`CodeInfo`), the\n final block does not necessarily return and may `goto` another block.\n And if the `return` statement is not included in the slice in such\n cases, it is necessary to terminate `selective_eval!` when execution\n reaches such implicit return statements. `controller.implicit_returns`\n records the PCs of such return statements, and `selective_eval!` will\n return when reaching those statements.\n This is the core part of the fix for the test cases in\n JuliaDebug/LoweredCodeUtils.jl#99.\n\n- **CFG short-cut**: When the successors of a conditional branch are\n inactive, and it is safe to move the program counter from the\n conditional branch to the nearest common post-dominator of those\n successors, this short-cut is taken. This short-cut is not merely an\n optimization but is actually essential for the correctness of the\n selective execution. This is because, in `CodeInfo`, even if we simply\n fall-through dead blocks (i.e., increment the program counter without\n executing the statements of those blocks), it does not necessarily\n lead to the nearest common post-dominator block.\n\nAnd now [`lines_required`](@ref) or [`lines_required!`](@ref) will\nupdate the `SelectiveEvalController` passed as their argument to be\nappropriate for the program slice generated.\n\nOne thing to note is that currently, the `controller` is not be recursed.\nThat said, in Revise, which is the main consumer of LCU, there is no\nneed for recursive selective execution, and so `selective_eval!` does\nnot provide a system for inter-procedural selective evaluation.\nAccordingly `SelectiveEvalController` does not recurse too, but this can\nbe left as a future extension.","shortMessageHtmlLink":"proper termination, take 2"}},{"before":"5f5a420c8827642f26fba84c47ef86b445f3f9cf","after":"e7ab8b60248f52223818d2baa0c63e613d1a008a","ref":"refs/heads/gh-pages","pushedAt":"2024-09-11T04:34:18.000Z","pushType":"push","commitsCount":1,"pusher":{"login":"timholy","name":"Tim Holy","path":"/timholy","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/1525481?s=80&v=4"},"commit":{"message":"build based on 969e7c9","shortMessageHtmlLink":"build based on 969e7c9"}},{"before":"fb5896d2de5805f330c5d3478c61ce36da25bd34","after":null,"ref":"refs/heads/avi/new-add_control_flow!","pushedAt":"2024-09-11T04:32:14.000Z","pushType":"branch_deletion","commitsCount":0,"pusher":{"login":"aviatesk","name":"Shuhei Kadowaki","path":"/aviatesk","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/40514306?s=80&v=4"}},{"before":"75da0d8f68451e6edbd3a904ddca8d848e25ffa1","after":"969e7c9be89327af9b9c3b3e0240094d03d573ba","ref":"refs/heads/master","pushedAt":"2024-09-11T04:32:10.000Z","pushType":"pr_merge","commitsCount":1,"pusher":{"login":"aviatesk","name":"Shuhei Kadowaki","path":"/aviatesk","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/40514306?s=80&v=4"},"commit":{"message":"switch to a new CFG selection logic (#116)\n\n* switch to a new CFG selection logic\r\n\r\nThis commit aims to port the new CFG selection logic implemented in\r\naviatesk/JET.jl#654 to LCU, so that it can be shared between LCU and JET.\r\n\r\nThe new algorithm is based on what was proposed in [Wei84][^Wei84]. If there is\r\neven one active block in the blocks reachable from a conditional branch\r\nup to its successors' nearest common post-dominator (referred to as\r\n\"๐‘ฐ๐‘ต๐‘ญ๐‘ณ\" in the paper), it is necessary to follow that conditional\r\nbranch and execute the code. Otherwise, execution can be\r\nshort-circuited[^short-circuit] from the conditional branch to the\r\nnearest common post-dominator.\r\n\r\nRegarding the `GotoNode`, it is now marked only for active blocks after\r\nall requirements have converged, rather than marking it inside the\r\n`add_loop!` or such. This approach eliminates the need to add\r\nunnecessary blocks inside the loop, and the need to use `add_loop!`\r\nwhile allowing the required CFG to be executed safely.\r\n\r\n[^Wei84]: M. Weiser, \"Program Slicing,\" IEEE Transactions on Software Engineering, 10, pages 352-357, July 1984. https://ieeexplore.ieee.org/document/5010248\r\n\r\n[^short-circuit]: It is important to note that in Julia's IR (`CodeInfo`),\r\n \"short-circuiting\" a specific code region is not a simple task. Simply\r\n ignoring the path to the post-dominator does not guarantee fall-through\r\n to the post-dominator. Therefore, a more careful implementation is\r\n required for this aspect.","shortMessageHtmlLink":"switch to a new CFG selection logic (#116)"}},{"before":"a11ae239b2a787906edbdc64c0939f6b780d1906","after":"5f5a420c8827642f26fba84c47ef86b445f3f9cf","ref":"refs/heads/gh-pages","pushedAt":"2024-09-10T16:29:04.000Z","pushType":"push","commitsCount":1,"pusher":{"login":"timholy","name":"Tim Holy","path":"/timholy","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/1525481?s=80&v=4"},"commit":{"message":"build based on 02cd0af","shortMessageHtmlLink":"build based on 02cd0af"}},{"before":"0dfe9a3a5ebe2a19ca6e9a5c9682f543c4607ca2","after":"e92ca7362337b163080d41e274677e0c9060ae3b","ref":"refs/heads/avi/implicit-return","pushedAt":"2024-09-10T16:26:56.000Z","pushType":"force_push","commitsCount":0,"pusher":{"login":"aviatesk","name":"Shuhei Kadowaki","path":"/aviatesk","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/40514306?s=80&v=4"},"commit":{"message":"proper termination, take 2\n\nThis PR is an alternative to JuliaDebug/LoweredCodeUtils.jl#99.\nThis is built on top of JuliaDebug/LoweredCodeUtils.jl#116.\n\nWith this PR, the following test cases now pass correctly:\n```julia\n # Final block is not a `return`: Need to use `config::SelectiveEvalRecurse` explicitly\n ex = quote\n x = 1\n yy = 7\n @label loop\n x += 1\n x < 5 || return yy\n @goto loop\n end\n frame = Frame(ModSelective, ex)\n src = frame.framecode.src\n edges = CodeEdges(ModSelective, src)\n config = SelectiveEvalRecurse()\n isrequired = lines_required(GlobalRef(ModSelective, :x), src, edges, config)\n selective_eval_fromstart!(config, frame, isrequired, true)\n @test ModSelective.x == 5\n @test !isdefined(ModSelective, :yy)\n```\n\nThe basic approach is overloading `JuliaInterpreter.step_expr!` and\n`LoweredCodeUtils.next_or_nothing!` for the new `SelectiveEvalController`\ntype, as described below, to perform correct selective execution.\n\nWhen `SelectiveEvalController` is passed as the `recurse` argument of\n`selective_eval!`, the selective execution is adjusted as follows:\n\n- **Implicit return**: In Julia's IR representation (`CodeInfo`), the\n final block does not necessarily return and may `goto` another block.\n And if the `return` statement is not included in the slice in such\n cases, it is necessary to terminate `selective_eval!` when execution\n reaches such implicit return statements. `controller.implicit_returns`\n records the PCs of such return statements, and `selective_eval!` will\n return when reaching those statements.\n This is the core part of the fix for the test cases in\n JuliaDebug/LoweredCodeUtils.jl#99.\n\n- **CFG short-cut**: When the successors of a conditional branch are\n inactive, and it is safe to move the program counter from the\n conditional branch to the nearest common post-dominator of those\n successors, this short-cut is taken. This short-cut is not merely an\n optimization but is actually essential for the correctness of the\n selective execution. This is because, in `CodeInfo`, even if we simply\n fall-through dead blocks (i.e., increment the program counter without\n executing the statements of those blocks), it does not necessarily\n lead to the nearest common post-dominator block.\n\nAnd now [`lines_required`](@ref) or [`lines_required!`](@ref) will\nupdate the `SelectiveEvalController` passed as their argument to be\nappropriate for the program slice generated.\n\nOne thing to note is that currently, the `controller` is not be recursed.\nThat said, in Revise, which is the main consumer of LCU, there is no\nneed for recursive selective execution, and so `selective_eval!` does\nnot provide a system for inter-procedural selective evaluation.\nAccordingly `SelectiveEvalController` does not recurse too, but this can\nbe left as a future extension.","shortMessageHtmlLink":"proper termination, take 2"}},{"before":"5a10c8495b3cf4ada4c9a1400ac042f3b911abeb","after":"0dfe9a3a5ebe2a19ca6e9a5c9682f543c4607ca2","ref":"refs/heads/avi/implicit-return","pushedAt":"2024-09-10T16:22:43.000Z","pushType":"force_push","commitsCount":0,"pusher":{"login":"aviatesk","name":"Shuhei Kadowaki","path":"/aviatesk","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/40514306?s=80&v=4"},"commit":{"message":"proper termination, take 2\n\nThis PR is an alternative to JuliaDebug/LoweredCodeUtils.jl#99.\nThis is built on top of JuliaDebug/LoweredCodeUtils.jl#116.\n\nWith this PR, the following test cases now pass correctly:\n```julia\n # Final block is not a `return`: Need to use `config::SelectiveEvalRecurse` explicitly\n ex = quote\n x = 1\n yy = 7\n @label loop\n x += 1\n x < 5 || return yy\n @goto loop\n end\n frame = Frame(ModSelective, ex)\n src = frame.framecode.src\n edges = CodeEdges(ModSelective, src)\n config = SelectiveEvalRecurse()\n isrequired = lines_required(GlobalRef(ModSelective, :x), src, edges, config)\n selective_eval_fromstart!(config, frame, isrequired, true)\n @test ModSelective.x == 5\n @test !isdefined(ModSelective, :yy)\n```\n\nThe basic approach is overloading `JuliaInterpreter.step_expr!` and\n`LoweredCodeUtils.next_or_nothing!` for the new `SelectiveEvalController`\ntype, as described below, to perform correct selective execution.\n\nWhen `SelectiveEvalController` is passed as the `recurse` argument of\n`selective_eval!`, the selective execution is adjusted as follows:\n\n- **Implicit return**: In Julia's IR representation (`CodeInfo`), the\n final block does not necessarily return and may `goto` another block.\n And if the `return` statement is not included in the slice in such\n cases, it is necessary to terminate `selective_eval!` when execution\n reaches such implicit return statements. `controller.implicit_returns`\n records the PCs of such return statements, and `selective_eval!` will\n return when reaching those statements.\n This is the core part of the fix for the test cases in\n JuliaDebug/LoweredCodeUtils.jl#99.\n\n- **CFG short-cut**: When the successors of a conditional branch are\n inactive, and it is safe to move the program counter from the\n conditional branch to the nearest common post-dominator of those\n successors, this short-cut is taken. This short-cut is not merely an\n optimization but is actually essential for the correctness of the\n selective execution. This is because, in `CodeInfo`, even if we simply\n fall-through dead blocks (i.e., increment the program counter without\n executing the statements of those blocks), it does not necessarily\n lead to the nearest common post-dominator block.\n\nAnd now [`lines_required`](@ref) or [`lines_required!`](@ref) will\nupdate the `SelectiveEvalController` passed as their argument to be\nappropriate for the program slice generated.\n\nOne thing to note is that currently, the `controller` is not be recursed.\nThat said, in Revise, which is the main consumer of LCU, there is no\nneed for recursive selective execution, and so `selective_eval!` does\nnot provide a system for inter-procedural selective evaluation.\nAccordingly `SelectiveEvalController` does not recurse too, but this can\nbe left as a future extension.","shortMessageHtmlLink":"proper termination, take 2"}},{"before":null,"after":"5a10c8495b3cf4ada4c9a1400ac042f3b911abeb","ref":"refs/heads/avi/implicit-return","pushedAt":"2024-09-10T16:21:11.000Z","pushType":"branch_creation","commitsCount":0,"pusher":{"login":"aviatesk","name":"Shuhei Kadowaki","path":"/aviatesk","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/40514306?s=80&v=4"},"commit":{"message":"proper termination, take 2\n\nThis PR is an alternative to JuliaDebug/LoweredCodeUtils.jl#99.\nThis is built on top of JuliaDebug/LoweredCodeUtils.jl#116.\n\nWith this PR, the following test cases now pass correctly:\n```julia\n # Final block is not a `return`: Need to use `config::SelectiveEvalRecurse` explicitly\n ex = quote\n x = 1\n yy = 7\n @label loop\n x += 1\n x < 5 || return yy\n @goto loop\n end\n frame = Frame(ModSelective, ex)\n src = frame.framecode.src\n edges = CodeEdges(ModSelective, src)\n config = SelectiveEvalRecurse()\n isrequired = lines_required(GlobalRef(ModSelective, :x), src, edges, config)\n selective_eval_fromstart!(config, frame, isrequired, true)\n @test ModSelective.x == 5\n @test !isdefined(ModSelective, :yy)\n```\n\nThe basic approach is overloading `JuliaInterpreter.step_expr!` and\n`LoweredCodeUtils.next_or_nothing!` for the new `SelectiveEvalController`\ntype, as described below, to perform correct selective execution.\n\nWhen `SelectiveEvalController` is passed as the `recurse` argument of\n`selective_eval!`, the selective execution is adjusted as follows:\n\n- **Implicit return**: In Julia's IR representation (`CodeInfo`), the\n final block does not necessarily return and may `goto` another block.\n And if the `return` statement is not included in the slice in such\n cases, it is necessary to terminate `selective_eval!` when execution\n reaches such implicit return statements. `controller.implicit_returns`\n records the PCs of such return statements, and `selective_eval!` will\n return when reaching those statements.\n This is the core part of the fix for the test cases in\n JuliaDebug/LoweredCodeUtils.jl#99.\n\n- **CFG short-cut**: When the successors of a conditional branch are\n inactive, and it is safe to move the program counter from the\n conditional branch to the nearest common post-dominator of those\n successors, this short-cut is taken. This short-cut is not merely an\n optimization but is actually essential for the correctness of the\n selective execution. This is because, in `CodeInfo`, even if we simply\n fall-through dead blocks (i.e., increment the program counter without\n executing the statements of those blocks), it does not necessarily\n lead to the nearest common post-dominator block.\n\nAnd now [`lines_required`](@ref) or [`lines_required!`](@ref) will\nupdate the `SelectiveEvalController` passed as their argument to be\nappropriate for the program slice generated.\n\nOne thing to note is that currently, the `controller` is not be recursed.\nThat said, in Revise, which is the main consumer of LCU, there is no\nneed for recursive selective execution, and so `selective_eval!` does\nnot provide a system for inter-procedural selective evaluation.\nAccordingly `SelectiveEvalController` does not recurse too, but this can\nbe left as a future extension.","shortMessageHtmlLink":"proper termination, take 2"}},{"before":"14f4cbc620b9c27978b4cc4df230adaab70f1796","after":"a11ae239b2a787906edbdc64c0939f6b780d1906","ref":"refs/heads/gh-pages","pushedAt":"2024-09-10T15:27:25.000Z","pushType":"push","commitsCount":1,"pusher":{"login":"timholy","name":"Tim Holy","path":"/timholy","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/1525481?s=80&v=4"},"commit":{"message":"build based on 58978f0","shortMessageHtmlLink":"build based on 58978f0"}},{"before":"c6dd7a19aff5ac9749fe445cc9dd266c405fe556","after":"fb5896d2de5805f330c5d3478c61ce36da25bd34","ref":"refs/heads/avi/new-add_control_flow!","pushedAt":"2024-09-10T15:25:11.000Z","pushType":"force_push","commitsCount":0,"pusher":{"login":"aviatesk","name":"Shuhei Kadowaki","path":"/aviatesk","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/40514306?s=80&v=4"},"commit":{"message":"remove `add_loops!`","shortMessageHtmlLink":"remove add_loops!"}},{"before":"c9d0ad601dc0aecb19d5a235ff7a65e4218ec27f","after":"14f4cbc620b9c27978b4cc4df230adaab70f1796","ref":"refs/heads/gh-pages","pushedAt":"2024-09-10T13:56:47.000Z","pushType":"push","commitsCount":1,"pusher":{"login":"timholy","name":"Tim Holy","path":"/timholy","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/1525481?s=80&v=4"},"commit":{"message":"build based on 75da0d8","shortMessageHtmlLink":"build based on 75da0d8"}},{"before":"8dd71bc6b2983dbce43206f15ef16ec1320f59c3","after":"75da0d8f68451e6edbd3a904ddca8d848e25ffa1","ref":"refs/heads/master","pushedAt":"2024-09-10T13:54:23.000Z","pushType":"push","commitsCount":1,"pusher":{"login":"aviatesk","name":"Shuhei Kadowaki","path":"/aviatesk","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/40514306?s=80&v=4"},"commit":{"message":"allow `recurse` overload for `next_or_nothing` and `skip_until[!]`","shortMessageHtmlLink":"allow recurse overload for next_or_nothing and skip_until[!]"}},{"before":"2138056d0d939d2afa15e5e12f086ee5ab2e9d37","after":"c9d0ad601dc0aecb19d5a235ff7a65e4218ec27f","ref":"refs/heads/gh-pages","pushedAt":"2024-09-10T13:51:56.000Z","pushType":"push","commitsCount":1,"pusher":{"login":"timholy","name":"Tim Holy","path":"/timholy","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/1525481?s=80&v=4"},"commit":{"message":"build based on 8dd71bc","shortMessageHtmlLink":"build based on 8dd71bc"}},{"before":"2576d56985d6c474e9a2a007f86e83871d0282e8","after":"8dd71bc6b2983dbce43206f15ef16ec1320f59c3","ref":"refs/heads/master","pushedAt":"2024-09-10T13:48:40.000Z","pushType":"push","commitsCount":1,"pusher":{"login":"aviatesk","name":"Shuhei Kadowaki","path":"/aviatesk","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/40514306?s=80&v=4"},"commit":{"message":"add missing `@nospecialize` annotations","shortMessageHtmlLink":"add missing @nospecialize annotations"}},{"before":"d79f4890de0eb16125c4989a5d776a7b44496903","after":"2138056d0d939d2afa15e5e12f086ee5ab2e9d37","ref":"refs/heads/gh-pages","pushedAt":"2024-09-10T13:08:22.000Z","pushType":"push","commitsCount":1,"pusher":{"login":"timholy","name":"Tim Holy","path":"/timholy","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/1525481?s=80&v=4"},"commit":{"message":"build based on 0ca301c","shortMessageHtmlLink":"build based on 0ca301c"}},{"before":"79363f7c8e41b14c8c2b6bab388d476cb9ea7b87","after":"c6dd7a19aff5ac9749fe445cc9dd266c405fe556","ref":"refs/heads/avi/new-add_control_flow!","pushedAt":"2024-09-10T13:05:52.000Z","pushType":"force_push","commitsCount":0,"pusher":{"login":"aviatesk","name":"Shuhei Kadowaki","path":"/aviatesk","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/40514306?s=80&v=4"},"commit":{"message":"remove `add_loops!`","shortMessageHtmlLink":"remove add_loops!"}},{"before":"906f71d13919749527bf33cb91c9e644aa3e6504","after":"d79f4890de0eb16125c4989a5d776a7b44496903","ref":"refs/heads/gh-pages","pushedAt":"2024-09-10T10:48:16.000Z","pushType":"push","commitsCount":1,"pusher":{"login":"timholy","name":"Tim Holy","path":"/timholy","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/1525481?s=80&v=4"},"commit":{"message":"build based on 2576d56","shortMessageHtmlLink":"build based on 2576d56"}},{"before":"54f669723a7fe23e60978a9539cd062b1d648d67","after":"2576d56985d6c474e9a2a007f86e83871d0282e8","ref":"refs/heads/master","pushedAt":"2024-09-10T10:46:03.000Z","pushType":"push","commitsCount":1,"pusher":{"login":"aviatesk","name":"Shuhei Kadowaki","path":"/aviatesk","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/40514306?s=80&v=4"},"commit":{"message":"follow up JuliaDebug/LoweredCodeUtils.jl#115","shortMessageHtmlLink":"follow up #115"}},{"before":"b6ed7855f09f4e0e815f866049c268a0d6145225","after":"906f71d13919749527bf33cb91c9e644aa3e6504","ref":"refs/heads/gh-pages","pushedAt":"2024-09-10T10:08:29.000Z","pushType":"push","commitsCount":1,"pusher":{"login":"timholy","name":"Tim Holy","path":"/timholy","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/1525481?s=80&v=4"},"commit":{"message":"build based on b1ef908","shortMessageHtmlLink":"build based on b1ef908"}},{"before":"0951d8564b0d5778fdb86dfdf19bb06b067f2678","after":"79363f7c8e41b14c8c2b6bab388d476cb9ea7b87","ref":"refs/heads/avi/new-add_control_flow!","pushedAt":"2024-09-10T10:06:05.000Z","pushType":"force_push","commitsCount":0,"pusher":{"login":"aviatesk","name":"Shuhei Kadowaki","path":"/aviatesk","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/40514306?s=80&v=4"},"commit":{"message":"remove `add_loops!`","shortMessageHtmlLink":"remove add_loops!"}}],"hasNextPage":true,"hasPreviousPage":false,"activityType":"all","actor":null,"timePeriod":"all","sort":"DESC","perPage":30,"startCursor":"Y3Vyc29yOnYyOpK7MjAyNC0wOS0xOVQwNzozMToxNy4wMDAwMDBazwAAAAS6iNDU","endCursor":"Y3Vyc29yOnYyOpK7MjAyNC0wOS0xMFQxMDowNjowNS4wMDAwMDBazwAAAASx40ge"}},"title":"Activity ยท JuliaDebug/LoweredCodeUtils.jl"}