// Copyright (c) 2016, 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/kernel_binary_flowgraph.h"
#include "vm/compiler.h"
#include "vm/longjump.h"
#include "vm/object_store.h"

#if !defined(DART_PRECOMPILED_RUNTIME)

namespace dart {
namespace kernel {

#define Z (zone_)
#define H (translation_helper_)
#define T (type_translator_)
#define I Isolate::Current()

static bool IsStaticInitializer(const Function& function, Zone* zone) {
  return (function.kind() == RawFunction::kImplicitStaticFinalGetter) &&
         String::Handle(zone, function.name())
             .StartsWith(Symbols::InitPrefix());
}

void FunctionNodeHelper::ReadUntilExcluding(Field field) {
  if (field <= next_read_) return;

  // Ordered with fall-through.
  switch (next_read_) {
    case kStart: {
      Tag tag = builder_->ReadTag();  // read tag.
      ASSERT(tag == kFunctionNode);
      if (++next_read_ == field) return;
    }
    case kPosition:
      position_ = builder_->ReadPosition();  // read position.
      if (++next_read_ == field) return;
    case kEndPosition:
      end_position_ = builder_->ReadPosition();  // read end position.
      if (++next_read_ == field) return;
    case kAsyncMarker:
      async_marker_ = static_cast<AsyncMarker>(builder_->ReadByte());
      if (++next_read_ == field) return;
    case kDartAsyncMarker:
      dart_async_marker_ = static_cast<AsyncMarker>(
          builder_->ReadByte());  // read dart async marker.
      if (++next_read_ == field) return;
    case kTypeParameters:
      builder_->SkipTypeParametersList();  // read type parameters.
      if (++next_read_ == field) return;
    case kTotalParameterCount:
      total_parameter_count_ =
          builder_->ReadUInt();  // read total parameter count.
      if (++next_read_ == field) return;
    case kRequiredParameterCount:
      required_parameter_count_ =
          builder_->ReadUInt();  // read required parameter count.
      if (++next_read_ == field) return;
    case kPositionalParameters:
      builder_->SkipListOfVariableDeclarations();  // read positionals.
      if (++next_read_ == field) return;
    case kNamedParameters:
      builder_->SkipListOfVariableDeclarations();  // read named.
      if (++next_read_ == field) return;
    case kReturnType:
      builder_->SkipDartType();  // read return type.
      if (++next_read_ == field) return;
    case kBody:
      if (builder_->ReadTag() == kSomething)
        builder_->SkipStatement();  // read body.
      if (++next_read_ == field) return;
    case kEnd:
      return;
  }
}

void VariableDeclarationHelper::ReadUntilExcluding(Field field) {
  if (field <= next_read_) return;

  // Ordered with fall-through.
  switch (next_read_) {
    case kPosition:
      position_ = builder_->ReadPosition();  // read position.
      if (++next_read_ == field) return;
    case kEqualPosition:
      equals_position_ = builder_->ReadPosition();  // read equals position.
      if (++next_read_ == field) return;
    case kFlags:
      flags_ = builder_->ReadFlags();
      if (++next_read_ == field) return;
    case kNameIndex:
      name_index_ = builder_->ReadStringReference();  // read name index.
      if (++next_read_ == field) return;
    case kType:
      builder_->SkipDartType();  // read type.
      if (++next_read_ == field) return;
    case kInitializer:
      if (builder_->ReadTag() == kSomething)
        builder_->SkipExpression();  // read initializer.
      if (++next_read_ == field) return;
    case kEnd:
      return;
  }
}

FieldHelper::FieldHelper(StreamingFlowGraphBuilder* builder, intptr_t offset)
    : builder_(builder),
      next_read_(kStart),
      has_function_literal_initializer_(false) {
  builder_->SetOffset(offset);
}

void FieldHelper::ReadUntilExcluding(Field field,
                                     bool detect_function_literal_initializer) {
  if (field <= next_read_) return;

  // Ordered with fall-through.
  switch (next_read_) {
    case kStart: {
      Tag tag = builder_->ReadTag();  // read tag.
      ASSERT(tag == kField);
      if (++next_read_ == field) return;
    }
    case kCanonicalName:
      canonical_name_ =
          builder_->ReadCanonicalNameReference();  // read canonical_name.
      if (++next_read_ == field) return;
    case kPosition:
      position_ = builder_->ReadPosition(false);  // read position.
      if (++next_read_ == field) return;
    case kEndPosition:
      end_position_ = builder_->ReadPosition(false);  // read end position.
      if (++next_read_ == field) return;
    case kFlags:
      flags_ = builder_->ReadFlags();
      if (++next_read_ == field) return;
    case kName:
      builder_->SkipName();  // read name.
      if (++next_read_ == field) return;
    case kSourceUriIndex:
      source_uri_index_ = builder_->ReadUInt();  // read source_uri_index.
      builder_->current_script_id_ = source_uri_index_;
      builder_->record_token_position(position_);
      builder_->record_token_position(end_position_);
      if (++next_read_ == field) return;
    case kDocumentationCommentIndex:
      builder_->ReadStringReference();
      if (++next_read_ == field) return;
    case kAnnotations: {
      annotation_count_ = builder_->ReadListLength();  // read list length.
      for (intptr_t i = 0; i < annotation_count_; ++i) {
        builder_->SkipExpression();  // read ith expression.
      }
      if (++next_read_ == field) return;
    }
    case kType:
      builder_->SkipDartType();  // read type.
      if (++next_read_ == field) return;
    case kInitializer:
      if (builder_->ReadTag() == kSomething) {
        if (detect_function_literal_initializer &&
            builder_->PeekTag() == kFunctionExpression) {
          AlternativeReadingScope alt(builder_->reader_);
          Tag tag = builder_->ReadTag();
          ASSERT(tag == kFunctionExpression);
          builder_->ReadPosition();  // read position.

          FunctionNodeHelper helper(builder_);
          helper.ReadUntilIncluding(FunctionNodeHelper::kEndPosition);

          has_function_literal_initializer_ = true;
          function_literal_start_ = helper.position_;
          function_literal_end_ = helper.end_position_;
        }
        builder_->SkipExpression();  // read initializer.
      }
      if (++next_read_ == field) return;
    case kEnd:
      return;
  }
}

void ProcedureHelper::ReadUntilExcluding(Field field) {
  if (field <= next_read_) return;

  // Ordered with fall-through.
  switch (next_read_) {
    case kStart: {
      Tag tag = builder_->ReadTag();  // read tag.
      ASSERT(tag == kProcedure);
      if (++next_read_ == field) return;
    }
    case kCanonicalName:
      canonical_name_ =
          builder_->ReadCanonicalNameReference();  // read canonical_name.
      if (++next_read_ == field) return;
    case kPosition:
      position_ = builder_->ReadPosition(false);  // read position.
      if (++next_read_ == field) return;
    case kEndPosition:
      end_position_ = builder_->ReadPosition(false);  // read end position.
      if (++next_read_ == field) return;
    case kKind:
      kind_ = static_cast<Kind>(builder_->ReadByte());
      if (++next_read_ == field) return;
    case kFlags:
      flags_ = builder_->ReadFlags();
      if (++next_read_ == field) return;
    case kName:
      builder_->SkipName();  // read name.
      if (++next_read_ == field) return;
    case kSourceUriIndex:
      source_uri_index_ = builder_->ReadUInt();  // read source_uri_index.
      builder_->current_script_id_ = source_uri_index_;
      builder_->record_token_position(position_);
      builder_->record_token_position(end_position_);
      if (++next_read_ == field) return;
    case kDocumentationCommentIndex:
      builder_->ReadStringReference();
      if (++next_read_ == field) return;
    case kAnnotations: {
      annotation_count_ = builder_->ReadListLength();  // read list length.
      for (intptr_t i = 0; i < annotation_count_; ++i) {
        builder_->SkipExpression();  // read ith expression.
      }
      if (++next_read_ == field) return;
    }
    case kFunction:
      if (builder_->ReadTag() == kSomething)
        builder_->SkipFunctionNode();  // read function node.
      if (++next_read_ == field) return;
    case kEnd:
      return;
  }
}

void ConstructorHelper::ReadUntilExcluding(Field field) {
  if (field <= next_read_) return;

  // Ordered with fall-through.
  switch (next_read_) {
    case kStart: {
      Tag tag = builder_->ReadTag();  // read tag.
      ASSERT(tag == kConstructor);
      if (++next_read_ == field) return;
    }
    case kCanonicalName:
      canonical_name_ =
          builder_->ReadCanonicalNameReference();  // read canonical_name.
      if (++next_read_ == field) return;
    case kPosition:
      position_ = builder_->ReadPosition();  // read position.
      if (++next_read_ == field) return;
    case kEndPosition:
      end_position_ = builder_->ReadPosition();  // read end position.
      if (++next_read_ == field) return;
    case kFlags:
      flags_ = builder_->ReadFlags();
      if (++next_read_ == field) return;
    case kName:
      builder_->SkipName();  // read name.
      if (++next_read_ == field) return;
    case kDocumentationCommentIndex:
      builder_->ReadStringReference();
      if (++next_read_ == field) return;
    case kAnnotations: {
      annotation_count_ = builder_->ReadListLength();  // read list length.
      for (intptr_t i = 0; i < annotation_count_; ++i) {
        builder_->SkipExpression();  // read ith expression.
      }
      if (++next_read_ == field) return;
    }
    case kFunction:
      builder_->SkipFunctionNode();  // read function.
      if (++next_read_ == field) return;
    case kInitializers: {
      intptr_t list_length =
          builder_->ReadListLength();  // read initializers list length.
      for (intptr_t i = 0; i < list_length; i++) {
        Tag tag = builder_->ReadTag();
        builder_->ReadByte();  // read isSynthetic.
        switch (tag) {
          case kInvalidInitializer:
            continue;
          case kFieldInitializer:
            builder_->SkipCanonicalNameReference();  // read field_reference.
            builder_->SkipExpression();              // read value.
            continue;
          case kSuperInitializer:
            builder_->SkipCanonicalNameReference();  // read target_reference.
            builder_->SkipArguments();               // read arguments.
            continue;
          case kRedirectingInitializer:
            builder_->SkipCanonicalNameReference();  // read target_reference.
            builder_->SkipArguments();               // read arguments.
            continue;
          case kLocalInitializer:
            builder_->SkipVariableDeclaration();  // read variable.
            continue;
          default:
            UNREACHABLE();
        }
      }
      if (++next_read_ == field) return;
    }
    case kEnd:
      return;
  }
}

void ClassHelper::ReadUntilExcluding(Field field) {
  if (field <= next_read_) return;

  // Ordered with fall-through.
  switch (next_read_) {
    case kStart: {
      Tag tag = builder_->ReadTag();  // read tag.
      ASSERT(tag == kClass);
      if (++next_read_ == field) return;
    }
    case kCanonicalName:
      canonical_name_ =
          builder_->ReadCanonicalNameReference();  // read canonical_name.
      if (++next_read_ == field) return;
    case kPosition:
      position_ = builder_->ReadPosition(false);  // read position.
      if (++next_read_ == field) return;
    case kEndPosition:
      end_position_ = builder_->ReadPosition();  // read end position.
      if (++next_read_ == field) return;
    case kIsAbstract:
      is_abstract_ = builder_->ReadBool();  // read is_abstract.
      if (++next_read_ == field) return;
    case kNameIndex:
      name_index_ = builder_->ReadStringReference();  // read name index.
      if (++next_read_ == field) return;
    case kSourceUriIndex:
      source_uri_index_ = builder_->ReadUInt();  // read source_uri_index.
      builder_->current_script_id_ = source_uri_index_;
      builder_->record_token_position(position_);
      if (++next_read_ == field) return;
    case kDocumentationCommentIndex:
      builder_->ReadStringReference();
      if (++next_read_ == field) return;
    case kAnnotations: {
      annotation_count_ = builder_->ReadListLength();  // read list length.
      for (intptr_t i = 0; i < annotation_count_; ++i) {
        builder_->SkipExpression();  // read ith expression.
      }
      if (++next_read_ == field) return;
    }
    case kTypeParameters:
      builder_->SkipTypeParametersList();  // read type parameters.
      if (++next_read_ == field) return;
    case kSuperClass: {
      Tag type_tag = builder_->ReadTag();  // read super class type (part 1).
      if (type_tag == kSomething) {
        builder_->SkipDartType();  // read super class type (part 2).
      }
      if (++next_read_ == field) return;
    }
    case kMixinType: {
      Tag type_tag = builder_->ReadTag();  // read mixin type (part 1).
      if (type_tag == kSomething) {
        builder_->SkipDartType();  // read mixin type (part 2).
      }
      if (++next_read_ == field) return;
    }
    case kImplementedClasses:
      builder_->SkipListOfDartTypes();  // read implemented_classes.
      if (++next_read_ == field) return;
    case kFields: {
      intptr_t list_length =
          builder_->ReadListLength();  // read fields list length.
      for (intptr_t i = 0; i < list_length; i++) {
        FieldHelper field_helper(builder_);
        field_helper.ReadUntilExcluding(FieldHelper::kEnd);  // read field.
      }
      if (++next_read_ == field) return;
    }
    case kConstructors: {
      intptr_t list_length =
          builder_->ReadListLength();  // read constructors list length.
      for (intptr_t i = 0; i < list_length; i++) {
        ConstructorHelper constructor_helper(builder_);
        constructor_helper.ReadUntilExcluding(
            ConstructorHelper::kEnd);  // read constructor.
      }
      if (++next_read_ == field) return;
    }
    case kProcedures: {
      intptr_t list_length =
          builder_->ReadListLength();  // read procedures list length.
      for (intptr_t i = 0; i < list_length; i++) {
        ProcedureHelper procedure_helper(builder_);
        procedure_helper.ReadUntilExcluding(
            ProcedureHelper::kEnd);  // read procedure.
      }
      if (++next_read_ == field) return;
    }
    case kEnd:
      return;
  }
}

void LibraryHelper::ReadUntilExcluding(Field field) {
  if (field <= next_read_) return;

  // Ordered with fall-through.
  switch (next_read_) {
    case kFlags: {
      flags_ = builder_->ReadFlags();
      if (++next_read_ == field) return;
    }
    case kCanonicalName:
      canonical_name_ =
          builder_->ReadCanonicalNameReference();  // read canonical_name.
      if (++next_read_ == field) return;
    case kName:
      name_index_ = builder_->ReadStringReference();  // read name index.
      if (++next_read_ == field) return;
    case kSourceUriIndex:
      source_uri_index_ = builder_->ReadUInt();  // read source_uri_index.
      builder_->current_script_id_ = source_uri_index_;
      if (++next_read_ == field) return;
    case kAnnotations:
      builder_->SkipListOfExpressions();  // read annotations.
      if (++next_read_ == field) return;
    case kDependencies: {
      intptr_t dependency_count = builder_->ReadUInt();  // read list length.
      for (intptr_t i = 0; i < dependency_count; ++i) {
        builder_->SkipLibraryDependency();
      }
      if (++next_read_ == field) return;
    }
    case kParts: {
      intptr_t part_count = builder_->ReadUInt();  // read list length.
      for (intptr_t i = 0; i < part_count; ++i) {
        builder_->SkipLibraryPart();
      }
      if (++next_read_ == field) return;
    }
    case kTypedefs: {
      intptr_t typedef_count = builder_->ReadListLength();  // read list length.
      for (intptr_t i = 0; i < typedef_count; i++) {
        builder_->SkipLibraryTypedef();
      }
      if (++next_read_ == field) return;
    }
    case kClasses: {
      int class_count = builder_->ReadListLength();  // read list length.
      for (intptr_t i = 0; i < class_count; ++i) {
        ClassHelper class_helper(builder_);
        class_helper.ReadUntilExcluding(ClassHelper::kEnd);
      }
      if (++next_read_ == field) return;
    }
    case kToplevelField: {
      intptr_t field_count = builder_->ReadListLength();  // read list length.
      for (intptr_t i = 0; i < field_count; ++i) {
        FieldHelper field_helper(builder_);
        field_helper.ReadUntilExcluding(FieldHelper::kEnd);
      }
      if (++next_read_ == field) return;
    }
    case kToplevelProcedures: {
      intptr_t procedure_count =
          builder_->ReadListLength();  // read list length.
      for (intptr_t i = 0; i < procedure_count; ++i) {
        ProcedureHelper procedure_helper(builder_);
        procedure_helper.ReadUntilExcluding(ProcedureHelper::kEnd);
      }
      if (++next_read_ == field) return;
    }
    case kEnd:
      return;
  }
}

StreamingScopeBuilder::StreamingScopeBuilder(ParsedFunction* parsed_function,
                                             intptr_t relative_kernel_offset,
                                             const TypedData& data)
    : result_(NULL),
      parsed_function_(parsed_function),
      relative_kernel_offset_(relative_kernel_offset),
      translation_helper_(Thread::Current()),
      zone_(translation_helper_.zone()),
      current_function_scope_(NULL),
      scope_(NULL),
      depth_(0),
      name_index_(0),
      needs_expr_temp_(false),
      builder_(new StreamingFlowGraphBuilder(&translation_helper_,
                                             zone_,
                                             relative_kernel_offset,
                                             data)),
      type_translator_(builder_, /*finalize=*/true) {
  Script& script = Script::Handle(Z, parsed_function->function().script());
  H.SetStringOffsets(TypedData::Handle(Z, script.kernel_string_offsets()));
  H.SetStringData(TypedData::Handle(Z, script.kernel_string_data()));
  H.SetCanonicalNames(TypedData::Handle(Z, script.kernel_canonical_names()));
  type_translator_.active_class_ = &active_class_;
}

StreamingScopeBuilder::~StreamingScopeBuilder() {
  delete builder_;
}

ScopeBuildingResult* StreamingScopeBuilder::BuildScopes() {
  if (result_ != NULL) return result_;

  ASSERT(scope_ == NULL && depth_.loop_ == 0 && depth_.function_ == 0);
  result_ = new (Z) ScopeBuildingResult();

  const Function& function = parsed_function_->function();

  // Setup a [ActiveClassScope] and a [ActiveMemberScope] which will be used
  // e.g. for type translation.
  const Class& klass =
      Class::Handle(zone_, parsed_function_->function().Owner());

  Function& outermost_function = Function::Handle(Z);
  builder_->DiscoverEnclosingElements(Z, function, &outermost_function);

  ActiveClassScope active_class_scope(&active_class_, &klass);
  ActiveMemberScope active_member(&active_class_, &outermost_function);

  LocalScope* enclosing_scope = NULL;
  if (function.IsLocalFunction()) {
    enclosing_scope = LocalScope::RestoreOuterScope(
        ContextScope::Handle(Z, function.context_scope()));
  }
  current_function_scope_ = scope_ = new (Z) LocalScope(enclosing_scope, 0, 0);
  scope_->set_begin_token_pos(function.token_pos());
  scope_->set_end_token_pos(function.end_token_pos());

  // Add function type arguments variable before current context variable.
  if (FLAG_reify_generic_functions && function.IsGeneric()) {
    LocalVariable* type_args_var = MakeVariable(
        TokenPosition::kNoSource, TokenPosition::kNoSource,
        Symbols::FunctionTypeArgumentsVar(), AbstractType::dynamic_type());
    scope_->AddVariable(type_args_var);
    parsed_function_->set_function_type_arguments(type_args_var);
  }

  LocalVariable* context_var = parsed_function_->current_context_var();
  context_var->set_is_forced_stack();
  scope_->AddVariable(context_var);

  parsed_function_->SetNodeSequence(
      new SequenceNode(TokenPosition::kNoSource, scope_));

  builder_->SetOffset(0);

  FunctionNodeHelper function_node_helper(builder_);

  switch (function.kind()) {
    case RawFunction::kClosureFunction:
    case RawFunction::kImplicitClosureFunction:
    case RawFunction::kConvertedClosureFunction:
    case RawFunction::kRegularFunction:
    case RawFunction::kGetterFunction:
    case RawFunction::kSetterFunction:
    case RawFunction::kConstructor: {
      const Tag tag = builder_->PeekTag();
      builder_->ReadUntilFunctionNode();
      function_node_helper.ReadUntilExcluding(
          FunctionNodeHelper::kPositionalParameters);
      current_function_async_marker_ = function_node_helper.async_marker_;
      // NOTE: FunctionNode is read further below the if.

      intptr_t pos = 0;
      if (function.IsClosureFunction()) {
        LocalVariable* variable = MakeVariable(
            TokenPosition::kNoSource, TokenPosition::kNoSource,
            Symbols::ClosureParameter(), AbstractType::dynamic_type());
        variable->set_is_forced_stack();
        scope_->InsertParameterAt(pos++, variable);
      } else if (!function.is_static()) {
        // We use [is_static] instead of [IsStaticFunction] because the latter
        // returns `false` for constructors.
        Class& klass = Class::Handle(Z, function.Owner());
        Type& klass_type = H.GetCanonicalType(klass);
        LocalVariable* variable =
            MakeVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
                         Symbols::This(), klass_type);
        scope_->InsertParameterAt(pos++, variable);
        result_->this_variable = variable;

        // We visit instance field initializers because they might contain
        // [Let] expressions and we need to have a mapping.
        if (tag == kConstructor) {
          Class& parent_class = Class::Handle(Z, function.Owner());
          Array& class_fields = Array::Handle(Z, parent_class.fields());
          Field& class_field = Field::Handle(Z);
          for (intptr_t i = 0; i < class_fields.Length(); ++i) {
            class_field ^= class_fields.At(i);
            if (!class_field.is_static()) {
              TypedData& kernel_data =
                  TypedData::Handle(Z, class_field.kernel_data());
              ASSERT(!kernel_data.IsNull());
              AlternativeReadingScope alt(builder_->reader_, &kernel_data, 0);
              intptr_t saved_relative_kernel_offset_ = relative_kernel_offset_;
              relative_kernel_offset_ = class_field.kernel_offset();
              FieldHelper field_helper(builder_);
              field_helper.ReadUntilExcluding(FieldHelper::kInitializer);
              Tag initializer_tag =
                  builder_->ReadTag();  // read first part of initializer.
              if (initializer_tag == kSomething) {
                EnterScope(class_field.kernel_offset());
                VisitExpression();  // read initializer.
                ExitScope(field_helper.position_, field_helper.end_position_);
              }
              relative_kernel_offset_ = saved_relative_kernel_offset_;
            }
          }
        }
      } else if (function.IsFactory()) {
        LocalVariable* variable = MakeVariable(
            TokenPosition::kNoSource, TokenPosition::kNoSource,
            Symbols::TypeArgumentsParameter(), AbstractType::dynamic_type());
        scope_->InsertParameterAt(pos++, variable);
        result_->type_arguments_variable = variable;
      }

      // Continue reading FunctionNode:
      // read positional_parameters and named_parameters.
      AddPositionalAndNamedParameters(pos);

      // We generate a synthetic body for implicit closure functions - which
      // will forward the call to the real function.
      //     -> see BuildGraphOfImplicitClosureFunction
      if (!function.IsImplicitClosureFunction()) {
        builder_->SetOffset(0);
        first_body_token_position_ = TokenPosition::kNoSource;
        VisitNode();

        // TODO(jensj): HACK: Push the begin token to after any parameters to
        // avoid crash when breaking on definition line of async method in
        // debugger. It seems that another scope needs to be added
        // in which captures are made, but I can't make that work.
        // This 'solution' doesn't crash, but I cannot see the parameters at
        // that particular breakpoint either.
        // Also push the end token to after the "}" to avoid crashing on
        // stepping past the last line (to the "}" character).
        if (first_body_token_position_.IsReal()) {
          scope_->set_begin_token_pos(first_body_token_position_);
        }
        if (scope_->end_token_pos().IsReal()) {
          scope_->set_end_token_pos(scope_->end_token_pos().Next());
        }
      }
      break;
    }
    case RawFunction::kImplicitGetter:
    case RawFunction::kImplicitStaticFinalGetter:
    case RawFunction::kImplicitSetter: {
      ASSERT(builder_->PeekTag() == kField);
      if (IsStaticInitializer(function, Z)) {
        VisitNode();
        break;
      }
      bool is_setter = function.IsImplicitSetterFunction();
      bool is_method = !function.IsStaticFunction();
      intptr_t pos = 0;
      if (is_method) {
        Class& klass = Class::Handle(Z, function.Owner());
        Type& klass_type = H.GetCanonicalType(klass);
        LocalVariable* variable =
            MakeVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
                         Symbols::This(), klass_type);
        scope_->InsertParameterAt(pos++, variable);
        result_->this_variable = variable;
      }
      if (is_setter) {
        result_->setter_value =
            MakeVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
                         Symbols::Value(), AbstractType::dynamic_type());
        scope_->InsertParameterAt(pos++, result_->setter_value);
      }
      break;
    }
    case RawFunction::kMethodExtractor: {
      // Add a receiver parameter.  Though it is captured, we emit code to
      // explicitly copy it to a fixed offset in a freshly-allocated context
      // instead of using the generic code for regular functions.
      // Therefore, it isn't necessary to mark it as captured here.
      Class& klass = Class::Handle(Z, function.Owner());
      Type& klass_type = H.GetCanonicalType(klass);
      LocalVariable* variable =
          MakeVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
                       Symbols::This(), klass_type);
      scope_->InsertParameterAt(0, variable);
      result_->this_variable = variable;
      break;
    }
    case RawFunction::kNoSuchMethodDispatcher:
    case RawFunction::kInvokeFieldDispatcher:
      for (intptr_t i = 0; i < function.NumParameters(); ++i) {
        LocalVariable* variable =
            MakeVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
                         String::ZoneHandle(Z, function.ParameterNameAt(i)),
                         AbstractType::dynamic_type());
        scope_->InsertParameterAt(i, variable);
      }
      break;
    case RawFunction::kSignatureFunction:
    case RawFunction::kIrregexpFunction:
      UNREACHABLE();
  }
  if (needs_expr_temp_) {
    scope_->AddVariable(parsed_function_->EnsureExpressionTemp());
  }
  parsed_function_->AllocateVariables();

  return result_;
}

void StreamingScopeBuilder::VisitNode() {
  Tag tag = builder_->PeekTag();
  switch (tag) {
    case kConstructor:
      VisitConstructor();
      return;
    case kProcedure:
      VisitProcedure();
      return;
    case kField:
      VisitField();
      return;
    case kFunctionNode:
      VisitFunctionNode();
      return;
    default:
      UNIMPLEMENTED();
      return;
  }
}

void StreamingScopeBuilder::VisitConstructor() {
  // Field initializers that come from non-static field declarations are
  // compiled as if they appear in the constructor initializer list.  This is
  // important for closure-valued field initializers because the VM expects the
  // corresponding closure functions to appear as if they were nested inside the
  // constructor.
  ConstructorHelper constructor_helper(builder_);
  constructor_helper.ReadUntilExcluding(ConstructorHelper::kFunction);
  {
    const Function& function = parsed_function_->function();
    Class& parent_class = Class::Handle(Z, function.Owner());
    Array& class_fields = Array::Handle(Z, parent_class.fields());
    Field& class_field = Field::Handle(Z);
    for (intptr_t i = 0; i < class_fields.Length(); ++i) {
      class_field ^= class_fields.At(i);
      if (!class_field.is_static()) {
        TypedData& kernel_data =
            TypedData::Handle(Z, class_field.kernel_data());
        ASSERT(!kernel_data.IsNull());
        AlternativeReadingScope alt(builder_->reader_, &kernel_data, 0);
        intptr_t saved_relative_kernel_offset_ = relative_kernel_offset_;
        relative_kernel_offset_ = class_field.kernel_offset();
        FieldHelper field_helper(builder_);
        field_helper.ReadUntilExcluding(FieldHelper::kInitializer);
        Tag initializer_tag = builder_->ReadTag();
        if (initializer_tag == kSomething) {
          VisitExpression();  // read initializer.
        }
        relative_kernel_offset_ = saved_relative_kernel_offset_;
      }
    }
  }

  // Visit children (note that there's no reason to visit the name).
  VisitFunctionNode();
  intptr_t list_length =
      builder_->ReadListLength();  // read initializers list length.
  for (intptr_t i = 0; i < list_length; i++) {
    VisitInitializer();
  }
}

void StreamingScopeBuilder::VisitProcedure() {
  ProcedureHelper procedure_helper(builder_);
  procedure_helper.ReadUntilExcluding(ProcedureHelper::kFunction);
  if (builder_->ReadTag() == kSomething) {
    VisitFunctionNode();
  }
}

void StreamingScopeBuilder::VisitField() {
  FieldHelper field_helper(builder_);
  field_helper.ReadUntilExcluding(FieldHelper::kType);
  VisitDartType();                // read type.
  Tag tag = builder_->ReadTag();  // read initializer (part 1).
  if (tag == kSomething) {
    VisitExpression();  // read initializer (part 2).
  }
}

void StreamingScopeBuilder::VisitFunctionNode() {
  FunctionNodeHelper function_node_helper(builder_);
  function_node_helper.ReadUntilExcluding(FunctionNodeHelper::kTypeParameters);

  intptr_t list_length =
      builder_->ReadListLength();  // read type_parameters list length.
  for (intptr_t i = 0; i < list_length; ++i) {
    builder_->SkipStringReference();  // read ith name index.
    VisitDartType();                  // read ith bound.
  }
  function_node_helper.SetJustRead(FunctionNodeHelper::kTypeParameters);

  if (FLAG_causal_async_stacks &&
      (function_node_helper.dart_async_marker_ == FunctionNodeHelper::kAsync ||
       function_node_helper.dart_async_marker_ ==
           FunctionNodeHelper::kAsyncStar)) {
    LocalVariable* asyncStackTraceVar = MakeVariable(
        TokenPosition::kNoSource, TokenPosition::kNoSource,
        Symbols::AsyncStackTraceVar(), AbstractType::dynamic_type());
    scope_->AddVariable(asyncStackTraceVar);
  }

  if (function_node_helper.async_marker_ == FunctionNodeHelper::kSyncYielding) {
    LocalScope* scope = parsed_function_->node_sequence()->scope();
    intptr_t offset = parsed_function_->function().num_fixed_parameters();
    for (intptr_t i = 0;
         i < parsed_function_->function().NumOptionalPositionalParameters();
         i++) {
      scope->VariableAt(offset + i)->set_is_forced_stack();
    }
  }

  // Read (but don't visit) the positional and named parameters, because they've
  // already been added to the scope.
  function_node_helper.ReadUntilExcluding(FunctionNodeHelper::kBody);

  if (builder_->ReadTag() == kSomething) {
    PositionScope scope(builder_->reader_);
    VisitStatement();  // Read body
    first_body_token_position_ = builder_->reader_->min_position();
  }

  // Ensure that :await_jump_var, :await_ctx_var, :async_op and
  // :async_stack_trace are captured.
  if (function_node_helper.async_marker_ == FunctionNodeHelper::kSyncYielding) {
    {
      LocalVariable* temp = NULL;
      LookupCapturedVariableByName(
          (depth_.function_ == 0) ? &result_->yield_jump_variable : &temp,
          Symbols::AwaitJumpVar());
    }
    {
      LocalVariable* temp = NULL;
      LookupCapturedVariableByName(
          (depth_.function_ == 0) ? &result_->yield_context_variable : &temp,
          Symbols::AwaitContextVar());
    }
    {
      LocalVariable* temp =
          scope_->LookupVariable(Symbols::AsyncOperation(), true);
      if (temp != NULL) {
        scope_->CaptureVariable(temp);
      }
    }
    if (FLAG_causal_async_stacks) {
      LocalVariable* temp =
          scope_->LookupVariable(Symbols::AsyncStackTraceVar(), true);
      if (temp != NULL) {
        scope_->CaptureVariable(temp);
      }
    }
  }
}

void StreamingScopeBuilder::VisitInitializer() {
  Tag tag = builder_->ReadTag();
  builder_->ReadByte();  // read isSynthetic flag.
  switch (tag) {
    case kInvalidInitializer:
      return;
    case kFieldInitializer:
      builder_->SkipCanonicalNameReference();  // read field_reference.
      VisitExpression();                       // read value.
      return;
    case kSuperInitializer:
      builder_->SkipCanonicalNameReference();  // read target_reference.
      VisitArguments();                        // read arguments.
      return;
    case kRedirectingInitializer:
      builder_->SkipCanonicalNameReference();  // read target_reference.
      VisitArguments();                        // read arguments.
      return;
    case kLocalInitializer:
      VisitVariableDeclaration();  // read variable.
      return;
    default:
      UNREACHABLE();
  }
}

