// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#include "vm/flow_graph_builder.h"

#include "lib/invocation_mirror.h"
#include "vm/ast_printer.h"
#include "vm/bit_vector.h"
#include "vm/compiler.h"
#include "vm/class_finalizer.h"
#include "vm/exceptions.h"
#include "vm/flags.h"
#include "vm/flow_graph.h"
#include "vm/flow_graph_compiler.h"
#include "vm/heap.h"
#include "vm/il_printer.h"
#include "vm/intermediate_language.h"
#include "vm/isolate.h"
#include "vm/object.h"
#include "vm/object_store.h"
#include "vm/os.h"
#include "vm/parser.h"
#include "vm/report.h"
#include "vm/resolver.h"
#include "vm/scopes.h"
#include "vm/stack_frame.h"
#include "vm/stub_code.h"
#include "vm/symbols.h"
#include "vm/token.h"
#include "vm/zone.h"

namespace dart {

DEFINE_FLAG(bool,
            eliminate_type_checks,
            true,
            "Eliminate type checks when allowed by static type analysis.");
DEFINE_FLAG(bool, print_ast, false, "Print abstract syntax tree.");
DEFINE_FLAG(bool, print_scopes, false, "Print scopes of local variables.");
DEFINE_FLAG(bool,
            trace_type_check_elimination,
            false,
            "Trace type check elimination at compile time.");

DECLARE_FLAG(bool, profile_vm);
DECLARE_FLAG(bool, support_externalizable_strings);

// Quick access to the locally defined zone() method.
#define Z (zone())

// Quick access to the locally defined thread() method.
#define T (thread())

// Quick synthetic token position.
#define ST(token_pos) ((token_pos).ToSynthetic())

// TODO(srdjan): Allow compiler to add constants as they are encountered in
// the compilation.
const double kCommonDoubleConstants[] = {
    -1.0, -0.5, -0.1, 0.0, 0.1, 0.5, 1.0, 2.0, 4.0, 5.0, 10.0, 20.0, 30.0, 64.0,
    255.0, NAN,
    // From dart:math
    2.718281828459045, 2.302585092994046, 0.6931471805599453,
    1.4426950408889634, 0.4342944819032518, 3.1415926535897932,
    0.7071067811865476, 1.4142135623730951};

uword FlowGraphBuilder::FindDoubleConstant(double value) {
  intptr_t len = sizeof(kCommonDoubleConstants) / sizeof(double);  // NOLINT
  for (intptr_t i = 0; i < len; i++) {
    if (Utils::DoublesBitEqual(value, kCommonDoubleConstants[i])) {
      return reinterpret_cast<uword>(&kCommonDoubleConstants[i]);
    }
  }
  return 0;
}


#define RECOGNIZE_FACTORY(symbol, class_name, constructor_name, cid, fp)       \
  {Symbols::k##symbol##Id, cid, fp, #symbol ", " #cid},  // NOLINT

static struct {
  intptr_t symbol_id;
  intptr_t cid;
  intptr_t finger_print;
  const char* name;
} factory_recognizer_list[] = {RECOGNIZED_LIST_FACTORY_LIST(RECOGNIZE_FACTORY){
    Symbols::kIllegal, -1, -1, NULL}};

#undef RECOGNIZE_FACTORY

intptr_t FactoryRecognizer::ResultCid(const Function& factory) {
  ASSERT(factory.IsFactory());
  const Class& function_class = Class::Handle(factory.Owner());
  const Library& lib = Library::Handle(function_class.library());
  ASSERT((lib.raw() == Library::CoreLibrary()) ||
         (lib.raw() == Library::TypedDataLibrary()));
  const String& factory_name = String::Handle(factory.name());
  for (intptr_t i = 0;
       factory_recognizer_list[i].symbol_id != Symbols::kIllegal; i++) {
    if (String::EqualsIgnoringPrivateKey(
            factory_name,
            Symbols::Symbol(factory_recognizer_list[i].symbol_id))) {
      return factory_recognizer_list[i].cid;
    }
  }
  return kDynamicCid;
}


// Base class for a stack of enclosing statements of interest (e.g.,
// blocks (breakable) and loops (continuable)).
class NestedStatement : public ValueObject {
 public:
  FlowGraphBuilder* owner() const { return owner_; }
  const SourceLabel* label() const { return label_; }
  NestedStatement* outer() const { return outer_; }
  JoinEntryInstr* break_target() const { return break_target_; }

  virtual intptr_t ContextLevel() const;
  virtual void AdjustContextLevel(intptr_t context_level);

  virtual JoinEntryInstr* BreakTargetFor(SourceLabel* label);
  virtual JoinEntryInstr* ContinueTargetFor(SourceLabel* label);

 protected:
  NestedStatement(FlowGraphBuilder* owner, const SourceLabel* label)
      : owner_(owner),
        label_(label),
        outer_(owner->nesting_stack_),
        break_target_(NULL),
        try_index_(owner->try_index()) {
    // Push on the owner's nesting stack.
    owner->nesting_stack_ = this;
  }

  intptr_t try_index() const { return try_index_; }

  virtual ~NestedStatement() {
    // Pop from the owner's nesting stack.
    ASSERT(owner_->nesting_stack_ == this);
    owner_->nesting_stack_ = outer_;
  }

 private:
  FlowGraphBuilder* owner_;
  const SourceLabel* label_;
  NestedStatement* outer_;

  JoinEntryInstr* break_target_;
  const intptr_t try_index_;
};


intptr_t NestedStatement::ContextLevel() const {
  // Context level is determined by the innermost nested statement having one.
  return (outer() == NULL) ? 0 : outer()->ContextLevel();
}


void NestedStatement::AdjustContextLevel(intptr_t context_level) {
  // There must be a NestedContextAdjustment on the nesting stack.
  ASSERT(outer() != NULL);
  outer()->AdjustContextLevel(context_level);
}


intptr_t FlowGraphBuilder::context_level() const {
  return (nesting_stack() == NULL) ? 0 : nesting_stack()->ContextLevel();
}


JoinEntryInstr* NestedStatement::BreakTargetFor(SourceLabel* label) {
  if (label != label_) return NULL;
  if (break_target_ == NULL) {
    break_target_ = new (owner()->zone())
        JoinEntryInstr(owner()->AllocateBlockId(), try_index());
  }
  return break_target_;
}


JoinEntryInstr* NestedStatement::ContinueTargetFor(SourceLabel* label) {
  return NULL;
}


// A nested statement that has its own context level.
class NestedBlock : public NestedStatement {
 public:
  NestedBlock(FlowGraphBuilder* owner, SequenceNode* node)
      : NestedStatement(owner, node->label()), scope_(node->scope()) {}

  virtual intptr_t ContextLevel() const;

 private:
  LocalScope* scope_;
};


intptr_t NestedBlock::ContextLevel() const {
  return ((scope_ == NULL) || (scope_->num_context_variables() == 0))
             ? NestedStatement::ContextLevel()
             : scope_->context_level();
}


// A nested statement reflecting a context level adjustment.
class NestedContextAdjustment : public NestedStatement {
 public:
  NestedContextAdjustment(FlowGraphBuilder* owner, intptr_t context_level)
      : NestedStatement(owner, NULL), context_level_(context_level) {}

  virtual intptr_t ContextLevel() const { return context_level_; }

  virtual void AdjustContextLevel(intptr_t context_level) {
    ASSERT(context_level <= context_level_);
    context_level_ = context_level;
  }

 private:
  intptr_t context_level_;
};


// A nested statement that can be the target of a continue as well as a
// break.
class NestedLoop : public NestedStatement {
 public:
  NestedLoop(FlowGraphBuilder* owner, SourceLabel* label)
      : NestedStatement(owner, label), continue_target_(NULL) {
    owner->IncrementLoopDepth();
  }

  virtual ~NestedLoop() { owner()->DecrementLoopDepth(); }

  JoinEntryInstr* continue_target() const { return continue_target_; }

  virtual JoinEntryInstr* ContinueTargetFor(SourceLabel* label);

 private:
  JoinEntryInstr* continue_target_;
};


JoinEntryInstr* NestedLoop::ContinueTargetFor(SourceLabel* label) {
  if (label != this->label()) return NULL;
  if (continue_target_ == NULL) {
    continue_target_ = new (owner()->zone())
        JoinEntryInstr(owner()->AllocateBlockId(), try_index());
  }
  return continue_target_;
}


// A nested switch which can be the target of a break if labeled, and whose
// cases can be the targets of continues.
class NestedSwitch : public NestedStatement {
 public:
  NestedSwitch(FlowGraphBuilder* owner, SwitchNode* node);

  virtual JoinEntryInstr* ContinueTargetFor(SourceLabel* label);

 private:
  GrowableArray<SourceLabel*> case_labels_;
  GrowableArray<JoinEntryInstr*> case_targets_;
};


NestedSwitch::NestedSwitch(FlowGraphBuilder* owner, SwitchNode* node)
    : NestedStatement(owner, node->label()),
      case_labels_(node->body()->length()),
      case_targets_(node->body()->length()) {
  SequenceNode* body = node->body();
  for (intptr_t i = 0; i < body->length(); ++i) {
    CaseNode* case_node = body->NodeAt(i)->AsCaseNode();
    if (case_node != NULL) {
      case_labels_.Add(case_node->label());
      case_targets_.Add(NULL);
    }
  }
}


JoinEntryInstr* NestedSwitch::ContinueTargetFor(SourceLabel* label) {
  // Allocate a join for a case clause that matches the label.  This block
  // is not necessarily targeted by a continue, but we always use a join in
  // the graph anyway.
  for (intptr_t i = 0; i < case_labels_.length(); ++i) {
    if (label != case_labels_[i]) continue;
    if (case_targets_[i] == NULL) {
      case_targets_[i] = new (owner()->zone())
          JoinEntryInstr(owner()->AllocateBlockId(), try_index());
    }
    return case_targets_[i];
  }
  return NULL;
}


FlowGraphBuilder::FlowGraphBuilder(
    const ParsedFunction& parsed_function,
    const ZoneGrowableArray<const ICData*>& ic_data_array,
    InlineExitCollector* exit_collector,
    intptr_t osr_id)
    : parsed_function_(parsed_function),
      ic_data_array_(ic_data_array),
      num_copied_params_(parsed_function.num_copied_params()),
      // All parameters are copied if any parameter is.
      num_non_copied_params_(
          (num_copied_params_ == 0)
              ? parsed_function.function().num_fixed_parameters()
              : 0),
      num_stack_locals_(parsed_function.num_stack_locals()),
      exit_collector_(exit_collector),
      last_used_block_id_(0),  // 0 is used for the graph entry.
      try_index_(CatchClauseNode::kInvalidTryIndex),
      catch_try_index_(CatchClauseNode::kInvalidTryIndex),
      loop_depth_(0),
      graph_entry_(NULL),
      temp_count_(0),
      args_pushed_(0),
      nesting_stack_(NULL),
      osr_id_(osr_id),
      jump_count_(0),
      await_joins_(new (Z) ZoneGrowableArray<JoinEntryInstr*>()),
      await_token_positions_(new (Z) ZoneGrowableArray<TokenPosition>()) {}


void FlowGraphBuilder::AddCatchEntry(CatchBlockEntryInstr* entry) {
  graph_entry_->AddCatchEntry(entry);
}


void InlineExitCollector::PrepareGraphs(FlowGraph* callee_graph) {
  ASSERT(callee_graph->graph_entry()->SuccessorCount() == 1);
  ASSERT(callee_graph->max_block_id() > caller_graph_->max_block_id());
  ASSERT(callee_graph->max_virtual_register_number() >
         caller_graph_->max_virtual_register_number());

  // Adjust the caller's maximum block id and current SSA temp index.
  caller_graph_->set_max_block_id(callee_graph->max_block_id());
  caller_graph_->set_current_ssa_temp_index(
      callee_graph->max_virtual_register_number());

  // Attach the outer environment on each instruction in the callee graph.
  ASSERT(call_->env() != NULL);
  // Scale the edge weights by the call count for the inlined function.
  double scale_factor =
      static_cast<double>(call_->CallCount()) /
      static_cast<double>(caller_graph_->graph_entry()->entry_count());
  for (BlockIterator block_it = callee_graph->postorder_iterator();
       !block_it.Done(); block_it.Advance()) {
    BlockEntryInstr* block = block_it.Current();
    if (block->IsTargetEntry()) {
      block->AsTargetEntry()->adjust_edge_weight(scale_factor);
    }
    Instruction* instr = block;
    if (block->env() != NULL) {
      call_->env()->DeepCopyToOuter(callee_graph->zone(), block);
    }
    for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
      instr = it.Current();
      // TODO(zerny): Avoid creating unnecessary environments. Note that some
      // optimizations need deoptimization info for non-deoptable instructions,
      // eg, LICM on GOTOs.
      if (instr->env() != NULL) {
        call_->env()->DeepCopyToOuter(callee_graph->zone(), instr);
      }
    }
    if (instr->IsGoto()) {
      instr->AsGoto()->adjust_edge_weight(scale_factor);
    }
  }

  RemoveUnreachableExits(callee_graph);
}


void InlineExitCollector::AddExit(ReturnInstr* exit) {
  Data data = {NULL, exit};
  exits_.Add(data);
}


void InlineExitCollector::Union(const InlineExitCollector* other) {
  // It doesn't make sense to combine different calls or calls from
  // different graphs.
  ASSERT(caller_graph_ == other->caller_graph_);
  ASSERT(call_ == other->call_);
  exits_.AddArray(other->exits_);
}


int InlineExitCollector::LowestBlockIdFirst(const Data* a, const Data* b) {
  return (a->exit_block->block_id() - b->exit_block->block_id());
}


void InlineExitCollector::RemoveUnreachableExits(FlowGraph* callee_graph) {
  const GrowableArray<BlockEntryInstr*>& postorder = callee_graph->postorder();
  int j = 0;
  for (int i = 0; i < exits_.length(); ++i) {
    BlockEntryInstr* block = exits_[i].exit_return->GetBlock();
    if ((block != NULL) && (0 <= block->postorder_number()) &&
        (block->postorder_number() < postorder.length()) &&
        (postorder[block->postorder_number()] == block)) {
      if (i != j) {
        exits_[j] = exits_[i];
      }
      j++;
    }
  }
  exits_.TruncateTo(j);
}


void InlineExitCollector::SortExits() {
  // Assign block entries here because we did not necessarily know them when
  // the return exit was added to the array.
  for (int i = 0; i < exits_.length(); ++i) {
    exits_[i].exit_block = exits_[i].exit_return->GetBlock();
  }
  exits_.Sort(LowestBlockIdFirst);
}


Definition* InlineExitCollector::JoinReturns(BlockEntryInstr** exit_block,
                                             Instruction** last_instruction,
                                             intptr_t try_index) {
  // First sort the list of exits by block id (caching return instruction
  // block entries as a side effect).
  SortExits();
  intptr_t num_exits = exits_.length();
  if (num_exits == 1) {
    ReturnAt(0)->UnuseAllInputs();
    *exit_block = ExitBlockAt(0);
    *last_instruction = LastInstructionAt(0);
    return call_->HasUses() ? ValueAt(0)->definition() : NULL;
  } else {
    ASSERT(num_exits > 1);
    // Create a join of the returns.
    intptr_t join_id = caller_graph_->max_block_id() + 1;
    caller_graph_->set_max_block_id(join_id);
    JoinEntryInstr* join = new (Z) JoinEntryInstr(join_id, try_index);

    // The dominator set of the join is the intersection of the dominator
    // sets of all the predecessors.  If we keep the dominator sets ordered
    // by height in the dominator tree, we can also get the immediate
    // dominator of the join node from the intersection.
    //
    // block_dominators is the dominator set for each block, ordered from
    // the immediate dominator to the root of the dominator tree.  This is
    // the order we collect them in (adding at the end).
    //
    // join_dominators is the join's dominators ordered from the root of the
    // dominator tree to the immediate dominator.  This order supports
    // removing during intersection by truncating the list.
    GrowableArray<BlockEntryInstr*> block_dominators;
    GrowableArray<BlockEntryInstr*> join_dominators;
    for (intptr_t i = 0; i < num_exits; ++i) {
      // Add the control-flow edge.
      GotoInstr* goto_instr = new (Z) GotoInstr(join);
      goto_instr->InheritDeoptTarget(zone(), ReturnAt(i));
      LastInstructionAt(i)->LinkTo(goto_instr);
      ExitBlockAt(i)->set_last_instruction(LastInstructionAt(i)->next());
      join->predecessors_.Add(ExitBlockAt(i));

      // Collect the block's dominators.
      block_dominators.Clear();
      BlockEntryInstr* dominator = ExitBlockAt(i)->dominator();
      while (dominator != NULL) {
        block_dominators.Add(dominator);
        dominator = dominator->dominator();
      }

      if (i == 0) {
        // The initial dominator set is the first predecessor's dominator
        // set.  Reverse it.
        for (intptr_t j = block_dominators.length() - 1; j >= 0; --j) {
          join_dominators.Add(block_dominators[j]);
        }
      } else {
        // Intersect the block's dominators with the join's dominators so far.
        intptr_t last = block_dominators.length() - 1;
        for (intptr_t j = 0; j < join_dominators.length(); ++j) {
          intptr_t k = last - j;  // Corresponding index in block_dominators.
          if ((k < 0) || (join_dominators[j] != block_dominators[k])) {
            // We either exhausted the dominators for this block before
            // exhausting the current intersection, or else we found a block
            // on the path from the root of the tree that is not in common.
            // I.e., there cannot be an empty set of dominators.
            ASSERT(j > 0);
            join_dominators.TruncateTo(j);
            break;
          }
        }
      }
    }
    // The immediate dominator of the join is the last one in the ordered
    // intersection.
    join_dominators.Last()->AddDominatedBlock(join);
    *exit_block = join;
    *last_instruction = join;

    // If the call has uses, create a phi of the returns.
    if (call_->HasUses()) {
      // Add a phi of the return values.
      PhiInstr* phi = new (Z) PhiInstr(join, num_exits);
      caller_graph_->AllocateSSAIndexes(phi);
      phi->mark_alive();
      for (intptr_t i = 0; i < num_exits; ++i) {
        ReturnAt(i)->RemoveEnvironment();
        phi->SetInputAt(i, ValueAt(i));
      }
      join->InsertPhi(phi);
      join->InheritDeoptTargetAfter(caller_graph_, call_, phi);
      return phi;
    } else {
      // In the case that the result is unused, remove the return value uses
      // from their definition's use list.
      for (intptr_t i = 0; i < num_exits; ++i) {
        ReturnAt(i)->UnuseAllInputs();
      }
      join->InheritDeoptTargetAfter(caller_graph_, call_, NULL);
      return NULL;
    }
  }
}


void InlineExitCollector::ReplaceCall(TargetEntryInstr* callee_entry) {
  ASSERT(call_->previous() != NULL);
  ASSERT(call_->next() != NULL);
  BlockEntryInstr* call_block = call_->GetBlock();

  // Insert the callee graph into the caller graph.
  BlockEntryInstr* callee_exit = NULL;
  Instruction* callee_last_instruction = NULL;

  if (exits_.length() == 0) {
    // Handle the case when there are no normal return exits from the callee
    // (i.e. the callee unconditionally throws) by inserting an artificial
    // branch (true === true).
    // The true successor is the inlined body, the false successor
    // goes to the rest of the caller graph. It is removed as unreachable code
    // by the constant propagation.
    TargetEntryInstr* false_block = new (Z) TargetEntryInstr(
        caller_graph_->allocate_block_id(), call_block->try_index());
    false_block->InheritDeoptTargetAfter(caller_graph_, call_, NULL);
    false_block->LinkTo(call_->next());
    call_block->ReplaceAsPredecessorWith(false_block);

    ConstantInstr* true_const = caller_graph_->GetConstant(Bool::True());
    BranchInstr* branch = new (Z) BranchInstr(new (Z) StrictCompareInstr(
        TokenPosition::kNoSource, Token::kEQ_STRICT, new (Z) Value(true_const),
        new (Z) Value(true_const),
        false));  // No number check.
    branch->InheritDeoptTarget(zone(), call_);
    *branch->true_successor_address() = callee_entry;
    *branch->false_successor_address() = false_block;

    call_->previous()->AppendInstruction(branch);
    call_block->set_last_instruction(branch);

    // Replace uses of the return value with null to maintain valid
    // SSA form - even though the rest of the caller is unreachable.
    call_->ReplaceUsesWith(caller_graph_->constant_null());

    // Update dominator tree.
    call_block->AddDominatedBlock(callee_entry);
    call_block->AddDominatedBlock(false_block);

  } else {
    Definition* callee_result = JoinReturns(
        &callee_exit, &callee_last_instruction, call_block->try_index());
    if (callee_result != NULL) {
      call_->ReplaceUsesWith(callee_result);
    }
    if (callee_last_instruction == callee_entry) {
      // There are no instructions in the inlined function (e.g., it might be
      // a return of a parameter or a return of a constant defined in the
      // initial definitions).
      call_->previous()->LinkTo(call_->next());
    } else {
      call_->previous()->LinkTo(callee_entry->next());
      callee_last_instruction->LinkTo(call_->next());
    }
    if (callee_exit != callee_entry) {
      // In case of control flow, locally update the predecessors, phis and
      // dominator tree.
      //
      // Pictorially, the graph structure is:
      //
      //   Bc : call_block      Bi : callee_entry
      //     before_call          inlined_head
      //     call               ... other blocks ...
      //     after_call         Be : callee_exit
      //                          inlined_foot
      // And becomes:
      //
      //   Bc : call_block
      //     before_call
      //     inlined_head
      //   ... other blocks ...
      //   Be : callee_exit
      //    inlined_foot
      //    after_call
      //
      // For successors of 'after_call', the call block (Bc) is replaced as a
      // predecessor by the callee exit (Be).
      call_block->ReplaceAsPredecessorWith(callee_exit);
      // For successors of 'inlined_head', the callee entry (Bi) is replaced
      // as a predecessor by the call block (Bc).
      callee_entry->ReplaceAsPredecessorWith(call_block);

      // The callee exit is now the immediate dominator of blocks whose
      // immediate dominator was the call block.
      ASSERT(callee_exit->dominated_blocks().is_empty());
      for (intptr_t i = 0; i < call_block->dominated_blocks().length(); ++i) {
        BlockEntryInstr* block = call_block->dominated_blocks()[i];
        callee_exit->AddDominatedBlock(block);
      }
      // The call block is now the immediate dominator of blocks whose
      // immediate dominator was the callee entry.
      call_block->ClearDominatedBlocks();
      for (intptr_t i = 0; i < callee_entry->dominated_blocks().length(); ++i) {
        BlockEntryInstr* block = callee_entry->dominated_blocks()[i];
        call_block->AddDominatedBlock(block);
      }
    }

    // Callee entry in not in the graph anymore. Remove it from use lists.
    callee_entry->UnuseAllInputs();
  }
  // Neither call nor the graph entry (if present) are in the
  // graph at this point. Remove them from use lists.
  if (callee_entry->PredecessorCount() > 0) {
    callee_entry->PredecessorAt(0)->AsGraphEntry()->UnuseAllInputs();
  }
  call_->UnuseAllInputs();
}


void EffectGraphVisitor::Append(const EffectGraphVisitor& other_fragment) {
  ASSERT(is_open());
  if (other_fragment.is_empty()) return;
  if (is_empty()) {
    entry_ = other_fragment.entry();
  } else {
    exit()->LinkTo(other_fragment.entry());
  }
  exit_ = other_fragment.exit();
}


Value* EffectGraphVisitor::Bind(Definition* definition) {
  ASSERT(is_open());
  owner()->DeallocateTemps(definition->InputCount());
  owner()->add_args_pushed(-definition->ArgumentCount());
  definition->set_temp_index(owner()->AllocateTemp());
  if (is_empty()) {
    entry_ = definition;
  } else {
    exit()->LinkTo(definition);
  }
  exit_ = definition;
  return new (Z) Value(definition);
}


void EffectGraphVisitor::Do(Definition* definition) {
  ASSERT(is_open());
  owner()->DeallocateTemps(definition->InputCount());
  owner()->add_args_pushed(-definition->ArgumentCount());
  if (is_empty()) {
    entry_ = definition;
  } else {
    exit()->LinkTo(definition);
  }
  exit_ = definition;
}


void EffectGraphVisitor::AddInstruction(Instruction* instruction) {
  ASSERT(is_open());
  ASSERT(instruction->IsPushArgument() || !instruction->IsDefinition());
  ASSERT(!instruction->IsBlockEntry());
  owner()->DeallocateTemps(instruction->InputCount());
  owner()->add_args_pushed(-instruction->ArgumentCount());
  if (is_empty()) {
    entry_ = exit_ = instruction;
  } else {
    exit()->LinkTo(instruction);
    exit_ = instruction;
  }
}


void EffectGraphVisitor::AddReturnExit(TokenPosition token_pos, Value* value) {
  ASSERT(is_open());
  ReturnInstr* return_instr = new (Z) ReturnInstr(token_pos, value);
  AddInstruction(return_instr);
  InlineExitCollector* exit_collector = owner()->exit_collector();
  if (exit_collector != NULL) {
    exit_collector->AddExit(return_instr);
  }
  CloseFragment();
}


void EffectGraphVisitor::Goto(JoinEntryInstr* join) {
  ASSERT(is_open());
  if (is_empty()) {
    entry_ = new (Z) GotoInstr(join);
  } else {
    exit()->Goto(join);
  }
  CloseFragment();
}


// Appends a graph fragment to a block entry instruction.  Returns the entry
// instruction if the fragment was empty or else the exit of the fragment if
// it was non-empty (so NULL if the fragment is closed).
//
// Note that the fragment is no longer a valid fragment after calling this
// function -- the fragment is closed at its entry because the entry has a
// predecessor in the graph.
static Instruction* AppendFragment(BlockEntryInstr* entry,
                                   const EffectGraphVisitor& fragment) {
  if (fragment.is_empty()) return entry;
  entry->LinkTo(fragment.entry());
  return fragment.exit();
}


void EffectGraphVisitor::Join(const TestGraphVisitor& test_fragment,
                              const EffectGraphVisitor& true_fragment,
                              const EffectGraphVisitor& false_fragment) {
  // We have: a test graph fragment with zero, one, or two available exits;
  // and a pair of effect graph fragments with zero or one available exits.
  // We want to append the branch and (if necessary) a join node to this
  // graph fragment.
  ASSERT(is_open());

  // 1. Connect the test to this graph.
  Append(test_fragment);

  // 2. Connect the true and false bodies to the test and record their exits
  // (if any).
  BlockEntryInstr* true_entry = test_fragment.CreateTrueSuccessor();
  Instruction* true_exit = AppendFragment(true_entry, true_fragment);

  BlockEntryInstr* false_entry = test_fragment.CreateFalseSuccessor();
  Instruction* false_exit = AppendFragment(false_entry, false_fragment);

  // 3. Add a join or select one (or neither) of the arms as exit.
  if (true_exit == NULL) {
    exit_ = false_exit;  // May be NULL.
  } else if (false_exit == NULL) {
    exit_ = true_exit;
  } else {
    JoinEntryInstr* join = new (Z)
        JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index());
    true_exit->Goto(join);
    false_exit->Goto(join);
    exit_ = join;
  }
}


