// 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/compiler/frontend/kernel_binary_flowgraph.h"

#include "vm/compiler/ffi/callback.h"
#include "vm/compiler/frontend/bytecode_flow_graph_builder.h"
#include "vm/compiler/frontend/bytecode_reader.h"
#include "vm/compiler/frontend/flow_graph_builder.h"  // For dart::FlowGraphBuilder::SimpleInstanceOfType.
#include "vm/compiler/frontend/prologue_builder.h"
#include "vm/compiler/jit/compiler.h"
#include "vm/object_store.h"
#include "vm/resolver.h"
#include "vm/stack_frame.h"

namespace dart {

DECLARE_FLAG(bool, enable_interpreter);

namespace kernel {

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

Class& StreamingFlowGraphBuilder::GetSuperOrDie() {
  Class& klass = Class::Handle(Z, parsed_function()->function().Owner());
  ASSERT(!klass.IsNull());
  klass = klass.SuperClass();
  ASSERT(!klass.IsNull());
  return klass;
}

FlowGraph* StreamingFlowGraphBuilder::BuildGraphOfFieldInitializer() {
  FieldHelper field_helper(this);
  field_helper.ReadUntilExcluding(FieldHelper::kInitializer);

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

  B->graph_entry_ = new (Z) GraphEntryInstr(*parsed_function(), B->osr_id_);

  auto normal_entry = B->BuildFunctionEntry(B->graph_entry_);
  B->graph_entry_->set_normal_entry(normal_entry);

  Fragment body(normal_entry);
  body += B->CheckStackOverflowInPrologue(field_helper.position_);
  if (field_helper.IsConst()) {
    // This will read the initializer.
    body += Constant(
        Instance::ZoneHandle(Z, constant_reader_.ReadConstantExpression()));
  } else {
    body += SetupCapturedParameters(parsed_function()->function());
    body += BuildExpression();  // read initializer.
  }
  body += Return(TokenPosition::kNoSource);

  PrologueInfo prologue_info(-1, -1);
  if (B->IsCompiledForOsr()) {
    B->graph_entry_->RelinkToOsrEntry(Z, B->last_used_block_id_ + 1);
  }
  return new (Z) FlowGraph(*parsed_function(), B->graph_entry_,
                           B->last_used_block_id_, prologue_info);
}

void StreamingFlowGraphBuilder::EvaluateConstFieldValue(const Field& field) {
  ASSERT(field.is_const() && field.IsUninitialized());

  FieldHelper field_helper(this);
  field_helper.ReadUntilExcluding(FieldHelper::kInitializer);
  Tag initializer_tag = ReadTag();  // read first part of initializer.

  ASSERT(initializer_tag == kSomething);

  Instance& value =
      Instance::Handle(Z, constant_reader_.ReadConstantExpression());
  field.SetStaticValue(value);
}

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 read the initializer.
          default_value = &Instance::ZoneHandle(
              Z, constant_reader_.ReadConstantExpression());
        } 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 read the initializer.
          default_value = &Instance::ZoneHandle(
              Z, constant_reader_.ReadConstantExpression());
        } 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(
    const Field& field,
    bool only_for_side_effects) {
  ASSERT(Error::Handle(Z, H.thread()->sticky_error()).IsNull());
  if (PeekTag() == kNullLiteral) {
    SkipExpression();  // read past the null literal.
    if (H.thread()->IsMutatorThread()) {
      field.RecordStore(Object::null_object());
    } else {
      ASSERT(field.is_nullable(/* silence_assert = */ true));
    }
    return Fragment();
  }

  Fragment instructions;
  if (!only_for_side_effects) {
    instructions += LoadLocal(parsed_function()->receiver_var());
  }
  // All closures created inside BuildExpression will have
  // field.RawOwner() as its owner.
  closure_owner_ = field.RawOwner();
  instructions += BuildExpression();
  closure_owner_ = Object::null();
  if (only_for_side_effects) {
    instructions += Drop();
  } else {
    instructions += flow_graph_builder_->StoreInstanceFieldGuarded(
        field, StoreInstanceFieldInstr::Kind::kInitializing);
  }
  return instructions;
}

Fragment StreamingFlowGraphBuilder::BuildLateFieldInitializer(
    const Field& field,
    bool has_initializer) {
  if (has_initializer && PeekTag() == kNullLiteral) {
    SkipExpression();  // read past the null literal.
    if (H.thread()->IsMutatorThread()) {
      field.RecordStore(Object::null_object());
    } else {
      ASSERT(field.is_nullable(/* silence_assert = */ true));
    }
    return Fragment();
  }

  Fragment instructions;
  instructions += LoadLocal(parsed_function()->receiver_var());
  instructions += flow_graph_builder_->Constant(Object::sentinel());
  instructions += flow_graph_builder_->StoreInstanceField(
      field, StoreInstanceFieldInstr::Kind::kInitializing);
  return instructions;
}

Fragment StreamingFlowGraphBuilder::BuildInitializers(
    const Class& parent_class) {
  ASSERT(Error::Handle(Z, H.thread()->sticky_error()).IsNull());
  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();
  }

  bool is_redirecting_constructor = false;

  // Field which will be initialized by the initializer with the given index.
  GrowableArray<const Field*> initializer_fields(5);

  // Check if this is a redirecting constructor and collect all fields which
  // will be initialized by the constructor initializer list.
  {
    AlternativeReadingScope alt(&reader_, initializers_offset);

    const intptr_t list_length =
        ReadListLength();  // read initializers list length.
    initializer_fields.EnsureLength(list_length, nullptr);

    bool has_field_initializers = false;
    for (intptr_t i = 0; i < list_length; ++i) {
      if (PeekTag() == kRedirectingInitializer) {
        is_redirecting_constructor = true;
      } else if (PeekTag() == kFieldInitializer) {
        has_field_initializers = true;
        ReadTag();
        ReadBool();
        const NameIndex field_name = ReadCanonicalNameReference();
        const Field& field =
            Field::Handle(Z, H.LookupFieldByKernelField(field_name));
        initializer_fields[i] = &field;
        SkipExpression();
        continue;
      }
      SkipInitializer();
    }
    ASSERT(!is_redirecting_constructor || !has_field_initializers);
  }

  // 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).
  if (!is_redirecting_constructor) {
    // Sort list of fields (represented as their kernel offsets) which will
    // be initialized by the constructor initializer list. We will not emit
    // StoreInstanceField instructions for those initializers though we will
    // still evaluate initialization expression for its side effects.
    GrowableArray<intptr_t> constructor_initialized_field_offsets(
        initializer_fields.length());
    for (auto field : initializer_fields) {
      if (field != nullptr) {
        constructor_initialized_field_offsets.Add(field->kernel_offset());
      }
    }

    constructor_initialized_field_offsets.Sort(
        [](const intptr_t* a, const intptr_t* b) {
          return static_cast<int>(*a) - static_cast<int>(*b);
        });
    constructor_initialized_field_offsets.Add(-1);

    ExternalTypedData& kernel_data = ExternalTypedData::Handle(Z);
    Array& class_fields = Array::Handle(Z, parent_class.fields());
    Field& class_field = Field::Handle(Z);
    intptr_t next_constructor_initialized_field_index = 0;
    for (intptr_t i = 0; i < class_fields.Length(); ++i) {
      class_field ^= class_fields.At(i);
      if (!class_field.is_static()) {
        const intptr_t field_offset = class_field.kernel_offset();

        // Check if this field will be initialized by the constructor
        // initializer list.
        // Note that both class_fields and the list of initialized fields
        // are sorted by their kernel offset (by construction) -
        // so we don't need to perform the search.
        bool is_constructor_initialized = false;
        const intptr_t constructor_initialized_field_offset =
            constructor_initialized_field_offsets
                [next_constructor_initialized_field_index];
        if (constructor_initialized_field_offset == field_offset) {
          next_constructor_initialized_field_index++;
          is_constructor_initialized = true;
        }

        kernel_data = class_field.KernelData();
        ASSERT(!kernel_data.IsNull());
        AlternativeReadingScopeWithNewData alt(&reader_, &kernel_data,
                                               field_offset);
        FieldHelper field_helper(this);
        field_helper.ReadUntilExcluding(FieldHelper::kInitializer);
        const Tag initializer_tag = ReadTag();
        if (class_field.is_late()) {
          if (!is_constructor_initialized) {
            instructions += BuildLateFieldInitializer(
                Field::ZoneHandle(Z, class_field.raw()),
                initializer_tag == kSomething);
          }
        } else if (initializer_tag == kSomething) {
          EnterScope(field_offset);
          // If this field is initialized in constructor then we can ignore the
          // value produced by the field initializer. However we still need to
          // execute it for its side effects.
          instructions += BuildFieldInitializer(
              Field::ZoneHandle(Z, class_field.raw()),
              /*only_for_side_effects=*/is_constructor_initialized);
          ExitScope(field_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();
      bool isSynthetic = ReadBool();  // read isSynthetic flag.
      switch (tag) {
        case kInvalidInitializer:
          UNIMPLEMENTED();
          return Fragment();
        case kFieldInitializer: {
          ReadCanonicalNameReference();
          instructions += BuildFieldInitializer(
              Field::ZoneHandle(Z, initializer_fields[i]->raw()),
              /*only_for_size_effects=*/false);
          break;
        }
        case kAssertInitializer: {
          instructions += BuildStatement();
          break;
        }
        case kSuperInitializer: {
          TokenPosition position = ReadPosition();  // read position.
          NameIndex canonical_target =
              ReadCanonicalNameReference();  // read target_reference.

          instructions += LoadLocal(parsed_function()->receiver_var());

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

          Class& parent_klass = GetSuperOrDie();

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

          instructions += LoadLocal(parsed_function()->receiver_var());

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

          const Function& target = Function::ZoneHandle(
              Z, H.LookupConstructorByKernelConstructor(canonical_target));
          instructions += StaticCall(
              isSynthetic ? TokenPosition::kNoSource : position, target,
              argument_count, argument_names, ICData::kStatic);
          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() + data_program_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:
          ReportUnexpectedTag("initializer", tag);
          UNREACHABLE();
      }
    }
  }
  return instructions;
}

void StreamingFlowGraphBuilder::ReadDefaultFunctionTypeArguments(
    const Function& function) {
  if (!function.IsGeneric()) {
    return;
  }
  AlternativeReadingScope alt(&reader_);
  FunctionNodeHelper function_node_helper(this);
  function_node_helper.ReadUntilExcluding(FunctionNodeHelper::kTypeParameters);
  intptr_t num_type_params = ReadListLength();
  ASSERT(num_type_params == function.NumTypeParameters());
  TypeArguments& default_types =
      TypeArguments::Handle(Z, TypeArguments::New(num_type_params));
  for (intptr_t i = 0; i < num_type_params; ++i) {
    TypeParameterHelper helper(this);
    helper.ReadUntilExcludingAndSetJustRead(TypeParameterHelper::kDefaultType);
    if (ReadTag() == kSomething) {
      default_types.SetTypeAt(i, T.BuildType());
    } else {
      default_types.SetTypeAt(i, Object::dynamic_type());
    }
    helper.Finish();
  }
  default_types = default_types.Canonicalize(thread(), nullptr);
  parsed_function()->SetDefaultFunctionTypeArguments(default_types);
}

Fragment StreamingFlowGraphBuilder::DebugStepCheckInPrologue(
    const Function& dart_function,
    TokenPosition position) {
  if (!NeedsDebugStepCheck(dart_function, position)) {
    return {};
  }

  // 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) {
    const LocalVariable& parameter =
        *parsed_function()->ParameterVariable(parameter_count - 1);
    check_pos = parameter.token_pos();
  }
  if (!check_pos.IsDebugPause()) {
    // No parameters or synthetic parameters.
    check_pos = position;
    ASSERT(check_pos.IsDebugPause());
  }

  return DebugStepCheck(check_pos);
}

Fragment StreamingFlowGraphBuilder::SetAsyncStackTrace(
    const Function& dart_function) {
  if (!FLAG_causal_async_stacks ||
      !(dart_function.IsAsyncClosure() || dart_function.IsAsyncGenClosure())) {
    return {};
  }

  // The code we are building will be executed right after we enter
  // the function and before any nested contexts are allocated.
  ASSERT(B->context_depth_ ==
         scopes()->yield_jump_variable->owner()->context_level());

  Fragment instructions;
  LocalScope* scope = parsed_function()->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());

  Fragment code;
  code += LoadLocal(async_stack_trace_var);
  // Call _asyncSetThreadStackTrace
  code += StaticCall(TokenPosition::kNoSource, target,
                     /* argument_count = */ 1, ICData::kStatic);
  code += Drop();
  return code;
}

Fragment StreamingFlowGraphBuilder::TypeArgumentsHandling(
    const Function& dart_function) {
  Fragment prologue = B->BuildDefaultTypeHandling(dart_function);

  if (dart_function.IsClosureFunction() &&
      dart_function.NumParentTypeParameters() > 0) {
    LocalVariable* closure = parsed_function()->ParameterVariable(0);

    // Function with yield points can not be generic itself but the outer
    // function can be.
    ASSERT(yield_continuations().is_empty() || !dart_function.IsGeneric());

    LocalVariable* fn_type_args = parsed_function()->function_type_arguments();
    ASSERT(fn_type_args != NULL && closure != NULL);

    if (dart_function.IsGeneric()) {
      prologue += LoadLocal(fn_type_args);

      prologue += LoadLocal(closure);
      prologue += LoadNativeField(Slot::Closure_function_type_arguments());

      prologue += IntConstant(dart_function.NumParentTypeParameters());

      prologue += IntConstant(dart_function.NumTypeParameters() +
                              dart_function.NumParentTypeParameters());

      const Library& dart_internal =
          Library::Handle(Z, Library::InternalLibrary());
      const Function& prepend_function =
          Function::ZoneHandle(Z, dart_internal.LookupFunctionAllowPrivate(
                                      Symbols::PrependTypeArguments()));
      ASSERT(!prepend_function.IsNull());

      prologue += StaticCall(TokenPosition::kNoSource, prepend_function, 4,
                             ICData::kStatic);
      prologue += StoreLocal(TokenPosition::kNoSource, fn_type_args);
      prologue += Drop();
    } else {
      prologue += LoadLocal(closure);
      prologue += LoadNativeField(Slot::Closure_function_type_arguments());
      prologue += StoreLocal(TokenPosition::kNoSource, fn_type_args);
      prologue += Drop();
    }
  }

  return prologue;
}

Fragment StreamingFlowGraphBuilder::CompleteBodyWithYieldContinuations(
    Fragment body) {
  // 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 = B->context_depth_;
  B->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), kInvalidTryIndex));
  yield_continuations()[0].entry->LinkTo(body.entry);

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

  const intptr_t continuation_count = yield_continuations().length();

  IndirectGotoInstr* indirect_goto;
  if (FLAG_async_igoto_threshold >= 0 &&
      continuation_count >= FLAG_async_igoto_threshold) {
    const auto& offsets = TypedData::ZoneHandle(
        Z, TypedData::New(kTypedDataInt32ArrayCid, continuation_count,
                          Heap::kOld));

    dispatch += Constant(offsets);
    dispatch += LoadLocal(scopes()->switch_variable);

    // Ideally this would just be LoadIndexedTypedData(kTypedDataInt32ArrayCid),
    // but that doesn't work in unoptimised code.
    // The optimiser will turn this into that in any case.
    dispatch += InstanceCall(TokenPosition::kNoSource, Symbols::IndexToken(),
                             Token::kINDEX, /*argument_count=*/2);

    Value* offset_from_start = Pop();

    indirect_goto = new (Z) IndirectGotoInstr(&offsets, offset_from_start);
    dispatch <<= indirect_goto;

    for (intptr_t i = 0; i < continuation_count; i++) {
      if (i >= 1) {
        Fragment resumption;
        // Every continuation after the first 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.
        resumption += LoadLocal(scopes()->yield_context_variable);
        resumption += StoreLocal(TokenPosition::kNoSource,
                                 parsed_function()->current_context_var());
        resumption += Drop();

        Instruction* next = yield_continuations()[i].entry->next();
        yield_continuations()[i].entry->LinkTo(resumption.entry);
        resumption <<= next;
      }

      IndirectEntryInstr* indirect_entry = B->BuildIndirectEntry(
          /*indirect_id=*/i, yield_continuations()[i].try_index);
      indirect_entry->LinkTo(yield_continuations()[i].entry->next());

      TargetEntryInstr* target = B->BuildTargetEntry();
      Fragment(target) + Goto(indirect_entry);

      indirect_goto->AddSuccessor(target);
    }
  } else {
    BlockEntryInstr* block = nullptr;
    for (intptr_t i = 0; i < continuation_count; 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 == (continuation_count - 1)) {
        // We reached the last possibility, 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_jump_var == i) {
      //     -> yield_continuations()[i]
      //   } else ...
      //
      TargetEntryInstr* then;
      TargetEntryInstr* otherwise;
      dispatch += LoadLocal(scopes()->switch_variable);
      dispatch += IntConstant(i);
      dispatch += B->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;
    }
  }
  B->context_depth_ = current_context_depth;
  return dispatch;
}

