{"action":"created","comment":{"url":"https://api.github.com/repos/tildeio/glimmer/pulls/comments/72110779","id":72110779,"diff_hunk":"@@ -89,11 +106,121 @@ export abstract class AppendOpcode<T extends Insertion> extends Opcode {\n   }\n }\n \n+export abstract class GuardedAppendOpcode<T extends Insertion> extends AppendOpcode<T> {\n+  protected abstract AppendOpcode: typeof OptimizedCautiousAppendOpcode | typeof OptimizedTrustingAppendOpcode;\n+  private expression: CompiledExpression<any>;\n+  private deopted: OpSeq = null;\n+\n+  constructor(expression: CompiledExpression<any>) {\n+    super();\n+    this.expression = expression;\n+  }\n+\n+  evaluate(vm: VM) {\n+    if (this.deopted) {\n+      vm.pushEvalFrame(this.deopted);\n+    } else {\n+      vm.evaluateOperand(this.expression);\n+\n+      let value = vm.frame.getOperand().value();\n+\n+      if(isComponentDefinition(value)) {\n+        vm.pushEvalFrame(this.deopt(vm.env));\n+      } else {\n+        super.evaluate(vm);\n+      }\n+    }\n+  }\n+\n+  public deopt(env: Environment): OpSeq { // Public because it's used in the lazy deopt\n+    // At compile time, we determined that this append callsite might refer\n+    // to a local variable/property lookup that resolves to a component\n+    // definition at runtime.\n+    //\n+    // We could have eagerly compiled this callsite into something like this:\n+    //\n+    //   {{#if (is-component-definition foo)}}\n+    //     {{component foo}}\n+    //   {{else}}\n+    //     {{foo}}\n+    //   {{/if}}\n+    //\n+    // However, in practice, there might be a large amout of these callsites\n+    // and most of them would resolve to a simple value lookup. Therefore, we\n+    // tried to be optimistic and assumed that the callsite will resolve to\n+    // appending a simple value.\n+    //\n+    // However, we have reached here because at runtime, the guard conditional\n+    // have detected that this callsite is indeed referring to a component\n+    // definition object. Since this is likely going to be true for other\n+    // instances of the same callsite, it is now appropiate to deopt into the\n+    // expanded version that handles both cases. The compilation would look\n+    // like this:\n+    //\n+    //               Enter(BEGIN, END)\n+    //   BEGIN:      Noop\n+    //               Test(is-component-definition)\n+    //               JumpUnless(VALUE)\n+    //   COMPONENT:  Noop\n+    //               PutDynamicComponentDefinitionOpcode\n+    //               OpenComponent\n+    //               CloseComponent\n+    //               Jump(END)\n+    //   VALUE:      Noop\n+    //               OptimizedAppend\n+    //   END:        Noop\n+    //               Exit\n+    //\n+    // Keep in mind that even if we *don't* reach here at initial render time,\n+    // it is still possible (although quite rare) that the simple value we\n+    // encounter during initial render could later change into a component\n+    // definition object at update time. That is handled by the \"lazy deopt\"\n+    // code on the update side (scroll down for the next big block of comment).\n+\n+    let buffer = new CompileIntoList(env, null);\n+    let dsl = new OpcodeBuilderDSL(buffer, null, env);\n+\n+    dsl.block({ templates: null }, (dsl, BEGIN, END) => {","path":"packages/glimmer-runtime/lib/compiled/opcodes/content.ts","position":142,"original_position":142,"commit_id":"4ed5f01590248c141568ec04b459cd6a2b9f2685","original_commit_id":"4ed5f01590248c141568ec04b459cd6a2b9f2685","user":{"login":"krisselden","id":61024,"avatar_url":"https://avatars.githubusercontent.com/u/61024?v=3","gravatar_id":"","url":"https://api.github.com/users/krisselden","html_url":"https://github.com/krisselden","followers_url":"https://api.github.com/users/krisselden/followers","following_url":"https://api.github.com/users/krisselden/following{/other_user}","gists_url":"https://api.github.com/users/krisselden/gists{/gist_id}","starred_url":"https://api.github.com/users/krisselden/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/krisselden/subscriptions","organizations_url":"https://api.github.com/users/krisselden/orgs","repos_url":"https://api.github.com/users/krisselden/repos","events_url":"https://api.github.com/users/krisselden/events{/privacy}","received_events_url":"https://api.github.com/users/krisselden/received_events","type":"User","site_admin":false},"body":"can there be an empty const for `{ templates: null }`? it isn't mutable?","created_at":"2016-07-25T17:49:42Z","updated_at":"2016-07-25T17:49:42Z","html_url":"https://github.com/tildeio/glimmer/pull/230#discussion_r72110779","pull_request_url":"https://api.github.com/repos/tildeio/glimmer/pulls/230","_links":{"self":{"href":"https://api.github.com/repos/tildeio/glimmer/pulls/comments/72110779"},"html":{"href":"https://github.com/tildeio/glimmer/pull/230#discussion_r72110779"},"pull_request":{"href":"https://api.github.com/repos/tildeio/glimmer/pulls/230"}}},"pull_request":{"url":"https://api.github.com/repos/tildeio/glimmer/pulls/230","id":78620498,"html_url":"https://github.com/tildeio/glimmer/pull/230","diff_url":"https://github.com/tildeio/glimmer/pull/230.diff","patch_url":"https://github.com/tildeio/glimmer/pull/230.patch","issue_url":"https://api.github.com/repos/tildeio/glimmer/issues/230","number":230,"state":"open","locked":false,"title":"Optimistic append","user":{"login":"chancancode","id":55829,"avatar_url":"https://avatars.githubusercontent.com/u/55829?v=3","gravatar_id":"","url":"https://api.github.com/users/chancancode","html_url":"https://github.com/chancancode","followers_url":"https://api.github.com/users/chancancode/followers","following_url":"https://api.github.com/users/chancancode/following{/other_user}","gists_url":"https://api.github.com/users/chancancode/gists{/gist_id}","starred_url":"https://api.github.com/users/chancancode/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/chancancode/subscriptions","organizations_url":"https://api.github.com/users/chancancode/orgs","repos_url":"https://api.github.com/users/chancancode/repos","events_url":"https://api.github.com/users/chancancode/events{/privacy}","received_events_url":"https://api.github.com/users/chancancode/received_events","type":"User","site_admin":false},"body":"This enables a feature (closure components) in Ember where certain curlies can dynamically resolve into component definition objects and need to be rendered as component invocations.\r\n\r\nThe general strategy to handle that is to change all curlies into (at least semantically) the equivalent of:\r\n\r\n\r\n```hbs\r\n{{#if (isComponentDefinition foo)}}{{component foo}}{{else}}{{foo}}{{/if}}\r\n```\r\n\r\nHowever, doing all that extra work and bookkeeping for literally every single curly would be very slow. Therefore, we take a tiered approach to handle this.\r\n\r\nFirst of all, in Ember the syntactic requirement for this feature is that there needs to be at least one dot in the path lookup, e.g. `... as |f|}}{{f.input}}...`, `{{foo.bar.baz}}` or `{{this.foo}}`. This allows us to emit the same append opcode (now called `OptimizedAppend`) for the majority of the append curlies. (By default, all curlies are optimized, but the consuming environment can override that in `refineStatement`.)\r\n\r\nEven then, there are still a large amount of path lookups with a dot that will not ever resolve into a component, and doing the extra work for all those cases would be less than ideal. For that reason, even we need to emit `UnoptimizedAppend`, we still assume that the values are going to be simple values.\r\n\r\nIf we discover that the assumption is not true, i.e. we see that the value is indeed a component definition at either initial render time or at update time, we will then deopt the opcodes into the expanded form.\r\n\r\nSee the code comments for more details on how it works.\r\n\r\nTODO:\r\n\r\n- [x] Handle deopts in the visualizer\r\n\r\ncc @wycats @krisselden @zackthehuman @chadhietala ","created_at":"2016-07-25T02:55:43Z","updated_at":"2016-07-25T17:49:42Z","closed_at":null,"merged_at":null,"merge_commit_sha":"df79a1af99ba78548176423acfe43fa5da7a3048","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/tildeio/glimmer/pulls/230/commits","review_comments_url":"https://api.github.com/repos/tildeio/glimmer/pulls/230/comments","review_comment_url":"https://api.github.com/repos/tildeio/glimmer/pulls/comments{/number}","comments_url":"https://api.github.com/repos/tildeio/glimmer/issues/230/comments","statuses_url":"https://api.github.com/repos/tildeio/glimmer/statuses/4ed5f01590248c141568ec04b459cd6a2b9f2685","head":{"label":"tildeio:optimistic-append","ref":"optimistic-append","sha":"4ed5f01590248c141568ec04b459cd6a2b9f2685","user":{"login":"tildeio","id":1355851,"avatar_url":"https://avatars.githubusercontent.com/u/1355851?v=3","gravatar_id":"","url":"https://api.github.com/users/tildeio","html_url":"https://github.com/tildeio","followers_url":"https://api.github.com/users/tildeio/followers","following_url":"https://api.github.com/users/tildeio/following{/other_user}","gists_url":"https://api.github.com/users/tildeio/gists{/gist_id}","starred_url":"https://api.github.com/users/tildeio/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tildeio/subscriptions","organizations_url":"https://api.github.com/users/tildeio/orgs","repos_url":"https://api.github.com/users/tildeio/repos","events_url":"https://api.github.com/users/tildeio/events{/privacy}","received_events_url":"https://api.github.com/users/tildeio/received_events","type":"Organization","site_admin":false},"repo":{"id":42467001,"name":"glimmer","full_name":"tildeio/glimmer","owner":{"login":"tildeio","id":1355851,"avatar_url":"https://avatars.githubusercontent.com/u/1355851?v=3","gravatar_id":"","url":"https://api.github.com/users/tildeio","html_url":"https://github.com/tildeio","followers_url":"https://api.github.com/users/tildeio/followers","following_url":"https://api.github.com/users/tildeio/following{/other_user}","gists_url":"https://api.github.com/users/tildeio/gists{/gist_id}","starred_url":"https://api.github.com/users/tildeio/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tildeio/subscriptions","organizations_url":"https://api.github.com/users/tildeio/orgs","repos_url":"https://api.github.com/users/tildeio/repos","events_url":"https://api.github.com/users/tildeio/events{/privacy}","received_events_url":"https://api.github.com/users/tildeio/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/tildeio/glimmer","description":"","fork":false,"url":"https://api.github.com/repos/tildeio/glimmer","forks_url":"https://api.github.com/repos/tildeio/glimmer/forks","keys_url":"https://api.github.com/repos/tildeio/glimmer/keys{/key_id}","collaborators_url":"https://api.github.com/repos/tildeio/glimmer/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/tildeio/glimmer/teams","hooks_url":"https://api.github.com/repos/tildeio/glimmer/hooks","issue_events_url":"https://api.github.com/repos/tildeio/glimmer/issues/events{/number}","events_url":"https://api.github.com/repos/tildeio/glimmer/events","assignees_url":"https://api.github.com/repos/tildeio/glimmer/assignees{/user}","branches_url":"https://api.github.com/repos/tildeio/glimmer/branches{/branch}","tags_url":"https://api.github.com/repos/tildeio/glimmer/tags","blobs_url":"https://api.github.com/repos/tildeio/glimmer/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/tildeio/glimmer/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/tildeio/glimmer/git/refs{/sha}","trees_url":"https://api.github.com/repos/tildeio/glimmer/git/trees{/sha}","statuses_url":"https://api.github.com/repos/tildeio/glimmer/statuses/{sha}","languages_url":"https://api.github.com/repos/tildeio/glimmer/languages","stargazers_url":"https://api.github.com/repos/tildeio/glimmer/stargazers","contributors_url":"https://api.github.com/repos/tildeio/glimmer/contributors","subscribers_url":"https://api.github.com/repos/tildeio/glimmer/subscribers","subscription_url":"https://api.github.com/repos/tildeio/glimmer/subscription","commits_url":"https://api.github.com/repos/tildeio/glimmer/commits{/sha}","git_commits_url":"https://api.github.com/repos/tildeio/glimmer/git/commits{/sha}","comments_url":"https://api.github.com/repos/tildeio/glimmer/comments{/number}","issue_comment_url":"https://api.github.com/repos/tildeio/glimmer/issues/comments{/number}","contents_url":"https://api.github.com/repos/tildeio/glimmer/contents/{+path}","compare_url":"https://api.github.com/repos/tildeio/glimmer/compare/{base}...{head}","merges_url":"https://api.github.com/repos/tildeio/glimmer/merges","archive_url":"https://api.github.com/repos/tildeio/glimmer/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/tildeio/glimmer/downloads","issues_url":"https://api.github.com/repos/tildeio/glimmer/issues{/number}","pulls_url":"https://api.github.com/repos/tildeio/glimmer/pulls{/number}","milestones_url":"https://api.github.com/repos/tildeio/glimmer/milestones{/number}","notifications_url":"https://api.github.com/repos/tildeio/glimmer/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/tildeio/glimmer/labels{/name}","releases_url":"https://api.github.com/repos/tildeio/glimmer/releases{/id}","deployments_url":"https://api.github.com/repos/tildeio/glimmer/deployments","created_at":"2015-09-14T17:59:26Z","updated_at":"2016-07-23T03:22:29Z","pushed_at":"2016-07-25T16:27:12Z","git_url":"git://github.com/tildeio/glimmer.git","ssh_url":"git@github.com:tildeio/glimmer.git","clone_url":"https://github.com/tildeio/glimmer.git","svn_url":"https://github.com/tildeio/glimmer","homepage":null,"size":3774,"stargazers_count":231,"watchers_count":231,"language":"TypeScript","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":39,"mirror_url":null,"open_issues_count":28,"forks":39,"open_issues":28,"watchers":231,"default_branch":"master"}},"base":{"label":"tildeio:master","ref":"master","sha":"ec42f9837eceb3ea5cbe0b1311a4df6ef38e5e4e","user":{"login":"tildeio","id":1355851,"avatar_url":"https://avatars.githubusercontent.com/u/1355851?v=3","gravatar_id":"","url":"https://api.github.com/users/tildeio","html_url":"https://github.com/tildeio","followers_url":"https://api.github.com/users/tildeio/followers","following_url":"https://api.github.com/users/tildeio/following{/other_user}","gists_url":"https://api.github.com/users/tildeio/gists{/gist_id}","starred_url":"https://api.github.com/users/tildeio/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tildeio/subscriptions","organizations_url":"https://api.github.com/users/tildeio/orgs","repos_url":"https://api.github.com/users/tildeio/repos","events_url":"https://api.github.com/users/tildeio/events{/privacy}","received_events_url":"https://api.github.com/users/tildeio/received_events","type":"Organization","site_admin":false},"repo":{"id":42467001,"name":"glimmer","full_name":"tildeio/glimmer","owner":{"login":"tildeio","id":1355851,"avatar_url":"https://avatars.githubusercontent.com/u/1355851?v=3","gravatar_id":"","url":"https://api.github.com/users/tildeio","html_url":"https://github.com/tildeio","followers_url":"https://api.github.com/users/tildeio/followers","following_url":"https://api.github.com/users/tildeio/following{/other_user}","gists_url":"https://api.github.com/users/tildeio/gists{/gist_id}","starred_url":"https://api.github.com/users/tildeio/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tildeio/subscriptions","organizations_url":"https://api.github.com/users/tildeio/orgs","repos_url":"https://api.github.com/users/tildeio/repos","events_url":"https://api.github.com/users/tildeio/events{/privacy}","received_events_url":"https://api.github.com/users/tildeio/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/tildeio/glimmer","description":"","fork":false,"url":"https://api.github.com/repos/tildeio/glimmer","forks_url":"https://api.github.com/repos/tildeio/glimmer/forks","keys_url":"https://api.github.com/repos/tildeio/glimmer/keys{/key_id}","collaborators_url":"https://api.github.com/repos/tildeio/glimmer/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/tildeio/glimmer/teams","hooks_url":"https://api.github.com/repos/tildeio/glimmer/hooks","issue_events_url":"https://api.github.com/repos/tildeio/glimmer/issues/events{/number}","events_url":"https://api.github.com/repos/tildeio/glimmer/events","assignees_url":"https://api.github.com/repos/tildeio/glimmer/assignees{/user}","branches_url":"https://api.github.com/repos/tildeio/glimmer/branches{/branch}","tags_url":"https://api.github.com/repos/tildeio/glimmer/tags","blobs_url":"https://api.github.com/repos/tildeio/glimmer/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/tildeio/glimmer/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/tildeio/glimmer/git/refs{/sha}","trees_url":"https://api.github.com/repos/tildeio/glimmer/git/trees{/sha}","statuses_url":"https://api.github.com/repos/tildeio/glimmer/statuses/{sha}","languages_url":"https://api.github.com/repos/tildeio/glimmer/languages","stargazers_url":"https://api.github.com/repos/tildeio/glimmer/stargazers","contributors_url":"https://api.github.com/repos/tildeio/glimmer/contributors","subscribers_url":"https://api.github.com/repos/tildeio/glimmer/subscribers","subscription_url":"https://api.github.com/repos/tildeio/glimmer/subscription","commits_url":"https://api.github.com/repos/tildeio/glimmer/commits{/sha}","git_commits_url":"https://api.github.com/repos/tildeio/glimmer/git/commits{/sha}","comments_url":"https://api.github.com/repos/tildeio/glimmer/comments{/number}","issue_comment_url":"https://api.github.com/repos/tildeio/glimmer/issues/comments{/number}","contents_url":"https://api.github.com/repos/tildeio/glimmer/contents/{+path}","compare_url":"https://api.github.com/repos/tildeio/glimmer/compare/{base}...{head}","merges_url":"https://api.github.com/repos/tildeio/glimmer/merges","archive_url":"https://api.github.com/repos/tildeio/glimmer/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/tildeio/glimmer/downloads","issues_url":"https://api.github.com/repos/tildeio/glimmer/issues{/number}","pulls_url":"https://api.github.com/repos/tildeio/glimmer/pulls{/number}","milestones_url":"https://api.github.com/repos/tildeio/glimmer/milestones{/number}","notifications_url":"https://api.github.com/repos/tildeio/glimmer/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/tildeio/glimmer/labels{/name}","releases_url":"https://api.github.com/repos/tildeio/glimmer/releases{/id}","deployments_url":"https://api.github.com/repos/tildeio/glimmer/deployments","created_at":"2015-09-14T17:59:26Z","updated_at":"2016-07-23T03:22:29Z","pushed_at":"2016-07-25T16:27:12Z","git_url":"git://github.com/tildeio/glimmer.git","ssh_url":"git@github.com:tildeio/glimmer.git","clone_url":"https://github.com/tildeio/glimmer.git","svn_url":"https://github.com/tildeio/glimmer","homepage":null,"size":3774,"stargazers_count":231,"watchers_count":231,"language":"TypeScript","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":39,"mirror_url":null,"open_issues_count":28,"forks":39,"open_issues":28,"watchers":231,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/tildeio/glimmer/pulls/230"},"html":{"href":"https://github.com/tildeio/glimmer/pull/230"},"issue":{"href":"https://api.github.com/repos/tildeio/glimmer/issues/230"},"comments":{"href":"https://api.github.com/repos/tildeio/glimmer/issues/230/comments"},"review_comments":{"href":"https://api.github.com/repos/tildeio/glimmer/pulls/230/comments"},"review_comment":{"href":"https://api.github.com/repos/tildeio/glimmer/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/tildeio/glimmer/pulls/230/commits"},"statuses":{"href":"https://api.github.com/repos/tildeio/glimmer/statuses/4ed5f01590248c141568ec04b459cd6a2b9f2685"}}}}
{"actor":{"display_login":"krisselden"}}