void EffectGraphVisitor::TieLoop(
    TokenPosition token_pos,
    const TestGraphVisitor& test_fragment,
    const EffectGraphVisitor& body_fragment,
    const EffectGraphVisitor& test_preamble_fragment) {
  // We have: a test graph fragment with zero, one, or two available exits;
  // and an effect graph fragment with zero or one available exits.  We want
  // to append the 'while loop' consisting of the test graph fragment as
  // condition and the effect graph fragment as body.
  ASSERT(is_open());

  // 1. Connect the body to the test if it is reachable, and if so record
  // its exit (if any).
  BlockEntryInstr* body_entry = test_fragment.CreateTrueSuccessor();
  Instruction* body_exit = AppendFragment(body_entry, body_fragment);

  // 2. Connect the test to this graph, including the body if reachable and
  // using a fresh join node if the body is reachable and has an open exit.
  if (body_exit == NULL) {
    Append(test_preamble_fragment);
    Append(test_fragment);
  } else {
    JoinEntryInstr* join = new (Z)
        JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index());
    CheckStackOverflowInstr* check =
        new (Z) CheckStackOverflowInstr(token_pos, owner()->loop_depth());
    join->LinkTo(check);
    if (!test_preamble_fragment.is_empty()) {
      check->LinkTo(test_preamble_fragment.entry());
      test_preamble_fragment.exit()->LinkTo(test_fragment.entry());
    } else {
      check->LinkTo(test_fragment.entry());
    }
    Goto(join);
    body_exit->Goto(join);
  }

  // 3. Set the exit to the graph to be the false successor of the test, a
  // fresh target node
  exit_ = test_fragment.CreateFalseSuccessor();
}


PushArgumentInstr* EffectGraphVisitor::PushArgument(Value* value) {
  owner_->add_args_pushed(1);
  PushArgumentInstr* result = new (Z) PushArgumentInstr(value);
  AddInstruction(result);
  return result;
}


Definition* EffectGraphVisitor::BuildStoreTemp(const LocalVariable& local,
                                               Value* value,
                                               TokenPosition token_pos) {
  ASSERT(!local.is_captured());
  ASSERT(!token_pos.IsClassifying());
  return new (Z) StoreLocalInstr(local, value, ST(token_pos));
}


Definition* EffectGraphVisitor::BuildStoreExprTemp(Value* value,
                                                   TokenPosition token_pos) {
  return BuildStoreTemp(*owner()->parsed_function().expression_temp_var(),
                        value, token_pos);
}


Definition* EffectGraphVisitor::BuildLoadExprTemp(TokenPosition token_pos) {
  ASSERT(!token_pos.IsClassifying());
  return BuildLoadLocal(*owner()->parsed_function().expression_temp_var(),
                        token_pos);
}


Definition* EffectGraphVisitor::BuildStoreLocal(const LocalVariable& local,
                                                Value* value,
                                                TokenPosition token_pos) {
  if (local.is_captured()) {
    LocalVariable* tmp_var = EnterTempLocalScope(value);
    intptr_t delta = owner()->context_level() - local.owner()->context_level();
    ASSERT(delta >= 0);
    Value* context = Bind(BuildCurrentContext(token_pos));
    while (delta-- > 0) {
      context = Bind(new (Z) LoadFieldInstr(context, Context::parent_offset(),
                                            Type::ZoneHandle(Z, Type::null()),
                                            token_pos));
    }
    Value* tmp_val = Bind(new (Z) LoadLocalInstr(*tmp_var, token_pos));
    StoreInstanceFieldInstr* store = new (Z)
        StoreInstanceFieldInstr(Context::variable_offset(local.index()),
                                context, tmp_val, kEmitStoreBarrier, token_pos);
    Do(store);
    return ExitTempLocalScope(value);
  } else {
    return new (Z) StoreLocalInstr(local, value, token_pos);
  }
}


Definition* EffectGraphVisitor::BuildLoadLocal(const LocalVariable& local,
                                               TokenPosition token_pos) {
  if (local.IsConst()) {
    return new (Z) ConstantInstr(*local.ConstValue(), token_pos);
  } else if (local.is_captured()) {
    intptr_t delta = owner()->context_level() - local.owner()->context_level();
    ASSERT(delta >= 0);
    Value* context = Bind(BuildCurrentContext(token_pos));
    while (delta-- > 0) {
      context = Bind(new (Z) LoadFieldInstr(context, Context::parent_offset(),
                                            Type::ZoneHandle(Z, Type::null()),
                                            token_pos));
    }
    LoadFieldInstr* load =
        new (Z) LoadFieldInstr(context, Context::variable_offset(local.index()),
                               local.type(), token_pos);
    load->set_is_immutable(local.is_final());
    return load;
  } else {
    return new (Z) LoadLocalInstr(local, token_pos);
  }
}


// Stores current context into the 'variable'
void EffectGraphVisitor::BuildSaveContext(const LocalVariable& variable,
                                          TokenPosition token_pos) {
  ASSERT(token_pos.IsSynthetic() || token_pos.IsNoSource());
  Value* context = Bind(BuildCurrentContext(token_pos));
  Do(BuildStoreLocal(variable, context, token_pos));
}


// Loads context saved in 'context_variable' into the current context.
void EffectGraphVisitor::BuildRestoreContext(const LocalVariable& variable,
                                             TokenPosition token_pos) {
  Value* load_saved_context = Bind(BuildLoadLocal(variable, token_pos));
  Do(BuildStoreContext(load_saved_context, token_pos));
}


Definition* EffectGraphVisitor::BuildStoreContext(Value* value,
                                                  TokenPosition token_pos) {
  return new (Z) StoreLocalInstr(
      *owner()->parsed_function().current_context_var(), value, token_pos);
}


Definition* EffectGraphVisitor::BuildCurrentContext(TokenPosition token_pos) {
  return new (Z) LoadLocalInstr(
      *owner()->parsed_function().current_context_var(), token_pos);
}


void TestGraphVisitor::ConnectBranchesTo(
    const GrowableArray<TargetEntryInstr**>& branches,
    JoinEntryInstr* join) const {
  ASSERT(!branches.is_empty());
  for (intptr_t i = 0; i < branches.length(); i++) {
    TargetEntryInstr* target = new (Z)
        TargetEntryInstr(owner()->AllocateBlockId(), owner()->try_index());
    *(branches[i]) = target;
    target->Goto(join);
  }
}


void TestGraphVisitor::IfTrueGoto(JoinEntryInstr* join) const {
  ConnectBranchesTo(true_successor_addresses_, join);
}


void TestGraphVisitor::IfFalseGoto(JoinEntryInstr* join) const {
  ConnectBranchesTo(false_successor_addresses_, join);
}


BlockEntryInstr* TestGraphVisitor::CreateSuccessorFor(
    const GrowableArray<TargetEntryInstr**>& branches) const {
  ASSERT(!branches.is_empty());

  if (branches.length() == 1) {
    TargetEntryInstr* target = new (Z)
        TargetEntryInstr(owner()->AllocateBlockId(), owner()->try_index());
    *(branches[0]) = target;
    return target;
  }

  JoinEntryInstr* join =
      new (Z) JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index());
  ConnectBranchesTo(branches, join);
  return join;
}


BlockEntryInstr* TestGraphVisitor::CreateTrueSuccessor() const {
  return CreateSuccessorFor(true_successor_addresses_);
}


BlockEntryInstr* TestGraphVisitor::CreateFalseSuccessor() const {
  return CreateSuccessorFor(false_successor_addresses_);
}


void TestGraphVisitor::ReturnValue(Value* value) {
  Isolate* isolate = Isolate::Current();
  if (isolate->type_checks() || isolate->asserts()) {
    value = Bind(new (Z) AssertBooleanInstr(condition_token_pos(), value));
  }
  Value* constant_true = Bind(new (Z) ConstantInstr(Bool::True()));
  StrictCompareInstr* comp = new (Z) StrictCompareInstr(
      condition_token_pos(), Token::kEQ_STRICT, value, constant_true,
      false);  // No number check.
  BranchInstr* branch = new (Z) BranchInstr(comp);
  AddInstruction(branch);
  CloseFragment();

  true_successor_addresses_.Add(branch->true_successor_address());
  false_successor_addresses_.Add(branch->false_successor_address());
}


void TestGraphVisitor::MergeBranchWithStrictCompare(StrictCompareInstr* comp) {
  BranchInstr* branch = new (Z) BranchInstr(comp);
  AddInstruction(branch);
  CloseFragment();
  true_successor_addresses_.Add(branch->true_successor_address());
  false_successor_addresses_.Add(branch->false_successor_address());
}


void TestGraphVisitor::MergeBranchWithNegate(BooleanNegateInstr* neg) {
  ASSERT(!Isolate::Current()->type_checks());
  Value* constant_true = Bind(new (Z) ConstantInstr(Bool::True()));
  StrictCompareInstr* comp = new (Z) StrictCompareInstr(
      condition_token_pos(), Token::kNE_STRICT, neg->value(), constant_true,
      false);  // No number check.
  BranchInstr* branch = new (Z) BranchInstr(comp);
  AddInstruction(branch);
  CloseFragment();
  true_successor_addresses_.Add(branch->true_successor_address());
  false_successor_addresses_.Add(branch->false_successor_address());
}


void TestGraphVisitor::ReturnDefinition(Definition* definition) {
  StrictCompareInstr* comp = definition->AsStrictCompare();
  if (comp != NULL) {
    MergeBranchWithStrictCompare(comp);
    return;
  }
  if (!Isolate::Current()->type_checks()) {
    BooleanNegateInstr* neg = definition->AsBooleanNegate();
    if (neg != NULL) {
      MergeBranchWithNegate(neg);
      return;
    }
  }
  ReturnValue(Bind(definition));
}


// Special handling for AND/OR.
void TestGraphVisitor::VisitBinaryOpNode(BinaryOpNode* node) {
  // Operators "&&" and "||" cannot be overloaded therefore do not call
  // operator.
  if ((node->kind() == Token::kAND) || (node->kind() == Token::kOR)) {
    TestGraphVisitor for_left(owner(), node->left()->token_pos());
    node->left()->Visit(&for_left);

    TestGraphVisitor for_right(owner(), node->right()->token_pos());
    node->right()->Visit(&for_right);

    Append(for_left);

    if (node->kind() == Token::kAND) {
      AppendFragment(for_left.CreateTrueSuccessor(), for_right);
      true_successor_addresses_.AddArray(for_right.true_successor_addresses_);
      false_successor_addresses_.AddArray(for_left.false_successor_addresses_);
      false_successor_addresses_.AddArray(for_right.false_successor_addresses_);
    } else {
      ASSERT(node->kind() == Token::kOR);
      AppendFragment(for_left.CreateFalseSuccessor(), for_right);
      false_successor_addresses_.AddArray(for_right.false_successor_addresses_);
      true_successor_addresses_.AddArray(for_left.true_successor_addresses_);
      true_successor_addresses_.AddArray(for_right.true_successor_addresses_);
    }
    CloseFragment();
    return;
  }
  ValueGraphVisitor::VisitBinaryOpNode(node);
}


void EffectGraphVisitor::Bailout(const char* reason) const {
  owner()->Bailout(reason);
}


void EffectGraphVisitor::InlineBailout(const char* reason) const {
  owner()->function().set_is_inlinable(false);
  if (owner()->IsInlining()) owner()->Bailout(reason);
}


// <Statement> ::= Return { value:                <Expression>
//                          inlined_finally_list: <InlinedFinally>* }
void EffectGraphVisitor::VisitReturnNode(ReturnNode* node) {
  ValueGraphVisitor for_value(owner());
  node->value()->Visit(&for_value);
  Append(for_value);
  Value* return_value = for_value.value();

  // Call to stub that checks whether the debugger is in single
  // step mode. This call must happen before the contexts are
  // unchained so that captured variables can be inspected.
  // No debugger check is done in native functions or for return
  // statements for which there is no associated source position.
  const Function& function = owner()->function();
  if (FLAG_support_debugger && node->token_pos().IsDebugPause() &&
      !function.is_native()) {
    AddInstruction(new (Z) DebugStepCheckInstr(node->token_pos(),
                                               RawPcDescriptors::kRuntimeCall));
  }

  NestedContextAdjustment context_adjustment(owner(), owner()->context_level());

  if (node->inlined_finally_list_length() > 0) {
    LocalVariable* temp = owner()->parsed_function().finally_return_temp_var();
    ASSERT(temp != NULL);
    Do(BuildStoreLocal(*temp, return_value, node->token_pos()));
    for (intptr_t i = 0; i < node->inlined_finally_list_length(); i++) {
      InlineBailout("EffectGraphVisitor::VisitReturnNode (exception)");
      EffectGraphVisitor for_effect(owner());
      node->InlinedFinallyNodeAt(i)->Visit(&for_effect);
      Append(for_effect);
      if (!is_open()) {
        return;
      }
    }
    return_value = Bind(BuildLoadLocal(*temp, node->token_pos()));
  }

  if (Isolate::Current()->type_checks()) {
    const bool is_implicit_dynamic_getter =
        (!function.is_static() &&
         ((function.kind() == RawFunction::kImplicitGetter) ||
          (function.kind() == RawFunction::kImplicitStaticFinalGetter)));
    // Implicit getters do not need a type check at return, unless they compute
    // the initial value of a static field.
    // The body of a constructor cannot modify the type of the
    // constructed instance, which is passed in as an implicit parameter.
    // However, factories may create an instance of the wrong type.
    if (!is_implicit_dynamic_getter && !function.IsGenerativeConstructor()) {
      const AbstractType& dst_type =
          AbstractType::ZoneHandle(Z, function.result_type());
      return_value =
          BuildAssignableValue(node->value()->token_pos(), return_value,
                               dst_type, Symbols::FunctionResult());
    }
  }

  if (FLAG_causal_async_stacks &&
      (function.IsAsyncClosure() || function.IsAsyncGenClosure())) {
    // We are returning from an asynchronous closure. Before we do that, be
    // sure to clear the thread's asynchronous stack trace.
    const Function& async_clear_thread_stack_trace = Function::ZoneHandle(
        Z, isolate()->object_store()->async_clear_thread_stack_trace());
    ZoneGrowableArray<PushArgumentInstr*>* no_arguments =
        new (Z) ZoneGrowableArray<PushArgumentInstr*>(0);
    StaticCallInstr* call_async_clear_thread_stack_trace = new (Z)
        StaticCallInstr(node->token_pos().ToSynthetic(),
                        async_clear_thread_stack_trace, Object::null_array(),
                        no_arguments, owner()->ic_data_array());
    Do(call_async_clear_thread_stack_trace);
  }

  // Async functions contain two types of return statements:
  // 1) Returns that should complete the completer once all finally blocks have
  //    been inlined (call: :async_completer.complete(return_value)). These
  //    returns end up returning null in the end.
  // 2) "Continuation" returns that should not complete the completer but return
  //    the value.
  //
  // We distinguish those kinds of nodes via is_regular_return().
  //
  if (function.IsAsyncClosure() &&
      (node->return_type() == ReturnNode::kRegular)) {
    // Temporary store the computed return value.
    Do(BuildStoreExprTemp(return_value, node->token_pos()));

    LocalVariable* rcv_var =
        node->scope()->LookupVariable(Symbols::AsyncCompleter(), false);
    ASSERT(rcv_var != NULL && rcv_var->is_captured());
    ZoneGrowableArray<PushArgumentInstr*>* arguments =
        new (Z) ZoneGrowableArray<PushArgumentInstr*>(2);
    Value* rcv_value = Bind(BuildLoadLocal(*rcv_var, node->token_pos()));
    arguments->Add(PushArgument(rcv_value));
    Value* returned_value = Bind(BuildLoadExprTemp(node->token_pos()));
    arguments->Add(PushArgument(returned_value));
    InstanceCallInstr* call = new (Z) InstanceCallInstr(
        node->token_pos(), Symbols::CompleterComplete(), Token::kILLEGAL,
        arguments, Object::null_array(), 1, owner()->ic_data_array());
    Do(call);

    // Rebind the return value for the actual return call to be null.
    return_value = BuildNullValue(node->token_pos());
  }

  intptr_t current_context_level = owner()->context_level();
  ASSERT(current_context_level >= 0);
  if (HasContextScope()) {
    UnchainContexts(current_context_level);
  }

  AddReturnExit(node->token_pos(), return_value);

  if ((function.IsAsyncClosure() || function.IsSyncGenClosure() ||
       function.IsAsyncGenClosure()) &&
      (node->return_type() == ReturnNode::kContinuationTarget)) {
    JoinEntryInstr* const join = new (Z)
        JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index());
    owner()->await_joins()->Add(join);
    exit_ = join;
  }
}