Fragment StreamingFlowGraphBuilder::CheckStackOverflowInPrologue(
    const Function& dart_function) {
  if (dart_function.is_native()) return {};
  return B->CheckStackOverflowInPrologue(dart_function.token_pos());
}

Fragment StreamingFlowGraphBuilder::SetupCapturedParameters(
    const Function& dart_function) {
  Fragment body;
  const LocalScope* scope = parsed_function()->scope();
  if (scope->num_context_variables() > 0) {
    body += flow_graph_builder_->PushContext(scope);
    LocalVariable* context = MakeTemporary();

    // Copy captured parameters from the stack into the context.
    LocalScope* scope = parsed_function()->scope();
    intptr_t parameter_count = dart_function.NumParameters();
    const ParsedFunction& pf = *flow_graph_builder_->parsed_function_;
    const Function& function = pf.function();

    for (intptr_t i = 0; i < parameter_count; ++i) {
      LocalVariable* variable = pf.ParameterVariable(i);
      if (variable->is_captured()) {
        LocalVariable& raw_parameter = *pf.RawParameterVariable(i);
        ASSERT((function.HasOptionalParameters() &&
                raw_parameter.owner() == scope) ||
               (!function.HasOptionalParameters() &&
                raw_parameter.owner() == NULL));
        ASSERT(!raw_parameter.is_captured());

        // Copy the parameter from the stack to the context.
        body += LoadLocal(context);
        body += LoadLocal(&raw_parameter);
        body += flow_graph_builder_->StoreInstanceField(
            TokenPosition::kNoSource,
            Slot::GetContextVariableSlotFor(thread(), *variable),
            StoreInstanceFieldInstr::Kind::kInitializing);
      }
    }
    body += Drop();  // The context.
  }
  return body;
}

// If we run in checked mode or strong mode, we have to check the type of the
// passed arguments.
//
// TODO(#34162): If we're building an extra entry-point to skip
// type checks, we should substitute Redefinition nodes for the AssertAssignable
// instructions to ensure that the argument types are known.
void StreamingFlowGraphBuilder::CheckArgumentTypesAsNecessary(
    const Function& dart_function,
    intptr_t type_parameters_offset,
    Fragment* explicit_checks,
    Fragment* implicit_checks,
    Fragment* implicit_redefinitions) {
  if (!dart_function.NeedsArgumentTypeChecks()) return;

  // Check if parent function was annotated with no-dynamic-invocations.
  const ProcedureAttributesMetadata attrs =
      procedure_attributes_metadata_helper_.GetProcedureAttributes(
          dart_function.kernel_offset());

  AlternativeReadingScope _(&reader_);
  SetOffset(type_parameters_offset);
  B->BuildArgumentTypeChecks(
      MethodCanSkipTypeChecksForNonCovariantArguments(dart_function, attrs)
          ? TypeChecksToBuild::kCheckCovariantTypeParameterBounds
          : TypeChecksToBuild::kCheckAllTypeParameterBounds,
      explicit_checks, implicit_checks, implicit_redefinitions);
}

Fragment StreamingFlowGraphBuilder::ShortcutForUserDefinedEquals(
    const Function& dart_function,
    LocalVariable* first_parameter) {
  // 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.
  Fragment body;
  if ((dart_function.NumParameters() == 2) &&
      (dart_function.name() == Symbols::EqualOperator().raw()) &&
      (dart_function.Owner() != I->object_store()->object_class())) {
    TargetEntryInstr* null_entry;
    TargetEntryInstr* non_null_entry;

    body += LoadLocal(first_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);
  }
  return body;
}

Fragment StreamingFlowGraphBuilder::BuildFunctionBody(
    const Function& dart_function,
    LocalVariable* first_parameter,
    bool constructor) {
  Fragment body;

  // 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.
  if (constructor) {
    body += BuildInitializers(Class::Handle(Z, dart_function.Owner()));
  }

  if (body.is_closed()) return body;

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

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

  if (dart_function.is_native()) {
    body += B->NativeFunctionBody(dart_function, first_parameter);
  } else if (has_body) {
    body += BuildStatement();
  } else if (dart_function.is_external()) {
    body += ThrowNoSuchMethodError(dart_function);
  }

  if (body.is_open()) {
    body += NullConstant();
    body += Return(dart_function.end_token_pos());
  }

  return body;
}

Fragment StreamingFlowGraphBuilder::BuildEveryTimePrologue(
    const Function& dart_function,
    TokenPosition token_position,
    intptr_t type_parameters_offset) {
  Fragment F;
  F += CheckStackOverflowInPrologue(dart_function);
  F += DebugStepCheckInPrologue(dart_function, token_position);
  F += SetAsyncStackTrace(dart_function);
  F += B->InitConstantParameters();
  return F;
}

Fragment StreamingFlowGraphBuilder::BuildFirstTimePrologue(
    const Function& dart_function,
    LocalVariable* first_parameter,
    intptr_t type_parameters_offset) {
  Fragment F;
  F += SetupCapturedParameters(dart_function);
  F += ShortcutForUserDefinedEquals(dart_function, first_parameter);
  return F;
}

Fragment StreamingFlowGraphBuilder::ClearRawParameters(
    const Function& dart_function) {
  const ParsedFunction& pf = *flow_graph_builder_->parsed_function_;
  Fragment code;
  for (intptr_t i = 0; i < dart_function.NumParameters(); ++i) {
    LocalVariable* variable = pf.ParameterVariable(i);

    if (!variable->is_captured()) continue;

    // Captured 'this' is immutable, so within the outer method we don't need to
    // load it from the context. Therefore we don't reset it to null.
    if (pf.function().HasThisParameter() && pf.has_receiver_var() &&
        variable == pf.receiver_var()) {
      ASSERT(i == 0);
      continue;
    }

    variable = pf.RawParameterVariable(i);
    code += NullConstant();
    code += StoreLocal(TokenPosition::kNoSource, variable);
    code += Drop();
  }
  return code;
}

UncheckedEntryPointStyle StreamingFlowGraphBuilder::ChooseEntryPointStyle(
    const Function& dart_function,
    const Fragment& implicit_type_checks,
    const Fragment& first_time_prologue,
    const Fragment& every_time_prologue,
    const Fragment& type_args_handling) {
  ASSERT(!dart_function.IsImplicitClosureFunction());
  if (!dart_function.MayHaveUncheckedEntryPoint() ||
      implicit_type_checks.is_empty()) {
    return UncheckedEntryPointStyle::kNone;
  }

  // Record which entry-point was taken into a variable and test it later if
  // either:
  //
  // 1. There is a non-empty PrologueBuilder-prologue.
  //
  // 2. There is a non-empty "first-time" prologue.
  //
  // 3. The "every-time" prologue has more than two instructions (DebugStepCheck
  //    and CheckStackOverflow).
  //
  // TODO(#34162): For regular closures we can often avoid the
  // PrologueBuilder-prologue on non-dynamic invocations.
  if (!PrologueBuilder::HasEmptyPrologue(dart_function) ||
      !type_args_handling.is_empty() || !first_time_prologue.is_empty() ||
      !(every_time_prologue.entry == every_time_prologue.current ||
        every_time_prologue.current->previous() == every_time_prologue.entry)) {
    return UncheckedEntryPointStyle::kSharedWithVariable;
  }

  return UncheckedEntryPointStyle::kSeparate;
}

FlowGraph* StreamingFlowGraphBuilder::BuildGraphOfFunction(
    bool is_constructor) {
  const Function& dart_function = parsed_function()->function();

  intptr_t type_parameters_offset = 0;
  LocalVariable* first_parameter = nullptr;
  TokenPosition token_position = TokenPosition::kNoSource;
  {
    AlternativeReadingScope alt(&reader_);
    FunctionNodeHelper function_node_helper(this);
    function_node_helper.ReadUntilExcluding(
        FunctionNodeHelper::kTypeParameters);
    type_parameters_offset = ReaderOffset();
    function_node_helper.ReadUntilExcluding(
        FunctionNodeHelper::kPositionalParameters);
    intptr_t list_length = ReadListLength();  // read number of positionals.
    if (list_length > 0) {
      intptr_t first_parameter_offset = ReaderOffset() + data_program_offset_;
      first_parameter = LookupVariable(first_parameter_offset);
    }
    token_position = function_node_helper.position_;
  }

  auto graph_entry = flow_graph_builder_->graph_entry_ =
      new (Z) GraphEntryInstr(*parsed_function(), flow_graph_builder_->osr_id_);

  auto normal_entry = flow_graph_builder_->BuildFunctionEntry(graph_entry);
  graph_entry->set_normal_entry(normal_entry);

  PrologueInfo prologue_info(-1, -1);
  BlockEntryInstr* instruction_cursor =
      flow_graph_builder_->BuildPrologue(normal_entry, &prologue_info);

  // The 'every_time_prologue' runs first and is run when resuming from yield
  // points.
  const Fragment every_time_prologue = BuildEveryTimePrologue(
      dart_function, token_position, type_parameters_offset);

  // The 'first_time_prologue' run after 'every_time_prologue' and is *not* run
  // when resuming from yield points.
  const Fragment first_time_prologue = BuildFirstTimePrologue(
      dart_function, first_parameter, type_parameters_offset);

  // TODO(#34162): We can remove the default type handling (and
  // shorten the prologue type handling sequence) for non-dynamic invocations of
  // regular methods.
  const Fragment type_args_handling = TypeArgumentsHandling(dart_function);

  Fragment explicit_type_checks;
  Fragment implicit_type_checks;
  Fragment implicit_redefinitions;
  CheckArgumentTypesAsNecessary(dart_function, type_parameters_offset,
                                &explicit_type_checks, &implicit_type_checks,
                                &implicit_redefinitions);

  // The RawParameter variables should be set to null to avoid retaining more
  // objects than necessary during GC.
  const Fragment body =
      ClearRawParameters(dart_function) + B->BuildNullAssertions() +
      BuildFunctionBody(dart_function, first_parameter, is_constructor);

  auto extra_entry_point_style = ChooseEntryPointStyle(
      dart_function, implicit_type_checks, first_time_prologue,
      every_time_prologue, type_args_handling);

  Fragment function(instruction_cursor);
  if (yield_continuations().is_empty()) {
    FunctionEntryInstr* extra_entry = nullptr;
    switch (extra_entry_point_style) {
      case UncheckedEntryPointStyle::kNone: {
        function += every_time_prologue + first_time_prologue +
                    type_args_handling + implicit_type_checks +
                    explicit_type_checks + body;
        break;
      }
      case UncheckedEntryPointStyle::kSeparate: {
        ASSERT(instruction_cursor == normal_entry);
        ASSERT(first_time_prologue.is_empty());
        ASSERT(type_args_handling.is_empty());

        const Fragment prologue_copy = BuildEveryTimePrologue(
            dart_function, token_position, type_parameters_offset);

        extra_entry = B->BuildSeparateUncheckedEntryPoint(
            normal_entry,
            /*normal_prologue=*/every_time_prologue + implicit_type_checks,
            /*extra_prologue=*/prologue_copy,
            /*shared_prologue=*/explicit_type_checks,
            /*body=*/body);
        break;
      }
      case UncheckedEntryPointStyle::kSharedWithVariable: {
        Fragment prologue(normal_entry, instruction_cursor);
        prologue += every_time_prologue;
        prologue += first_time_prologue;
        prologue += type_args_handling;
        prologue += explicit_type_checks;
        extra_entry = B->BuildSharedUncheckedEntryPoint(
            /*shared_prologue_linked_in=*/prologue,
            /*skippable_checks=*/implicit_type_checks,
            /*redefinitions_if_skipped=*/implicit_redefinitions,
            /*body=*/body);
        break;
      }
    }
    if (extra_entry != nullptr) {
      B->RecordUncheckedEntryPoint(graph_entry, extra_entry);
    }
  } else {
    // If the function's body contains any yield points, build switch statement
    // that selects a continuation point based on the value of :await_jump_var.
    ASSERT(explicit_type_checks.is_empty());

    // If the function is generic, type_args_handling might require access to
    // (possibly captured) 'this' for preparing default type arguments, in which
    // case we can't run it before the 'first_time_prologue'.
    ASSERT(!dart_function.IsGeneric());

    // TODO(#34162): We can probably ignore the implicit checks
    // here as well since the arguments are passed from generated code.
    function += every_time_prologue + type_args_handling +
                CompleteBodyWithYieldContinuations(first_time_prologue +
                                                   implicit_type_checks + body);
  }

  // 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_->IsCompiledForOsr()) {
    graph_entry->RelinkToOsrEntry(Z,
                                  flow_graph_builder_->last_used_block_id_ + 1);
  }
  return new (Z)
      FlowGraph(*parsed_function(), graph_entry,
                flow_graph_builder_->last_used_block_id_, prologue_info);
}