void StreamingScopeBuilder::VisitExpression() {
  uint8_t payload = 0;
  Tag tag = builder_->ReadTag(&payload);
  switch (tag) {
    case kInvalidExpression:
      return;
    case kVariableGet: {
      builder_->ReadPosition();  // read position.
      intptr_t variable_kernel_offset =
          builder_->ReadUInt();          // read kernel position.
      builder_->ReadUInt();              // read relative variable index.
      builder_->SkipOptionalDartType();  // read promoted type.
      LookupVariable(variable_kernel_offset);
      return;
    }
    case kSpecializedVariableGet: {
      builder_->ReadPosition();  // read position.
      intptr_t variable_kernel_offset =
          builder_->ReadUInt();  // read kernel position.
      LookupVariable(variable_kernel_offset);
      return;
    }
    case kVariableSet: {
      builder_->ReadPosition();  // read position.
      intptr_t variable_kernel_offset =
          builder_->ReadUInt();  // read kernel position.
      builder_->ReadUInt();      // read relative variable index.
      LookupVariable(variable_kernel_offset);
      VisitExpression();  // read expression.
      return;
    }
    case kSpecializedVariableSet: {
      builder_->ReadPosition();  // read position.
      intptr_t variable_kernel_offset =
          builder_->ReadUInt();  // read kernel position.
      LookupVariable(variable_kernel_offset);
      VisitExpression();  // read expression.
      return;
    }
    case kPropertyGet:
      builder_->ReadPosition();  // read position.
      VisitExpression();         // read receiver.
      builder_->SkipName();      // read name.
      // read interface_target_reference.
      builder_->SkipCanonicalNameReference();
      return;
    case kPropertySet:
      builder_->ReadPosition();  // read position.
      VisitExpression();         // read receiver.
      builder_->SkipName();      // read name.
      VisitExpression();         // read value.
      // read interface_target_reference.
      builder_->SkipCanonicalNameReference();
      return;
    case kDirectPropertyGet:
      builder_->ReadPosition();                // read position.
      VisitExpression();                       // read receiver.
      builder_->SkipCanonicalNameReference();  // read target_reference.
      return;
    case kDirectPropertySet:
      builder_->ReadPosition();                // read position.
      VisitExpression();                       // read receiver.
      builder_->SkipCanonicalNameReference();  // read target_reference.
      VisitExpression();                       // read value·
      return;
    case kStaticGet:
      builder_->ReadPosition();                // read position.
      builder_->SkipCanonicalNameReference();  // read target_reference.
      return;
    case kStaticSet:
      builder_->ReadPosition();                // read position.
      builder_->SkipCanonicalNameReference();  // read target_reference.
      VisitExpression();                       // read expression.
      return;
    case kMethodInvocation:
      builder_->ReadPosition();  // read position.
      VisitExpression();         // read receiver.
      builder_->SkipName();      // read name.
      VisitArguments();          // read arguments.
      // read interface_target_reference.
      builder_->SkipCanonicalNameReference();
      return;
    case kDirectMethodInvocation:
      VisitExpression();                       // read receiver.
      builder_->SkipCanonicalNameReference();  // read target_reference.
      VisitArguments();                        // read arguments.
      return;
    case kStaticInvocation:
    case kConstStaticInvocation:
      builder_->ReadPosition();                // read position.
      builder_->SkipCanonicalNameReference();  // read procedure_reference.
      VisitArguments();                        // read arguments.
      return;
    case kConstructorInvocation:
    case kConstConstructorInvocation:
      builder_->ReadPosition();                // read position.
      builder_->SkipCanonicalNameReference();  // read target_reference.
      VisitArguments();                        // read arguments.
      return;
    case kNot:
      VisitExpression();  // read expression.
      return;
    case kLogicalExpression:
      needs_expr_temp_ = true;
      VisitExpression();       // read left.
      builder_->SkipBytes(1);  // read operator.
      VisitExpression();       // read right.
      return;
    case kConditionalExpression: {
      needs_expr_temp_ = true;
      VisitExpression();                 // read condition.
      VisitExpression();                 // read then.
      VisitExpression();                 // read otherwise.
      builder_->SkipOptionalDartType();  // read unused static type.
      return;
    }
    case kStringConcatenation: {
      builder_->ReadPosition();                           // read position.
      intptr_t list_length = builder_->ReadListLength();  // read list length.
      for (intptr_t i = 0; i < list_length; ++i) {
        VisitExpression();  // read ith expression.
      }
      return;
    }
    case kIsExpression:
      builder_->ReadPosition();  // read position.
      VisitExpression();         // read operand.
      VisitDartType();           // read type.
      return;
    case kAsExpression:
      builder_->ReadPosition();  // read position.
      VisitExpression();         // read operand.
      VisitDartType();           // read type.
      return;
    case kSymbolLiteral:
      builder_->SkipStringReference();  // read index into string table.
      return;
    case kTypeLiteral:
      VisitDartType();  // read type.
      return;
    case kThisExpression:
      HandleSpecialLoad(&result_->this_variable, Symbols::This());
      return;
    case kRethrow:
      builder_->ReadPosition();  // read position.
      return;
    case kThrow:
      builder_->ReadPosition();  // read position.
      VisitExpression();         // read expression.
      return;
    case kListLiteral:
    case kConstListLiteral: {
      builder_->ReadPosition();                           // read position.
      VisitDartType();                                    // read type.
      intptr_t list_length = builder_->ReadListLength();  // read list length.
      for (intptr_t i = 0; i < list_length; ++i) {
        VisitExpression();  // read ith expression.
      }
      return;
    }
    case kMapLiteral:
    case kConstMapLiteral: {
      builder_->ReadPosition();                           // read position.
      VisitDartType();                                    // read key type.
      VisitDartType();                                    // read value type.
      intptr_t list_length = builder_->ReadListLength();  // read list length.
      for (intptr_t i = 0; i < list_length; ++i) {
        VisitExpression();  // read ith key.
        VisitExpression();  // read ith value.
      }
      return;
    }
    case kFunctionExpression: {
      intptr_t offset =
          builder_->ReaderOffset() - 1;  // -1 to include tag byte.
      builder_->ReadPosition();          // read position.
      HandleLocalFunction(offset);       // read function node.
      return;
    }
    case kLet: {
      PositionScope scope(builder_->reader_);
      intptr_t offset =
          builder_->ReaderOffset() - 1;  // -1 to include tag byte.

      EnterScope(relative_kernel_offset_ + offset);

      VisitVariableDeclaration();  // read variable declaration.
      VisitExpression();           // read expression.

      ExitScope(builder_->reader_->min_position(),
                builder_->reader_->max_position());
      return;
    }
    case kBigIntLiteral:
      builder_->SkipStringReference();  // read string reference.
      return;
    case kStringLiteral:
      builder_->SkipStringReference();  // read string reference.
      return;
    case kSpecialIntLiteral:
      return;
    case kNegativeIntLiteral:
      builder_->ReadUInt();  // read value.
      return;
    case kPositiveIntLiteral:
      builder_->ReadUInt();  // read value.
      return;
    case kDoubleLiteral:
      builder_->SkipStringReference();  // read index into string table.
      return;
    case kTrueLiteral:
      return;
    case kFalseLiteral:
      return;
    case kNullLiteral:
      return;
    case kVectorCreation:
      builder_->ReadUInt();  // read size.
      return;
    case kVectorGet:
      VisitExpression();     // read expression.
      builder_->ReadUInt();  // read index.
      return;
    case kVectorSet:
      VisitExpression();     // read vector expression.
      builder_->ReadUInt();  // read index.
      VisitExpression();     // read value.
      return;
    case kVectorCopy:
      VisitExpression();  // read vector expression.
      return;
    case kClosureCreation:
      builder_->SkipCanonicalNameReference();  // read function reference.
      VisitExpression();                       // read context vector.
      VisitDartType();                  // read function type of the closure.
      builder_->SkipListOfDartTypes();  // read type arguments.
      return;
    default:
      UNREACHABLE();
  }
}

void StreamingScopeBuilder::VisitStatement() {
  Tag tag = builder_->ReadTag();  // read tag.
  switch (tag) {
    case kInvalidStatement:
      return;
    case kExpressionStatement:
      VisitExpression();  // read expression.
      return;
    case kBlock: {
      PositionScope scope(builder_->reader_);
      intptr_t offset =
          builder_->ReaderOffset() - 1;  // -1 to include tag byte.

      EnterScope(relative_kernel_offset_ + offset);

      intptr_t list_length =
          builder_->ReadListLength();  // read number of statements.
      for (intptr_t i = 0; i < list_length; ++i) {
        VisitStatement();  // read ith statement.
      }

      ExitScope(builder_->reader_->min_position(),
                builder_->reader_->max_position());
      return;
    }
    case kEmptyStatement:
      return;
    case kAssertStatement: {
      if (I->asserts()) {
        VisitExpression();              // Read condition.
        builder_->ReadPosition();       // read condition start offset.
        builder_->ReadPosition();       // read condition end offset.
        Tag tag = builder_->ReadTag();  // read (first part of) message.
        if (tag == kSomething) {
          VisitExpression();  // read (rest of) message.
        }
      } else {
        builder_->SkipExpression();     // Read condition.
        builder_->ReadPosition();       // read condition start offset.
        builder_->ReadPosition();       // read condition end offset.
        Tag tag = builder_->ReadTag();  // read (first part of) message.
        if (tag == kSomething) {
          builder_->SkipExpression();  // read (rest of) message.
        }
      }
      return;
    }
    case kLabeledStatement:
      VisitStatement();  // read body.
      return;
    case kBreakStatement:
      builder_->ReadPosition();  // read position.
      builder_->ReadUInt();      // read target_index.
      return;
    case kWhileStatement:
      ++depth_.loop_;
      builder_->ReadPosition();  // read position.
      VisitExpression();  // read condition.
      VisitStatement();   // read body.
      --depth_.loop_;
      return;
    case kDoStatement:
      ++depth_.loop_;
      builder_->ReadPosition();  // read position.
      VisitStatement();   // read body.
      VisitExpression();  // read condition.
      --depth_.loop_;
      return;
    case kForStatement: {
      PositionScope scope(builder_->reader_);

      intptr_t offset =
          builder_->ReaderOffset() - 1;  // -1 to include tag byte.

      EnterScope(relative_kernel_offset_ + offset);

      TokenPosition position = builder_->ReadPosition();  // read position.
      intptr_t list_length =
          builder_->ReadListLength();  // read number of variables.
      for (intptr_t i = 0; i < list_length; ++i) {
        VisitVariableDeclaration();  // read ith variable.
      }

      ++depth_.loop_;

      Tag tag = builder_->ReadTag();  // Read first part of condition.
      if (tag == kSomething) {
        VisitExpression();  // read rest of condition.
      }
      list_length = builder_->ReadListLength();  // read number of updates.
      for (intptr_t i = 0; i < list_length; ++i) {
        VisitExpression();  // read ith update.
      }
      VisitStatement();  // read body.

      --depth_.loop_;

      ExitScope(position, builder_->reader_->max_position());
      return;
    }
    case kForInStatement:
    case kAsyncForInStatement: {
      PositionScope scope(builder_->reader_);

      intptr_t start_offset =
          builder_->ReaderOffset() - 1;  // -1 to include tag byte.

      builder_->ReadPosition();  // read position.
      TokenPosition body_position =
          builder_->ReadPosition();  // read body position.

      // Notice the ordering: We skip the variable, read the iterable, go back,
      // re-read the variable, go forward to after having read the iterable.
      intptr_t offset = builder_->ReaderOffset();
      builder_->SkipVariableDeclaration();  // read variable.
      VisitExpression();                    // read iterable.

      ++depth_.for_in_;
      AddIteratorVariable();
      ++depth_.loop_;
      EnterScope(relative_kernel_offset_ + start_offset);

      {
        AlternativeReadingScope alt(builder_->reader_, offset);
        VisitVariableDeclaration();  // read variable.
      }
      VisitStatement();  // read body.

      if (!body_position.IsReal()) {
        body_position = builder_->reader_->min_position();
      }
      // TODO(jensj): From kernel_binary.cc
      // forinstmt->variable_->set_end_position(forinstmt->position_);
      ExitScope(body_position, builder_->reader_->max_position());
      --depth_.loop_;
      --depth_.for_in_;
      return;
    }
    case kSwitchStatement: {
      AddSwitchVariable();
      VisitExpression();                            // read condition.
      int case_count = builder_->ReadListLength();  // read number of cases.
      for (intptr_t i = 0; i < case_count; ++i) {
        int expression_count =
            builder_->ReadListLength();  // read number of expressions.
        for (intptr_t j = 0; j < expression_count; ++j) {
          builder_->ReadPosition();  // read jth position.
          VisitExpression();         // read jth expression.
        }
        builder_->ReadBool();  // read is_default.
        VisitStatement();      // read body.
      }
      return;
    }
    case kContinueSwitchStatement:
      builder_->ReadUInt();  // read target_index.
      return;
    case kIfStatement:
      VisitExpression();  // read condition.
      VisitStatement();   // read then.
      VisitStatement();   // read otherwise.
      return;
    case kReturnStatement: {
      if ((depth_.function_ == 0) && (depth_.finally_ > 0) &&
          (result_->finally_return_variable == NULL)) {
        const String& name = H.DartSymbol(":try_finally_return_value");
        LocalVariable* variable =
            MakeVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
                         name, AbstractType::dynamic_type());
        current_function_scope_->AddVariable(variable);
        result_->finally_return_variable = variable;
      }

      builder_->ReadPosition();       // read position
      Tag tag = builder_->ReadTag();  // read (first part of) expression.
      if (tag == kSomething) {
        VisitExpression();  // read (rest of) expression.
      }
      return;
    }
    case kTryCatch: {
      ++depth_.try_;
      AddTryVariables();
      VisitStatement();  // read body.
      --depth_.try_;

      ++depth_.catch_;
      AddCatchVariables();

      builder_->ReadBool();  // read any_catch_needs_stack_trace.
      intptr_t catch_count =
          builder_->ReadListLength();  // read number of catches.
      for (intptr_t i = 0; i < catch_count; ++i) {
        PositionScope scope(builder_->reader_);
        intptr_t offset = builder_->ReaderOffset();  // Catch has no tag.

        EnterScope(relative_kernel_offset_ + offset);

        VisitDartType();            // Read the guard.
        tag = builder_->ReadTag();  // read first part of exception.
        if (tag == kSomething) {
          VisitVariableDeclaration();  // read exception.
        }
        tag = builder_->ReadTag();  // read first part of stack trace.
        if (tag == kSomething) {
          VisitVariableDeclaration();  // read stack trace.
        }
        VisitStatement();  // read body.

        ExitScope(builder_->reader_->min_position(),
                  builder_->reader_->max_position());
      }
      --depth_.catch_;
      return;
    }
    case kTryFinally: {
      ++depth_.try_;
      ++depth_.finally_;
      AddTryVariables();

      VisitStatement();  // read body.

      --depth_.finally_;
      --depth_.try_;
      ++depth_.catch_;
      AddCatchVariables();

      VisitStatement();  // read finalizer.

      --depth_.catch_;
      return;
    }
    case kYieldStatement: {
      builder_->ReadPosition();           // read position.
      word flags = builder_->ReadByte();  // read flags.
      builder_->SkipExpression();         // read expression.

      ASSERT(flags == kNativeYieldFlags);
      if (depth_.function_ == 0) {
        AddSwitchVariable();
        // Promote all currently visible local variables into the context.
        // TODO(27590) CaptureLocalVariables promotes to many variables into
        // the scope. Mark those variables as stack_local.
        // TODO(27590) we don't need to promote those variables that are
        // not used across yields.
        scope_->CaptureLocalVariables(current_function_scope_);
      }
      return;
    }
    case kVariableDeclaration:
      VisitVariableDeclaration();  // read variable declaration.
      return;
    case kFunctionDeclaration: {
      intptr_t offset =
          builder_->ReaderOffset() - 1;  // -1 to include tag byte.
      builder_->ReadPosition();          // read position.
      VisitVariableDeclaration();        // read variable declaration.
      HandleLocalFunction(offset);       // read function node.
      return;
    }
    default:
      UNREACHABLE();
  }
}

void StreamingScopeBuilder::VisitArguments() {
  builder_->ReadUInt();  // read argument_count.

  // Types
  intptr_t list_length = builder_->ReadListLength();  // read list length.
  for (intptr_t i = 0; i < list_length; ++i) {
    VisitDartType();  // read ith type.
  }

  // Positional.
  list_length = builder_->ReadListLength();  // read list length.
  for (intptr_t i = 0; i < list_length; ++i) {
    VisitExpression();  // read ith positional.
  }

  // Named.
  list_length = builder_->ReadListLength();  // read list length.
  for (intptr_t i = 0; i < list_length; ++i) {
    builder_->SkipStringReference();  // read ith name index.
    VisitExpression();                // read ith expression.
  }
}

void StreamingScopeBuilder::VisitVariableDeclaration() {
  PositionScope scope(builder_->reader_);

  intptr_t kernel_offset_no_tag = builder_->ReaderOffset();
  VariableDeclarationHelper helper(builder_);
  helper.ReadUntilExcluding(VariableDeclarationHelper::kType);
  intptr_t offset_for_type = builder_->ReaderOffset();
  AbstractType& type = T.BuildVariableType();  // read type.

  // In case `declaration->IsConst()` the flow graph building will take care of
  // evaluating the constant and setting it via
  // `declaration->SetConstantValue()`.
  const String& name = (H.StringSize(helper.name_index_) == 0)
                           ? GenerateName(":var", name_index_++)
                           : H.DartSymbol(helper.name_index_);
  // We also need to visit the type.
  builder_->SetOffset(offset_for_type);
  VisitDartType();  // read type.

  Tag tag = builder_->ReadTag();  // read (first part of) initializer.
  if (tag == kSomething) {
    VisitExpression();  // read (actual) initializer.
  }

  // Go to next token position so it ends *after* the last potentially
  // debuggable position in the initializer.
  TokenPosition end_position = builder_->reader_->max_position();
  if (end_position.IsReal()) {
    end_position.Next();
  }
  LocalVariable* variable =
      MakeVariable(helper.position_, end_position, name, type);
  if (helper.IsFinal()) {
    variable->set_is_final();
  }
  scope_->AddVariable(variable);
  result_->locals.Insert(relative_kernel_offset_ + kernel_offset_no_tag,
                         variable);
}

void StreamingScopeBuilder::VisitDartType() {
  Tag tag = builder_->ReadTag();
  switch (tag) {
    case kInvalidType:
    case kDynamicType:
    case kVoidType:
    case kBottomType:
    case kVectorType:
      // those contain nothing.
      return;
    case kInterfaceType:
      VisitInterfaceType(false);
      return;
    case kSimpleInterfaceType:
      VisitInterfaceType(true);
      return;
    case kFunctionType:
      VisitFunctionType(false);
      return;
    case kSimpleFunctionType:
      VisitFunctionType(true);
      return;
    case kTypeParameterType:
      VisitTypeParameterType();
      return;
    default:
      UNREACHABLE();
  }
}

void StreamingScopeBuilder::VisitInterfaceType(bool simple) {
  builder_->ReadUInt();  // read klass_name.
  if (!simple) {
    intptr_t length = builder_->ReadListLength();  // read number of types.
    for (intptr_t i = 0; i < length; ++i) {
      VisitDartType();  // read the ith type.
    }
  }
}

void StreamingScopeBuilder::VisitFunctionType(bool simple) {
  if (!simple) {
    intptr_t list_length =
        builder_->ReadListLength();  // read type_parameters list length.
    for (int i = 0; i < list_length; ++i) {
      builder_->SkipStringReference();  // read string index (name).
      VisitDartType();                  // read dart type.
    }
    builder_->ReadUInt();  // read required parameter count.
    builder_->ReadUInt();  // read total parameter count.
  }

  const intptr_t positional_count =
      builder_->ReadListLength();  // read positional_parameters list length.
  for (intptr_t i = 0; i < positional_count; ++i) {
    VisitDartType();  // read ith positional parameter.
  }

  if (!simple) {
    const intptr_t named_count =
        builder_->ReadListLength();  // read named_parameters list length.
    for (intptr_t i = 0; i < named_count; ++i) {
      // read string reference (i.e. named_parameters[i].name).
      builder_->SkipStringReference();
      VisitDartType();  // read named_parameters[i].type.
    }
  }

  builder_->SkipListOfStrings();  // read positional parameter names.

  if (!simple) {
    builder_->SkipCanonicalNameReference();  // read typedef reference.
  }

  VisitDartType();  // read return type.
}

void StreamingScopeBuilder::VisitTypeParameterType() {
  Function& function = Function::Handle(Z, parsed_function_->function().raw());
  while (function.IsClosureFunction()) {
    function = function.parent_function();
  }

  if (function.IsFactory()) {
    // The type argument vector is passed as the very first argument to the
    // factory constructor function.
    HandleSpecialLoad(&result_->type_arguments_variable,
                      Symbols::TypeArgumentsParameter());
  } else if (!function.IsGeneric()) {
    // TODO(30455): Kernel generic methods undone. Currently we only support
    // generic toplevel methods. For no special load needs to be prepared for
    // these, because the 'LocalVariable' for the type arguments is set on the
    // 'ParsedFunction' directly. So we do nothing for generic methods.

    // The type argument vector is stored on the
    // instance object. We therefore need to capture `this`.
    HandleSpecialLoad(&result_->this_variable, Symbols::This());
  }

  builder_->ReadUInt();              // read index for parameter.
  builder_->SkipOptionalDartType();  // read bound bound.
}

void StreamingScopeBuilder::HandleLocalFunction(intptr_t parent_kernel_offset) {
  // "Peek" ahead into the function node
  intptr_t offset = builder_->ReaderOffset();

  FunctionNodeHelper function_node_helper(builder_);
  function_node_helper.ReadUntilExcluding(
      FunctionNodeHelper::kPositionalParameters);

  LocalScope* saved_function_scope = current_function_scope_;
  FunctionNodeHelper::AsyncMarker saved_function_async_marker =
      current_function_async_marker_;
  DepthState saved_depth_state = depth_;
  depth_ = DepthState(depth_.function_ + 1);
  EnterScope(relative_kernel_offset_ + parent_kernel_offset);
  current_function_scope_ = scope_;
  current_function_async_marker_ = function_node_helper.async_marker_;
  if (depth_.function_ == 1) {
    FunctionScope function_scope = {relative_kernel_offset_ + offset, scope_};
    result_->function_scopes.Add(function_scope);
  }

  // read positional_parameters and named_parameters.
  AddPositionalAndNamedParameters();

  // "Peek" is now done.
  builder_->SetOffset(offset);

  VisitFunctionNode();  // read function node.

  ExitScope(function_node_helper.position_, function_node_helper.end_position_);
  depth_ = saved_depth_state;
  current_function_scope_ = saved_function_scope;
  current_function_async_marker_ = saved_function_async_marker;
}

void StreamingScopeBuilder::EnterScope(intptr_t kernel_offset) {
  scope_ = new (Z) LocalScope(scope_, depth_.function_, depth_.loop_);
  ASSERT(kernel_offset >= 0);
  result_->scopes.Insert(kernel_offset, scope_);
}

void StreamingScopeBuilder::ExitScope(TokenPosition start_position,
                                      TokenPosition end_position) {
  scope_->set_begin_token_pos(start_position);
  scope_->set_end_token_pos(end_position);
  scope_ = scope_->parent();
}

void StreamingScopeBuilder::AddPositionalAndNamedParameters(intptr_t pos) {
  // List of positional.
  intptr_t list_length = builder_->ReadListLength();  // read list length.
  for (intptr_t i = 0; i < list_length; ++i) {
    AddVariableDeclarationParameter(pos++);  // read ith positional parameter.
  }

  // List of named.
  list_length = builder_->ReadListLength();  // read list length.
  for (intptr_t i = 0; i < list_length; ++i) {
    AddVariableDeclarationParameter(pos++);  // read ith named parameter.
  }
}

void StreamingScopeBuilder::AddVariableDeclarationParameter(intptr_t pos) {
  intptr_t kernel_offset = builder_->ReaderOffset();  // no tag.
  VariableDeclarationHelper helper(builder_);
  helper.ReadUntilExcluding(VariableDeclarationHelper::kType);
  String& name = H.DartSymbol(helper.name_index_);
  AbstractType& type = T.BuildVariableType();  // read type.
  helper.SetJustRead(VariableDeclarationHelper::kType);
  helper.ReadUntilExcluding(VariableDeclarationHelper::kInitializer);

  LocalVariable* variable =
      MakeVariable(helper.position_, helper.position_, name, type);
  if (helper.IsFinal()) {
    variable->set_is_final();
  }
  if (variable->name().raw() == Symbols::IteratorParameter().raw()) {
    variable->set_is_forced_stack();
  }
  scope_->InsertParameterAt(pos, variable);
  result_->locals.Insert(relative_kernel_offset_ + kernel_offset, variable);

  // The default value may contain 'let' bindings for which the constant
  // evaluator needs scope bindings.
  Tag tag = builder_->ReadTag();
  if (tag == kSomething) {
    VisitExpression();  // read initializer.
  }
}

LocalVariable* StreamingScopeBuilder::MakeVariable(
    TokenPosition declaration_pos,
    TokenPosition token_pos,
    const String& name,
    const AbstractType& type) {
  return new (Z) LocalVariable(declaration_pos, token_pos, name, type);
}

void StreamingScopeBuilder::AddExceptionVariable(
    GrowableArray<LocalVariable*>* variables,
    const char* prefix,
    intptr_t nesting_depth) {
  LocalVariable* v = NULL;

  // If we are inside a function with yield points then Kernel transformer
  // could have lifted some of the auxiliary exception variables into the
  // context to preserve them across yield points because they might
  // be needed for rethrow.
  // Check if it did and capture such variables instead of introducing
  // new local ones.
  // Note: function that wrap kSyncYielding function does not contain
  // its own try/catches.
  if (current_function_async_marker_ == FunctionNodeHelper::kSyncYielding) {
    ASSERT(current_function_scope_->parent() != NULL);
    v = current_function_scope_->parent()->LocalLookupVariable(
        GenerateName(prefix, nesting_depth - 1));
    if (v != NULL) {
      scope_->CaptureVariable(v);
    }
  }

  // No need to create variables for try/catch-statements inside
  // nested functions.
  if (depth_.function_ > 0) return;
  if (variables->length() >= nesting_depth) return;

  // If variable was not lifted by the transformer introduce a new
  // one into the current function scope.
  if (v == NULL) {
    v = MakeVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
                     GenerateName(prefix, nesting_depth - 1),
                     AbstractType::dynamic_type());

    // If transformer did not lift the variable then there is no need
    // to lift it into the context when we encouter a YieldStatement.
    v->set_is_forced_stack();
    current_function_scope_->AddVariable(v);
  }

  variables->Add(v);
}

void StreamingScopeBuilder::AddTryVariables() {
  AddExceptionVariable(&result_->catch_context_variables,
                       ":saved_try_context_var", depth_.try_);
}

void StreamingScopeBuilder::AddCatchVariables() {
  AddExceptionVariable(&result_->exception_variables, ":exception",
                       depth_.catch_);
  AddExceptionVariable(&result_->stack_trace_variables, ":stack_trace",
                       depth_.catch_);
}

void StreamingScopeBuilder::AddIteratorVariable() {
  if (depth_.function_ > 0) return;
  if (result_->iterator_variables.length() >= depth_.for_in_) return;

  ASSERT(result_->iterator_variables.length() == depth_.for_in_ - 1);
  LocalVariable* iterator =
      MakeVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
                   GenerateName(":iterator", depth_.for_in_ - 1),
                   AbstractType::dynamic_type());
  current_function_scope_->AddVariable(iterator);
  result_->iterator_variables.Add(iterator);
}

void StreamingScopeBuilder::AddSwitchVariable() {
  if ((depth_.function_ == 0) && (result_->switch_variable == NULL)) {
    LocalVariable* variable =
        MakeVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
                     Symbols::SwitchExpr(), AbstractType::dynamic_type());
    variable->set_is_forced_stack();
    current_function_scope_->AddVariable(variable);
    result_->switch_variable = variable;
  }
}

void StreamingScopeBuilder::LookupVariable(intptr_t declaration_binary_offset) {
  LocalVariable* variable = result_->locals.Lookup(declaration_binary_offset);
  if (variable == NULL) {
    // We have not seen a declaration of the variable, so it must be the
    // case that we are compiling a nested function and the variable is
    // declared in an outer scope.  In that case, look it up in the scope by
    // name and add it to the variable map to simplify later lookup.
    ASSERT(current_function_scope_->parent() != NULL);
    StringIndex var_name = builder_->GetNameFromVariableDeclaration(
        declaration_binary_offset, parsed_function_->function());

    const String& name = H.DartSymbol(var_name);
    variable = current_function_scope_->parent()->LookupVariable(name, true);
    ASSERT(variable != NULL);
    result_->locals.Insert(declaration_binary_offset, variable);
  }

  if (variable->owner()->function_level() < scope_->function_level()) {
    // We call `LocalScope->CaptureVariable(variable)` in two scenarios for two
    // different reasons:
    //   Scenario 1:
    //       We need to know which variables defined in this function
    //       are closed over by nested closures in order to ensure we will
    //       create a [Context] object of appropriate size and store captured
    //       variables there instead of the stack.
    //   Scenario 2:
    //       We need to find out which variables defined in enclosing functions
    //       are closed over by this function/closure or nested closures. This
    //       is necessary in order to build a fat flattened [ContextScope]
    //       object.
    scope_->CaptureVariable(variable);
  } else {
    ASSERT(variable->owner()->function_level() == scope_->function_level());
  }
}

const String& StreamingScopeBuilder::GenerateName(const char* prefix,
                                                  intptr_t suffix) {
  char name[64];
  OS::SNPrint(name, 64, "%s%" Pd "", prefix, suffix);
  return H.DartSymbol(name);
}

void StreamingScopeBuilder::HandleSpecialLoad(LocalVariable** variable,
                                              const String& symbol) {
  if (current_function_scope_->parent() != NULL) {
    // We are building the scope tree of a closure function and saw [node]. We
    // lazily populate the variable using the parent function scope.
    if (*variable == NULL) {
      *variable =
          current_function_scope_->parent()->LookupVariable(symbol, true);
      ASSERT(*variable != NULL);
    }
  }

  if ((current_function_scope_->parent() != NULL) ||
      (scope_->function_level() > 0)) {
    // Every scope we use the [variable] from needs to be notified of the usage
    // in order to ensure that preserving the context scope on that particular
    // use-site also includes the [variable].
    scope_->CaptureVariable(*variable);
  }
}

void StreamingScopeBuilder::LookupCapturedVariableByName(
    LocalVariable** variable,
    const String& name) {
  if (*variable == NULL) {
    *variable = scope_->LookupVariable(name, true);
    ASSERT(*variable != NULL);
    scope_->CaptureVariable(*variable);
  }
}

StreamingDartTypeTranslator::StreamingDartTypeTranslator(
    StreamingFlowGraphBuilder* builder,
    bool finalize)
    : builder_(builder),
      translation_helper_(builder->translation_helper_),
      active_class_(builder->active_class()),
      type_parameter_scope_(NULL),
      zone_(translation_helper_.zone()),
      result_(AbstractType::Handle(translation_helper_.zone())),
      finalize_(finalize) {}

AbstractType& StreamingDartTypeTranslator::BuildType() {
  BuildTypeInternal();

  // We return a new `ZoneHandle` here on purpose: The intermediate language
  // instructions do not make a copy of the handle, so we do it.
  return AbstractType::ZoneHandle(Z, result_.raw());
}

AbstractType& StreamingDartTypeTranslator::BuildTypeWithoutFinalization() {
  bool saved_finalize = finalize_;
  finalize_ = false;
  BuildTypeInternal();
  finalize_ = saved_finalize;

  // We return a new `ZoneHandle` here on purpose: The intermediate language
  // instructions do not make a copy of the handle, so we do it.
  return AbstractType::ZoneHandle(Z, result_.raw());
}

AbstractType& StreamingDartTypeTranslator::BuildVariableType() {
  AbstractType& abstract_type = BuildType();

  // We return a new `ZoneHandle` here on purpose: The intermediate language
  // instructions do not make a copy of the handle, so we do it.
  AbstractType& type = Type::ZoneHandle(Z);

  if (abstract_type.IsMalformed()) {
    type = AbstractType::dynamic_type().raw();
  } else {
    type = result_.raw();
  }

  return type;
}

void StreamingDartTypeTranslator::BuildTypeInternal() {
  Tag tag = builder_->ReadTag();
  switch (tag) {
    case kInvalidType:
      result_ = ClassFinalizer::NewFinalizedMalformedType(
          Error::Handle(Z),  // No previous error.
          Script::Handle(Z, Script::null()), TokenPosition::kNoSource,
          "[InvalidType] in Kernel IR.");
      break;
    case kDynamicType:
      result_ = Object::dynamic_type().raw();
      break;
    case kVoidType:
      result_ = Object::void_type().raw();
      break;
    case kVectorType:
      result_ = Object::vector_type().raw();
      break;
    case kBottomType:
      result_ =
          Class::Handle(Z, I->object_store()->null_class()).CanonicalType();
      break;
    case kInterfaceType:
      BuildInterfaceType(false);
      break;
    case kSimpleInterfaceType:
      BuildInterfaceType(true);
      break;
    case kFunctionType:
      BuildFunctionType(false);
      break;
    case kSimpleFunctionType:
      BuildFunctionType(true);
      break;
    case kTypeParameterType:
      BuildTypeParameterType();
      break;
    default:
      UNREACHABLE();
  }
}

void StreamingDartTypeTranslator::BuildInterfaceType(bool simple) {
  // NOTE: That an interface type like `T<A, B>` is considered to be
  // malformed iff `T` is malformed.
  //   => We therefore ignore errors in `A` or `B`.

  NameIndex klass_name =
      builder_->ReadCanonicalNameReference();  // read klass_name.

  intptr_t length;
  if (simple) {
    length = 0;
  } else {
    length = builder_->ReadListLength();  // read type_arguments list length.
  }
  const TypeArguments& type_arguments =
      BuildTypeArguments(length);  // read type arguments.

  Object& klass = Object::Handle(Z, H.LookupClassByKernelClass(klass_name));
  result_ = Type::New(klass, type_arguments, TokenPosition::kNoSource);
  if (finalize_) {
    ASSERT(active_class_->klass != NULL);
    result_ = ClassFinalizer::FinalizeType(*active_class_->klass, result_);
  }
}

void StreamingDartTypeTranslator::BuildFunctionType(bool simple) {
  intptr_t list_length = 0;
  if (!simple) {
    list_length =
        builder_->ReadListLength();  // read type_parameters list length
    for (int i = 0; i < list_length; ++i) {
      builder_->SkipStringReference();  // read string index (name).
      builder_->SkipDartType();         // read dart type.
    }
  }

  // The spec describes in section "19.1 Static Types":
  //
  //     Any use of a malformed type gives rise to a static warning. A
  //     malformed type is then interpreted as dynamic by the static type
  //     checker and the runtime unless explicitly specified otherwise.
  //
  // So we convert malformed return/parameter types to `dynamic`.
  TypeParameterScope scope(this, list_length);

  Function& signature_function = Function::ZoneHandle(
      Z,
      Function::NewSignatureFunction(*active_class_->klass, Function::Handle(Z),
                                     TokenPosition::kNoSource));

  intptr_t required_count;
  intptr_t all_count;
  intptr_t positional_count;
  if (!simple) {
    required_count = builder_->ReadUInt();  // read required parameter count.
    all_count = builder_->ReadUInt();       // read total parameter count.
    positional_count =
        builder_->ReadListLength();  // read positional_parameters list length.
  } else {
    positional_count =
        builder_->ReadListLength();  // read positional_parameters list length.
    required_count = positional_count;
    all_count = positional_count;
  }

  const Array& parameter_types =
      Array::Handle(Z, Array::New(1 + all_count, Heap::kOld));
  signature_function.set_parameter_types(parameter_types);
  const Array& parameter_names =
      Array::Handle(Z, Array::New(1 + all_count, Heap::kOld));
  signature_function.set_parameter_names(parameter_names);

  intptr_t pos = 0;
  parameter_types.SetAt(pos, AbstractType::dynamic_type());
  parameter_names.SetAt(pos, H.DartSymbol("_receiver_"));
  ++pos;
  for (intptr_t i = 0; i < positional_count; ++i, ++pos) {
    BuildTypeInternal();  // read ith positional parameter.
    if (result_.IsMalformed()) {
      result_ = AbstractType::dynamic_type().raw();
    }
    parameter_types.SetAt(pos, result_);
    parameter_names.SetAt(pos, H.DartSymbol("noname"));
  }

  // The additional first parameter is the receiver type (set to dynamic).
  signature_function.set_num_fixed_parameters(1 + required_count);
  signature_function.SetNumOptionalParameters(
      all_count - required_count, positional_count > required_count);

  if (!simple) {
    const intptr_t named_count =
        builder_->ReadListLength();  // read named_parameters list length.
    for (intptr_t i = 0; i < named_count; ++i, ++pos) {
      // read string reference (i.e. named_parameters[i].name).
      String& name = H.DartSymbol(builder_->ReadStringReference());
      BuildTypeInternal();  // read named_parameters[i].type.
      if (result_.IsMalformed()) {
        result_ = AbstractType::dynamic_type().raw();
      }
      parameter_types.SetAt(pos, result_);
      parameter_names.SetAt(pos, name);
    }
  }

  builder_->SkipListOfStrings();  // read positional parameter names.

  if (!simple) {
    builder_->SkipCanonicalNameReference();  // read typedef reference.
  }

  BuildTypeInternal();  // read return type.
  if (result_.IsMalformed()) {
    result_ = AbstractType::dynamic_type().raw();
  }
  signature_function.set_result_type(result_);

  Type& signature_type =
      Type::ZoneHandle(Z, signature_function.SignatureType());

  if (finalize_) {
    signature_type ^=
        ClassFinalizer::FinalizeType(*active_class_->klass, signature_type);
    // Do not refer to signature_function anymore, since it may have been
    // replaced during canonicalization.
    signature_function = Function::null();
  }

  result_ = signature_type.raw();
}