// <Expression> ::= Literal { literal: Instance }
void EffectGraphVisitor::VisitLiteralNode(LiteralNode* node) {
  ReturnDefinition(new (Z) ConstantInstr(node->literal(), node->token_pos()));
}


// Type nodes are used when a type is referenced as a literal. Type nodes
// can also be used for the right-hand side of instanceof comparisons,
// but they are handled specially in that context, not here.
void EffectGraphVisitor::VisitTypeNode(TypeNode* node) {
  return;
}


void ValueGraphVisitor::VisitTypeNode(TypeNode* node) {
  const AbstractType& type = node->type();
  // Type may be malbounded, but not malformed.
  ASSERT(type.IsFinalized() && !type.IsMalformed());
  if (type.IsInstantiated()) {
    ReturnDefinition(new (Z) ConstantInstr(type));
  } else {
    const Class& instantiator_class =
        Class::ZoneHandle(Z, owner()->function().Owner());
    Value* instantiator_value = BuildInstantiatorTypeArguments(
        node->token_pos(), instantiator_class, NULL);
    ReturnDefinition(new (Z) InstantiateTypeInstr(
        node->token_pos(), type, instantiator_class, instantiator_value));
  }
}


// Returns true if the type check can be skipped, for example, if the
// destination type is dynamic or if the compile type of the value is a subtype
// of the destination type.
bool EffectGraphVisitor::CanSkipTypeCheck(TokenPosition token_pos,
                                          Value* value,
                                          const AbstractType& dst_type,
                                          const String& dst_name) {
  ASSERT(!dst_type.IsNull());
  ASSERT(dst_type.IsFinalized());

  // If the destination type is malformed or malbounded, a dynamic type error
  // must be thrown at run time.
  if (dst_type.IsMalformedOrMalbounded()) {
    return false;
  }

  // Any type is more specific than the dynamic type and than the Object type.
  if (dst_type.IsDynamicType() || dst_type.IsObjectType()) {
    return true;
  }

  // Do not perform type check elimination if this optimization is turned off.
  if (!FLAG_eliminate_type_checks) {
    return false;
  }

  // If nothing is known about the value, as is the case for passed-in
  // parameters, and since dst_type is not one of the tested cases above, then
  // the type test cannot be eliminated.
  if (value == NULL) {
    return false;
  }

  const bool eliminated = value->Type()->IsAssignableTo(dst_type);
  if (FLAG_trace_type_check_elimination) {
    FlowGraphPrinter::PrintTypeCheck(owner()->parsed_function(), token_pos,
                                     value, dst_type, dst_name, eliminated);
  }
  return eliminated;
}


// <Expression> :: Assignable { expr:     <Expression>
//                              type:     AbstractType
//                              dst_name: String }
void EffectGraphVisitor::VisitAssignableNode(AssignableNode* node) {
  ValueGraphVisitor for_value(owner());
  node->expr()->Visit(&for_value);
  Append(for_value);
  if (CanSkipTypeCheck(node->expr()->token_pos(), for_value.value(),
                       node->type(), node->dst_name())) {
    ReturnValue(for_value.value());
  } else {
    ReturnDefinition(BuildAssertAssignable(node->expr()->token_pos(),
                                           for_value.value(), node->type(),
                                           node->dst_name()));
  }
}


void ValueGraphVisitor::VisitAssignableNode(AssignableNode* node) {
  ValueGraphVisitor for_value(owner());
  node->expr()->Visit(&for_value);
  Append(for_value);
  ReturnValue(BuildAssignableValue(node->expr()->token_pos(), for_value.value(),
                                   node->type(), node->dst_name()));
}


// <Expression> :: BinaryOp { kind:  Token::Kind
//                            left:  <Expression>
//                            right: <Expression> }
void EffectGraphVisitor::VisitBinaryOpNode(BinaryOpNode* node) {
  // Operators "&&" and "||" cannot be overloaded therefore do not call
  // operator.
  if ((node->kind() == Token::kAND) || (node->kind() == Token::kOR)) {
    // See ValueGraphVisitor::VisitBinaryOpNode.
    TestGraphVisitor for_left(owner(), node->left()->token_pos());
    node->left()->Visit(&for_left);
    EffectGraphVisitor empty(owner());
    Isolate* isolate = Isolate::Current();
    if (isolate->type_checks() || isolate->asserts()) {
      ValueGraphVisitor for_right(owner());
      node->right()->Visit(&for_right);
      Value* right_value = for_right.value();
      for_right.Do(
          new (Z) AssertBooleanInstr(node->right()->token_pos(), right_value));
      if (node->kind() == Token::kAND) {
        Join(for_left, for_right, empty);
      } else {
        Join(for_left, empty, for_right);
      }
    } else {
      EffectGraphVisitor for_right(owner());
      node->right()->Visit(&for_right);
      if (node->kind() == Token::kAND) {
        Join(for_left, for_right, empty);
      } else {
        Join(for_left, empty, for_right);
      }
    }
    return;
  }
  ASSERT(node->kind() != Token::kIFNULL);
  ValueGraphVisitor for_left_value(owner());
  node->left()->Visit(&for_left_value);
  Append(for_left_value);
  PushArgumentInstr* push_left = PushArgument(for_left_value.value());

  ValueGraphVisitor for_right_value(owner());
  node->right()->Visit(&for_right_value);
  Append(for_right_value);
  PushArgumentInstr* push_right = PushArgument(for_right_value.value());

  ZoneGrowableArray<PushArgumentInstr*>* arguments =
      new (Z) ZoneGrowableArray<PushArgumentInstr*>(2);
  arguments->Add(push_left);
  arguments->Add(push_right);
  const String& name = Symbols::Token(node->kind());
  const intptr_t kNumArgsChecked = 2;
  InstanceCallInstr* call = new (Z) InstanceCallInstr(
      node->token_pos(), name, node->kind(), arguments, Object::null_array(),
      kNumArgsChecked, owner()->ic_data_array());
  ReturnDefinition(call);
}


// Special handling for AND/OR.
void ValueGraphVisitor::VisitBinaryOpNode(BinaryOpNode* node) {
  // Operators "&&" and "||" cannot be overloaded therefore do not call
  // operator.
  if ((node->kind() == Token::kAND) || (node->kind() == Token::kOR)) {
    // Implement short-circuit logic: do not evaluate right if evaluation
    // of left is sufficient.
    // AND:  left ? right === true : false;
    // OR:   left ? true : right === true;

    TestGraphVisitor for_test(owner(), node->left()->token_pos());
    node->left()->Visit(&for_test);

    ValueGraphVisitor for_right(owner());
    node->right()->Visit(&for_right);
    Value* right_value = for_right.value();
    Isolate* isolate = Isolate::Current();
    if (isolate->type_checks() || isolate->asserts()) {
      right_value = for_right.Bind(
          new (Z) AssertBooleanInstr(node->right()->token_pos(), right_value));
    }
    Value* constant_true = for_right.Bind(new (Z) ConstantInstr(Bool::True()));
    Value* compare = for_right.Bind(new (Z) StrictCompareInstr(
        node->token_pos(), Token::kEQ_STRICT, right_value, constant_true,
        false));  // No number check.
    for_right.Do(BuildStoreExprTemp(compare, node->token_pos()));

    if (node->kind() == Token::kAND) {
      ValueGraphVisitor for_false(owner());
      Value* constant_false =
          for_false.Bind(new (Z) ConstantInstr(Bool::False()));
      for_false.Do(BuildStoreExprTemp(constant_false, node->token_pos()));
      Join(for_test, for_right, for_false);
    } else {
      ASSERT(node->kind() == Token::kOR);
      ValueGraphVisitor for_true(owner());
      Value* constant_true = for_true.Bind(new (Z) ConstantInstr(Bool::True()));
      for_true.Do(BuildStoreExprTemp(constant_true, node->token_pos()));
      Join(for_test, for_true, for_right);
    }
    ReturnDefinition(BuildLoadExprTemp(node->token_pos()));
    return;
  }

  EffectGraphVisitor::VisitBinaryOpNode(node);
}


void EffectGraphVisitor::BuildTypecheckPushArguments(
    TokenPosition token_pos,
    PushArgumentInstr** push_instantiator_type_arguments_result) {
  const Class& instantiator_class =
      Class::Handle(Z, owner()->function().Owner());
  // Since called only when type tested against is not instantiated.
  ASSERT(instantiator_class.IsGeneric());
  Value* instantiator_type_arguments = NULL;
  Value* instantiator = BuildInstantiator(token_pos);
  if (instantiator == NULL) {
    // No instantiator when inside factory.
    instantiator_type_arguments =
        BuildInstantiatorTypeArguments(token_pos, instantiator_class, NULL);
  } else {
    instantiator_type_arguments = BuildInstantiatorTypeArguments(
        token_pos, instantiator_class, instantiator);
  }
  *push_instantiator_type_arguments_result =
      PushArgument(instantiator_type_arguments);
}


void EffectGraphVisitor::BuildTypecheckArguments(
    TokenPosition token_pos,
    Value** instantiator_type_arguments_result) {
  Value* instantiator = NULL;
  Value* instantiator_type_arguments = NULL;
  const Class& instantiator_class =
      Class::Handle(Z, owner()->function().Owner());
  // Since called only when type tested against is not instantiated.
  ASSERT(instantiator_class.IsGeneric());
  instantiator = BuildInstantiator(token_pos);
  if (instantiator == NULL) {
    // No instantiator when inside factory.
    instantiator_type_arguments =
        BuildInstantiatorTypeArguments(token_pos, instantiator_class, NULL);
  } else {
    instantiator_type_arguments = BuildInstantiatorTypeArguments(
        token_pos, instantiator_class, instantiator);
  }
  *instantiator_type_arguments_result = instantiator_type_arguments;
}


Value* EffectGraphVisitor::BuildNullValue(TokenPosition token_pos) {
  return Bind(
      new (Z) ConstantInstr(Object::ZoneHandle(Z, Object::null()), token_pos));
}


// Used for testing incoming arguments.
AssertAssignableInstr* EffectGraphVisitor::BuildAssertAssignable(
    TokenPosition token_pos,
    Value* value,
    const AbstractType& dst_type,
    const String& dst_name) {
  // Build the type check computation.
  Value* instantiator_type_arguments = NULL;
  if (dst_type.IsInstantiated()) {
    instantiator_type_arguments = BuildNullValue(token_pos);
  } else {
    BuildTypecheckArguments(token_pos, &instantiator_type_arguments);
  }

  const intptr_t deopt_id = Thread::Current()->GetNextDeoptId();
  return new (Z)
      AssertAssignableInstr(token_pos, value, instantiator_type_arguments,
                            dst_type, dst_name, deopt_id);
}


// Used for type casts and to test assignments.
Value* EffectGraphVisitor::BuildAssignableValue(TokenPosition token_pos,
                                                Value* value,
                                                const AbstractType& dst_type,
                                                const String& dst_name) {
  if (CanSkipTypeCheck(token_pos, value, dst_type, dst_name)) {
    return value;
  }
  return Bind(BuildAssertAssignable(token_pos, value, dst_type, dst_name));
}


static bool simpleInstanceOfType(const AbstractType& type) {
  // Bail if the type is still uninstantiated at compile time.
  if (!type.IsInstantiated()) return false;

  // Bail if the type is a function or a Dart Function type.
  if (type.IsFunctionType() || type.IsDartFunctionType()) return false;

  ASSERT(type.HasResolvedTypeClass());
  const Class& type_class = Class::Handle(type.type_class());
  // Bail if the type has any type parameters.
  if (type_class.IsGeneric()) return false;

  // Finally a simple class for instance of checking.
  return true;
}


void EffectGraphVisitor::BuildTypeTest(ComparisonNode* node) {
  ASSERT(Token::IsTypeTestOperator(node->kind()));
  const AbstractType& type = node->right()->AsTypeNode()->type();
  ASSERT(type.IsFinalized() && !type.IsMalformedOrMalbounded());
  const bool negate_result = (node->kind() == Token::kISNOT);
  // All objects are instances of type T if Object type is a subtype of type T.
  const Type& object_type = Type::Handle(Z, Type::ObjectType());
  if (type.IsInstantiated() &&
      object_type.IsSubtypeOf(type, NULL, NULL, Heap::kOld)) {
    // Must evaluate left side.
    EffectGraphVisitor for_left_value(owner());
    node->left()->Visit(&for_left_value);
    Append(for_left_value);
    ReturnDefinition(new (Z) ConstantInstr(Bool::Get(!negate_result)));
    return;
  }
  ValueGraphVisitor for_left_value(owner());
  node->left()->Visit(&for_left_value);
  Append(for_left_value);

  // We now know type is a real class (!num, !int, !smi, !string)
  // and the type check could NOT be removed at compile time.
  PushArgumentInstr* push_left = PushArgument(for_left_value.value());
  if (simpleInstanceOfType(type)) {
    ASSERT(!node->right()->AsTypeNode()->type().IsNull());
    ZoneGrowableArray<PushArgumentInstr*>* arguments =
        new (Z) ZoneGrowableArray<PushArgumentInstr*>(2);
    arguments->Add(push_left);
    Value* type_const = Bind(new (Z) ConstantInstr(type));
    arguments->Add(PushArgument(type_const));
    const intptr_t kNumArgsChecked = 2;
    Definition* result = new (Z) InstanceCallInstr(
        node->token_pos(),
        Library::PrivateCoreLibName(Symbols::_simpleInstanceOf()), node->kind(),
        arguments,
        Object::null_array(),  // No argument names.
        kNumArgsChecked, owner()->ic_data_array());
    if (negate_result) {
      result = new (Z) BooleanNegateInstr(Bind(result));
    }
    ReturnDefinition(result);
    return;
  }

  PushArgumentInstr* push_type_args = NULL;
  if (type.IsInstantiated()) {
    push_type_args = PushArgument(BuildNullValue(node->token_pos()));
  } else {
    BuildTypecheckPushArguments(node->token_pos(), &push_type_args);
  }
  ZoneGrowableArray<PushArgumentInstr*>* arguments =
      new (Z) ZoneGrowableArray<PushArgumentInstr*>(3);
  arguments->Add(push_left);
  arguments->Add(push_type_args);
  ASSERT(!node->right()->AsTypeNode()->type().IsNull());
  Value* type_const = Bind(new (Z) ConstantInstr(type));
  arguments->Add(PushArgument(type_const));
  const intptr_t kNumArgsChecked = 1;
  Definition* result = new (Z) InstanceCallInstr(
      node->token_pos(), Library::PrivateCoreLibName(Symbols::_instanceOf()),
      node->kind(), arguments,
      Object::null_array(),  // No argument names.
      kNumArgsChecked, owner()->ic_data_array());
  if (negate_result) {
    result = new (Z) BooleanNegateInstr(Bind(result));
  }
  ReturnDefinition(result);
}


void EffectGraphVisitor::BuildTypeCast(ComparisonNode* node) {
  ASSERT(Token::IsTypeCastOperator(node->kind()));
  ASSERT(!node->right()->AsTypeNode()->type().IsNull());
  const AbstractType& type = node->right()->AsTypeNode()->type();
  ASSERT(type.IsFinalized() && !type.IsMalformed() && !type.IsMalbounded());
  ValueGraphVisitor for_value(owner());
  node->left()->Visit(&for_value);
  Append(for_value);
  if (CanSkipTypeCheck(node->token_pos(), for_value.value(), type,
                       Symbols::InTypeCast())) {
    ReturnValue(for_value.value());
    return;
  }
  PushArgumentInstr* push_left = PushArgument(for_value.value());
  PushArgumentInstr* push_type_args = NULL;
  if (type.IsInstantiated()) {
    push_type_args = PushArgument(BuildNullValue(node->token_pos()));
  } else {
    BuildTypecheckPushArguments(node->token_pos(), &push_type_args);
  }
  ZoneGrowableArray<PushArgumentInstr*>* arguments =
      new (Z) ZoneGrowableArray<PushArgumentInstr*>(3);
  arguments->Add(push_left);
  arguments->Add(push_type_args);
  Value* type_arg = Bind(new (Z) ConstantInstr(type));
  arguments->Add(PushArgument(type_arg));
  const intptr_t kNumArgsChecked = 1;
  InstanceCallInstr* call = new (Z) InstanceCallInstr(
      node->token_pos(), Library::PrivateCoreLibName(Symbols::_as()),
      node->kind(), arguments,
      Object::null_array(),  // No argument names.
      kNumArgsChecked, owner()->ic_data_array());
  ReturnDefinition(call);
}


StrictCompareInstr* EffectGraphVisitor::BuildStrictCompare(
    AstNode* left,
    AstNode* right,
    Token::Kind kind,
    TokenPosition token_pos) {
  ValueGraphVisitor for_left_value(owner());
  left->Visit(&for_left_value);
  Append(for_left_value);
  ValueGraphVisitor for_right_value(owner());
  right->Visit(&for_right_value);
  Append(for_right_value);
  StrictCompareInstr* comp = new (Z) StrictCompareInstr(
      token_pos, kind, for_left_value.value(), for_right_value.value(),
      true);  // Number check.
  return comp;
}


// <Expression> :: Comparison { kind:  Token::Kind
//                              left:  <Expression>
//                              right: <Expression> }
void EffectGraphVisitor::VisitComparisonNode(ComparisonNode* node) {
  if (Token::IsTypeTestOperator(node->kind())) {
    BuildTypeTest(node);
    return;
  }
  if (Token::IsTypeCastOperator(node->kind())) {
    BuildTypeCast(node);
    return;
  }

  if ((node->kind() == Token::kEQ_STRICT) ||
      (node->kind() == Token::kNE_STRICT)) {
    ReturnDefinition(BuildStrictCompare(node->left(), node->right(),
                                        node->kind(), node->token_pos()));
    return;
  }

  if ((node->kind() == Token::kEQ) || (node->kind() == Token::kNE)) {
    // Eagerly fold null-comparisons.
    LiteralNode* left_lit = node->left()->AsLiteralNode();
    LiteralNode* right_lit = node->right()->AsLiteralNode();
    if (((left_lit != NULL) && left_lit->literal().IsNull()) ||
        ((right_lit != NULL) && right_lit->literal().IsNull())) {
      Token::Kind kind =
          (node->kind() == Token::kEQ) ? Token::kEQ_STRICT : Token::kNE_STRICT;
      StrictCompareInstr* compare = BuildStrictCompare(
          node->left(), node->right(), kind, node->token_pos());
      ReturnDefinition(compare);
      return;
    }

    ZoneGrowableArray<PushArgumentInstr*>* arguments =
        new (Z) ZoneGrowableArray<PushArgumentInstr*>(2);

    ValueGraphVisitor for_left_value(owner());
    node->left()->Visit(&for_left_value);
    Append(for_left_value);
    PushArgumentInstr* push_left = PushArgument(for_left_value.value());
    arguments->Add(push_left);

    ValueGraphVisitor for_right_value(owner());
    node->right()->Visit(&for_right_value);
    Append(for_right_value);
    PushArgumentInstr* push_right = PushArgument(for_right_value.value());
    arguments->Add(push_right);

    const intptr_t kNumArgsChecked = 2;
    Definition* result = new (Z)
        InstanceCallInstr(node->token_pos(), Symbols::EqualOperator(),
                          Token::kEQ,  // Result is negated later for kNE.
                          arguments, Object::null_array(), kNumArgsChecked,
                          owner()->ic_data_array());
    if (node->kind() == Token::kNE) {
      Isolate* isolate = Isolate::Current();
      if (isolate->type_checks() || isolate->asserts()) {
        Value* value = Bind(result);
        result = new (Z) AssertBooleanInstr(node->token_pos(), value);
      }
      Value* value = Bind(result);
      result = new (Z) BooleanNegateInstr(value);
    }
    ReturnDefinition(result);
    return;
  }

  ZoneGrowableArray<PushArgumentInstr*>* arguments =
      new (Z) ZoneGrowableArray<PushArgumentInstr*>(2);

  ValueGraphVisitor for_left_value(owner());
  node->left()->Visit(&for_left_value);
  Append(for_left_value);
  PushArgumentInstr* push_left = PushArgument(for_left_value.value());
  arguments->Add(push_left);

  ValueGraphVisitor for_right_value(owner());
  node->right()->Visit(&for_right_value);
  Append(for_right_value);
  PushArgumentInstr* push_right = PushArgument(for_right_value.value());
  arguments->Add(push_right);

  ASSERT(Token::IsRelationalOperator(node->kind()));
  InstanceCallInstr* comp = new (Z) InstanceCallInstr(
      node->token_pos(), Symbols::Token(node->kind()), node->kind(), arguments,
      Object::null_array(), 2, owner()->ic_data_array());
  ReturnDefinition(comp);
}