FlowGraph* StreamingFlowGraphBuilder::BuildGraph() {
  ASSERT(Error::Handle(Z, H.thread()->sticky_error()).IsNull());
  ASSERT(flow_graph_builder_ != nullptr);

  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, function.GetOutermostFunction());

  ActiveClassScope active_class_scope(active_class(), &klass);
  ActiveMemberScope active_member(active_class(), &outermost_function);
  ActiveTypeParametersScope active_type_params(active_class(), function, Z);

  if (function.is_declared_in_bytecode()) {
    bytecode_metadata_helper_.ParseBytecodeFunction(parsed_function());

    switch (function.kind()) {
      case FunctionLayout::kImplicitClosureFunction:
        return B->BuildGraphOfImplicitClosureFunction(function);
      case FunctionLayout::kImplicitGetter:
      case FunctionLayout::kImplicitSetter:
        return B->BuildGraphOfFieldAccessor(function);
      case FunctionLayout::kImplicitStaticGetter: {
        if (IsStaticFieldGetterGeneratedAsInitializer(function, Z)) {
          break;
        }
        return B->BuildGraphOfFieldAccessor(function);
      }
      case FunctionLayout::kDynamicInvocationForwarder:
        return B->BuildGraphOfDynamicInvocationForwarder(function);
      case FunctionLayout::kMethodExtractor:
        return B->BuildGraphOfMethodExtractor(function);
      case FunctionLayout::kNoSuchMethodDispatcher:
        return B->BuildGraphOfNoSuchMethodDispatcher(function);
      default:
        break;
    }

    ASSERT(function.HasBytecode());

    BytecodeFlowGraphBuilder bytecode_compiler(
        flow_graph_builder_, parsed_function(),
        &(flow_graph_builder_->ic_data_array_));

    if (B->IsRecognizedMethodForFlowGraph(function)) {
      bytecode_compiler.CreateParameterVariables();
      return B->BuildGraphOfRecognizedMethod(function);
    }

    return bytecode_compiler.BuildGraph();
  }

  // Certain special functions could have a VM-internal bytecode
  // attached to them.
  ASSERT((!function.HasBytecode()) ||
         (function.kind() == FunctionLayout::kImplicitGetter) ||
         (function.kind() == FunctionLayout::kImplicitSetter) ||
         (function.kind() == FunctionLayout::kImplicitStaticGetter) ||
         (function.kind() == FunctionLayout::kMethodExtractor) ||
         (function.kind() == FunctionLayout::kInvokeFieldDispatcher) ||
         (function.kind() == FunctionLayout::kNoSuchMethodDispatcher));

  ParseKernelASTFunction();

  switch (function.kind()) {
    case FunctionLayout::kRegularFunction:
    case FunctionLayout::kGetterFunction:
    case FunctionLayout::kSetterFunction:
    case FunctionLayout::kClosureFunction:
    case FunctionLayout::kConstructor: {
      if (B->IsRecognizedMethodForFlowGraph(function)) {
        return B->BuildGraphOfRecognizedMethod(function);
      }
      return BuildGraphOfFunction(function.IsGenerativeConstructor());
    }
    case FunctionLayout::kImplicitGetter:
    case FunctionLayout::kImplicitStaticGetter:
    case FunctionLayout::kImplicitSetter: {
      const Field& field = Field::Handle(Z, function.accessor_field());
      if (field.is_const() && field.IsUninitialized()) {
        EvaluateConstFieldValue(field);
      }
      return B->BuildGraphOfFieldAccessor(function);
    }
    case FunctionLayout::kFieldInitializer:
      return BuildGraphOfFieldInitializer();
    case FunctionLayout::kDynamicInvocationForwarder:
      return B->BuildGraphOfDynamicInvocationForwarder(function);
    case FunctionLayout::kMethodExtractor:
      return flow_graph_builder_->BuildGraphOfMethodExtractor(function);
    case FunctionLayout::kNoSuchMethodDispatcher:
      return flow_graph_builder_->BuildGraphOfNoSuchMethodDispatcher(function);
    case FunctionLayout::kInvokeFieldDispatcher:
      return flow_graph_builder_->BuildGraphOfInvokeFieldDispatcher(function);
    case FunctionLayout::kImplicitClosureFunction:
      return flow_graph_builder_->BuildGraphOfImplicitClosureFunction(function);
    case FunctionLayout::kFfiTrampoline:
      return flow_graph_builder_->BuildGraphOfFfiTrampoline(function);
    case FunctionLayout::kSignatureFunction:
    case FunctionLayout::kIrregexpFunction:
      break;
  }
  UNREACHABLE();
  return NULL;
}

void StreamingFlowGraphBuilder::ParseKernelASTFunction() {
  const Function& function = parsed_function()->function();

  const intptr_t kernel_offset = function.kernel_offset();
  ASSERT(kernel_offset >= 0);

  SetOffset(kernel_offset);

  // Mark forwarding stubs.
  switch (function.kind()) {
    case FunctionLayout::kRegularFunction:
    case FunctionLayout::kImplicitClosureFunction:
    case FunctionLayout::kGetterFunction:
    case FunctionLayout::kSetterFunction:
    case FunctionLayout::kClosureFunction:
    case FunctionLayout::kConstructor:
    case FunctionLayout::kDynamicInvocationForwarder:
      ReadForwardingStubTarget(function);
      break;
    default:
      break;
  }

  set_scopes(parsed_function()->EnsureKernelScopes());

  switch (function.kind()) {
    case FunctionLayout::kRegularFunction:
    case FunctionLayout::kGetterFunction:
    case FunctionLayout::kSetterFunction:
    case FunctionLayout::kClosureFunction:
    case FunctionLayout::kConstructor:
    case FunctionLayout::kImplicitClosureFunction:
      ReadUntilFunctionNode();
      SetupDefaultParameterValues();
      ReadDefaultFunctionTypeArguments(function);
      break;
    case FunctionLayout::kImplicitGetter:
    case FunctionLayout::kImplicitStaticGetter:
    case FunctionLayout::kImplicitSetter:
    case FunctionLayout::kFieldInitializer:
    case FunctionLayout::kMethodExtractor:
    case FunctionLayout::kNoSuchMethodDispatcher:
    case FunctionLayout::kInvokeFieldDispatcher:
    case FunctionLayout::kFfiTrampoline:
      break;
    case FunctionLayout::kDynamicInvocationForwarder:
      if (PeekTag() != kField) {
        ReadUntilFunctionNode();
        SetupDefaultParameterValues();
        ReadDefaultFunctionTypeArguments(function);
      }
      break;
    case FunctionLayout::kSignatureFunction:
    case FunctionLayout::kIrregexpFunction:
      UNREACHABLE();
      break;
  }
}

void StreamingFlowGraphBuilder::ReadForwardingStubTarget(
    const Function& function) {
  if (PeekTag() == kProcedure) {
    AlternativeReadingScope alt(&reader_);
    ProcedureHelper procedure_helper(this);
    procedure_helper.ReadUntilExcluding(ProcedureHelper::kFunction);
    if (procedure_helper.IsForwardingStub() && !procedure_helper.IsAbstract()) {
      const NameIndex target_name =
          procedure_helper.forwarding_stub_super_target_;
      ASSERT(target_name != NameIndex::kInvalidName);
      const String& name = function.IsSetterFunction()
                               ? H.DartSetterName(target_name)
                               : H.DartProcedureName(target_name);
      const Function* forwarding_target =
          &Function::ZoneHandle(Z, H.LookupMethodByMember(target_name, name));
      ASSERT(!forwarding_target->IsNull());
      parsed_function()->MarkForwardingStub(forwarding_target);
    }
  }
}

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 kSuperPropertyGet:
      return BuildSuperPropertyGet(position);
    case kSuperPropertySet:
      return BuildSuperPropertySet(position);
    case kStaticGet:
      return BuildStaticGet(position);
    case kStaticSet:
      return BuildStaticSet(position);
    case kMethodInvocation:
      return BuildMethodInvocation(position);
    case kSuperMethodInvocation:
      return BuildSuperMethodInvocation(position);
    case kDirectMethodInvocation:
      return BuildDirectMethodInvocation(position);
    case kStaticInvocation:
      return BuildStaticInvocation(position);
    case kConstructorInvocation:
      return BuildConstructorInvocation(position);
    case kNot:
      return BuildNot(position);
    case kNullCheck:
      return BuildNullCheck(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 kTypeLiteral:
      return BuildTypeLiteral(position);
    case kThisExpression:
      return BuildThisExpression(position);
    case kRethrow:
      return BuildRethrow(position);
    case kThrow:
      return BuildThrow(position);
    case kListLiteral:
      return BuildListLiteral(position);
    case kSetLiteral:
      // Set literals are currently desugared in the frontend and will not
      // reach the VM. See http://dartbug.com/35124 for discussion.
      UNREACHABLE();
      break;
    case kMapLiteral:
      return BuildMapLiteral(position);
    case kFunctionExpression:
      return BuildFunctionExpression();
    case kLet:
      return BuildLet(position);
    case kBlockExpression:
      return BuildBlockExpression();
    case kBigIntLiteral:
      return BuildBigIntLiteral(position);
    case kStringLiteral:
      return BuildStringLiteral(position);
    case kSpecializedIntLiteral:
      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 kConstantExpression:
      return BuildConstantExpression(position, tag);
    case kInstantiation:
      return BuildPartialTearoffInstantiation(position);
    case kLoadLibrary:
      return BuildLibraryPrefixAction(position, Symbols::LoadLibrary());
    case kCheckLibraryIsLoaded:
      return BuildLibraryPrefixAction(position, Symbols::CheckLoaded());
    case kConstStaticInvocation:
    case kConstConstructorInvocation:
    case kConstListLiteral:
    case kConstSetLiteral:
    case kConstMapLiteral:
    case kSymbolLiteral:
      // Const invocations and const literals are removed by the
      // constant evaluator.
    case kListConcatenation:
    case kSetConcatenation:
    case kMapConcatenation:
    case kInstanceCreation:
    case kFileUriExpression:
      // Collection concatenation, instance creation operations and
      // in-expression URI changes are internal to the front end and
      // removed by the constant evaluator.
    default:
      ReportUnexpectedTag("expression", tag);
      UNREACHABLE();
  }

  return Fragment();
}

Fragment StreamingFlowGraphBuilder::BuildStatement() {
  Tag tag = ReadTag();  // read tag.
  switch (tag) {
    case kExpressionStatement:
      return BuildExpressionStatement();
    case kBlock:
      return BuildBlock();
    case kEmptyStatement:
      return BuildEmptyStatement();
    case kAssertBlock:
      return BuildAssertBlock();
    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:
      ReportUnexpectedTag("statement", tag);
      UNREACHABLE();
  }
  return Fragment();
}

void StreamingFlowGraphBuilder::ReportUnexpectedTag(const char* variant,
                                                    Tag tag) {
  if ((flow_graph_builder_ == NULL) || (parsed_function() == NULL)) {
    KernelReaderHelper::ReportUnexpectedTag(variant, tag);
  } else {
    H.ReportError(script_, TokenPosition::kNoSource,
                  "Unexpected tag %d (%s) in %s, expected %s", tag,
                  Reader::TagName(tag),
                  parsed_function()->function().ToQualifiedCString(), variant);
  }
}

Tag KernelReaderHelper::ReadTag(uint8_t* payload) {
  return reader_.ReadTag(payload);
}

Tag KernelReaderHelper::PeekTag(uint8_t* payload) {
  return reader_.PeekTag(payload);
}

Nullability KernelReaderHelper::ReadNullability() {
  return reader_.ReadNullability();
}

Variance KernelReaderHelper::ReadVariance() {
  if (translation_helper_.info().kernel_binary_version() >= 34) {
    return reader_.ReadVariance();
  }
  return kCovariant;
}

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::block_expression_depth() {
  return flow_graph_builder_->block_expression_depth_;
}

void StreamingFlowGraphBuilder::block_expression_depth_inc() {
  ++flow_graph_builder_->block_expression_depth_;
}

void StreamingFlowGraphBuilder::block_expression_depth_dec() {
  --flow_graph_builder_->block_expression_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 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.
  if (list_length > 0) {
    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();
}

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

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

Function& StreamingFlowGraphBuilder::FindMatchingFunction(
    const Class& klass,
    const String& name,
    int type_args_len,
    int argument_count,
    const Array& argument_names) {
  // Search the superclass chain for the selector.
  ArgumentsDescriptor args_desc(
      Array::Handle(Z, ArgumentsDescriptor::NewBoxed(
                           type_args_len, argument_count, argument_names)));
  Function& function =
      Function::Handle(Z, Resolver::ResolveDynamicForReceiverClassAllowPrivate(
                              klass, name, args_desc, /*allow_add=*/false));
  return function;
}

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,
                                           intptr_t yield_index) {
  return flow_graph_builder_->Return(position, /*omit_result_type_check=*/false,
                                     yield_index);
}

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(
    const Function& target) {
  return flow_graph_builder_->ThrowNoSuchMethodError(target);
}

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(const Field& field,
                                                    bool calls_initializer) {
  return flow_graph_builder_->LoadStaticField(field, calls_initializer);
}

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

Fragment StreamingFlowGraphBuilder::CheckNull(
    TokenPosition position,
    LocalVariable* receiver,
    const String& function_name,
    bool clear_the_temp /* = true */) {
  return flow_graph_builder_->CheckNull(position, receiver, function_name,
                                        clear_the_temp);
}

Fragment StreamingFlowGraphBuilder::StaticCall(TokenPosition position,
                                               const Function& target,
                                               intptr_t argument_count,
                                               ICData::RebindRule rebind_rule) {
  if (!target.AreValidArgumentCounts(0, argument_count, 0, nullptr)) {
    return flow_graph_builder_->ThrowNoSuchMethodError(target);
  }
  return flow_graph_builder_->StaticCall(position, target, argument_count,
                                         rebind_rule);
}

Fragment StreamingFlowGraphBuilder::StaticCall(
    TokenPosition position,
    const Function& target,
    intptr_t argument_count,
    const Array& argument_names,
    ICData::RebindRule rebind_rule,
    const InferredTypeMetadata* result_type,
    intptr_t type_args_count,
    bool use_unchecked_entry) {
  if (!target.AreValidArguments(type_args_count, argument_count, argument_names,
                                nullptr)) {
    return flow_graph_builder_->ThrowNoSuchMethodError(target);
  }
  return flow_graph_builder_->StaticCall(
      position, target, argument_count, argument_names, rebind_rule,
      result_type, type_args_count, use_unchecked_entry);
}

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);
}

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,
    const Function& tearoff_interface_target,
    const InferredTypeMetadata* result_type,
    bool use_unchecked_entry,
    const CallSiteAttributesMetadata* call_site_attrs,
    bool receiver_is_not_smi) {
  return flow_graph_builder_->InstanceCall(
      position, name, kind, type_args_len, argument_count, argument_names,
      checked_argument_count, interface_target, tearoff_interface_target,
      result_type, use_unchecked_entry, call_site_attrs, receiver_is_not_smi);
}

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(TokenPosition position,
                                                  Token::Kind kind,
                                                  bool number_check) {
  return flow_graph_builder_->StrictCompare(position, 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::AllocateContext(
    const ZoneGrowableArray<const Slot*>& context_slots) {
  return flow_graph_builder_->AllocateContext(context_slots);
}

Fragment StreamingFlowGraphBuilder::LoadNativeField(const Slot& field) {
  return flow_graph_builder_->LoadNativeField(field);
}

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::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(TokenPosition position) {
  return flow_graph_builder_->CheckStackOverflow(
      position, flow_graph_builder_->GetStackDepth(),
      flow_graph_builder_->loop_depth_);
}

Fragment StreamingFlowGraphBuilder::CloneContext(
    const ZoneGrowableArray<const Slot*>& context_slots) {
  return flow_graph_builder_->CloneContext(context_slots);
}

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_);

  // Save context.
  TryFinallyBlock* const saved_finally_block = B->try_finally_block_;
  TryCatchBlock* const saved_try_catch_block = B->CurrentTryCatchBlock();
  const intptr_t saved_context_depth = B->context_depth_;
  const ProgramState state(B->breakable_block_, B->switch_block_,
                           B->loop_depth_, B->for_in_depth_, B->try_depth_,
                           B->catch_depth_, B->block_expression_depth_);

  Fragment instructions;

  // While translating the body of a finalizer we need to set the try-finally
  // block which is active when translating the body.
  while (B->try_finally_block_ != outer_finally) {
    ASSERT(B->try_finally_block_ != nullptr);
    // Adjust program context to finalizer's position.
    B->try_finally_block_->state().assignTo(B);

    // Potentially restore the context to what is expected for the finally
    // block.
    instructions += B->AdjustContextTo(B->try_finally_block_->context_depth());

    // The to-be-translated finalizer has to have the correct try-index (namely
    // the one outside the try-finally block).
    bool changed_try_index = false;
    intptr_t target_try_index = B->try_finally_block_->try_index();
    while (B->CurrentTryIndex() != target_try_index) {
      B->SetCurrentTryCatchBlock(B->CurrentTryCatchBlock()->outer());
      changed_try_index = true;
    }
    if (changed_try_index) {
      JoinEntryInstr* entry = BuildJoinEntry();
      instructions += Goto(entry);
      instructions = Fragment(instructions.entry, entry);
    }

    intptr_t finalizer_kernel_offset =
        B->try_finally_block_->finalizer_kernel_offset();
    B->try_finally_block_ = B->try_finally_block_->outer();
    instructions += BuildStatementAt(finalizer_kernel_offset);

    // We only need to make sure that if the finalizer ended normally, we
    // continue towards the next outer try-finally.
    if (!instructions.is_open()) break;
  }

  if (instructions.is_open() && target_context_depth != -1) {
    // A target context depth of -1 indicates that the code after this
    // will not care about the context chain so we can leave it any way we
    // want after the last finalizer.  That is used when returning.
    instructions += B->AdjustContextTo(target_context_depth);
  }

  // Restore.
  B->try_finally_block_ = saved_finally_block;
  B->SetCurrentTryCatchBlock(saved_try_catch_block);
  B->context_depth_ = saved_context_depth;
  state.assignTo(B);

  return instructions;
}

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,
                                                    bool is_synthesized) {
  return flow_graph_builder_->CatchBlockEntry(handler_types, handler_index,
                                              needs_stacktrace, is_synthesized);
}

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::DropTempsPreserveTop(
    intptr_t num_temps_to_drop) {
  return flow_graph_builder_->DropTempsPreserveTop(num_temps_to_drop);
}

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

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::CheckBoolean(TokenPosition position) {
  return flow_graph_builder_->CheckBoolean(position);
}