void StreamingDartTypeTranslator::BuildTypeParameterType() {
  intptr_t parameter_index = builder_->ReadUInt();  // read parameter index.
  builder_->SkipOptionalDartType();                 // read bound.

  const TypeArguments& class_types =
      TypeArguments::Handle(Z, active_class_->klass->type_parameters());
  if (parameter_index < class_types.Length()) {
    // The index of the type parameter in [parameters] is
    // the same index into the `klass->type_parameters()` array.
    result_ ^= class_types.TypeAt(parameter_index);
    return;
  }
  parameter_index -= class_types.Length();

  if (active_class_->HasMember()) {
    if (active_class_->MemberIsFactoryProcedure()) {
      //
      // WARNING: This is a little hackish:
      //
      // We have a static factory constructor. The kernel IR gives the factory
      // constructor function it's own type parameters (which are equal in name
      // and number to the ones of the enclosing class).
      // I.e.,
      //
      //   class A<T> {
      //     factory A.x() { return new B<T>(); }
      //   }
      //
      //  is basically translated to this:
      //
      //   class A<T> {
      //     static A.x<T'>() { return new B<T'>(); }
      //   }
      //
      if (class_types.Length() > parameter_index) {
        result_ ^= class_types.TypeAt(parameter_index);
        return;
      }
      parameter_index -= class_types.Length();
    }

    intptr_t procedure_type_parameter_count =
        active_class_->MemberIsProcedure()
            ? active_class_->MemberTypeParameterCount(Z)
            : 0;
    if (procedure_type_parameter_count > 0) {
      if (procedure_type_parameter_count > parameter_index) {
        if (FLAG_reify_generic_functions) {
          result_ ^=
              TypeArguments::Handle(Z, active_class_->member->type_parameters())
                  .TypeAt(parameter_index);
        } else {
          result_ ^= Type::DynamicType();
        }
        return;
      }
      parameter_index -= procedure_type_parameter_count;
    }
  }

  if (type_parameter_scope_ != NULL && parameter_index >= 0 &&
      parameter_index < type_parameter_scope_->outer_parameter_count() +
                            type_parameter_scope_->parameter_count()) {
    result_ ^= Type::DynamicType();
    return;
  }

  H.ReportError("Unexpected input. Please report this at dartbug.com.");
}

const TypeArguments& StreamingDartTypeTranslator::BuildTypeArguments(
    intptr_t length) {
  bool only_dynamic = true;
  intptr_t offset = builder_->ReaderOffset();
  for (intptr_t i = 0; i < length; ++i) {
    if (builder_->ReadTag() != kDynamicType) {  // Read the ith types tag.
      only_dynamic = false;
      builder_->SetOffset(offset);
      break;
    }
  }
  TypeArguments& type_arguments = TypeArguments::ZoneHandle(Z);
  if (!only_dynamic) {
    type_arguments = TypeArguments::New(length);
    for (intptr_t i = 0; i < length; ++i) {
      BuildTypeInternal();  // read ith type.
      if (result_.IsMalformed()) {
        type_arguments = TypeArguments::null();
        // Skip the rest of the arguments.
        for (++i; i < length; ++i) {
          builder_->SkipDartType();
        }
        return type_arguments;
      }
      type_arguments.SetTypeAt(i, result_);
    }

    if (finalize_) {
      type_arguments = type_arguments.Canonicalize();
    }
  }
  return type_arguments;
}

const TypeArguments&
StreamingDartTypeTranslator::BuildInstantiatedTypeArguments(
    const Class& receiver_class,
    intptr_t length) {
  const TypeArguments& type_arguments = BuildTypeArguments(length);

  // If type_arguments is null all arguments are dynamic.
  // If, however, this class doesn't specify all the type arguments directly we
  // still need to finalize the type below in order to get any non-dynamic types
  // from any super. See http://www.dartbug.com/29537.
  if (type_arguments.IsNull() && receiver_class.NumTypeArguments() == length) {
    return type_arguments;
  }

  // We make a temporary [Type] object and use `ClassFinalizer::FinalizeType` to
  // finalize the argument types.
  // (This can for example make the [type_arguments] vector larger)
  Type& type = Type::Handle(
      Z, Type::New(receiver_class, type_arguments, TokenPosition::kNoSource));
  if (finalize_) {
    type ^= ClassFinalizer::FinalizeType(*active_class_->klass, type);
  }

  const TypeArguments& instantiated_type_arguments =
      TypeArguments::ZoneHandle(Z, type.arguments());
  return instantiated_type_arguments;
}

const Type& StreamingDartTypeTranslator::ReceiverType(const Class& klass) {
  ASSERT(!klass.IsNull());
  ASSERT(!klass.IsTypedefClass());
  // Note that if klass is _Closure, the returned type will be _Closure,
  // and not the signature type.
  Type& type = Type::ZoneHandle(Z, klass.CanonicalType());
  if (!type.IsNull()) {
    return type;
  }
  type = Type::New(klass, TypeArguments::Handle(Z, klass.type_parameters()),
                   klass.token_pos());
  if (klass.is_type_finalized()) {
    type ^= ClassFinalizer::FinalizeType(klass, type);
    klass.SetCanonicalType(type);
  }
  return type;
}

StreamingConstantEvaluator::StreamingConstantEvaluator(
    StreamingFlowGraphBuilder* builder)
    : builder_(builder),
      isolate_(Isolate::Current()),
      zone_(builder_->zone_),
      translation_helper_(builder_->translation_helper_),
      type_translator_(builder_->type_translator_),
      script_(Script::Handle(
          zone_,
          // TODO(jensj): This was added to temporarily be able to let the scope
          // builder have a StreamingFlowGraphBuilder to get access to
          // reading functions.
          (builder == NULL || builder_->flow_graph_builder_ == NULL)
              ? Script::null()
              : builder_->parsed_function()->function().script())),
      result_(Instance::Handle(zone_)) {}

Instance& StreamingConstantEvaluator::EvaluateExpression(intptr_t offset,
                                                         bool reset_position) {
  if (!GetCachedConstant(offset, &result_)) {
    intptr_t original_offset = builder_->ReaderOffset();
    builder_->SetOffset(offset);
    uint8_t payload = 0;
    Tag tag = builder_->ReadTag(&payload);  // read tag.
    switch (tag) {
      case kVariableGet:
        EvaluateVariableGet();
        break;
      case kSpecializedVariableGet:
        EvaluateVariableGet(payload);
        break;
      case kPropertyGet:
        EvaluatePropertyGet();
        break;
      case kStaticGet:
        EvaluateStaticGet();
        break;
      case kMethodInvocation:
        EvaluateMethodInvocation();
        break;
      case kStaticInvocation:
      case kConstStaticInvocation:
        EvaluateStaticInvocation();
        break;
      case kConstructorInvocation:
      case kConstConstructorInvocation:
        EvaluateConstructorInvocationInternal();
        break;
      case kNot:
        EvaluateNot();
        break;
      case kLogicalExpression:
        EvaluateLogicalExpression();
        break;
      case kConditionalExpression:
        EvaluateConditionalExpression();
        break;
      case kStringConcatenation:
        EvaluateStringConcatenation();
        break;
      case kSymbolLiteral:
        EvaluateSymbolLiteral();
        break;
      case kTypeLiteral:
        EvaluateTypeLiteral();
        break;
      case kListLiteral:
      case kConstListLiteral:
        EvaluateListLiteralInternal();
        break;
      case kMapLiteral:
      case kConstMapLiteral:
        EvaluateMapLiteralInternal();
        break;
      case kLet:
        EvaluateLet();
        break;
      case kBigIntLiteral:
        EvaluateBigIntLiteral();
        break;
      case kStringLiteral:
        EvaluateStringLiteral();
        break;
      case kSpecialIntLiteral:
        EvaluateIntLiteral(payload);
        break;
      case kNegativeIntLiteral:
        EvaluateIntLiteral(true);
        break;
      case kPositiveIntLiteral:
        EvaluateIntLiteral(false);
        break;
      case kDoubleLiteral:
        EvaluateDoubleLiteral();
        break;
      case kTrueLiteral:
        EvaluateBoolLiteral(true);
        break;
      case kFalseLiteral:
        EvaluateBoolLiteral(false);
        break;
      case kNullLiteral:
        EvaluateNullLiteral();
        break;
      default:
        UNREACHABLE();
    }

    CacheConstantValue(offset, result_);
    if (reset_position) builder_->SetOffset(original_offset);
  }
  // We return a new `ZoneHandle` here on purpose: The intermediate language
  // instructions do not make a copy of the handle, so we do it.
  return Instance::ZoneHandle(Z, result_.raw());
}

Instance& StreamingConstantEvaluator::EvaluateListLiteral(intptr_t offset,
                                                          bool reset_position) {
  if (!GetCachedConstant(offset, &result_)) {
    intptr_t original_offset = builder_->ReaderOffset();
    builder_->SetOffset(offset);
    builder_->ReadTag();  // skip tag.
    EvaluateListLiteralInternal();

    CacheConstantValue(offset, result_);
    if (reset_position) builder_->SetOffset(original_offset);
  }
  // We return a new `ZoneHandle` here on purpose: The intermediate language
  // instructions do not make a copy of the handle, so we do it.
  return Instance::ZoneHandle(Z, result_.raw());
}

Instance& StreamingConstantEvaluator::EvaluateMapLiteral(intptr_t offset,
                                                         bool reset_position) {
  if (!GetCachedConstant(offset, &result_)) {
    intptr_t original_offset = builder_->ReaderOffset();
    builder_->SetOffset(offset);
    builder_->ReadTag();  // skip tag.
    EvaluateMapLiteralInternal();

    CacheConstantValue(offset, result_);
    if (reset_position) builder_->SetOffset(original_offset);
  }
  // We return a new `ZoneHandle` here on purpose: The intermediate language
  // instructions do not make a copy of the handle, so we do it.
  return Instance::ZoneHandle(Z, result_.raw());
}

Instance& StreamingConstantEvaluator::EvaluateConstructorInvocation(
    intptr_t offset,
    bool reset_position) {
  if (!GetCachedConstant(offset, &result_)) {
    intptr_t original_offset = builder_->ReaderOffset();
    builder_->SetOffset(offset);
    builder_->ReadTag();  // skip tag.
    EvaluateConstructorInvocationInternal();

    CacheConstantValue(offset, result_);
    if (reset_position) builder_->SetOffset(original_offset);
  }
  // We return a new `ZoneHandle` here on purpose: The intermediate language
  // instructions do not make a copy of the handle, so we do it.
  return Instance::ZoneHandle(Z, result_.raw());
}

Object& StreamingConstantEvaluator::EvaluateExpressionSafe(intptr_t offset) {
  LongJumpScope jump;
  if (setjmp(*jump.Set()) == 0) {
    return EvaluateExpression(offset);
  } else {
    Thread* thread = H.thread();
    Error& error = Error::Handle(Z);
    error = thread->sticky_error();
    thread->clear_sticky_error();
    return error;
  }
}

void StreamingConstantEvaluator::EvaluateVariableGet() {
  // When we see a [VariableGet] the corresponding [VariableDeclaration] must've
  // been executed already. It therefore must have a constant object associated
  // with it.
  builder_->ReadPosition();  // read position.
  intptr_t variable_kernel_position =
      builder_->ReadUInt();          // read kernel position.
  builder_->ReadUInt();              // read relative variable index.
  builder_->SkipOptionalDartType();  // read promoted type.
  LocalVariable* variable = builder_->LookupVariable(variable_kernel_position);
  ASSERT(variable->IsConst());
  result_ = variable->ConstValue()->raw();
}

void StreamingConstantEvaluator::EvaluateVariableGet(uint8_t payload) {
  // When we see a [VariableGet] the corresponding [VariableDeclaration] must've
  // been executed already. It therefore must have a constant object associated
  // with it.
  builder_->ReadPosition();  // read position.
  intptr_t variable_kernel_position =
      builder_->ReadUInt();  // read kernel position.
  LocalVariable* variable = builder_->LookupVariable(variable_kernel_position);
  ASSERT(variable->IsConst());
  result_ = variable->ConstValue()->raw();
}

void StreamingConstantEvaluator::EvaluatePropertyGet() {
  builder_->ReadPosition();  // read position.
  intptr_t expression_offset = builder_->ReaderOffset();
  builder_->SkipExpression();                            // read receiver.
  StringIndex name = builder_->ReadNameAsStringIndex();  // read name.
  builder_->SkipCanonicalNameReference();  // read interface_target_reference.

  if (H.StringEquals(name, "length")) {
    EvaluateExpression(expression_offset);
    if (result_.IsString()) {
      const String& str = String::Handle(Z, String::RawCast(result_.raw()));
      result_ = Integer::New(str.Length());
    } else {
      H.ReportError(
          "Constant expressions can only call "
          "'length' on string constants.");
    }
  } else {
    UNREACHABLE();
  }
}

void StreamingConstantEvaluator::EvaluateStaticGet() {
  builder_->ReadPosition();  // read position.
  NameIndex target =
      builder_->ReadCanonicalNameReference();  // read target_reference.

  if (H.IsField(target)) {
    const Field& field = Field::Handle(Z, H.LookupFieldByKernelField(target));
    if (field.StaticValue() == Object::sentinel().raw() ||
        field.StaticValue() == Object::transition_sentinel().raw()) {
      field.EvaluateInitializer();
      result_ = field.StaticValue();
      result_ = H.Canonicalize(result_);
      field.SetStaticValue(result_, true);
    } else {
      result_ = field.StaticValue();
    }
  } else if (H.IsProcedure(target)) {
    const Function& function =
        Function::ZoneHandle(Z, H.LookupStaticMethodByKernelProcedure(target));

    if (H.IsMethod(target)) {
      Function& closure_function =
          Function::ZoneHandle(Z, function.ImplicitClosureFunction());
      result_ = closure_function.ImplicitStaticClosure();
      result_ = H.Canonicalize(result_);
    } else if (H.IsGetter(target)) {
      UNIMPLEMENTED();
    } else {
      UNIMPLEMENTED();
    }
  }
}

void StreamingConstantEvaluator::EvaluateMethodInvocation() {
  builder_->ReadPosition();  // read position.
  // This method call wasn't cached, so receiver et al. isn't cached either.
  const Instance& receiver =
      EvaluateExpression(builder_->ReaderOffset(), false);  // read receiver.
  Class& klass =
      Class::Handle(Z, isolate_->class_table()->At(receiver.GetClassId()));
  ASSERT(!klass.IsNull());

  // Search the superclass chain for the selector.
  Function& function = Function::Handle(Z);
  const String& method_name = builder_->ReadNameAsMethodName();  // read name.
  while (!klass.IsNull()) {
    function = klass.LookupDynamicFunctionAllowPrivate(method_name);
    if (!function.IsNull()) break;
    klass = klass.SuperClass();
  }

  // The frontend should guarantee that [MethodInvocation]s inside constant
  // expressions are always valid.
  ASSERT(!function.IsNull());

  // Read first parts of arguments: count and list of types.
  intptr_t argument_count = builder_->PeekArgumentsCount();
  // Dart does not support generic methods yet.
  ASSERT(builder_->PeekArgumentsTypeCount() == 0);
  builder_->SkipArgumentsBeforeActualArguments();

  // Run the method and canonicalize the result.
  const Object& result = RunFunction(function, argument_count, &receiver, NULL);
  result_ ^= result.raw();
  result_ = H.Canonicalize(result_);

  builder_->SkipCanonicalNameReference();  // read interface_target_reference.
}

void StreamingConstantEvaluator::EvaluateStaticInvocation() {
  builder_->ReadPosition();  // read position.
  NameIndex procedue_reference =
      builder_->ReadCanonicalNameReference();  // read procedure reference.

  const Function& function = Function::ZoneHandle(
      Z, H.LookupStaticMethodByKernelProcedure(procedue_reference));
  Class& klass = Class::Handle(Z, function.Owner());

  intptr_t argument_count =
      builder_->ReadUInt();  // read arguments part #1: arguments count.

  // Build the type arguments vector (if necessary).
  const TypeArguments* type_arguments =
      TranslateTypeArguments(function, &klass);  // read argument types.

  // read positional and named parameters.
  const Object& result =
      RunFunction(function, argument_count, NULL, type_arguments);
  result_ ^= result.raw();
  result_ = H.Canonicalize(result_);
}

void StreamingConstantEvaluator::EvaluateConstructorInvocationInternal() {
  builder_->ReadPosition();  // read position.

  NameIndex target = builder_->ReadCanonicalNameReference();  // read target.
  const Function& constructor =
      Function::Handle(Z, H.LookupConstructorByKernelConstructor(target));
  Class& klass = Class::Handle(Z, constructor.Owner());

  intptr_t argument_count =
      builder_->ReadUInt();  // read arguments part #1: arguments count.

  // Build the type arguments vector (if necessary).
  const TypeArguments* type_arguments =
      TranslateTypeArguments(constructor, &klass);  // read argument types.

  // Prepare either the instance or the type argument vector for the constructor
  // call.
  Instance* receiver = NULL;
  const TypeArguments* type_arguments_argument = NULL;
  if (!constructor.IsFactory()) {
    receiver = &Instance::ZoneHandle(Z, Instance::New(klass, Heap::kOld));
    if (type_arguments != NULL) {
      receiver->SetTypeArguments(*type_arguments);
    }
  } else {
    type_arguments_argument = type_arguments;
  }

  // read positional and named parameters.
  const Object& result = RunFunction(constructor, argument_count, receiver,
                                     type_arguments_argument);

  if (constructor.IsFactory()) {
    // Factories return the new object.
    result_ ^= result.raw();
    result_ = H.Canonicalize(result_);
  } else {
    ASSERT(!receiver->IsNull());
    result_ = H.Canonicalize(*receiver);
  }
}

void StreamingConstantEvaluator::EvaluateNot() {
  result_ ^= Bool::Get(!EvaluateBooleanExpressionHere()).raw();
}

void StreamingConstantEvaluator::EvaluateLogicalExpression() {
  bool left = EvaluateBooleanExpressionHere();  // read left.
  LogicalOperator op = static_cast<LogicalOperator>(builder_->ReadByte());
  if (op == kAnd) {
    if (left) {
      EvaluateBooleanExpressionHere();  // read right.
    } else {
      builder_->SkipExpression();  // read right.
    }
  } else {
    ASSERT(op == kOr);
    if (!left) {
      EvaluateBooleanExpressionHere();  // read right.
    } else {
      builder_->SkipExpression();  // read right.
    }
  }
}

void StreamingConstantEvaluator::EvaluateConditionalExpression() {
  bool condition = EvaluateBooleanExpressionHere();
  if (condition) {
    EvaluateExpression(builder_->ReaderOffset(), false);  // read then.
    builder_->SkipExpression();                           // read otherwise.
  } else {
    builder_->SkipExpression();                           // read then.
    EvaluateExpression(builder_->ReaderOffset(), false);  // read otherwise.
  }
  builder_->SkipOptionalDartType();  // read unused static type.
}

void StreamingConstantEvaluator::EvaluateStringConcatenation() {
  builder_->ReadPosition();                      // read position.
  intptr_t length = builder_->ReadListLength();  // read list length.

  bool all_string = true;
  const Array& strings = Array::Handle(Z, Array::New(length));
  for (intptr_t i = 0; i < length; ++i) {
    EvaluateExpression(builder_->ReaderOffset(),
                       false);  // read ith expression.
    strings.SetAt(i, result_);
    all_string = all_string && result_.IsString();
  }
  if (all_string) {
    result_ = String::ConcatAll(strings, Heap::kOld);
    result_ = H.Canonicalize(result_);
  } else {
    // Get string interpolation function.
    const Class& cls =
        Class::Handle(Z, Library::LookupCoreClass(Symbols::StringBase()));
    ASSERT(!cls.IsNull());
    const Function& func = Function::Handle(
        Z, cls.LookupStaticFunction(
               Library::PrivateCoreLibName(Symbols::Interpolate())));
    ASSERT(!func.IsNull());

    // Build argument array to pass to the interpolation function.
    const Array& interpolate_arg = Array::Handle(Z, Array::New(1, Heap::kOld));
    interpolate_arg.SetAt(0, strings);

    // Run and canonicalize.
    const Object& result =
        RunFunction(func, interpolate_arg, Array::null_array());
    result_ = H.Canonicalize(String::Cast(result));
  }
}

void StreamingConstantEvaluator::EvaluateSymbolLiteral() {
  const String& symbol_value = H.DartSymbol(
      builder_->ReadStringReference());  // read index into string table.

  const Class& symbol_class =
      Class::ZoneHandle(Z, I->object_store()->symbol_class());
  ASSERT(!symbol_class.IsNull());
  const Function& symbol_constructor = Function::ZoneHandle(
      Z, symbol_class.LookupConstructor(Symbols::SymbolCtor()));
  ASSERT(!symbol_constructor.IsNull());
  result_ ^= EvaluateConstConstructorCall(
      symbol_class, TypeArguments::Handle(Z), symbol_constructor, symbol_value);
}

void StreamingConstantEvaluator::EvaluateTypeLiteral() {
  const AbstractType& type = T.BuildType();
  if (type.IsMalformed()) {
    H.ReportError("Malformed type literal in constant expression.");
  }
  result_ = type.raw();
}

void StreamingConstantEvaluator::EvaluateListLiteralInternal() {
  builder_->ReadPosition();  // read position.
  const TypeArguments& type_arguments = T.BuildTypeArguments(1);  // read type.
  intptr_t length = builder_->ReadListLength();  // read list length.
  const Array& const_list =
      Array::ZoneHandle(Z, Array::New(length, Heap::kOld));
  const_list.SetTypeArguments(type_arguments);
  for (intptr_t i = 0; i < length; ++i) {
    const Instance& expression = EvaluateExpression(
        builder_->ReaderOffset(), false);  // read ith expression.
    const_list.SetAt(i, expression);
  }
  const_list.MakeImmutable();
  result_ = H.Canonicalize(const_list);
}

void StreamingConstantEvaluator::EvaluateMapLiteralInternal() {
  builder_->ReadPosition();  // read position.
  const TypeArguments& type_arguments =
      T.BuildTypeArguments(2);  // read key type and value type.

  intptr_t length = builder_->ReadListLength();  // read length of entries.

  // This MapLiteral wasn't cached, so content isn't cached either.
  Array& const_kv_array =
      Array::ZoneHandle(Z, Array::New(2 * length, Heap::kOld));
  for (intptr_t i = 0; i < length; ++i) {
    const_kv_array.SetAt(2 * i + 0, EvaluateExpression(builder_->ReaderOffset(),
                                                       false));  // read key.
    const_kv_array.SetAt(2 * i + 1, EvaluateExpression(builder_->ReaderOffset(),
                                                       false));  // read value.
  }

  const_kv_array.MakeImmutable();
  const_kv_array ^= H.Canonicalize(const_kv_array);

  const Class& map_class =
      Class::Handle(Z, Library::LookupCoreClass(Symbols::ImmutableMap()));
  ASSERT(!map_class.IsNull());
  ASSERT(map_class.NumTypeArguments() == 2);

  const Field& field = Field::Handle(
      Z, map_class.LookupInstanceFieldAllowPrivate(H.DartSymbol("_kvPairs")));
  ASSERT(!field.IsNull());

  // NOTE: This needs to be kept in sync with `runtime/lib/immutable_map.dart`!
  result_ = Instance::New(map_class, Heap::kOld);
  ASSERT(!result_.IsNull());
  result_.SetTypeArguments(type_arguments);
  result_.SetField(field, const_kv_array);
  result_ = H.Canonicalize(result_);
}

void StreamingConstantEvaluator::EvaluateLet() {
  intptr_t kernel_position =
      builder_->ReaderOffset() + builder_->relative_kernel_offset_;
  LocalVariable* local = builder_->LookupVariable(kernel_position);

  // read variable declaration.
  VariableDeclarationHelper helper(builder_);
  helper.ReadUntilExcluding(VariableDeclarationHelper::kInitializer);
  Tag tag = builder_->ReadTag();  // read (first part of) initializer.
  if (tag == kNothing) {
    local->SetConstValue(Instance::ZoneHandle(Z, Instance::null()));
  } else {
    local->SetConstValue(EvaluateExpression(
        builder_->ReaderOffset(), false));  // read rest of initializer.
  }

  EvaluateExpression(builder_->ReaderOffset(), false);  // read body
}

void StreamingConstantEvaluator::EvaluateBigIntLiteral() {
  const String& value =
      H.DartString(builder_->ReadStringReference());  // read string reference.
  result_ = Integer::New(value, Heap::kOld);
  if (result_.IsNull()) {
    H.ReportError("Integer literal %s is out of range", value.ToCString());
    UNREACHABLE();
  }
  result_ = H.Canonicalize(result_);
}

void StreamingConstantEvaluator::EvaluateStringLiteral() {
  result_ = H.DartSymbol(builder_->ReadStringReference())
                .raw();  // read string reference.
}

void StreamingConstantEvaluator::EvaluateIntLiteral(uint8_t payload) {
  int64_t value = static_cast<int32_t>(payload) - SpecializedIntLiteralBias;
  result_ = Integer::New(value, Heap::kOld);
  result_ = H.Canonicalize(result_);
}

void StreamingConstantEvaluator::EvaluateIntLiteral(bool is_negative) {
  int64_t value = is_negative ? -static_cast<int64_t>(builder_->ReadUInt())
                              : builder_->ReadUInt();  // read value.
  result_ = Integer::New(value, Heap::kOld);
  result_ = H.Canonicalize(result_);
}

void StreamingConstantEvaluator::EvaluateDoubleLiteral() {
  result_ = Double::New(H.DartString(builder_->ReadStringReference()),
                        Heap::kOld);  // read string reference.
  result_ = H.Canonicalize(result_);
}

void StreamingConstantEvaluator::EvaluateBoolLiteral(bool value) {
  result_ = Bool::Get(value).raw();
}

void StreamingConstantEvaluator::EvaluateNullLiteral() {
  result_ = Instance::null();
}

// This depends on being about to read the list of positionals on arguments.
const Object& StreamingConstantEvaluator::RunFunction(
    const Function& function,
    intptr_t argument_count,
    const Instance* receiver,
    const TypeArguments* type_args) {
  // We do not support generic methods yet.
  ASSERT((receiver == NULL) || (type_args == NULL));
  intptr_t extra_arguments =
      (receiver != NULL ? 1 : 0) + (type_args != NULL ? 1 : 0);

  // Build up arguments.
  const Array& arguments =
      Array::ZoneHandle(Z, Array::New(extra_arguments + argument_count));
  intptr_t pos = 0;
  if (receiver != NULL) {
    arguments.SetAt(pos++, *receiver);
  }
  if (type_args != NULL) {
    arguments.SetAt(pos++, *type_args);
  }

  // List of positional.
  intptr_t list_length = builder_->ReadListLength();  // read list length.
  for (intptr_t i = 0; i < list_length; ++i) {
    EvaluateExpression(builder_->ReaderOffset(),
                       false);  // read ith expression.
    arguments.SetAt(pos++, result_);
  }

  // List of named.
  list_length = builder_->ReadListLength();  // read list length.
  const Array& names = Array::ZoneHandle(Z, Array::New(list_length));
  for (intptr_t i = 0; i < list_length; ++i) {
    String& name =
        H.DartSymbol(builder_->ReadStringReference());  // read ith name index.
    names.SetAt(i, name);
    EvaluateExpression(builder_->ReaderOffset(),
                       false);  // read ith expression.
    arguments.SetAt(pos++, result_);
  }

  return RunFunction(function, arguments, names);
}

const Object& StreamingConstantEvaluator::RunFunction(const Function& function,
                                                      const Array& arguments,
                                                      const Array& names) {
  // We do not support generic methods yet.
  const int kTypeArgsLen = 0;
  const Array& args_descriptor = Array::Handle(
      Z, ArgumentsDescriptor::New(kTypeArgsLen, arguments.Length(), names));
  const Object& result = Object::Handle(
      Z, DartEntry::InvokeFunction(function, arguments, args_descriptor));
  if (result.IsError()) {
    H.ReportError(Error::Cast(result), "error evaluating constant constructor");
  }
  return result;
}

RawObject* StreamingConstantEvaluator::EvaluateConstConstructorCall(
    const Class& type_class,
    const TypeArguments& type_arguments,
    const Function& constructor,
    const Object& argument) {
  // Factories have one extra argument: the type arguments.
  // Constructors have 1 extra arguments: receiver.
  const int kTypeArgsLen = 0;
  const int kNumArgs = 1;
  const int kNumExtraArgs = 1;
  const int argument_count = kNumArgs + kNumExtraArgs;
  const Array& arg_values =
      Array::Handle(Z, Array::New(argument_count, Heap::kOld));
  Instance& instance = Instance::Handle(Z);
  if (!constructor.IsFactory()) {
    instance = Instance::New(type_class, Heap::kOld);
    if (!type_arguments.IsNull()) {
      ASSERT(type_arguments.IsInstantiated());
      instance.SetTypeArguments(
          TypeArguments::Handle(Z, type_arguments.Canonicalize()));
    }
    arg_values.SetAt(0, instance);
  } else {
    // Prepend type_arguments to list of arguments to factory.
    ASSERT(type_arguments.IsZoneHandle());
    arg_values.SetAt(0, type_arguments);
  }
  arg_values.SetAt((0 + kNumExtraArgs), argument);
  const Array& args_descriptor =
      Array::Handle(Z, ArgumentsDescriptor::New(kTypeArgsLen, argument_count,
                                                Object::empty_array()));
  const Object& result = Object::Handle(
      Z, DartEntry::InvokeFunction(constructor, arg_values, args_descriptor));
  ASSERT(!result.IsError());
  if (constructor.IsFactory()) {
    // The factory method returns the allocated object.
    instance ^= result.raw();
  }
  return H.Canonicalize(instance);
}

const TypeArguments* StreamingConstantEvaluator::TranslateTypeArguments(
    const Function& target,
    Class* target_klass) {
  intptr_t type_count = builder_->ReadListLength();  // read type count.

  const TypeArguments* type_arguments = NULL;
  if (type_count > 0) {
    type_arguments = &T.BuildInstantiatedTypeArguments(
        *target_klass, type_count);  // read types.

    if (!(type_arguments->IsNull() || type_arguments->IsInstantiated())) {
      H.ReportError("Type must be constant in const constructor.");
    }
  } else if (target.IsFactory() && type_arguments == NULL) {
    // All factories take a type arguments vector as first argument (independent
    // of whether the class is generic or not).
    type_arguments = &TypeArguments::ZoneHandle(Z, TypeArguments::null());
  }
  return type_arguments;
}

bool StreamingConstantEvaluator::EvaluateBooleanExpressionHere() {
  EvaluateExpression(builder_->ReaderOffset(), false);
  AssertBool();
  return result_.raw() == Bool::True().raw();
}

bool StreamingConstantEvaluator::GetCachedConstant(intptr_t kernel_offset,
                                                   Instance* value) {
  if (builder_ == NULL || builder_->flow_graph_builder_ == NULL) return false;

  const Function& function = builder_->parsed_function()->function();
  if (function.kind() == RawFunction::kImplicitStaticFinalGetter) {
    // Don't cache constants in initializer expressions. They get
    // evaluated only once.
    return false;
  }

  bool is_present = false;
  ASSERT(!script_.InVMHeap());
  if (script_.compile_time_constants() == Array::null()) {
    return false;
  }
  KernelConstantsMap constants(script_.compile_time_constants());
  *value ^= constants.GetOrNull(
      kernel_offset + builder_->relative_kernel_offset_, &is_present);
  // Mutator compiler thread may add constants while background compiler
  // is running, and thus change the value of 'compile_time_constants';
  // do not assert that 'compile_time_constants' has not changed.
  constants.Release();
  if (FLAG_compiler_stats && is_present) {
    ++H.thread()->compiler_stats()->num_const_cache_hits;
  }
  return is_present;
}

void StreamingConstantEvaluator::CacheConstantValue(intptr_t kernel_offset,
                                                    const Instance& value) {
  ASSERT(Thread::Current()->IsMutatorThread());

  if (builder_ == NULL || builder_->flow_graph_builder_ == NULL) return;

  const Function& function = builder_->parsed_function()->function();
  if (function.kind() == RawFunction::kImplicitStaticFinalGetter) {
    // Don't cache constants in initializer expressions. They get
    // evaluated only once.
    return;
  }
  const intptr_t kInitialConstMapSize = 16;
  ASSERT(!script_.InVMHeap());
  if (script_.compile_time_constants() == Array::null()) {
    const Array& array = Array::Handle(
        HashTables::New<KernelConstantsMap>(kInitialConstMapSize, Heap::kNew));
    script_.set_compile_time_constants(array);
  }
  KernelConstantsMap constants(script_.compile_time_constants());
  constants.InsertNewOrGetValue(
      kernel_offset + builder_->relative_kernel_offset_, value);
  script_.set_compile_time_constants(constants.Release());
}