void EffectGraphVisitor::VisitUnaryOpNode(UnaryOpNode* node) {
  // "!" cannot be overloaded, therefore do not call operator.
  if (node->kind() == Token::kNOT) {
    ValueGraphVisitor for_value(owner());
    node->operand()->Visit(&for_value);
    Append(for_value);
    Value* value = for_value.value();
    Isolate* isolate = Isolate::Current();
    if (isolate->type_checks() || isolate->asserts()) {
      value =
          Bind(new (Z) AssertBooleanInstr(node->operand()->token_pos(), value));
    }
    BooleanNegateInstr* negate = new (Z) BooleanNegateInstr(value);
    ReturnDefinition(negate);
    return;
  }

  ValueGraphVisitor for_value(owner());
  node->operand()->Visit(&for_value);
  Append(for_value);
  PushArgumentInstr* push_value = PushArgument(for_value.value());
  ZoneGrowableArray<PushArgumentInstr*>* arguments =
      new (Z) ZoneGrowableArray<PushArgumentInstr*>(1);
  arguments->Add(push_value);
  InstanceCallInstr* call = new (Z) InstanceCallInstr(
      node->token_pos(), Symbols::Token(node->kind()), node->kind(), arguments,
      Object::null_array(), 1, owner()->ic_data_array());
  ReturnDefinition(call);
}


void EffectGraphVisitor::VisitConditionalExprNode(ConditionalExprNode* node) {
  TestGraphVisitor for_test(owner(), node->condition()->token_pos());
  node->condition()->Visit(&for_test);

  // Translate the subexpressions for their effects.
  EffectGraphVisitor for_true(owner());
  node->true_expr()->Visit(&for_true);
  EffectGraphVisitor for_false(owner());
  node->false_expr()->Visit(&for_false);

  Join(for_test, for_true, for_false);
}


void ValueGraphVisitor::VisitConditionalExprNode(ConditionalExprNode* node) {
  TestGraphVisitor for_test(owner(), node->condition()->token_pos());
  node->condition()->Visit(&for_test);

  ValueGraphVisitor for_true(owner());
  node->true_expr()->Visit(&for_true);
  ASSERT(for_true.is_open());
  for_true.Do(
      BuildStoreExprTemp(for_true.value(), node->true_expr()->token_pos()));

  ValueGraphVisitor for_false(owner());
  node->false_expr()->Visit(&for_false);
  ASSERT(for_false.is_open());
  for_false.Do(
      BuildStoreExprTemp(for_false.value(), node->false_expr()->token_pos()));

  Join(for_test, for_true, for_false);
  ReturnDefinition(BuildLoadExprTemp(node->token_pos()));
}


// <Statement> ::= If { condition: <Expression>
//                      true_branch: <Sequence>
//                      false_branch: <Sequence> }
void EffectGraphVisitor::VisitIfNode(IfNode* node) {
  TestGraphVisitor for_test(owner(), node->condition()->token_pos());
  node->condition()->Visit(&for_test);

  EffectGraphVisitor for_true(owner());
  EffectGraphVisitor for_false(owner());

  node->true_branch()->Visit(&for_true);
  // The for_false graph fragment will be empty (default graph fragment) if
  // we do not call Visit.
  if (node->false_branch() != NULL) node->false_branch()->Visit(&for_false);
  Join(for_test, for_true, for_false);
}


void EffectGraphVisitor::VisitSwitchNode(SwitchNode* node) {
  NestedSwitch nested_switch(owner(), node);
  EffectGraphVisitor switch_body(owner());
  node->body()->Visit(&switch_body);
  Append(switch_body);
  if (nested_switch.break_target() != NULL) {
    if (is_open()) Goto(nested_switch.break_target());
    exit_ = nested_switch.break_target();
  }
}


// A case node contains zero or more case expressions, can contain default
// and a case statement body.
// Compose fragment as follows:
// - if no case expressions, must have default:
//   a) target
//   b) [ case-statements ]
//
// - if has 1 or more case statements
//   a) target-0
//   b) [ case-expression-0 ] -> (true-target-0, target-1)
//   c) target-1
//   d) [ case-expression-1 ] -> (true-target-1, exit-target)
//   e) true-target-0 -> case-statements-join
//   f) true-target-1 -> case-statements-join
//   g) case-statements-join
//   h) [ case-statements ] -> exit-join
//   i) exit-target -> exit-join
//   j) exit-join
//
// Note: The specification of switch/case is under discussion and may change
// drastically.
void EffectGraphVisitor::VisitCaseNode(CaseNode* node) {
  const intptr_t len = node->case_expressions()->length();
  // Create case statements instructions.
  EffectGraphVisitor for_case_statements(owner());
  // Compute the start of the statements fragment.
  JoinEntryInstr* statement_start = NULL;
  if (node->label() == NULL) {
    statement_start = new (Z)
        JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index());
  } else {
    // The case nodes are nested inside a SequenceNode that is the body of a
    // SwitchNode.  The SwitchNode on the nesting stack contains the
    // continue labels for all the case clauses.
    statement_start =
        owner()->nesting_stack()->outer()->ContinueTargetFor(node->label());
  }
  ASSERT(statement_start != NULL);
  node->statements()->Visit(&for_case_statements);
  Instruction* statement_exit =
      AppendFragment(statement_start, for_case_statements);
  if (is_open() && (len == 0)) {
    ASSERT(node->contains_default());
    // Default only case node.
    Goto(statement_start);
    exit_ = statement_exit;
    return;
  }

  // Generate instructions for all case expressions.
  TargetEntryInstr* next_target = NULL;
  for (intptr_t i = 0; i < len; i++) {
    AstNode* case_expr = node->case_expressions()->NodeAt(i);
    TestGraphVisitor for_case_expression(owner(), case_expr->token_pos());
    case_expr->Visit(&for_case_expression);
    if (i == 0) {
      // Append only the first one, everything else is connected from it.
      Append(for_case_expression);
    } else {
      ASSERT(next_target != NULL);
      AppendFragment(next_target, for_case_expression);
    }
    for_case_expression.IfTrueGoto(statement_start);
    next_target = for_case_expression.CreateFalseSuccessor()->AsTargetEntry();
  }

  // Once a test fragment has been added, this fragment is closed.
  ASSERT(!is_open());

  Instruction* exit_instruction = NULL;
  // Handle last (or only) case: false goes to exit or to statement if this
  // node contains default.
  if (len > 0) {
    ASSERT(next_target != NULL);
    if (node->contains_default()) {
      // True and false go to statement start.
      next_target->Goto(statement_start);
      exit_instruction = statement_exit;
    } else {
      if (statement_exit != NULL) {
        JoinEntryInstr* join = new (Z)
            JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index());
        statement_exit->Goto(join);
        next_target->Goto(join);
        exit_instruction = join;
      } else {
        exit_instruction = next_target;
      }
    }
  } else {
    // A CaseNode without case expressions must contain default.
    ASSERT(node->contains_default());
    Goto(statement_start);
    exit_instruction = statement_exit;
  }

  ASSERT(!is_open());
  exit_ = exit_instruction;
}


// <Statement> ::= While { label:     SourceLabel
//                         condition: <Expression>
//                         body:      <Sequence> }
// The fragment is composed as follows:
// a) loop-join
// b) [ test_preamble ]?
// c) [ test ] -> (body-entry-target, loop-exit-target)
// d) body-entry-target
// e) [ body ] -> (continue-join)
// f) continue-join -> (loop-join)
// g) loop-exit-target
// h) break-join (optional)
void EffectGraphVisitor::VisitWhileNode(WhileNode* node) {
  NestedLoop nested_loop(owner(), node->label());

  EffectGraphVisitor for_preamble(owner());
  if (node->condition_preamble() != NULL) {
    node->condition_preamble()->Visit(&for_preamble);
  }

  TestGraphVisitor for_test(owner(), node->condition()->token_pos());
  node->condition()->Visit(&for_test);
  ASSERT(!for_test.is_empty());  // Language spec.

  EffectGraphVisitor for_body(owner());
  node->body()->Visit(&for_body);

  // Labels are set after body traversal.
  JoinEntryInstr* join = nested_loop.continue_target();
  if (join != NULL) {
    if (for_body.is_open()) for_body.Goto(join);
    for_body.exit_ = join;
  }
  TieLoop(node->token_pos(), for_test, for_body, for_preamble);
  join = nested_loop.break_target();
  if (join != NULL) {
    Goto(join);
    exit_ = join;
  }
}


// The fragment is composed as follows:
// a) body-entry-join
// b) [ body ]
// c) test-entry (continue-join or body-exit-target)
// d) [ test-entry ] -> (back-target, loop-exit-target)
// e) back-target -> (body-entry-join)
// f) loop-exit-target
// g) break-join
void EffectGraphVisitor::VisitDoWhileNode(DoWhileNode* node) {
  NestedLoop nested_loop(owner(), node->label());

  // Traverse the body first in order to generate continue and break labels.
  EffectGraphVisitor for_body(owner());
  node->body()->Visit(&for_body);

  TestGraphVisitor for_test(owner(), node->condition()->token_pos());
  node->condition()->Visit(&for_test);
  ASSERT(is_open());

  // Tie do-while loop (test is after the body).
  JoinEntryInstr* body_entry_join =
      new (Z) JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index());
  Goto(body_entry_join);
  Instruction* body_exit = AppendFragment(body_entry_join, for_body);

  JoinEntryInstr* join = nested_loop.continue_target();
  if ((body_exit != NULL) || (join != NULL)) {
    if (join == NULL) {
      join = new (Z)
          JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index());
    }
    CheckStackOverflowInstr* check = new (Z)
        CheckStackOverflowInstr(node->token_pos(), owner()->loop_depth());
    join->LinkTo(check);
    check->LinkTo(for_test.entry());
    if (body_exit != NULL) {
      body_exit->Goto(join);
    }
  }

  for_test.IfTrueGoto(body_entry_join);
  join = nested_loop.break_target();
  if (join == NULL) {
    exit_ = for_test.CreateFalseSuccessor();
  } else {
    for_test.IfFalseGoto(join);
    exit_ = join;
  }
}


// A ForNode can contain break and continue jumps. 'break' joins to
// ForNode exit, 'continue' joins at increment entry. The fragment is composed
// as follows:
// a) [ initializer ]
// b) loop-join
// c) [ test ] -> (body-entry-target, loop-exit-target)
// d) body-entry-target
// e) [ body ]
// f) continue-join (optional)
// g) [ increment ] -> (loop-join)
// h) loop-exit-target
// i) break-join
void EffectGraphVisitor::VisitForNode(ForNode* node) {
  EffectGraphVisitor for_initializer(owner());
  node->initializer()->Visit(&for_initializer);
  Append(for_initializer);
  ASSERT(is_open());

  NestedLoop nested_loop(owner(), node->label());
  // Compose body to set any jump labels.
  EffectGraphVisitor for_body(owner());
  node->body()->Visit(&for_body);

  EffectGraphVisitor for_increment(owner());
  node->increment()->Visit(&for_increment);

  // Join the loop body and increment and then tie the loop.
  JoinEntryInstr* continue_join = nested_loop.continue_target();
  if ((continue_join != NULL) || for_body.is_open()) {
    JoinEntryInstr* loop_entry = new (Z)
        JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index());
    if (continue_join != NULL) {
      if (for_body.is_open()) for_body.Goto(continue_join);
      Instruction* current = AppendFragment(continue_join, for_increment);
      current->Goto(loop_entry);
    } else {
      for_body.Append(for_increment);
      for_body.Goto(loop_entry);
    }
    Goto(loop_entry);
    exit_ = loop_entry;
    // Note: the stack overflow check happens on the back branch that jumps
    // to the increment instruction. The token position for the overflow
    // check must match the position of the increment expression, so that
    // the context level (if any) matches the that of the increment
    // expression.
    AddInstruction(new (Z) CheckStackOverflowInstr(
        node->increment()->token_pos(), owner()->loop_depth()));
  }

  if (node->condition() == NULL) {
    // Endless loop, no test.
    Append(for_body);
    exit_ = nested_loop.break_target();  // May be NULL.
  } else {
    EffectGraphVisitor for_test_preamble(owner());
    if (node->condition_preamble() != NULL) {
      node->condition_preamble()->Visit(&for_test_preamble);
      Append(for_test_preamble);
    }

    TestGraphVisitor for_test(owner(), node->condition()->token_pos());
    node->condition()->Visit(&for_test);
    Append(for_test);

    BlockEntryInstr* body_entry = for_test.CreateTrueSuccessor();
    AppendFragment(body_entry, for_body);

    if (nested_loop.break_target() == NULL) {
      exit_ = for_test.CreateFalseSuccessor();
    } else {
      for_test.IfFalseGoto(nested_loop.break_target());
      exit_ = nested_loop.break_target();
    }
  }
}


void EffectGraphVisitor::VisitJumpNode(JumpNode* node) {
  if (FLAG_support_debugger && owner()->function().is_debuggable()) {
    AddInstruction(new (Z) DebugStepCheckInstr(node->token_pos(),
                                               RawPcDescriptors::kRuntimeCall));
  }

  NestedContextAdjustment context_adjustment(owner(), owner()->context_level());

  for (intptr_t i = 0; i < node->inlined_finally_list_length(); i++) {
    EffectGraphVisitor for_effect(owner());
    node->InlinedFinallyNodeAt(i)->Visit(&for_effect);
    Append(for_effect);
    if (!is_open()) return;
  }

  // Unchain the context(s) up to the outer context level of the scope which
  // contains the destination label.
  SourceLabel* label = node->label();
  ASSERT(label->owner() != NULL);
  AdjustContextLevel(label->owner());

  JoinEntryInstr* jump_target = NULL;
  NestedStatement* current = owner()->nesting_stack();
  while (current != NULL) {
    jump_target = (node->kind() == Token::kBREAK)
                      ? current->BreakTargetFor(node->label())
                      : current->ContinueTargetFor(node->label());
    if (jump_target != NULL) break;
    current = current->outer();
  }
  ASSERT(jump_target != NULL);
  Goto(jump_target);
}


void EffectGraphVisitor::VisitArgumentListNode(ArgumentListNode* node) {
  UNREACHABLE();
}


void EffectGraphVisitor::VisitAwaitNode(AwaitNode* node) {
  // Await nodes are temporary during parsing.
  UNREACHABLE();
}


void EffectGraphVisitor::VisitAwaitMarkerNode(AwaitMarkerNode* node) {
  // We need to create a new await state which involves:
  // * Increase the jump counter. Sanity check against the list of targets.
  // * Save the current context for resuming.
  ASSERT(node->token_pos().IsSynthetic() || node->token_pos().IsNoSource());
  ASSERT(node->async_scope() != NULL);
  ASSERT(node->await_scope() != NULL);
  LocalVariable* jump_var =
      node->async_scope()->LookupVariable(Symbols::AwaitJumpVar(), false);
  LocalVariable* ctx_var =
      node->async_scope()->LookupVariable(Symbols::AwaitContextVar(), false);
  ASSERT((jump_var != NULL) && jump_var->is_captured());
  ASSERT((ctx_var != NULL) && ctx_var->is_captured());
  const intptr_t jump_count = owner()->next_await_counter();
  ASSERT(jump_count >= 0);
  // Sanity check that we always add a JoinEntryInstr before adding a new
  // state.
  ASSERT(jump_count == owner()->await_joins()->length());
  // Store the counter in :await_jump_var.
  Value* jump_val = Bind(new (Z) ConstantInstr(
      Smi::ZoneHandle(Z, Smi::New(jump_count)), node->token_pos()));
  Do(BuildStoreLocal(*jump_var, jump_val, node->token_pos()));
  // Add a mapping from jump_count -> token_position.
  owner()->AppendAwaitTokenPosition(node->token_pos());
  // Save the current context for resuming.
  BuildSaveContext(*ctx_var, node->token_pos());
}


intptr_t EffectGraphVisitor::GetCurrentTempLocalIndex() const {
  return kFirstLocalSlotFromFp - owner()->num_stack_locals() -
         owner()->num_copied_params() - owner()->args_pushed() -
         owner()->temp_count() + 1;
}


LocalVariable* EffectGraphVisitor::EnterTempLocalScope(Value* value) {
  ASSERT(value->definition()->temp_index() == (owner()->temp_count() - 1));
  intptr_t index = GetCurrentTempLocalIndex();
  char name[64];
  OS::SNPrint(name, 64, ":tmp_local%" Pd, index);
  LocalVariable* var =
      new (Z) LocalVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
                            String::ZoneHandle(Z, Symbols::New(T, name)),
                            *value->Type()->ToAbstractType());
  var->set_index(index);
  return var;
}


Definition* EffectGraphVisitor::ExitTempLocalScope(Value* value) {
  return new (Z) DropTempsInstr(0, value);
}


void EffectGraphVisitor::BuildLetTempExpressions(LetNode* node) {
  intptr_t num_temps = node->num_temps();
  for (intptr_t i = 0; i < num_temps; ++i) {
    ValueGraphVisitor for_value(owner());
    node->InitializerAt(i)->Visit(&for_value);
    Append(for_value);
    ASSERT(!node->TempAt(i)->HasIndex() ||
           (node->TempAt(i)->index() == GetCurrentTempLocalIndex()));
    node->TempAt(i)->set_index(GetCurrentTempLocalIndex());
  }
}


void EffectGraphVisitor::VisitLetNode(LetNode* node) {
  BuildLetTempExpressions(node);

  // Visit body.
  for (intptr_t i = 0; i < node->nodes().length(); ++i) {
    EffectGraphVisitor for_effect(owner());
    node->nodes()[i]->Visit(&for_effect);
    Append(for_effect);
  }

  intptr_t num_temps = node->num_temps();
  if (num_temps > 0) {
    owner()->DeallocateTemps(num_temps);
    Do(new (Z) DropTempsInstr(num_temps, NULL));
  }
}


void ValueGraphVisitor::VisitLetNode(LetNode* node) {
  BuildLetTempExpressions(node);

  // Visit body.
  for (intptr_t i = 0; i < node->nodes().length() - 1; ++i) {
    EffectGraphVisitor for_effect(owner());
    node->nodes()[i]->Visit(&for_effect);
    Append(for_effect);
  }
  // Visit the last body expression for value.
  ValueGraphVisitor for_value(owner());
  node->nodes().Last()->Visit(&for_value);
  Append(for_value);
  Value* result_value = for_value.value();

  intptr_t num_temps = node->num_temps();
  if (num_temps > 0) {
    owner()->DeallocateTemps(num_temps);
    ReturnDefinition(new (Z) DropTempsInstr(num_temps, result_value));
  } else {
    ReturnValue(result_value);
  }
}


void EffectGraphVisitor::VisitArrayNode(ArrayNode* node) {
  const TypeArguments& type_args =
      TypeArguments::ZoneHandle(Z, node->type().arguments());
  Value* element_type =
      BuildInstantiatedTypeArguments(node->token_pos(), type_args);
  Value* num_elements =
      Bind(new (Z) ConstantInstr(Smi::ZoneHandle(Z, Smi::New(node->length()))));
  CreateArrayInstr* create =
      new (Z) CreateArrayInstr(node->token_pos(), element_type, num_elements);
  Value* array_val = Bind(create);

  {
    LocalVariable* tmp_var = EnterTempLocalScope(array_val);
    const intptr_t class_id = kArrayCid;
    const intptr_t deopt_id = Thread::kNoDeoptId;
    for (int i = 0; i < node->length(); ++i) {
      Value* array = Bind(new (Z) LoadLocalInstr(*tmp_var, node->token_pos()));
      Value* index = Bind(new (Z) ConstantInstr(Smi::ZoneHandle(Z, Smi::New(i)),
                                                node->token_pos()));
      ValueGraphVisitor for_value(owner());
      node->ElementAt(i)->Visit(&for_value);
      Append(for_value);
      // No store barrier needed for constants.
      const StoreBarrierType emit_store_barrier =
          for_value.value()->BindsToConstant() ? kNoStoreBarrier
                                               : kEmitStoreBarrier;
      const intptr_t index_scale = Instance::ElementSizeFor(class_id);
      StoreIndexedInstr* store = new (Z) StoreIndexedInstr(
          array, index, for_value.value(), emit_store_barrier, index_scale,
          class_id, kAlignedAccess, deopt_id, node->token_pos());
      Do(store);
    }
    ReturnDefinition(ExitTempLocalScope(array_val));
  }
}


void EffectGraphVisitor::VisitStringInterpolateNode(
    StringInterpolateNode* node) {
  ValueGraphVisitor for_argument(owner());
  ArrayNode* arguments = node->value();
  if (arguments->length() == 1) {
    ZoneGrowableArray<PushArgumentInstr*>* values =
        new (Z) ZoneGrowableArray<PushArgumentInstr*>(1);
    arguments->ElementAt(0)->Visit(&for_argument);
    Append(for_argument);
    PushArgumentInstr* push_arg = PushArgument(for_argument.value());
    values->Add(push_arg);
    const int kNumberOfArguments = 1;
    const Array& kNoArgumentNames = Object::null_array();
    const Class& cls =
        Class::Handle(Library::LookupCoreClass(Symbols::StringBase()));
    ASSERT(!cls.IsNull());
    const Function& function = Function::ZoneHandle(
        Z, Resolver::ResolveStatic(
               cls, Library::PrivateCoreLibName(Symbols::InterpolateSingle()),
               kNumberOfArguments, kNoArgumentNames));
    StaticCallInstr* call =
        new (Z) StaticCallInstr(node->token_pos(), function, kNoArgumentNames,
                                values, owner()->ic_data_array());
    ReturnDefinition(call);
    return;
  }
  arguments->Visit(&for_argument);
  Append(for_argument);
  StringInterpolateInstr* instr =
      new (Z) StringInterpolateInstr(for_argument.value(), node->token_pos());
  ReturnDefinition(instr);
}