Fragment StreamingFlowGraphBuilder::CheckArgumentType(
    LocalVariable* variable,
    const AbstractType& type) {
  return flow_graph_builder_->CheckAssignable(
      type, variable->name(), AssertAssignableInstr::kParameterCheck);
}

Fragment StreamingFlowGraphBuilder::EnterScope(
    intptr_t kernel_offset,
    const LocalScope** scope /* = nullptr */) {
  return flow_graph_builder_->EnterScope(kernel_offset, scope);
}

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

TestFragment StreamingFlowGraphBuilder::TranslateConditionForControl() {
  // Skip all negations and go directly to the expression.
  bool negate = false;
  while (PeekTag() == kNot) {
    SkipBytes(1);
    negate = !negate;
  }

  TestFragment result;
  if (PeekTag() == kLogicalExpression) {
    // Handle '&&' and '||' operators specially to implement short circuit
    // evaluation.
    SkipBytes(1);  // tag.

    TestFragment left = TranslateConditionForControl();
    LogicalOperator op = static_cast<LogicalOperator>(ReadByte());
    TestFragment right = TranslateConditionForControl();

    result.entry = left.entry;
    if (op == kAnd) {
      left.CreateTrueSuccessor(flow_graph_builder_)->LinkTo(right.entry);
      result.true_successor_addresses = right.true_successor_addresses;
      result.false_successor_addresses = left.false_successor_addresses;
      result.false_successor_addresses->AddArray(
          *right.false_successor_addresses);
    } else {
      ASSERT(op == kOr);
      left.CreateFalseSuccessor(flow_graph_builder_)->LinkTo(right.entry);
      result.true_successor_addresses = left.true_successor_addresses;
      result.true_successor_addresses->AddArray(
          *right.true_successor_addresses);
      result.false_successor_addresses = right.false_successor_addresses;
    }
  } else {
    // Other expressions.
    TokenPosition position = TokenPosition::kNoSource;
    Fragment instructions = BuildExpression(&position);  // read expression.

    // Check if the top of the stack is already a StrictCompare that
    // can be merged with a branch. Otherwise compare TOS with
    // true value and branch on that.
    BranchInstr* branch;
    if (stack()->definition()->IsStrictCompare() &&
        stack()->definition() == instructions.current) {
      StrictCompareInstr* compare = Pop()->definition()->AsStrictCompare();
      if (negate) {
        compare->NegateComparison();
        negate = false;
      }
      branch =
          new (Z) BranchInstr(compare, flow_graph_builder_->GetNextDeoptId());
      branch->comparison()->ClearTempIndex();
      ASSERT(instructions.current->previous() != nullptr);
      instructions.current = instructions.current->previous();
    } else {
      instructions += CheckBoolean(position);
      instructions += Constant(Bool::True());
      Value* right_value = Pop();
      Value* left_value = Pop();
      StrictCompareInstr* compare = new (Z) StrictCompareInstr(
          TokenPosition::kNoSource,
          negate ? Token::kNE_STRICT : Token::kEQ_STRICT, left_value,
          right_value, false, flow_graph_builder_->GetNextDeoptId());
      branch =
          new (Z) BranchInstr(compare, flow_graph_builder_->GetNextDeoptId());
      negate = false;
    }
    instructions <<= branch;

    result = TestFragment(instructions.entry, branch);
  }

  return result.Negate(negate);
}

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,
                                                   intptr_t* positional_count) {
  intptr_t dummy;
  if (argument_count == NULL) argument_count = &dummy;
  *argument_count = ReadUInt();  // read arguments count.

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

  {
    AlternativeReadingScope _(&reader_);
    if (positional_count == NULL) positional_count = &dummy;
    *positional_count = ReadListLength();  // read length of expression list
  }
  return BuildArgumentsFromActualArguments(argument_names);
}

Fragment StreamingFlowGraphBuilder::BuildArgumentsFromActualArguments(
    Array* argument_names) {
  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.
  }

  // 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.DartSymbolObfuscate(ReadStringReference());  // read ith name index.
    instructions += BuildExpression();                 // read ith expression.
    if (argument_names != NULL) {
      argument_names->SetAt(i, name);
    }
  }

  return instructions;
}

Fragment StreamingFlowGraphBuilder::BuildInvalidExpression(
    TokenPosition* position) {
  // 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).
  TokenPosition pos = ReadPosition();
  if (position != NULL) *position = pos;
  const String& message = H.DartString(ReadStringReference());
  // Invalid expression message has pointer to the source code, no need to
  // report it twice.
  H.ReportError(script(), TokenPosition::kNoSource, "%s", message.ToCString());
  return Fragment();
}

Fragment StreamingFlowGraphBuilder::BuildVariableGet(TokenPosition* position) {
  const TokenPosition pos = ReadPosition();
  if (position != nullptr) *position = pos;
  intptr_t variable_kernel_position = ReadUInt();  // read kernel position.
  ReadUInt();              // read relative variable index.
  SkipOptionalDartType();  // read promoted type.
  return BuildVariableGetImpl(variable_kernel_position, pos);
}

Fragment StreamingFlowGraphBuilder::BuildVariableGet(uint8_t payload,
                                                     TokenPosition* position) {
  const TokenPosition pos = ReadPosition();
  if (position != nullptr) *position = pos;
  intptr_t variable_kernel_position = ReadUInt();  // read kernel position.
  return BuildVariableGetImpl(variable_kernel_position, pos);
}

Fragment StreamingFlowGraphBuilder::BuildVariableGetImpl(
    intptr_t variable_kernel_position,
    TokenPosition position) {
  LocalVariable* variable = LookupVariable(variable_kernel_position);
  if (!variable->is_late()) {
    return LoadLocal(variable);
  }

  // Late variable, so check whether it has been initialized already.
  Fragment instructions = LoadLocal(variable);
  TargetEntryInstr *is_uninitialized, *is_initialized;
  instructions += Constant(Object::sentinel());
  instructions += flow_graph_builder_->BranchIfStrictEqual(&is_uninitialized,
                                                           &is_initialized);
  JoinEntryInstr* join = BuildJoinEntry();

  {
    AlternativeReadingScope alt(&reader_, variable->late_init_offset());
    const bool has_initializer = (ReadTag() != kNothing);

    if (has_initializer) {
      // If the variable isn't initialized, call the initializer and set it.
      Fragment initialize(is_uninitialized);
      initialize += BuildExpression();
      initialize += StoreLocal(position, variable);
      initialize += Drop();
      initialize += Goto(join);
    } else {
      // The variable has no initializer, so throw a LateInitializationError.
      Fragment initialize(is_uninitialized);
      initialize += flow_graph_builder_->ThrowLateInitializationError(
          position, variable->name());
      initialize += Goto(join);
    }
  }

  {
    // Already initialized, so there's nothing to do.
    Fragment already_initialized(is_initialized);
    already_initialized += Goto(join);
  }

  Fragment done = Fragment(instructions.entry, join);
  done += LoadLocal(variable);
  return done;
}

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.
  return BuildVariableSetImpl(position, variable_kernel_position);
}

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.
  return BuildVariableSetImpl(position, variable_kernel_position);
}

Fragment StreamingFlowGraphBuilder::BuildVariableSetImpl(
    TokenPosition position,
    intptr_t variable_kernel_position) {
  Fragment instructions = BuildExpression();  // read expression.
  if (NeedsDebugStepCheck(stack(), position)) {
    instructions = DebugStepCheck(position) + instructions;
  }

  LocalVariable* variable = LookupVariable(variable_kernel_position);
  if (variable->is_late() && variable->is_final()) {
    // Late final variable, so check whether it has been initialized.
    LocalVariable* expr_temp = MakeTemporary();
    instructions += LoadLocal(variable);
    TargetEntryInstr *is_uninitialized, *is_initialized;
    instructions += Constant(Object::sentinel());
    instructions += flow_graph_builder_->BranchIfStrictEqual(&is_uninitialized,
                                                             &is_initialized);
    JoinEntryInstr* join = BuildJoinEntry();

    {
      // The variable is uninitialized, so store the expression value.
      Fragment initialize(is_uninitialized);
      initialize += LoadLocal(expr_temp);
      initialize += StoreLocal(position, variable);
      initialize += Drop();
      initialize += Goto(join);
    }

    {
      // Already initialized, so throw a LateInitializationError.
      Fragment already_initialized(is_initialized);
      already_initialized += flow_graph_builder_->ThrowLateInitializationError(
          position, variable->name());
      already_initialized += Goto(join);
    }

    instructions = Fragment(instructions.entry, join);
  } else {
    instructions += StoreLocal(position, variable);
  }

  return instructions;
}

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

  const DirectCallMetadata direct_call =
      direct_call_metadata_helper_.GetDirectTargetForPropertyGet(offset);
  const InferredTypeMetadata result_type =
      inferred_type_metadata_helper_.GetInferredType(offset);

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

  LocalVariable* receiver = NULL;
  if (direct_call.check_receiver_for_null_) {
    // Duplicate receiver for CheckNull before it is consumed by PushArgument.
    receiver = MakeTemporary();
    instructions += LoadLocal(receiver);
  }

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

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

  if (direct_call.check_receiver_for_null_) {
    instructions += CheckNull(position, receiver, getter_name);
  }

  const String* mangled_name = &getter_name;
  const Function* direct_call_target = &direct_call.target_;
  if (H.IsRoot(itarget_name)) {
    mangled_name = &String::ZoneHandle(
        Z, Function::CreateDynamicInvocationForwarderName(getter_name));
    if (!direct_call_target->IsNull()) {
      direct_call_target = &Function::ZoneHandle(
          direct_call.target_.GetDynamicInvocationForwarder(*mangled_name));
    }
  }

  if (!direct_call_target->IsNull()) {
    ASSERT(CompilerState::Current().is_aot());
    instructions +=
        StaticCall(position, *direct_call_target, 1, Array::null_array(),
                   ICData::kNoRebind, &result_type);
  } else {
    const intptr_t kTypeArgsLen = 0;
    const intptr_t kNumArgsChecked = 1;
    instructions +=
        InstanceCall(position, *mangled_name, Token::kGET, kTypeArgsLen, 1,
                     Array::null_array(), kNumArgsChecked, *interface_target,
                     *tearoff_interface_target, &result_type);
  }

  if (direct_call.check_receiver_for_null_) {
    instructions += DropTempsPreserveTop(1);  // Drop receiver, preserve result.
  }

  return instructions;
}

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

  const DirectCallMetadata direct_call =
      direct_call_metadata_helper_.GetDirectTargetForPropertySet(offset);
  const CallSiteAttributesMetadata call_site_attributes =
      call_site_attributes_metadata_helper_.GetCallSiteAttributes(offset);
  const InferredTypeMetadata inferred_type =
      inferred_type_metadata_helper_.GetInferredType(offset);

  // True if callee can skip argument type checks.
  bool is_unchecked_call = inferred_type.IsSkipCheck();
  if (call_site_attributes.receiver_type != nullptr &&
      call_site_attributes.receiver_type->HasTypeClass() &&
      !Class::Handle(call_site_attributes.receiver_type->type_class())
           .IsGeneric()) {
    is_unchecked_call = true;
  }

  Fragment instructions(MakeTemp());
  LocalVariable* variable = MakeTemporary();

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

  if (PeekTag() == kThisExpression) {
    is_unchecked_call = true;
  }
  instructions += BuildExpression();  // read receiver.

  LocalVariable* receiver = nullptr;
  if (direct_call.check_receiver_for_null_) {
    // Duplicate receiver for CheckNull before it is consumed by PushArgument.
    receiver = MakeTemporary();
    instructions += LoadLocal(receiver);
  }

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

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

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

  if (direct_call.check_receiver_for_null_) {
    instructions += CheckNull(position, receiver, setter_name);
  }

  const String* mangled_name = &setter_name;
  const Function* direct_call_target = &direct_call.target_;
  if (H.IsRoot(itarget_name)) {
    mangled_name = &String::ZoneHandle(
        Z, Function::CreateDynamicInvocationForwarderName(setter_name));
    if (!direct_call_target->IsNull()) {
      direct_call_target = &Function::ZoneHandle(
          direct_call.target_.GetDynamicInvocationForwarder(*mangled_name));
    }
  }

  if (!direct_call_target->IsNull()) {
    ASSERT(CompilerState::Current().is_aot());
    instructions +=
        StaticCall(position, *direct_call_target, 2, Array::null_array(),
                   ICData::kNoRebind, /*result_type=*/nullptr,
                   /*type_args_count=*/0,
                   /*use_unchecked_entry=*/is_unchecked_call);
  } else {
    const intptr_t kTypeArgsLen = 0;
    const intptr_t kNumArgsChecked = 1;

    instructions += InstanceCall(
        position, *mangled_name, Token::kSET, kTypeArgsLen, 2,
        Array::null_array(), kNumArgsChecked, *interface_target,
        Function::null_function(),
        /*result_type=*/nullptr,
        /*use_unchecked_entry=*/is_unchecked_call, &call_site_attributes);
  }

  instructions += Drop();  // Drop result of the setter invocation.

  if (direct_call.check_receiver_for_null_) {
    instructions += Drop();  // Drop receiver.
  }

  return instructions;
}

static Function& GetNoSuchMethodOrDie(Thread* thread,
                                      Zone* zone,
                                      const Class& klass) {
  Function& nsm_function = Function::Handle(zone);
  Class& iterate_klass = Class::Handle(zone, klass.raw());
  while (!iterate_klass.IsNull()) {
    if (iterate_klass.EnsureIsFinalized(thread) == Error::null()) {
      nsm_function =
          iterate_klass.LookupDynamicFunction(Symbols::NoSuchMethod());
    }
    if (!nsm_function.IsNull() && nsm_function.NumParameters() == 2 &&
        nsm_function.NumTypeParameters() == 0) {
      break;
    }
    iterate_klass = iterate_klass.SuperClass();
  }
  // We are guaranteed to find noSuchMethod of class Object.
  ASSERT(!nsm_function.IsNull());

  return nsm_function;
}