void StreamingFlowGraphBuilder::DiscoverEnclosingElements(
    Zone* zone,
    const Function& function,
    Function* outermost_function) {
  // Find out if there is an enclosing kernel class (which will be used to
  // resolve type parameters).
  *outermost_function = function.raw();
  while (outermost_function->parent_function() != Object::null()) {
    *outermost_function = outermost_function->parent_function();
  }
}

void StreamingFlowGraphBuilder::ReadUntilFunctionNode() {
  const Tag tag = PeekTag();
  if (tag == kProcedure) {
    ProcedureHelper procedure_helper(this);
    procedure_helper.ReadUntilExcluding(ProcedureHelper::kFunction);
    if (ReadTag() == kNothing) {  // read function node tag.
      // Running a procedure without a function node doesn't make sense.
      UNREACHABLE();
    }
    return;
    // Now at start of FunctionNode.
  } else if (tag == kConstructor) {
    ConstructorHelper constructor_helper(this);
    constructor_helper.ReadUntilExcluding(ConstructorHelper::kFunction);
    return;
    // Now at start of FunctionNode.
    // Notice that we also have a list of initializers after that!
  } else if (tag == kFunctionNode) {
    // Already at start of FunctionNode.
  } else {
    UNREACHABLE();
  }
  return;
}

StringIndex StreamingFlowGraphBuilder::GetNameFromVariableDeclaration(
    intptr_t kernel_offset,
    const Function& function) {
  Function& function_or_parent = Function::Handle(Z, function.raw());
  intptr_t function_start_relative =
      function_or_parent.kernel_offset() - kernel_offset;
  while (function_start_relative > 0) {
    function_or_parent = function_or_parent.parent_function();
    function_start_relative =
        function_or_parent.kernel_offset() - kernel_offset;
  }
  TypedData& kernel_data =
      TypedData::Handle(Z, function_or_parent.kernel_data());
  ASSERT(!kernel_data.IsNull());

  // Temporarily go to the variable declaration, read the name.
  AlternativeReadingScope alt(
      reader_, &kernel_data,
      kernel_offset - function_or_parent.kernel_offset());
  VariableDeclarationHelper helper(this);
  helper.ReadUntilIncluding(VariableDeclarationHelper::kNameIndex);
  return helper.name_index_;
}

FlowGraph* StreamingFlowGraphBuilder::BuildGraphOfStaticFieldInitializer() {
  FieldHelper field_helper(this);
  field_helper.ReadUntilExcluding(FieldHelper::kInitializer);
  ASSERT(field_helper.IsStatic());

  Tag initializer_tag = ReadTag();  // read first part of initializer.
  if (initializer_tag != kSomething) {
    UNREACHABLE();
  }

  TargetEntryInstr* normal_entry = flow_graph_builder_->BuildTargetEntry();
  flow_graph_builder_->graph_entry_ = new (Z) GraphEntryInstr(
      *parsed_function(), normal_entry, Compiler::kNoOSRDeoptId);

  Fragment body(normal_entry);
  body += flow_graph_builder_->CheckStackOverflowInPrologue();
  if (field_helper.IsConst()) {
    // this will (potentially) read the initializer, but reset the position.
    body += Constant(constant_evaluator_.EvaluateExpression(ReaderOffset()));
    SkipExpression();  // read the initializer.
  } else {
    body += BuildExpression();  // read initializer.
  }
  body += Return(TokenPosition::kNoSource);

  return new (Z)
      FlowGraph(*parsed_function(), flow_graph_builder_->graph_entry_,
                flow_graph_builder_->next_block_id_ - 1);
}

FlowGraph* StreamingFlowGraphBuilder::BuildGraphOfFieldAccessor(
    LocalVariable* setter_value) {
  FieldHelper field_helper(this);
  field_helper.ReadUntilIncluding(FieldHelper::kCanonicalName);

  const Function& function = parsed_function()->function();

  bool is_setter = function.IsImplicitSetterFunction();
  bool is_method = !function.IsStaticFunction();
  Field& field = Field::ZoneHandle(
      Z, H.LookupFieldByKernelField(field_helper.canonical_name_));

  TargetEntryInstr* normal_entry = flow_graph_builder_->BuildTargetEntry();
  flow_graph_builder_->graph_entry_ = new (Z) GraphEntryInstr(
      *parsed_function(), normal_entry, Compiler::kNoOSRDeoptId);

  Fragment body(normal_entry);
  if (is_setter) {
    if (is_method) {
      body += LoadLocal(scopes()->this_variable);
      body += LoadLocal(setter_value);
      body += flow_graph_builder_->StoreInstanceFieldGuarded(field, false);
    } else {
      body += LoadLocal(setter_value);
      body += StoreStaticField(TokenPosition::kNoSource, field);
    }
    body += NullConstant();
  } else if (is_method) {
    body += LoadLocal(scopes()->this_variable);
    body += flow_graph_builder_->LoadField(field);
  } else if (field.is_const()) {
    field_helper.ReadUntilExcluding(FieldHelper::kInitializer);
    Tag initializer_tag = ReadTag();  // read first part of initializer.

    // If the parser needs to know the value of an uninitialized constant field
    // it will set the value to the transition sentinel (used to detect circular
    // initialization) and then call the implicit getter.  Thus, the getter
    // cannot contain the InitStaticField instruction that normal static getters
    // contain because it would detect spurious circular initialization when it
    // checks for the transition sentinel.
    ASSERT(initializer_tag == kSomething);
    body += Constant(constant_evaluator_.EvaluateExpression(ReaderOffset()));
  } else {
    // The field always has an initializer because static fields without
    // initializers are initialized eagerly and do not have implicit getters.
    ASSERT(field.has_initializer());
    body += Constant(field);
    body += flow_graph_builder_->InitStaticField(field);
    body += Constant(field);
    body += LoadStaticField();
  }
  body += Return(TokenPosition::kNoSource);

  return new (Z)
      FlowGraph(*parsed_function(), flow_graph_builder_->graph_entry_,
                flow_graph_builder_->next_block_id_ - 1);
}

void StreamingFlowGraphBuilder::SetupDefaultParameterValues() {
  intptr_t optional_parameter_count =
      parsed_function()->function().NumOptionalParameters();
  if (optional_parameter_count > 0) {
    ZoneGrowableArray<const Instance*>* default_values =
        new ZoneGrowableArray<const Instance*>(Z, optional_parameter_count);

    AlternativeReadingScope alt(reader_);
    FunctionNodeHelper function_node_helper(this);
    function_node_helper.ReadUntilExcluding(
        FunctionNodeHelper::kPositionalParameters);

    if (parsed_function()->function().HasOptionalNamedParameters()) {
      // List of positional.
      intptr_t list_length = ReadListLength();  // read list length.
      for (intptr_t i = 0; i < list_length; ++i) {
        SkipVariableDeclaration();  // read ith variable declaration.
      }

      // List of named.
      list_length = ReadListLength();  // read list length.
      ASSERT(optional_parameter_count == list_length);
      ASSERT(!parsed_function()->function().HasOptionalPositionalParameters());
      for (intptr_t i = 0; i < list_length; ++i) {
        Instance* default_value;

        // Read ith variable declaration
        VariableDeclarationHelper helper(this);
        helper.ReadUntilExcluding(VariableDeclarationHelper::kInitializer);
        Tag tag = ReadTag();  // read (first part of) initializer.
        if (tag == kSomething) {
          // this will (potentially) read the initializer,
          // but reset the position.
          default_value =
              &constant_evaluator_.EvaluateExpression(ReaderOffset());
          SkipExpression();  // read (actual) initializer.
        } else {
          default_value = &Instance::ZoneHandle(Z, Instance::null());
        }
        default_values->Add(default_value);
      }
    } else {
      // List of positional.
      intptr_t list_length = ReadListLength();  // read list length.
      ASSERT(list_length == function_node_helper.required_parameter_count_ +
                                optional_parameter_count);
      ASSERT(parsed_function()->function().HasOptionalPositionalParameters());
      for (intptr_t i = 0; i < function_node_helper.required_parameter_count_;
           ++i) {
        SkipVariableDeclaration();  // read ith variable declaration.
      }
      for (intptr_t i = 0; i < optional_parameter_count; ++i) {
        Instance* default_value;

        // Read ith variable declaration
        VariableDeclarationHelper helper(this);
        helper.ReadUntilExcluding(VariableDeclarationHelper::kInitializer);
        Tag tag = ReadTag();  // read (first part of) initializer.
        if (tag == kSomething) {
          // this will (potentially) read the initializer,
          // but reset the position.
          default_value =
              &constant_evaluator_.EvaluateExpression(ReaderOffset());
          SkipExpression();  // read (actual) initializer.
        } else {
          default_value = &Instance::ZoneHandle(Z, Instance::null());
        }
        default_values->Add(default_value);
      }

      // List of named.
      list_length = ReadListLength();  // read list length.
      ASSERT(list_length == 0);
    }
    parsed_function()->set_default_parameter_values(default_values);
  }
}

Fragment StreamingFlowGraphBuilder::BuildFieldInitializer(
    NameIndex canonical_name) {
  Field& field =
      Field::ZoneHandle(Z, H.LookupFieldByKernelField(canonical_name));
  if (PeekTag() == kNullLiteral) {
    SkipExpression();  // read past the null literal.
    field.RecordStore(Object::null_object());
    return Fragment();
  }

  Fragment instructions;
  instructions += LoadLocal(scopes()->this_variable);
  instructions += BuildExpression();
  instructions += flow_graph_builder_->StoreInstanceFieldGuarded(field, true);
  return instructions;
}

Fragment StreamingFlowGraphBuilder::BuildInitializers(
    const Class& parent_class) {
  Fragment instructions;

  // Start by getting the position of the constructors initializer.
  intptr_t initializers_offset = -1;
  {
    AlternativeReadingScope alt(reader_);
    SkipFunctionNode();  // read constructors function node.
    initializers_offset = ReaderOffset();
  }

  // These come from:
  //   class A {
  //     var x = (expr);
  //   }
  // We don't want to do that when this is a Redirecting Constructors though
  // (i.e. has a single initializer being of type kRedirectingInitializer).
  bool is_redirecting_constructor = false;
  {
    AlternativeReadingScope alt(reader_, initializers_offset);
    intptr_t list_length = ReadListLength();  // read initializers list length.
    bool no_field_initializers = true;
    for (intptr_t i = 0; i < list_length; ++i) {
      if (PeekTag() == kRedirectingInitializer) {
        is_redirecting_constructor = true;
      } else if (PeekTag() == kFieldInitializer) {
        no_field_initializers = false;
      }
      SkipInitializer();
    }
    ASSERT(is_redirecting_constructor ? no_field_initializers : true);
  }

  if (!is_redirecting_constructor) {
    Array& class_fields = Array::Handle(Z, parent_class.fields());
    Field& class_field = Field::Handle(Z);
    for (intptr_t i = 0; i < class_fields.Length(); ++i) {
      class_field ^= class_fields.At(i);
      if (!class_field.is_static()) {
        TypedData& kernel_data =
            TypedData::Handle(Z, class_field.kernel_data());
        ASSERT(!kernel_data.IsNull());
        AlternativeReadingScope alt(reader_, &kernel_data, 0);
        intptr_t saved_relative_kernel_offset_ = relative_kernel_offset_;
        relative_kernel_offset_ = class_field.kernel_offset();
        FieldHelper field_helper(this);
        field_helper.ReadUntilExcluding(FieldHelper::kInitializer);
        Tag initializer_tag = ReadTag();  // read first part of initializer.
        if (initializer_tag == kSomething) {
          EnterScope(class_field.kernel_offset());
          instructions += BuildFieldInitializer(
              field_helper.canonical_name_);  // read initializer.
          ExitScope(class_field.kernel_offset());
        }
        relative_kernel_offset_ = saved_relative_kernel_offset_;
      }
    }
  }

  // These to come from:
  //   class A {
  //     var x;
  //     var y;
  //     A(this.x) : super(expr), y = (expr);
  //   }
  {
    AlternativeReadingScope alt(reader_, initializers_offset);
    intptr_t list_length = ReadListLength();  // read initializers list length.
    for (intptr_t i = 0; i < list_length; ++i) {
      Tag tag = ReadTag();
      ReadByte();  // read isSynthetic flag.
      switch (tag) {
        case kInvalidInitializer:
          UNIMPLEMENTED();
          return Fragment();
        case kFieldInitializer: {
          NameIndex canonical_name =
              ReadCanonicalNameReference();  // read field_reference.
          instructions += BuildFieldInitializer(canonical_name);  // read value.
          break;
        }
        case kSuperInitializer: {
          NameIndex canonical_target =
              ReadCanonicalNameReference();  // read target_reference.

          instructions += LoadLocal(scopes()->this_variable);
          instructions += PushArgument();

          // TODO(jensj): ASSERT(init->arguments()->types().length() == 0);
          Array& argument_names = Array::ZoneHandle(Z);
          intptr_t argument_count;
          instructions += BuildArguments(&argument_names,
                                         &argument_count);  // read arguments.
          argument_count += 1;

          const Function& target = Function::ZoneHandle(
              Z, H.LookupConstructorByKernelConstructor(canonical_target));
          instructions += StaticCall(TokenPosition::kNoSource, target,
                                     argument_count, argument_names);
          instructions += Drop();
          break;
        }
        case kRedirectingInitializer: {
          NameIndex canonical_target =
              ReadCanonicalNameReference();  // read target_reference.

          instructions += LoadLocal(scopes()->this_variable);
          instructions += PushArgument();

          // TODO(jensj): ASSERT(init->arguments()->types().length() == 0);
          Array& argument_names = Array::ZoneHandle(Z);
          intptr_t argument_count;
          instructions += BuildArguments(&argument_names,
                                         &argument_count);  // read arguments.
          argument_count += 1;

          const Function& target = Function::ZoneHandle(
              Z, H.LookupConstructorByKernelConstructor(canonical_target));
          instructions += StaticCall(TokenPosition::kNoSource, target,
                                     argument_count, argument_names);
          instructions += Drop();
          break;
        }
        case kLocalInitializer: {
          // The other initializers following this one might read the variable.
          // This is used e.g. for evaluating the arguments to a super call
          // first, run normal field initializers next and then make the actual
          // super call:
          //
          //   The frontend converts
          //
          //      class A {
          //        var x;
          //        A(a, b) : super(a + b), x = 2*b {}
          //      }
          //
          //   to
          //
          //      class A {
          //        var x;
          //        A(a, b) : tmp = a + b, x = 2*b, super(tmp) {}
          //      }
          //
          // (This is strictly speaking not what one should do in terms of the
          //  specification but that is how it is currently implemented.)
          LocalVariable* variable =
              LookupVariable(ReaderOffset() + relative_kernel_offset_);

          // Variable declaration
          VariableDeclarationHelper helper(this);
          helper.ReadUntilExcluding(VariableDeclarationHelper::kInitializer);
          ASSERT(!helper.IsConst());
          Tag tag = ReadTag();  // read (first part of) initializer.
          if (tag != kSomething) {
            UNREACHABLE();
          }

          instructions += BuildExpression();  // read initializer.
          instructions += StoreLocal(TokenPosition::kNoSource, variable);
          instructions += Drop();
          break;
        }
        default:
          UNREACHABLE();
      }
    }
  }
  return instructions;
}

FlowGraph* StreamingFlowGraphBuilder::BuildGraphOfImplicitClosureFunction(
    const Function& function) {
  const Function& target = Function::ZoneHandle(Z, function.parent_function());

  TargetEntryInstr* normal_entry = flow_graph_builder_->BuildTargetEntry();
  flow_graph_builder_->graph_entry_ = new (Z) GraphEntryInstr(
      *parsed_function(), normal_entry, Compiler::kNoOSRDeoptId);
  SetupDefaultParameterValues();

  Fragment body(normal_entry);
  body += flow_graph_builder_->CheckStackOverflowInPrologue();

  // Load all the arguments.
  if (!target.is_static()) {
    // The context has a fixed shape: a single variable which is the
    // closed-over receiver.
    body += LoadLocal(parsed_function()->current_context_var());
    body += flow_graph_builder_->LoadField(Context::variable_offset(0));
    body += PushArgument();
  }

  FunctionNodeHelper function_node_helper(this);
  function_node_helper.ReadUntilExcluding(
      FunctionNodeHelper::kPositionalParameters);

  // Positional.
  intptr_t positional_argument_count = ReadListLength();
  for (intptr_t i = 0; i < positional_argument_count; ++i) {
    body += LoadLocal(LookupVariable(
        ReaderOffset() + relative_kernel_offset_));  // ith variable offset.
    body += PushArgument();
    SkipVariableDeclaration();  // read ith variable.
  }

  // Named.
  intptr_t named_argument_count = ReadListLength();
  Array& argument_names = Array::ZoneHandle(Z);
  if (named_argument_count > 0) {
    argument_names = Array::New(named_argument_count);
    for (intptr_t i = 0; i < named_argument_count; ++i) {
      // ith variable offset.
      body +=
          LoadLocal(LookupVariable(ReaderOffset() + relative_kernel_offset_));
      body += PushArgument();

      // read ith variable.
      VariableDeclarationHelper helper(this);
      helper.ReadUntilExcluding(VariableDeclarationHelper::kEnd);

      argument_names.SetAt(i, H.DartSymbol(helper.name_index_));
    }
  }

  // Forward them to the target.
  intptr_t argument_count = positional_argument_count + named_argument_count;
  if (!target.is_static()) ++argument_count;
  body += StaticCall(TokenPosition::kNoSource, target, argument_count,
                     argument_names);

  // Return the result.
  body += Return(function_node_helper.end_position_);

  return new (Z)
      FlowGraph(*parsed_function(), flow_graph_builder_->graph_entry_,
                flow_graph_builder_->next_block_id_ - 1);
}

// This method follows the logic of
// StreamingFlowGraphBuilder::BuildGraphOfImplicitClosureFunction.  For
// additional details on converted closure functions, please, see the comment on
// the method Function::ConvertedClosureFunction.
FlowGraph* StreamingFlowGraphBuilder::BuildGraphOfConvertedClosureFunction(
    const Function& function) {
  const Function& target = Function::ZoneHandle(Z, function.parent_function());

  TargetEntryInstr* normal_entry = flow_graph_builder_->BuildTargetEntry();
  flow_graph_builder_->graph_entry_ = new (Z) GraphEntryInstr(
      *parsed_function(), normal_entry, Compiler::kNoOSRDeoptId);
  SetupDefaultParameterValues();

  Fragment body(normal_entry);
  body += flow_graph_builder_->CheckStackOverflowInPrologue();
  body += NullConstant();
  LocalVariable* result = MakeTemporary();

  // Load all the arguments.
  ASSERT(target.is_static());

  // TODO(30455): Kernel generic methods undone. Since the frontend can't yet
  // emit generic methods into kernel, all type parameters to the target must
  // come from the context. When generic methods are fully supported, we will
  // need to get the type arguments provided by the caller and append them to
  // the captured type arguments via 'prependTypeArguments'.

  FunctionNodeHelper function_node_helper(this);
  function_node_helper.ReadUntilExcluding(FunctionNodeHelper::kTypeParameters);
  intptr_t type_param_count = PeekUInt();
  function_node_helper.ReadUntilExcluding(
      FunctionNodeHelper::kPositionalParameters);

  // Positional.
  const intptr_t positional_argument_count = ReadListLength();

  // The first argument is the instance of the closure class.  For converted
  // closures its context field contains the context vector that is used by the
  // converted top-level function (target) explicitly and that should be passed
  // to that function as the first parameter.
  body += LoadLocal(LookupVariable(
      ReaderOffset() + relative_kernel_offset_));  // 0th variable offset.
  body += flow_graph_builder_->LoadField(Closure::context_offset());
  LocalVariable* context = MakeTemporary();

  if (type_param_count > 0) {
    body += LoadLocal(context);
    body += flow_graph_builder_->LoadField(Context::variable_offset(0));
    body += PushArgument();
  }

  body += LoadLocal(context);
  body += PushArgument();
  SkipVariableDeclaration();  // read 0th variable.

  // The rest of the parameters are the same for the method of the Closure class
  // being invoked and the top-level function (target).
  for (intptr_t i = 1; i < positional_argument_count; i++) {
    body += LoadLocal(LookupVariable(
        ReaderOffset() + relative_kernel_offset_));  // ith variable offset.
    body += PushArgument();
    SkipVariableDeclaration();  // read ith variable.
  }

  // Named.
  const intptr_t named_argument_count = ReadListLength();
  Array& argument_names = Array::ZoneHandle(Z);
  if (named_argument_count > 0) {
    argument_names = Array::New(named_argument_count);
    for (intptr_t i = 0; i < named_argument_count; i++) {
      // ith variable offset.
      body +=
          LoadLocal(LookupVariable(ReaderOffset() + relative_kernel_offset_));
      body += PushArgument();

      // read ith variable.
      VariableDeclarationHelper helper(this);
      helper.ReadUntilExcluding(VariableDeclarationHelper::kEnd);

      argument_names.SetAt(i, H.DartSymbol(helper.name_index_));
    }
  }

  // Forward them to the target.
  intptr_t argument_count = positional_argument_count + named_argument_count;
  if (type_param_count) ++argument_count;
  body += StaticCall(TokenPosition::kNoSource, target, argument_count,
                     argument_names, type_param_count);

  // Return the result.
  body += StoreLocal(TokenPosition::kNoSource, result);
  body += Drop();
  body += Drop();
  body += Return(function_node_helper.end_position_);

  return new (Z)
      FlowGraph(*parsed_function(), flow_graph_builder_->graph_entry_,
                flow_graph_builder_->next_block_id_ - 1);
}

FlowGraph* StreamingFlowGraphBuilder::BuildGraphOfFunction(bool constructor) {
  const Function& dart_function = parsed_function()->function();
  TargetEntryInstr* normal_entry = flow_graph_builder_->BuildTargetEntry();
  flow_graph_builder_->graph_entry_ = new (Z) GraphEntryInstr(
      *parsed_function(), normal_entry, flow_graph_builder_->osr_id_);

  SetupDefaultParameterValues();

  Fragment body;
  if (!dart_function.is_native())
    body += flow_graph_builder_->CheckStackOverflowInPrologue();
  intptr_t context_size =
      parsed_function()->node_sequence()->scope()->num_context_variables();
  if (context_size > 0) {
    body += flow_graph_builder_->PushContext(context_size);
    LocalVariable* context = MakeTemporary();

    // Copy captured parameters from the stack into the context.
    LocalScope* scope = parsed_function()->node_sequence()->scope();
    intptr_t parameter_count = dart_function.NumParameters();
    intptr_t parameter_index = parsed_function()->first_parameter_index();
    for (intptr_t i = 0; i < parameter_count; ++i, --parameter_index) {
      LocalVariable* variable = scope->VariableAt(i);
      if (variable->is_captured()) {
        // There is no LocalVariable describing the on-stack parameter so
        // create one directly and use the same type.
        LocalVariable* parameter = new (Z)
            LocalVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
                          Symbols::TempParam(), variable->type());
        parameter->set_index(parameter_index);
        // Mark the stack variable so it will be ignored by the code for
        // try/catch.
        parameter->set_is_captured_parameter(true);

        // Copy the parameter from the stack to the context.  Overwrite it
        // with a null constant on the stack so the original value is
        // eligible for garbage collection.
        body += LoadLocal(context);
        body += LoadLocal(parameter);
        body += flow_graph_builder_->StoreInstanceField(
            TokenPosition::kNoSource,
            Context::variable_offset(variable->index()));
        body += NullConstant();
        body += StoreLocal(TokenPosition::kNoSource, parameter);
        body += Drop();
      }
    }
    body += Drop();  // The context.
  }
  if (constructor) {
    // TODO(27590): Currently the [VariableDeclaration]s from the
    // initializers will be visible inside the entire body of the constructor.
    // We should make a separate scope for them.
    body += BuildInitializers(Class::Handle(Z, dart_function.Owner()));
  }

  FunctionNodeHelper function_node_helper(this);
  function_node_helper.ReadUntilExcluding(
      FunctionNodeHelper::kPositionalParameters);
  intptr_t first_parameter_offset = -1;
  {
    AlternativeReadingScope alt(reader_);
    intptr_t list_length = ReadListLength();  // read number of positionals.
    if (list_length > 0) {
      first_parameter_offset = ReaderOffset() + relative_kernel_offset_;
    }
  }
  // Current position: About to read list of positionals.

  // The specification defines the result of `a == b` to be:
  //
  //   a) if either side is `null` then the result is `identical(a, b)`.
  //   b) else the result is `a.operator==(b)`
  //
  // For user-defined implementations of `operator==` we need therefore
  // implement the handling of a).
  //
  // The default `operator==` implementation in `Object` is implemented in terms
  // of identical (which we assume here!) which means that case a) is actually
  // included in b).  So we just use the normal implementation in the body.
  if ((dart_function.NumParameters() == 2) &&
      (dart_function.name() == Symbols::EqualOperator().raw()) &&
      (dart_function.Owner() != I->object_store()->object_class())) {
    LocalVariable* parameter = LookupVariable(first_parameter_offset);

    TargetEntryInstr* null_entry;
    TargetEntryInstr* non_null_entry;

    body += LoadLocal(parameter);
    body += BranchIfNull(&null_entry, &non_null_entry);

    // The argument was `null` and the receiver is not the null class (we only
    // go into this branch for user-defined == operators) so we can return
    // false.
    Fragment null_fragment(null_entry);
    null_fragment += Constant(Bool::False());
    null_fragment += Return(dart_function.end_token_pos());

    body = Fragment(body.entry, non_null_entry);
  }

  // If we run in checked mode, we have to check the type of the passed
  // arguments.
  if (I->type_checks()) {
    // Positional.
    intptr_t list_length = ReadListLength();
    for (intptr_t i = 0; i < list_length; ++i) {
      // ith variable offset.
      body +=
          LoadLocal(LookupVariable(ReaderOffset() + relative_kernel_offset_));
      body += CheckVariableTypeInCheckedMode(ReaderOffset() +
                                             relative_kernel_offset_);
      body += Drop();
      SkipVariableDeclaration();  // read ith variable.
    }

    // Named.
    list_length = ReadListLength();
    for (intptr_t i = 0; i < list_length; ++i) {
      // ith variable offset.
      body +=
          LoadLocal(LookupVariable(ReaderOffset() + relative_kernel_offset_));
      body += CheckVariableTypeInCheckedMode(ReaderOffset() +
                                             relative_kernel_offset_);
      body += Drop();
      SkipVariableDeclaration();  // read ith variable.
    }

    function_node_helper.SetJustRead(FunctionNodeHelper::kNamedParameters);
  }

  function_node_helper.ReadUntilExcluding(FunctionNodeHelper::kBody);

  bool has_body = ReadTag() == kSomething;  // read first part of body.

  if (dart_function.is_native()) {
    body += flow_graph_builder_->NativeFunctionBody(first_parameter_offset,
                                                    dart_function);
  } else if (has_body) {
    body += BuildStatement();  // read body.
  }
  if (body.is_open()) {
    body += NullConstant();
    body += Return(dart_function.end_token_pos());
  }

  // If functions body contains any yield points build switch statement that
  // selects a continuation point based on the value of :await_jump_var.
  if (!yield_continuations().is_empty()) {
    // The code we are building will be executed right after we enter
    // the function and before any nested contexts are allocated.
    // Reset current context_depth_ to match this.
    const intptr_t current_context_depth = flow_graph_builder_->context_depth_;
    flow_graph_builder_->context_depth_ =
        scopes()->yield_jump_variable->owner()->context_level();

    // Prepend an entry corresponding to normal entry to the function.
    yield_continuations().InsertAt(
        0, YieldContinuation(new (Z) DropTempsInstr(0, NULL),
                             CatchClauseNode::kInvalidTryIndex));
    yield_continuations()[0].entry->LinkTo(body.entry);

    // Build a switch statement.
    Fragment dispatch;

    // Load :await_jump_var into a temporary.
    dispatch += LoadLocal(scopes()->yield_jump_variable);
    dispatch += StoreLocal(TokenPosition::kNoSource, scopes()->switch_variable);
    dispatch += Drop();

    BlockEntryInstr* block = NULL;
    for (intptr_t i = 0; i < yield_continuations().length(); i++) {
      if (i == 1) {
        // This is not a normal entry but a resumption.  Restore
        // :current_context_var from :await_ctx_var.
        // Note: after this point context_depth_ does not match current context
        // depth so we should not access any local variables anymore.
        dispatch += LoadLocal(scopes()->yield_context_variable);
        dispatch += StoreLocal(TokenPosition::kNoSource,
                               parsed_function()->current_context_var());
        dispatch += Drop();
      }
      if (i == (yield_continuations().length() - 1)) {
        // We reached the last possility, no need to build more ifs.
        // Continue to the last continuation.
        // Note: continuations start with nop DropTemps instruction
        // which acts like an anchor, so we need to skip it.
        block->set_try_index(yield_continuations()[i].try_index);
        dispatch <<= yield_continuations()[i].entry->next();
        break;
      }

      // Build comparison:
      //
      //   if (:await_ctx_var == i) {
      //     -> yield_continuations()[i]
      //   } else ...
      //
      TargetEntryInstr* then;
      TargetEntryInstr* otherwise;
      dispatch += LoadLocal(scopes()->switch_variable);
      dispatch += IntConstant(i);
      dispatch += flow_graph_builder_->BranchIfStrictEqual(&then, &otherwise);

      // True branch is linked to appropriate continuation point.
      // Note: continuations start with nop DropTemps instruction
      // which acts like an anchor, so we need to skip it.
      then->LinkTo(yield_continuations()[i].entry->next());
      then->set_try_index(yield_continuations()[i].try_index);
      // False branch will contain the next comparison.
      dispatch = Fragment(dispatch.entry, otherwise);
      block = otherwise;
    }
    body = dispatch;

    flow_graph_builder_->context_depth_ = current_context_depth;
  }

  if (FLAG_causal_async_stacks &&
      (dart_function.IsAsyncClosure() || dart_function.IsAsyncGenClosure())) {
    // The code we are building will be executed right after we enter
    // the function and before any nested contexts are allocated.
    // Reset current context_depth_ to match this.
    const intptr_t current_context_depth = flow_graph_builder_->context_depth_;
    flow_graph_builder_->context_depth_ =
        scopes()->yield_jump_variable->owner()->context_level();

    Fragment instructions;
    LocalScope* scope = parsed_function()->node_sequence()->scope();

    const Function& target = Function::ZoneHandle(
        Z, I->object_store()->async_set_thread_stack_trace());
    ASSERT(!target.IsNull());

    // Fetch and load :async_stack_trace
    LocalVariable* async_stack_trace_var =
        scope->LookupVariable(Symbols::AsyncStackTraceVar(), false);
    ASSERT((async_stack_trace_var != NULL) &&
           async_stack_trace_var->is_captured());
    instructions += LoadLocal(async_stack_trace_var);
    instructions += PushArgument();

    // Call _asyncSetThreadStackTrace
    instructions += StaticCall(TokenPosition::kNoSource, target, 1);
    instructions += Drop();

    // TODO(29737): This sequence should be generated in order.
    body = instructions + body;
    flow_graph_builder_->context_depth_ = current_context_depth;
  }

  if (NeedsDebugStepCheck(dart_function, function_node_helper.position_)) {
    const intptr_t current_context_depth = flow_graph_builder_->context_depth_;
    flow_graph_builder_->context_depth_ = 0;
    // If a switch was added above: Start the switch by injecting a debuggable
    // safepoint so stepping over an await works.
    // If not, still start the body with a debuggable safepoint 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 parameter_count = dart_function.NumParameters();
    TokenPosition check_pos = TokenPosition::kNoSource;
    if (parameter_count > 0) {
      LocalScope* scope = parsed_function()->node_sequence()->scope();
      const LocalVariable& parameter = *scope->VariableAt(parameter_count - 1);
      check_pos = parameter.token_pos();
    }
    if (!check_pos.IsDebugPause()) {
      // No parameters or synthetic parameters.
      check_pos = function_node_helper.position_;
      ASSERT(check_pos.IsDebugPause());
    }

    // TODO(29737): This sequence should be generated in order.
    body = DebugStepCheck(check_pos) + body;
    flow_graph_builder_->context_depth_ = current_context_depth;
  }

  normal_entry->LinkTo(body.entry);

  GraphEntryInstr* graph_entry = flow_graph_builder_->graph_entry_;
  // When compiling for OSR, use a depth first search to find the OSR
  // entry and make graph entry jump to it instead of normal entry.
  // Catch entries are always considered reachable, even if they
  // become unreachable after OSR.
  if (flow_graph_builder_->osr_id_ != Compiler::kNoOSRDeoptId) {
    graph_entry->RelinkToOsrEntry(Z, flow_graph_builder_->next_block_id_);
  }
  return new (Z) FlowGraph(*parsed_function(), graph_entry,
                           flow_graph_builder_->next_block_id_ - 1);
}

FlowGraph* StreamingFlowGraphBuilder::BuildGraph(intptr_t kernel_offset) {
  const Function& function = parsed_function()->function();

  // Setup a [ActiveClassScope] and a [ActiveMemberScope] which will be used
  // e.g. for type translation.
  const Class& klass =
      Class::Handle(zone_, parsed_function()->function().Owner());

  Function& outermost_function = Function::Handle(Z);
  DiscoverEnclosingElements(Z, function, &outermost_function);

  ActiveClassScope active_class_scope(active_class(), &klass);
  ActiveMemberScope active_member(active_class(), &outermost_function);

  // The IR builder will create its own local variables and scopes, and it
  // will not need an AST.  The code generator will assume that there is a
  // local variable stack slot allocated for the current context and (I
  // think) that the runtime will expect it to be at a fixed offset which
  // requires allocating an unused expression temporary variable.
  set_scopes(parsed_function()->EnsureKernelScopes());

  SetOffset(kernel_offset);

  switch (function.kind()) {
    case RawFunction::kClosureFunction:
    case RawFunction::kImplicitClosureFunction:
    case RawFunction::kConvertedClosureFunction:
    case RawFunction::kRegularFunction:
    case RawFunction::kGetterFunction:
    case RawFunction::kSetterFunction: {
      ReadUntilFunctionNode();  // read until function node.
      if (function.IsImplicitClosureFunction()) {
        return BuildGraphOfImplicitClosureFunction(function);
      } else if (function.IsConvertedClosureFunction()) {
        return BuildGraphOfConvertedClosureFunction(function);
      }
      return BuildGraphOfFunction(false);
    }
    case RawFunction::kConstructor: {
      ReadUntilFunctionNode();  // read until function node.
      return BuildGraphOfFunction(!function.IsFactory());
    }
    case RawFunction::kImplicitGetter:
    case RawFunction::kImplicitStaticFinalGetter:
    case RawFunction::kImplicitSetter: {
      return IsStaticInitializer(function, Z)
                 ? BuildGraphOfStaticFieldInitializer()
                 : BuildGraphOfFieldAccessor(scopes()->setter_value);
    }
    case RawFunction::kMethodExtractor:
      return flow_graph_builder_->BuildGraphOfMethodExtractor(function);
    case RawFunction::kNoSuchMethodDispatcher:
      return flow_graph_builder_->BuildGraphOfNoSuchMethodDispatcher(function);
    case RawFunction::kInvokeFieldDispatcher:
      return flow_graph_builder_->BuildGraphOfInvokeFieldDispatcher(function);
    case RawFunction::kSignatureFunction:
    case RawFunction::kIrregexpFunction:
      break;
  }
  UNREACHABLE();
  return NULL;
}