void EffectGraphVisitor::VisitClosureNode(ClosureNode* node) {
  const Function& function = node->function();
  if (function.IsImplicitStaticClosureFunction()) {
    const Instance& closure =
        Instance::ZoneHandle(Z, function.ImplicitStaticClosure());
    ReturnDefinition(new (Z) ConstantInstr(closure));
    return;
  }

  const bool is_implicit = function.IsImplicitInstanceClosureFunction();
  ASSERT(is_implicit || function.IsNonImplicitClosureFunction());
  // The context scope may have already been set by the non-optimizing
  // compiler.  If it was not, set it here.
  if (function.context_scope() == ContextScope::null()) {
    ASSERT(!is_implicit);
    ASSERT(node->scope() != NULL);
    const ContextScope& context_scope = ContextScope::ZoneHandle(
        Z, node->scope()->PreserveOuterScope(owner()->context_level()));
    ASSERT(!function.HasCode());
    ASSERT(function.context_scope() == ContextScope::null());
    function.set_context_scope(context_scope);

    // The closure is now properly setup, add it to the lookup table.
    // It is possible that the compiler creates more than one function
    // object for the same closure, e.g. when inlining nodes from
    // finally clauses. If we already have a function object for the
    // same closure, do not add a second one. We compare token position,
    // and parent function to detect duplicates.
    const Function& parent = Function::Handle(function.parent_function());
    const Function& found_func = Function::Handle(
        Z, isolate()->LookupClosureFunction(parent, function.token_pos()));
    if (found_func.IsNull()) {
      isolate()->AddClosureFunction(function);
    }
  }
  ASSERT(function.context_scope() != ContextScope::null());

  // The function type of a closure may have type arguments. In that case,
  // pass the type arguments of the instantiator.
  const Class& closure_class =
      Class::ZoneHandle(Z, isolate()->object_store()->closure_class());
  ZoneGrowableArray<PushArgumentInstr*>* no_arguments =
      new (Z) ZoneGrowableArray<PushArgumentInstr*>(0);
  AllocateObjectInstr* alloc = new (Z)
      AllocateObjectInstr(node->token_pos(), closure_class, no_arguments);
  alloc->set_closure_function(function);

  Value* closure_val = Bind(alloc);
  {
    LocalVariable* closure_tmp_var = EnterTempLocalScope(closure_val);
    // Store instantiator type arguments if scope class is generic.
    const Type& function_type = Type::ZoneHandle(Z, function.SignatureType());
    const Class& scope_cls = Class::ZoneHandle(Z, function_type.type_class());
    if (scope_cls.IsGeneric()) {
      ASSERT(function.Owner() == scope_cls.raw());
      Value* closure_tmp_val =
          Bind(new (Z) LoadLocalInstr(*closure_tmp_var, node->token_pos()));
      const Class& instantiator_class =
          Class::Handle(Z, owner()->function().Owner());
      Value* type_arguments = BuildInstantiatorTypeArguments(
          node->token_pos(), instantiator_class, NULL);
      Do(new (Z) StoreInstanceFieldInstr(Closure::instantiator_offset(),
                                         closure_tmp_val, type_arguments,
                                         kEmitStoreBarrier, node->token_pos()));
    }

    // Store function.
    Value* closure_tmp_val =
        Bind(new (Z) LoadLocalInstr(*closure_tmp_var, node->token_pos()));
    Value* func_val =
        Bind(new (Z) ConstantInstr(Function::ZoneHandle(Z, function.raw())));
    Do(new (Z) StoreInstanceFieldInstr(Closure::function_offset(),
                                       closure_tmp_val, func_val,
                                       kEmitStoreBarrier, node->token_pos()));
    if (is_implicit) {
      // Create new context containing the receiver.
      const intptr_t kNumContextVariables = 1;  // The receiver.
      Value* allocated_context = Bind(new (Z) AllocateContextInstr(
          node->token_pos(), kNumContextVariables));
      {
        LocalVariable* context_tmp_var = EnterTempLocalScope(allocated_context);
        // Store receiver in context.
        Value* context_tmp_val =
            Bind(new (Z) LoadLocalInstr(*context_tmp_var, node->token_pos()));
        ValueGraphVisitor for_receiver(owner());
        node->receiver()->Visit(&for_receiver);
        Append(for_receiver);
        Value* receiver = for_receiver.value();
        Do(new (Z) StoreInstanceFieldInstr(
            Context::variable_offset(0), context_tmp_val, receiver,
            kEmitStoreBarrier, node->token_pos()));
        // Store new context in closure.
        closure_tmp_val =
            Bind(new (Z) LoadLocalInstr(*closure_tmp_var, node->token_pos()));
        context_tmp_val =
            Bind(new (Z) LoadLocalInstr(*context_tmp_var, node->token_pos()));
        Do(new (Z) StoreInstanceFieldInstr(
            Closure::context_offset(), closure_tmp_val, context_tmp_val,
            kEmitStoreBarrier, node->token_pos()));
        Do(ExitTempLocalScope(allocated_context));
      }
    } else {
      // Store current context in closure.
      closure_tmp_val =
          Bind(new (Z) LoadLocalInstr(*closure_tmp_var, node->token_pos()));
      Value* context = Bind(BuildCurrentContext(node->token_pos()));
      Do(new (Z) StoreInstanceFieldInstr(Closure::context_offset(),
                                         closure_tmp_val, context,
                                         kEmitStoreBarrier, node->token_pos()));
    }
    ReturnDefinition(ExitTempLocalScope(closure_val));
  }
}


void EffectGraphVisitor::BuildPushArguments(
    const ArgumentListNode& node,
    ZoneGrowableArray<PushArgumentInstr*>* values) {
  for (intptr_t i = 0; i < node.length(); ++i) {
    ValueGraphVisitor for_argument(owner());
    node.NodeAt(i)->Visit(&for_argument);
    Append(for_argument);
    PushArgumentInstr* push_arg = PushArgument(for_argument.value());
    values->Add(push_arg);
  }
}


void EffectGraphVisitor::BuildInstanceCallConditional(InstanceCallNode* node) {
  const TokenPosition token_pos = node->token_pos();
  LocalVariable* temp_var = owner()->parsed_function().expression_temp_var();
  LoadLocalNode* load_temp = new (Z) LoadLocalNode(token_pos, temp_var);

  LiteralNode* null_constant =
      new (Z) LiteralNode(ST(token_pos), Object::null_instance());
  ComparisonNode* check_is_null = new (Z)
      ComparisonNode(ST(token_pos), Token::kEQ, load_temp, null_constant);
  TestGraphVisitor for_test(owner(), ST(token_pos));
  check_is_null->Visit(&for_test);

  EffectGraphVisitor for_true(owner());
  EffectGraphVisitor for_false(owner());

  StoreLocalNode* store_null =
      new (Z) StoreLocalNode(ST(token_pos), temp_var, null_constant);
  store_null->Visit(&for_true);

  InstanceCallNode* call = new (Z) InstanceCallNode(
      token_pos, load_temp, node->function_name(), node->arguments());
  StoreLocalNode* store_result =
      new (Z) StoreLocalNode(ST(token_pos), temp_var, call);
  store_result->Visit(&for_false);

  Join(for_test, for_true, for_false);
}


void ValueGraphVisitor::VisitInstanceCallNode(InstanceCallNode* node) {
  if (node->is_conditional()) {
    ValueGraphVisitor for_receiver(owner());
    node->receiver()->Visit(&for_receiver);
    Append(for_receiver);
    Do(BuildStoreExprTemp(for_receiver.value(), node->token_pos()));
    BuildInstanceCallConditional(node);
    ReturnDefinition(BuildLoadExprTemp(node->token_pos()));
  } else {
    EffectGraphVisitor::VisitInstanceCallNode(node);
  }
}


void EffectGraphVisitor::VisitInstanceCallNode(InstanceCallNode* node) {
  ValueGraphVisitor for_receiver(owner());
  node->receiver()->Visit(&for_receiver);
  Append(for_receiver);
  if (node->is_conditional()) {
    Do(BuildStoreExprTemp(for_receiver.value(), node->token_pos()));
    BuildInstanceCallConditional(node);
  } else {
    PushArgumentInstr* push_receiver = PushArgument(for_receiver.value());
    ZoneGrowableArray<PushArgumentInstr*>* arguments = new (Z)
        ZoneGrowableArray<PushArgumentInstr*>(node->arguments()->length() + 1);
    arguments->Add(push_receiver);

    BuildPushArguments(*node->arguments(), arguments);
    InstanceCallInstr* call = new (Z) InstanceCallInstr(
        node->token_pos(), node->function_name(), Token::kILLEGAL, arguments,
        node->arguments()->names(), 1, owner()->ic_data_array());
    ReturnDefinition(call);
  }
}


// <Expression> ::= StaticCall { function: Function
//                               arguments: <ArgumentList> }
void EffectGraphVisitor::VisitStaticCallNode(StaticCallNode* node) {
  ZoneGrowableArray<PushArgumentInstr*>* arguments = new (Z)
      ZoneGrowableArray<PushArgumentInstr*>(node->arguments()->length());
  BuildPushArguments(*node->arguments(), arguments);
  StaticCallInstr* call = new (Z) StaticCallInstr(
      node->token_pos(), node->function(), node->arguments()->names(),
      arguments, owner()->ic_data_array());
  if (node->function().recognized_kind() != MethodRecognizer::kUnknown) {
    call->set_result_cid(MethodRecognizer::ResultCid(node->function()));
  }
  ReturnDefinition(call);
}


void EffectGraphVisitor::BuildClosureCall(ClosureCallNode* node,
                                          bool result_needed) {
  ValueGraphVisitor for_closure(owner());
  node->closure()->Visit(&for_closure);
  Append(for_closure);

  Value* closure_value = for_closure.value();
  LocalVariable* tmp_var = EnterTempLocalScope(closure_value);

  ZoneGrowableArray<PushArgumentInstr*>* arguments = new (Z)
      ZoneGrowableArray<PushArgumentInstr*>(node->arguments()->length());
  Value* closure_val =
      Bind(new (Z) LoadLocalInstr(*tmp_var, node->token_pos()));
  PushArgumentInstr* push_closure = PushArgument(closure_val);
  arguments->Add(push_closure);
  BuildPushArguments(*node->arguments(), arguments);

  closure_val = Bind(new (Z) LoadLocalInstr(*tmp_var, node->token_pos()));
  LoadFieldInstr* function_load = new (Z) LoadFieldInstr(
      closure_val, Closure::function_offset(),
      AbstractType::ZoneHandle(Z, AbstractType::null()), node->token_pos());
  function_load->set_is_immutable(true);
  Value* function_val = Bind(function_load);

  Definition* closure_call =
      new (Z) ClosureCallInstr(function_val, node, arguments);
  if (result_needed) {
    Value* result = Bind(closure_call);
    Do(new (Z) StoreLocalInstr(*tmp_var, result, ST(node->token_pos())));
  } else {
    Do(closure_call);
  }
  ReturnDefinition(ExitTempLocalScope(closure_value));
}


void EffectGraphVisitor::VisitClosureCallNode(ClosureCallNode* node) {
  BuildClosureCall(node, false);
}


void ValueGraphVisitor::VisitClosureCallNode(ClosureCallNode* node) {
  BuildClosureCall(node, true);
}


void EffectGraphVisitor::VisitInitStaticFieldNode(InitStaticFieldNode* node) {
  Value* field = Bind(
      new (Z) ConstantInstr(Field::ZoneHandle(Z, node->field().Original())));
  AddInstruction(new (Z) InitStaticFieldInstr(field, node->field()));
}


void EffectGraphVisitor::VisitCloneContextNode(CloneContextNode* node) {
  Value* context = Bind(BuildCurrentContext(node->token_pos()));
  Value* clone = Bind(new (Z) CloneContextInstr(node->token_pos(), context));
  Do(BuildStoreContext(clone, node->token_pos()));
}


Value* EffectGraphVisitor::BuildObjectAllocation(ConstructorCallNode* node) {
  const Class& cls = Class::ZoneHandle(Z, node->constructor().Owner());
  const bool cls_is_parameterized = cls.NumTypeArguments() > 0;

  ZoneGrowableArray<PushArgumentInstr*>* allocate_arguments = new (Z)
      ZoneGrowableArray<PushArgumentInstr*>(cls_is_parameterized ? 1 : 0);
  if (cls_is_parameterized) {
    Value* type_args = BuildInstantiatedTypeArguments(node->token_pos(),
                                                      node->type_arguments());
    allocate_arguments->Add(PushArgument(type_args));
  }

  Definition* allocation = new (Z) AllocateObjectInstr(
      node->token_pos(), Class::ZoneHandle(Z, node->constructor().Owner()),
      allocate_arguments);

  return Bind(allocation);
}


void EffectGraphVisitor::BuildConstructorCall(
    ConstructorCallNode* node,
    PushArgumentInstr* push_alloc_value) {
  ZoneGrowableArray<PushArgumentInstr*>* arguments =
      new (Z) ZoneGrowableArray<PushArgumentInstr*>(2);
  arguments->Add(push_alloc_value);

  BuildPushArguments(*node->arguments(), arguments);
  Do(new (Z) StaticCallInstr(node->token_pos(), node->constructor(),
                             node->arguments()->names(), arguments,
                             owner()->ic_data_array()));
}


static intptr_t GetResultCidOfListFactory(ConstructorCallNode* node) {
  const Function& function = node->constructor();
  const Class& function_class = Class::Handle(function.Owner());

  if ((function_class.library() != Library::CoreLibrary()) &&
      (function_class.library() != Library::TypedDataLibrary())) {
    return kDynamicCid;
  }

  if (node->constructor().IsFactory()) {
    if ((function_class.Name() == Symbols::List().raw()) &&
        (function.name() == Symbols::ListFactory().raw())) {
      // Special recognition of 'new List()' vs 'new List(n)'.
      if (node->arguments()->length() == 0) {
        return kGrowableObjectArrayCid;
      }
      return kArrayCid;
    }
    return FactoryRecognizer::ResultCid(function);
  }
  return kDynamicCid;  // Not a known list constructor.
}


void EffectGraphVisitor::VisitConstructorCallNode(ConstructorCallNode* node) {
  if (node->constructor().IsFactory()) {
    ZoneGrowableArray<PushArgumentInstr*>* arguments =
        new (Z) ZoneGrowableArray<PushArgumentInstr*>();
    PushArgumentInstr* push_type_arguments =
        PushArgument(BuildInstantiatedTypeArguments(node->token_pos(),
                                                    node->type_arguments()));
    arguments->Add(push_type_arguments);
    ASSERT(arguments->length() == 1);
    BuildPushArguments(*node->arguments(), arguments);
    StaticCallInstr* call = new (Z) StaticCallInstr(
        node->token_pos(), 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);
      call->set_is_known_list_constructor(true);
      // Recognized fixed length array factory must have two arguments:
      // (0) type-arguments, (1) length.
      ASSERT(!LoadFieldInstr::IsFixedLengthArrayCid(result_cid) ||
             arguments->length() == 2);
    } else if (node->constructor().recognized_kind() !=
               MethodRecognizer::kUnknown) {
      call->set_result_cid(MethodRecognizer::ResultCid(node->constructor()));
    }
    ReturnDefinition(call);
    return;
  }
  // t_n contains the allocated and initialized object.
  //   t_n      <- AllocateObject(class)
  //   t_n+1    <- ctor-arg
  //   t_n+2... <- constructor arguments start here
  //   StaticCall(constructor, t_n+1, t_n+2, ...)
  // No need to preserve allocated value (simpler than in ValueGraphVisitor).
  Value* allocated_value = BuildObjectAllocation(node);
  PushArgumentInstr* push_allocated_value = PushArgument(allocated_value);
  BuildConstructorCall(node, push_allocated_value);
}


Value* EffectGraphVisitor::BuildInstantiator(TokenPosition token_pos) {
  Function& outer_function = Function::Handle(Z, owner()->function().raw());
  while (outer_function.IsLocalFunction()) {
    outer_function = outer_function.parent_function();
  }
  if (outer_function.IsFactory()) {
    return NULL;
  }

  LocalVariable* instantiator = owner()->parsed_function().instantiator();
  ASSERT(instantiator != NULL);
  Value* result = Bind(BuildLoadLocal(*instantiator, token_pos));
  return result;
}


// 'expression_temp_var' may not be used inside this method if 'instantiator'
// is not NULL.
Value* EffectGraphVisitor::BuildInstantiatorTypeArguments(
    TokenPosition token_pos,
    const Class& instantiator_class,
    Value* instantiator) {
  if (!instantiator_class.IsGeneric()) {
    // The type arguments are compile time constants.
    TypeArguments& type_arguments =
        TypeArguments::ZoneHandle(Z, TypeArguments::null());
    // Type is temporary. Only its type arguments are preserved.
    Type& type = Type::Handle(Z, Type::New(instantiator_class, type_arguments,
                                           token_pos, Heap::kNew));
    type ^= ClassFinalizer::FinalizeType(instantiator_class, type,
                                         ClassFinalizer::kFinalize);
    ASSERT(!type.IsMalformedOrMalbounded());
    type_arguments = type.arguments();
    type_arguments = type_arguments.Canonicalize();
    return Bind(new (Z) ConstantInstr(type_arguments));
  }
  Function& outer_function = Function::Handle(Z, owner()->function().raw());
  while (outer_function.IsLocalFunction()) {
    outer_function = outer_function.parent_function();
  }
  if (outer_function.IsFactory()) {
    // No instantiator for factories.
    ASSERT(instantiator == NULL);
    LocalVariable* instantiator_var = owner()->parsed_function().instantiator();
    ASSERT(instantiator_var != NULL);
    return Bind(BuildLoadLocal(*instantiator_var, token_pos));
  }
  if (instantiator == NULL) {
    instantiator = BuildInstantiator(token_pos);
  }
  // The instantiator is the receiver of the caller, which is not a factory.
  // The receiver cannot be null; extract its TypeArguments object.
  // Note that in the factory case, the instantiator is the first parameter
  // of the factory, i.e. already a TypeArguments object.
  intptr_t type_arguments_field_offset =
      instantiator_class.type_arguments_field_offset();
  ASSERT(type_arguments_field_offset != Class::kNoTypeArguments);

  return Bind(new (Z) LoadFieldInstr(
      instantiator, type_arguments_field_offset,
      Type::ZoneHandle(Z, Type::null()),  // Not an instance, no type.
      token_pos));
}


Value* EffectGraphVisitor::BuildInstantiatedTypeArguments(
    TokenPosition token_pos,
    const TypeArguments& type_arguments) {
  if (type_arguments.IsNull() || type_arguments.IsInstantiated()) {
    return Bind(new (Z) ConstantInstr(type_arguments));
  }
  // The type arguments are uninstantiated.
  const Class& instantiator_class =
      Class::ZoneHandle(Z, owner()->function().Owner());
  Value* instantiator_value =
      BuildInstantiatorTypeArguments(token_pos, instantiator_class, NULL);
  const bool use_instantiator_type_args =
      type_arguments.IsUninstantiatedIdentity() ||
      type_arguments.CanShareInstantiatorTypeArguments(instantiator_class);
  if (use_instantiator_type_args) {
    return instantiator_value;
  } else {
    return Bind(new (Z) InstantiateTypeArgumentsInstr(
        token_pos, type_arguments, instantiator_class, instantiator_value));
  }
}


void ValueGraphVisitor::VisitConstructorCallNode(ConstructorCallNode* node) {
  if (node->constructor().IsFactory()) {
    EffectGraphVisitor::VisitConstructorCallNode(node);
    return;
  }

  // t_n contains the allocated and initialized object.
  //   t_n      <- AllocateObject(class)
  //   t_n      <- StoreLocal(temp, t_n);
  //   t_n+1    <- ctor-arg
  //   t_n+2... <- constructor arguments start here
  //   StaticCall(constructor, t_n, t_n+1, ...)
  //   tn       <- LoadLocal(temp)

  Value* allocate = BuildObjectAllocation(node);
  {
    LocalVariable* tmp_var = EnterTempLocalScope(allocate);
    Value* allocated_tmp =
        Bind(new (Z) LoadLocalInstr(*tmp_var, node->token_pos()));
    PushArgumentInstr* push_allocated_value = PushArgument(allocated_tmp);
    BuildConstructorCall(node, push_allocated_value);
    ReturnDefinition(ExitTempLocalScope(allocate));
  }
}


