{"action":"created","issue":{"url":"https://api.github.com/repos/jruby/jruby/issues/2562","labels_url":"https://api.github.com/repos/jruby/jruby/issues/2562/labels{/name}","comments_url":"https://api.github.com/repos/jruby/jruby/issues/2562/comments","events_url":"https://api.github.com/repos/jruby/jruby/issues/2562/events","html_url":"https://github.com/jruby/jruby/pull/2562","id":56597076,"number":2562,"title":"Skip block-to-proc conversion for explicit block syntax when possible","user":{"login":"sgrif","id":1529387,"avatar_url":"https://avatars.githubusercontent.com/u/1529387?v=3","gravatar_id":"","url":"https://api.github.com/users/sgrif","html_url":"https://github.com/sgrif","followers_url":"https://api.github.com/users/sgrif/followers","following_url":"https://api.github.com/users/sgrif/following{/other_user}","gists_url":"https://api.github.com/users/sgrif/gists{/gist_id}","starred_url":"https://api.github.com/users/sgrif/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/sgrif/subscriptions","organizations_url":"https://api.github.com/users/sgrif/orgs","repos_url":"https://api.github.com/users/sgrif/repos","events_url":"https://api.github.com/users/sgrif/events{/privacy}","received_events_url":"https://api.github.com/users/sgrif/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/jruby/jruby/labels/ir","name":"ir","color":"fbca04"}],"state":"open","locked":false,"assignee":null,"milestone":{"url":"https://api.github.com/repos/jruby/jruby/milestones/32","labels_url":"https://api.github.com/repos/jruby/jruby/milestones/32/labels","id":944306,"number":32,"title":"9.0.0.0.pre2","description":"","creator":{"login":"enebo","id":19819,"avatar_url":"https://avatars.githubusercontent.com/u/19819?v=3","gravatar_id":"","url":"https://api.github.com/users/enebo","html_url":"https://github.com/enebo","followers_url":"https://api.github.com/users/enebo/followers","following_url":"https://api.github.com/users/enebo/following{/other_user}","gists_url":"https://api.github.com/users/enebo/gists{/gist_id}","starred_url":"https://api.github.com/users/enebo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/enebo/subscriptions","organizations_url":"https://api.github.com/users/enebo/orgs","repos_url":"https://api.github.com/users/enebo/repos","events_url":"https://api.github.com/users/enebo/events{/privacy}","received_events_url":"https://api.github.com/users/enebo/received_events","type":"User","site_admin":false},"open_issues":15,"closed_issues":20,"state":"open","created_at":"2015-01-20T21:46:46Z","updated_at":"2015-02-05T19:59:02Z","due_on":null,"closed_at":null},"comments":19,"created_at":"2015-02-04T22:22:54Z","updated_at":"2015-02-05T20:49:20Z","closed_at":null,"pull_request":{"url":"https://api.github.com/repos/jruby/jruby/pulls/2562","html_url":"https://github.com/jruby/jruby/pull/2562","diff_url":"https://github.com/jruby/jruby/pull/2562.diff","patch_url":"https://github.com/jruby/jruby/pull/2562.patch"},"body":"If an explicit block is captured as a proc, but its only usage is\r\nconverting it back to a block and passing it through, we can skip the\r\nconversion entirely, and just pass through the original block.\r\n\r\nThis pass looks for all explicit block conversions, and checks if\r\nthey're ever used in any context besides being passed as a block. If\r\nnot, we rewrite all uses of the proc to pass the block through instead.\r\nThe dead code elimination will remove the proc as an unused variable.\r\n\r\nIt may be possible to implement this without adding another compiler\r\npass, but I had trouble finding a place where it fit nicely, especially\r\nsince it needs to run before the LiveVariableAnalysis.\r\n\r\nI believe the same optimization could occur to skip array allocation for splatted args, and hash allocation for double splatted args, in this same compiler pass.\r\n\r\nGiven the following Ruby code:\r\n\r\n```ruby\r\ndef foo(&block)\r\n  bar(&block)\r\nend\r\n```\r\n\r\nThe instruction sequence before was:\r\n\r\n```\r\n%self = recv_self\r\ncheck_arity req: 0, opt: 0, *r: -1, kw: false, **r: -1\r\n%v_1 = load_implicit_closure\r\n%t_block_2 = reify_closure(%v_1)\r\nline_num(1)\r\n%v_1 = call(FUNCTIONAL, bar, %self, [], &%t_block_2)\r\nreturn(%v_1)\r\n```\r\n\r\nWith this patch, the instruction sequence changes to:\r\n\r\n```\r\n%self = recv_self\r\ncheck_arity req: 0, opt: 0, *r: -1, kw: false, **r: -1\r\n%v_1 = load_implicit_closure\r\nline_num(1)\r\n%v_1 = call(FUNCTIONAL, bar, %self, [], &%v_1)\r\nreturn(%v_1)\r\n```\r\n\r\nWhich gives a healthy boost to performance on any code which passes\r\nblocks through explicitly."},"comment":{"url":"https://api.github.com/repos/jruby/jruby/issues/comments/73124586","html_url":"https://github.com/jruby/jruby/pull/2562#issuecomment-73124586","issue_url":"https://api.github.com/repos/jruby/jruby/issues/2562","id":73124586,"user":{"login":"sgrif","id":1529387,"avatar_url":"https://avatars.githubusercontent.com/u/1529387?v=3","gravatar_id":"","url":"https://api.github.com/users/sgrif","html_url":"https://github.com/sgrif","followers_url":"https://api.github.com/users/sgrif/followers","following_url":"https://api.github.com/users/sgrif/following{/other_user}","gists_url":"https://api.github.com/users/sgrif/gists{/gist_id}","starred_url":"https://api.github.com/users/sgrif/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/sgrif/subscriptions","organizations_url":"https://api.github.com/users/sgrif/orgs","repos_url":"https://api.github.com/users/sgrif/repos","events_url":"https://api.github.com/users/sgrif/events{/privacy}","received_events_url":"https://api.github.com/users/sgrif/received_events","type":"User","site_admin":false},"created_at":"2015-02-05T20:49:20Z","updated_at":"2015-02-05T20:49:20Z","body":"Cool. I'll squash into a single commit. Were there any explicit tests I should add for this?"}}