Fragment StreamingFlowGraphBuilder::BuildStatementAt(intptr_t kernel_offset) {
  SetOffset(kernel_offset);
  return BuildStatement();  // read statement.
}

Fragment StreamingFlowGraphBuilder::BuildExpression(TokenPosition* position) {
  uint8_t payload = 0;
  Tag tag = ReadTag(&payload);  // read tag.
  switch (tag) {
    case kInvalidExpression:
      return BuildInvalidExpression(position);
    case kVariableGet:
      return BuildVariableGet(position);
    case kSpecializedVariableGet:
      return BuildVariableGet(payload, position);
    case kVariableSet:
      return BuildVariableSet(position);
    case kSpecializedVariableSet:
      return BuildVariableSet(payload, position);
    case kPropertyGet:
      return BuildPropertyGet(position);
    case kPropertySet:
      return BuildPropertySet(position);
    case kDirectPropertyGet:
      return BuildDirectPropertyGet(position);
    case kDirectPropertySet:
      return BuildDirectPropertySet(position);
    case kStaticGet:
      return BuildStaticGet(position);
    case kStaticSet:
      return BuildStaticSet(position);
    case kMethodInvocation:
      return BuildMethodInvocation(position);
    case kDirectMethodInvocation:
      return BuildDirectMethodInvocation(position);
    case kStaticInvocation:
      return BuildStaticInvocation(false, position);
    case kConstStaticInvocation:
      return BuildStaticInvocation(true, position);
    case kConstructorInvocation:
      return BuildConstructorInvocation(false, position);
    case kConstConstructorInvocation:
      return BuildConstructorInvocation(true, position);
    case kNot:
      return BuildNot(position);
    case kLogicalExpression:
      return BuildLogicalExpression(position);
    case kConditionalExpression:
      return BuildConditionalExpression(position);
    case kStringConcatenation:
      return BuildStringConcatenation(position);
    case kIsExpression:
      return BuildIsExpression(position);
    case kAsExpression:
      return BuildAsExpression(position);
    case kSymbolLiteral:
      return BuildSymbolLiteral(position);
    case kTypeLiteral:
      return BuildTypeLiteral(position);
    case kThisExpression:
      return BuildThisExpression(position);
    case kRethrow:
      return BuildRethrow(position);
    case kThrow:
      return BuildThrow(position);
    case kListLiteral:
      return BuildListLiteral(false, position);
    case kConstListLiteral:
      return BuildListLiteral(true, position);
    case kMapLiteral:
      return BuildMapLiteral(false, position);
    case kConstMapLiteral:
      return BuildMapLiteral(true, position);
    case kFunctionExpression:
      return BuildFunctionExpression();
    case kLet:
      return BuildLet(position);
    case kBigIntLiteral:
      return BuildBigIntLiteral(position);
    case kStringLiteral:
      return BuildStringLiteral(position);
    case kSpecialIntLiteral:
      return BuildIntLiteral(payload, position);
    case kNegativeIntLiteral:
      return BuildIntLiteral(true, position);
    case kPositiveIntLiteral:
      return BuildIntLiteral(false, position);
    case kDoubleLiteral:
      return BuildDoubleLiteral(position);
    case kTrueLiteral:
      return BuildBoolLiteral(true, position);
    case kFalseLiteral:
      return BuildBoolLiteral(false, position);
    case kNullLiteral:
      return BuildNullLiteral(position);
    case kVectorCreation:
      return BuildVectorCreation(position);
    case kVectorGet:
      return BuildVectorGet(position);
    case kVectorSet:
      return BuildVectorSet(position);
    case kVectorCopy:
      return BuildVectorCopy(position);
    case kClosureCreation:
      return BuildClosureCreation(position);
    default:
      UNREACHABLE();
  }

  return Fragment();
}

Fragment StreamingFlowGraphBuilder::BuildStatement() {
  Tag tag = ReadTag();  // read tag.
  switch (tag) {
    case kInvalidStatement:
      return BuildInvalidStatement();
    case kExpressionStatement:
      return BuildExpressionStatement();
    case kBlock:
      return BuildBlock();
    case kEmptyStatement:
      return BuildEmptyStatement();
    case kAssertStatement:
      return BuildAssertStatement();
    case kLabeledStatement:
      return BuildLabeledStatement();
    case kBreakStatement:
      return BuildBreakStatement();
    case kWhileStatement:
      return BuildWhileStatement();
    case kDoStatement:
      return BuildDoStatement();
    case kForStatement:
      return BuildForStatement();
    case kForInStatement:
      return BuildForInStatement(false);
    case kAsyncForInStatement:
      return BuildForInStatement(true);
    case kSwitchStatement:
      return BuildSwitchStatement();
    case kContinueSwitchStatement:
      return BuildContinueSwitchStatement();
    case kIfStatement:
      return BuildIfStatement();
    case kReturnStatement:
      return BuildReturnStatement();
    case kTryCatch:
      return BuildTryCatch();
    case kTryFinally:
      return BuildTryFinally();
    case kYieldStatement:
      return BuildYieldStatement();
    case kVariableDeclaration:
      return BuildVariableDeclaration();
    case kFunctionDeclaration:
      return BuildFunctionDeclaration();
    default:
      UNREACHABLE();
  }
  return Fragment();
}

intptr_t StreamingFlowGraphBuilder::ReaderOffset() {
  return reader_->offset();
}

void StreamingFlowGraphBuilder::SetOffset(intptr_t offset) {
  reader_->set_offset(offset);
}

void StreamingFlowGraphBuilder::SkipBytes(intptr_t bytes) {
  reader_->set_offset(ReaderOffset() + bytes);
}

bool StreamingFlowGraphBuilder::ReadBool() {
  return reader_->ReadBool();
}

uint8_t StreamingFlowGraphBuilder::ReadByte() {
  return reader_->ReadByte();
}

uint32_t StreamingFlowGraphBuilder::ReadUInt() {
  return reader_->ReadUInt();
}

uint32_t StreamingFlowGraphBuilder::PeekUInt() {
  AlternativeReadingScope alt(reader_);
  return reader_->ReadUInt();
}

intptr_t StreamingFlowGraphBuilder::ReadListLength() {
  return reader_->ReadListLength();
}

StringIndex StreamingFlowGraphBuilder::ReadStringReference() {
  return StringIndex(ReadUInt());
}

NameIndex StreamingFlowGraphBuilder::ReadCanonicalNameReference() {
  return reader_->ReadCanonicalNameReference();
}

StringIndex StreamingFlowGraphBuilder::ReadNameAsStringIndex() {
  StringIndex name_index = ReadStringReference();  // read name index.
  if ((H.StringSize(name_index) >= 1) && H.CharacterAt(name_index, 0) == '_') {
    ReadUInt();  // read library index.
  }
  return name_index;
}

const String& StreamingFlowGraphBuilder::ReadNameAsMethodName() {
  StringIndex name_index = ReadStringReference();  // read name index.
  if ((H.StringSize(name_index) >= 1) && H.CharacterAt(name_index, 0) == '_') {
    NameIndex library_reference =
        ReadCanonicalNameReference();  // read library index.
    return H.DartMethodName(library_reference, name_index);
  } else {
    return H.DartMethodName(NameIndex(), name_index);
  }
}

const String& StreamingFlowGraphBuilder::ReadNameAsSetterName() {
  StringIndex name_index = ReadStringReference();  // read name index.
  if ((H.StringSize(name_index) >= 1) && H.CharacterAt(name_index, 0) == '_') {
    NameIndex library_reference =
        ReadCanonicalNameReference();  // read library index.
    return H.DartSetterName(library_reference, name_index);
  } else {
    return H.DartSetterName(NameIndex(), name_index);
  }
}

const String& StreamingFlowGraphBuilder::ReadNameAsGetterName() {
  StringIndex name_index = ReadStringReference();  // read name index.
  if ((H.StringSize(name_index) >= 1) && H.CharacterAt(name_index, 0) == '_') {
    NameIndex library_reference =
        ReadCanonicalNameReference();  // read library index.
    return H.DartGetterName(library_reference, name_index);
  } else {
    return H.DartGetterName(NameIndex(), name_index);
  }
}

const String& StreamingFlowGraphBuilder::ReadNameAsFieldName() {
  StringIndex name_index = ReadStringReference();  // read name index.
  if ((H.StringSize(name_index) >= 1) && H.CharacterAt(name_index, 0) == '_') {
    NameIndex library_reference =
        ReadCanonicalNameReference();  // read library index.
    return H.DartFieldName(library_reference, name_index);
  } else {
    return H.DartFieldName(NameIndex(), name_index);
  }
}

void StreamingFlowGraphBuilder::SkipStringReference() {
  ReadUInt();
}

void StreamingFlowGraphBuilder::SkipCanonicalNameReference() {
  ReadUInt();
}

void StreamingFlowGraphBuilder::SkipDartType() {
  Tag tag = ReadTag();
  switch (tag) {
    case kInvalidType:
    case kDynamicType:
    case kVoidType:
    case kBottomType:
    case kVectorType:
      // those contain nothing.
      return;
    case kInterfaceType:
      SkipInterfaceType(false);
      return;
    case kSimpleInterfaceType:
      SkipInterfaceType(true);
      return;
    case kFunctionType:
      SkipFunctionType(false);
      return;
    case kSimpleFunctionType:
      SkipFunctionType(true);
      return;
    case kTypeParameterType:
      ReadUInt();              // read index for parameter.
      SkipOptionalDartType();  // read bound bound.
      return;
    default:
      UNREACHABLE();
  }
}

void StreamingFlowGraphBuilder::SkipOptionalDartType() {
  Tag tag = ReadTag();  // read tag.
  if (tag == kNothing) {
    return;
  }
  ASSERT(tag == kSomething);

  SkipDartType();  // read type.
}

void StreamingFlowGraphBuilder::SkipInterfaceType(bool simple) {
  ReadUInt();  // read klass_name.
  if (!simple) {
    SkipListOfDartTypes();  // read list of types.
  }
}

void StreamingFlowGraphBuilder::SkipFunctionType(bool simple) {
  if (!simple) {
    SkipTypeParametersList();  // read type_parameters.
    ReadUInt();                // read required parameter count.
    ReadUInt();                // read total parameter count.
  }

  SkipListOfDartTypes();  // read positional_parameters types.

  if (!simple) {
    const intptr_t named_count =
        ReadListLength();  // read named_parameters list length.
    for (intptr_t i = 0; i < named_count; ++i) {
      // read string reference (i.e. named_parameters[i].name).
      SkipStringReference();
      SkipDartType();  // read named_parameters[i].type.
    }
  }

  SkipListOfStrings();  // read positional parameter names.

  if (!simple) {
    SkipCanonicalNameReference();  // read typedef reference.
  }

  SkipDartType();  // read return type.
}

void StreamingFlowGraphBuilder::SkipListOfExpressions() {
  intptr_t list_length = ReadListLength();  // read list length.
  for (intptr_t i = 0; i < list_length; ++i) {
    SkipExpression();  // read ith expression.
  }
}

void StreamingFlowGraphBuilder::SkipListOfDartTypes() {
  intptr_t list_length = ReadListLength();  // read list length.
  for (intptr_t i = 0; i < list_length; ++i) {
    SkipDartType();  // read ith type.
  }
}

void StreamingFlowGraphBuilder::SkipListOfStrings() {
  intptr_t list_length = ReadListLength();  // read list length.
  for (intptr_t i = 0; i < list_length; ++i) {
    SkipStringReference();  // read ith string index.
  }
}

void StreamingFlowGraphBuilder::SkipListOfVariableDeclarations() {
  intptr_t list_length = ReadListLength();  // read list length.
  for (intptr_t i = 0; i < list_length; ++i) {
    SkipVariableDeclaration();  // read ith variable declaration.
  }
}

void StreamingFlowGraphBuilder::SkipTypeParametersList() {
  intptr_t list_length = ReadListLength();  // read list length.
  for (intptr_t i = 0; i < list_length; ++i) {
    SkipStringReference();  // read ith name index.
    SkipDartType();         // read ith bound.
  }
}

void StreamingFlowGraphBuilder::SkipInitializer() {
  Tag tag = ReadTag();
  ReadByte();  // read isSynthetic flag.
  switch (tag) {
    case kInvalidInitializer:
      return;
    case kFieldInitializer:
      SkipCanonicalNameReference();  // read field_reference.
      SkipExpression();              // read value.
      return;
    case kSuperInitializer:
      SkipCanonicalNameReference();  // read target_reference.
      SkipArguments();               // read arguments.
      return;
    case kRedirectingInitializer:
      SkipCanonicalNameReference();  // read target_reference.
      SkipArguments();               // read arguments.
      return;
    case kLocalInitializer:
      SkipVariableDeclaration();  // read variable.
      return;
    default:
      UNREACHABLE();
  }
}

void StreamingFlowGraphBuilder::SkipExpression() {
  uint8_t payload = 0;
  Tag tag = ReadTag(&payload);
  switch (tag) {
    case kInvalidExpression:
      return;
    case kVariableGet:
      ReadPosition();          // read position.
      ReadUInt();              // read kernel position.
      ReadUInt();              // read relative variable index.
      SkipOptionalDartType();  // read promoted type.
      return;
    case kSpecializedVariableGet:
      ReadPosition();  // read position.
      ReadUInt();      // read kernel position.
      return;
    case kVariableSet:
      ReadPosition();    // read position.
      ReadUInt();        // read kernel position.
      ReadUInt();        // read relative variable index.
      SkipExpression();  // read expression.
      return;
    case kSpecializedVariableSet:
      ReadPosition();    // read position.
      ReadUInt();        // read kernel position.
      SkipExpression();  // read expression.
      return;
    case kPropertyGet:
      ReadPosition();    // read position.
      SkipExpression();  // read receiver.
      SkipName();        // read name.
      SkipCanonicalNameReference();  // read interface_target_reference.
      return;
    case kPropertySet:
      ReadPosition();    // read position.
      SkipExpression();  // read receiver.
      SkipName();        // read name.
      SkipExpression();  // read value.
      SkipCanonicalNameReference();  // read interface_target_reference.
      return;
    case kDirectPropertyGet:
      ReadPosition();                // read position.
      SkipExpression();              // read receiver.
      SkipCanonicalNameReference();  // read target_reference.
      return;
    case kDirectPropertySet:
      ReadPosition();                // read position.
      SkipExpression();              // read receiver.
      SkipCanonicalNameReference();  // read target_reference.
      SkipExpression();              // read value·
      return;
    case kStaticGet:
      ReadPosition();                // read position.
      SkipCanonicalNameReference();  // read target_reference.
      return;
    case kStaticSet:
      ReadPosition();                // read position.
      SkipCanonicalNameReference();  // read target_reference.
      SkipExpression();              // read expression.
      return;
    case kMethodInvocation:
      ReadPosition();    // read position.
      SkipExpression();  // read receiver.
      SkipName();        // read name.
      SkipArguments();   // read arguments.
      SkipCanonicalNameReference();  // read interface_target_reference.
      return;
    case kDirectMethodInvocation:
      SkipExpression();              // read receiver.
      SkipCanonicalNameReference();  // read target_reference.
      SkipArguments();               // read arguments.
      return;
    case kStaticInvocation:
    case kConstStaticInvocation:
      ReadPosition();                // read position.
      SkipCanonicalNameReference();  // read procedure_reference.
      SkipArguments();               // read arguments.
      return;
    case kConstructorInvocation:
    case kConstConstructorInvocation:
      ReadPosition();                // read position.
      SkipCanonicalNameReference();  // read target_reference.
      SkipArguments();               // read arguments.
      return;
    case kNot:
      SkipExpression();  // read expression.
      return;
    case kLogicalExpression:
      SkipExpression();  // read left.
      SkipBytes(1);      // read operator.
      SkipExpression();  // read right.
      return;
    case kConditionalExpression:
      SkipExpression();        // read condition.
      SkipExpression();        // read then.
      SkipExpression();        // read otherwise.
      SkipOptionalDartType();  // read unused static type.
      return;
    case kStringConcatenation:
      ReadPosition();           // read position.
      SkipListOfExpressions();  // read list of expressions.
      return;
    case kIsExpression:
      ReadPosition();    // read position.
      SkipExpression();  // read operand.
      SkipDartType();    // read type.
      return;
    case kAsExpression:
      ReadPosition();    // read position.
      SkipExpression();  // read operand.
      SkipDartType();    // read type.
      return;
    case kSymbolLiteral:
      SkipStringReference();  // read index into string table.
      return;
    case kTypeLiteral:
      SkipDartType();  // read type.
      return;
    case kThisExpression:
      return;
    case kRethrow:
      ReadPosition();  // read position.
      return;
    case kThrow:
      ReadPosition();    // read position.
      SkipExpression();  // read expression.
      return;
    case kListLiteral:
    case kConstListLiteral:
      ReadPosition();           // read position.
      SkipDartType();           // read type.
      SkipListOfExpressions();  // read list of expressions.
      return;
    case kMapLiteral:
    case kConstMapLiteral: {
      ReadPosition();                           // read position.
      SkipDartType();                           // read key type.
      SkipDartType();                           // read value type.
      intptr_t list_length = ReadListLength();  // read list length.
      for (intptr_t i = 0; i < list_length; ++i) {
        SkipExpression();  // read ith key.
        SkipExpression();  // read ith value.
      }
      return;
    }
    case kFunctionExpression:
      ReadPosition();      // read position.
      SkipFunctionNode();  // read function node.
      return;
    case kLet:
      SkipVariableDeclaration();  // read variable declaration.
      SkipExpression();           // read expression.
      return;
    case kVectorCreation:
      ReadUInt();  // read value.
      return;
    case kVectorGet:
      SkipExpression();  // read vector expression.
      ReadUInt();        // read index.
      return;
    case kVectorSet:
      SkipExpression();  // read vector expression.
      ReadUInt();        // read index.
      SkipExpression();  // read value.
      return;
    case kVectorCopy:
      SkipExpression();  // read vector expression.
      return;
    case kClosureCreation:
      SkipCanonicalNameReference();  // read top-level function reference.
      SkipExpression();              // read context vector.
      SkipDartType();                // read function type.
      SkipListOfDartTypes();         // read type arguments.
      return;
    case kBigIntLiteral:
      SkipStringReference();  // read string reference.
      return;
    case kStringLiteral:
      SkipStringReference();  // read string reference.
      return;
    case kSpecialIntLiteral:
      return;
    case kNegativeIntLiteral:
      ReadUInt();  // read value.
      return;
    case kPositiveIntLiteral:
      ReadUInt();  // read value.
      return;
    case kDoubleLiteral:
      SkipStringReference();  // read index into string table.
      return;
    case kTrueLiteral:
      return;
    case kFalseLiteral:
      return;
    case kNullLiteral:
      return;
    default:
      UNREACHABLE();
  }
}

void StreamingFlowGraphBuilder::SkipStatement() {
  Tag tag = ReadTag();  // read tag.
  switch (tag) {
    case kInvalidStatement:
      return;
    case kExpressionStatement:
      SkipExpression();  // read expression.
      return;
    case kBlock: {
      intptr_t list_length = ReadListLength();  // read number of statements.
      for (intptr_t i = 0; i < list_length; ++i) {
        SkipStatement();  // read ith statement.
      }
      return;
    }
    case kEmptyStatement:
      return;
    case kAssertStatement: {
      SkipExpression();     // Read condition.
      ReadPosition();       // read condition start offset.
      ReadPosition();       // read condition end offset.
      Tag tag = ReadTag();  // read (first part of) message.
      if (tag == kSomething) {
        SkipExpression();  // read (rest of) message.
      }
      return;
    }
    case kLabeledStatement:
      SkipStatement();  // read body.
      return;
    case kBreakStatement:
      ReadPosition();  // read position.
      ReadUInt();      // read target_index.
      return;
    case kWhileStatement:
      ReadPosition();    // read position.
      SkipExpression();  // read condition.
      SkipStatement();   // read body.
      return;
    case kDoStatement:
      ReadPosition();    // read position.
      SkipStatement();   // read body.
      SkipExpression();  // read condition.
      return;
    case kForStatement: {
      ReadPosition();                    // read position.
      SkipListOfVariableDeclarations();  // read variables.
      Tag tag = ReadTag();               // Read first part of condition.
      if (tag == kSomething) {
        SkipExpression();  // read rest of condition.
      }
      SkipListOfExpressions();  // read updates.
      SkipStatement();          // read body.
      return;
    }
    case kForInStatement:
    case kAsyncForInStatement:
      ReadPosition();             // read position.
      ReadPosition();             // read body position.
      SkipVariableDeclaration();  // read variable.
      SkipExpression();           // read iterable.
      SkipStatement();            // read body.
      return;
    case kSwitchStatement: {
      SkipExpression();                   // read condition.
      int case_count = ReadListLength();  // read number of cases.
      for (intptr_t i = 0; i < case_count; ++i) {
        int expression_count = ReadListLength();  // read number of expressions.
        for (intptr_t j = 0; j < expression_count; ++j) {
          ReadPosition();    // read jth position.
          SkipExpression();  // read jth expression.
        }
        ReadBool();       // read is_default.
        SkipStatement();  // read body.
      }
      return;
    }
    case kContinueSwitchStatement:
      ReadUInt();  // read target_index.
      return;
    case kIfStatement:
      SkipExpression();  // read condition.
      SkipStatement();   // read then.
      SkipStatement();   // read otherwise.
      return;
    case kReturnStatement: {
      ReadPosition();       // read position
      Tag tag = ReadTag();  // read (first part of) expression.
      if (tag == kSomething) {
        SkipExpression();  // read (rest of) expression.
      }
      return;
    }
    case kTryCatch: {
      SkipStatement();  // read body.
      ReadBool();       // read any_catch_needs_stack_trace.
      intptr_t catch_count = ReadListLength();  // read number of catches.
      for (intptr_t i = 0; i < catch_count; ++i) {
        SkipDartType();   // read guard.
        tag = ReadTag();  // read first part of exception.
        if (tag == kSomething) {
          SkipVariableDeclaration();  // read exception.
        }
        tag = ReadTag();  // read first part of stack trace.
        if (tag == kSomething) {
          SkipVariableDeclaration();  // read stack trace.
        }
        SkipStatement();  // read body.
      }
      return;
    }
    case kTryFinally:
      SkipStatement();  // read body.
      SkipStatement();  // read finalizer.
      return;
    case kYieldStatement: {
      TokenPosition position = ReadPosition();  // read position.
      record_yield_position(position);
      ReadByte();        // read flags.
      SkipExpression();  // read expression.
      return;
    }
    case kVariableDeclaration:
      SkipVariableDeclaration();  // read variable declaration.
      return;
    case kFunctionDeclaration:
      ReadPosition();             // read position.
      SkipVariableDeclaration();  // read variable.
      SkipFunctionNode();         // read function node.
      return;
    default:
      UNREACHABLE();
  }
}

void StreamingFlowGraphBuilder::SkipFunctionNode() {
  FunctionNodeHelper function_node_helper(this);
  function_node_helper.ReadUntilExcluding(FunctionNodeHelper::kEnd);
}

void StreamingFlowGraphBuilder::SkipName() {
  StringIndex name_index = ReadStringReference();  // read name index.
  if ((H.StringSize(name_index) >= 1) && H.CharacterAt(name_index, 0) == '_') {
    SkipCanonicalNameReference();  // read library index.
  }
}

void StreamingFlowGraphBuilder::SkipArguments() {
  ReadUInt();  // read argument count.

  SkipListOfDartTypes();    // read list of types.
  SkipListOfExpressions();  // read positionals.

  // List of named.
  intptr_t list_length = ReadListLength();  // read list length.
  for (intptr_t i = 0; i < list_length; ++i) {
    SkipStringReference();  // read ith name index.
    SkipExpression();       // read ith expression.
  }
}

void StreamingFlowGraphBuilder::SkipVariableDeclaration() {
  VariableDeclarationHelper helper(this);
  helper.ReadUntilExcluding(VariableDeclarationHelper::kEnd);
}

void StreamingFlowGraphBuilder::SkipLibraryCombinator() {
  ReadBool();                        // read is_show.
  intptr_t name_count = ReadUInt();  // read list length.
  for (intptr_t j = 0; j < name_count; ++j) {
    ReadUInt();  // read ith entry of name_indices.
  }
}

void StreamingFlowGraphBuilder::SkipLibraryDependency() {
  ReadFlags();
  SkipListOfExpressions();  // Annotations.
  ReadCanonicalNameReference();
  ReadStringReference();  // Name.
  intptr_t combinator_count = ReadListLength();
  for (intptr_t i = 0; i < combinator_count; ++i) {
    SkipLibraryCombinator();
  }
}

void StreamingFlowGraphBuilder::SkipLibraryPart() {
  SkipListOfExpressions();  // Read annotations.
  ReadStringReference();    // read uri_index.
}

void StreamingFlowGraphBuilder::SkipLibraryTypedef() {
  SkipCanonicalNameReference();  // read canonical name.
  ReadPosition();                // read position.
  SkipStringReference();         // read name index.
  ReadUInt();                    // read source_uri_index.
  SkipTypeParametersList();      // read type parameters.
  SkipDartType();                // read type.
}

TokenPosition StreamingFlowGraphBuilder::ReadPosition(bool record) {
  TokenPosition position = reader_->ReadPosition();
  if (record) {
    record_token_position(position);
  }
  return position;
}

void StreamingFlowGraphBuilder::record_token_position(TokenPosition position) {
  if (record_for_script_id_ == current_script_id_ &&
      record_token_positions_into_ != NULL) {
    record_token_positions_into_->Add(position.value());
  }
}

void StreamingFlowGraphBuilder::record_yield_position(TokenPosition position) {
  if (record_for_script_id_ == current_script_id_ &&
      record_yield_positions_into_ != NULL) {
    record_yield_positions_into_->Add(position.value());
  }
}

Tag StreamingFlowGraphBuilder::ReadTag(uint8_t* payload) {
  return reader_->ReadTag(payload);
}

Tag StreamingFlowGraphBuilder::PeekTag(uint8_t* payload) {
  return reader_->PeekTag(payload);
}

void StreamingFlowGraphBuilder::loop_depth_inc() {
  ++flow_graph_builder_->loop_depth_;
}

void StreamingFlowGraphBuilder::loop_depth_dec() {
  --flow_graph_builder_->loop_depth_;
}

intptr_t StreamingFlowGraphBuilder::for_in_depth() {
  return flow_graph_builder_->for_in_depth_;
}

void StreamingFlowGraphBuilder::for_in_depth_inc() {
  ++flow_graph_builder_->for_in_depth_;
}

void StreamingFlowGraphBuilder::for_in_depth_dec() {
  --flow_graph_builder_->for_in_depth_;
}

void StreamingFlowGraphBuilder::catch_depth_inc() {
  ++flow_graph_builder_->catch_depth_;
}

void StreamingFlowGraphBuilder::catch_depth_dec() {
  --flow_graph_builder_->catch_depth_;
}

void StreamingFlowGraphBuilder::try_depth_inc() {
  ++flow_graph_builder_->try_depth_;
}

void StreamingFlowGraphBuilder::try_depth_dec() {
  --flow_graph_builder_->try_depth_;
}

intptr_t StreamingFlowGraphBuilder::CurrentTryIndex() {
  return flow_graph_builder_->CurrentTryIndex();
}

intptr_t StreamingFlowGraphBuilder::AllocateTryIndex() {
  return flow_graph_builder_->AllocateTryIndex();
}

LocalVariable* StreamingFlowGraphBuilder::CurrentException() {
  return flow_graph_builder_->CurrentException();
}

LocalVariable* StreamingFlowGraphBuilder::CurrentStackTrace() {
  return flow_graph_builder_->CurrentStackTrace();
}

CatchBlock* StreamingFlowGraphBuilder::catch_block() {
  return flow_graph_builder_->catch_block_;
}

ActiveClass* StreamingFlowGraphBuilder::active_class() {
  return &flow_graph_builder_->active_class_;
}

ScopeBuildingResult* StreamingFlowGraphBuilder::scopes() {
  return flow_graph_builder_->scopes_;
}

void StreamingFlowGraphBuilder::set_scopes(ScopeBuildingResult* scope) {
  flow_graph_builder_->scopes_ = scope;
}

ParsedFunction* StreamingFlowGraphBuilder::parsed_function() {
  return flow_graph_builder_->parsed_function_;
}

TryFinallyBlock* StreamingFlowGraphBuilder::try_finally_block() {
  return flow_graph_builder_->try_finally_block_;
}

SwitchBlock* StreamingFlowGraphBuilder::switch_block() {
  return flow_graph_builder_->switch_block_;
}

BreakableBlock* StreamingFlowGraphBuilder::breakable_block() {
  return flow_graph_builder_->breakable_block_;
}

GrowableArray<YieldContinuation>&
StreamingFlowGraphBuilder::yield_continuations() {
  return flow_graph_builder_->yield_continuations_;
}

Value* StreamingFlowGraphBuilder::stack() {
  return flow_graph_builder_->stack_;
}

void StreamingFlowGraphBuilder::Push(Definition* definition) {
  flow_graph_builder_->Push(definition);
}

Value* StreamingFlowGraphBuilder::Pop() {
  return flow_graph_builder_->Pop();
}

Tag StreamingFlowGraphBuilder::PeekArgumentsFirstPositionalTag() {
  // read parts of arguments, then go back to before doing so.
  AlternativeReadingScope alt(reader_);
  ReadUInt();  // read number of arguments.

  SkipListOfDartTypes();  // Read list of types.

  // List of positional.
  intptr_t list_length = ReadListLength();  // read list length.
  for (intptr_t i = 0; i < list_length; ++i) {
    return ReadTag();  // read first tag.
  }

  UNREACHABLE();
  return kNothing;
}

const TypeArguments& StreamingFlowGraphBuilder::PeekArgumentsInstantiatedType(
    const Class& klass) {
  // read parts of arguments, then go back to before doing so.
  AlternativeReadingScope alt(reader_);
  ReadUInt();                               // read argument count.
  intptr_t list_length = ReadListLength();  // read types list length.
  return T.BuildInstantiatedTypeArguments(klass, list_length);  // read types.
}

intptr_t StreamingFlowGraphBuilder::PeekArgumentsCount() {
  return PeekUInt();
}

intptr_t StreamingFlowGraphBuilder::PeekArgumentsTypeCount() {
  AlternativeReadingScope alt(reader_);
  ReadUInt();               // read arguments count.
  return ReadListLength();  // read length of types list.
}

void StreamingFlowGraphBuilder::SkipArgumentsBeforeActualArguments() {
  ReadUInt();             // read arguments count.
  SkipListOfDartTypes();  // read list of types.
}

LocalVariable* StreamingFlowGraphBuilder::LookupVariable(
    intptr_t kernel_offset) {
  return flow_graph_builder_->LookupVariable(kernel_offset);
}

LocalVariable* StreamingFlowGraphBuilder::MakeTemporary() {
  return flow_graph_builder_->MakeTemporary();
}

Token::Kind StreamingFlowGraphBuilder::MethodKind(const String& name) {
  return flow_graph_builder_->MethodKind(name);
}

RawFunction* StreamingFlowGraphBuilder::LookupMethodByMember(
    NameIndex target,
    const String& method_name) {
  return flow_graph_builder_->LookupMethodByMember(target, method_name);
}

bool StreamingFlowGraphBuilder::NeedsDebugStepCheck(const Function& function,
                                                    TokenPosition position) {
  return flow_graph_builder_->NeedsDebugStepCheck(function, position);
}

bool StreamingFlowGraphBuilder::NeedsDebugStepCheck(Value* value,
                                                    TokenPosition position) {
  return flow_graph_builder_->NeedsDebugStepCheck(value, position);
}

void StreamingFlowGraphBuilder::InlineBailout(const char* reason) {
  flow_graph_builder_->InlineBailout(reason);
}

Fragment StreamingFlowGraphBuilder::DebugStepCheck(TokenPosition position) {
  return flow_graph_builder_->DebugStepCheck(position);
}

Fragment StreamingFlowGraphBuilder::LoadLocal(LocalVariable* variable) {
  return flow_graph_builder_->LoadLocal(variable);
}

Fragment StreamingFlowGraphBuilder::Return(TokenPosition position) {
  return flow_graph_builder_->Return(position);
}

Fragment StreamingFlowGraphBuilder::PushArgument() {
  return flow_graph_builder_->PushArgument();
}

Fragment StreamingFlowGraphBuilder::EvaluateAssertion() {
  return flow_graph_builder_->EvaluateAssertion();
}

Fragment StreamingFlowGraphBuilder::RethrowException(TokenPosition position,
                                                     int catch_try_index) {
  return flow_graph_builder_->RethrowException(position, catch_try_index);
}

Fragment StreamingFlowGraphBuilder::ThrowNoSuchMethodError() {
  return flow_graph_builder_->ThrowNoSuchMethodError();
}

Fragment StreamingFlowGraphBuilder::Constant(const Object& value) {
  return flow_graph_builder_->Constant(value);
}

Fragment StreamingFlowGraphBuilder::IntConstant(int64_t value) {
  return flow_graph_builder_->IntConstant(value);
}

Fragment StreamingFlowGraphBuilder::LoadStaticField() {
  return flow_graph_builder_->LoadStaticField();
}

Fragment StreamingFlowGraphBuilder::StaticCall(TokenPosition position,
                                               const Function& target,
                                               intptr_t argument_count) {
  return flow_graph_builder_->StaticCall(position, target, argument_count);
}

Fragment StreamingFlowGraphBuilder::StaticCall(TokenPosition position,
                                               const Function& target,
                                               intptr_t argument_count,
                                               const Array& argument_names,
                                               intptr_t type_args_count) {
  return flow_graph_builder_->StaticCall(position, target, argument_count,
                                         argument_names, type_args_count);
}

