| Index: runtime/vm/flow_graph_builder.cc
 | 
| ===================================================================
 | 
| --- runtime/vm/flow_graph_builder.cc	(revision 41393)
 | 
| +++ runtime/vm/flow_graph_builder.cc	(working copy)
 | 
| @@ -759,7 +759,7 @@
 | 
|      intptr_t delta =
 | 
|          owner()->context_level() - local.owner()->context_level();
 | 
|      ASSERT(delta >= 0);
 | 
| -    Value* context = Bind(new(I) CurrentContextInstr());
 | 
| +    Value* context = Bind(BuildCurrentContext());
 | 
|      while (delta-- > 0) {
 | 
|        context = Bind(new(I) LoadFieldInstr(
 | 
|            context, Context::parent_offset(), Type::ZoneHandle(I, Type::null()),
 | 
| @@ -787,7 +787,7 @@
 | 
|      intptr_t delta =
 | 
|          owner()->context_level() - local.owner()->context_level();
 | 
|      ASSERT(delta >= 0);
 | 
| -    Value* context = Bind(new(I) CurrentContextInstr());
 | 
| +    Value* context = Bind(BuildCurrentContext());
 | 
|      while (delta-- > 0) {
 | 
|        context = Bind(new(I) LoadFieldInstr(
 | 
|            context, Context::parent_offset(), Type::ZoneHandle(I, Type::null()),
 | 
| @@ -805,7 +805,7 @@
 | 
|  
 | 
|  // Stores current context into the 'variable'
 | 
|  void EffectGraphVisitor::BuildSaveContext(const LocalVariable& variable) {
 | 
| -  Value* context = Bind(new(I) CurrentContextInstr());
 | 
| +  Value* context = Bind(BuildCurrentContext());
 | 
|    Do(BuildStoreLocal(variable, context));
 | 
|  }
 | 
|  
 | 
| @@ -813,10 +813,22 @@
 | 
|  // Loads context saved in 'context_variable' into the current context.
 | 
|  void EffectGraphVisitor::BuildRestoreContext(const LocalVariable& variable) {
 | 
|    Value* load_saved_context = Bind(BuildLoadLocal(variable));
 | 
| -  AddInstruction(new(I) StoreContextInstr(load_saved_context));
 | 
| +  Do(BuildStoreContext(load_saved_context));
 | 
|  }
 | 
|  
 | 
|  
 | 
| +Definition* EffectGraphVisitor::BuildStoreContext(Value* value) {
 | 
| +  return new(I) StoreLocalInstr(
 | 
| +      *owner()->parsed_function()->current_context_var(), value);
 | 
| +}
 | 
| +
 | 
| +
 | 
| +Definition* EffectGraphVisitor::BuildCurrentContext() {
 | 
| +  return new(I) LoadLocalInstr(
 | 
| +      *owner()->parsed_function()->current_context_var());
 | 
| +}
 | 
| +
 | 
| +
 | 
|  void TestGraphVisitor::ConnectBranchesTo(
 | 
|      const GrowableArray<TargetEntryInstr**>& branches,
 | 
|      JoinEntryInstr* join) const {
 | 
| @@ -1268,12 +1280,12 @@
 | 
|    const String& name = String::ZoneHandle(I, Symbols::New(node->TokenName()));
 | 
|    const intptr_t kNumArgsChecked = 2;
 | 
|    InstanceCallInstr* call = new(I) InstanceCallInstr(node->token_pos(),
 | 
| -                                                  name,
 | 
| -                                                  node->kind(),
 | 
| -                                                  arguments,
 | 
| -                                                  Object::null_array(),
 | 
| -                                                  kNumArgsChecked,
 | 
| -                                                  owner()->ic_data_array());
 | 
| +                                                     name,
 | 
| +                                                     node->kind(),
 | 
| +                                                     arguments,
 | 
| +                                                     Object::null_array(),
 | 
| +                                                     kNumArgsChecked,
 | 
| +                                                     owner()->ic_data_array());
 | 
|    ReturnDefinition(call);
 | 
|  }
 | 
|  
 | 
| @@ -1366,12 +1378,12 @@
 | 
|    arguments->Add(push_mask);
 | 
|    const intptr_t kNumArgsChecked = 2;
 | 
|    InstanceCallInstr* call = new(I) InstanceCallInstr(node->token_pos(),
 | 
| -                                                  BinaryOpAndMaskName(node),
 | 
| -                                                  Token::kILLEGAL,
 | 
| -                                                  arguments,
 | 
| -                                                  Object::null_array(),
 | 
| -                                                  kNumArgsChecked,
 | 
| -                                                  owner()->ic_data_array());
 | 
| +                                                     BinaryOpAndMaskName(node),
 | 
| +                                                     Token::kILLEGAL,
 | 
| +                                                     arguments,
 | 
| +                                                     Object::null_array(),
 | 
| +                                                     kNumArgsChecked,
 | 
| +                                                     owner()->ic_data_array());
 | 
|    ReturnDefinition(call);
 | 
|  }
 | 
|  
 | 
| @@ -1496,7 +1508,7 @@
 | 
|    intptr_t delta = old_ctx_level -
 | 
|                     continuation_result->owner()->context_level();
 | 
|    ASSERT(delta >= 0);
 | 
| -  Value* context = Bind(new(I) CurrentContextInstr());
 | 
| +  Value* context = Bind(BuildCurrentContext());
 | 
|    while (delta-- > 0) {
 | 
|      context = Bind(new(I) LoadFieldInstr(
 | 
|          context, Context::parent_offset(), Type::ZoneHandle(I, Type::null()),
 | 
| @@ -1744,14 +1756,14 @@
 | 
|      PushArgumentInstr* push_right = PushArgument(for_right_value.value());
 | 
|      arguments->Add(push_right);
 | 
|  
 | 
| -    Definition* result =
 | 
| -        new(I) InstanceCallInstr(node->token_pos(),
 | 
| -                                 Symbols::EqualOperator(),
 | 
| -                              Token::kEQ,  // Result is negated later for kNE.
 | 
| -                              arguments,
 | 
| -                              Object::null_array(),
 | 
| -                              2,
 | 
| -                              owner()->ic_data_array());
 | 
| +    Definition* result = new(I) InstanceCallInstr(
 | 
| +        node->token_pos(),
 | 
| +        Symbols::EqualOperator(),
 | 
| +        Token::kEQ,  // Result is negated later for kNE.
 | 
| +        arguments,
 | 
| +        Object::null_array(),
 | 
| +        2,
 | 
| +        owner()->ic_data_array());
 | 
|      if (node->kind() == Token::kNE) {
 | 
|        if (FLAG_enable_type_checks) {
 | 
|          Value* value = Bind(result);
 | 
| @@ -1780,15 +1792,14 @@
 | 
|    arguments->Add(push_right);
 | 
|  
 | 
|    ASSERT(Token::IsRelationalOperator(node->kind()));
 | 
| -  InstanceCallInstr* comp =
 | 
| -      new(I) InstanceCallInstr(node->token_pos(),
 | 
| -                            String::ZoneHandle(
 | 
| -                                I, Symbols::New(node->TokenName())),
 | 
| -                            node->kind(),
 | 
| -                            arguments,
 | 
| -                            Object::null_array(),
 | 
| -                            2,
 | 
| -                            owner()->ic_data_array());
 | 
| +  InstanceCallInstr* comp = new(I) InstanceCallInstr(
 | 
| +      node->token_pos(),
 | 
| +      String::ZoneHandle(I, Symbols::New(node->TokenName())),
 | 
| +      node->kind(),
 | 
| +      arguments,
 | 
| +      Object::null_array(),
 | 
| +      2,
 | 
| +      owner()->ic_data_array());
 | 
|    ReturnDefinition(comp);
 | 
|  }
 | 
|  
 | 
| @@ -1816,15 +1827,14 @@
 | 
|    ZoneGrowableArray<PushArgumentInstr*>* arguments =
 | 
|        new(I) ZoneGrowableArray<PushArgumentInstr*>(1);
 | 
|    arguments->Add(push_value);
 | 
| -  InstanceCallInstr* call =
 | 
| -      new(I) InstanceCallInstr(node->token_pos(),
 | 
| -                            String::ZoneHandle(
 | 
| -                                I, Symbols::New(node->TokenName())),
 | 
| -                            node->kind(),
 | 
| -                            arguments,
 | 
| -                            Object::null_array(),
 | 
| -                            1,
 | 
| -                            owner()->ic_data_array());
 | 
| +  InstanceCallInstr* call = new(I) InstanceCallInstr(
 | 
| +      node->token_pos(),
 | 
| +      String::ZoneHandle(I, Symbols::New(node->TokenName())),
 | 
| +      node->kind(),
 | 
| +      arguments,
 | 
| +      Object::null_array(),
 | 
| +      1,
 | 
| +      owner()->ic_data_array());
 | 
|    ReturnDefinition(call);
 | 
|  }
 | 
|  
 | 
| @@ -2525,7 +2535,7 @@
 | 
|      } else {
 | 
|        // Store current context in closure.
 | 
|        closure_tmp_val = Bind(new(I) LoadLocalInstr(*closure_tmp_var));
 | 
| -      Value* context = Bind(new(I) CurrentContextInstr());
 | 
| +      Value* context = Bind(BuildCurrentContext());
 | 
|        Do(new(I) StoreInstanceFieldInstr(Closure::context_offset(),
 | 
|                                          closure_tmp_val,
 | 
|                                          context,
 | 
| @@ -2611,10 +2621,10 @@
 | 
|    BuildPushArguments(*node->arguments(), arguments);
 | 
|    StaticCallInstr* call =
 | 
|        new(I) StaticCallInstr(node->token_pos(),
 | 
| -                          node->function(),
 | 
| -                          node->arguments()->names(),
 | 
| -                          arguments,
 | 
| -                          owner()->ic_data_array());
 | 
| +                             node->function(),
 | 
| +                             node->arguments()->names(),
 | 
| +                             arguments,
 | 
| +                             owner()->ic_data_array());
 | 
|    if (node->function().is_native()) {
 | 
|      const intptr_t result_cid = GetResultCidOfNativeFactory(node->function());
 | 
|      if (result_cid != kDynamicCid) {
 | 
| @@ -2641,19 +2651,7 @@
 | 
|    arguments->Add(push_closure);
 | 
|    BuildPushArguments(*node->arguments(), arguments);
 | 
|  
 | 
| -  // Save context around the call.
 | 
| -  ASSERT(owner()->parsed_function()->saved_current_context_var() != NULL);
 | 
| -  BuildSaveContext(*owner()->parsed_function()->saved_current_context_var());
 | 
|    closure_val = Bind(new(I) LoadLocalInstr(*tmp_var));
 | 
| -  LoadFieldInstr* context_load = new(I) LoadFieldInstr(
 | 
| -      closure_val,
 | 
| -      Closure::context_offset(),
 | 
| -      AbstractType::ZoneHandle(I, AbstractType::null()),
 | 
| -      node->token_pos());
 | 
| -  context_load->set_is_immutable(true);
 | 
| -  Value* context_val = Bind(context_load);
 | 
| -  AddInstruction(new(I) StoreContextInstr(context_val));
 | 
| -  closure_val = Bind(new(I) LoadLocalInstr(*tmp_var));
 | 
|    LoadFieldInstr* function_load = new(I) LoadFieldInstr(
 | 
|        closure_val,
 | 
|        Closure::function_offset(),
 | 
| @@ -2661,22 +2659,16 @@
 | 
|        node->token_pos());
 | 
|    function_load->set_is_immutable(true);
 | 
|    Value* function_val = Bind(function_load);
 | 
| +
 | 
|    Definition* closure_call =
 | 
|        new(I) ClosureCallInstr(function_val, node, arguments);
 | 
|    if (result_needed) {
 | 
|      Value* result = Bind(closure_call);
 | 
|      Do(new(I) StoreLocalInstr(*tmp_var, result));
 | 
| -    // Restore context from temp.
 | 
| -    BuildRestoreContext(
 | 
| -        *owner()->parsed_function()->saved_current_context_var());
 | 
| -    ReturnDefinition(ExitTempLocalScope(tmp_var));
 | 
|    } else {
 | 
|      Do(closure_call);
 | 
| -    // Restore context from saved location.
 | 
| -    BuildRestoreContext(
 | 
| -        *owner()->parsed_function()->saved_current_context_var());
 | 
| -    Do(ExitTempLocalScope(tmp_var));
 | 
|    }
 | 
| +  ReturnDefinition(ExitTempLocalScope(tmp_var));
 | 
|  }
 | 
|  
 | 
|  
 | 
| @@ -2697,9 +2689,9 @@
 | 
|  
 | 
|  
 | 
|  void EffectGraphVisitor::VisitCloneContextNode(CloneContextNode* node) {
 | 
| -  Value* context = Bind(new(I) CurrentContextInstr());
 | 
| +  Value* context = Bind(BuildCurrentContext());
 | 
|    Value* clone = Bind(new(I) CloneContextInstr(node->token_pos(), context));
 | 
| -  AddInstruction(new(I) StoreContextInstr(clone));
 | 
| +  Do(BuildStoreContext(clone));
 | 
|  }
 | 
|  
 | 
|  
 | 
| @@ -2739,10 +2731,10 @@
 | 
|  
 | 
|    BuildPushArguments(*node->arguments(), arguments);
 | 
|    Do(new(I) StaticCallInstr(node->token_pos(),
 | 
| -                         node->constructor(),
 | 
| -                         node->arguments()->names(),
 | 
| -                         arguments,
 | 
| -                         owner()->ic_data_array()));
 | 
| +                            node->constructor(),
 | 
| +                            node->arguments()->names(),
 | 
| +                            arguments,
 | 
| +                            owner()->ic_data_array()));
 | 
|  }
 | 
|  
 | 
|  
 | 
| @@ -2782,10 +2774,10 @@
 | 
|      BuildPushArguments(*node->arguments(), arguments);
 | 
|      StaticCallInstr* call =
 | 
|          new(I) StaticCallInstr(node->token_pos(),
 | 
| -                            node->constructor(),
 | 
| -                            node->arguments()->names(),
 | 
| -                            arguments,
 | 
| -                            owner()->ic_data_array());
 | 
| +                               node->constructor(),
 | 
| +                               node->arguments()->names(),
 | 
| +                               arguments,
 | 
| +                               owner()->ic_data_array());
 | 
|      const intptr_t result_cid = GetResultCidOfListFactory(node);
 | 
|      if (result_cid != kDynamicCid) {
 | 
|        call->set_result_cid(result_cid);
 | 
| @@ -3536,21 +3528,22 @@
 | 
|    if (super_function != NULL) {
 | 
|      // Generate static call to super operator.
 | 
|      StaticCallInstr* load = new(I) StaticCallInstr(node->token_pos(),
 | 
| -                                                *super_function,
 | 
| -                                                Object::null_array(),
 | 
| -                                                arguments,
 | 
| -                                                owner()->ic_data_array());
 | 
| +                                                   *super_function,
 | 
| +                                                   Object::null_array(),
 | 
| +                                                   arguments,
 | 
| +                                                   owner()->ic_data_array());
 | 
|      ReturnDefinition(load);
 | 
|    } else {
 | 
|      // Generate dynamic call to index operator.
 | 
|      const intptr_t checked_argument_count = 1;
 | 
| -    InstanceCallInstr* load = new(I) InstanceCallInstr(node->token_pos(),
 | 
| -                                                    Symbols::IndexToken(),
 | 
| -                                                    Token::kINDEX,
 | 
| -                                                    arguments,
 | 
| -                                                    Object::null_array(),
 | 
| -                                                    checked_argument_count,
 | 
| -                                                    owner()->ic_data_array());
 | 
| +    InstanceCallInstr* load = new(I) InstanceCallInstr(
 | 
| +        node->token_pos(),
 | 
| +        Symbols::IndexToken(),
 | 
| +        Token::kINDEX,
 | 
| +        arguments,
 | 
| +        Object::null_array(),
 | 
| +        checked_argument_count,
 | 
| +        owner()->ic_data_array());
 | 
|      ReturnDefinition(load);
 | 
|    }
 | 
|  }
 | 
| @@ -3617,10 +3610,10 @@
 | 
|  
 | 
|      StaticCallInstr* store =
 | 
|          new(I) StaticCallInstr(node->token_pos(),
 | 
| -                            *super_function,
 | 
| -                            Object::null_array(),
 | 
| -                            arguments,
 | 
| -                            owner()->ic_data_array());
 | 
| +                               *super_function,
 | 
| +                               Object::null_array(),
 | 
| +                               arguments,
 | 
| +                               owner()->ic_data_array());
 | 
|      if (result_is_needed) {
 | 
|        Do(store);
 | 
|        return BuildLoadExprTemp();
 | 
| @@ -3634,12 +3627,12 @@
 | 
|          String::ZoneHandle(I, Symbols::New(Token::Str(Token::kASSIGN_INDEX)));
 | 
|      InstanceCallInstr* store =
 | 
|          new(I) InstanceCallInstr(node->token_pos(),
 | 
| -                              name,
 | 
| -                              Token::kASSIGN_INDEX,
 | 
| -                              arguments,
 | 
| -                              Object::null_array(),
 | 
| -                              checked_argument_count,
 | 
| -                              owner()->ic_data_array());
 | 
| +                                 name,
 | 
| +                                 Token::kASSIGN_INDEX,
 | 
| +                                 arguments,
 | 
| +                                 Object::null_array(),
 | 
| +                                 checked_argument_count,
 | 
| +                                 owner()->ic_data_array());
 | 
|      if (result_is_needed) {
 | 
|        Do(store);
 | 
|        return BuildLoadExprTemp();
 | 
| @@ -3668,7 +3661,7 @@
 | 
|  
 | 
|  void EffectGraphVisitor::UnchainContexts(intptr_t n) {
 | 
|    if (n > 0) {
 | 
| -    Value* context = Bind(new(I) CurrentContextInstr());
 | 
| +    Value* context = Bind(BuildCurrentContext());
 | 
|      while (n-- > 0) {
 | 
|        context = Bind(
 | 
|            new(I) LoadFieldInstr(context,
 | 
| @@ -3677,7 +3670,7 @@
 | 
|                                  Type::ZoneHandle(I, Type::null()),
 | 
|                                  Scanner::kNoSourcePos));
 | 
|      }
 | 
| -    AddInstruction(new(I) StoreContextInstr(context));
 | 
| +    Do(BuildStoreContext(context));
 | 
|    }
 | 
|  }
 | 
|  
 | 
| @@ -3697,7 +3690,7 @@
 | 
|    if (num_context_variables > 0) {
 | 
|      // The loop local scope declares variables that are captured.
 | 
|      // Allocate and chain a new context.
 | 
| -    // Allocate context computation (uses current CTX)
 | 
| +    // Allocate context computation (uses current context)
 | 
|      Value* allocated_context =
 | 
|          Bind(new(I) AllocateContextInstr(node->token_pos(),
 | 
|                                           num_context_variables));
 | 
| @@ -3716,15 +3709,14 @@
 | 
|          parent_context = Bind(
 | 
|              new(I) ConstantInstr(Object::ZoneHandle(I, Object::null())));
 | 
|        } else {
 | 
| -        parent_context = Bind(new(I) CurrentContextInstr());
 | 
| +        parent_context = Bind(BuildCurrentContext());
 | 
|        }
 | 
|        Do(new(I) StoreInstanceFieldInstr(Context::parent_offset(),
 | 
|                                          tmp_val,
 | 
|                                          parent_context,
 | 
|                                          kEmitStoreBarrier,
 | 
|                                          Scanner::kNoSourcePos));
 | 
| -      AddInstruction(
 | 
| -          new(I) StoreContextInstr(Bind(ExitTempLocalScope(tmp_var))));
 | 
| +      Do(BuildStoreContext(Bind(ExitTempLocalScope(tmp_var))));
 | 
|      }
 | 
|  
 | 
|      // If this node_sequence is the body of the function being compiled, copy
 | 
| @@ -3772,9 +3764,8 @@
 | 
|      // object.
 | 
|      BuildSaveContext(
 | 
|          *owner()->parsed_function()->saved_entry_context_var());
 | 
| -    AddInstruction(
 | 
| -        new(I) StoreContextInstr(Bind(new(I) ConstantInstr(Object::ZoneHandle(
 | 
| -            I, I->object_store()->empty_context())))));
 | 
| +    Do(BuildStoreContext(Bind(new(I) ConstantInstr(Object::ZoneHandle(
 | 
| +        I, I->object_store()->empty_context())))));
 | 
|    }
 | 
|  
 | 
|    // This check may be deleted if the generated code is leaf.
 | 
| @@ -3943,7 +3934,7 @@
 | 
|  
 | 
|  void EffectGraphVisitor::VisitCatchClauseNode(CatchClauseNode* node) {
 | 
|    InlineBailout("EffectGraphVisitor::VisitCatchClauseNode (exception)");
 | 
| -  // Restores CTX from local variable ':saved_context'.
 | 
| +  // Restores current context from local variable ':saved_context'.
 | 
|    BuildRestoreContext(node->context_var());
 | 
|  
 | 
|    EffectGraphVisitor for_catch(owner());
 | 
| @@ -3959,7 +3950,7 @@
 | 
|    ASSERT(try_handler_index != original_handler_index);
 | 
|    owner()->set_try_index(try_handler_index);
 | 
|  
 | 
| -  // Preserve CTX into local variable '%saved_context'.
 | 
| +  // Preserve current context into local variable '%saved_context'.
 | 
|    BuildSaveContext(node->context_var());
 | 
|  
 | 
|    EffectGraphVisitor for_try(owner());
 | 
| 
 |