void EffectGraphVisitor::BuildInstanceGetterConditional(
    InstanceGetterNode* node) {
  const TokenPosition token_pos = node->token_pos();
  LocalVariable* temp_var = owner()->parsed_function().expression_temp_var();
  LoadLocalNode* load_temp = new (Z) LoadLocalNode(token_pos, temp_var);

  LiteralNode* null_constant =
      new (Z) LiteralNode(ST(token_pos), Object::null_instance());
  ComparisonNode* check_is_null = new (Z)
      ComparisonNode(ST(token_pos), Token::kEQ, load_temp, null_constant);
  TestGraphVisitor for_test(owner(), ST(token_pos));
  check_is_null->Visit(&for_test);

  EffectGraphVisitor for_true(owner());
  EffectGraphVisitor for_false(owner());

  StoreLocalNode* store_null =
      new (Z) StoreLocalNode(ST(token_pos), temp_var, null_constant);
  store_null->Visit(&for_true);

  InstanceGetterNode* getter =
      new (Z) InstanceGetterNode(token_pos, load_temp, node->field_name());
  StoreLocalNode* store_getter =
      new (Z) StoreLocalNode(ST(token_pos), temp_var, getter);
  store_getter->Visit(&for_false);

  Join(for_test, for_true, for_false);
}


void ValueGraphVisitor::VisitInstanceGetterNode(InstanceGetterNode* node) {
  if (node->is_conditional()) {
    ValueGraphVisitor for_receiver(owner());
    node->receiver()->Visit(&for_receiver);
    Append(for_receiver);
    Do(BuildStoreExprTemp(for_receiver.value(), node->token_pos()));
    BuildInstanceGetterConditional(node);
    ReturnDefinition(BuildLoadExprTemp(node->token_pos()));
  } else {
    EffectGraphVisitor::VisitInstanceGetterNode(node);
  }
}


void EffectGraphVisitor::VisitInstanceGetterNode(InstanceGetterNode* node) {
  ValueGraphVisitor for_receiver(owner());
  node->receiver()->Visit(&for_receiver);
  Append(for_receiver);
  if (node->is_conditional()) {
    Do(BuildStoreExprTemp(for_receiver.value(), node->token_pos()));
    BuildInstanceGetterConditional(node);
  } else {
    PushArgumentInstr* push_receiver = PushArgument(for_receiver.value());
    ZoneGrowableArray<PushArgumentInstr*>* arguments =
        new (Z) ZoneGrowableArray<PushArgumentInstr*>(1);
    arguments->Add(push_receiver);
    const String& name =
        String::ZoneHandle(Z, Field::GetterSymbol(node->field_name()));
    InstanceCallInstr* call = new (Z)
        InstanceCallInstr(node->token_pos(), name, Token::kGET, arguments,
                          Object::null_array(), 1, owner()->ic_data_array());
    ReturnDefinition(call);
  }
}


void EffectGraphVisitor::BuildInstanceSetterArguments(
    InstanceSetterNode* node,
    ZoneGrowableArray<PushArgumentInstr*>* arguments,
    bool result_is_needed) {
  ValueGraphVisitor for_receiver(owner());
  node->receiver()->Visit(&for_receiver);
  Append(for_receiver);
  arguments->Add(PushArgument(for_receiver.value()));

  ValueGraphVisitor for_value(owner());
  node->value()->Visit(&for_value);
  Append(for_value);

  Value* value = NULL;
  if (result_is_needed) {
    value = Bind(BuildStoreExprTemp(for_value.value(), node->token_pos()));
  } else {
    value = for_value.value();
  }
  arguments->Add(PushArgument(value));
}


void EffectGraphVisitor::VisitInstanceSetterNode(InstanceSetterNode* node) {
  const TokenPosition token_pos = node->token_pos();
  if (node->is_conditional()) {
    ValueGraphVisitor for_receiver(owner());
    node->receiver()->Visit(&for_receiver);
    Append(for_receiver);
    Do(BuildStoreExprTemp(for_receiver.value(), token_pos));

    LocalVariable* temp_var = owner()->parsed_function().expression_temp_var();
    LoadLocalNode* load_temp = new (Z) LoadLocalNode(ST(token_pos), temp_var);
    LiteralNode* null_constant =
        new (Z) LiteralNode(ST(token_pos), Object::null_instance());
    ComparisonNode* check_is_null = new (Z)
        ComparisonNode(ST(token_pos), Token::kEQ, load_temp, null_constant);
    TestGraphVisitor for_test(owner(), ST(token_pos));
    check_is_null->Visit(&for_test);

    EffectGraphVisitor for_true(owner());
    EffectGraphVisitor for_false(owner());

    InstanceSetterNode* setter = new (Z) InstanceSetterNode(
        token_pos, load_temp, node->field_name(), node->value());
    setter->Visit(&for_false);
    Join(for_test, for_true, for_false);
    return;
  }
  ZoneGrowableArray<PushArgumentInstr*>* arguments =
      new (Z) ZoneGrowableArray<PushArgumentInstr*>(2);
  BuildInstanceSetterArguments(node, arguments, kResultNotNeeded);
  const String& name =
      String::ZoneHandle(Z, Field::SetterSymbol(node->field_name()));
  const intptr_t kNumArgsChecked = 1;  // Do not check value type.
  InstanceCallInstr* call = new (Z) InstanceCallInstr(
      token_pos, name, Token::kSET, arguments, Object::null_array(),
      kNumArgsChecked, owner()->ic_data_array());
  ReturnDefinition(call);
}


void ValueGraphVisitor::VisitInstanceSetterNode(InstanceSetterNode* node) {
  const TokenPosition token_pos = node->token_pos();
  if (node->is_conditional()) {
    ValueGraphVisitor for_receiver(owner());
    node->receiver()->Visit(&for_receiver);
    Append(for_receiver);
    Do(BuildStoreExprTemp(for_receiver.value(), token_pos));

    LocalVariable* temp_var = owner()->parsed_function().expression_temp_var();
    LoadLocalNode* load_temp = new (Z) LoadLocalNode(ST(token_pos), temp_var);
    LiteralNode* null_constant =
        new (Z) LiteralNode(ST(token_pos), Object::null_instance());
    ComparisonNode* check_is_null = new (Z)
        ComparisonNode(ST(token_pos), Token::kEQ, load_temp, null_constant);
    TestGraphVisitor for_test(owner(), ST(token_pos));
    check_is_null->Visit(&for_test);

    ValueGraphVisitor for_true(owner());
    null_constant->Visit(&for_true);
    for_true.Do(BuildStoreExprTemp(for_true.value(), token_pos));

    ValueGraphVisitor for_false(owner());
    InstanceSetterNode* setter = new (Z) InstanceSetterNode(
        token_pos, load_temp, node->field_name(), node->value());
    setter->Visit(&for_false);
    for_false.Do(BuildStoreExprTemp(for_false.value(), token_pos));

    Join(for_test, for_true, for_false);
    ReturnDefinition(BuildLoadExprTemp(token_pos));
    return;
  }
  ZoneGrowableArray<PushArgumentInstr*>* arguments =
      new (Z) ZoneGrowableArray<PushArgumentInstr*>(2);
  BuildInstanceSetterArguments(node, arguments, kResultNeeded);
  const String& name =
      String::ZoneHandle(Z, Field::SetterSymbol(node->field_name()));
  const intptr_t kNumArgsChecked = 1;  // Do not check value type.
  Do(new (Z) InstanceCallInstr(token_pos, name, Token::kSET, arguments,
                               Object::null_array(), kNumArgsChecked,
                               owner()->ic_data_array()));
  ReturnDefinition(BuildLoadExprTemp(token_pos));
}


void EffectGraphVisitor::VisitStaticGetterNode(StaticGetterNode* node) {
  const String& getter_name =
      String::ZoneHandle(Z, Field::GetterSymbol(node->field_name()));
  ZoneGrowableArray<PushArgumentInstr*>* arguments =
      new (Z) ZoneGrowableArray<PushArgumentInstr*>();
  Function& getter_function = Function::ZoneHandle(Z, Function::null());
  if (node->is_super_getter()) {
    // Statically resolved instance getter, i.e. "super getter".
    ASSERT(node->receiver() != NULL);
    getter_function =
        Resolver::ResolveDynamicAnyArgs(Z, node->cls(), getter_name);
    if (getter_function.IsNull()) {
      // Resolve and call noSuchMethod.
      ArgumentListNode* arguments = new (Z) ArgumentListNode(node->token_pos());
      arguments->Add(node->receiver());
      StaticCallInstr* call = BuildStaticNoSuchMethodCall(
          node->cls(), node->receiver(), getter_name, arguments,
          false,  // Don't save last argument.
          true);  // Super invocation.
      ReturnDefinition(call);
      return;
    } else {
      ValueGraphVisitor receiver_value(owner());
      node->receiver()->Visit(&receiver_value);
      Append(receiver_value);
      arguments->Add(PushArgument(receiver_value.value()));
    }
  } else {
    getter_function = node->cls().LookupStaticFunction(getter_name);
    if (getter_function.IsNull()) {
      // When the parser encounters a reference to a static field materialized
      // only by a static setter, but no corresponding static getter, it creates
      // a StaticGetterNode ast node referring to the non-existing static getter
      // for the case this field reference appears in a left hand side
      // expression (the parser has not distinguished between left and right
      // hand side yet at this stage). If the parser establishes later that the
      // field access is part of a left hand side expression, the
      // StaticGetterNode is transformed into a StaticSetterNode referring to
      // the existing static setter.
      // However, if the field reference appears in a right hand side
      // expression, no such transformation occurs and we land here with a
      // StaticGetterNode missing a getter function, so we throw a
      // NoSuchMethodError.

      // Throw a NoSuchMethodError.
      StaticCallInstr* call = BuildThrowNoSuchMethodError(
          node->token_pos(), node->cls(), getter_name,
          NULL,  // No Arguments to getter.
          InvocationMirror::EncodeType(node->cls().IsTopLevel()
                                           ? InvocationMirror::kTopLevel
                                           : InvocationMirror::kStatic,
                                       InvocationMirror::kGetter));
      ReturnDefinition(call);
      return;
    }
  }
  ASSERT(!getter_function.IsNull());
  StaticCallInstr* call =
      new (Z) StaticCallInstr(node->token_pos(), getter_function,
                              Object::null_array(),  // No names
                              arguments, owner()->ic_data_array());
  ReturnDefinition(call);
}


void EffectGraphVisitor::BuildStaticSetter(StaticSetterNode* node,
                                           bool result_is_needed) {
  const String& setter_name =
      String::ZoneHandle(Z, Field::SetterSymbol(node->field_name()));
  ZoneGrowableArray<PushArgumentInstr*>* arguments =
      new (Z) ZoneGrowableArray<PushArgumentInstr*>(1);
  const TokenPosition token_pos = node->token_pos();
  // A super setter is an instance setter whose setter function is
  // resolved at compile time (in the caller instance getter's super class).
  // Unlike a static getter, a super getter has a receiver parameter.
  const bool is_super_setter = (node->receiver() != NULL);
  const Function& setter_function = node->function();
  StaticCallInstr* call;
  if (setter_function.IsNull()) {
    if (is_super_setter) {
      ASSERT(node->receiver() != NULL);
      // Resolve and call noSuchMethod.
      ArgumentListNode* arguments = new (Z) ArgumentListNode(token_pos);
      arguments->Add(node->receiver());
      arguments->Add(node->value());
      call = BuildStaticNoSuchMethodCall(
          node->cls(), node->receiver(), setter_name, arguments,
          result_is_needed,  // Save last arg if result is needed.
          true);             // Super invocation.
    } else {
      // Throw a NoSuchMethodError.
      ArgumentListNode* arguments = new (Z) ArgumentListNode(token_pos);
      arguments->Add(node->value());
      call = BuildThrowNoSuchMethodError(
          token_pos, node->cls(), setter_name,
          arguments,  // Argument is the value passed to the setter.
          InvocationMirror::EncodeType(node->cls().IsTopLevel()
                                           ? InvocationMirror::kTopLevel
                                           : InvocationMirror::kStatic,
                                       InvocationMirror::kSetter));
    }
  } else {
    if (is_super_setter) {
      // Add receiver of instance getter.
      ValueGraphVisitor for_receiver(owner());
      node->receiver()->Visit(&for_receiver);
      Append(for_receiver);
      arguments->Add(PushArgument(for_receiver.value()));
    }
    ValueGraphVisitor for_value(owner());
    node->value()->Visit(&for_value);
    Append(for_value);
    Value* value = NULL;
    if (result_is_needed) {
      value = Bind(BuildStoreExprTemp(for_value.value(), token_pos));
    } else {
      value = for_value.value();
    }
    arguments->Add(PushArgument(value));

    call = new (Z) StaticCallInstr(token_pos, setter_function,
                                   Object::null_array(),  // No names.
                                   arguments, owner()->ic_data_array());
  }
  if (result_is_needed) {
    Do(call);
    ReturnDefinition(BuildLoadExprTemp(token_pos));
  } else {
    ReturnDefinition(call);
  }
}


void EffectGraphVisitor::VisitStaticSetterNode(StaticSetterNode* node) {
  BuildStaticSetter(node, false);  // Result not needed.
}


void ValueGraphVisitor::VisitStaticSetterNode(StaticSetterNode* node) {
  BuildStaticSetter(node, true);  // Result needed.
}


static intptr_t OffsetForLengthGetter(MethodRecognizer::Kind kind) {
  switch (kind) {
    case MethodRecognizer::kObjectArrayLength:
    case MethodRecognizer::kImmutableArrayLength:
      return Array::length_offset();
    case MethodRecognizer::kTypedDataLength:
      // .length is defined in _TypedList which is the base class for internal
      // and external typed data.
      ASSERT(TypedData::length_offset() == ExternalTypedData::length_offset());
      return TypedData::length_offset();
    case MethodRecognizer::kGrowableArrayLength:
      return GrowableObjectArray::length_offset();
    default:
      UNREACHABLE();
      return 0;
  }
}


LoadLocalInstr* EffectGraphVisitor::BuildLoadThisVar(LocalScope* scope,
                                                     TokenPosition token_pos) {
  LocalVariable* receiver_var = scope->LookupVariable(Symbols::This(),
                                                      true);  // Test only.
  return new (Z) LoadLocalInstr(*receiver_var, token_pos);
}


LoadFieldInstr* EffectGraphVisitor::BuildNativeGetter(
    NativeBodyNode* node,
    MethodRecognizer::Kind kind,
    intptr_t offset,
    const Type& type,
    intptr_t class_id) {
  Value* receiver = Bind(BuildLoadThisVar(node->scope(), node->token_pos()));
  LoadFieldInstr* load =
      new (Z) LoadFieldInstr(receiver, offset, type, node->token_pos());
  load->set_result_cid(class_id);
  load->set_recognized_kind(kind);
  return load;
}


ConstantInstr* EffectGraphVisitor::DoNativeSetterStoreValue(
    NativeBodyNode* node,
    intptr_t offset,
    StoreBarrierType emit_store_barrier) {
  Value* receiver = Bind(BuildLoadThisVar(node->scope(), node->token_pos()));
  LocalVariable* value_var =
      node->scope()->LookupVariable(Symbols::Value(), true);
  Value* value = Bind(new (Z) LoadLocalInstr(*value_var, node->token_pos()));
  StoreInstanceFieldInstr* store = new (Z) StoreInstanceFieldInstr(
      offset, receiver, value, emit_store_barrier, node->token_pos());
  Do(store);
  return new (Z) ConstantInstr(Object::ZoneHandle(Z, Object::null()));
}


void EffectGraphVisitor::VisitNativeBodyNode(NativeBodyNode* node) {
  const Function& function = owner()->function();
  const TokenPosition token_pos = node->token_pos();
  if (!function.IsClosureFunction()) {
    MethodRecognizer::Kind kind = MethodRecognizer::RecognizeKind(function);
    switch (kind) {
      case MethodRecognizer::kObjectEquals: {
        Value* receiver = Bind(BuildLoadThisVar(node->scope(), token_pos));
        LocalVariable* other_var =
            node->scope()->LookupVariable(Symbols::Other(),
                                          true);  // Test only.
        Value* other = Bind(new (Z) LoadLocalInstr(*other_var, token_pos));
        // Receiver is not a number because numbers override equality.
        const bool kNoNumberCheck = false;
        StrictCompareInstr* compare = new (Z) StrictCompareInstr(
            token_pos, Token::kEQ_STRICT, receiver, other, kNoNumberCheck);
        return ReturnDefinition(compare);
      }
      case MethodRecognizer::kStringBaseLength:
      case MethodRecognizer::kStringBaseIsEmpty: {
        // Treat length loads as mutable (i.e. affected by side effects) to
        // avoid hoisting them since we can't hoist the preceding class-check.
        // This is because of externalization of strings that affects their
        // class-id.
        LoadFieldInstr* load = BuildNativeGetter(
            node, MethodRecognizer::kStringBaseLength, String::length_offset(),
            Type::ZoneHandle(Z, Type::SmiType()), kSmiCid);
        load->set_is_immutable(!FLAG_support_externalizable_strings);
        if (kind == MethodRecognizer::kStringBaseLength) {
          return ReturnDefinition(load);
        }
        ASSERT(kind == MethodRecognizer::kStringBaseIsEmpty);
        Value* zero_val =
            Bind(new (Z) ConstantInstr(Smi::ZoneHandle(Z, Smi::New(0))));
        Value* load_val = Bind(load);
        StrictCompareInstr* compare = new (Z)
            StrictCompareInstr(token_pos, Token::kEQ_STRICT, load_val, zero_val,
                               false);  // No number check.
        return ReturnDefinition(compare);
      }
      case MethodRecognizer::kGrowableArrayLength:
      case MethodRecognizer::kObjectArrayLength:
      case MethodRecognizer::kImmutableArrayLength:
      case MethodRecognizer::kTypedDataLength: {
        LoadFieldInstr* load =
            BuildNativeGetter(node, kind, OffsetForLengthGetter(kind),
                              Type::ZoneHandle(Z, Type::SmiType()), kSmiCid);
        load->set_is_immutable(kind != MethodRecognizer::kGrowableArrayLength);
        return ReturnDefinition(load);
      }
      case MethodRecognizer::kClassIDgetID: {
        LocalVariable* value_var =
            node->scope()->LookupVariable(Symbols::Value(), true);
        Value* value = Bind(new (Z) LoadLocalInstr(*value_var, token_pos));
        LoadClassIdInstr* load = new (Z) LoadClassIdInstr(value);
        return ReturnDefinition(load);
      }
      case MethodRecognizer::kGrowableArrayCapacity: {
        Value* receiver = Bind(BuildLoadThisVar(node->scope(), token_pos));
        LoadFieldInstr* data_load =
            new (Z) LoadFieldInstr(receiver, Array::data_offset(),
                                   Object::dynamic_type(), node->token_pos());
        data_load->set_result_cid(kArrayCid);
        Value* data = Bind(data_load);
        LoadFieldInstr* length_load = new (Z) LoadFieldInstr(
            data, Array::length_offset(), Type::ZoneHandle(Z, Type::SmiType()),
            node->token_pos());
        length_load->set_result_cid(kSmiCid);
        length_load->set_recognized_kind(MethodRecognizer::kObjectArrayLength);
        return ReturnDefinition(length_load);
      }
      case MethodRecognizer::kObjectArrayAllocate: {
        LocalVariable* type_args_parameter = node->scope()->LookupVariable(
            Symbols::TypeArgumentsParameter(), true);
        Value* element_type =
            Bind(new (Z) LoadLocalInstr(*type_args_parameter, token_pos));
        LocalVariable* length_parameter =
            node->scope()->LookupVariable(Symbols::Length(), true);
        Value* length =
            Bind(new (Z) LoadLocalInstr(*length_parameter, token_pos));
        CreateArrayInstr* create_array =
            new CreateArrayInstr(token_pos, element_type, length);
        return ReturnDefinition(create_array);
      }
      case MethodRecognizer::kBigint_getDigits: {
        return ReturnDefinition(BuildNativeGetter(
            node, kind, Bigint::digits_offset(), Object::dynamic_type(),
            kTypedDataUint32ArrayCid));
      }
      case MethodRecognizer::kBigint_getUsed: {
        return ReturnDefinition(
            BuildNativeGetter(node, kind, Bigint::used_offset(),
                              Type::ZoneHandle(Z, Type::SmiType()), kSmiCid));
      }
      case MethodRecognizer::kLinkedHashMap_getIndex: {
        return ReturnDefinition(
            BuildNativeGetter(node, kind, LinkedHashMap::index_offset(),
                              Object::dynamic_type(), kDynamicCid));
      }
      case MethodRecognizer::kLinkedHashMap_setIndex: {
        return ReturnDefinition(DoNativeSetterStoreValue(
            node, LinkedHashMap::index_offset(), kEmitStoreBarrier));
      }
      case MethodRecognizer::kLinkedHashMap_getData: {
        return ReturnDefinition(
            BuildNativeGetter(node, kind, LinkedHashMap::data_offset(),
                              Object::dynamic_type(), kArrayCid));
      }
      case MethodRecognizer::kLinkedHashMap_setData: {
        return ReturnDefinition(DoNativeSetterStoreValue(
            node, LinkedHashMap::data_offset(), kEmitStoreBarrier));
      }
      case MethodRecognizer::kLinkedHashMap_getHashMask: {
        return ReturnDefinition(
            BuildNativeGetter(node, kind, LinkedHashMap::hash_mask_offset(),
                              Type::ZoneHandle(Z, Type::SmiType()), kSmiCid));
      }
      case MethodRecognizer::kLinkedHashMap_setHashMask: {
        // Smi field; no barrier needed.
        return ReturnDefinition(DoNativeSetterStoreValue(
            node, LinkedHashMap::hash_mask_offset(), kNoStoreBarrier));
      }
      case MethodRecognizer::kLinkedHashMap_getUsedData: {
        return ReturnDefinition(
            BuildNativeGetter(node, kind, LinkedHashMap::used_data_offset(),
                              Type::ZoneHandle(Z, Type::SmiType()), kSmiCid));
      }
      case MethodRecognizer::kLinkedHashMap_setUsedData: {
        // Smi field; no barrier needed.
        return ReturnDefinition(DoNativeSetterStoreValue(
            node, LinkedHashMap::used_data_offset(), kNoStoreBarrier));
      }
      case MethodRecognizer::kLinkedHashMap_getDeletedKeys: {
        return ReturnDefinition(
            BuildNativeGetter(node, kind, LinkedHashMap::deleted_keys_offset(),
                              Type::ZoneHandle(Z, Type::SmiType()), kSmiCid));
      }
      case MethodRecognizer::kLinkedHashMap_setDeletedKeys: {
        // Smi field; no barrier needed.
        return ReturnDefinition(DoNativeSetterStoreValue(
            node, LinkedHashMap::deleted_keys_offset(), kNoStoreBarrier));
      }
      case MethodRecognizer::kBigint_getNeg: {
        return ReturnDefinition(
            BuildNativeGetter(node, kind, Bigint::neg_offset(),
                              Type::ZoneHandle(Z, Type::BoolType()), kBoolCid));
      }
      default:
        break;
    }
  }
  InlineBailout("EffectGraphVisitor::VisitNativeBodyNode");
  NativeCallInstr* native_call = new (Z) NativeCallInstr(node);
  ReturnDefinition(native_call);
}