Fragment StreamingFlowGraphBuilder::InstanceCall(
    TokenPosition position,
    const String& name,
    Token::Kind kind,
    intptr_t argument_count,
    intptr_t checked_argument_count) {
  const intptr_t kTypeArgsLen = 0;
  return flow_graph_builder_->InstanceCall(
      position, name, kind, kTypeArgsLen, argument_count, Array::null_array(),
      checked_argument_count, Function::null_function());
}

Fragment StreamingFlowGraphBuilder::InstanceCall(
    TokenPosition position,
    const String& name,
    Token::Kind kind,
    intptr_t type_args_len,
    intptr_t argument_count,
    const Array& argument_names,
    intptr_t checked_argument_count,
    const Function& interface_target) {
  return flow_graph_builder_->InstanceCall(
      position, name, kind, type_args_len, argument_count, argument_names,
      checked_argument_count, interface_target);
}

Fragment StreamingFlowGraphBuilder::ThrowException(TokenPosition position) {
  return flow_graph_builder_->ThrowException(position);
}

Fragment StreamingFlowGraphBuilder::BooleanNegate() {
  return flow_graph_builder_->BooleanNegate();
}

Fragment StreamingFlowGraphBuilder::TranslateInstantiatedTypeArguments(
    const TypeArguments& type_arguments) {
  return flow_graph_builder_->TranslateInstantiatedTypeArguments(
      type_arguments);
}

Fragment StreamingFlowGraphBuilder::StrictCompare(Token::Kind kind,
                                                  bool number_check) {
  return flow_graph_builder_->StrictCompare(kind, number_check);
}

Fragment StreamingFlowGraphBuilder::AllocateObject(TokenPosition position,
                                                   const Class& klass,
                                                   intptr_t argument_count) {
  return flow_graph_builder_->AllocateObject(position, klass, argument_count);
}

Fragment StreamingFlowGraphBuilder::AllocateObject(
    const Class& klass,
    const Function& closure_function) {
  return flow_graph_builder_->AllocateObject(klass, closure_function);
}

Fragment StreamingFlowGraphBuilder::AllocateContext(intptr_t size) {
  return flow_graph_builder_->AllocateContext(size);
}

Fragment StreamingFlowGraphBuilder::LoadField(intptr_t offset) {
  return flow_graph_builder_->LoadField(offset);
}

Fragment StreamingFlowGraphBuilder::StoreLocal(TokenPosition position,
                                               LocalVariable* variable) {
  return flow_graph_builder_->StoreLocal(position, variable);
}

Fragment StreamingFlowGraphBuilder::StoreStaticField(TokenPosition position,
                                                     const Field& field) {
  return flow_graph_builder_->StoreStaticField(position, field);
}

Fragment StreamingFlowGraphBuilder::StoreInstanceField(TokenPosition position,
                                                       intptr_t offset) {
  return flow_graph_builder_->StoreInstanceField(position, offset);
}

Fragment StreamingFlowGraphBuilder::StringInterpolate(TokenPosition position) {
  return flow_graph_builder_->StringInterpolate(position);
}

Fragment StreamingFlowGraphBuilder::StringInterpolateSingle(
    TokenPosition position) {
  return flow_graph_builder_->StringInterpolateSingle(position);
}

Fragment StreamingFlowGraphBuilder::ThrowTypeError() {
  return flow_graph_builder_->ThrowTypeError();
}

Fragment StreamingFlowGraphBuilder::LoadInstantiatorTypeArguments() {
  return flow_graph_builder_->LoadInstantiatorTypeArguments();
}

Fragment StreamingFlowGraphBuilder::LoadFunctionTypeArguments() {
  return flow_graph_builder_->LoadFunctionTypeArguments();
}

Fragment StreamingFlowGraphBuilder::InstantiateType(const AbstractType& type) {
  return flow_graph_builder_->InstantiateType(type);
}

Fragment StreamingFlowGraphBuilder::CreateArray() {
  return flow_graph_builder_->CreateArray();
}

Fragment StreamingFlowGraphBuilder::StoreIndexed(intptr_t class_id) {
  return flow_graph_builder_->StoreIndexed(class_id);
}

Fragment StreamingFlowGraphBuilder::CheckStackOverflow() {
  return flow_graph_builder_->CheckStackOverflow();
}

Fragment StreamingFlowGraphBuilder::CloneContext() {
  return flow_graph_builder_->CloneContext();
}

Fragment StreamingFlowGraphBuilder::TranslateFinallyFinalizers(
    TryFinallyBlock* outer_finally,
    intptr_t target_context_depth) {
  // TranslateFinallyFinalizers can move the readers offset.
  // Save the current position and restore it afterwards.
  AlternativeReadingScope alt(reader_);
  return flow_graph_builder_->TranslateFinallyFinalizers(outer_finally,
                                                         target_context_depth);
}

Fragment StreamingFlowGraphBuilder::BranchIfTrue(
    TargetEntryInstr** then_entry,
    TargetEntryInstr** otherwise_entry,
    bool negate) {
  return flow_graph_builder_->BranchIfTrue(then_entry, otherwise_entry, negate);
}

Fragment StreamingFlowGraphBuilder::BranchIfEqual(
    TargetEntryInstr** then_entry,
    TargetEntryInstr** otherwise_entry,
    bool negate) {
  return flow_graph_builder_->BranchIfEqual(then_entry, otherwise_entry,
                                            negate);
}

Fragment StreamingFlowGraphBuilder::BranchIfNull(
    TargetEntryInstr** then_entry,
    TargetEntryInstr** otherwise_entry,
    bool negate) {
  return flow_graph_builder_->BranchIfNull(then_entry, otherwise_entry, negate);
}

Fragment StreamingFlowGraphBuilder::CatchBlockEntry(const Array& handler_types,
                                                    intptr_t handler_index,
                                                    bool needs_stacktrace) {
  return flow_graph_builder_->CatchBlockEntry(handler_types, handler_index,
                                              needs_stacktrace);
}

Fragment StreamingFlowGraphBuilder::TryCatch(int try_handler_index) {
  return flow_graph_builder_->TryCatch(try_handler_index);
}

Fragment StreamingFlowGraphBuilder::Drop() {
  return flow_graph_builder_->Drop();
}

Fragment StreamingFlowGraphBuilder::NullConstant() {
  return flow_graph_builder_->NullConstant();
}

JoinEntryInstr* StreamingFlowGraphBuilder::BuildJoinEntry() {
  return flow_graph_builder_->BuildJoinEntry();
}

JoinEntryInstr* StreamingFlowGraphBuilder::BuildJoinEntry(intptr_t try_index) {
  return flow_graph_builder_->BuildJoinEntry(try_index);
}

Fragment StreamingFlowGraphBuilder::Goto(JoinEntryInstr* destination) {
  return flow_graph_builder_->Goto(destination);
}

Fragment StreamingFlowGraphBuilder::BuildImplicitClosureCreation(
    const Function& target) {
  return flow_graph_builder_->BuildImplicitClosureCreation(target);
}

Fragment StreamingFlowGraphBuilder::CheckBooleanInCheckedMode() {
  return flow_graph_builder_->CheckBooleanInCheckedMode();
}

Fragment StreamingFlowGraphBuilder::CheckAssignableInCheckedMode(
    const AbstractType& dst_type,
    const String& dst_name) {
  return flow_graph_builder_->CheckAssignableInCheckedMode(dst_type, dst_name);
}

Fragment StreamingFlowGraphBuilder::CheckVariableTypeInCheckedMode(
    intptr_t variable_kernel_position) {
  if (I->type_checks()) {
    LocalVariable* variable = LookupVariable(variable_kernel_position);
    return flow_graph_builder_->CheckVariableTypeInCheckedMode(
        variable->type(), variable->name());
  }
  return Fragment();
}

Fragment StreamingFlowGraphBuilder::CheckVariableTypeInCheckedMode(
    const AbstractType& dst_type,
    const String& name_symbol) {
  return flow_graph_builder_->CheckVariableTypeInCheckedMode(dst_type,
                                                             name_symbol);
}

Fragment StreamingFlowGraphBuilder::EnterScope(intptr_t kernel_offset,
                                               bool* new_context) {
  return flow_graph_builder_->EnterScope(kernel_offset, new_context);
}

Fragment StreamingFlowGraphBuilder::ExitScope(intptr_t kernel_offset) {
  return flow_graph_builder_->ExitScope(kernel_offset);
}

Fragment StreamingFlowGraphBuilder::TranslateCondition(bool* negate) {
  *negate = PeekTag() == kNot;
  if (*negate) {
    SkipBytes(1);  // Skip Not tag, thus go directly to the inner expression.
  }
  Fragment instructions = BuildExpression();  // read expression.
  instructions += CheckBooleanInCheckedMode();
  return instructions;
}

const TypeArguments& StreamingFlowGraphBuilder::BuildTypeArguments() {
  ReadUInt();                                // read arguments count.
  intptr_t type_count = ReadListLength();    // read type count.
  return T.BuildTypeArguments(type_count);   // read types.
}

Fragment StreamingFlowGraphBuilder::BuildArguments(Array* argument_names,
                                                   intptr_t* argument_count,
                                                   bool skip_push_arguments,
                                                   bool do_drop) {
  intptr_t dummy;
  if (argument_count == NULL) argument_count = &dummy;
  *argument_count = ReadUInt();  // read arguments count.

  // List of types.
  SkipListOfDartTypes();  // read list of types.

  return BuildArgumentsFromActualArguments(argument_names, skip_push_arguments,
                                           do_drop);
}

Fragment StreamingFlowGraphBuilder::BuildArgumentsFromActualArguments(
    Array* argument_names,
    bool skip_push_arguments,
    bool do_drop) {
  Fragment instructions;

  // List of positional.
  intptr_t list_length = ReadListLength();  // read list length.
  for (intptr_t i = 0; i < list_length; ++i) {
    instructions += BuildExpression();  // read ith expression.
    if (!skip_push_arguments) instructions += PushArgument();
    if (do_drop) instructions += Drop();
  }

  // List of named.
  list_length = ReadListLength();  // read list length.
  if (argument_names != NULL && list_length > 0) {
    *argument_names ^= Array::New(list_length, Heap::kOld);
  }
  for (intptr_t i = 0; i < list_length; ++i) {
    String& name = H.DartSymbol(ReadStringReference());  // read ith name index.
    instructions += BuildExpression();        // read ith expression.
    if (!skip_push_arguments) instructions += PushArgument();
    if (do_drop) instructions += Drop();
    if (argument_names != NULL) {
      argument_names->SetAt(i, name);
    }
  }

  return instructions;
}

Fragment StreamingFlowGraphBuilder::BuildInvalidExpression(
    TokenPosition* position) {
  if (position != NULL) *position = TokenPosition::kNoSource;

  // The frontend will take care of emitting normal errors (like
  // [NoSuchMethodError]s) and only emit [InvalidExpression]s in very special
  // situations (e.g. an invalid annotation).
  return ThrowNoSuchMethodError();
}

Fragment StreamingFlowGraphBuilder::BuildVariableGet(TokenPosition* position) {
  (position != NULL) ? * position = ReadPosition()
                     : ReadPosition();             // read position.
  intptr_t variable_kernel_position = ReadUInt();  // read kernel position.
  ReadUInt();              // read relative variable index.
  SkipOptionalDartType();  // read promoted type.

  return LoadLocal(LookupVariable(variable_kernel_position));
}

Fragment StreamingFlowGraphBuilder::BuildVariableGet(uint8_t payload,
                                                     TokenPosition* position) {
  (position != NULL) ? * position = ReadPosition()
                     : ReadPosition();             // read position.
  intptr_t variable_kernel_position = ReadUInt();  // read kernel position.
  return LoadLocal(LookupVariable(variable_kernel_position));
}

Fragment StreamingFlowGraphBuilder::BuildVariableSet(TokenPosition* p) {
  TokenPosition position = ReadPosition();  // read position.
  if (p != NULL) *p = position;

  intptr_t variable_kernel_position = ReadUInt();  // read kernel position.
  ReadUInt();                                 // read relative variable index.
  Fragment instructions = BuildExpression();  // read expression.

  if (NeedsDebugStepCheck(stack(), position)) {
    instructions = DebugStepCheck(position) + instructions;
  }
  instructions += CheckVariableTypeInCheckedMode(variable_kernel_position);
  instructions +=
      StoreLocal(position, LookupVariable(variable_kernel_position));
  return instructions;
}

Fragment StreamingFlowGraphBuilder::BuildVariableSet(uint8_t payload,
                                                     TokenPosition* p) {
  TokenPosition position = ReadPosition();  // read position.
  if (p != NULL) *p = position;

  intptr_t variable_kernel_position = ReadUInt();  // read kernel position.
  Fragment instructions = BuildExpression();       // read expression.

  if (NeedsDebugStepCheck(stack(), position)) {
    instructions = DebugStepCheck(position) + instructions;
  }
  instructions += CheckVariableTypeInCheckedMode(variable_kernel_position);
  instructions +=
      StoreLocal(position, LookupVariable(variable_kernel_position));

  return instructions;
}

Fragment StreamingFlowGraphBuilder::BuildPropertyGet(TokenPosition* p) {
  TokenPosition position = ReadPosition();  // read position.
  if (p != NULL) *p = position;

  Fragment instructions = BuildExpression();  // read receiver.
  instructions += PushArgument();

  const String& getter_name = ReadNameAsGetterName();  // read name.

  const Function* interface_target = &Function::null_function();
  NameIndex itarget_name =
      ReadCanonicalNameReference();  // read interface_target_reference.
  if (FLAG_experimental_strong_mode && !H.IsRoot(itarget_name) &&
      (H.IsGetter(itarget_name) || H.IsField(itarget_name))) {
    interface_target = &Function::ZoneHandle(
        Z, LookupMethodByMember(itarget_name, H.DartGetterName(itarget_name)));
    ASSERT(getter_name.raw() == interface_target->name());
  }

  const intptr_t kTypeArgsLen = 0;
  const intptr_t kNumArgsChecked = 1;
  return instructions + InstanceCall(position, getter_name, Token::kGET,
                                     kTypeArgsLen, 1, Array::null_array(),
                                     kNumArgsChecked, *interface_target);
}

Fragment StreamingFlowGraphBuilder::BuildPropertySet(TokenPosition* p) {
  Fragment instructions(NullConstant());
  LocalVariable* variable = MakeTemporary();

  TokenPosition position = ReadPosition();  // read position.
  if (p != NULL) *p = position;

  instructions += BuildExpression();  // read receiver.
  instructions += PushArgument();

  const String& setter_name = ReadNameAsSetterName();  // read name.

  instructions += BuildExpression();  // read value.
  instructions += StoreLocal(TokenPosition::kNoSource, variable);
  instructions += PushArgument();

  const Function* interface_target = &Function::null_function();
  NameIndex itarget_name =
      ReadCanonicalNameReference();  // read interface_target_reference.
  if (FLAG_experimental_strong_mode && !H.IsRoot(itarget_name)) {
    interface_target = &Function::ZoneHandle(
        Z, LookupMethodByMember(itarget_name, H.DartSetterName(itarget_name)));
    ASSERT(setter_name.raw() == interface_target->name());
  }

  const intptr_t kTypeArgsLen = 0;
  const intptr_t kNumArgsChecked = 1;
  instructions +=
      InstanceCall(position, setter_name, Token::kSET, kTypeArgsLen, 2,
                   Array::null_array(), kNumArgsChecked, *interface_target);

  return instructions + Drop();
}

Fragment StreamingFlowGraphBuilder::BuildDirectPropertyGet(TokenPosition* p) {
  TokenPosition position = ReadPosition();  // read position.
  if (p != NULL) *p = position;

  Fragment instructions = BuildExpression();  // read receiver.
  NameIndex kernel_name =
      ReadCanonicalNameReference();  // read target_reference.

  Function& target = Function::ZoneHandle(Z);
  if (H.IsProcedure(kernel_name)) {
    if (H.IsGetter(kernel_name)) {
      target = LookupMethodByMember(kernel_name, H.DartGetterName(kernel_name));
    } else {
      // Undo stack change for the BuildExpression.
      Pop();

      target = LookupMethodByMember(kernel_name, H.DartMethodName(kernel_name));
      target = target.ImplicitClosureFunction();
      ASSERT(!target.IsNull());
      return BuildImplicitClosureCreation(target);
    }
  } else {
    ASSERT(H.IsField(kernel_name));
    const String& getter_name = H.DartGetterName(kernel_name);
    target = LookupMethodByMember(kernel_name, getter_name);
    ASSERT(target.IsGetterFunction() || target.IsImplicitGetterFunction());
  }

  instructions += PushArgument();
  return instructions + StaticCall(position, target, 1);
}

Fragment StreamingFlowGraphBuilder::BuildDirectPropertySet(TokenPosition* p) {
  TokenPosition position = ReadPosition();  // read position.
  if (p != NULL) *p = position;

  Fragment instructions(NullConstant());
  LocalVariable* value = MakeTemporary();

  instructions += BuildExpression();  // read receiver.
  instructions += PushArgument();

  NameIndex target_reference =
      ReadCanonicalNameReference();  // read target_reference.
  const String& method_name = H.DartSetterName(target_reference);
  const Function& target = Function::ZoneHandle(
      Z, LookupMethodByMember(target_reference, method_name));
  ASSERT(target.IsSetterFunction() || target.IsImplicitSetterFunction());

  instructions += BuildExpression();  // read value.
  instructions += StoreLocal(TokenPosition::kNoSource, value);
  instructions += PushArgument();

  instructions += StaticCall(position, target, 2);

  return instructions + Drop();
}

Fragment StreamingFlowGraphBuilder::BuildStaticGet(TokenPosition* p) {
  intptr_t offset = ReaderOffset() - 1;  // Include the tag.

  TokenPosition position = ReadPosition();  // read position.
  if (p != NULL) *p = position;

  NameIndex target = ReadCanonicalNameReference();  // read target_reference.

  if (H.IsField(target)) {
    const Field& field =
        Field::ZoneHandle(Z, H.LookupFieldByKernelField(target));
    if (field.is_const()) {
      return Constant(constant_evaluator_.EvaluateExpression(offset));
    } else {
      const Class& owner = Class::Handle(Z, field.Owner());
      const String& getter_name = H.DartGetterName(target);
      const Function& getter =
          Function::ZoneHandle(Z, owner.LookupStaticFunction(getter_name));
      if (getter.IsNull() || !field.has_initializer()) {
        Fragment instructions = Constant(field);
        return instructions + LoadStaticField();
      } else {
        return StaticCall(position, getter, 0);
      }
    }
  } else {
    const Function& function =
        Function::ZoneHandle(Z, H.LookupStaticMethodByKernelProcedure(target));

    if (H.IsGetter(target)) {
      return StaticCall(position, function, 0);
    } else if (H.IsMethod(target)) {
      return Constant(constant_evaluator_.EvaluateExpression(offset));
    } else {
      UNIMPLEMENTED();
    }
  }

  return Fragment();
}

Fragment StreamingFlowGraphBuilder::BuildStaticSet(TokenPosition* p) {
  TokenPosition position = ReadPosition();  // read position.
  if (p != NULL) *p = position;

  NameIndex target = ReadCanonicalNameReference();  // read target_reference.

  if (H.IsField(target)) {
    const Field& field =
        Field::ZoneHandle(Z, H.LookupFieldByKernelField(target));
    const AbstractType& dst_type = AbstractType::ZoneHandle(Z, field.type());
    Fragment instructions = BuildExpression();  // read expression.
    if (NeedsDebugStepCheck(stack(), position)) {
      instructions = DebugStepCheck(position) + instructions;
    }
    instructions += CheckAssignableInCheckedMode(
        dst_type, String::ZoneHandle(Z, field.name()));
    LocalVariable* variable = MakeTemporary();
    instructions += LoadLocal(variable);
    return instructions + StoreStaticField(position, field);
  } else {
    ASSERT(H.IsProcedure(target));

    // Evaluate the expression on the right hand side.
    Fragment instructions = BuildExpression();  // read expression.
    LocalVariable* variable = MakeTemporary();

    // Prepare argument.
    instructions += LoadLocal(variable);
    instructions += PushArgument();

    // Invoke the setter function.
    const Function& function =
        Function::ZoneHandle(Z, H.LookupStaticMethodByKernelProcedure(target));
    instructions += StaticCall(position, function, 1);

    // Drop the unused result & leave the stored value on the stack.
    return instructions + Drop();
  }
}

static bool IsNumberLiteral(Tag tag) {
  return tag == kNegativeIntLiteral || tag == kPositiveIntLiteral ||
         tag == kSpecialIntLiteral || tag == kDoubleLiteral;
}

Fragment StreamingFlowGraphBuilder::BuildMethodInvocation(TokenPosition* p) {
  intptr_t offset = ReaderOffset() - 1;     // Include the tag.
  TokenPosition position = ReadPosition();  // read position.
  if (p != NULL) *p = position;

  Tag receiver_tag = PeekTag();  // peek tag for receiver.
  if (IsNumberLiteral(receiver_tag)) {
    intptr_t before_branch_offset = ReaderOffset();

    SkipExpression();  // read receiver (it's just a number literal).

    const String& name = ReadNameAsMethodName();  // read name.
    const Token::Kind token_kind = MethodKind(name);
    intptr_t argument_count = PeekArgumentsCount() + 1;

    if ((argument_count == 1) && (token_kind == Token::kNEGATE)) {
      const Object& result = constant_evaluator_.EvaluateExpressionSafe(offset);
      if (!result.IsError()) {
        SkipArguments();               // read arguments.
        SkipCanonicalNameReference();  // read interface_target_reference.
        return Constant(result);
      }
    } else if ((argument_count == 2) &&
               Token::IsBinaryArithmeticOperator(token_kind) &&
               IsNumberLiteral(PeekArgumentsFirstPositionalTag())) {
      const Object& result = constant_evaluator_.EvaluateExpressionSafe(offset);
      if (!result.IsError()) {
        SkipArguments();               // read arguments.
        SkipCanonicalNameReference();  // read interface_target_reference.
        return Constant(result);
      }
    }

    SetOffset(before_branch_offset);
  }

  Fragment instructions = BuildExpression();  // read receiver.

  const String& name = ReadNameAsMethodName();  // read name.
  const Token::Kind token_kind = MethodKind(name);

  // Detect comparison with null.
  if ((token_kind == Token::kEQ || token_kind == Token::kNE) &&
      PeekArgumentsCount() == 1 &&
      (receiver_tag == kNullLiteral ||
       PeekArgumentsFirstPositionalTag() == kNullLiteral)) {
    // "==" or "!=" with null on either side.
    instructions += BuildArguments(NULL, NULL, true);  // read arguments.
    SkipCanonicalNameReference();  // read interface_target_reference.
    Token::Kind strict_cmp_kind =
        token_kind == Token::kEQ ? Token::kEQ_STRICT : Token::kNE_STRICT;
    return instructions +
           StrictCompare(strict_cmp_kind, /*number_check = */ true);
  }

  instructions += PushArgument();  // push receiver as argument.

  // TODO(28109) Support generic methods in the VM or reify them away.
  const intptr_t kTypeArgsLen = 0;
  Array& argument_names = Array::ZoneHandle(Z);
  intptr_t argument_count;
  instructions +=
      BuildArguments(&argument_names, &argument_count);  // read arguments.
  ++argument_count;

  intptr_t checked_argument_count = 1;
  // If we have a special operation (e.g. +/-/==) we mark both arguments as
  // to be checked.
  if (token_kind != Token::kILLEGAL) {
    ASSERT(argument_count <= 2);
    checked_argument_count = argument_count;
  }

  const Function* interface_target = &Function::null_function();
  NameIndex itarget_name =
      ReadCanonicalNameReference();  // read interface_target_reference.
  if (FLAG_experimental_strong_mode && !H.IsRoot(itarget_name) &&
      !H.IsField(itarget_name)) {
    interface_target = &Function::ZoneHandle(
        Z,
        LookupMethodByMember(itarget_name, H.DartProcedureName(itarget_name)));
    ASSERT(name.raw() == interface_target->name());
  }

  instructions +=
      InstanceCall(position, name, token_kind, kTypeArgsLen, argument_count,
                   argument_names, checked_argument_count, *interface_target);
  // Later optimization passes assume that result of a x.[]=(...) call is not
  // used. We must guarantee this invariant because violation will lead to an
  // illegal IL once we replace x.[]=(...) with a sequence that does not
  // actually produce any value. See http://dartbug.com/29135 for more details.
  if (name.raw() == Symbols::AssignIndexToken().raw()) {
    instructions += Drop();
    instructions += NullConstant();
  }

  return instructions;
}

Fragment StreamingFlowGraphBuilder::BuildDirectMethodInvocation(
    TokenPosition* position) {
  if (position != NULL) *position = TokenPosition::kNoSource;

  // TODO(28109) Support generic methods in the VM or reify them away.
  Tag receiver_tag = PeekTag();               // peek tag for receiver.
  Fragment instructions = BuildExpression();  // read receiver.

  NameIndex kernel_name =
      ReadCanonicalNameReference();  // read target_reference.
  const String& method_name = H.DartProcedureName(kernel_name);
  const Token::Kind token_kind = MethodKind(method_name);

  // Detect comparison with null.
  if ((token_kind == Token::kEQ || token_kind == Token::kNE) &&
      PeekArgumentsCount() == 1 &&
      (receiver_tag == kNullLiteral ||
       PeekArgumentsFirstPositionalTag() == kNullLiteral)) {
    // "==" or "!=" with null on either side.
    instructions += BuildArguments(NULL, NULL, true);  // read arguments.
    Token::Kind strict_cmp_kind =
        token_kind == Token::kEQ ? Token::kEQ_STRICT : Token::kNE_STRICT;
    return instructions +
           StrictCompare(strict_cmp_kind, /*number_check = */ true);
  }

  instructions += PushArgument();  // push receiver as argument.

  const Function& target =
      Function::ZoneHandle(Z, LookupMethodByMember(kernel_name, method_name));

  Array& argument_names = Array::ZoneHandle(Z);
  intptr_t argument_count;
  instructions +=
      BuildArguments(&argument_names, &argument_count);  // read arguments.
  ++argument_count;
  return instructions + StaticCall(TokenPosition::kNoSource, target,
                                   argument_count, argument_names);
}

Fragment StreamingFlowGraphBuilder::BuildStaticInvocation(bool is_const,
                                                          TokenPosition* p) {
  TokenPosition position = ReadPosition();  // read position.
  if (p != NULL) *p = position;

  NameIndex procedue_reference =
      ReadCanonicalNameReference();  // read procedure reference.
  intptr_t argument_count = PeekArgumentsCount();
  const Function& target = Function::ZoneHandle(
      Z, H.LookupStaticMethodByKernelProcedure(procedue_reference));
  const Class& klass = Class::ZoneHandle(Z, target.Owner());
  if (target.IsGenerativeConstructor() || target.IsFactory()) {
    // The VM requires a TypeArguments object as first parameter for
    // every factory constructor.
    ++argument_count;
  }

  Fragment instructions;
  LocalVariable* instance_variable = NULL;

  // If we cross the Kernel -> VM core library boundary, a [StaticInvocation]
  // can appear, but the thing we're calling is not a static method, but a
  // factory constructor.
  // The `H.LookupStaticmethodByKernelProcedure` will potentially resolve to the
  // forwarded constructor.
  // In that case we'll make an instance and pass it as first argument.
  //
  // TODO(27590): Get rid of this after we're using core libraries compiled
  // into Kernel.
  if (target.IsGenerativeConstructor()) {
    if (klass.NumTypeArguments() > 0) {
      const TypeArguments& type_arguments =
          PeekArgumentsInstantiatedType(klass);
      instructions += TranslateInstantiatedTypeArguments(type_arguments);
      instructions += PushArgument();
      instructions += AllocateObject(position, klass, 1);
    } else {
      instructions += AllocateObject(position, klass, 0);
    }

    instance_variable = MakeTemporary();

    instructions += LoadLocal(instance_variable);
    instructions += PushArgument();
  } else if (target.IsFactory()) {
    // The VM requires currently a TypeArguments object as first parameter for
    // every factory constructor :-/ !
    //
    // TODO(27590): Get rid of this after we're using core libraries compiled
    // into Kernel.
    const TypeArguments& type_arguments = PeekArgumentsInstantiatedType(klass);
    instructions += TranslateInstantiatedTypeArguments(type_arguments);
    instructions += PushArgument();
  } else {
    // TODO(28109) Support generic methods in the VM or reify them away.
  }

  bool special_case_identical = klass.IsTopLevel() &&
                                (klass.library() == Library::CoreLibrary()) &&
                                (target.name() == Symbols::Identical().raw());

  Array& argument_names = Array::ZoneHandle(Z);
  instructions += BuildArguments(&argument_names, NULL,
                                 special_case_identical);  // read arguments.
  const int kTypeArgsLen = 0;
  ASSERT(target.AreValidArguments(kTypeArgsLen, argument_count, argument_names,
                                  NULL));

  // Special case identical(x, y) call.
  // TODO(27590) consider moving this into the inliner and force inline it
  // there.
  if (special_case_identical) {
    ASSERT(argument_count == 2);
    instructions += StrictCompare(Token::kEQ_STRICT, /*number_check=*/true);
  } else {
    instructions +=
        StaticCall(position, target, argument_count, argument_names);
    if (target.IsGenerativeConstructor()) {
      // Drop the result of the constructor call and leave [instance_variable]
      // on top-of-stack.
      instructions += Drop();
    }
  }

  return instructions;
}

Fragment StreamingFlowGraphBuilder::BuildConstructorInvocation(
    bool is_const,
    TokenPosition* p) {
  if (is_const) {
    intptr_t offset = ReaderOffset() - 1;                 // Include the tag.
    (p != NULL) ? * p = ReadPosition() : ReadPosition();  // read position.

    SetOffset(offset);
    SkipExpression();  // read past this ConstructorInvocation.
    return Constant(constant_evaluator_.EvaluateConstructorInvocation(offset));
  }

  TokenPosition position = ReadPosition();  // read position.
  if (p != NULL) *p = position;

  NameIndex kernel_name =
      ReadCanonicalNameReference();  // read target_reference.

  Class& klass = Class::ZoneHandle(
      Z, H.LookupClassByKernelClass(H.EnclosingName(kernel_name)));

  Fragment instructions;

  // Check for malbounded-ness of type.
  if (I->type_checks()) {
    intptr_t offset = ReaderOffset();

    const TypeArguments& type_arguments = BuildTypeArguments();

    AbstractType& type = AbstractType::Handle(
        Z, Type::New(klass, type_arguments, TokenPosition::kNoSource));
    type = ClassFinalizer::FinalizeType(klass, type);

    if (type.IsMalbounded()) {
      // Evaluate expressions for correctness.
      instructions +=
          BuildArgumentsFromActualArguments(NULL, false, /*do_drop*/ true);

      // Throw an error & keep the [Value] on the stack.
      instructions += ThrowTypeError();

      // Bail out early.
      return instructions;
    }

    SetOffset(offset);
  }

  if (klass.NumTypeArguments() > 0) {
    if (!klass.IsGeneric()) {
      Type& type = Type::ZoneHandle(Z, T.ReceiverType(klass).raw());

      // TODO(27590): Can we move this code into [ReceiverType]?
      type ^= ClassFinalizer::FinalizeType(*active_class()->klass, type,
                                           ClassFinalizer::kFinalize);
      ASSERT(!type.IsMalformedOrMalbounded());

      TypeArguments& canonicalized_type_arguments =
          TypeArguments::ZoneHandle(Z, type.arguments());
      canonicalized_type_arguments =
          canonicalized_type_arguments.Canonicalize();
      instructions += Constant(canonicalized_type_arguments);
    } else {
      const TypeArguments& type_arguments =
          PeekArgumentsInstantiatedType(klass);
      instructions += TranslateInstantiatedTypeArguments(type_arguments);
    }

    instructions += PushArgument();
    instructions += AllocateObject(position, klass, 1);
  } else {
    instructions += AllocateObject(position, klass, 0);
  }
  LocalVariable* variable = MakeTemporary();

  instructions += LoadLocal(variable);
  instructions += PushArgument();

  Array& argument_names = Array::ZoneHandle(Z);
  intptr_t argument_count;
  instructions +=
      BuildArguments(&argument_names, &argument_count);  // read arguments.

  const Function& target = Function::ZoneHandle(
      Z, H.LookupConstructorByKernelConstructor(klass, kernel_name));
  ++argument_count;
  instructions += StaticCall(position, target, argument_count, argument_names);
  return instructions + Drop();
}

Fragment StreamingFlowGraphBuilder::BuildNot(TokenPosition* position) {
  if (position != NULL) *position = TokenPosition::kNoSource;

  Fragment instructions = BuildExpression();  // read expression.
  instructions += CheckBooleanInCheckedMode();
  instructions += BooleanNegate();
  return instructions;
}

Fragment StreamingFlowGraphBuilder::BuildLogicalExpression(
    TokenPosition* position) {
  if (position != NULL) *position = TokenPosition::kNoSource;

  bool negate;
  Fragment instructions = TranslateCondition(&negate);  // read left.

  TargetEntryInstr* right_entry;
  TargetEntryInstr* constant_entry;
  LogicalOperator op = static_cast<LogicalOperator>(ReadByte());

  if (op == kAnd) {
    instructions += BranchIfTrue(&right_entry, &constant_entry, negate);
  } else {
    instructions += BranchIfTrue(&constant_entry, &right_entry, negate);
  }

  Value* top = stack();
  Fragment right_fragment(right_entry);
  right_fragment += TranslateCondition(&negate);  // read right.

  right_fragment += Constant(Bool::True());
  right_fragment +=
      StrictCompare(negate ? Token::kNE_STRICT : Token::kEQ_STRICT);
  right_fragment += StoreLocal(TokenPosition::kNoSource,
                               parsed_function()->expression_temp_var());
  right_fragment += Drop();

  ASSERT(top == stack());
  Fragment constant_fragment(constant_entry);
  constant_fragment += Constant(Bool::Get(op == kOr));
  constant_fragment += StoreLocal(TokenPosition::kNoSource,
                                  parsed_function()->expression_temp_var());
  constant_fragment += Drop();

  JoinEntryInstr* join = BuildJoinEntry();
  right_fragment += Goto(join);
  constant_fragment += Goto(join);

  return Fragment(instructions.entry, join) +
         LoadLocal(parsed_function()->expression_temp_var());
}