// Note, that this will always mark `super` flag to true.
Fragment StreamingFlowGraphBuilder::BuildAllocateInvocationMirrorCall(
    TokenPosition position,
    const String& name,
    intptr_t num_type_arguments,
    intptr_t num_arguments,
    const Array& argument_names,
    LocalVariable* actuals_array,
    Fragment build_rest_of_actuals) {
  Fragment instructions;

  // Populate array containing the actual arguments. Just add [this] here.
  instructions += LoadLocal(actuals_array);                      // array
  instructions += IntConstant(num_type_arguments == 0 ? 0 : 1);  // index
  instructions += LoadLocal(parsed_function()->receiver_var());  // receiver
  instructions += StoreIndexed(kArrayCid);
  instructions += build_rest_of_actuals;

  // First argument is receiver.
  instructions += LoadLocal(parsed_function()->receiver_var());

  // Push the arguments for allocating the invocation mirror:
  //   - the name.
  instructions += Constant(String::ZoneHandle(Z, name.raw()));

  //   - the arguments descriptor.
  const Array& args_descriptor =
      Array::Handle(Z, ArgumentsDescriptor::NewBoxed(
                           num_type_arguments, num_arguments, argument_names));
  instructions += Constant(Array::ZoneHandle(Z, args_descriptor.raw()));

  //   - an array containing the actual arguments.
  instructions += LoadLocal(actuals_array);

  //   - [true] indicating this is a `super` NoSuchMethod.
  instructions += Constant(Bool::True());

  const Class& mirror_class =
      Class::Handle(Z, Library::LookupCoreClass(Symbols::InvocationMirror()));
  ASSERT(!mirror_class.IsNull());
  const auto& error = mirror_class.EnsureIsFinalized(thread());
  ASSERT(error == Error::null());
  const Function& allocation_function = Function::ZoneHandle(
      Z, mirror_class.LookupStaticFunction(
             Library::PrivateCoreLibName(Symbols::AllocateInvocationMirror())));
  ASSERT(!allocation_function.IsNull());
  instructions += StaticCall(position, allocation_function,
                             /* argument_count = */ 4, ICData::kStatic);
  return instructions;
}

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

  const InferredTypeMetadata result_type =
      inferred_type_metadata_helper_.GetInferredType(offset);

  Class& klass = GetSuperOrDie();

  StringIndex name_index = ReadStringReference();  // read name index.
  NameIndex library_reference =
      ((H.StringSize(name_index) >= 1) && H.CharacterAt(name_index, 0) == '_')
          ? ReadCanonicalNameReference()  // read library index.
          : NameIndex();
  const String& getter_name = H.DartGetterName(library_reference, name_index);
  const String& method_name = H.DartMethodName(library_reference, name_index);

  SkipInterfaceMemberNameReference();  // skip target_reference.

  // Search the superclass chain for the selector looking for either getter or
  // method.
  Function& function = Function::Handle(Z);
  while (!klass.IsNull()) {
    if (klass.EnsureIsFinalized(thread()) == Error::null()) {
      function = klass.LookupDynamicFunction(method_name);
      if (!function.IsNull()) {
        Function& target =
            Function::ZoneHandle(Z, function.ImplicitClosureFunction());
        ASSERT(!target.IsNull());
        // Generate inline code for allocation closure object with context
        // which captures `this`.
        return BuildImplicitClosureCreation(target);
      }
      function = klass.LookupDynamicFunction(getter_name);
      if (!function.IsNull()) break;
    }
    klass = klass.SuperClass();
  }

  Fragment instructions;
  if (klass.IsNull()) {
    instructions +=
        Constant(TypeArguments::ZoneHandle(Z, TypeArguments::null()));
    instructions += IntConstant(1);  // array size
    instructions += CreateArray();
    LocalVariable* actuals_array = MakeTemporary();

    Class& parent_klass = GetSuperOrDie();

    instructions += BuildAllocateInvocationMirrorCall(
        position, getter_name,
        /* num_type_arguments = */ 0,
        /* num_arguments = */ 1,
        /* argument_names = */ Object::empty_array(), actuals_array,
        /* build_rest_of_actuals = */ Fragment());

    Function& nsm_function = GetNoSuchMethodOrDie(thread(), Z, parent_klass);
    instructions +=
        StaticCall(position, Function::ZoneHandle(Z, nsm_function.raw()),
                   /* argument_count = */ 2, ICData::kNSMDispatch);
    instructions += DropTempsPreserveTop(1);  // Drop array
  } else {
    ASSERT(!klass.IsNull());
    ASSERT(!function.IsNull());

    instructions += LoadLocal(parsed_function()->receiver_var());

    instructions +=
        StaticCall(position, Function::ZoneHandle(Z, function.raw()),
                   /* argument_count = */ 1, Array::null_array(),
                   ICData::kSuper, &result_type);
  }

  return instructions;
}

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

  Class& klass = GetSuperOrDie();

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

  Function& function = Function::Handle(Z);
  if (klass.EnsureIsFinalized(thread()) == Error::null()) {
    function = H.LookupDynamicFunction(klass, setter_name);
  }

  Fragment instructions(MakeTemp());
  LocalVariable* value = MakeTemporary();  // this holds RHS value

  if (function.IsNull()) {
    instructions +=
        Constant(TypeArguments::ZoneHandle(Z, TypeArguments::null()));
    instructions += IntConstant(2);  // array size
    instructions += CreateArray();
    LocalVariable* actuals_array = MakeTemporary();

    Fragment build_rest_of_actuals;
    build_rest_of_actuals += LoadLocal(actuals_array);  // array
    build_rest_of_actuals += IntConstant(1);            // index
    build_rest_of_actuals += BuildExpression();         // value.
    build_rest_of_actuals += StoreLocal(position, value);
    build_rest_of_actuals += StoreIndexed(kArrayCid);

    instructions += BuildAllocateInvocationMirrorCall(
        position, setter_name, /* num_type_arguments = */ 0,
        /* num_arguments = */ 2,
        /* argument_names = */ Object::empty_array(), actuals_array,
        build_rest_of_actuals);

    SkipInterfaceMemberNameReference();  // skip target_reference.

    Function& nsm_function = GetNoSuchMethodOrDie(thread(), Z, klass);
    instructions +=
        StaticCall(position, Function::ZoneHandle(Z, nsm_function.raw()),
                   /* argument_count = */ 2, ICData::kNSMDispatch);
    instructions += Drop();  // Drop result of NoSuchMethod invocation
    instructions += Drop();  // Drop array
  } else {
    // receiver
    instructions += LoadLocal(parsed_function()->receiver_var());

    instructions += BuildExpression();  // read value.
    instructions += StoreLocal(position, value);

    SkipInterfaceMemberNameReference();  // skip target_reference.

    instructions += StaticCall(
        position, Function::ZoneHandle(Z, function.raw()),
        /* argument_count = */ 2, Array::null_array(), ICData::kSuper,
        /*result_type=*/nullptr, /*type_args_len=*/0,
        /*use_unchecked_entry=*/true);
    instructions += Drop();  // Drop result of the setter invocation.
  }

  return instructions;
}

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

  const InferredTypeMetadata result_type =
      inferred_type_metadata_helper_.GetInferredType(offset);

  const Tag receiver_tag = PeekTag();         // peek tag for receiver.
  Fragment instructions = BuildExpression();  // read receiver.
  const NameIndex kernel_name =
      ReadInterfaceMemberNameReference();  // read target_reference.

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

      target =
          H.LookupMethodByMember(kernel_name, H.DartMethodName(kernel_name));
      target = target.ImplicitClosureFunction();
      ASSERT(!target.IsNull());

      // Generate inline code for allocating closure object with context which
      // captures `this`.
      return BuildImplicitClosureCreation(target);
    } else {
      // Need to create implicit closure (tear-off), receiver != this.
      // Ensure method extractor exists and call it directly.
      const Function& target_method = Function::ZoneHandle(
          Z,
          H.LookupMethodByMember(kernel_name, H.DartMethodName(kernel_name)));
      const String& getter_name = H.DartGetterName(kernel_name);
      target = target_method.GetMethodExtractor(getter_name);
    }
  } else {
    ASSERT(H.IsField(kernel_name));
    const String& getter_name = H.DartGetterName(kernel_name);
    target = H.LookupMethodByMember(kernel_name, getter_name);
    ASSERT(target.IsGetterFunction() || target.IsImplicitGetterFunction());
  }

  // Static calls are marked as "no-rebind", which is currently safe because
  // DirectPropertyGet are only used in enums (index in toString) and enums
  // can't change their structure during hot reload.
  // If there are other sources of DirectPropertyGet in the future, this code
  // have to be adjusted.
  return instructions + StaticCall(position, target, 1, Array::null_array(),
                                   ICData::kNoRebind, &result_type);
}

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

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

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

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

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

  // Static calls are marked as "no-rebind", which is currently safe because
  // DirectPropertyGet are only used in enums (index in toString) and enums
  // can't change their structure during hot reload.
  // If there are other sources of DirectPropertyGet in the future, this code
  // have to be adjusted.
  instructions +=
      StaticCall(position, target, 2, Array::null_array(), ICData::kNoRebind,
                 /* result_type = */ NULL);

  return instructions + Drop();
}