void EffectGraphVisitor::VisitPrimaryNode(PrimaryNode* node) {
  // PrimaryNodes are temporary during parsing.
  UNREACHABLE();
}


// <Expression> ::= LoadLocal { local: LocalVariable }
void EffectGraphVisitor::VisitLoadLocalNode(LoadLocalNode* node) {
  // Nothing to do.
}


void ValueGraphVisitor::VisitLoadLocalNode(LoadLocalNode* node) {
  Definition* load = BuildLoadLocal(node->local(), node->token_pos());
  ReturnDefinition(load);
}


// <Expression> ::= StoreLocal { local: LocalVariable
//                               value: <Expression> }
void EffectGraphVisitor::VisitStoreLocalNode(StoreLocalNode* node) {
  // If the right hand side is an expression that does not contain
  // a safe point for the debugger to stop, add an explicit stub
  // call. Exception: don't do this when assigning to or from internal
  // variables, or for generated code that has no source position.
  if (FLAG_support_debugger) {
    AstNode* rhs = node->value();
    if (rhs->IsAssignableNode()) {
      rhs = rhs->AsAssignableNode()->expr();
    }
    if ((rhs->IsLiteralNode() || rhs->IsLoadStaticFieldNode() ||
         (rhs->IsLoadLocalNode() &&
          !rhs->AsLoadLocalNode()->local().IsInternal()) ||
         rhs->IsClosureNode()) &&
        !node->local().IsInternal() && node->token_pos().IsDebugPause()) {
      AddInstruction(new (Z) DebugStepCheckInstr(
          node->token_pos(), RawPcDescriptors::kRuntimeCall));
    }
  }

  ValueGraphVisitor for_value(owner());
  node->value()->Visit(&for_value);
  Append(for_value);
  Value* store_value = for_value.value();
  if (Isolate::Current()->type_checks()) {
    store_value =
        BuildAssignableValue(node->value()->token_pos(), store_value,
                             node->local().type(), node->local().name());
  }
  Definition* store =
      BuildStoreLocal(node->local(), store_value, node->token_pos());
  ReturnDefinition(store);
}


void EffectGraphVisitor::VisitLoadInstanceFieldNode(
    LoadInstanceFieldNode* node) {
  ValueGraphVisitor for_instance(owner());
  node->instance()->Visit(&for_instance);
  Append(for_instance);
  LoadFieldInstr* load =
      new (Z) LoadFieldInstr(for_instance.value(), &node->field(),
                             AbstractType::ZoneHandle(Z, node->field().type()),
                             node->token_pos(), &owner()->parsed_function());
  ReturnDefinition(load);
}


void EffectGraphVisitor::VisitStoreInstanceFieldNode(
    StoreInstanceFieldNode* node) {
  const TokenPosition token_pos = node->token_pos();
  ValueGraphVisitor for_instance(owner());
  node->instance()->Visit(&for_instance);
  Append(for_instance);
  ValueGraphVisitor for_value(owner());
  node->value()->Visit(&for_value);
  Append(for_value);
  Value* store_value = for_value.value();
  if (isolate()->type_checks()) {
    const AbstractType& type =
        AbstractType::ZoneHandle(Z, node->field().type());
    const String& dst_name = String::ZoneHandle(Z, node->field().name());
    store_value = BuildAssignableValue(node->value()->token_pos(), store_value,
                                       type, dst_name);
  }

  if (isolate()->use_field_guards()) {
    store_value = Bind(BuildStoreExprTemp(store_value, token_pos));
    GuardFieldClassInstr* guard_field_class = new (Z) GuardFieldClassInstr(
        store_value, node->field(), thread()->GetNextDeoptId());
    AddInstruction(guard_field_class);
    store_value = Bind(BuildLoadExprTemp(token_pos));
    GuardFieldLengthInstr* guard_field_length = new (Z) GuardFieldLengthInstr(
        store_value, node->field(), thread()->GetNextDeoptId());
    AddInstruction(guard_field_length);
    store_value = Bind(BuildLoadExprTemp(token_pos));
  }
  StoreInstanceFieldInstr* store = new (Z)
      StoreInstanceFieldInstr(node->field(), for_instance.value(), store_value,
                              kEmitStoreBarrier, token_pos);
  // Maybe initializing unboxed store.
  store->set_is_initialization(node->is_initializer());
  ReturnDefinition(store);
}


void EffectGraphVisitor::VisitLoadStaticFieldNode(LoadStaticFieldNode* node) {
  const TokenPosition token_pos = node->token_pos();
  if (node->field().is_const()) {
    ASSERT(node->field().StaticValue() != Object::sentinel().raw());
    ASSERT(node->field().StaticValue() != Object::transition_sentinel().raw());
    Definition* result = new (Z) ConstantInstr(
        Instance::ZoneHandle(Z, node->field().StaticValue()), token_pos);
    return ReturnDefinition(result);
  }
  Value* field_value = Bind(new (Z) ConstantInstr(
      Field::ZoneHandle(Z, node->field().Original()), token_pos));
  LoadStaticFieldInstr* load =
      new (Z) LoadStaticFieldInstr(field_value, token_pos);
  ReturnDefinition(load);
}


Definition* EffectGraphVisitor::BuildStoreStaticField(
    StoreStaticFieldNode* node,
    bool result_is_needed,
    TokenPosition token_pos) {
  if (FLAG_support_debugger) {
    // If the right hand side is an expression that does not contain
    // a safe point for the debugger to stop, add an explicit stub
    // call.
    AstNode* rhs = node->value();
    if (rhs->IsAssignableNode()) {
      rhs = rhs->AsAssignableNode()->expr();
    }
    if ((rhs->IsLiteralNode() || rhs->IsLoadLocalNode() ||
         rhs->IsLoadStaticFieldNode() || rhs->IsClosureNode()) &&
        node->token_pos().IsDebugPause()) {
      AddInstruction(new (Z) DebugStepCheckInstr(
          node->token_pos(), RawPcDescriptors::kRuntimeCall));
    }
  }

  ValueGraphVisitor for_value(owner());
  node->value()->Visit(&for_value);
  Append(for_value);
  Value* store_value = NULL;
  if (result_is_needed) {
    store_value = Bind(BuildStoreExprTemp(for_value.value(), token_pos));
  } else {
    store_value = for_value.value();
  }
  StoreStaticFieldInstr* store =
      new (Z) StoreStaticFieldInstr(node->field(), store_value, token_pos);

  if (result_is_needed) {
    Do(store);
    return BuildLoadExprTemp(token_pos);
  } else {
    return store;
  }
}


void EffectGraphVisitor::VisitStoreStaticFieldNode(StoreStaticFieldNode* node) {
  ReturnDefinition(
      BuildStoreStaticField(node, kResultNotNeeded, node->token_pos()));
}


void ValueGraphVisitor::VisitStoreStaticFieldNode(StoreStaticFieldNode* node) {
  ReturnDefinition(
      BuildStoreStaticField(node, kResultNeeded, node->token_pos()));
}


void EffectGraphVisitor::VisitLoadIndexedNode(LoadIndexedNode* node) {
  Function* super_function = NULL;
  if (node->IsSuperLoad()) {
    // Resolve the load indexed operator in the super class.
    super_function = &Function::ZoneHandle(
        Z, Resolver::ResolveDynamicAnyArgs(Z, node->super_class(),
                                           Symbols::IndexToken()));
    if (super_function->IsNull()) {
      // Could not resolve super operator. Generate call noSuchMethod() of the
      // super class instead.
      ArgumentListNode* arguments = new (Z) ArgumentListNode(node->token_pos());
      arguments->Add(node->array());
      arguments->Add(node->index_expr());
      StaticCallInstr* call = BuildStaticNoSuchMethodCall(
          node->super_class(), node->array(), Symbols::IndexToken(), arguments,
          false,  // Don't save last arg.
          true);  // Super invocation.
      ReturnDefinition(call);
      return;
    }
  }
  ZoneGrowableArray<PushArgumentInstr*>* arguments =
      new (Z) ZoneGrowableArray<PushArgumentInstr*>(2);
  ValueGraphVisitor for_array(owner());
  node->array()->Visit(&for_array);
  Append(for_array);
  arguments->Add(PushArgument(for_array.value()));

  ValueGraphVisitor for_index(owner());
  node->index_expr()->Visit(&for_index);
  Append(for_index);
  arguments->Add(PushArgument(for_index.value()));

  if (super_function != NULL) {
    // Generate static call to super operator.
    StaticCallInstr* load = new (Z) StaticCallInstr(
        node->token_pos(), *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 (Z) InstanceCallInstr(
        node->token_pos(), Symbols::IndexToken(), Token::kINDEX, arguments,
        Object::null_array(), checked_argument_count, owner()->ic_data_array());
    ReturnDefinition(load);
  }
}


Definition* EffectGraphVisitor::BuildStoreIndexedValues(StoreIndexedNode* node,
                                                        bool result_is_needed) {
  Function* super_function = NULL;
  const TokenPosition token_pos = node->token_pos();
  if (node->IsSuperStore()) {
    // Resolve the store indexed operator in the super class.
    super_function = &Function::ZoneHandle(
        Z, Resolver::ResolveDynamicAnyArgs(Z, node->super_class(),
                                           Symbols::AssignIndexToken()));
    if (super_function->IsNull()) {
      // Could not resolve super operator. Generate call noSuchMethod() of the
      // super class instead.
      ArgumentListNode* arguments = new (Z) ArgumentListNode(token_pos);
      arguments->Add(node->array());
      arguments->Add(node->index_expr());
      arguments->Add(node->value());
      StaticCallInstr* call = BuildStaticNoSuchMethodCall(
          node->super_class(), node->array(), Symbols::AssignIndexToken(),
          arguments,
          result_is_needed,  // Save last arg if result is needed.
          true);             // Super invocation.
      if (result_is_needed) {
        Do(call);
        // BuildStaticNoSuchMethodCall stores the value in expression_temp.
        return BuildLoadExprTemp(token_pos);
      } else {
        return call;
      }
    }
  }

  ZoneGrowableArray<PushArgumentInstr*>* arguments =
      new (Z) ZoneGrowableArray<PushArgumentInstr*>(3);
  ValueGraphVisitor for_array(owner());
  node->array()->Visit(&for_array);
  Append(for_array);
  arguments->Add(PushArgument(for_array.value()));

  ValueGraphVisitor for_index(owner());
  node->index_expr()->Visit(&for_index);
  Append(for_index);
  arguments->Add(PushArgument(for_index.value()));

  ValueGraphVisitor for_value(owner());
  node->value()->Visit(&for_value);
  Append(for_value);
  Value* value = NULL;
  if (result_is_needed) {
    value = Bind(BuildStoreExprTemp(for_value.value(), token_pos));
  } else {
    value = for_value.value();
  }
  arguments->Add(PushArgument(value));

  if (super_function != NULL) {
    // Generate static call to super operator []=.

    StaticCallInstr* store = new (Z)
        StaticCallInstr(token_pos, *super_function, Object::null_array(),
                        arguments, owner()->ic_data_array());
    if (result_is_needed) {
      Do(store);
      return BuildLoadExprTemp(token_pos);
    } else {
      return store;
    }
  } else {
    // Generate dynamic call to operator []=.
    const intptr_t checked_argument_count = 2;  // Do not check for value type.
    InstanceCallInstr* store = new (Z) InstanceCallInstr(
        token_pos, Symbols::AssignIndexToken(), Token::kASSIGN_INDEX, arguments,
        Object::null_array(), checked_argument_count, owner()->ic_data_array());
    if (result_is_needed) {
      Do(store);
      return BuildLoadExprTemp(token_pos);
    } else {
      return store;
    }
  }
}


void EffectGraphVisitor::VisitStoreIndexedNode(StoreIndexedNode* node) {
  ReturnDefinition(BuildStoreIndexedValues(node, kResultNotNeeded));
}


void ValueGraphVisitor::VisitStoreIndexedNode(StoreIndexedNode* node) {
  ReturnDefinition(BuildStoreIndexedValues(node, kResultNeeded));
}


bool EffectGraphVisitor::HasContextScope() const {
  const ContextScope& context_scope =
      ContextScope::Handle(owner()->function().context_scope());
  return !context_scope.IsNull() && (context_scope.num_variables() > 0);
}


void EffectGraphVisitor::UnchainContexts(intptr_t n) {
  // TODO(johnmccutchan): Pass this in.
  const TokenPosition token_pos = TokenPosition::kContext;
  if (n > 0) {
    Value* context = Bind(BuildCurrentContext(token_pos));
    while (n-- > 0) {
      context = Bind(new (Z) LoadFieldInstr(context, Context::parent_offset(),
                                            // Not an instance, no type.
                                            Type::ZoneHandle(Z, Type::null()),
                                            token_pos));
    }
    Do(BuildStoreContext(context, token_pos));
  }
}


void EffectGraphVisitor::AdjustContextLevel(LocalScope* target_scope) {
  ASSERT(target_scope != NULL);
  intptr_t target_context_level = 0;
  if (target_scope->num_context_variables() > 0) {
    // The scope of the target label allocates a context, therefore its outer
    // scope is at a lower context level.
    target_context_level = target_scope->context_level() - 1;
  } else {
    // The scope of the target label does not allocate a context, so its outer
    // scope is at the same context level. Find it.
    while ((target_scope != NULL) &&
           (target_scope->num_context_variables() == 0)) {
      target_scope = target_scope->parent();
    }
    if (target_scope != NULL) {
      target_context_level = target_scope->context_level();
    }
  }
  ASSERT(target_context_level >= 0);
  intptr_t current_context_level = owner()->context_level();
  ASSERT(current_context_level >= target_context_level);
  UnchainContexts(current_context_level - target_context_level);
  // Record adjusted context level.
  owner()->nesting_stack()->AdjustContextLevel(target_context_level);
}


// <Statement> ::= Sequence { scope: LocalScope
//                            nodes: <Statement>*
//                            label: SourceLabel }
void EffectGraphVisitor::VisitSequenceNode(SequenceNode* node) {
  LocalScope* scope = node->scope();
  const Function& function = owner()->function();
  const intptr_t num_context_variables =
      (scope != NULL) ? scope->num_context_variables() : 0;
  const bool is_top_level_sequence =
      node == owner()->parsed_function().node_sequence();
  // The outermost function sequence cannot contain a label.
  ASSERT((node->label() == NULL) || !is_top_level_sequence);
  NestedBlock nested_block(owner(), node);

  if (num_context_variables > 0) {
    // The local scope declares variables that are captured.
    // Allocate and chain a new context (Except don't chain when at the function
    // entry if the function does not capture any variables from outer scopes).
    Value* allocated_context = Bind(
        new (Z) AllocateContextInstr(node->token_pos(), num_context_variables));
    {
      LocalVariable* tmp_var = EnterTempLocalScope(allocated_context);
      if (!is_top_level_sequence || HasContextScope()) {
        ASSERT(is_top_level_sequence ||
               (nested_block.ContextLevel() ==
                nested_block.outer()->ContextLevel() + 1));
        Value* tmp_val =
            Bind(new (Z) LoadLocalInstr(*tmp_var, node->token_pos()));
        Value* parent_context = Bind(BuildCurrentContext(node->token_pos()));
        Do(new (Z) StoreInstanceFieldInstr(Context::parent_offset(), tmp_val,
                                           parent_context, kEmitStoreBarrier,
                                           node->token_pos()));
      }
      Do(BuildStoreContext(Bind(ExitTempLocalScope(allocated_context)),
                           node->token_pos()));
    }

    // If this node_sequence is the body of the function being compiled, copy
    // the captured parameters from the frame into the context.
    if (is_top_level_sequence) {
      ASSERT(scope->context_level() == 1);
      const int num_params = function.NumParameters();
      int param_frame_index = (num_params == function.num_fixed_parameters())
                                  ? (kParamEndSlotFromFp + num_params)
                                  : kFirstLocalSlotFromFp;
      for (int pos = 0; pos < num_params; param_frame_index--, pos++) {
        const LocalVariable& parameter = *scope->VariableAt(pos);
        ASSERT(parameter.owner() == scope);
        if (parameter.is_captured()) {
          // Create a temporary local describing the original position.
          const String& temp_name = Symbols::TempParam();
          LocalVariable* temp_local =
              new (Z) LocalVariable(TokenPosition::kNoSource,  // Token index.
                                    TokenPosition::kNoSource,  // Token index.
                                    temp_name,
                                    Object::dynamic_type());  // Type.
          temp_local->set_index(param_frame_index);

          // Mark this local as captured parameter so that the optimizer
          // correctly handles these when compiling try-catch: Captured
          // parameters are not in the stack environment, therefore they
          // must be skipped when emitting sync-code in try-blocks.
          temp_local->set_is_captured_parameter(true);

          // Copy parameter from local frame to current context.
          Value* load = Bind(BuildLoadLocal(*temp_local, node->token_pos()));
          Do(BuildStoreLocal(parameter, load, ST(node->token_pos())));
          // Write NULL to the source location to detect buggy accesses and
          // allow GC of passed value if it gets overwritten by a new value in
          // the function.
          Value* null_constant = Bind(
              new (Z) ConstantInstr(Object::ZoneHandle(Z, Object::null())));
          Do(BuildStoreLocal(*temp_local, null_constant,
                             ST(node->token_pos())));
        }
      }
    }
  }

  if (FLAG_causal_async_stacks && is_top_level_sequence &&
      (function.IsAsyncClosure() || function.IsAsyncGenClosure())) {
    LocalScope* top_scope = node->scope();
    // Fetch the :async_stack_trace variable and store it into the thread.
    LocalVariable* async_stack_trace_var =
        top_scope->LookupVariable(Symbols::AsyncStackTraceVar(), false);
    ASSERT((async_stack_trace_var != NULL) &&
           async_stack_trace_var->is_captured());
    // Load :async_stack_trace
    Value* async_stack_trace_value = Bind(BuildLoadLocal(
        *async_stack_trace_var, node->token_pos().ToSynthetic()));
    // Setup arguments for _asyncSetThreadStackTrace.
    ZoneGrowableArray<PushArgumentInstr*>* arguments =
        new (Z) ZoneGrowableArray<PushArgumentInstr*>(1);
    arguments->Add(PushArgument(async_stack_trace_value));

    const Function& async_set_thread_stack_trace = Function::ZoneHandle(
        Z, isolate()->object_store()->async_set_thread_stack_trace());
    ASSERT(!async_set_thread_stack_trace.IsNull());
    // Call _asyncSetThreadStackTrace
    StaticCallInstr* call_async_set_thread_stack_trace = new (Z)
        StaticCallInstr(node->token_pos().ToSynthetic(),
                        async_set_thread_stack_trace, Object::null_array(),
                        arguments, owner()->ic_data_array());
    Do(call_async_set_thread_stack_trace);
  }


  if (FLAG_support_debugger && is_top_level_sequence &&
      function.is_debuggable()) {
    // Place a debug check at method entry to ensure breaking on a method always
    // happens, even if there are no assignments/calls/runtimecalls in the first
    // basic block. Place this check at the last parameter to ensure parameters
    // are in scope in the debugger at method entry.
    const int num_params = function.NumParameters();
    TokenPosition check_pos = TokenPosition::kNoSource;
    if (num_params > 0) {
      const LocalVariable& parameter = *scope->VariableAt(num_params - 1);
      check_pos = parameter.token_pos();
    }

    if (!check_pos.IsDebugPause()) {
      // No parameters or synthetic parameters.
      check_pos = node->token_pos();
      ASSERT(check_pos.IsDebugPause());
    }
    AddInstruction(
        new (Z) DebugStepCheckInstr(check_pos, RawPcDescriptors::kRuntimeCall));
  }

  // This check may be deleted if the generated code is leaf.
  // Native functions don't need a stack check at entry.
  if (is_top_level_sequence && !function.is_native()) {
    // Always allocate CheckOverflowInstr so that deopt-ids match regardless
    // if we inline or not.
    if (!function.IsImplicitGetterFunction() &&
        !function.IsImplicitSetterFunction()) {
      CheckStackOverflowInstr* check =
          new (Z) CheckStackOverflowInstr(node->token_pos(), 0);
      // If we are inlining don't actually attach the stack check. We must still
      // create the stack check in order to allocate a deopt id.
      if (!owner()->IsInlining()) {
        AddInstruction(check);
      }
    }
  }

  if (Isolate::Current()->type_checks() && is_top_level_sequence) {
    const int num_params = function.NumParameters();
    int pos = 0;
    if (function.IsFactory() || function.IsDynamicFunction() ||
        function.IsGenerativeConstructor()) {
      // Skip type checking of type arguments for factory functions.
      // Skip type checking of receiver for instance functions and constructors.
      pos = 1;
    }
    while (pos < num_params) {
      const LocalVariable& parameter = *scope->VariableAt(pos);
      ASSERT(parameter.owner() == scope);
      if (!CanSkipTypeCheck(parameter.token_pos(), NULL, parameter.type(),
                            parameter.name())) {
        Value* parameter_value =
            Bind(BuildLoadLocal(parameter, parameter.token_pos()));
        Do(BuildAssertAssignable(parameter.token_pos(), parameter_value,
                                 parameter.type(), parameter.name()));
      }
      pos++;
    }
  }

  // Continuation part:
  // If this node sequence is the body of a function with continuations,
  // leave room for a preamble.
  // The preamble is generated after visiting the body.
  GotoInstr* preamble_start = NULL;
  if (is_top_level_sequence &&
      (function.IsAsyncClosure() || function.IsSyncGenClosure() ||
       function.IsAsyncGenClosure())) {
    JoinEntryInstr* preamble_end = new (Z)
        JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index());
    ASSERT(exit() != NULL);
    exit()->Goto(preamble_end);
    ASSERT(exit()->next()->IsGoto());
    preamble_start = exit()->next()->AsGoto();
    ASSERT(preamble_start->IsGoto());
    exit_ = preamble_end;
  }

  intptr_t i = 0;
  while (is_open() && (i < node->length())) {
    EffectGraphVisitor for_effect(owner());
    node->NodeAt(i++)->Visit(&for_effect);
    Append(for_effect);
    if (!is_open()) {
      // E.g., because of a JumpNode.
      break;
    }
  }

  // Continuation part:
  // After generating the CFG for the body we can create the preamble
  // because we know exactly how many continuation states we need.
  if (is_top_level_sequence &&
      (function.IsAsyncClosure() || function.IsSyncGenClosure() ||
       function.IsAsyncGenClosure())) {
    ASSERT(preamble_start != NULL);
    // We are at the top level. Fetch the corresponding scope.
    LocalScope* top_scope = node->scope();
    LocalVariable* jump_var =
        top_scope->LookupVariable(Symbols::AwaitJumpVar(), false);
    ASSERT(jump_var != NULL && jump_var->is_captured());
    Instruction* saved_entry = entry_;
    Instruction* saved_exit = exit_;
    entry_ = NULL;
    exit_ = NULL;

    LoadLocalNode* load_jump_count =
        new (Z) LoadLocalNode(node->token_pos(), jump_var);
    ComparisonNode* check_jump_count;
    const intptr_t num_await_states = owner()->await_joins()->length();

    LocalVariable* old_context =
        top_scope->LookupVariable(Symbols::AwaitContextVar(), false);
    for (intptr_t i = 0; i < num_await_states; i++) {
      check_jump_count = new (Z)
          ComparisonNode(ST(node->token_pos()), Token::kEQ, load_jump_count,
                         new (Z) LiteralNode(ST(node->token_pos()),
                                             Smi::ZoneHandle(Z, Smi::New(i))));
      TestGraphVisitor for_test(owner(), ST(node->token_pos()));
      check_jump_count->Visit(&for_test);
      EffectGraphVisitor for_true(owner());
      EffectGraphVisitor for_false(owner());

      // Build async jump or sync yield jump.
      ASSERT(function.IsAsyncClosure() || function.IsAsyncGenClosure() ||
             function.IsSyncGenClosure());

      // Restore the saved continuation context, i.e. the context that was
      // saved into :await_ctx_var before the closure suspended.
      for_true.BuildRestoreContext(*old_context, ST(node->token_pos()));

      // Goto saved join.
      for_true.Goto((*owner()->await_joins())[i]);

      Join(for_test, for_true, for_false);
      if (i == 0) {
        // Manually link up the preamble start.
        preamble_start->previous()->set_next(for_test.entry());
        for_test.entry()->set_previous(preamble_start->previous());
      }
      if (i == (num_await_states - 1)) {
        // Link up preamble end.
        if (exit_ == NULL) {
          exit_ = preamble_start;
        } else {
          exit_->LinkTo(preamble_start);
        }
      }
    }
    entry_ = saved_entry;
    exit_ = saved_exit;
  }

  if (is_open() && (num_context_variables > 0) &&
      (!is_top_level_sequence || HasContextScope())) {
    UnchainContexts(1);
  }

  // If this node sequence is labeled, a break out of the sequence will have
  // taken care of unchaining the context.
  if (nested_block.break_target() != NULL) {
    if (is_open()) Goto(nested_block.break_target());
    exit_ = nested_block.break_target();
  }
}