Fragment StreamingFlowGraphBuilder::BuildConditionalExpression(
    TokenPosition* position) {
  if (position != NULL) *position = TokenPosition::kNoSource;

  bool negate;
  Fragment instructions = TranslateCondition(&negate);  // read condition.

  TargetEntryInstr* then_entry;
  TargetEntryInstr* otherwise_entry;
  instructions += BranchIfTrue(&then_entry, &otherwise_entry, negate);

  Value* top = stack();
  Fragment then_fragment(then_entry);
  then_fragment += BuildExpression();  // read then.
  then_fragment += StoreLocal(TokenPosition::kNoSource,
                              parsed_function()->expression_temp_var());
  then_fragment += Drop();
  ASSERT(stack() == top);

  Fragment otherwise_fragment(otherwise_entry);
  otherwise_fragment += BuildExpression();  // read otherwise.
  otherwise_fragment += StoreLocal(TokenPosition::kNoSource,
                                   parsed_function()->expression_temp_var());
  otherwise_fragment += Drop();
  ASSERT(stack() == top);

  JoinEntryInstr* join = BuildJoinEntry();
  then_fragment += Goto(join);
  otherwise_fragment += Goto(join);

  SkipOptionalDartType();  // read unused static type.

  return Fragment(instructions.entry, join) +
         LoadLocal(parsed_function()->expression_temp_var());
}

Fragment StreamingFlowGraphBuilder::BuildStringConcatenation(TokenPosition* p) {
  TokenPosition position = ReadPosition();  // read position.
  if (p != NULL) *p = position;

  intptr_t length = ReadListLength();  // read list length.
  // Note: there will be "length" expressions.

  Fragment instructions;
  if (length == 1) {
    instructions += BuildExpression();  // read expression.
    instructions += StringInterpolateSingle(position);
  } else {
    // The type arguments for CreateArray.
    instructions += Constant(TypeArguments::ZoneHandle(Z));
    instructions += IntConstant(length);
    instructions += CreateArray();
    LocalVariable* array = MakeTemporary();

    for (intptr_t i = 0; i < length; ++i) {
      instructions += LoadLocal(array);
      instructions += IntConstant(i);
      instructions += BuildExpression();  // read ith expression.
      instructions += StoreIndexed(kArrayCid);
      instructions += Drop();
    }

    instructions += StringInterpolate(position);
  }

  return instructions;
}

Fragment StreamingFlowGraphBuilder::BuildIsExpression(TokenPosition* p) {
  TokenPosition position = ReadPosition();  // read position.
  if (p != NULL) *p = position;

  Fragment instructions = BuildExpression();  // read operand.

  const AbstractType& type = T.BuildType();  // read type.

  // The VM does not like an instanceOf call with a dynamic type. We need to
  // special case this situation.
  const Type& object_type = Type::Handle(Z, Type::ObjectType());

  if (type.IsMalformed()) {
    instructions += Drop();
    instructions += ThrowTypeError();
    return instructions;
  }

  if (type.IsInstantiated() &&
      object_type.IsSubtypeOf(type, NULL, NULL, Heap::kOld)) {
    // Evaluate the expression on the left but ignore it's result.
    instructions += Drop();

    // Let condition be always true.
    instructions += Constant(Bool::True());
  } else {
    instructions += PushArgument();

    // See if simple instanceOf is applicable.
    if (dart::FlowGraphBuilder::SimpleInstanceOfType(type)) {
      instructions += Constant(type);
      instructions += PushArgument();  // Type.
      instructions += InstanceCall(
          position, Library::PrivateCoreLibName(Symbols::_simpleInstanceOf()),
          Token::kIS, 2, 2);  // 2 checked arguments.
      return instructions;
    }

    if (!type.IsInstantiated(kCurrentClass)) {
      instructions += LoadInstantiatorTypeArguments();
    } else {
      instructions += NullConstant();
    }
    instructions += PushArgument();  // Instantiator type arguments.

    if (!type.IsInstantiated(kFunctions)) {
      instructions += LoadFunctionTypeArguments();
    } else {
      instructions += NullConstant();
    }
    instructions += PushArgument();  // Function type arguments.

    instructions += Constant(type);
    instructions += PushArgument();  // Type.

    instructions += InstanceCall(
        position, Library::PrivateCoreLibName(Symbols::_instanceOf()),
        Token::kIS, 4);
  }
  return instructions;
}

Fragment StreamingFlowGraphBuilder::BuildAsExpression(TokenPosition* p) {
  TokenPosition position = ReadPosition();  // read position.
  if (p != NULL) *p = position;

  Fragment instructions = BuildExpression();  // read operand.

  const AbstractType& type = T.BuildType();  // read type.

  // The VM does not like an Object_as call with a dynamic type. We need to
  // special case this situation.
  const Type& object_type = Type::Handle(Z, Type::ObjectType());

  if (type.IsMalformed()) {
    instructions += Drop();
    instructions += ThrowTypeError();
    return instructions;
  }

  if (type.IsInstantiated() &&
      object_type.IsSubtypeOf(type, NULL, NULL, Heap::kOld)) {
    // We already evaluated the operand on the left and just leave it there as
    // the result of the `obj as dynamic` expression.
  } else {
    instructions += PushArgument();

    if (!type.IsInstantiated(kCurrentClass)) {
      instructions += LoadInstantiatorTypeArguments();
    } else {
      instructions += NullConstant();
    }
    instructions += PushArgument();  // Instantiator type arguments.

    if (!type.IsInstantiated(kFunctions)) {
      instructions += LoadFunctionTypeArguments();
    } else {
      instructions += NullConstant();
    }
    instructions += PushArgument();  // Function type arguments.

    instructions += Constant(type);
    instructions += PushArgument();  // Type.

    instructions += InstanceCall(
        position, Library::PrivateCoreLibName(Symbols::_as()), Token::kAS, 4);
  }
  return instructions;
}

Fragment StreamingFlowGraphBuilder::BuildSymbolLiteral(
    TokenPosition* position) {
  if (position != NULL) *position = TokenPosition::kNoSource;

  intptr_t offset = ReaderOffset() - 1;  // EvaluateExpression needs the tag.
  SkipStringReference();                 // read index into string table.
  return Constant(constant_evaluator_.EvaluateExpression(offset));
}

Fragment StreamingFlowGraphBuilder::BuildTypeLiteral(TokenPosition* position) {
  if (position != NULL) *position = TokenPosition::kNoSource;

  const AbstractType& type = T.BuildType();  // read type.
  if (type.IsMalformed()) H.ReportError("Malformed type literal");

  Fragment instructions;
  if (type.IsInstantiated()) {
    instructions += Constant(type);
  } else {
    if (!type.IsInstantiated(kCurrentClass)) {
      instructions += LoadInstantiatorTypeArguments();
    } else {
      instructions += NullConstant();
    }
    if (!type.IsInstantiated(kFunctions)) {
      instructions += LoadFunctionTypeArguments();
    } else {
      instructions += NullConstant();
    }
    instructions += InstantiateType(type);
  }
  return instructions;
}

Fragment StreamingFlowGraphBuilder::BuildThisExpression(
    TokenPosition* position) {
  if (position != NULL) *position = TokenPosition::kNoSource;

  return LoadLocal(scopes()->this_variable);
}

Fragment StreamingFlowGraphBuilder::BuildRethrow(TokenPosition* p) {
  TokenPosition position = ReadPosition();  // read position.
  if (p != NULL) *p = position;

  Fragment instructions = DebugStepCheck(position);
  instructions += LoadLocal(catch_block()->exception_var());
  instructions += PushArgument();
  instructions += LoadLocal(catch_block()->stack_trace_var());
  instructions += PushArgument();
  instructions += RethrowException(position, catch_block()->catch_try_index());

  return instructions;
}

Fragment StreamingFlowGraphBuilder::BuildThrow(TokenPosition* p) {
  TokenPosition position = ReadPosition();  // read position.
  if (p != NULL) *p = position;

  Fragment instructions;

  instructions += BuildExpression();  // read expression.

  if (NeedsDebugStepCheck(stack(), position)) {
    instructions = DebugStepCheck(position) + instructions;
  }
  instructions += PushArgument();
  instructions += ThrowException(position);
  ASSERT(instructions.is_closed());

  return instructions;
}

Fragment StreamingFlowGraphBuilder::BuildListLiteral(bool is_const,
                                                     TokenPosition* p) {
  if (is_const) {
    intptr_t offset = ReaderOffset() - 1;                 // Include the tag.
    (p != NULL) ? * p = ReadPosition() : ReadPosition();  // read position.

    SetOffset(offset);
    SkipExpression();  // read past the ListLiteral.
    return Constant(constant_evaluator_.EvaluateListLiteral(offset));
  }

  TokenPosition position = ReadPosition();  // read position.
  if (p != NULL) *p = position;

  const TypeArguments& type_arguments = T.BuildTypeArguments(1);  // read type.
  intptr_t length = ReadListLength();  // read list length.
  // Note: there will be "length" expressions.

  // The type argument for the factory call.
  Fragment instructions = TranslateInstantiatedTypeArguments(type_arguments);
  instructions += PushArgument();
  if (length == 0) {
    instructions += Constant(Object::empty_array());
  } else {
    // The type arguments for CreateArray.
    instructions += Constant(type_arguments);
    instructions += IntConstant(length);
    instructions += CreateArray();
    AbstractType& list_type = AbstractType::ZoneHandle(Z);
    if (I->type_checks()) {
      if (type_arguments.IsNull()) {
        // It was dynamic.
        list_type = Object::dynamic_type().raw();
      } else {
        list_type = type_arguments.TypeAt(0);
      }
    }

    LocalVariable* array = MakeTemporary();
    for (intptr_t i = 0; i < length; ++i) {
      instructions += LoadLocal(array);
      instructions += IntConstant(i);
      instructions += BuildExpression();  // read ith expression.
      instructions += CheckAssignableInCheckedMode(
          list_type, Symbols::ListLiteralElement());
      instructions += StoreIndexed(kArrayCid);
      instructions += Drop();
    }
  }
  instructions += PushArgument();  // The array.

  const Class& factory_class =
      Class::Handle(Z, Library::LookupCoreClass(Symbols::List()));
  const Function& factory_method = Function::ZoneHandle(
      Z, factory_class.LookupFactory(
             Library::PrivateCoreLibName(Symbols::ListLiteralFactory())));

  return instructions + StaticCall(position, factory_method, 2);
}

Fragment StreamingFlowGraphBuilder::BuildMapLiteral(bool is_const,
                                                    TokenPosition* p) {
  if (is_const) {
    intptr_t offset = ReaderOffset() - 1;  // Include the tag.
    (p != NULL) ? * p = ReadPosition() : ReadPosition();

    SetOffset(offset);
    SkipExpression();  // Read past the MapLiteral.
    return Constant(constant_evaluator_.EvaluateMapLiteral(offset));
  }

  TokenPosition position = ReadPosition();  // read position.
  if (p != NULL) *p = position;

  const TypeArguments& type_arguments =
      T.BuildTypeArguments(2);  // read key_type and value_type.

  // The type argument for the factory call `new Map<K, V>._fromLiteral(List)`.
  Fragment instructions = TranslateInstantiatedTypeArguments(type_arguments);
  instructions += PushArgument();

  intptr_t length = ReadListLength();  // read list length.
  // Note: there will be "length" map entries (i.e. key and value expressions).

  if (length == 0) {
    instructions += Constant(Object::empty_array());
  } else {
    // The type arguments for `new List<X>(int len)`.
    instructions += Constant(TypeArguments::ZoneHandle(Z));

    // We generate a list of tuples, i.e. [key1, value1, ..., keyN, valueN].
    instructions += IntConstant(2 * length);
    instructions += CreateArray();

    LocalVariable* array = MakeTemporary();
    for (intptr_t i = 0; i < length; ++i) {
      instructions += LoadLocal(array);
      instructions += IntConstant(2 * i);
      instructions += BuildExpression();  // read ith key.
      instructions += StoreIndexed(kArrayCid);
      instructions += Drop();

      instructions += LoadLocal(array);
      instructions += IntConstant(2 * i + 1);
      instructions += BuildExpression();  // read ith value.
      instructions += StoreIndexed(kArrayCid);
      instructions += Drop();
    }
  }
  instructions += PushArgument();  // The array.

  const Class& map_class =
      Class::Handle(Z, Library::LookupCoreClass(Symbols::Map()));
  const Function& factory_method = Function::ZoneHandle(
      Z, map_class.LookupFactory(
             Library::PrivateCoreLibName(Symbols::MapLiteralFactory())));

  return instructions + StaticCall(position, factory_method, 2);
}

Fragment StreamingFlowGraphBuilder::BuildFunctionExpression() {
  ReadPosition();  // read position.
  return BuildFunctionNode(TokenPosition::kNoSource, StringIndex());
}

Fragment StreamingFlowGraphBuilder::BuildLet(TokenPosition* position) {
  if (position != NULL) *position = TokenPosition::kNoSource;

  Fragment instructions = BuildVariableDeclaration();  // read variable.
  instructions += BuildExpression();                   // read body.
  return instructions;
}

Fragment StreamingFlowGraphBuilder::BuildBigIntLiteral(
    TokenPosition* position) {
  if (position != NULL) *position = TokenPosition::kNoSource;

  const String& value =
      H.DartString(ReadStringReference());  // read index into string table.
  const Integer& integer =
      Integer::ZoneHandle(Z, Integer::New(value, Heap::kOld));
  if (integer.IsNull()) {
    H.ReportError("Integer literal %s is out of range", value.ToCString());
    UNREACHABLE();
  }
  return Constant(integer);
}

Fragment StreamingFlowGraphBuilder::BuildStringLiteral(
    TokenPosition* position) {
  if (position != NULL) *position = TokenPosition::kNoSource;

  return Constant(
      H.DartSymbol(ReadStringReference()));  // read index into string table.
}

Fragment StreamingFlowGraphBuilder::BuildIntLiteral(uint8_t payload,
                                                    TokenPosition* position) {
  if (position != NULL) *position = TokenPosition::kNoSource;

  int64_t value = static_cast<int32_t>(payload) - SpecializedIntLiteralBias;
  return IntConstant(value);
}

Fragment StreamingFlowGraphBuilder::BuildIntLiteral(bool is_negative,
                                                    TokenPosition* position) {
  if (position != NULL) *position = TokenPosition::kNoSource;

  int64_t value = is_negative ? -static_cast<int64_t>(ReadUInt())
                              : ReadUInt();  // read value.
  return IntConstant(value);
}

Fragment StreamingFlowGraphBuilder::BuildDoubleLiteral(
    TokenPosition* position) {
  if (position != NULL) *position = TokenPosition::kNoSource;

  intptr_t offset = ReaderOffset() - 1;  // EvaluateExpression needs the tag.
  SkipStringReference();                 // read index into string table.
  return Constant(constant_evaluator_.EvaluateExpression(offset));
}

Fragment StreamingFlowGraphBuilder::BuildBoolLiteral(bool value,
                                                     TokenPosition* position) {
  if (position != NULL) *position = TokenPosition::kNoSource;

  return Constant(Bool::Get(value));
}

Fragment StreamingFlowGraphBuilder::BuildNullLiteral(TokenPosition* position) {
  if (position != NULL) *position = TokenPosition::kNoSource;

  return Constant(Instance::ZoneHandle(Z, Instance::null()));
}

Fragment StreamingFlowGraphBuilder::BuildVectorCreation(
    TokenPosition* position) {
  if (position != NULL) *position = TokenPosition::kNoSource;

  intptr_t size = ReadUInt();  // read size.
  return AllocateContext(size);
}

Fragment StreamingFlowGraphBuilder::BuildVectorGet(TokenPosition* position) {
  if (position != NULL) *position = TokenPosition::kNoSource;

  Fragment instructions = BuildExpression();  // read expression.
  intptr_t index = ReadUInt();                // read index.
  instructions += LoadField(Context::variable_offset(index));
  return instructions;
}

Fragment StreamingFlowGraphBuilder::BuildVectorSet(TokenPosition* position) {
  if (position != NULL) *position = TokenPosition::kNoSource;

  Fragment instructions = NullConstant();
  LocalVariable* result = MakeTemporary();

  instructions += BuildExpression();  // read vector expression.
  intptr_t index = ReadUInt();        // read index.
  instructions += BuildExpression();  // read value expression.
  instructions += StoreLocal(TokenPosition::kNoSource, result);

  instructions += StoreInstanceField(TokenPosition::kNoSource,
                                     Context::variable_offset(index));

  return instructions;
}

Fragment StreamingFlowGraphBuilder::BuildVectorCopy(TokenPosition* position) {
  if (position != NULL) *position = TokenPosition::kNoSource;

  Fragment instructions = BuildExpression();  // read vector expression.
  Value* context_to_copy = Pop();
  CloneContextInstr* clone_instruction =
      new (Z) CloneContextInstr(TokenPosition::kNoSource, context_to_copy,
                                Thread::Current()->GetNextDeoptId());
  instructions <<= clone_instruction;
  Push(clone_instruction);

  return instructions;
}

Fragment StreamingFlowGraphBuilder::BuildClosureCreation(
    TokenPosition* position) {
  if (position != NULL) *position = TokenPosition::kNoSource;

  NameIndex function_reference =
      ReadCanonicalNameReference();  // read function reference.
  Function& function = Function::ZoneHandle(
      Z, H.LookupStaticMethodByKernelProcedure(function_reference));
  function = function.ConvertedClosureFunction();
  ASSERT(!function.IsNull());

  const Class& closure_class =
      Class::ZoneHandle(Z, I->object_store()->closure_class());
  Fragment instructions = AllocateObject(closure_class, function);
  LocalVariable* closure = MakeTemporary();

  instructions += BuildExpression();  // read context vector.
  LocalVariable* context = MakeTemporary();

  instructions += LoadLocal(closure);
  instructions += Constant(function);
  instructions +=
      StoreInstanceField(TokenPosition::kNoSource, Closure::function_offset());

  instructions += LoadLocal(closure);
  instructions += LoadLocal(context);
  instructions +=
      StoreInstanceField(TokenPosition::kNoSource, Closure::context_offset());

  instructions += Drop();

  SkipDartType();  // skip function type of the closure.

  // TODO(30455): Kernel generic methods undone. When generic methods are
  // fully supported in kernel, we'll need to store a NULL in the type arguments
  // slot when type arguments are absent, so the wrapper for the target function
  // can tell how many type args are captured vs. provided by the caller of the
  // closure.

  intptr_t types_count = ReadListLength();  // read type count.
  if (types_count > 0) {
    instructions += LoadLocal(context);

    const TypeArguments& type_args =
        T.BuildTypeArguments(types_count);  // read list of type arguments.
    instructions += TranslateInstantiatedTypeArguments(type_args);

    instructions += StoreInstanceField(TokenPosition::kNoSource,
                                       Context::variable_offset(0));
  }

  return instructions;
}

Fragment StreamingFlowGraphBuilder::BuildInvalidStatement() {
  H.ReportError("Invalid statements not implemented yet!");
  return Fragment();
}

Fragment StreamingFlowGraphBuilder::BuildExpressionStatement() {
  Fragment instructions = BuildExpression();  // read expression.
  instructions += Drop();
  return instructions;
}

Fragment StreamingFlowGraphBuilder::BuildBlock() {
  intptr_t offset = ReaderOffset() - 1;  // Include the tag.

  Fragment instructions;

  instructions += EnterScope(offset + relative_kernel_offset_);
  intptr_t list_length = ReadListLength();  // read number of statements.
  for (intptr_t i = 0; i < list_length; ++i) {
    if (instructions.is_open()) {
      instructions += BuildStatement();  // read ith statement.
    } else {
      SkipStatement();  // read ith statement.
    }
  }
  instructions += ExitScope(offset + relative_kernel_offset_);

  return instructions;
}

Fragment StreamingFlowGraphBuilder::BuildEmptyStatement() {
  return Fragment();
}

Fragment StreamingFlowGraphBuilder::BuildAssertStatement() {
  if (!I->asserts()) {
    SetOffset(ReaderOffset() - 1);  // Include the tag.
    SkipStatement();                // read this statement.
    return Fragment();
  }

  TargetEntryInstr* then;
  TargetEntryInstr* otherwise;

  Fragment instructions;
  // Asserts can be of the following two kinds:
  //
  //    * `assert(expr)`
  //    * `assert(() { ... })`
  //
  // The call to `_AssertionError._evaluateAssertion()` will take care of both
  // and returns a boolean.
  instructions += BuildExpression();  // read condition.
  instructions += PushArgument();
  instructions += EvaluateAssertion();
  instructions += CheckBooleanInCheckedMode();
  instructions += Constant(Bool::True());
  instructions += BranchIfEqual(&then, &otherwise, false);

  TokenPosition condition_start_offset =
      ReadPosition();  // read condition start offset.
  TokenPosition condition_end_offset =
      ReadPosition();  // read condition end offset.

  const Class& klass =
      Class::ZoneHandle(Z, Library::LookupCoreClass(Symbols::AssertionError()));
  ASSERT(!klass.IsNull());
  const Function& target = Function::ZoneHandle(
      Z, klass.LookupStaticFunctionAllowPrivate(Symbols::ThrowNew()));
  ASSERT(!target.IsNull());

  // Build call to _AsertionError._throwNew(start, end, message)
  Fragment otherwise_fragment(otherwise);
  otherwise_fragment += IntConstant(condition_start_offset.Pos());
  otherwise_fragment += PushArgument();  // start
  otherwise_fragment += IntConstant(condition_end_offset.Pos());
  otherwise_fragment += PushArgument();  // end
  Tag tag = ReadTag();                   // read (first part of) message.
  if (tag == kSomething) {
    otherwise_fragment += BuildExpression();  // read (rest of) message.
  } else {
    otherwise_fragment += Constant(Instance::ZoneHandle(Z));  // null.
  }
  otherwise_fragment += PushArgument();  // message

  otherwise_fragment += StaticCall(TokenPosition::kNoSource, target, 3);
  otherwise_fragment += Drop();

  return Fragment(instructions.entry, then);
}

Fragment StreamingFlowGraphBuilder::BuildLabeledStatement() {
  // There can be serveral cases:
  //
  //   * the body contains a break
  //   * the body doesn't contain a break
  //
  //   * translating the body results in a closed fragment
  //   * translating the body results in a open fragment
  //
  // => We will only know which case we are in after the body has been
  //    traversed.

  BreakableBlock block(flow_graph_builder_);
  Fragment instructions = BuildStatement();  // read body.
  if (block.HadJumper()) {
    if (instructions.is_open()) {
      instructions += Goto(block.destination());
    }
    return Fragment(instructions.entry, block.destination());
  } else {
    return instructions;
  }
}

Fragment StreamingFlowGraphBuilder::BuildBreakStatement() {
  TokenPosition position = ReadPosition();  // read position.
  intptr_t target_index = ReadUInt();       // read target index.

  TryFinallyBlock* outer_finally = NULL;
  intptr_t target_context_depth = -1;
  JoinEntryInstr* destination = breakable_block()->BreakDestination(
      target_index, &outer_finally, &target_context_depth);

  Fragment instructions;
  instructions +=
      TranslateFinallyFinalizers(outer_finally, target_context_depth);
  if (instructions.is_open()) {
    if (NeedsDebugStepCheck(parsed_function()->function(), position)) {
      instructions += DebugStepCheck(position);
    }
    instructions += Goto(destination);
  }
  return instructions;
}

Fragment StreamingFlowGraphBuilder::BuildWhileStatement() {
  loop_depth_inc();
  ReadPosition();  // read position.

  bool negate;
  Fragment condition = TranslateCondition(&negate);  // read condition.
  TargetEntryInstr* body_entry;
  TargetEntryInstr* loop_exit;
  condition += BranchIfTrue(&body_entry, &loop_exit, negate);

  Fragment body(body_entry);
  body += BuildStatement();  // read body.

  Instruction* entry;
  if (body.is_open()) {
    JoinEntryInstr* join = BuildJoinEntry();
    body += Goto(join);

    Fragment loop(join);
    loop += CheckStackOverflow();
    loop += condition;
    entry = new (Z) GotoInstr(join, Thread::Current()->GetNextDeoptId());
  } else {
    entry = condition.entry;
  }

  loop_depth_dec();
  return Fragment(entry, loop_exit);
}

Fragment StreamingFlowGraphBuilder::BuildDoStatement() {
  loop_depth_inc();
  ReadPosition();                    // read position.
  Fragment body = BuildStatement();  // read body.

  if (body.is_closed()) {
    SkipExpression();  // read condition.
    loop_depth_dec();
    return body;
  }

  bool negate;
  JoinEntryInstr* join = BuildJoinEntry();
  Fragment loop(join);
  loop += CheckStackOverflow();
  loop += body;
  loop += TranslateCondition(&negate);  // read condition.
  TargetEntryInstr* loop_repeat;
  TargetEntryInstr* loop_exit;
  loop += BranchIfTrue(&loop_repeat, &loop_exit, negate);

  Fragment repeat(loop_repeat);
  repeat += Goto(join);

  loop_depth_dec();
  return Fragment(new (Z) GotoInstr(join, Thread::Current()->GetNextDeoptId()),
                  loop_exit);
}

Fragment StreamingFlowGraphBuilder::BuildForStatement() {
  intptr_t offset = ReaderOffset() - 1;  // Include the tag.

  ReadPosition();  // read position.

  Fragment declarations;

  bool new_context = false;
  declarations += EnterScope(offset + relative_kernel_offset_, &new_context);

  intptr_t list_length = ReadListLength();  // read number of variables.
  for (intptr_t i = 0; i < list_length; ++i) {
    declarations += BuildVariableDeclaration();  // read ith variable.
  }

  loop_depth_inc();
  bool negate = false;
  Tag tag = ReadTag();  // Read first part of condition.
  Fragment condition =
      tag == kNothing ? Constant(Bool::True())
                      : TranslateCondition(&negate);  // read rest of condition.
  TargetEntryInstr* body_entry;
  TargetEntryInstr* loop_exit;
  condition += BranchIfTrue(&body_entry, &loop_exit, negate);

  Fragment updates;
  list_length = ReadListLength();  // read number of updates.
  for (intptr_t i = 0; i < list_length; ++i) {
    updates += BuildExpression();  // read ith update.
    updates += Drop();
  }

  Fragment body(body_entry);
  body += BuildStatement();  // read body.

  if (body.is_open()) {
    // We allocated a fresh context before the loop which contains captured
    // [ForStatement] variables.  Before jumping back to the loop entry we clone
    // the context object (at same depth) which ensures the next iteration of
    // the body gets a fresh set of [ForStatement] variables (with the old
    // (possibly updated) values).
    if (new_context) body += CloneContext();

    body += updates;
    JoinEntryInstr* join = BuildJoinEntry();
    declarations += Goto(join);
    body += Goto(join);

    Fragment loop(join);
    loop += CheckStackOverflow();
    loop += condition;
  } else {
    declarations += condition;
  }

  Fragment loop(declarations.entry, loop_exit);
  loop_depth_dec();

  loop += ExitScope(offset + relative_kernel_offset_);

  return loop;
}

Fragment StreamingFlowGraphBuilder::BuildForInStatement(bool async) {
  intptr_t offset = ReaderOffset() - 1;  // Include the tag.

  ReadPosition();                                // read position.
  TokenPosition body_position = ReadPosition();  // read body position.
  intptr_t variable_kernel_position = ReaderOffset() + relative_kernel_offset_;
  SkipVariableDeclaration();  // read variable.

  TokenPosition iterable_position = TokenPosition::kNoSource;
  Fragment instructions =
      BuildExpression(&iterable_position);  // read iterable.
  instructions += PushArgument();

  const String& iterator_getter =
      String::ZoneHandle(Z, Field::GetterSymbol(Symbols::Iterator()));
  instructions +=
      InstanceCall(iterable_position, iterator_getter, Token::kGET, 1);
  LocalVariable* iterator = scopes()->iterator_variables[for_in_depth()];
  instructions += StoreLocal(TokenPosition::kNoSource, iterator);
  instructions += Drop();

  for_in_depth_inc();
  loop_depth_inc();
  Fragment condition = LoadLocal(iterator);
  condition += PushArgument();
  condition +=
      InstanceCall(iterable_position, Symbols::MoveNext(), Token::kILLEGAL, 1);
  TargetEntryInstr* body_entry;
  TargetEntryInstr* loop_exit;
  condition += BranchIfTrue(&body_entry, &loop_exit, false);

  Fragment body(body_entry);
  body += EnterScope(offset + relative_kernel_offset_);
  body += LoadLocal(iterator);
  body += PushArgument();
  const String& current_getter =
      String::ZoneHandle(Z, Field::GetterSymbol(Symbols::Current()));
  body += InstanceCall(body_position, current_getter, Token::kGET, 1);
  body += StoreLocal(TokenPosition::kNoSource,
                     LookupVariable(variable_kernel_position));
  body += Drop();
  body += BuildStatement();  // read body.
  body += ExitScope(offset + relative_kernel_offset_);

  if (body.is_open()) {
    JoinEntryInstr* join = BuildJoinEntry();
    instructions += Goto(join);
    body += Goto(join);

    Fragment loop(join);
    loop += CheckStackOverflow();
    loop += condition;
  } else {
    instructions += condition;
  }

  loop_depth_dec();
  for_in_depth_dec();
  return Fragment(instructions.entry, loop_exit);
}

Fragment StreamingFlowGraphBuilder::BuildSwitchStatement() {
  // We need the number of cases. So start by getting that, then go back.
  intptr_t offset = ReaderOffset();
  SkipExpression();                   // temporarily skip condition
  int case_count = ReadListLength();  // read number of cases.
  SetOffset(offset);

  SwitchBlock block(flow_graph_builder_, case_count);

  // Instead of using a variable we should reuse the expression on the stack,
  // since it won't be assigned again, we don't need phi nodes.
  Fragment head_instructions = BuildExpression();  // read condition.
  head_instructions +=
      StoreLocal(TokenPosition::kNoSource, scopes()->switch_variable);
  head_instructions += Drop();

  case_count = ReadListLength();  // read number of cases.

  // Phase 1: Generate bodies and try to find out whether a body will be target
  // of a jump due to:
  //   * `continue case_label`
  //   * `case e1: case e2: body`
  Fragment* body_fragments = new Fragment[case_count];
  intptr_t* case_expression_offsets = new intptr_t[case_count];
  int default_case = -1;

  for (intptr_t i = 0; i < case_count; ++i) {
    case_expression_offsets[i] = ReaderOffset();
    int expression_count = ReadListLength();  // read number of expressions.
    for (intptr_t j = 0; j < expression_count; ++j) {
      ReadPosition();    // read jth position.
      SkipExpression();  // read jth expression.
    }
    bool is_default = ReadBool();  // read is_default.
    if (is_default) default_case = i;
    Fragment& body_fragment = body_fragments[i] =
        BuildStatement();  // read body.

    if (body_fragment.entry == NULL) {
      // Make a NOP in order to ensure linking works properly.
      body_fragment = NullConstant();
      body_fragment += Drop();
    }

    // The Dart language specification mandates fall-throughs in [SwitchCase]es
    // to be runtime errors.
    if (!is_default && body_fragment.is_open() && (i < (case_count - 1))) {
      const Class& klass = Class::ZoneHandle(
          Z, Library::LookupCoreClass(Symbols::FallThroughError()));
      ASSERT(!klass.IsNull());
      const Function& constructor = Function::ZoneHandle(
          Z, klass.LookupConstructorAllowPrivate(
                 H.DartSymbol("FallThroughError._create")));
      ASSERT(!constructor.IsNull());
      const String& url = H.DartString(
          parsed_function()->function().ToLibNamePrefixedQualifiedCString(),
          Heap::kOld);

      // Create instance of _FallThroughError
      body_fragment += AllocateObject(TokenPosition::kNoSource, klass, 0);
      LocalVariable* instance = MakeTemporary();

      // Call _FallThroughError._create constructor.
      body_fragment += LoadLocal(instance);
      body_fragment += PushArgument();  // this

      body_fragment += Constant(url);
      body_fragment += PushArgument();  // url

      body_fragment += NullConstant();
      body_fragment += PushArgument();  // line

      body_fragment += StaticCall(TokenPosition::kNoSource, constructor, 3);
      body_fragment += Drop();

      // Throw the exception
      body_fragment += PushArgument();
      body_fragment += ThrowException(TokenPosition::kNoSource);
      body_fragment += Drop();
    }

    // If there is an implicit fall-through we have one [SwitchCase] and
    // multiple expressions, e.g.
    //
    //    switch(expr) {
    //      case a:
    //      case b:
    //        <stmt-body>
    //    }
    //
    // This means that the <stmt-body> will have more than 1 incoming edge (one
    // from `a == expr` and one from `a != expr && b == expr`). The
    // `block.Destination()` records the additional jump.
    if (expression_count > 1) {
      block.DestinationDirect(i);
    }
  }

  intptr_t end_offset = ReaderOffset();

  // Phase 2: Generate everything except the real bodies:
  //   * jump directly to a body (if there is no jumper)
  //   * jump to a wrapper block which jumps to the body (if there is a jumper)
  Fragment current_instructions = head_instructions;
  for (intptr_t i = 0; i < case_count; ++i) {
    SetOffset(case_expression_offsets[i]);
    int expression_count = ReadListLength();  // read length of expressions.

    if (i == default_case) {
      ASSERT(i == (case_count - 1));

      // Evaluate the conditions for the default [SwitchCase] just for the
      // purpose of potentially triggering a compile-time error.

      for (intptr_t j = 0; j < expression_count; ++j) {
        ReadPosition();  // read jth position.
        // this reads the expression, but doesn't skip past it.
        constant_evaluator_.EvaluateExpression(ReaderOffset());
        SkipExpression();  // read jth expression.
      }

      if (block.HadJumper(i)) {
        // There are several branches to the body, so we will make a goto to
        // the join block (and prepend a join instruction to the real body).
        JoinEntryInstr* join = block.DestinationDirect(i);
        current_instructions += Goto(join);

        current_instructions = Fragment(current_instructions.entry, join);
        current_instructions += body_fragments[i];
      } else {
        current_instructions += body_fragments[i];
      }
    } else {
      JoinEntryInstr* body_join = NULL;
      if (block.HadJumper(i)) {
        body_join = block.DestinationDirect(i);
        body_fragments[i] = Fragment(body_join) + body_fragments[i];
      }

      for (intptr_t j = 0; j < expression_count; ++j) {
        TargetEntryInstr* then;
        TargetEntryInstr* otherwise;

        TokenPosition position = ReadPosition();  // read jth position.
        current_instructions +=
            Constant(constant_evaluator_.EvaluateExpression(ReaderOffset()));
        SkipExpression();  // read jth expression.
        current_instructions += PushArgument();
        current_instructions += LoadLocal(scopes()->switch_variable);
        current_instructions += PushArgument();
        current_instructions +=
            InstanceCall(position, Symbols::EqualOperator(), Token::kEQ,
                         /*argument_count=*/2,
                         /*checked_argument_count=*/2);
        current_instructions += BranchIfTrue(&then, &otherwise, false);

        Fragment then_fragment(then);

        if (body_join != NULL) {
          // There are several branches to the body, so we will make a goto to
          // the join block (the real body has already been prepended with a
          // join instruction).
          then_fragment += Goto(body_join);
        } else {
          // There is only a signle branch to the body, so we will just append
          // the body fragment.
          then_fragment += body_fragments[i];
        }

        current_instructions = Fragment(otherwise);
      }
    }
  }

  if (case_count > 0 && default_case < 0) {
    // There is no default, which means we have an open [current_instructions]
    // (which is a [TargetEntryInstruction] for the last "otherwise" branch).
    //
    // Furthermore the last [SwitchCase] can be open as well.  If so, we need
    // to join these two.
    Fragment& last_body = body_fragments[case_count - 1];
    if (last_body.is_open()) {
      ASSERT(current_instructions.is_open());
      ASSERT(current_instructions.current->IsTargetEntry());

      // Join the last "otherwise" branch and the last [SwitchCase] fragment.
      JoinEntryInstr* join = BuildJoinEntry();
      current_instructions += Goto(join);
      last_body += Goto(join);

      current_instructions = Fragment(join);
    }
  } else {
    // All non-default cases will be closed (i.e. break/continue/throw/return)
    // So it is fine to just let more statements after the switch append to the
    // default case.
  }

  delete[] body_fragments;
  delete[] case_expression_offsets;

  SetOffset(end_offset);
  return Fragment(head_instructions.entry, current_instructions.current);
}