Fragment StreamingFlowGraphBuilder::BuildStaticGet(TokenPosition* p) {
  ASSERT(Error::Handle(Z, H.thread()->sticky_error()).IsNull());
  const intptr_t offset = ReaderOffset() - 1;  // Include the tag.

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

  const InferredTypeMetadata result_type =
      inferred_type_metadata_helper_.GetInferredType(offset);

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

  if (H.IsField(target)) {
    const Field& field =
        Field::ZoneHandle(Z, H.LookupFieldByKernelField(target));
    if (field.is_const()) {
      // Since the CFE inlines all references to const variables and fields,
      // it never emits a StaticGet of a const field.
      // This situation only arises because of the static const fields in
      // the ClassID class, which are generated internally in the VM
      // during loading. See also Class::InjectCIDFields.
      ASSERT(Class::Handle(field.Owner()).library() ==
                 Library::InternalLibrary() &&
             Class::Handle(field.Owner()).Name() == Symbols::ClassID().raw());
      return Constant(Instance::ZoneHandle(Z, field.StaticValue()));
    } 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.NeedsGetter()) {
        return StaticCall(position, getter, 0, Array::null_array(),
                          ICData::kStatic, &result_type);
      } else {
        if (result_type.IsConstant()) {
          return Constant(result_type.constant_value);
        }
        return LoadStaticField(field, /*calls_initializer=*/false);
      }
    }
  } else {
    const Function& function =
        Function::ZoneHandle(Z, H.LookupStaticMethodByKernelProcedure(target));

    if (H.IsGetter(target)) {
      return StaticCall(position, function, 0, Array::null_array(),
                        ICData::kStatic, &result_type);
    } else if (H.IsMethod(target)) {
      const auto& closure_function =
          Function::Handle(Z, function.ImplicitClosureFunction());
      const auto& static_closure =
          Instance::Handle(Z, closure_function.ImplicitStaticClosure());
      return Constant(Instance::ZoneHandle(Z, H.Canonicalize(static_closure)));
    } 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 Class& owner = Class::Handle(Z, field.Owner());
    const String& setter_name = H.DartSetterName(target);
    const Function& setter =
        Function::ZoneHandle(Z, owner.LookupStaticFunction(setter_name));
    Fragment instructions = BuildExpression();  // read expression.
    if (NeedsDebugStepCheck(stack(), position)) {
      instructions = DebugStepCheck(position) + instructions;
    }
    LocalVariable* variable = MakeTemporary();
    instructions += LoadLocal(variable);
    if (!setter.IsNull() && field.NeedsSetter()) {
      instructions += StaticCall(position, setter, 1, ICData::kStatic);
      instructions += Drop();
    } else {
      instructions += StoreStaticField(position, field);
    }
    return instructions;
  } 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);

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

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

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

  const DirectCallMetadata direct_call =
      direct_call_metadata_helper_.GetDirectTargetForMethodInvocation(offset);
  const InferredTypeMetadata result_type =
      inferred_type_metadata_helper_.GetInferredType(offset);
  const CallSiteAttributesMetadata call_site_attributes =
      call_site_attributes_metadata_helper_.GetCallSiteAttributes(offset);

  const Tag receiver_tag = PeekTag();  // peek tag for receiver.

  bool is_unchecked_closure_call = false;
  bool is_unchecked_call = result_type.IsSkipCheck();
  if (call_site_attributes.receiver_type != nullptr) {
    if (call_site_attributes.receiver_type->IsFunctionType()) {
      AlternativeReadingScope alt(&reader_);
      SkipExpression();  // skip receiver
      is_unchecked_closure_call =
          ReadNameAsMethodName().Equals(Symbols::Call());
    } else if (call_site_attributes.receiver_type->HasTypeClass() &&
               !call_site_attributes.receiver_type->IsDynamicType() &&
               !Class::Handle(call_site_attributes.receiver_type->type_class())
                    .IsGeneric()) {
      is_unchecked_call = true;
    }
  }

  Fragment instructions;

  intptr_t type_args_len = 0;
  LocalVariable* type_arguments_temp = NULL;
  {
    AlternativeReadingScope alt(&reader_);
    SkipExpression();                         // skip receiver
    SkipName();                               // skip method name
    ReadUInt();                               // read argument count.
    intptr_t list_length = ReadListLength();  // read types list length.
    if (list_length > 0) {
      const TypeArguments& type_arguments =
          T.BuildTypeArguments(list_length);  // read types.
      instructions += TranslateInstantiatedTypeArguments(type_arguments);
      if (direct_call.check_receiver_for_null_ || is_unchecked_closure_call) {
        // Don't yet push type arguments if we need to check receiver for null.
        // In this case receiver will be duplicated so instead of pushing
        // type arguments here we need to push it between receiver_temp
        // and actual receiver. See the code below.
        type_arguments_temp = MakeTemporary();
      }
    }
    type_args_len = list_length;
  }

  // Take note of whether the invocation is against the receiver of the current
  // function: in this case, we may skip some type checks in the callee.
  if (PeekTag() == kThisExpression) {
    is_unchecked_call = true;
  }
  instructions += BuildExpression();  // read receiver.

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

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

  LocalVariable* receiver_temp = NULL;
  if (direct_call.check_receiver_for_null_ || is_unchecked_closure_call) {
    // Duplicate receiver for CheckNull before it is consumed by PushArgument.
    receiver_temp = MakeTemporary();
    if (type_arguments_temp != NULL) {
      // If call has type arguments then push them before pushing the receiver.
      // The stack will contain:
      //
      //   [type_arguments_temp][receiver_temp][type_arguments][receiver] ...
      //
      instructions += LoadLocal(type_arguments_temp);
    }
    instructions += LoadLocal(receiver_temp);
  }

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

  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();
  const NameIndex itarget_name =
      ReadInterfaceMemberNameReference();  // read interface_target_reference.
  // TODO(dartbug.com/34497): Once front-end desugars calls via
  // fields/getters, filtering of field and getter interface targets here
  // can be turned into assertions.
  if (!H.IsRoot(itarget_name) && !H.IsField(itarget_name) &&
      !H.IsGetter(itarget_name)) {
    interface_target = &Function::ZoneHandle(
        Z, H.LookupMethodByMember(itarget_name,
                                  H.DartProcedureName(itarget_name)));
    ASSERT(name.raw() == interface_target->name());
    ASSERT(!interface_target->IsGetterFunction());
  }

  // TODO(sjindel): Avoid the check for null on unchecked closure calls if TFA
  // allows.
  if (direct_call.check_receiver_for_null_ || is_unchecked_closure_call) {
    // Receiver temp is needed to load the function to call from the closure.
    instructions += CheckNull(position, receiver_temp, name,
                              /*clear_temp=*/!is_unchecked_closure_call);
  }

  const String* mangled_name = &name;
  // Do not mangle ==:
  //   * operator == takes an Object so its either not checked or checked
  //     at the entry because the parameter is marked covariant, neither of
  //     those cases require a dynamic invocation forwarder.
  const Function* direct_call_target = &direct_call.target_;
  if (H.IsRoot(itarget_name) &&
      (name.raw() != Symbols::EqualOperator().raw())) {
    mangled_name = &String::ZoneHandle(
        Z, Function::CreateDynamicInvocationForwarderName(name));
    if (!direct_call_target->IsNull()) {
      direct_call_target = &Function::ZoneHandle(
          direct_call_target->GetDynamicInvocationForwarder(*mangled_name));
    }
  }

  if (is_unchecked_closure_call) {
    // Lookup the function in the closure.
    instructions += LoadLocal(receiver_temp);
    instructions += LoadNativeField(Slot::Closure_function());
    if (parsed_function()->function().is_debuggable()) {
      ASSERT(!parsed_function()->function().is_native());
      instructions += DebugStepCheck(position);
    }
    instructions +=
        B->ClosureCall(position, type_args_len, argument_count, argument_names,
                       /*use_unchecked_entry=*/true);
  } else if (!direct_call_target->IsNull()) {
    // Even if TFA infers a concrete receiver type, the static type of the
    // call-site may still be dynamic and we need to call the dynamic invocation
    // forwarder to ensure type-checks are performed.
    ASSERT(CompilerState::Current().is_aot());
    instructions +=
        StaticCall(position, *direct_call_target, argument_count,
                   argument_names, ICData::kNoRebind, &result_type,
                   type_args_len, /*use_unchecked_entry=*/is_unchecked_call);
  } else {
    instructions +=
        InstanceCall(position, *mangled_name, token_kind, type_args_len,
                     argument_count, argument_names, checked_argument_count,
                     *interface_target, Function::null_function(), &result_type,
                     /*use_unchecked_entry=*/is_unchecked_call,
                     &call_site_attributes, result_type.ReceiverNotInt());
  }

  // Drop temporaries preserving result on the top of the stack.
  ASSERT((receiver_temp != NULL) || (type_arguments_temp == NULL));
  if (receiver_temp != NULL) {
    const intptr_t num_temps =
        (receiver_temp != NULL ? 1 : 0) + (type_arguments_temp != NULL ? 1 : 0);
    instructions += DropTempsPreserveTop(num_temps);
  }

  // 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* p) {
  const intptr_t offset = ReaderOffset() - 1;  // Include the tag.
  TokenPosition position = ReadPosition();     // read offset.
  if (p != NULL) *p = position;

  const InferredTypeMetadata result_type =
      inferred_type_metadata_helper_.GetInferredType(offset);

  Tag receiver_tag = PeekTag();  // peek tag for receiver.

  Fragment instructions;
  intptr_t type_args_len = 0;
  {
    AlternativeReadingScope alt(&reader_);
    SkipExpression();                         // skip receiver
    ReadInterfaceMemberNameReference();       // skip target reference
    ReadUInt();                               // read argument count.
    intptr_t list_length = ReadListLength();  // read types list length.
    if (list_length > 0) {
      const TypeArguments& type_arguments =
          T.BuildTypeArguments(list_length);  // read types.
      instructions += TranslateInstantiatedTypeArguments(type_arguments);
    }
    type_args_len = list_length;
  }

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

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

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

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

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

  return instructions + StaticCall(position, target, argument_count,
                                   argument_names, ICData::kNoRebind,
                                   &result_type, type_args_len);
}

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

  const InferredTypeMetadata result_type =
      inferred_type_metadata_helper_.GetInferredType(offset);

  intptr_t type_args_len = 0;
  {
    AlternativeReadingScope alt(&reader_);
    SkipName();                        // skip method name
    ReadUInt();                        // read argument count.
    type_args_len = ReadListLength();  // read types list length.
  }

  Class& klass = GetSuperOrDie();

  // Search the superclass chain for the selector.
  const String& method_name = ReadNameAsMethodName();  // read name.

  // Figure out selector signature.
  intptr_t argument_count;
  Array& argument_names = Array::Handle(Z);
  {
    AlternativeReadingScope alt(&reader_);
    argument_count = ReadUInt();
    SkipListOfDartTypes();

    SkipListOfExpressions();
    intptr_t named_list_length = ReadListLength();
    argument_names = Array::New(named_list_length, H.allocation_space());
    for (intptr_t i = 0; i < named_list_length; i++) {
      const String& arg_name = H.DartSymbolObfuscate(ReadStringReference());
      argument_names.SetAt(i, arg_name);
      SkipExpression();
    }
  }

  Function& function = FindMatchingFunction(
      klass, method_name, type_args_len,
      argument_count + 1 /* account for 'this' */, argument_names);

  if (function.IsNull()) {
    ReadUInt();  // argument count
    intptr_t type_list_length = ReadListLength();

    Fragment instructions;
    instructions +=
        Constant(TypeArguments::ZoneHandle(Z, TypeArguments::null()));
    instructions += IntConstant(argument_count + 1 /* this */ +
                                (type_list_length == 0 ? 0 : 1));  // array size
    instructions += CreateArray();
    LocalVariable* actuals_array = MakeTemporary();

    // Call allocationInvocationMirror to get instance of Invocation.
    Fragment build_rest_of_actuals;
    intptr_t actuals_array_index = 0;
    if (type_list_length > 0) {
      const TypeArguments& type_arguments =
          T.BuildTypeArguments(type_list_length);
      build_rest_of_actuals += LoadLocal(actuals_array);
      build_rest_of_actuals += IntConstant(actuals_array_index);
      build_rest_of_actuals +=
          TranslateInstantiatedTypeArguments(type_arguments);
      build_rest_of_actuals += StoreIndexed(kArrayCid);
      ++actuals_array_index;
    }

    ++actuals_array_index;  // account for 'this'.
    // Read arguments
    intptr_t list_length = ReadListLength();
    intptr_t i = 0;
    while (i < list_length) {
      build_rest_of_actuals += LoadLocal(actuals_array);              // array
      build_rest_of_actuals += IntConstant(actuals_array_index + i);  // index
      build_rest_of_actuals += BuildExpression();                     // value.
      build_rest_of_actuals += StoreIndexed(kArrayCid);
      ++i;
    }
    // Read named arguments
    intptr_t named_list_length = ReadListLength();
    if (named_list_length > 0) {
      ASSERT(argument_count == list_length + named_list_length);
      while ((i - list_length) < named_list_length) {
        SkipStringReference();
        build_rest_of_actuals += LoadLocal(actuals_array);              // array
        build_rest_of_actuals += IntConstant(i + actuals_array_index);  // index
        build_rest_of_actuals += BuildExpression();  // value.
        build_rest_of_actuals += StoreIndexed(kArrayCid);
        ++i;
      }
    }
    instructions += BuildAllocateInvocationMirrorCall(
        position, method_name, type_list_length,
        /* num_arguments = */ argument_count + 1, argument_names, actuals_array,
        build_rest_of_actuals);

    SkipInterfaceMemberNameReference();  //  skip target_reference.

    Function& nsm_function = GetNoSuchMethodOrDie(thread(), Z, klass);
    instructions += StaticCall(TokenPosition::kNoSource,
                               Function::ZoneHandle(Z, nsm_function.raw()),
                               /* argument_count = */ 2, ICData::kNSMDispatch);
    instructions += DropTempsPreserveTop(1);  // Drop actuals_array temp.
    return instructions;
  } else {
    Fragment instructions;

    {
      AlternativeReadingScope alt(&reader_);
      ReadUInt();                               // read argument count.
      intptr_t list_length = ReadListLength();  // read types list length.
      if (list_length > 0) {
        const TypeArguments& type_arguments =
            T.BuildTypeArguments(list_length);  // read types.
        instructions += TranslateInstantiatedTypeArguments(type_arguments);
      }
    }

    // receiver
    instructions += LoadLocal(parsed_function()->receiver_var());

    Array& argument_names = Array::ZoneHandle(Z);
    intptr_t argument_count;
    instructions += BuildArguments(
        &argument_names, &argument_count,
        /* positional_argument_count = */ NULL);  // read arguments.
    ++argument_count;                             // include receiver
    SkipInterfaceMemberNameReference();           // interfaceTargetReference
    return instructions +
           StaticCall(position, Function::ZoneHandle(Z, function.raw()),
                      argument_count, argument_names, ICData::kSuper,
                      &result_type, type_args_len,
                      /*use_unchecked_entry_point=*/true);
  }
}

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

  const InferredTypeMetadata result_type =
      inferred_type_metadata_helper_.GetInferredType(offset);

  NameIndex procedure_reference =
      ReadCanonicalNameReference();  // read procedure reference.
  intptr_t argument_count = PeekArgumentsCount();
  const Function& target = Function::ZoneHandle(
      Z, H.LookupStaticMethodByKernelProcedure(procedure_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;
  }

  const auto recognized_kind = target.recognized_kind();
  if (recognized_kind == MethodRecognizer::kFfiAsFunctionInternal) {
    return BuildFfiAsFunctionInternal();
  } else if (CompilerState::Current().is_aot() &&
             recognized_kind == MethodRecognizer::kFfiNativeCallbackFunction) {
    return BuildFfiNativeCallbackFunction();
  }

  Fragment instructions;
  LocalVariable* instance_variable = NULL;

  const bool special_case_nop_async_stack_trace_helper =
      !FLAG_causal_async_stacks &&
      recognized_kind == MethodRecognizer::kAsyncStackTraceHelper;

  const bool special_case_unchecked_cast =
      klass.IsTopLevel() && (klass.library() == Library::InternalLibrary()) &&
      (target.name() == Symbols::UnsafeCast().raw());

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

  const bool special_case = special_case_identical ||
                            special_case_unchecked_cast ||
                            special_case_nop_async_stack_trace_helper;

  // 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.
  intptr_t type_args_len = 0;
  if (target.IsGenerativeConstructor()) {
    if (klass.NumTypeArguments() > 0) {
      const TypeArguments& type_arguments =
          PeekArgumentsInstantiatedType(klass);
      instructions += TranslateInstantiatedTypeArguments(type_arguments);
      instructions += AllocateObject(position, klass, 1);
    } else {
      instructions += AllocateObject(position, klass, 0);
    }

    instance_variable = MakeTemporary();

    instructions += LoadLocal(instance_variable);
  } 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);
  } else if (!special_case) {
    AlternativeReadingScope alt(&reader_);
    ReadUInt();                               // read argument count.
    intptr_t list_length = ReadListLength();  // read types list length.
    if (list_length > 0) {
      const TypeArguments& type_arguments =
          T.BuildTypeArguments(list_length);  // read types.
      instructions += TranslateInstantiatedTypeArguments(type_arguments);
    }
    type_args_len = list_length;
  }

  Array& argument_names = Array::ZoneHandle(Z);
  instructions +=
      BuildArguments(&argument_names, NULL /* arg count */,
                     NULL /* positional arg count */);  // read arguments.
  ASSERT(!special_case ||
         target.AreValidArguments(type_args_len, argument_count, argument_names,
                                  NULL));

  // Special case identical(x, y) call.
  // Note: similar optimization is performed in bytecode flow graph builder -
  // see BytecodeFlowGraphBuilder::BuildDirectCall().
  // TODO(27590) consider moving this into the inliner and force inline it
  // there.
  if (special_case_identical) {
    ASSERT(argument_count == 2);
    instructions +=
        StrictCompare(position, Token::kEQ_STRICT, /*number_check=*/true);
  } else if (special_case_nop_async_stack_trace_helper) {
    ASSERT(argument_count == 1);
    instructions += Drop();
    instructions += NullConstant();
  } else if (special_case_unchecked_cast) {
    // Simply do nothing: the result value is already pushed on the stack.
  } else {
    instructions += StaticCall(position, target, argument_count, argument_names,
                               ICData::kStatic, &result_type, type_args_len);
    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(
    TokenPosition* p) {
  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;

  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);
      TypeArguments& canonicalized_type_arguments =
          TypeArguments::ZoneHandle(Z, type.arguments());
      canonicalized_type_arguments =
          canonicalized_type_arguments.Canonicalize(thread(), nullptr);
      instructions += Constant(canonicalized_type_arguments);
    } else {
      const TypeArguments& type_arguments =
          PeekArgumentsInstantiatedType(klass);
      instructions += TranslateInstantiatedTypeArguments(type_arguments);
    }

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

  instructions += LoadLocal(variable);

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

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

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

  TokenPosition operand_position = TokenPosition::kNoSource;
  Fragment instructions =
      BuildExpression(&operand_position);  // read expression.
  instructions += CheckBoolean(operand_position);
  instructions += BooleanNegate();
  return instructions;
}

Fragment StreamingFlowGraphBuilder::BuildNullCheck(TokenPosition* p) {
  const TokenPosition position = ReadPosition();  // read position.
  if (p != nullptr) *p = position;

  TokenPosition operand_position = TokenPosition::kNoSource;
  Fragment instructions = BuildExpression(&operand_position);
  LocalVariable* expr_temp = MakeTemporary();
  instructions += CheckNull(position, expr_temp, String::null_string(),
                            /* clear_the_temp = */ false);

  return instructions;
}

// Translate the logical expression (lhs && rhs or lhs || rhs) in a context
// where a value is required.
//
// Translation accumulates short-circuit exits from logical
// subexpressions in the side_exits. These exits are expected to store
// true and false into :expr_temp.
//
// The result of evaluating the last
// expression in chain would be stored in :expr_temp directly to avoid
// generating graph like:
//
//     if (v) :expr_temp = true; else :expr_temp = false;
//
// Outer negations are stripped and instead negation is passed down via
// negated parameter.
Fragment StreamingFlowGraphBuilder::TranslateLogicalExpressionForValue(
    bool negated,
    TestFragment* side_exits) {
  TestFragment left = TranslateConditionForControl().Negate(negated);
  LogicalOperator op = static_cast<LogicalOperator>(ReadByte());
  if (negated) {
    op = (op == kAnd) ? kOr : kAnd;
  }

  // Short circuit the control flow after the left hand side condition.
  if (op == kAnd) {
    side_exits->false_successor_addresses->AddArray(
        *left.false_successor_addresses);
  } else {
    side_exits->true_successor_addresses->AddArray(
        *left.true_successor_addresses);
  }

  // Skip negations of the right hand side.
  while (PeekTag() == kNot) {
    SkipBytes(1);
    negated = !negated;
  }

  Fragment right_value(op == kAnd
                           ? left.CreateTrueSuccessor(flow_graph_builder_)
                           : left.CreateFalseSuccessor(flow_graph_builder_));

  if (PeekTag() == kLogicalExpression) {
    SkipBytes(1);
    // Handle nested logical expressions specially to avoid materializing
    // intermediate boolean values.
    right_value += TranslateLogicalExpressionForValue(negated, side_exits);
  } else {
    // Arbitrary expression on the right hand side. Translate it for value.
    TokenPosition position = TokenPosition::kNoSource;
    right_value += BuildExpression(&position);  // read expression.

    // Check if the top of the stack is known to be a non-nullable boolean.
    // Note that in strong mode we know that any value that reaches here
    // is at least a nullable boolean - so there is no need to compare
    // with true like in Dart 1.
    Definition* top = stack()->definition();
    const bool is_bool = top->IsStrictCompare() || top->IsBooleanNegate();
    if (!is_bool) {
      right_value += CheckBoolean(position);
    }
    if (negated) {
      right_value += BooleanNegate();
    }
    right_value += StoreLocal(TokenPosition::kNoSource,
                              parsed_function()->expression_temp_var());
    right_value += Drop();
  }

  return Fragment(left.entry, right_value.current);
}

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

  TestFragment exits;
  exits.true_successor_addresses = new TestFragment::SuccessorAddressArray(2);
  exits.false_successor_addresses = new TestFragment::SuccessorAddressArray(2);

  JoinEntryInstr* join = BuildJoinEntry();
  Fragment instructions =
      TranslateLogicalExpressionForValue(/*negated=*/false, &exits);
  instructions += Goto(join);

  // Generate :expr_temp = true if needed and connect it to true side-exits.
  if (!exits.true_successor_addresses->is_empty()) {
    Fragment constant_fragment(exits.CreateTrueSuccessor(flow_graph_builder_));
    constant_fragment += Constant(Bool::Get(true));
    constant_fragment += StoreLocal(TokenPosition::kNoSource,
                                    parsed_function()->expression_temp_var());
    constant_fragment += Drop();
    constant_fragment += Goto(join);
  }

  // Generate :expr_temp = false if needed and connect it to false side-exits.
  if (!exits.false_successor_addresses->is_empty()) {
    Fragment constant_fragment(exits.CreateFalseSuccessor(flow_graph_builder_));
    constant_fragment += Constant(Bool::Get(false));
    constant_fragment += StoreLocal(TokenPosition::kNoSource,
                                    parsed_function()->expression_temp_var());
    constant_fragment += Drop();
    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;

  TestFragment condition = TranslateConditionForControl();  // read condition.

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

  Fragment otherwise_fragment(
      condition.CreateFalseSuccessor(flow_graph_builder_));
  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(condition.entry, join) +
         LoadLocal(parsed_function()->expression_temp_var());
}