void EffectGraphVisitor::VisitCatchClauseNode(CatchClauseNode* node) {
  InlineBailout("EffectGraphVisitor::VisitCatchClauseNode (exception)");
  // Restores current context from local variable ':saved_try_context_var'.
  BuildRestoreContext(node->context_var(), node->token_pos());

  EffectGraphVisitor for_catch(owner());
  node->VisitChildren(&for_catch);
  Append(for_catch);
}


void EffectGraphVisitor::VisitTryCatchNode(TryCatchNode* node) {
  InlineBailout("EffectGraphVisitor::VisitTryCatchNode (exception)");
  CatchClauseNode* catch_block = node->catch_block();
  SequenceNode* finally_block = node->finally_block();
  if ((finally_block != NULL) && (finally_block->length() == 0)) {
    SequenceNode* catch_sequence = catch_block->sequence();
    if (catch_sequence->length() == 1) {
      // Check for a single rethrow statement. This only matches the synthetic
      // catch-clause generated for try-finally.
      ThrowNode* throw_node = catch_sequence->NodeAt(0)->AsThrowNode();
      if ((throw_node != NULL) && (throw_node->stacktrace() != NULL)) {
        // Empty finally-block in a try-finally can be optimized away.
        EffectGraphVisitor for_try(owner());
        node->try_block()->Visit(&for_try);
        Append(for_try);
        return;
      }
    }
  }

  const intptr_t original_handler_index = owner()->try_index();
  const intptr_t try_handler_index = node->try_index();
  ASSERT(try_handler_index != original_handler_index);
  owner()->set_try_index(try_handler_index);

  // Preserve current context into local variable ':saved_try_context_var'.
  BuildSaveContext(node->context_var(), ST(node->token_pos()));

  EffectGraphVisitor for_try(owner());
  node->try_block()->Visit(&for_try);

  if (for_try.is_open()) {
    JoinEntryInstr* after_try = new (Z)
        JoinEntryInstr(owner()->AllocateBlockId(), original_handler_index);
    for_try.Goto(after_try);
    for_try.exit_ = after_try;
  }

  JoinEntryInstr* try_entry =
      new (Z) JoinEntryInstr(owner()->AllocateBlockId(), try_handler_index);

  Goto(try_entry);
  AppendFragment(try_entry, for_try);
  exit_ = for_try.exit_;

  // We are done generating code for the try block.
  owner()->set_try_index(original_handler_index);

  // If there is a finally block, it is the handler for code in the catch
  // block.
  const intptr_t catch_handler_index = (finally_block == NULL)
                                           ? original_handler_index
                                           : catch_block->catch_handler_index();

  const intptr_t prev_catch_try_index = owner()->catch_try_index();

  owner()->set_try_index(catch_handler_index);
  owner()->set_catch_try_index(try_handler_index);
  EffectGraphVisitor for_catch(owner());
  catch_block->Visit(&for_catch);
  owner()->set_catch_try_index(prev_catch_try_index);

  // NOTE: The implicit variables ':saved_try_context_var', ':exception_var'
  // and ':stack_trace_var' can never be captured variables.
  ASSERT(!catch_block->context_var().is_captured());
  ASSERT(!catch_block->exception_var().is_captured());
  ASSERT(!catch_block->stacktrace_var().is_captured());

  CatchBlockEntryInstr* catch_entry = new (Z) CatchBlockEntryInstr(
      catch_block->token_pos(), (node->token_pos() == TokenPosition::kNoSource),
      owner()->AllocateBlockId(), catch_handler_index, owner()->graph_entry(),
      catch_block->handler_types(), try_handler_index,
      catch_block->exception_var(), catch_block->stacktrace_var(),
      catch_block->needs_stacktrace(), Thread::Current()->GetNextDeoptId());
  owner()->AddCatchEntry(catch_entry);
  AppendFragment(catch_entry, for_catch);

  if (for_catch.is_open()) {
    JoinEntryInstr* join = new (Z)
        JoinEntryInstr(owner()->AllocateBlockId(), original_handler_index);
    for_catch.Goto(join);
    if (is_open()) Goto(join);
    exit_ = join;
  }

  if (finally_block != NULL) {
    ASSERT(node->rethrow_clause() != NULL);
    // Create a handler for the code in the catch block, containing the
    // code in the finally block.
    owner()->set_try_index(original_handler_index);
    EffectGraphVisitor for_finally(owner());
    for_finally.BuildRestoreContext(catch_block->context_var(),
                                    finally_block->token_pos());

    node->rethrow_clause()->Visit(&for_finally);
    if (for_finally.is_open()) {
      // Rethrow the exception.  Manually build the graph for rethrow.
      Value* exception = for_finally.Bind(for_finally.BuildLoadLocal(
          catch_block->rethrow_exception_var(), finally_block->token_pos()));
      for_finally.PushArgument(exception);
      Value* stacktrace = for_finally.Bind(for_finally.BuildLoadLocal(
          catch_block->rethrow_stacktrace_var(), finally_block->token_pos()));
      for_finally.PushArgument(stacktrace);
      for_finally.AddInstruction(
          new (Z) ReThrowInstr(catch_block->token_pos(), catch_handler_index));
      for_finally.CloseFragment();
    }
    ASSERT(!for_finally.is_open());

    const Array& types = Array::ZoneHandle(Z, Array::New(1, Heap::kOld));
    types.SetAt(0, Object::dynamic_type());
    CatchBlockEntryInstr* finally_entry = new (Z) CatchBlockEntryInstr(
        finally_block->token_pos(),
        true,  // this is not a catch block from user code.
        owner()->AllocateBlockId(), original_handler_index,
        owner()->graph_entry(), types, catch_handler_index,
        catch_block->exception_var(), catch_block->stacktrace_var(),
        catch_block->needs_stacktrace(), Thread::Current()->GetNextDeoptId());
    owner()->AddCatchEntry(finally_entry);
    AppendFragment(finally_entry, for_finally);
  }

  // Generate code for the finally block if one exists.
  if ((finally_block != NULL) && is_open()) {
    EffectGraphVisitor for_finally_block(owner());
    finally_block->Visit(&for_finally_block);
    Append(for_finally_block);
  }
}


// Looks up dynamic method noSuchMethod in target_class
// (including its super class chain) and builds a static call to it.
StaticCallInstr* EffectGraphVisitor::BuildStaticNoSuchMethodCall(
    const Class& target_class,
    AstNode* receiver,
    const String& method_name,
    ArgumentListNode* method_arguments,
    bool save_last_arg,
    bool is_super_invocation) {
  TokenPosition args_pos = method_arguments->token_pos();
  LocalVariable* temp = NULL;
  if (save_last_arg) {
    temp = owner()->parsed_function().expression_temp_var();
  }
  ArgumentListNode* args = Parser::BuildNoSuchMethodArguments(
      args_pos, method_name, *method_arguments, temp, is_super_invocation);
  // Make sure we resolve to a compatible noSuchMethod, otherwise call
  // noSuchMethod of class Object.
  const int kNumArguments = 2;
  ArgumentsDescriptor args_desc(
      Array::ZoneHandle(Z, ArgumentsDescriptor::New(kNumArguments)));
  Function& no_such_method_func = Function::ZoneHandle(
      Z, Resolver::ResolveDynamicForReceiverClass(
             target_class, Symbols::NoSuchMethod(), args_desc));
  if (no_such_method_func.IsNull()) {
    const Class& object_class =
        Class::ZoneHandle(Z, isolate()->object_store()->object_class());
    no_such_method_func = Resolver::ResolveDynamicForReceiverClass(
        object_class, Symbols::NoSuchMethod(), args_desc);
  }
  // We are guaranteed to find noSuchMethod of class Object.
  ASSERT(!no_such_method_func.IsNull());
  ZoneGrowableArray<PushArgumentInstr*>* push_arguments =
      new (Z) ZoneGrowableArray<PushArgumentInstr*>(2);
  BuildPushArguments(*args, push_arguments);
  return new (Z)
      StaticCallInstr(args_pos, no_such_method_func, Object::null_array(),
                      push_arguments, owner()->ic_data_array());
}


StaticCallInstr* EffectGraphVisitor::BuildThrowNoSuchMethodError(
    TokenPosition token_pos,
    const Class& function_class,
    const String& function_name,
    ArgumentListNode* function_arguments,
    int invocation_type) {
  ZoneGrowableArray<PushArgumentInstr*>* arguments =
      new (Z) ZoneGrowableArray<PushArgumentInstr*>();
  // Object receiver, actually a class literal of the unresolved method's owner.
  AbstractType& type = Type::ZoneHandle(
      Z,
      Type::New(function_class, TypeArguments::Handle(Z, TypeArguments::null()),
                token_pos, Heap::kOld));
  type ^= ClassFinalizer::FinalizeType(function_class, type);
  Value* receiver_value = Bind(new (Z) ConstantInstr(type));
  arguments->Add(PushArgument(receiver_value));
  // String memberName.
  const String& member_name =
      String::ZoneHandle(Z, Symbols::New(T, function_name));
  Value* member_name_value = Bind(new (Z) ConstantInstr(member_name));
  arguments->Add(PushArgument(member_name_value));
  // Smi invocation_type.
  Value* invocation_type_value = Bind(
      new (Z) ConstantInstr(Smi::ZoneHandle(Z, Smi::New(invocation_type))));
  arguments->Add(PushArgument(invocation_type_value));
  // List arguments.
  if (function_arguments == NULL) {
    Value* arguments_value =
        Bind(new (Z) ConstantInstr(Array::ZoneHandle(Z, Array::null())));
    arguments->Add(PushArgument(arguments_value));
  } else {
    ValueGraphVisitor array_val(owner());
    ArrayNode* array =
        new (Z) ArrayNode(token_pos, Type::ZoneHandle(Z, Type::ArrayType()),
                          function_arguments->nodes());
    array->Visit(&array_val);
    Append(array_val);
    arguments->Add(PushArgument(array_val.value()));
  }
  // List argumentNames.
  ConstantInstr* cinstr = new (Z) ConstantInstr(
      (function_arguments == NULL) ? Array::ZoneHandle(Z, Array::null())
                                   : function_arguments->names());
  Value* argument_names_value = Bind(cinstr);
  arguments->Add(PushArgument(argument_names_value));

  // List existingArgumentNames.
  Value* existing_argument_names_value =
      Bind(new (Z) ConstantInstr(Array::ZoneHandle(Z, Array::null())));
  arguments->Add(PushArgument(existing_argument_names_value));
  // Resolve and call NoSuchMethodError._throwNew.
  const Library& core_lib = Library::Handle(Z, Library::CoreLibrary());
  const Class& cls =
      Class::Handle(Z, core_lib.LookupClass(Symbols::NoSuchMethodError()));
  ASSERT(!cls.IsNull());
  const Function& func = Function::ZoneHandle(
      Z, Resolver::ResolveStatic(
             cls, Library::PrivateCoreLibName(Symbols::ThrowNew()),
             arguments->length(), Object::null_array()));
  ASSERT(!func.IsNull());
  return new (Z) StaticCallInstr(token_pos, func,
                                 Object::null_array(),  // No names.
                                 arguments, owner()->ic_data_array());
}


void EffectGraphVisitor::BuildThrowNode(ThrowNode* node) {
  if (FLAG_support_debugger) {
    if (node->exception()->IsLiteralNode() ||
        node->exception()->IsLoadLocalNode() ||
        node->exception()->IsLoadStaticFieldNode() ||
        node->exception()->IsClosureNode()) {
      AddInstruction(new (Z) DebugStepCheckInstr(
          node->token_pos(), RawPcDescriptors::kRuntimeCall));
    }
  }
  ValueGraphVisitor for_exception(owner());
  node->exception()->Visit(&for_exception);
  Append(for_exception);
  PushArgument(for_exception.value());
  Instruction* instr = NULL;
  if (node->stacktrace() == NULL) {
    instr = new (Z) ThrowInstr(node->token_pos());
  } else {
    ValueGraphVisitor for_stack_trace(owner());
    node->stacktrace()->Visit(&for_stack_trace);
    Append(for_stack_trace);
    PushArgument(for_stack_trace.value());
    instr = new (Z) ReThrowInstr(node->token_pos(), owner()->catch_try_index());
  }
  AddInstruction(instr);
}


void EffectGraphVisitor::VisitThrowNode(ThrowNode* node) {
  BuildThrowNode(node);
  CloseFragment();
}


// A throw cannot be part of an expression, however, the parser may replace
// certain expression nodes with a throw. In that case generate a literal null
// so that the fragment is not closed in the middle of an expression.
void ValueGraphVisitor::VisitThrowNode(ThrowNode* node) {
  BuildThrowNode(node);
  ReturnDefinition(
      new (Z) ConstantInstr(Instance::ZoneHandle(Z, Instance::null())));
}


void EffectGraphVisitor::VisitInlinedFinallyNode(InlinedFinallyNode* node) {
  InlineBailout("EffectGraphVisitor::VisitInlinedFinallyNode (exception)");
  const intptr_t try_index = owner()->try_index();
  if (try_index >= 0) {
    // We are about to generate code for an inlined finally block. Exceptions
    // thrown in this block of code should be treated as though they are
    // thrown not from the current try block but the outer try block if any.
    intptr_t outer_try_index = node->try_index();
    owner()->set_try_index(outer_try_index);
  }

  // Note: do not restore the saved_try_context here since the inlined
  // code is not reached via an exception handler, therefore the context is
  // always properly set on entry. In other words, the inlined finally clause is
  // never the target of a long jump that would find an uninitialized current
  // context variable.

  JoinEntryInstr* finally_entry =
      new (Z) JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index());
  EffectGraphVisitor for_finally_block(owner());
  for_finally_block.AdjustContextLevel(node->finally_block()->scope());
  node->finally_block()->Visit(&for_finally_block);

  if (try_index >= 0) {
    owner()->set_try_index(try_index);
  }

  if (for_finally_block.is_open()) {
    JoinEntryInstr* after_finally = new (Z)
        JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index());
    for_finally_block.Goto(after_finally);
    for_finally_block.exit_ = after_finally;
  }

  Goto(finally_entry);
  AppendFragment(finally_entry, for_finally_block);
  exit_ = for_finally_block.exit_;
}


void EffectGraphVisitor::VisitStopNode(StopNode* node) {
  AddInstruction(new (Z) StopInstr(node->message()));
}


FlowGraph* FlowGraphBuilder::BuildGraph() {
  VMTagScope tagScope(thread(), VMTag::kCompileFlowGraphBuilderTagId,
                      FLAG_profile_vm);
  if (FLAG_support_ast_printer && FLAG_print_ast &&
      FlowGraphPrinter::ShouldPrint(parsed_function().function())) {
    // Print the function ast before IL generation.
    AstPrinter ast_printer;
    ast_printer.PrintFunctionNodes(parsed_function());
  }
  if (FLAG_support_ast_printer && FLAG_print_scopes &&
      FlowGraphPrinter::ShouldPrint(parsed_function().function())) {
    AstPrinter ast_printer;
    ast_printer.PrintFunctionScope(parsed_function());
  }
  TargetEntryInstr* normal_entry = new (Z)
      TargetEntryInstr(AllocateBlockId(), CatchClauseNode::kInvalidTryIndex);
  graph_entry_ =
      new (Z) GraphEntryInstr(parsed_function(), normal_entry, osr_id_);
  EffectGraphVisitor for_effect(this);
  parsed_function().node_sequence()->Visit(&for_effect);
  AppendFragment(normal_entry, for_effect);
  // Check that the graph is properly terminated.
  ASSERT(!for_effect.is_open());

  // When compiling for OSR, use a depth first search to prune instructions
  // unreachable from the OSR entry. Catch entries are always considered
  // reachable, even if they become unreachable after OSR.
  if (osr_id_ != Compiler::kNoOSRDeoptId) {
    PruneUnreachable();
  }

  FlowGraph* graph =
      new (Z) FlowGraph(parsed_function(), graph_entry_, last_used_block_id_);
  graph->set_await_token_positions(await_token_positions_);
  return graph;
}


void FlowGraphBuilder::AppendAwaitTokenPosition(TokenPosition token_pos) {
  await_token_positions_->Add(token_pos);
}


void FlowGraphBuilder::PruneUnreachable() {
  ASSERT(osr_id_ != Compiler::kNoOSRDeoptId);
  BitVector* block_marks = new (Z) BitVector(Z, last_used_block_id_ + 1);
  bool found =
      graph_entry_->PruneUnreachable(graph_entry_, NULL, osr_id_, block_marks);
  ASSERT(found);
}


void FlowGraphBuilder::Bailout(const char* reason) const {
  parsed_function_.Bailout("FlowGraphBuilder", reason);
}

}  // namespace dart