Fragment StreamingFlowGraphBuilder::BuildContinueSwitchStatement() {
  intptr_t target_index = ReadUInt();  // read target index.

  TryFinallyBlock* outer_finally = NULL;
  intptr_t target_context_depth = -1;
  JoinEntryInstr* entry = switch_block()->Destination(
      target_index, &outer_finally, &target_context_depth);

  Fragment instructions;
  instructions +=
      TranslateFinallyFinalizers(outer_finally, target_context_depth);
  if (instructions.is_open()) {
    instructions += Goto(entry);
  }
  return instructions;
}

Fragment StreamingFlowGraphBuilder::BuildIfStatement() {
  bool negate;
  Fragment instructions = TranslateCondition(&negate);  // read condition.
  TargetEntryInstr* then_entry;
  TargetEntryInstr* otherwise_entry;
  instructions += BranchIfTrue(&then_entry, &otherwise_entry, negate);

  Fragment then_fragment(then_entry);
  then_fragment += BuildStatement();  // read then.

  Fragment otherwise_fragment(otherwise_entry);
  otherwise_fragment += BuildStatement();  // read otherwise.

  if (then_fragment.is_open()) {
    if (otherwise_fragment.is_open()) {
      JoinEntryInstr* join = BuildJoinEntry();
      then_fragment += Goto(join);
      otherwise_fragment += Goto(join);
      return Fragment(instructions.entry, join);
    } else {
      return Fragment(instructions.entry, then_fragment.current);
    }
  } else if (otherwise_fragment.is_open()) {
    return Fragment(instructions.entry, otherwise_fragment.current);
  } else {
    return instructions.closed();
  }
}

Fragment StreamingFlowGraphBuilder::BuildReturnStatement() {
  TokenPosition position = ReadPosition();  // read position.
  Tag tag = ReadTag();                      // read first part of expression.

  bool inside_try_finally = try_finally_block() != NULL;

  Fragment instructions = tag == kNothing
                              ? NullConstant()
                              : BuildExpression();  // read rest of expression.

  if (instructions.is_open()) {
    if (inside_try_finally) {
      ASSERT(scopes()->finally_return_variable != NULL);
      const Function& function = parsed_function()->function();
      if (NeedsDebugStepCheck(function, position)) {
        instructions += DebugStepCheck(position);
      }
      instructions += StoreLocal(position, scopes()->finally_return_variable);
      instructions += Drop();
      instructions += TranslateFinallyFinalizers(NULL, -1);
      if (instructions.is_open()) {
        instructions += LoadLocal(scopes()->finally_return_variable);
        instructions += Return(TokenPosition::kNoSource);
      }
    } else {
      instructions += Return(position);
    }
  } else {
    Pop();
  }

  return instructions;
}

Fragment StreamingFlowGraphBuilder::BuildTryCatch() {
  InlineBailout("kernel::FlowgraphBuilder::VisitTryCatch");

  intptr_t try_handler_index = AllocateTryIndex();
  Fragment try_body = TryCatch(try_handler_index);
  JoinEntryInstr* after_try = BuildJoinEntry();

  // Fill in the body of the try.
  try_depth_inc();
  {
    TryCatchBlock block(flow_graph_builder_, try_handler_index);
    try_body += BuildStatement();  // read body.
    try_body += Goto(after_try);
  }
  try_depth_dec();

  bool needs_stacktrace = ReadBool();  // read any_catch_needs_stack_trace

  catch_depth_inc();
  intptr_t catch_count = ReadListLength();  // read number of catches.
  const Array& handler_types =
      Array::ZoneHandle(Z, Array::New(catch_count, Heap::kOld));
  Fragment catch_body =
      CatchBlockEntry(handler_types, try_handler_index, needs_stacktrace);
  // Fill in the body of the catch.
  for (intptr_t i = 0; i < catch_count; ++i) {
    intptr_t catch_offset = ReaderOffset();  // Catch has no tag.
    Tag tag = PeekTag();                     // peek guard type.
    AbstractType* type_guard = NULL;
    if (tag != kDynamicType) {
      type_guard = &T.BuildType();  // read guard.
      handler_types.SetAt(i, *type_guard);
    } else {
      SkipDartType();  // read guard.
      handler_types.SetAt(i, Object::dynamic_type());
    }

    Fragment catch_handler_body =
        EnterScope(catch_offset + relative_kernel_offset_);

    tag = ReadTag();  // read first part of exception.
    if (tag == kSomething) {
      catch_handler_body += LoadLocal(CurrentException());
      catch_handler_body +=
          StoreLocal(TokenPosition::kNoSource,
                     LookupVariable(ReaderOffset() + relative_kernel_offset_));
      catch_handler_body += Drop();
      SkipVariableDeclaration();  // read exception.
    }

    tag = ReadTag();  // read first part of stack trace.
    if (tag == kSomething) {
      catch_handler_body += LoadLocal(CurrentStackTrace());
      catch_handler_body +=
          StoreLocal(TokenPosition::kNoSource,
                     LookupVariable(ReaderOffset() + relative_kernel_offset_));
      catch_handler_body += Drop();
      SkipVariableDeclaration();  // read stack trace.
    }

    {
      CatchBlock block(flow_graph_builder_, CurrentException(),
                       CurrentStackTrace(), try_handler_index);

      catch_handler_body += BuildStatement();  // read body.

      // Note: ExitScope adjusts context_depth_ so even if catch_handler_body
      // is closed we still need to execute ExitScope for its side effect.
      catch_handler_body += ExitScope(catch_offset + relative_kernel_offset_);
      if (catch_handler_body.is_open()) {
        catch_handler_body += Goto(after_try);
      }
    }

    if (type_guard != NULL) {
      if (type_guard->IsMalformed()) {
        catch_body += ThrowTypeError();
        catch_body += Drop();
      } else {
        catch_body += LoadLocal(CurrentException());
        catch_body += PushArgument();  // exception
        if (!type_guard->IsInstantiated(kCurrentClass)) {
          catch_body += LoadInstantiatorTypeArguments();
        } else {
          catch_body += NullConstant();
        }
        catch_body += PushArgument();  // instantiator type arguments
        if (!type_guard->IsInstantiated(kFunctions)) {
          catch_body += LoadFunctionTypeArguments();
        } else {
          catch_body += NullConstant();
        }
        catch_body += PushArgument();  // function type arguments
        catch_body += Constant(*type_guard);
        catch_body += PushArgument();  // guard type
        catch_body += InstanceCall(
            TokenPosition::kNoSource,
            Library::PrivateCoreLibName(Symbols::_instanceOf()), Token::kIS, 4);

        TargetEntryInstr* catch_entry;
        TargetEntryInstr* next_catch_entry;
        catch_body += BranchIfTrue(&catch_entry, &next_catch_entry, false);

        Fragment(catch_entry) + catch_handler_body;
        catch_body = Fragment(next_catch_entry);
      }
    } else {
      catch_body += catch_handler_body;
    }
  }

  // In case the last catch body was not handling the exception and branching to
  // after the try block, we will rethrow the exception (i.e. no default catch
  // handler).
  if (catch_body.is_open()) {
    catch_body += LoadLocal(CurrentException());
    catch_body += PushArgument();
    catch_body += LoadLocal(CurrentStackTrace());
    catch_body += PushArgument();
    catch_body += RethrowException(TokenPosition::kNoSource, try_handler_index);
    Drop();
  }
  catch_depth_dec();

  return Fragment(try_body.entry, after_try);
}

Fragment StreamingFlowGraphBuilder::BuildTryFinally() {
  // Note on streaming:
  // We only stream this TryFinally if we can stream everything inside it,
  // so creating a "TryFinallyBlock" with a kernel binary offset instead of an
  // AST node isn't a problem.

  InlineBailout("kernel::FlowgraphBuilder::VisitTryFinally");

  // There are 5 different cases where we need to execute the finally block:
  //
  //  a) 1/2/3th case: Special control flow going out of `node->body()`:
  //
  //   * [BreakStatement] transfers control to a [LabledStatement]
  //   * [ContinueSwitchStatement] transfers control to a [SwitchCase]
  //   * [ReturnStatement] returns a value
  //
  //   => All three cases will automatically append all finally blocks
  //      between the branching point and the destination (so we don't need to
  //      do anything here).
  //
  //  b) 4th case: Translating the body resulted in an open fragment (i.e. body
  //               executes without any control flow out of it)
  //
  //   => We are responsible for jumping out of the body to a new block (with
  //      different try index) and execute the finalizer.
  //
  //  c) 5th case: An exception occurred inside the body.
  //
  //   => We are responsible for catching it, executing the finally block and
  //      rethrowing the exception.
  intptr_t try_handler_index = AllocateTryIndex();
  Fragment try_body = TryCatch(try_handler_index);
  JoinEntryInstr* after_try = BuildJoinEntry();

  intptr_t offset = ReaderOffset();
  SkipStatement();  // temporarily read body.
  intptr_t finalizer_offset = ReaderOffset();
  SetOffset(offset);

  // Fill in the body of the try.
  try_depth_inc();
  {
    TryFinallyBlock tfb(flow_graph_builder_, finalizer_offset);
    TryCatchBlock tcb(flow_graph_builder_, try_handler_index);
    try_body += BuildStatement();  // read body.
  }
  try_depth_dec();

  if (try_body.is_open()) {
    // Please note: The try index will be on level out of this block,
    // thereby ensuring if there's an exception in the finally block we
    // won't run it twice.
    JoinEntryInstr* finally_entry = BuildJoinEntry();

    try_body += Goto(finally_entry);

    Fragment finally_body(finally_entry);
    finally_body += BuildStatement();  // read finalizer.
    finally_body += Goto(after_try);
  }

  // Fill in the body of the catch.
  catch_depth_inc();
  const Array& handler_types = Array::ZoneHandle(Z, Array::New(1, Heap::kOld));
  handler_types.SetAt(0, Object::dynamic_type());
  // Note: rethrow will actually force mark the handler as needing a stacktrace.
  Fragment finally_body = CatchBlockEntry(handler_types, try_handler_index,
                                          /* needs_stacktrace = */ false);
  SetOffset(finalizer_offset);
  finally_body += BuildStatement();  // read finalizer
  if (finally_body.is_open()) {
    finally_body += LoadLocal(CurrentException());
    finally_body += PushArgument();
    finally_body += LoadLocal(CurrentStackTrace());
    finally_body += PushArgument();
    finally_body +=
        RethrowException(TokenPosition::kNoSource, try_handler_index);
    Drop();
  }
  catch_depth_dec();

  return Fragment(try_body.entry, after_try);
}

Fragment StreamingFlowGraphBuilder::BuildYieldStatement() {
  TokenPosition position = ReadPosition();  // read position.
  uint8_t flags = ReadByte();               // read flags.

  ASSERT(flags == kNativeYieldFlags);  // Must have been desugared.

  // Setup yield/continue point:
  //
  //   ...
  //   :await_jump_var = index;
  //   :await_ctx_var = :current_context_var
  //   return <expr>
  //
  // Continuation<index>:
  //   Drop(1)
  //   ...
  //
  // BuildGraphOfFunction will create a dispatch that jumps to
  // Continuation<:await_jump_var> upon entry to the function.
  //
  Fragment instructions = IntConstant(yield_continuations().length() + 1);
  instructions +=
      StoreLocal(TokenPosition::kNoSource, scopes()->yield_jump_variable);
  instructions += Drop();
  instructions += LoadLocal(parsed_function()->current_context_var());
  instructions +=
      StoreLocal(TokenPosition::kNoSource, scopes()->yield_context_variable);
  instructions += Drop();
  instructions += BuildExpression();  // read expression.
  instructions += Return(TokenPosition::kNoSource);

  // Note: DropTempsInstr serves as an anchor instruction. It will not
  // be linked into the resulting graph.
  DropTempsInstr* anchor = new (Z) DropTempsInstr(0, NULL);
  yield_continuations().Add(YieldContinuation(anchor, CurrentTryIndex()));

  Fragment continuation(instructions.entry, anchor);

  if (parsed_function()->function().IsAsyncClosure() ||
      parsed_function()->function().IsAsyncGenClosure()) {
    // If function is async closure or async gen closure it takes three
    // parameters where the second and the third are exception and stack_trace.
    // Check if exception is non-null and rethrow it.
    //
    //   :async_op([:result, :exception, :stack_trace]) {
    //     ...
    //     Continuation<index>:
    //       if (:exception != null) rethrow(:exception, :stack_trace);
    //     ...
    //   }
    //
    LocalScope* scope = parsed_function()->node_sequence()->scope();
    LocalVariable* exception_var = scope->VariableAt(2);
    LocalVariable* stack_trace_var = scope->VariableAt(3);
    ASSERT(exception_var->name().raw() == Symbols::ExceptionParameter().raw());
    ASSERT(stack_trace_var->name().raw() ==
           Symbols::StackTraceParameter().raw());

    TargetEntryInstr* no_error;
    TargetEntryInstr* error;

    continuation += LoadLocal(exception_var);
    continuation += BranchIfNull(&no_error, &error);

    Fragment rethrow(error);
    rethrow += LoadLocal(exception_var);
    rethrow += PushArgument();
    rethrow += LoadLocal(stack_trace_var);
    rethrow += PushArgument();
    rethrow += RethrowException(position, CatchClauseNode::kInvalidTryIndex);
    Drop();

    continuation = Fragment(continuation.entry, no_error);
  }

  return continuation;
}

Fragment StreamingFlowGraphBuilder::BuildVariableDeclaration() {
  intptr_t kernel_position_no_tag = ReaderOffset() + relative_kernel_offset_;
  LocalVariable* variable = LookupVariable(kernel_position_no_tag);

  VariableDeclarationHelper helper(this);
  helper.ReadUntilExcluding(VariableDeclarationHelper::kType);
  String& name = H.DartSymbol(helper.name_index_);
  AbstractType& type = T.BuildType();  // read type.
  Tag tag = ReadTag();                 // read (first part of) initializer.

  Fragment instructions;
  if (tag == kNothing) {
    instructions += NullConstant();
  } else {
    if (helper.IsConst()) {
      const Instance& constant_value = constant_evaluator_.EvaluateExpression(
          ReaderOffset());  // read initializer form current position.
      variable->SetConstValue(constant_value);
      instructions += Constant(constant_value);
      SkipExpression();  // skip initializer.
    } else {
      // Initializer
      instructions += BuildExpression();  // read (actual) initializer.
      instructions += CheckVariableTypeInCheckedMode(type, name);
    }
  }

  // Use position of equal sign if it exists. If the equal sign does not exist
  // use the position of the identifier.
  TokenPosition debug_position =
      Utils::Maximum(helper.position_, helper.equals_position_);
  if (NeedsDebugStepCheck(stack(), debug_position)) {
    instructions = DebugStepCheck(debug_position) + instructions;
  }
  instructions += StoreLocal(helper.position_, variable);
  instructions += Drop();
  return instructions;
}

Fragment StreamingFlowGraphBuilder::BuildFunctionDeclaration() {
  TokenPosition position = ReadPosition();  // read position.
  intptr_t variable_offset = ReaderOffset() + relative_kernel_offset_;

  // read variable declaration.
  VariableDeclarationHelper helper(this);
  helper.ReadUntilExcluding(VariableDeclarationHelper::kEnd);

  Fragment instructions = DebugStepCheck(position);
  instructions += BuildFunctionNode(position, helper.name_index_);
  instructions += StoreLocal(position, LookupVariable(variable_offset));
  instructions += Drop();
  return instructions;
}

Fragment StreamingFlowGraphBuilder::BuildFunctionNode(
    TokenPosition parent_position,
    StringIndex name_index) {
  intptr_t offset = ReaderOffset() + relative_kernel_offset_;

  FunctionNodeHelper function_node_helper(this);
  function_node_helper.ReadUntilExcluding(
      FunctionNodeHelper::kTotalParameterCount);
  TokenPosition position = function_node_helper.position_;

  bool declaration = name_index >= 0;

  if (declaration) {
    position = parent_position;
  }
  if (!position.IsReal()) {
    // Positions has to be unique in regards to the parent.
    // A non-real at this point is probably -1, we cannot blindly use that
    // as others might use it too. Create a new dummy non-real TokenPosition.
    position = TokenPosition(offset).ToSynthetic();
  }

  // The VM has a per-isolate table of functions indexed by the enclosing
  // function and token position.
  Function& function = Function::ZoneHandle(Z);

  // NOTE: This is not TokenPosition in the general sense!
  function = I->LookupClosureFunction(parsed_function()->function(), position);
  if (function.IsNull()) {
    for (intptr_t i = 0; i < scopes()->function_scopes.length(); ++i) {
      if (scopes()->function_scopes[i].kernel_offset != offset) {
        continue;
      }

      const String* name;
      if (declaration) {
        name = &H.DartSymbol(name_index);
      } else {
        name = &Symbols::AnonymousClosure();
      }
      // NOTE: This is not TokenPosition in the general sense!
      function = Function::NewClosureFunction(
          *name, parsed_function()->function(), position);

      function.set_is_debuggable(function_node_helper.dart_async_marker_ ==
                                 FunctionNodeHelper::kSync);
      switch (function_node_helper.dart_async_marker_) {
        case FunctionNodeHelper::kSyncStar:
          function.set_modifier(RawFunction::kSyncGen);
          break;
        case FunctionNodeHelper::kAsync:
          function.set_modifier(RawFunction::kAsync);
          function.set_is_inlinable(!FLAG_causal_async_stacks);
          break;
        case FunctionNodeHelper::kAsyncStar:
          function.set_modifier(RawFunction::kAsyncGen);
          function.set_is_inlinable(!FLAG_causal_async_stacks);
          break;
        default:
          // no special modifier
          break;
      }
      function.set_is_generated_body(function_node_helper.async_marker_ ==
                                     FunctionNodeHelper::kSyncYielding);
      if (function.IsAsyncClosure() || function.IsAsyncGenClosure()) {
        function.set_is_inlinable(!FLAG_causal_async_stacks);
      }

      function.set_end_token_pos(function_node_helper.end_position_);
      LocalScope* scope = scopes()->function_scopes[i].scope;
      const ContextScope& context_scope = ContextScope::Handle(
          Z, scope->PreserveOuterScope(flow_graph_builder_->context_depth_));
      function.set_context_scope(context_scope);
      function.set_kernel_offset(offset);
      SetupFunctionParameters(Class::Handle(Z), function,
                              false,  // is_method
                              true,   // is_closure
                              &function_node_helper);
      function_node_helper.ReadUntilExcluding(FunctionNodeHelper::kEnd);
      TypedData& kernel_data = reader_->CopyDataToVMHeap(
          Z, offset - relative_kernel_offset_, ReaderOffset());
      function.set_kernel_data(kernel_data);

      // Finalize function type.
      Type& signature_type = Type::Handle(Z, function.SignatureType());
      signature_type ^=
          ClassFinalizer::FinalizeType(*active_class()->klass, signature_type);
      function.SetSignatureType(signature_type);

      I->AddClosureFunction(function);
      break;
    }
  }

  function_node_helper.ReadUntilExcluding(FunctionNodeHelper::kEnd);

  const Class& closure_class =
      Class::ZoneHandle(Z, I->object_store()->closure_class());
  ASSERT(!closure_class.IsNull());
  Fragment instructions =
      flow_graph_builder_->AllocateObject(closure_class, function);
  LocalVariable* closure = MakeTemporary();

  // The function signature can have uninstantiated class type parameters.
  //
  // TODO(regis): Also handle the case of a function signature that has
  // uninstantiated function type parameters.
  if (!function.HasInstantiatedSignature(kCurrentClass)) {
    instructions += LoadLocal(closure);
    instructions += LoadInstantiatorTypeArguments();
    instructions += flow_graph_builder_->StoreInstanceField(
        TokenPosition::kNoSource,
        Closure::instantiator_type_arguments_offset());
  }

  // Store the function and the context in the closure.
  instructions += LoadLocal(closure);
  instructions += Constant(function);
  instructions += flow_graph_builder_->StoreInstanceField(
      TokenPosition::kNoSource, Closure::function_offset());

  instructions += LoadLocal(closure);
  instructions += LoadLocal(parsed_function()->current_context_var());
  instructions += flow_graph_builder_->StoreInstanceField(
      TokenPosition::kNoSource, Closure::context_offset());

  return instructions;
}

void StreamingFlowGraphBuilder::SetupFunctionParameters(
    const Class& klass,
    const Function& function,
    bool is_method,
    bool is_closure,
    FunctionNodeHelper* function_node_helper) {
  ASSERT(!(is_method && is_closure));
  bool is_factory = function.IsFactory();
  intptr_t extra_parameters = (is_method || is_closure || is_factory) ? 1 : 0;

  function_node_helper->ReadUntilExcluding(
      FunctionNodeHelper::kPositionalParameters);

  intptr_t required_parameter_count =
      function_node_helper->required_parameter_count_;
  intptr_t total_parameter_count = function_node_helper->total_parameter_count_;

  intptr_t positional_parameter_count = ReadListLength();  // read list length.

  intptr_t named_parameter_count =
      total_parameter_count - positional_parameter_count;

  function.set_num_fixed_parameters(extra_parameters +
                                    required_parameter_count);
  if (named_parameter_count > 0) {
    function.SetNumOptionalParameters(named_parameter_count, false);
  } else {
    function.SetNumOptionalParameters(
        positional_parameter_count - required_parameter_count, true);
  }
  intptr_t parameter_count = extra_parameters + total_parameter_count;
  function.set_parameter_types(
      Array::Handle(Z, Array::New(parameter_count, Heap::kOld)));
  function.set_parameter_names(
      Array::Handle(Z, Array::New(parameter_count, Heap::kOld)));
  intptr_t pos = 0;
  if (is_method) {
    ASSERT(!klass.IsNull());
    function.SetParameterTypeAt(pos, H.GetCanonicalType(klass));
    function.SetParameterNameAt(pos, Symbols::This());
    pos++;
  } else if (is_closure) {
    function.SetParameterTypeAt(pos, AbstractType::dynamic_type());
    function.SetParameterNameAt(pos, Symbols::ClosureParameter());
    pos++;
  } else if (is_factory) {
    function.SetParameterTypeAt(pos, AbstractType::dynamic_type());
    function.SetParameterNameAt(pos, Symbols::TypeArgumentsParameter());
    pos++;
  }

  for (intptr_t i = 0; i < positional_parameter_count; ++i, ++pos) {
    // Read ith variable declaration.
    VariableDeclarationHelper helper(this);
    helper.ReadUntilExcluding(VariableDeclarationHelper::kType);
    const AbstractType& type = T.BuildTypeWithoutFinalization();  // read type.
    Tag tag = ReadTag();  // read (first part of) initializer.
    if (tag == kSomething) {
      SkipExpression();  // read (actual) initializer.
    }

    function.SetParameterTypeAt(
        pos, type.IsMalformed() ? Type::dynamic_type() : type);
    function.SetParameterNameAt(pos, H.DartSymbol(helper.name_index_));
  }

  intptr_t named_parameter_count_check = ReadListLength();  // read list length.
  ASSERT(named_parameter_count_check == named_parameter_count);
  for (intptr_t i = 0; i < named_parameter_count; ++i, ++pos) {
    // Read ith variable declaration.
    VariableDeclarationHelper helper(this);
    helper.ReadUntilExcluding(VariableDeclarationHelper::kType);
    const AbstractType& type = T.BuildTypeWithoutFinalization();  // read type.
    Tag tag = ReadTag();  // read (first part of) initializer.
    if (tag == kSomething) {
      SkipExpression();  // read (actual) initializer.
    }

    function.SetParameterTypeAt(
        pos, type.IsMalformed() ? Type::dynamic_type() : type);
    function.SetParameterNameAt(pos, H.DartSymbol(helper.name_index_));
  }

  function_node_helper->SetJustRead(FunctionNodeHelper::kNamedParameters);

  // The result type for generative constructors has already been set.
  if (!function.IsGenerativeConstructor()) {
    const AbstractType& return_type =
        T.BuildTypeWithoutFinalization();  // read return type.
    function.set_result_type(return_type.IsMalformed() ? Type::dynamic_type()
                                                       : return_type);
    function_node_helper->SetJustRead(FunctionNodeHelper::kReturnType);
  }
}

RawObject* StreamingFlowGraphBuilder::BuildParameterDescriptor(
    intptr_t kernel_offset) {
  SetOffset(kernel_offset);
  ReadUntilFunctionNode();  // read until function node.
  FunctionNodeHelper function_node_helper(this);
  function_node_helper.ReadUntilExcluding(
      FunctionNodeHelper::kPositionalParameters);
  intptr_t param_count = function_node_helper.total_parameter_count_;
  intptr_t positional_count = ReadListLength();  // read list length.
  intptr_t named_parameter_count = param_count - positional_count;

  const Array& param_descriptor = Array::Handle(
      Array::New(param_count * Parser::kParameterEntrySize, Heap::kOld));
  for (intptr_t i = 0; i < param_count; ++i) {
    const intptr_t entry_start = i * Parser::kParameterEntrySize;

    if (i == positional_count) {
      intptr_t named_parameter_count_check =
          ReadListLength();  // read list length.
      ASSERT(named_parameter_count_check == named_parameter_count);
    }

    // Read ith variable declaration.
    VariableDeclarationHelper helper(this);
    helper.ReadUntilExcluding(VariableDeclarationHelper::kInitializer);
    param_descriptor.SetAt(entry_start + Parser::kParameterIsFinalOffset,
                           helper.IsFinal() ? Bool::True() : Bool::False());

    Tag tag = ReadTag();  // read (first part of) initializer.
    if (tag == kSomething) {
      // this will (potentially) read the initializer, but reset the position.
      Instance& constant =
          constant_evaluator_.EvaluateExpression(ReaderOffset());
      SkipExpression();  // read (actual) initializer.
      param_descriptor.SetAt(entry_start + Parser::kParameterDefaultValueOffset,
                             constant);
    } else {
      param_descriptor.SetAt(entry_start + Parser::kParameterDefaultValueOffset,
                             Object::null_instance());
    }

    param_descriptor.SetAt(entry_start + Parser::kParameterMetadataOffset,
                           /* Issue(28434): Missing parameter metadata. */
                           Object::null_instance());
  }
  return param_descriptor.raw();
}

RawObject* StreamingFlowGraphBuilder::EvaluateMetadata(intptr_t kernel_offset) {
  SetOffset(kernel_offset);
  const Tag tag = PeekTag();

  if (tag == kClass) {
    ClassHelper class_helper(this);
    class_helper.ReadUntilExcluding(ClassHelper::kAnnotations);
  } else if (tag == kProcedure) {
    ProcedureHelper procedure_helper(this);
    procedure_helper.ReadUntilExcluding(ProcedureHelper::kAnnotations);
  } else if (tag == kField) {
    FieldHelper field_helper(this);
    field_helper.ReadUntilExcluding(FieldHelper::kAnnotations);
  } else if (tag == kConstructor) {
    ConstructorHelper constructor_helper(this);
    constructor_helper.ReadUntilExcluding(ConstructorHelper::kAnnotations);
  } else {
    FATAL("No support for metadata on this type of kernel node\n");
  }

  intptr_t list_length = ReadListLength();  // read list length.
  const Array& metadata_values = Array::Handle(Z, Array::New(list_length));
  for (intptr_t i = 0; i < list_length; ++i) {
    // this will (potentially) read the expression, but reset the position.
    Instance& value = constant_evaluator_.EvaluateExpression(ReaderOffset());
    SkipExpression();  // read (actual) initializer.
    metadata_values.SetAt(i, value);
  }

  return metadata_values.raw();
}

void StreamingFlowGraphBuilder::CollectTokenPositionsFor(
    intptr_t script_index,
    intptr_t initial_script_index,
    GrowableArray<intptr_t>* record_token_positions_in,
    GrowableArray<intptr_t>* record_yield_positions_in) {
  record_token_positions_into_ = record_token_positions_in;
  record_yield_positions_into_ = record_yield_positions_in;
  record_for_script_id_ = script_index;
  current_script_id_ = initial_script_index;

  const Tag tag = PeekTag();
  if (tag == kProcedure) {
    ProcedureHelper procedure_helper(this);
    procedure_helper.ReadUntilExcluding(ProcedureHelper::kEnd);
  } else if (tag == kConstructor) {
    ConstructorHelper constructor_helper(this);
    constructor_helper.ReadUntilExcluding(ConstructorHelper::kEnd);
  } else if (tag == kFunctionNode) {
    FunctionNodeHelper function_node_helper(this);
    function_node_helper.ReadUntilExcluding(FunctionNodeHelper::kEnd);
  } else if (tag == kField) {
    FieldHelper field_helper(this);
    field_helper.ReadUntilExcluding(FieldHelper::kEnd);
  } else {
    UNREACHABLE();
  }

  record_token_positions_into_ = NULL;
  record_yield_positions_into_ = NULL;
  record_for_script_id_ = -1;
}

intptr_t StreamingFlowGraphBuilder::SourceTableSize() {
  AlternativeReadingScope alt(reader_);
  SetOffset(reader_->size() - 4);
  intptr_t library_count = reader_->ReadUInt32();
  SetOffset(reader_->size() - 4 - 4 * library_count - 3 * 4);
  SetOffset(reader_->ReadUInt32());  // read source table offset.
  return ReadUInt();                 // read source table size.
}

String& StreamingFlowGraphBuilder::SourceTableUriFor(intptr_t index) {
  AlternativeReadingScope alt(reader_);
  SetOffset(reader_->size() - 4);
  intptr_t library_count = reader_->ReadUInt32();
  SetOffset(reader_->size() - 4 - 4 * library_count - 3 * 4);
  SetOffset(reader_->ReadUInt32());  // read source table offset.
  intptr_t size = ReadUInt();        // read source table size.
  intptr_t start = 0;
  intptr_t end = -1;
  for (intptr_t i = 0; i < size; ++i) {
    intptr_t offset = ReadUInt();
    if (i == index - 1) {
      start = offset;
    } else if (i == index) {
      end = offset;
    }
  }
  intptr_t end_offset = ReaderOffset();
  return H.DartString(
      reader_->CopyDataIntoZone(Z, end_offset + start, end - start),
      end - start, Heap::kOld);
}

String& StreamingFlowGraphBuilder::GetSourceFor(intptr_t index) {
  AlternativeReadingScope alt(reader_);
  SetOffset(reader_->size() - 4);
  intptr_t library_count = reader_->ReadUInt32();
  SetOffset(reader_->size() - 4 - 4 * library_count - 3 * 4);
  SetOffset(reader_->ReadUInt32());  // read source table offset.
  intptr_t size = ReadUInt();        // read source table size.
  intptr_t uris_size = 0;
  for (intptr_t i = 0; i < size; ++i) {
    uris_size = ReadUInt();
  }
  SkipBytes(uris_size);

  // Read the source code strings and line starts.
  for (intptr_t i = 0; i < size; ++i) {
    intptr_t length = ReadUInt();
    if (index == i) {
      return H.DartString(reader_->CopyDataIntoZone(Z, ReaderOffset(), length),
                          length, Heap::kOld);
    }
    SkipBytes(length);
    intptr_t line_count = ReadUInt();
    for (intptr_t j = 0; j < line_count; ++j) {
      ReadUInt();
    }
  }

  return String::Handle(String::null());
}

Array& StreamingFlowGraphBuilder::GetLineStartsFor(intptr_t index) {
  AlternativeReadingScope alt(reader_);
  SetOffset(reader_->size() - 4);
  intptr_t library_count = reader_->ReadUInt32();
  SetOffset(reader_->size() - 4 - 4 * library_count - 3 * 4);
  SetOffset(reader_->ReadUInt32());  // read source table offset.
  intptr_t size = ReadUInt();        // read source table size.
  intptr_t uris_size = 0;
  for (intptr_t i = 0; i < size; ++i) {
    uris_size = ReadUInt();
  }
  SkipBytes(uris_size);

  // Read the source code strings and line starts.
  for (intptr_t i = 0; i < size; ++i) {
    intptr_t length = ReadUInt();
    SkipBytes(length);
    intptr_t line_count = ReadUInt();
    if (i == index) {
      Array& array_object =
          Array::Handle(Z, Array::New(line_count, Heap::kOld));
      Smi& value = Smi::Handle(Z);
      intptr_t previous_line_start = 0;
      for (intptr_t j = 0; j < line_count; ++j) {
        intptr_t line_start = ReadUInt() + previous_line_start;
        value = Smi::New(line_start);
        array_object.SetAt(j, value);
        previous_line_start = line_start;
      }
      return array_object;
    } else {
      for (intptr_t j = 0; j < line_count; ++j) {
        ReadUInt();
      }
    }
  }

  return Array::Handle(Array::null());
}

}  // namespace kernel
}  // namespace dart

#endif  // !defined(DART_PRECOMPILED_RUNTIME)