void StreamingFlowGraphBuilder::FlattenStringConcatenation(
    PiecesCollector* collector) {
  const auto length = ReadListLength();
  for (intptr_t i = 0; i < length; ++i) {
    const auto offset = reader_.offset();
    switch (PeekTag()) {
      case kStringLiteral: {
        ReadTag();
        const String& s = H.DartSymbolPlain(ReadStringReference());
        // Skip empty strings.
        if (!s.Equals("")) {
          collector->Add({-1, &s});
        }
        break;
      }
      case kStringConcatenation: {
        // Flatten by hoisting nested expressions up into the outer concat.
        ReadTag();
        ReadPosition();
        FlattenStringConcatenation(collector);
        break;
      }
      default: {
        collector->Add({offset, nullptr});
        SkipExpression();
      }
    }
  }
}

Fragment StreamingFlowGraphBuilder::BuildStringConcatenation(TokenPosition* p) {
  TokenPosition position = ReadPosition();
  if (p != nullptr) {
    *p = position;
  }

  // Collect and flatten all pieces of this and any nested StringConcats.
  // The result is a single sequence of pieces, potentially flattened to
  // a single String.
  // The collector will hold concatenated strings and Reader offsets of
  // non-string pieces.
  PiecesCollector collector(Z, &H);
  FlattenStringConcatenation(&collector);
  collector.FlushRun();

  if (collector.pieces.length() == 1) {
    // No need to Interp. a single string, so return string as a Constant:
    if (collector.pieces[0].literal != nullptr) {
      return Constant(*collector.pieces[0].literal);
    }
    // A single non-string piece is handle by StringInterpolateSingle:
    AlternativeReadingScope scope(&reader_, collector.pieces[0].offset);
    Fragment instructions;
    instructions += BuildExpression();
    instructions += StringInterpolateSingle(position);
    return instructions;
  }

  Fragment instructions;
  instructions += Constant(TypeArguments::ZoneHandle(Z));
  instructions += IntConstant(collector.pieces.length());
  instructions += CreateArray();
  LocalVariable* array = MakeTemporary();
  for (intptr_t i = 0; i < collector.pieces.length(); ++i) {
    // All pieces are now either a concat'd string or an expression we can
    // read at a given offset.
    if (collector.pieces[i].literal != nullptr) {
      instructions += LoadLocal(array);
      instructions += IntConstant(i);
      instructions += Constant(*collector.pieces[i].literal);
    } else {
      AlternativeReadingScope scope(&reader_, collector.pieces[i].offset);
      instructions += LoadLocal(array);
      instructions += IntConstant(i);
      instructions += BuildExpression();
    }
    instructions += StoreIndexed(kArrayCid);
  }

  instructions += StringInterpolate(position);

  return instructions;
}

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

  if (translation_helper_.info().kernel_binary_version() >= 38) {
    // We do not use the library mode for the type test, which is indicated by
    // the flag kIsExpressionFlagForNonNullableByDefault.
    ReadFlags();
  }

  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 by detecting a top type.
  if (type.IsTopTypeForInstanceOf()) {
    // Evaluate the expression on the left but ignore its result.
    instructions += Drop();

    // Let condition be always true.
    instructions += Constant(Bool::True());
  } else {
    // See if simple instanceOf is applicable.
    if (dart::SimpleInstanceOfType(type)) {
      instructions += Constant(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();
    }

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

    instructions += Constant(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;

  const uint8_t flags = ReadFlags();  // read flags.
  const bool is_type_error = (flags & kAsExpressionFlagTypeError) != 0;

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

  const AbstractType& type = T.BuildType();  // read type.
  if (type.IsInstantiated() && type.IsTopTypeForSubtyping()) {
    // We already evaluated the operand on the left and just leave it there as
    // the result of the `obj as dynamic` expression.
  } else {
    // We do not care whether the 'as' cast as implicitly added by the frontend
    // or explicitly written by the user, in both cases we use an assert
    // assignable.
    instructions += LoadLocal(MakeTemporary());
    instructions += B->AssertAssignableLoadTypeArguments(
        position, type,
        is_type_error ? Symbols::Empty() : Symbols::InTypeCast(),
        AssertAssignableInstr::kInsertedByFrontend);
    instructions += Drop();
  }
  return instructions;
}

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

  const AbstractType& type = T.BuildType();  // read type.
  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(parsed_function()->receiver_var());
}

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 += LoadLocal(catch_block()->stack_trace_var());
  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 += ThrowException(position);
  ASSERT(instructions.is_closed());

  return instructions;
}

Fragment StreamingFlowGraphBuilder::BuildListLiteral(TokenPosition* p) {
  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);

  if (length == 0) {
    instructions += IntConstant(0);
    instructions += StaticCall(
        position,
        Function::ZoneHandle(Z, I->object_store()->growable_list_factory()), 2,
        ICData::kStatic);
    return instructions;
  }

  LocalVariable* type = MakeTemporary();
  instructions += LoadLocal(type);

  // The type arguments for CreateArray.
  instructions += LoadLocal(type);
  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);
  }

  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())));

  instructions += StaticCall(position, factory_method, 2, ICData::kStatic);
  instructions += DropTempsPreserveTop(1);  // Instantiated type_arguments.
  return instructions;
}

Fragment StreamingFlowGraphBuilder::BuildMapLiteral(TokenPosition* p) {
  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);

  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 += LoadLocal(array);
      instructions += IntConstant(2 * i + 1);
      instructions += BuildExpression();  // read ith value.
      instructions += StoreIndexed(kArrayCid);
    }
  }

  const Class& map_class =
      Class::Handle(Z, Library::LookupCoreClass(Symbols::Map()));
  Function& factory_method = Function::ZoneHandle(Z);
  if (map_class.EnsureIsFinalized(H.thread()) == Error::null()) {
    factory_method = map_class.LookupFactory(
        Library::PrivateCoreLibName(Symbols::MapLiteralFactory()));
  }

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

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::BuildBlockExpression() {
  block_expression_depth_inc();
  const intptr_t offset = ReaderOffset() - 1;  // Include the tag.

  Fragment instructions;

  instructions += EnterScope(offset);
  const intptr_t list_length = ReadListLength();  // read number of statements.
  for (intptr_t i = 0; i < list_length; ++i) {
    instructions += BuildStatement();  // read ith statement.
  }
  instructions += BuildExpression();  // read expression (inside scope).
  instructions += ExitScope(offset);

  block_expression_depth_dec();
  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::NewCanonical(value));
  if (integer.IsNull()) {
    H.ReportError(script_, TokenPosition::kNoSource,
                  "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.DartSymbolPlain(
      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;

  Double& constant = Double::ZoneHandle(
      Z, Double::NewCanonical(ReadDouble()));  // read double.
  return Constant(constant);
}

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::BuildFutureNullValue(
    TokenPosition* position) {
  if (position != NULL) *position = TokenPosition::kNoSource;
  const Class& future = Class::Handle(Z, I->object_store()->future_class());
  ASSERT(!future.IsNull());
  const auto& error = future.EnsureIsFinalized(thread());
  ASSERT(error == Error::null());
  const Function& constructor =
      Function::ZoneHandle(Z, future.LookupFunction(Symbols::FutureValue()));
  ASSERT(!constructor.IsNull());

  Fragment instructions;
  instructions += BuildNullLiteral(position);
  instructions += StaticCall(TokenPosition::kNoSource, constructor,
                             /* argument_count = */ 1, ICData::kStatic);
  return instructions;
}

Fragment StreamingFlowGraphBuilder::BuildConstantExpression(
    TokenPosition* position,
    Tag tag) {
  TokenPosition p = TokenPosition::kNoSource;
  if (tag == kConstantExpression) {
    p = ReadPosition();
    SkipDartType();
  }
  if (position != nullptr) *position = p;
  const intptr_t constant_offset = ReadUInt();
  Fragment result = Constant(
      Object::ZoneHandle(Z, constant_reader_.ReadConstant(constant_offset)));
  return result;
}

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

  // Create a copy of the closure.

  Fragment instructions = BuildExpression();
  LocalVariable* original_closure = MakeTemporary();

  instructions += AllocateObject(
      TokenPosition::kNoSource,
      Class::ZoneHandle(Z, I->object_store()->closure_class()), 0);
  LocalVariable* new_closure = MakeTemporary();

  intptr_t num_type_args = ReadListLength();
  const TypeArguments& type_args = T.BuildTypeArguments(num_type_args);
  instructions += TranslateInstantiatedTypeArguments(type_args);
  LocalVariable* type_args_vec = MakeTemporary();

  // Check the bounds.
  //
  // TODO(sjindel): We should be able to skip this check in many cases, e.g.
  // when the closure is coming from a tearoff of a top-level method or from a
  // local closure.
  instructions += LoadLocal(original_closure);
  instructions += LoadLocal(type_args_vec);
  const Library& dart_internal = Library::Handle(Z, Library::InternalLibrary());
  const Function& bounds_check_function = Function::ZoneHandle(
      Z, dart_internal.LookupFunctionAllowPrivate(
             Symbols::BoundsCheckForPartialInstantiation()));
  ASSERT(!bounds_check_function.IsNull());
  instructions += StaticCall(TokenPosition::kNoSource, bounds_check_function, 2,
                             ICData::kStatic);
  instructions += Drop();

  instructions += LoadLocal(new_closure);
  instructions += LoadLocal(type_args_vec);
  instructions += flow_graph_builder_->StoreInstanceField(
      TokenPosition::kNoSource, Slot::Closure_delayed_type_arguments(),
      StoreInstanceFieldInstr::Kind::kInitializing);
  instructions += Drop();  // Drop type args.

  // Copy over the target function.
  instructions += LoadLocal(new_closure);
  instructions += LoadLocal(original_closure);
  instructions +=
      flow_graph_builder_->LoadNativeField(Slot::Closure_function());
  instructions += flow_graph_builder_->StoreInstanceField(
      TokenPosition::kNoSource, Slot::Closure_function(),
      StoreInstanceFieldInstr::Kind::kInitializing);

  // Copy over the instantiator type arguments.
  instructions += LoadLocal(new_closure);
  instructions += LoadLocal(original_closure);
  instructions += flow_graph_builder_->LoadNativeField(
      Slot::Closure_instantiator_type_arguments());
  instructions += flow_graph_builder_->StoreInstanceField(
      TokenPosition::kNoSource, Slot::Closure_instantiator_type_arguments(),
      StoreInstanceFieldInstr::Kind::kInitializing);

  // Copy over the function type arguments.
  instructions += LoadLocal(new_closure);
  instructions += LoadLocal(original_closure);
  instructions += flow_graph_builder_->LoadNativeField(
      Slot::Closure_function_type_arguments());
  instructions += flow_graph_builder_->StoreInstanceField(
      TokenPosition::kNoSource, Slot::Closure_function_type_arguments(),
      StoreInstanceFieldInstr::Kind::kInitializing);

  // Copy over the context.
  instructions += LoadLocal(new_closure);
  instructions += LoadLocal(original_closure);
  instructions += flow_graph_builder_->LoadNativeField(Slot::Closure_context());
  instructions += flow_graph_builder_->StoreInstanceField(
      TokenPosition::kNoSource, Slot::Closure_context(),
      StoreInstanceFieldInstr::Kind::kInitializing);

  instructions += DropTempsPreserveTop(1);  // Drop old closure.

  return instructions;
}

Fragment StreamingFlowGraphBuilder::BuildLibraryPrefixAction(
    TokenPosition* position,
    const String& selector) {
  const intptr_t dependency_index = ReadUInt();
  const Library& current_library = Library::Handle(
      Z, Class::Handle(Z, parsed_function()->function().origin()).library());
  const Array& dependencies = Array::Handle(Z, current_library.dependencies());
  const LibraryPrefix& prefix =
      LibraryPrefix::CheckedZoneHandle(Z, dependencies.At(dependency_index));
  const Function& function =
      Function::ZoneHandle(Z, Library::Handle(Z, Library::CoreLibrary())
                                  .LookupFunctionAllowPrivate(selector));
  ASSERT(!function.IsNull());
  Fragment instructions;
  instructions += Constant(prefix);
  instructions +=
      StaticCall(TokenPosition::kNoSource, function, 1, ICData::kStatic);
  return instructions;
}

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);
  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);

  return instructions;
}

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

Fragment StreamingFlowGraphBuilder::BuildAssertBlock() {
  if (!I->asserts()) {
    SkipStatementList();
    return Fragment();
  }

  intptr_t offset = ReaderOffset() - 1;  // Include the tag.

  Fragment instructions;

  instructions += EnterScope(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);

  return instructions;
}

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.

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

  instructions += EvaluateAssertion();
  instructions += CheckBoolean(condition_start_offset);
  instructions += Constant(Bool::True());
  instructions += BranchIfEqual(&then, &otherwise, false);

  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 equivalent of `throw _AssertionError._throwNew(start, end, message)`
  // expression. We build throw (even through _throwNew already throws) because
  // call is not a valid last instruction for the block. Blocks can only
  // terminate with explicit control flow instructions (Branch, Goto, Return
  // or Throw).
  Fragment otherwise_fragment(otherwise);
  otherwise_fragment += IntConstant(condition_start_offset.Pos());
  otherwise_fragment += IntConstant(condition_end_offset.Pos());
  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.
  }

  // Note: condition_start_offset points to the first token after the opening
  // paren, not the beginning of 'assert'.
  otherwise_fragment +=
      StaticCall(condition_start_offset, target, 3, ICData::kStatic);
  otherwise_fragment += ThrowException(TokenPosition::kNoSource);
  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;
  // Break statement should pause before manipulation of context, which
  // will possibly cause debugger having incorrect context object.
  if (NeedsDebugStepCheck(parsed_function()->function(), position)) {
    instructions += DebugStepCheck(position);
  }
  instructions +=
      TranslateFinallyFinalizers(outer_finally, target_context_depth);
  if (instructions.is_open()) {
    instructions += Goto(destination);
  }
  return instructions;
}

Fragment StreamingFlowGraphBuilder::BuildWhileStatement() {
  ASSERT(block_expression_depth() == 0);  // no while in block-expr
  loop_depth_inc();
  const TokenPosition position = ReadPosition();            // read position.
  TestFragment condition = TranslateConditionForControl();  // read condition.
  const Fragment body = BuildStatement();                   // read body

  Fragment body_entry(condition.CreateTrueSuccessor(flow_graph_builder_));
  body_entry += body;

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

    Fragment loop(join);
    ASSERT(B->GetStackDepth() == 0);
    loop += CheckStackOverflow(position);
    loop.current->LinkTo(condition.entry);

    entry = Goto(join).entry;
  } else {
    entry = condition.entry;
  }

  loop_depth_dec();
  return Fragment(entry, condition.CreateFalseSuccessor(flow_graph_builder_));
}

