{"action":"created","issue":{"url":"https://api.github.com/repos/JuliaLang/julia/issues/16034","repository_url":"https://api.github.com/repos/JuliaLang/julia","labels_url":"https://api.github.com/repos/JuliaLang/julia/issues/16034/labels{/name}","comments_url":"https://api.github.com/repos/JuliaLang/julia/issues/16034/comments","events_url":"https://api.github.com/repos/JuliaLang/julia/issues/16034/events","html_url":"https://github.com/JuliaLang/julia/pull/16034","id":150730229,"number":16034,"title":"WIP: Lazy store to gc slots","user":{"login":"yuyichao","id":712232,"avatar_url":"https://avatars.githubusercontent.com/u/712232?v=3","gravatar_id":"","url":"https://api.github.com/users/yuyichao","html_url":"https://github.com/yuyichao","followers_url":"https://api.github.com/users/yuyichao/followers","following_url":"https://api.github.com/users/yuyichao/following{/other_user}","gists_url":"https://api.github.com/users/yuyichao/gists{/gist_id}","starred_url":"https://api.github.com/users/yuyichao/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/yuyichao/subscriptions","organizations_url":"https://api.github.com/users/yuyichao/orgs","repos_url":"https://api.github.com/users/yuyichao/repos","events_url":"https://api.github.com/users/yuyichao/events{/privacy}","received_events_url":"https://api.github.com/users/yuyichao/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/JuliaLang/julia/labels/codegen","name":"codegen","color":"d4c5f9"},{"url":"https://api.github.com/repos/JuliaLang/julia/labels/GC","name":"GC","color":"009800"}],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":1,"created_at":"2016-04-25T02:40:02Z","updated_at":"2016-04-25T14:21:35Z","closed_at":null,"pull_request":{"url":"https://api.github.com/repos/JuliaLang/julia/pulls/16034","html_url":"https://github.com/JuliaLang/julia/pull/16034","diff_url":"https://github.com/JuliaLang/julia/pull/16034.diff","patch_url":"https://github.com/JuliaLang/julia/pull/16034.patch"},"body":"Fixes https://github.com/JuliaLang/julia/issues/15457\r\nThis should also help implementing GC transition in codegen since `GC unsafe` ≈ `there's pending GC stores`.\r\n\r\nCommits 1-22 are the iterative process of delaying when gc stores are flushed which should help bisecting if there's any missing root. I'll squash them when this is ready.\r\n\r\n@vtjnash It seems that not having a load or a kill doesn't mean the root is not needed? So how exactly can one tell the lifetime of a root?\r\n\r\nFor example, the LLVM IR generated for the following code on this PR,\r\n\r\n```jl\r\nfunction f2()\r\n    a = Ref(1)\r\n    b = a\r\n    g()\r\n    b\r\nend\r\n```\r\n\r\n```llvm\r\ndefine %jl_value_t* @julia_f2_53239() #0 {\r\ntop:\r\n  %a = alloca %jl_value_t*\r\n  %b = alloca %jl_value_t*\r\n  %0 = call %jl_value_t** @julia.gc_root_decl()\r\n  %1 = call %jl_value_t** @julia.gc_root_decl()\r\n  %2 = call %jl_value_t** @julia.gc_root_decl()\r\n  %3 = call %jl_value_t*** @jl_get_ptls_states()\r\n  call void @llvm.dbg.declare(metadata %jl_value_t** %a, metadata !11, metadata !16), !dbg !17\r\n  call void @llvm.dbg.declare(metadata %jl_value_t** %b, metadata !15, metadata !16), !dbg !17\r\n  %4 = call %jl_value_t* @jl_gc_alloc_1w(), !dbg !18\r\n  %5 = bitcast %jl_value_t* %4 to %jl_value_t**, !dbg !18\r\n  %6 = getelementptr %jl_value_t*, %jl_value_t** %5, i64 -1, !dbg !18\r\n  store %jl_value_t* inttoptr (i64 139959089228864 to %jl_value_t*), %jl_value_t** %6, !dbg !18\r\n  %7 = bitcast %jl_value_t* %4 to i8*, !dbg !18\r\n  %8 = getelementptr i8, i8* %7, i64 0, !dbg !18\r\n  %9 = bitcast i8* %8 to i64*, !dbg !18\r\n  %10 = getelementptr i64, i64* %9, i64 0, !dbg !18\r\n  store i64 1, i64* %10, align 16, !dbg !18, !tbaa !22\r\n  store %jl_value_t* %4, %jl_value_t** %b, !dbg !24\r\n  store %jl_value_t* %4, %jl_value_t** %1, !dbg !24\r\n  store %jl_value_t* %4, %jl_value_t** %0, !dbg !24\r\n  store %jl_value_t* %4, %jl_value_t** %a, !dbg !24\r\n  call void @julia_g_53240() #0, !dbg !24\r\n  %11 = load %jl_value_t*, %jl_value_t** %b, !dbg !25\r\n  ret %jl_value_t* %11, !dbg !25\r\n}\r\n```\r\n\r\n(on master the difference is that there's one more store to `%2` after the call and a few more load before the call). One of `%0` or `%1` should be the necessary root when calling `g` but it seems that none of them are loaded from or marked as use after the call either on master or on this PR.\r\n"},"comment":{"url":"https://api.github.com/repos/JuliaLang/julia/issues/comments/214357198","html_url":"https://github.com/JuliaLang/julia/pull/16034#issuecomment-214357198","issue_url":"https://api.github.com/repos/JuliaLang/julia/issues/16034","id":214357198,"user":{"login":"vtjnash","id":330950,"avatar_url":"https://avatars.githubusercontent.com/u/330950?v=3","gravatar_id":"","url":"https://api.github.com/users/vtjnash","html_url":"https://github.com/vtjnash","followers_url":"https://api.github.com/users/vtjnash/followers","following_url":"https://api.github.com/users/vtjnash/following{/other_user}","gists_url":"https://api.github.com/users/vtjnash/gists{/gist_id}","starred_url":"https://api.github.com/users/vtjnash/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/vtjnash/subscriptions","organizations_url":"https://api.github.com/users/vtjnash/orgs","repos_url":"https://api.github.com/users/vtjnash/repos","events_url":"https://api.github.com/users/vtjnash/events{/privacy}","received_events_url":"https://api.github.com/users/vtjnash/received_events","type":"User","site_admin":false},"created_at":"2016-04-25T14:21:34Z","updated_at":"2016-04-25T14:21:34Z","body":"i think this is one of the more trivial optimizations to implement in llvm-gcroot.cpp. in particular, it could use the dominator tree for a -> b -> ret and determine that the previous root was sufficient to keep the value alive. secondly, the instruction whitelist in collapse-redundant-roots can be extended to cover more cases. thirdly, we should also mark stores with, e.g., tbaa_gcstore to indicate they can be used to avoid a local root and teach the gcroot algorithm of this as well.\r\n\r\n> It seems that not having a load or a kill doesn't mean the root is not needed? So how exactly can one tell the lifetime of a root?\r\n\r\ncomputed via pointers tracing for all uses. it might be useful to try switching from `julia.gc_root_decl` to `julia.jlcall_frame_decl(1)` and updating the liveness algorithm to handle this (currently it assumes static-single-use)"}}