Fragment StreamingFlowGraphBuilder::BuildDoStatement() {
  ASSERT(block_expression_depth() == 0);  // no do-while in block-expr
  loop_depth_inc();
  const TokenPosition position = ReadPosition();  // read position.
  Fragment body = BuildStatement();               // read body.

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

  TestFragment condition = TranslateConditionForControl();

  JoinEntryInstr* join = BuildJoinEntry();
  Fragment loop(join);
  ASSERT(B->GetStackDepth() == 0);
  loop += CheckStackOverflow(position);
  loop += body;
  loop <<= condition.entry;

  condition.IfTrueGoto(flow_graph_builder_, join);

  loop_depth_dec();
  return Fragment(
      new (Z) GotoInstr(join, CompilerState::Current().GetNextDeoptId()),
      condition.CreateFalseSuccessor(flow_graph_builder_));
}

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

  const TokenPosition position = ReadPosition();  // read position.

  Fragment declarations;

  loop_depth_inc();

  const LocalScope* context_scope = nullptr;
  declarations += EnterScope(offset, &context_scope);

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

  Tag tag = ReadTag();  // Read first part of condition.
  TestFragment condition;
  BlockEntryInstr* body_entry;
  BlockEntryInstr* loop_exit;
  if (tag != kNothing) {
    condition = TranslateConditionForControl();
    body_entry = condition.CreateTrueSuccessor(flow_graph_builder_);
    loop_exit = condition.CreateFalseSuccessor(flow_graph_builder_);
  } else {
    body_entry = BuildJoinEntry();
    loop_exit = BuildJoinEntry();
  }

  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 (context_scope->num_context_variables() > 0) {
      body += CloneContext(context_scope->context_slots());
    }

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

    Fragment loop(join);
    loop += CheckStackOverflow(position);  // may have non-empty stack
    if (condition.entry != nullptr) {
      loop <<= condition.entry;
    } else {
      loop += Goto(body_entry->AsJoinEntry());
    }
  } else {
    if (condition.entry != nullptr) {
      declarations <<= condition.entry;
    } else {
      declarations += Goto(body_entry->AsJoinEntry());
    }
  }

  Fragment loop(declarations.entry, loop_exit);

  loop += ExitScope(offset);

  loop_depth_dec();

  return loop;
}

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

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

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

  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 +=
      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);
  body += LoadLocal(iterator);
  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);

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

    Fragment loop(join);
    loop += CheckStackOverflow(position);  // may have non-empty stack
    loop += condition;
  } else {
    instructions += condition;
  }

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

Fragment StreamingFlowGraphBuilder::BuildSwitchStatement() {
  ReadPosition();  // read position.
  // 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 = Z->Alloc<Fragment>(case_count);
  intptr_t* case_expression_offsets = Z->Alloc<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 auto& error = klass.EnsureIsFinalized(thread());
      ASSERT(error == Error::null());

      GrowableHandlePtrArray<const String> pieces(Z, 3);
      pieces.Add(Symbols::FallThroughError());
      pieces.Add(Symbols::Dot());
      pieces.Add(H.DartSymbolObfuscate("_create"));

      const Function& constructor = Function::ZoneHandle(
          Z, klass.LookupConstructorAllowPrivate(String::ZoneHandle(
                 Z, Symbols::FromConcatAll(H.thread(), pieces))));
      ASSERT(!constructor.IsNull());
      const String& url = H.DartSymbolPlain(
          parsed_function()->function().ToLibNamePrefixedQualifiedCString());

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

      // Call _FallThroughError._create constructor.
      body_fragment += LoadLocal(instance);  // this
      body_fragment += Constant(url);        // url
      body_fragment += NullConstant();       // line

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

      // Throw the exception
      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));

      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(
            Instance::ZoneHandle(Z, constant_reader_.ReadConstantExpression()));
        current_instructions += LoadLocal(scopes()->switch_variable);
        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.
  }

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

Fragment StreamingFlowGraphBuilder::BuildContinueSwitchStatement() {
  TokenPosition position = ReadPosition();  // read position.
  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()) {
    if (NeedsDebugStepCheck(parsed_function()->function(), position)) {
      instructions += DebugStepCheck(position);
    }
    instructions += Goto(entry);
  }
  return instructions;
}

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

  TestFragment condition = TranslateConditionForControl();

  Fragment then_fragment(condition.CreateTrueSuccessor(flow_graph_builder_));
  then_fragment += BuildStatement();  // read then.

  Fragment otherwise_fragment(
      condition.CreateFalseSuccessor(flow_graph_builder_));
  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(condition.entry, join);
    } else {
      return Fragment(condition.entry, then_fragment.current);
    }
  } else if (otherwise_fragment.is_open()) {
    return Fragment(condition.entry, otherwise_fragment.current);
  } else {
    return Fragment(condition.entry, nullptr);
  }
}

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() {
  ASSERT(block_expression_depth() == 0);  // no try-catch in block-expr
  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();

  const int kNeedsStracktraceBit = 1 << 0;
  const int kIsSyntheticBit = 1 << 1;

  uint8_t flags = ReadByte();
  bool needs_stacktrace =
      (flags & kNeedsStracktraceBit) == kNeedsStracktraceBit;
  bool is_synthetic = (flags & kIsSyntheticBit) == kIsSyntheticBit;

  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, is_synthetic);
  // 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.
    TokenPosition position = ReadPosition();         // read position.
    const AbstractType& type_guard = T.BuildType();  // read guard.
    handler_types.SetAt(i, type_guard);

    Fragment catch_handler_body = EnterScope(catch_offset);

    Tag tag = ReadTag();  // read first part of exception.
    if (tag == kSomething) {
      catch_handler_body += LoadLocal(CurrentException());
      catch_handler_body +=
          StoreLocal(TokenPosition::kNoSource,
                     LookupVariable(ReaderOffset() + data_program_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() + data_program_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);
      if (catch_handler_body.is_open()) {
        catch_handler_body += Goto(after_try);
      }
    }

    if (!type_guard.IsCatchAllType()) {
      catch_body += LoadLocal(CurrentException());

      if (!type_guard.IsInstantiated(kCurrentClass)) {
        catch_body += LoadInstantiatorTypeArguments();
      } else {
        catch_body += NullConstant();
      }

      if (!type_guard.IsInstantiated(kFunctions)) {
        catch_body += LoadFunctionTypeArguments();
      } else {
        catch_body += NullConstant();
      }

      catch_body += Constant(type_guard);

      catch_body += InstanceCall(
          position, 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 += LoadLocal(CurrentStackTrace());
    catch_body += RethrowException(TokenPosition::kNoSource, try_handler_index);
    Drop();
  }
  catch_depth_dec();

  return Fragment(try_body.entry, after_try);
}

Fragment StreamingFlowGraphBuilder::BuildTryFinally() {
  ASSERT(block_expression_depth() == 0);  // no try-finally in block-expr
  // 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 [LabeledStatement]
  //   * [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,
                                          /* is_synthesized = */ true);
  SetOffset(finalizer_offset);
  finally_body += BuildStatement();  // read finalizer
  if (finally_body.is_open()) {
    finally_body += LoadLocal(CurrentException());
    finally_body += LoadLocal(CurrentStackTrace());
    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.
  //
  const intptr_t new_yield_pos = yield_continuations().length() + 1;
  Fragment instructions = IntConstant(new_yield_pos);
  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(position, new_yield_pos);

  // 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);
    //     ...
    //   }
    //
    LocalVariable* exception_var = parsed_function()->ParameterVariable(2);
    LocalVariable* stack_trace_var = parsed_function()->ParameterVariable(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 += LoadLocal(stack_trace_var);
    rethrow += RethrowException(position, kInvalidTryIndex);
    Drop();

    continuation = Fragment(continuation.entry, no_error);
  }

  return continuation;
}

Fragment StreamingFlowGraphBuilder::BuildVariableDeclaration() {
  intptr_t kernel_position_no_tag = ReaderOffset() + data_program_offset_;
  LocalVariable* variable = LookupVariable(kernel_position_no_tag);

  VariableDeclarationHelper helper(this);
  helper.ReadUntilExcluding(VariableDeclarationHelper::kType);
  T.BuildType();  // read type.
  bool has_initializer = (ReadTag() != kNothing);

  Fragment instructions;
  if (variable->is_late()) {
    // TODO(liama): Treat the field as non-late if the initializer is trivial.
    if (has_initializer) {
      SkipExpression();
    }
    instructions += Constant(Object::sentinel());
  } else if (!has_initializer) {
    instructions += NullConstant();
  } else if (helper.IsConst()) {
    // Read const initializer form current position.
    const Instance& constant_value =
        Instance::ZoneHandle(Z, constant_reader_.ReadConstantExpression());
    variable->SetConstValue(constant_value);
    instructions += Constant(constant_value);
  } else {
    // Initializer
    instructions += BuildExpression();  // read (actual) initializer.
  }

  // 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() + data_program_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();

  FunctionNodeHelper function_node_helper(this);
  function_node_helper.ReadUntilExcluding(FunctionNodeHelper::kTypeParameters);
  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.DartSymbolObfuscate(name_index);
      } else {
        name = &Symbols::AnonymousClosure();
      }
      // NOTE: This is not TokenPosition in the general sense!
      if (!closure_owner_.IsNull()) {
        function = Function::NewClosureFunctionWithKind(
            FunctionLayout::kClosureFunction, *name,
            parsed_function()->function(), position, closure_owner_);
      } else {
        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(FunctionLayout::kSyncGen);
          break;
        case FunctionNodeHelper::kAsync:
          function.set_modifier(FunctionLayout::kAsync);
          function.set_is_inlinable(!FLAG_causal_async_stacks);
          break;
        case FunctionNodeHelper::kAsyncStar:
          function.set_modifier(FunctionLayout::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 &&
                                  !FLAG_lazy_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);
      type_translator_.SetupFunctionParameters(Class::Handle(Z), function,
                                               false,  // is_method
                                               true,   // is_closure
                                               &function_node_helper);
      // type_translator_.SetupUnboxingInfoMetadata is not called here at the
      // moment because closures do not have unboxed parameters and return value
      function_node_helper.ReadUntilExcluding(FunctionNodeHelper::kEnd);

      // 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);

  Fragment instructions =
      flow_graph_builder_->AllocateClosure(TokenPosition::kNoSource, function);
  LocalVariable* closure = MakeTemporary();

  // The function signature can have uninstantiated class type parameters.
  if (!function.HasInstantiatedSignature(kCurrentClass)) {
    instructions += LoadLocal(closure);
    instructions += LoadInstantiatorTypeArguments();
    instructions += flow_graph_builder_->StoreInstanceField(
        TokenPosition::kNoSource, Slot::Closure_instantiator_type_arguments(),
        StoreInstanceFieldInstr::Kind::kInitializing);
  }

  // TODO(30455): We only need to save these if the closure uses any captured
  // type parameters.
  instructions += LoadLocal(closure);
  instructions += LoadFunctionTypeArguments();
  instructions += flow_graph_builder_->StoreInstanceField(
      TokenPosition::kNoSource, Slot::Closure_function_type_arguments(),
      StoreInstanceFieldInstr::Kind::kInitializing);

  if (function.IsGeneric()) {
    // Only generic functions need to have properly initialized
    // delayed_type_arguments.
    instructions += LoadLocal(closure);
    instructions += Constant(Object::empty_type_arguments());
    instructions += flow_graph_builder_->StoreInstanceField(
        TokenPosition::kNoSource, Slot::Closure_delayed_type_arguments(),
        StoreInstanceFieldInstr::Kind::kInitializing);
  }

  // Store the function and the context in the closure.
  instructions += LoadLocal(closure);
  instructions += Constant(function);
  instructions += flow_graph_builder_->StoreInstanceField(
      TokenPosition::kNoSource, Slot::Closure_function(),
      StoreInstanceFieldInstr::Kind::kInitializing);

  instructions += LoadLocal(closure);
  instructions += LoadLocal(parsed_function()->current_context_var());
  instructions += flow_graph_builder_->StoreInstanceField(
      TokenPosition::kNoSource, Slot::Closure_context(),
      StoreInstanceFieldInstr::Kind::kInitializing);

  return instructions;
}

Fragment StreamingFlowGraphBuilder::BuildFfiAsFunctionInternal() {
  const intptr_t argc = ReadUInt();               // read argument count.
  ASSERT(argc == 1);                              // pointer
  const intptr_t list_length = ReadListLength();  // read types list length.
  ASSERT(list_length == 2);  // dart signature, then native signature
  const TypeArguments& type_arguments =
      T.BuildTypeArguments(list_length);  // read types.
  Fragment code;
  const intptr_t positional_count =
      ReadListLength();  // read positional argument count
  ASSERT(positional_count == 1);
  code += BuildExpression();  // build first positional argument (pointer)
  const intptr_t named_args_len =
      ReadListLength();  // skip (empty) named arguments list
  ASSERT(named_args_len == 0);
  code += B->BuildFfiAsFunctionInternalCall(type_arguments);
  return code;
}

Fragment StreamingFlowGraphBuilder::BuildFfiNativeCallbackFunction() {
  // The call-site must look like this (guaranteed by the FE which inserts it):
  //
  //   _nativeCallbackFunction<NativeSignatureType>(target, exceptionalReturn)
  //
  // The FE also guarantees that all three arguments are constants.

  const intptr_t argc = ReadUInt();  // read argument count
  ASSERT(argc == 2);                 // target, exceptionalReturn

  const intptr_t list_length = ReadListLength();  // read types list length
  ASSERT(list_length == 1);                       // native signature
  const TypeArguments& type_arguments =
      T.BuildTypeArguments(list_length);  // read types.
  ASSERT(type_arguments.Length() == 1 && type_arguments.IsInstantiated());
  const Function& native_sig = Function::Handle(
      Z, Type::CheckedHandle(Z, type_arguments.TypeAt(0)).signature());

  Fragment code;
  const intptr_t positional_count =
      ReadListLength();  // read positional argument count
  ASSERT(positional_count == 2);

  // Read target expression and extract the target function.
  code += BuildExpression();  // build first positional argument (target)
  Definition* target_def = B->Peek();
  ASSERT(target_def->IsConstant());
  const Closure& target_closure =
      Closure::Cast(target_def->AsConstant()->value());
  ASSERT(!target_closure.IsNull());
  Function& target = Function::Handle(Z, target_closure.function());
  ASSERT(!target.IsNull() && target.IsImplicitClosureFunction());
  target = target.parent_function();
  code += Drop();

  // Build second positional argument (exceptionalReturn).
  code += BuildExpression();
  Definition* exceptional_return_def = B->Peek();
  ASSERT(exceptional_return_def->IsConstant());
  const Instance& exceptional_return =
      Instance::Cast(exceptional_return_def->AsConstant()->value());
  code += Drop();

  const intptr_t named_args_len =
      ReadListLength();  // skip (empty) named arguments list
  ASSERT(named_args_len == 0);

  const Function& result =
      Function::ZoneHandle(Z, compiler::ffi::NativeCallbackFunction(
                                  native_sig, target, exceptional_return));
  code += Constant(result);

  auto& ffi_callback_functions = GrowableObjectArray::Handle(Z);
  ffi_callback_functions ^= I->object_store()->ffi_callback_functions();
  if (ffi_callback_functions.IsNull()) {
    ffi_callback_functions ^= GrowableObjectArray::New();
    I->object_store()->set_ffi_callback_functions(ffi_callback_functions);
  }
  ffi_callback_functions.Add(result);

  return code;
}

}  // namespace kernel
}  // namespace dart
