// 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/closure_functions_cache.h"
#include "vm/compiler/ffi/callback.h"
#include "vm/compiler/ffi/recognized_method.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/kernel_binary.h"
#include "vm/kernel_loader.h"
#include "vm/object_store.h"
#include "vm/resolver.h"
#include "vm/stack_frame.h"

namespace dart {
namespace kernel {

#define Z (zone_)
#define H (translation_helper_)
#define T (type_translator_)
#define I Isolate::Current()
#define IG IsolateGroup::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);

  // Constants are directly accessed at use sites of Dart code. In C++ - if
  // we need to access static constants - we do so directly using the kernel
  // evaluation instead of invoking the initializer function in Dart code.
  //
  // If the field is marked as @pragma('vm:entry-point') then the embedder might
  // invoke the getter, so we'll generate the initializer function.
  ASSERT(!field_helper.IsConst() ||
         Field::Handle(Z, parsed_function()->function().accessor_field())
                 .VerifyEntryPoint(EntryPointPragma::kGetterOnly) ==
             Error::null());

  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_);
  body += SetupCapturedParameters(parsed_function()->function());
  body += BuildExpression();  // read initializer.
  body += Return(TokenPosition::kNoSource);

  PrologueInfo prologue_info(-1, -1);
  if (B->IsCompiledForOsr()) {
    auto result = B->graph_entry_->FindOsrEntry(Z, B->last_used_block_id_ + 1);
    flow_graph_builder_->RelinkToOsrEntry(result);
  }
  return new (Z) FlowGraph(
      *parsed_function(), B->graph_entry_, B->last_used_block_id_,
      prologue_info,
      FlowGraph::CompilationModeFrom(flow_graph_builder_->optimizing()));
}

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()->IsDartMutatorThread()) {
      ASSERT(field.IsOriginal());
      LeaveCompilerScope cs(H.thread());
      field.RecordStore(Object::null_object());
    } else {
      ASSERT(field.is_nullable_unsafe());
    }
    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_->StoreFieldGuarded(
        field, StoreFieldInstr::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()->IsDartMutatorThread()) {
      LeaveCompilerScope cs(H.thread());
      field.RecordStore(Object::null_object());
    } else {
      ASSERT(field.is_nullable_unsafe());
    }
    return Fragment();
  }

  Fragment instructions;
  instructions += LoadLocal(parsed_function()->receiver_var());
  instructions += flow_graph_builder_->Constant(Object::sentinel());
  instructions += flow_graph_builder_->StoreField(
      field, StoreFieldInstr::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();
        ReadPosition();
        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
    // StoreField 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);

    auto& kernel_data = TypedDataView::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.KernelLibrary();
        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.ptr()),
                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.ptr()),
              /*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: {
          ReadPosition();  // read position.
          ReadCanonicalNameReference();
          instructions += BuildFieldInitializer(
              Field::ZoneHandle(Z, initializer_fields[i]->ptr()),
              /*only_for_side_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_argument_count=*/nullptr);  // 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_argument_count=*/nullptr);  // 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;
}

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::TypeArgumentsHandling(
    const Function& dart_function) {
  Fragment prologue = B->BuildDefaultTypeHandling(dart_function);

  if (dart_function.IsClosureFunction() &&
      dart_function.NumParentTypeArguments() > 0) {
    LocalVariable* closure = parsed_function()->ParameterVariable(0);
    LocalVariable* fn_type_args = parsed_function()->function_type_arguments();
    ASSERT(fn_type_args != nullptr && closure != nullptr);

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

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

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

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

      const auto& prepend_function =
          flow_graph_builder_->PrependTypeArgumentsFunction();

      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::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.MakesCopyOfParameters() &&
                raw_parameter.owner() == scope) ||
               (!function.MakesCopyOfParameters() &&
                raw_parameter.owner() == nullptr));
        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_->StoreNativeField(
            Slot::GetContextVariableSlotFor(thread(), *variable),
            StoreFieldInstr::Kind::kInitializing);
      }
    }
    body += Drop();  // The context.
  }
  return body;
}

Fragment StreamingFlowGraphBuilder::InitSuspendableFunction(
    const Function& dart_function,
    const AbstractType* emitted_value_type) {
  Fragment body;
  if (dart_function.IsAsyncFunction()) {
    ASSERT(emitted_value_type != nullptr);
    auto& type_args = TypeArguments::ZoneHandle(Z, TypeArguments::New(1));
    type_args.SetTypeAt(0, *emitted_value_type);
    type_args = Class::Handle(Z, IG->object_store()->future_class())
                    .GetInstanceTypeArguments(H.thread(), type_args);
    body += TranslateInstantiatedTypeArguments(type_args);
    body += B->Call1ArgStub(TokenPosition::kNoSource,
                            Call1ArgStubInstr::StubId::kInitAsync);
    body += Drop();
  } else if (dart_function.IsAsyncGenerator()) {
    ASSERT(emitted_value_type != nullptr);
    auto& type_args = TypeArguments::ZoneHandle(Z, TypeArguments::New(1));
    type_args.SetTypeAt(0, *emitted_value_type);
    type_args = Class::Handle(Z, IG->object_store()->stream_class())
                    .GetInstanceTypeArguments(H.thread(), type_args);
    body += TranslateInstantiatedTypeArguments(type_args);
    body += B->Call1ArgStub(TokenPosition::kNoSource,
                            Call1ArgStubInstr::StubId::kInitAsyncStar);
    body += Drop();
    body += NullConstant();
    body += B->Suspend(TokenPosition::kNoSource,
                       SuspendInstr::StubId::kYieldAsyncStar);
    body += Drop();
  } else if (dart_function.IsSyncGenerator()) {
    ASSERT(emitted_value_type != nullptr);
    auto& type_args = TypeArguments::ZoneHandle(Z, TypeArguments::New(1));
    type_args.SetTypeAt(0, *emitted_value_type);
    type_args = Class::Handle(Z, IG->object_store()->iterable_class())
                    .GetInstanceTypeArguments(H.thread(), type_args);
    body += TranslateInstantiatedTypeArguments(type_args);
    body += B->Call1ArgStub(TokenPosition::kNoSource,
                            Call1ArgStubInstr::StubId::kInitSyncStar);
    body += Drop();
    body += NullConstant();
    body += B->Suspend(TokenPosition::kNoSource,
                       SuspendInstr::StubId::kSuspendSyncStarAtStart);
    body += Drop();
    // Clone context if there are any captured parameter variables, so
    // each invocation of .iterator would get its own copy of parameters.
    const LocalScope* scope = parsed_function()->scope();
    if (scope->num_context_variables() > 0) {
      body += CloneContext(scope->context_slots());
    }
  } else {
    ASSERT(emitted_value_type == nullptr);
  }
  return body;
}

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().ptr()) &&
      (dart_function.Owner() != IG->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_old_native()) {
    body += B->NativeFunctionBody(dart_function, first_parameter);
  } else if (dart_function.is_ffi_native()) {
    body += B->FfiNativeFunctionBody(dart_function);
  } else if (dart_function.is_external()) {
    body += ThrowNoSuchMethodError(TokenPosition::kNoSource, dart_function,
                                   /*incompatible_arguments=*/false);
    ASSERT(body.is_closed());
  } else if (has_body) {
    body += BuildStatement();
  }

  if (body.is_open()) {
    if (parsed_function()->function().IsSyncGenerator()) {
      // Return false from sync* function to indicate the end of iteration.
      body += Constant(Bool::False());
    } else {
      body += NullConstant();
    }
    body += Return(dart_function.end_token_pos());
  }

  return body;
}

Fragment StreamingFlowGraphBuilder::BuildRegularFunctionPrologue(
    const Function& dart_function,
    TokenPosition token_position,
    LocalVariable* first_parameter) {
  Fragment F;
  F += CheckStackOverflowInPrologue(dart_function);
  F += DebugStepCheckInPrologue(dart_function, token_position);
  F += B->InitConstantParameters();
  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& regular_function_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. The regular function prologue has more than two instructions
  //    (DebugStepCheck and CheckStackOverflow).
  //
  if (!PrologueBuilder::HasEmptyPrologue(dart_function) ||
      !type_args_handling.is_empty()) {
    return UncheckedEntryPointStyle::kSharedWithVariable;
  }
  Instruction* instr = regular_function_prologue.entry;
  if (instr != nullptr && instr->IsCheckStackOverflow()) {
    instr = instr->next();
  }
  if (instr != nullptr && instr->IsDebugStepCheck()) {
    instr = instr->next();
  }
  if (instr != nullptr) {
    return UncheckedEntryPointStyle::kSharedWithVariable;
  }

  return UncheckedEntryPointStyle::kSeparate;
}

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

  LocalVariable* first_parameter = nullptr;
  TokenPosition token_position = TokenPosition::kNoSource;
  const AbstractType* emitted_value_type = nullptr;
  {
    AlternativeReadingScope alt(&reader_);
    FunctionNodeHelper function_node_helper(this);
    function_node_helper.ReadUntilExcluding(
        FunctionNodeHelper::kPositionalParameters);
    {
      AlternativeReadingScope alt2(&reader_);
      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_;
    if (dart_function.IsSuspendableFunction()) {
      function_node_helper.ReadUntilExcluding(
          FunctionNodeHelper::kEmittedValueType);
      if (ReadTag() == kSomething) {
        emitted_value_type = &T.BuildType();  // read emitted value type.
      } else {
        UNREACHABLE();
      }
    }
  }

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

  const Fragment regular_prologue = BuildRegularFunctionPrologue(
      dart_function, token_position, first_parameter);

  // 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 implicit_type_checks;
  if (dart_function.NeedsTypeArgumentTypeChecks()) {
    B->BuildTypeArgumentTypeChecks(
        TypeChecksToBuild::kCheckCovariantTypeParameterBounds,
        &implicit_type_checks);
  }

  Fragment explicit_type_checks;
  Fragment implicit_redefinitions;
  if (dart_function.NeedsArgumentTypeChecks()) {
    B->BuildArgumentTypeChecks(&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) +
      InitSuspendableFunction(dart_function, emitted_value_type) +
      BuildFunctionBody(dart_function, first_parameter, is_constructor);

  auto extra_entry_point_style =
      ChooseEntryPointStyle(dart_function, implicit_type_checks,
                            regular_prologue, type_args_handling);

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

      const Fragment prologue_copy = BuildRegularFunctionPrologue(
          dart_function, token_position, first_parameter);

      extra_entry = B->BuildSeparateUncheckedEntryPoint(
          normal_entry,
          /*normal_prologue=*/regular_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 += regular_prologue;
      prologue += type_args_handling;
      prologue += explicit_type_checks;
      extra_entry = B->BuildSharedUncheckedEntryPoint(
          /*prologue_from_normal_entry=*/prologue,
          /*skippable_checks=*/implicit_type_checks,
          /*redefinitions_if_skipped=*/implicit_redefinitions,
          /*body=*/body);
      break;
    }
  }
  if (extra_entry != nullptr) {
    B->RecordUncheckedEntryPoint(graph_entry, extra_entry);
  }

  auto flow_graph = new (Z) FlowGraph(
      *parsed_function(), graph_entry, flow_graph_builder_->last_used_block_id_,
      prologue_info,
      FlowGraph::CompilationModeFrom(flow_graph_builder_->optimizing()));

  // 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.
  // Include enclosing try blocks with corresponding catch blocks.
  if (flow_graph_builder_->IsCompiledForOsr()) {
    auto result = graph_entry->FindOsrEntry(
        Z, flow_graph_builder_->last_used_block_id_ + 1);
    flow_graph_builder_->RelinkToOsrEntry(result);
    flow_graph = new (Z) FlowGraph(
        *parsed_function(), graph_entry,
        flow_graph_builder_->last_used_block_id_, prologue_info,
        FlowGraph::CompilationModeFrom(flow_graph_builder_->optimizing_));
  }
  return flow_graph;
}

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

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

  // Setup an [ActiveClassScope] and an [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);
  FunctionType& signature = FunctionType::Handle(Z, function.signature());
  ActiveTypeParametersScope active_type_params(active_class(), function,
                                               &signature, Z);

  ParseKernelASTFunction();

  switch (function.kind()) {
    case UntaggedFunction::kRegularFunction:
    case UntaggedFunction::kGetterFunction:
    case UntaggedFunction::kSetterFunction:
    case UntaggedFunction::kClosureFunction:
    case UntaggedFunction::kConstructor: {
      if (FlowGraphBuilder::IsRecognizedMethodForFlowGraph(function)) {
        return B->BuildGraphOfRecognizedMethod(function);
      }
      return BuildGraphOfFunction(function.IsGenerativeConstructor());
    }
    case UntaggedFunction::kImplicitGetter:
    case UntaggedFunction::kImplicitStaticGetter:
    case UntaggedFunction::kImplicitSetter: {
      return B->BuildGraphOfFieldAccessor(function);
    }
    case UntaggedFunction::kFieldInitializer:
      return BuildGraphOfFieldInitializer();
    case UntaggedFunction::kDynamicInvocationForwarder:
      return B->BuildGraphOfDynamicInvocationForwarder(function);
    case UntaggedFunction::kMethodExtractor:
      return flow_graph_builder_->BuildGraphOfMethodExtractor(function);
    case UntaggedFunction::kNoSuchMethodDispatcher:
      return flow_graph_builder_->BuildGraphOfNoSuchMethodDispatcher(function);
    case UntaggedFunction::kInvokeFieldDispatcher:
      return flow_graph_builder_->BuildGraphOfInvokeFieldDispatcher(function);
    case UntaggedFunction::kImplicitClosureFunction:
      return flow_graph_builder_->BuildGraphOfImplicitClosureFunction(function);
    case UntaggedFunction::kFfiTrampoline:
      return flow_graph_builder_->BuildGraphOfFfiTrampoline(function);
    case UntaggedFunction::kRecordFieldGetter:
      return flow_graph_builder_->BuildGraphOfRecordFieldGetter(function);
    case UntaggedFunction::kIrregexpFunction:
      break;
  }
  UNREACHABLE();
  return nullptr;
}

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

  if (!function.IsNoSuchMethodDispatcher() &&
      !function.IsInvokeFieldDispatcher() &&
      !function.IsFfiCallbackTrampoline()) {
    const intptr_t kernel_offset = function.kernel_offset();
    ASSERT(kernel_offset >= 0);
    SetOffset(kernel_offset);
  }

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

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

  switch (function.kind()) {
    case UntaggedFunction::kRegularFunction:
    case UntaggedFunction::kGetterFunction:
    case UntaggedFunction::kSetterFunction:
    case UntaggedFunction::kClosureFunction:
    case UntaggedFunction::kConstructor:
    case UntaggedFunction::kImplicitClosureFunction:
      ReadUntilFunctionNode();
      SetupDefaultParameterValues();
      break;
    case UntaggedFunction::kImplicitGetter:
    case UntaggedFunction::kImplicitStaticGetter:
    case UntaggedFunction::kImplicitSetter:
    case UntaggedFunction::kFieldInitializer:
    case UntaggedFunction::kMethodExtractor:
    case UntaggedFunction::kNoSuchMethodDispatcher:
    case UntaggedFunction::kInvokeFieldDispatcher:
    case UntaggedFunction::kFfiTrampoline:
    case UntaggedFunction::kRecordFieldGetter:
      break;
    case UntaggedFunction::kDynamicInvocationForwarder:
      if (PeekTag() != kField) {
        ReadUntilFunctionNode();
        SetupDefaultParameterValues();
      }
      break;
    case UntaggedFunction::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.concrete_forwarding_stub_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) {
  ++num_ast_nodes_;
  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 kInstanceGet:
      return BuildInstanceGet(position);
    case kDynamicGet:
      return BuildDynamicGet(position);
    case kInstanceTearOff:
      return BuildInstanceTearOff(position);
    case kFunctionTearOff:
      // Removed by lowering kernel transformation.
      UNREACHABLE();
      break;
    case kInstanceSet:
      return BuildInstanceSet(position);
    case kDynamicSet:
      return BuildDynamicSet(position);
    case kAbstractSuperPropertyGet:
      // Abstract super property getters must be converted into super property
      // getters during mixin transformation.
      UNREACHABLE();
      break;
    case kAbstractSuperPropertySet:
      // Abstract super property setters must be converted into super property
      // setters during mixin transformation.
      UNREACHABLE();
      break;
    case kSuperPropertyGet:
      return BuildSuperPropertyGet(position);
    case kSuperPropertySet:
      return BuildSuperPropertySet(position);
    case kStaticGet:
      return BuildStaticGet(position);
    case kStaticSet:
      return BuildStaticSet(position);
    case kInstanceInvocation:
      return BuildMethodInvocation(position, /*is_dynamic=*/false);
    case kDynamicInvocation:
      return BuildMethodInvocation(position, /*is_dynamic=*/true);
    case kLocalFunctionInvocation:
      return BuildLocalFunctionInvocation(position);
    case kFunctionInvocation:
      return BuildFunctionInvocation(position);
    case kEqualsCall:
      return BuildEqualsCall(position);
    case kEqualsNull:
      return BuildEqualsNull(position);
    case kAbstractSuperMethodInvocation:
      // Abstract super method invocations must be converted into super
      // method invocations during mixin transformation.
      UNREACHABLE();
      break;
    case kSuperMethodInvocation:
      return BuildSuperMethodInvocation(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 kRecordLiteral:
      return BuildRecordLiteral(position);
    case kRecordIndexGet:
      return BuildRecordFieldGet(position, /*is_named=*/false);
    case kRecordNameGet:
      return BuildRecordFieldGet(position, /*is_named=*/true);
    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:
    case kFileUriConstantExpression:
      return BuildConstantExpression(position, tag);
    case kInstantiation:
      return BuildPartialTearoffInstantiation(position);
    case kLoadLibrary:
      return BuildLibraryPrefixAction(position, Symbols::LoadLibrary());
    case kCheckLibraryIsLoaded:
      return BuildLibraryPrefixAction(position, Symbols::CheckLoaded());
    case kAwaitExpression:
      return BuildAwaitExpression(position);
    case kFileUriExpression:
      return BuildFileUriExpression(position);
    case kConstStaticInvocation:
    case kConstConstructorInvocation:
    case kConstListLiteral:
    case kConstSetLiteral:
    case kConstMapLiteral:
    case kSymbolLiteral:
    case kListConcatenation:
    case kSetConcatenation:
    case kMapConcatenation:
    case kInstanceCreation:
    case kStaticTearOff:
    case kSwitchExpression:
    case kPatternAssignment:
    // These nodes are internal to the front end and
    // removed by the constant evaluator.
    default:
      ReportUnexpectedTag("expression", tag);
      UNREACHABLE();
  }

  return Fragment();
}

Fragment StreamingFlowGraphBuilder::BuildStatement(TokenPosition* position) {
  ++num_ast_nodes_;
  Tag tag = ReadTag();  // read tag.
  switch (tag) {
    case kExpressionStatement:
      return BuildExpressionStatement(position);
    case kBlock:
      return BuildBlock(position);
    case kEmptyStatement:
      return BuildEmptyStatement();
    case kAssertBlock:
      return BuildAssertBlock(position);
    case kAssertStatement:
      return BuildAssertStatement(position);
    case kLabeledStatement:
      return BuildLabeledStatement(position);
    case kBreakStatement:
      return BuildBreakStatement(position);
    case kWhileStatement:
      return BuildWhileStatement(position);
    case kDoStatement:
      return BuildDoStatement(position);
    case kForStatement:
      return BuildForStatement(position);
    case kSwitchStatement:
      return BuildSwitchStatement(position);
    case kContinueSwitchStatement:
      return BuildContinueSwitchStatement(position);
    case kIfStatement:
      return BuildIfStatement(position);
    case kReturnStatement:
      return BuildReturnStatement(position);
    case kTryCatch:
      return BuildTryCatch(position);
    case kTryFinally:
      return BuildTryFinally(position);
    case kYieldStatement:
      return BuildYieldStatement(position);
    case kVariableDeclaration:
      return BuildVariableDeclaration(position);
    case kFunctionDeclaration:
      return BuildFunctionDeclaration(position);
    case kForInStatement:
    case kAsyncForInStatement:
    case kIfCaseStatement:
    case kPatternSwitchStatement:
    case kPatternVariableDeclaration:
    // These nodes are internal to the front end and
    // removed by the constant evaluator.
    default:
      ReportUnexpectedTag("statement", tag);
      UNREACHABLE();
  }
  return Fragment();
}

Fragment StreamingFlowGraphBuilder::BuildStatementWithBranchCoverage(
    TokenPosition* position) {
  TokenPosition pos = TokenPosition::kNoSource;
  Fragment statement = BuildStatement(&pos);
  if (position != nullptr) *position = pos;
  Fragment covered_statement = flow_graph_builder_->RecordBranchCoverage(pos);
  covered_statement += statement;
  return covered_statement;
}

void StreamingFlowGraphBuilder::ReportUnexpectedTag(const char* variant,
                                                    Tag tag) {
  if ((flow_graph_builder_ == nullptr) || (parsed_function() == nullptr)) {
    KernelReaderHelper::ReportUnexpectedTag(variant, tag);
  } else {
    const auto& script = Script::Handle(Z, Script());
    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() {
  return reader_.ReadVariance();
}

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

void StreamingFlowGraphBuilder::loop_depth_dec() {
  --flow_graph_builder_->loop_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_;
}

void StreamingFlowGraphBuilder::synthetic_error_handler_depth_inc() {
  ++synthetic_error_handler_depth_;
}

void StreamingFlowGraphBuilder::synthetic_error_handler_depth_dec() {
  --synthetic_error_handler_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_;
}

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

void StreamingFlowGraphBuilder::set_stack(Value* top) {
  flow_graph_builder_->stack_ = top;
}

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

TokenPosition StreamingFlowGraphBuilder::ReadPosition() {
  TokenPosition position = KernelReaderHelper::ReadPosition();
  if (synthetic_error_handler_depth_ > 0 && position.IsReal()) {
    position = TokenPosition::Synthetic(position.Pos());
  }
  return position;
}

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

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

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

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)));
  return Function::Handle(Z, Resolver::ResolveDynamicForReceiverClass(
                                 klass, name, args_desc, /*allow_add=*/false));
}

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

IndirectGotoInstr* StreamingFlowGraphBuilder::IndirectGoto(
    intptr_t target_count) {
  return flow_graph_builder_->IndirectGoto(target_count);
}

Fragment StreamingFlowGraphBuilder::Return(TokenPosition position) {
  return flow_graph_builder_->Return(position,
                                     /*omit_result_type_check=*/false);
}

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

Fragment StreamingFlowGraphBuilder::ThrowNoSuchMethodError(
    TokenPosition position,
    const Function& target,
    bool incompatible_arguments) {
  return flow_graph_builder_->ThrowNoSuchMethodError(position, target,
                                                     incompatible_arguments);
}

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) {
  return flow_graph_builder_->CheckNull(position, receiver, function_name);
}

Fragment StreamingFlowGraphBuilder::StaticCall(TokenPosition position,
                                               const Function& target,
                                               intptr_t argument_count,
                                               ICData::RebindRule rebind_rule) {
  if (!target.AreValidArgumentCounts(0, argument_count, 0, nullptr)) {
    Fragment instructions;
    instructions += DropArguments(argument_count, /*type_args_count=*/0);
    instructions += ThrowNoSuchMethodError(position, target,
                                           /*incompatible_arguments=*/true);
    return instructions;
  }
  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)) {
    Fragment instructions;
    instructions += DropArguments(argument_count, type_args_count);
    instructions += ThrowNoSuchMethodError(position, target,
                                           /*incompatible_arguments=*/true);
    return instructions;
  }
  return flow_graph_builder_->StaticCall(
      position, target, argument_count, argument_names, rebind_rule,
      result_type, type_args_count, use_unchecked_entry);
}

Fragment StreamingFlowGraphBuilder::StaticCallMissing(
    TokenPosition position,
    const String& selector,
    intptr_t argument_count,
    InvocationMirror::Level level,
    InvocationMirror::Kind kind) {
  Fragment instructions;
  instructions += DropArguments(argument_count, /*type_args_count=*/0);
  instructions += flow_graph_builder_->ThrowNoSuchMethodError(
      position, selector, level, kind);
  return instructions;
}

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,
    bool is_call_on_this) {
  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,
      is_call_on_this);
}

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,
    InnerPointerAccess loads_inner_pointer) {
  return flow_graph_builder_->LoadNativeField(field, loads_inner_pointer);
}

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::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->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 B->CatchBlockEntry(handler_types, handler_index, needs_stacktrace,
                            is_synthesized);
}

Fragment StreamingFlowGraphBuilder::TryEntry(int try_handler_index) {
  return B->TryEntry(try_handler_index);
}

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

Fragment StreamingFlowGraphBuilder::DropArguments(intptr_t argument_count,
                                                  intptr_t type_args_count) {
  Fragment instructions;
  for (intptr_t i = 0; i < argument_count; i++) {
    instructions += Drop();
  }
  if (type_args_count != 0) {
    instructions += Drop();
  }
  return instructions;
}

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::CheckArgumentType(
    LocalVariable* variable,
    const AbstractType& type) {
  return flow_graph_builder_->CheckAssignable(
      type, variable->name(), AssertAssignableInstr::kParameterCheck);
}

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

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);
    ReadPosition();
    negate = !negate;
  }

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

    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->NegateCondition();
        negate = false;
      }
      branch =
          new (Z) BranchInstr(compare, flow_graph_builder_->GetNextDeoptId());
      branch->condition()->ClearTempIndex();
      ASSERT(instructions.current->previous() != nullptr);
      instructions.current = instructions.current->previous();
    } else {
      if (NeedsDebugStepCheck(stack(), position)) {
        instructions = DebugStepCheck(position) + instructions;
      }
      instructions += Constant(Bool::True());
      Value* right_value = Pop();
      Value* left_value = Pop();
      StrictCompareInstr* compare = new (Z) StrictCompareInstr(
          InstructionSource(), 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 == nullptr) argument_count = &dummy;
  *argument_count = ReadUInt();  // read arguments count.

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

  {
    AlternativeReadingScope _(&reader_);
    if (positional_count == nullptr) 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 != nullptr && 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 != nullptr) {
      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 != nullptr) *position = pos;
  const String& message = H.DartString(ReadStringReference());
  Tag tag = ReadTag();  // read (first part of) expression.
  if (tag == kSomething) {
    SkipExpression();  // read (rest of) expression.
  }

  // Invalid expression message has pointer to the source code, no need to
  // report it twice.
  const auto& script = Script::Handle(Z, Script());
  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;
  TargetEntryInstr* 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();
      if (variable->is_final()) {
        // Late final variable, so check whether it has been assigned
        // during initialization.
        initialize += LoadLocal(variable);
        TargetEntryInstr* is_uninitialized_after_init;
        TargetEntryInstr* is_initialized_after_init;
        initialize += Constant(Object::sentinel());
        initialize += flow_graph_builder_->BranchIfStrictEqual(
            &is_uninitialized_after_init, &is_initialized_after_init);
        {
          // The variable is uninitialized, so store the initializer result.
          Fragment store_result(is_uninitialized_after_init);
          store_result += StoreLocal(position, variable);
          store_result += Drop();
          store_result += Goto(join);
        }

        {
          // Already initialized, so throw a LateInitializationError.
          Fragment already_assigned(is_initialized_after_init);
          already_assigned += flow_graph_builder_->ThrowLateInitializationError(
              position, "_throwLocalAssignedDuringInitialization",
              variable->name());
          ASSERT(already_assigned.is_closed());
        }
      } else {
        // Late non-final variable. Store the initializer result.
        initialize += StoreLocal(position, variable);
        initialize += Drop();
        initialize += Goto(join);
      }
    } else {
      // The variable has no initializer, so throw a late initialization error.
      Fragment initialize(is_uninitialized);
      initialize += flow_graph_builder_->ThrowLateInitializationError(
          position, "_throwLocalNotInitialized", variable->name());
      ASSERT(initialize.is_closed());
    }
  }

  {
    // 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 != nullptr) *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 != nullptr) *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;
    TargetEntryInstr* 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, "_throwLocalAlreadyInitialized", variable->name());
      ASSERT(already_initialized.is_closed());
    }

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

  return instructions;
}

Fragment StreamingFlowGraphBuilder::BuildInstanceGet(TokenPosition* p) {
  const intptr_t offset = ReaderOffset() - 1;     // Include the tag.
  ReadByte();                                     // read kind.
  const TokenPosition position = ReadPosition();  // read position.
  if (p != nullptr) *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.
  const String& getter_name = ReadNameAsGetterName();  // read name.
  SkipDartType();                                      // read result_type.
  const NameIndex itarget_name =
      ReadInterfaceMemberNameReference();  // read interface_target_reference.
  ASSERT(!H.IsRoot(itarget_name) && H.IsGetter(itarget_name));
  const auto& interface_target = Function::ZoneHandle(
      Z, H.LookupMethodByMember(itarget_name, H.DartGetterName(itarget_name)));
  ASSERT(getter_name.ptr() == interface_target.name());

  if (direct_call.check_receiver_for_null_) {
    auto receiver = MakeTemporary();
    instructions += CheckNull(position, receiver, getter_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, getter_name, Token::kGET, kTypeArgsLen, 1,
                     Array::null_array(), kNumArgsChecked, interface_target,
                     Function::null_function(), &result_type);
  }

  return instructions;
}

Fragment StreamingFlowGraphBuilder::BuildDynamicGet(TokenPosition* p) {
  const intptr_t offset = ReaderOffset() - 1;     // Include the tag.
  ReadByte();                                     // read kind.
  const TokenPosition position = ReadPosition();  // read position.
  if (p != nullptr) *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.
  const String& getter_name = ReadNameAsGetterName();  // read name.
  const auto& mangled_name = String::ZoneHandle(
      Z, Function::CreateDynamicInvocationForwarderName(getter_name));
  const Function* direct_call_target = &direct_call.target_;
  if (!direct_call_target->IsNull()) {
    direct_call_target = &Function::ZoneHandle(
        direct_call.target_.GetDynamicInvocationForwarder(mangled_name));
  }

  if (direct_call.check_receiver_for_null_) {
    auto receiver = MakeTemporary();
    instructions += CheckNull(position, receiver, getter_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, Function::null_function(),
                                 Function::null_function(), &result_type);
  }

  return instructions;
}

Fragment StreamingFlowGraphBuilder::BuildInstanceTearOff(TokenPosition* p) {
  const intptr_t offset = ReaderOffset() - 1;     // Include the tag.
  ReadByte();                                     // read kind.
  const TokenPosition position = ReadPosition();  // read position.
  if (p != nullptr) *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.
  const String& getter_name = ReadNameAsGetterName();  // read name.
  SkipDartType();                                      // read result_type.
  const NameIndex itarget_name =
      ReadInterfaceMemberNameReference();  // read interface_target_reference.
  ASSERT(!H.IsRoot(itarget_name) && H.IsMethod(itarget_name));
  const auto& tearoff_interface_target = Function::ZoneHandle(
      Z, H.LookupMethodByMember(itarget_name, H.DartMethodName(itarget_name)));

  if (direct_call.check_receiver_for_null_) {
    const auto receiver = MakeTemporary();
    instructions += CheckNull(position, receiver, getter_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, getter_name, Token::kGET,
                                 kTypeArgsLen, 1, Array::null_array(),
                                 kNumArgsChecked, Function::null_function(),
                                 tearoff_interface_target, &result_type);
  }

  return instructions;
}

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

  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;

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

  LocalVariable* receiver = nullptr;
  if (direct_call.check_receiver_for_null_) {
    receiver = MakeTemporary();
  }

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

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

  const NameIndex itarget_name =
      ReadInterfaceMemberNameReference();  // read interface_target_reference.
  ASSERT(!H.IsRoot(itarget_name));
  const auto& interface_target = Function::ZoneHandle(
      Z, H.LookupMethodByMember(itarget_name, H.DartSetterName(itarget_name)));
  ASSERT(setter_name.ptr() == interface_target.name());

  if (direct_call.check_receiver_for_null_) {
    instructions += CheckNull(position, receiver, setter_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_len=*/0,
                   /*use_unchecked_entry=*/is_unchecked_call);
  } else {
    const intptr_t kTypeArgsLen = 0;
    const intptr_t kNumArgsChecked = 1;

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

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

  return instructions;
}

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

  const DirectCallMetadata direct_call =
      direct_call_metadata_helper_.GetDirectTargetForPropertySet(offset);
  const InferredTypeMetadata inferred_type =
      inferred_type_metadata_helper_.GetInferredType(offset);

  // True if callee can skip argument type checks.
  const bool is_unchecked_call = inferred_type.IsSkipCheck();

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

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

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

  LocalVariable* receiver = nullptr;
  if (direct_call.check_receiver_for_null_) {
    receiver = MakeTemporary();
  }

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

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

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

  const Function* direct_call_target = &direct_call.target_;
  const auto& 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_len=*/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, Function::null_function(),
        Function::null_function(),
        /*result_type=*/nullptr,
        /*use_unchecked_entry=*/is_unchecked_call, /*call_site_attrs=*/nullptr);
  }

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

  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.ptr());
  if (!iterate_klass.IsNull() &&
      iterate_klass.EnsureIsFinalized(thread) == Error::null()) {
    while (!iterate_klass.IsNull()) {
      nsm_function = Resolver::ResolveDynamicFunction(zone, iterate_klass,
                                                      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.ptr()));

  //   - 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.ptr()));

  //   - 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 != nullptr) *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);
  if (!klass.IsNull() && klass.EnsureIsFinalized(thread()) == Error::null()) {
    while (!klass.IsNull()) {
      function = Resolver::ResolveDynamicFunction(Z, klass, method_name);
      if (!function.IsNull()) {
        Function& target =
            Function::ZoneHandle(Z, function.ImplicitClosureFunction());
        ASSERT(!target.IsNull());
        // Generate inline code for allocation closure object
        // which captures `this`.
        return B->BuildImplicitClosureCreation(position, target);
      }
      function = Resolver::ResolveDynamicFunction(Z, klass, 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.ptr()),
                   /* 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.ptr()),
                   /* 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 != nullptr) *p = position;

  Class& klass = GetSuperOrDie();

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

  Function& function = Function::Handle(Z);
  if (klass.EnsureIsFinalized(thread()) == Error::null()) {
    function = Resolver::ResolveDynamicFunction(Z, 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.ptr()),
                   /* 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.ptr()),
        /* 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::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 != nullptr) *p = position;

  const InferredTypeMetadata result_type =
      inferred_type_metadata_helper_.GetInferredType(offset);

  NameIndex target = ReadCanonicalNameReference();  // read target_reference.
  ASSERT(H.IsGetter(target));

  const Field& field = Field::ZoneHandle(
      Z, H.LookupFieldByKernelGetterOrSetter(target, /*required=*/false));
  if (!field.IsNull()) {
    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().ptr());
      return Constant(Instance::ZoneHandle(
          Z, Instance::RawCast(field.StaticConstFieldValue())));
    } else if (field.is_final() && field.has_trivial_initializer()) {
      // Final fields with trivial initializers are effectively constant.
      return Constant(Instance::ZoneHandle(
          Z, Instance::RawCast(field.StaticConstFieldValue())));
    } 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);
      }
    }
  }

  const Function& function = Function::ZoneHandle(
      Z, H.LookupStaticMethodByKernelProcedure(target, /*required=*/false));
  if (!function.IsNull()) {
    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 StaticCallMissing(
      position, H.DartSymbolPlain(H.CanonicalNameString(target)),
      /* argument_count */ 0,
      H.IsLibrary(H.EnclosingName(target)) ? InvocationMirror::Level::kTopLevel
                                           : InvocationMirror::Level::kStatic,
      InvocationMirror::Kind::kGetter);
}

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

  NameIndex target = ReadCanonicalNameReference();  // read target_reference.
  ASSERT(H.IsSetter(target));

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

  // Look up the target as a setter first and, if not present, as a field
  // second. This order is needed to avoid looking up a final field as the
  // target.
  const Function& function = Function::ZoneHandle(
      Z, H.LookupStaticMethodByKernelProcedure(target, /*required=*/false));

  if (!function.IsNull()) {
    LocalVariable* variable = MakeTemporary();

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

    // Invoke the setter function.
    instructions += StaticCall(position, function, 1, ICData::kStatic);

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

  const Field& field = Field::ZoneHandle(
      Z, H.LookupFieldByKernelGetterOrSetter(target, /*required=*/false));
  if (!field.IsNull()) {
    if (NeedsDebugStepCheck(stack(), position)) {
      instructions = DebugStepCheck(position) + instructions;
    }
    LocalVariable* variable = MakeTemporary();
    instructions += LoadLocal(variable);
    instructions += StoreStaticField(position, field);
    return instructions;
  }

  instructions += StaticCallMissing(
      position, H.DartSymbolPlain(H.CanonicalNameString(target)),
      /* argument_count */ 1,
      H.IsLibrary(H.EnclosingName(target)) ? InvocationMirror::Level::kTopLevel
                                           : InvocationMirror::Level::kStatic,
      InvocationMirror::Kind::kSetter);
  return instructions;
}

Fragment StreamingFlowGraphBuilder::BuildMethodInvocation(TokenPosition* p,
                                                          bool is_dynamic) {
  const intptr_t offset = ReaderOffset() - 1;  // Include the tag.
  ReadByte();                                  // read kind.

  // read flags.
  const uint8_t flags = ReadFlags();
  bool is_invariant = false;
  bool is_implicit_call = false;
  if (is_dynamic) {
    is_implicit_call = (flags & kDynamicInvocationFlagImplicitCall) != 0;
  } else {
    is_invariant = (flags & kInstanceInvocationFlagInvariant) != 0;
  }

  const TokenPosition position = ReadPosition();  // read position.
  if (p != nullptr) *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_call = is_invariant || result_type.IsSkipCheck();
  if (!is_dynamic && (call_site_attributes.receiver_type != nullptr) &&
      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;
  {
    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);
    }
    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.
  const bool is_call_on_this = (PeekTag() == kThisExpression) && !is_dynamic;
  if (is_call_on_this) {
    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(nullptr /* named */, nullptr /* arg count */,
                       nullptr /* 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 = nullptr;
  if (direct_call.check_receiver_for_null_) {
    receiver_temp = MakeTemporary();
  }

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

  if (!is_dynamic) {
    SkipDartType();  // read function_type.
  }

  const Function* interface_target = &Function::null_function();
  // read interface_target_reference.
  const NameIndex itarget_name =
      is_dynamic ? NameIndex() : ReadInterfaceMemberNameReference();
  // 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.IsGetter(itarget_name)) {
    interface_target = &Function::ZoneHandle(
        Z, H.LookupMethodByMember(itarget_name,
                                  H.DartProcedureName(itarget_name)));
    ASSERT(name.ptr() == interface_target->name());
    ASSERT(!interface_target->IsGetterFunction());
  }

  if (direct_call.check_receiver_for_null_) {
    instructions += CheckNull(position, receiver_temp, name);
  }

  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 (is_dynamic && (name.ptr() != Symbols::EqualOperator().ptr())) {
    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_implicit_call) {
      ASSERT(mangled_name->ptr() == Symbols::DynamicCall().ptr());
      mangled_name = &Symbols::DynamicImplicitCall();
    }
  }

  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(), is_call_on_this);
  }

  // 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.ptr() == Symbols::AssignIndexToken().ptr()) {
    instructions += Drop();
    instructions += NullConstant();
  }

  return instructions;
}

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

  const InferredTypeMetadata result_type =
      inferred_type_metadata_helper_.GetInferredType(offset);

  // read variable kernel position.
  const intptr_t variable_kernel_position = ReadUInt();
  ReadUInt();  // read relative variable index.

  LocalVariable* variable = LookupVariable(variable_kernel_position);
  ASSERT(!variable->is_late());

  auto& target_function = Function::ZoneHandle(Z);
  {
    AlternativeReadingScope alt(
        &reader_, variable_kernel_position - data_program_offset_);
    SkipVariableDeclaration();
    // FunctionNode follows the variable declaration.
    const intptr_t function_node_kernel_offset = ReaderOffset();

    target_function = ClosureFunctionsCache::LookupClosureFunction(
        Function::Handle(Z,
                         parsed_function()->function().GetOutermostFunction()),
        function_node_kernel_offset);
    RELEASE_ASSERT(!target_function.IsNull());
  }

  Fragment instructions;

  // Type arguments.
  intptr_t type_args_len = 0;
  {
    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;
  }

  // Receiver (closure).
  instructions += LoadLocal(variable);

  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

  SkipDartType();  // read function_type.

  // Lookup the function in the closure.
  instructions += LoadLocal(variable);
  if (!FLAG_precompiled_mode) {
    instructions += LoadNativeField(Slot::Closure_function());
  }
  if (parsed_function()->function().is_debuggable()) {
    ASSERT(!parsed_function()->function().is_native());
    instructions += DebugStepCheck(position);
  }
  instructions += B->ClosureCall(target_function, position, type_args_len,
                                 argument_count, argument_names, &result_type);
  return instructions;
}

Fragment StreamingFlowGraphBuilder::BuildFunctionInvocation(TokenPosition* p) {
  const intptr_t offset = ReaderOffset() - 1;  // Include the tag.
  const FunctionAccessKind function_access_kind =
      static_cast<FunctionAccessKind>(ReadByte());  // read kind.
  const TokenPosition position = ReadPosition();    // read position.
  if (p != nullptr) *p = position;

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

  RELEASE_ASSERT((function_access_kind == FunctionAccessKind::kFunction) ||
                 (function_access_kind == FunctionAccessKind::kFunctionType));
  const bool is_unchecked_closure_call =
      (function_access_kind == FunctionAccessKind::kFunctionType);
  Fragment instructions;

  instructions += BuildExpression();  // read receiver.
  LocalVariable* receiver_temp = MakeTemporary();

  // Type arguments.
  intptr_t type_args_len = 0;
  {
    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;
  }

  // Receiver (closure).
  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

  SkipDartType();  // read function_type.

  if (is_unchecked_closure_call) {
    instructions += CheckNull(position, receiver_temp, Symbols::call());
    // Lookup the function in the closure.
    instructions += LoadLocal(receiver_temp);
    if (!FLAG_precompiled_mode) {
      instructions += LoadNativeField(Slot::Closure_function());
    }
    if (parsed_function()->function().is_debuggable()) {
      ASSERT(!parsed_function()->function().is_native());
      instructions += DebugStepCheck(position);
    }
    instructions +=
        B->ClosureCall(direct_call.target_, position, type_args_len,
                       argument_count, argument_names, &result_type);
  } else {
    instructions += InstanceCall(
        position, Symbols::DynamicCall(), Token::kILLEGAL, type_args_len,
        argument_count, argument_names, 1, Function::null_function(),
        Function::null_function(), &result_type,
        /*use_unchecked_entry=*/false, /*call_site_attrs=*/nullptr,
        result_type.ReceiverNotInt());
  }
  instructions += DropTempsPreserveTop(1);
  return instructions;
}

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

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

  Fragment instructions;
  instructions += BuildExpression();  // read left.
  instructions += BuildExpression();  // read right.
  SkipDartType();                     // read function_type.

  const NameIndex itarget_name =
      ReadInterfaceMemberNameReference();  // read interface_target_reference.
  const auto& interface_target = Function::ZoneHandle(
      Z,
      H.LookupMethodByMember(itarget_name, H.DartProcedureName(itarget_name)));
  ASSERT(interface_target.name() == Symbols::EqualOperator().ptr());

  const intptr_t kTypeArgsLen = 0;
  const intptr_t kNumArgs = 2;
  const intptr_t kNumCheckedArgs = 2;

  if (!direct_call.target_.IsNull()) {
    ASSERT(CompilerState::Current().is_aot());
    instructions +=
        StaticCall(position, direct_call.target_, kNumArgs, Array::null_array(),
                   ICData::kNoRebind, &result_type, kTypeArgsLen,
                   /*use_unchecked_entry=*/true);
  } else {
    instructions += InstanceCall(
        position, Symbols::EqualOperator(), Token::kEQ, kTypeArgsLen, kNumArgs,
        Array::null_array(), kNumCheckedArgs, interface_target,
        Function::null_function(), &result_type,
        /*use_unchecked_entry=*/true, &call_site_attributes,
        result_type.ReceiverNotInt());
  }

  return instructions;
}

Fragment StreamingFlowGraphBuilder::BuildEqualsNull(TokenPosition* p) {
  const TokenPosition position = ReadPosition();  // read position.
  if (p != nullptr) *p = position;
  Fragment instructions;
  instructions += BuildExpression();  // read expression.
  instructions += NullConstant();
  if (parsed_function()->function().is_debuggable()) {
    instructions += DebugStepCheck(position);
  }
  instructions +=
      StrictCompare(position, Token::kEQ_STRICT, /*number_check=*/false);
  return instructions;
}

Fragment StreamingFlowGraphBuilder::BuildSuperMethodInvocation(
    TokenPosition* p) {
  const intptr_t offset = ReaderOffset() - 1;     // Include the tag.
  const TokenPosition position = ReadPosition();  // read position.
  if (p != nullptr) *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.ptr()),
                               /* 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 = */ nullptr);  // read arguments.
    ++argument_count;                                // include receiver
    SkipInterfaceMemberNameReference();              // interfaceTargetReference
    return instructions +
           StaticCall(position, Function::ZoneHandle(Z, function.ptr()),
                      argument_count, argument_names, ICData::kSuper,
                      &result_type, type_args_len,
                      /*use_unchecked_entry=*/true);
  }
}

Fragment StreamingFlowGraphBuilder::BuildStaticInvocation(TokenPosition* p) {
  const intptr_t offset = ReaderOffset() - 1;  // Include the tag.
  TokenPosition position = ReadPosition();     // read position.
  if (p != nullptr) *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, /*required=*/false));

  if (target.IsNull()) {
    Fragment instructions;
    Array& argument_names = Array::ZoneHandle(Z);
    instructions +=
        BuildArguments(&argument_names, nullptr /* arg count */,
                       nullptr /* positional arg count */);  // read arguments.
    instructions += StaticCallMissing(
        position, H.DartSymbolPlain(H.CanonicalNameString(procedure_reference)),
        argument_count,
        H.IsLibrary(H.EnclosingName(procedure_reference))
            ? InvocationMirror::Level::kTopLevel
            : InvocationMirror::Level::kStatic,
        InvocationMirror::Kind::kMethod);
    return instructions;
  }

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

  if (target.IsCachableIdempotent()) {
    return BuildCachableIdempotentCall(position, target);
  }

  const auto recognized_kind = target.recognized_kind();
  switch (recognized_kind) {
    case MethodRecognizer::kNativeEffect:
      return BuildNativeEffect();
    case MethodRecognizer::kReachabilityFence:
      return BuildReachabilityFence();
    case MethodRecognizer::kFfiCall:
      return BuildFfiCall();
    case MethodRecognizer::kFfiNativeCallbackFunction:
      return BuildFfiNativeCallbackFunction(
          FfiCallbackKind::kIsolateLocalStaticCallback);
    case MethodRecognizer::kFfiNativeAddressOf:
      return BuildFfiNativeAddressOf();
    case MethodRecognizer::kFfiNativeIsolateLocalCallbackFunction:
      return BuildFfiNativeCallbackFunction(
          FfiCallbackKind::kIsolateLocalClosureCallback);
    case MethodRecognizer::kFfiNativeIsolateGroupBoundCallbackFunction:
      return BuildFfiNativeCallbackFunction(
          FfiCallbackKind::kIsolateGroupBoundStaticCallback);
    case MethodRecognizer::kFfiNativeIsolateGroupBoundClosureFunction:
      return BuildFfiNativeCallbackFunction(
          FfiCallbackKind::kIsolateGroupBoundClosureCallback);
    case MethodRecognizer::kFfiNativeAsyncCallbackFunction:
      return BuildFfiNativeCallbackFunction(FfiCallbackKind::kAsyncCallback);
    case MethodRecognizer::kFfiLoadAbiSpecificInt:
      return BuildLoadStoreAbiSpecificInt(/*is_store=*/false,
                                          /*at_index=*/false);
    case MethodRecognizer::kFfiLoadAbiSpecificIntAtIndex:
      return BuildLoadStoreAbiSpecificInt(/*is_store=*/false,
                                          /*at_index=*/true);
    case MethodRecognizer::kFfiStoreAbiSpecificInt:
      return BuildLoadStoreAbiSpecificInt(/*is_store=*/true,
                                          /*at_index=*/false);
    case MethodRecognizer::kFfiStoreAbiSpecificIntAtIndex:
      return BuildLoadStoreAbiSpecificInt(/*is_store=*/true, /*at_index=*/true);
    default:
      break;
  }

  Fragment instructions;
  LocalVariable* instance_variable = nullptr;

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

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

  const bool special_case =
      special_case_identical || special_case_unchecked_cast;

  // 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, nullptr /* arg count */,
                     nullptr /* positional arg count */);  // read arguments.
  ASSERT(!special_case ||
         target.AreValidArguments(type_args_len, argument_count, argument_names,
                                  nullptr));

  // Special case identical(x, y) call.
  // TODO(27590) consider moving this into the inliner and force inline it
  // there.
  if (special_case_identical) {
    ASSERT(argument_count == 2);
    instructions +=
        StrictCompare(position, Token::kEQ_STRICT, /*number_check=*/true);
  } 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();
    }

    // After reaching debugger(), we automatically do one single-step.
    // Ensure this doesn't cause us to exit the current scope.
    if (recognized_kind == MethodRecognizer::kDebugger) {
      instructions += DebugStepCheck(position);
    }
  }

  return instructions;
}

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

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

  Class& klass = Class::ZoneHandle(
      Z, H.LookupClassByKernelClass(H.EnclosingName(kernel_name),
                                    /*required=*/false));
  Fragment instructions;
  if (klass.IsNull()) {
    Array& argument_names = Array::ZoneHandle(Z);
    intptr_t argument_count;
    instructions += BuildArguments(
        &argument_names, &argument_count,
        /* positional_argument_count = */ nullptr);  // read arguments.
    instructions += StaticCallMissing(
        position, H.DartSymbolPlain(H.CanonicalNameString(kernel_name)),
        argument_count, InvocationMirror::Level::kConstructor,
        InvocationMirror::Kind::kMethod);
    return instructions;
  }
  const auto& error = klass.EnsureIsFinalized(H.thread());
  ASSERT(error == Error::null());

  if (klass.NumTypeArguments() > 0) {
    if (!klass.IsGeneric()) {
      const TypeArguments& type_arguments = TypeArguments::ZoneHandle(
          Z, klass.GetDeclarationInstanceTypeArguments());
      instructions += Constant(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 = */ nullptr);  // read arguments.

  const Function& target =
      Function::ZoneHandle(Z, H.LookupConstructorByKernelConstructor(
                                  klass, kernel_name, /*required=*/false));
  ++argument_count;

  if (target.IsNull()) {
    instructions += StaticCallMissing(
        position, H.DartSymbolPlain(H.CanonicalNameString(kernel_name)),
        argument_count, InvocationMirror::Level::kConstructor,
        InvocationMirror::Kind::kMethod);
  } else {
    instructions += StaticCall(position, target, argument_count, argument_names,
                               ICData::kStatic, /* result_type = */ nullptr);
  }
  return instructions + Drop();
}

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

  TokenPosition operand_position = TokenPosition::kNoSource;
  Fragment instructions =
      BuildExpression(&operand_position);  // read expression.
  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());

  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);
    ReadPosition();
    negated = !negated;
  }

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

  if (PeekTag() == kLogicalExpression) {
    SkipBytes(1);
    ReadPosition();
    // 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.
    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* p) {
  TokenPosition position = ReadPosition();
  if (p != nullptr) *p = position;

  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* p) {
  TokenPosition position = ReadPosition();
  if (p != nullptr) *p = position;

  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();
        ReadPosition();
        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::BuildIsTest(TokenPosition position,
                                                const AbstractType& type) {
  Fragment instructions;
  // 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.IsRecordType()) {
      instructions += BuildRecordIsTest(position, RecordType::Cast(type));
      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::BuildRecordIsTest(TokenPosition position,
                                                      const RecordType& type) {
  // Type of a record instance depends on the runtime types of all
  // its fields, so subtype test cache cannot be used for testing
  // record types and runtime call is used.
  // So it is more efficient to test each record field separately
  // without going to runtime.

  Fragment instructions;
  JoinEntryInstr* is_true = BuildJoinEntry();
  JoinEntryInstr* is_false = BuildJoinEntry();
  LocalVariable* instance = MakeTemporary();

  // Test if instance is null.
  if (type.IsNullable()) {
    TargetEntryInstr* is_null;
    TargetEntryInstr* not_null;

    instructions += LoadLocal(instance);
    instructions += BranchIfNull(&is_null, &not_null);
    Fragment(is_null) + Goto(is_true);
    instructions.current = not_null;
  }

  // Test if instance is record.
  {
    TargetEntryInstr* is_record;
    TargetEntryInstr* not_record;

    instructions += LoadLocal(instance);
    instructions += B->LoadClassId();
    instructions += IntConstant(kRecordCid);
    instructions += BranchIfEqual(&is_record, &not_record);
    Fragment(not_record) + Goto(is_false);
    instructions.current = is_record;
  }

  // Test record shape.
  {
    TargetEntryInstr* same_shape;
    TargetEntryInstr* different_shape;

    instructions += LoadLocal(instance);
    instructions += LoadNativeField(Slot::Record_shape());
    instructions += IntConstant(type.shape().AsInt());
    instructions += BranchIfEqual(&same_shape, &different_shape);
    Fragment(different_shape) + Goto(is_false);
    instructions.current = same_shape;
  }

  // Test each record field
  for (intptr_t i = 0, n = type.NumFields(); i < n; ++i) {
    TargetEntryInstr* success;
    TargetEntryInstr* failure;

    instructions += LoadLocal(instance);
    instructions += LoadNativeField(Slot::GetRecordFieldSlot(
        H.thread(), compiler::target::Record::field_offset(i)));
    instructions +=
        BuildIsTest(position, AbstractType::ZoneHandle(Z, type.FieldTypeAt(i)));
    instructions += Constant(Bool::True());
    instructions += BranchIfEqual(&success, &failure);
    Fragment(failure) + Goto(is_false);
    instructions.current = success;
  }

  instructions += Goto(is_true);

  JoinEntryInstr* join = BuildJoinEntry();
  LocalVariable* expr_temp = parsed_function()->expression_temp_var();

  instructions.current = is_true;
  instructions += Constant(Bool::True());
  instructions += StoreLocal(TokenPosition::kNoSource, expr_temp);
  instructions += Drop();
  instructions += Goto(join);

  instructions.current = is_false;
  instructions += Constant(Bool::False());
  instructions += StoreLocal(TokenPosition::kNoSource, expr_temp);
  instructions += Drop();
  instructions += Goto(join);

  instructions.current = join;
  instructions += Drop();  // Instance.
  instructions += LoadLocal(expr_temp);

  return instructions;
}

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

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

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

  instructions += BuildIsTest(position, type);
  return instructions;
}

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

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

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

  const AbstractType& type = T.BuildType();  // read type.
  if (is_unchecked_cast ||
      (type.IsInstantiated() && type.IsTopTypeForSubtyping())) {
    // We already evaluated the operand on the left and just leave it there as
    // the result of unchecked cast or `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 += B->AssertAssignableLoadTypeArguments(
        position, type,
        is_type_error ? Symbols::Empty() : Symbols::InTypeCast(),
        AssertAssignableInstr::kInsertedByFrontend);
  }
  return instructions;
}

Fragment StreamingFlowGraphBuilder::BuildTypeLiteral(TokenPosition* position) {
  TokenPosition pos = ReadPosition();  // read position.
  if (position != nullptr) *position = pos;

  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) {
  ReadPosition();  // ignore file offset.
  if (position != nullptr) *position = TokenPosition::kNoSource;

  return LoadLocal(parsed_function()->receiver_var());
}

Fragment StreamingFlowGraphBuilder::BuildRethrow(TokenPosition* p) {
  TokenPosition position = ReadPosition();  // read position.
  if (p != nullptr) *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 != nullptr) *p = position;

  Fragment instructions;

  const uint8_t flags = ReadByte();
  const bool is_synthetic_error_handler = (flags & kThrowForErrorHandling) != 0;
  if (is_synthetic_error_handler) {
    synthetic_error_handler_depth_inc();
  }

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

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

  if (is_synthetic_error_handler) {
    synthetic_error_handler_depth_dec();
  }

  return instructions;
}

Fragment StreamingFlowGraphBuilder::BuildListLiteral(TokenPosition* p) {
  TokenPosition position = ReadPosition();  // read position.
  if (p != nullptr) *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);

  // List literals up to 8 elements are lowered in the front-end
  // (pkg/vm/lib/transformations/list_literals_lowering.dart)
  const intptr_t kNumSpecializedListLiteralConstructors = 8;
  ASSERT(length > kNumSpecializedListLiteralConstructors);

  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& growable_list_class =
      Class::Handle(Z, Library::LookupCoreClass(Symbols::_GrowableList()));
  ASSERT(!growable_list_class.IsNull());

  const Function& factory_method =
      Function::ZoneHandle(Z, growable_list_class.LookupFunctionAllowPrivate(
                                  Symbols::_GrowableListLiteralFactory()));
  ASSERT(!factory_method.IsNull());

  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 != nullptr) *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::BuildRecordLiteral(TokenPosition* p) {
  const TokenPosition position = ReadPosition();  // read position.
  if (p != nullptr) *p = position;

  // Figure out record shape.
  const intptr_t positional_count = ReadListLength();
  intptr_t named_count = -1;
  const Array* field_names = &Object::empty_array();
  {
    AlternativeReadingScope alt(&reader_);
    for (intptr_t i = 0; i < positional_count; ++i) {
      SkipExpression();
    }
    named_count = ReadListLength();
    if (named_count > 0) {
      Array& names = Array::ZoneHandle(Z, Array::New(named_count, Heap::kOld));
      for (intptr_t i = 0; i < named_count; ++i) {
        String& name =
            H.DartSymbolObfuscate(ReadStringReference());  // read ith name.
        SkipExpression();  // read ith expression.
        names.SetAt(i, name);
      }
      names.MakeImmutable();
      field_names = &names;
    }
  }
  const intptr_t num_fields = positional_count + named_count;
  const RecordShape shape =
      RecordShape::Register(thread(), num_fields, *field_names);
  Fragment instructions;

  if (num_fields == 2 ||
      (num_fields == 3 && AllocateSmallRecordABI::kValue2Reg != kNoRegister)) {
    // Generate specialized allocation for a small number of fields.
    for (intptr_t i = 0; i < positional_count; ++i) {
      instructions += BuildExpression();  // read ith expression.
    }
    ReadListLength();  // read list length.
    for (intptr_t i = 0; i < named_count; ++i) {
      SkipStringReference();              // read ith name.
      instructions += BuildExpression();  // read ith expression.
    }
    SkipDartType();  // read recordType.

    instructions += B->AllocateSmallRecord(position, shape);

    return instructions;
  }

  instructions += B->AllocateRecord(position, shape);
  LocalVariable* record = MakeTemporary();

  // List of positional.
  intptr_t pos = 0;
  for (intptr_t i = 0; i < positional_count; ++i, ++pos) {
    instructions += LoadLocal(record);
    instructions += BuildExpression();  // read ith expression.
    instructions += B->StoreNativeField(
        Slot::GetRecordFieldSlot(thread(),
                                 compiler::target::Record::field_offset(pos)),
        StoreFieldInstr::Kind::kInitializing);
  }

  // List of named.
  ReadListLength();  // read list length.
  for (intptr_t i = 0; i < named_count; ++i, ++pos) {
    SkipStringReference();  // read ith name.
    instructions += LoadLocal(record);
    instructions += BuildExpression();  // read ith expression.
    instructions += B->StoreNativeField(
        Slot::GetRecordFieldSlot(thread(),
                                 compiler::target::Record::field_offset(pos)),
        StoreFieldInstr::Kind::kInitializing);
  }

  SkipDartType();  // read recordType.

  return instructions;
}

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

  Fragment instructions = BuildExpression();  // read receiver.
  const RecordType& record_type =
      RecordType::Cast(T.BuildType());  // read recordType.

  intptr_t field_index = -1;
  const Array& field_names =
      Array::Handle(Z, record_type.GetFieldNames(H.thread()));
  const intptr_t num_positional_fields =
      record_type.NumFields() - field_names.Length();
  if (is_named) {
    const String& field_name = H.DartSymbolObfuscate(ReadStringReference());
    for (intptr_t i = 0, n = field_names.Length(); i < n; ++i) {
      if (field_names.At(i) == field_name.ptr()) {
        field_index = i;
        break;
      }
    }
    ASSERT(field_index >= 0 && field_index < field_names.Length());
    field_index += num_positional_fields;
  } else {
    field_index = ReadUInt();
    ASSERT(field_index < num_positional_fields);
  }

  instructions += B->LoadNativeField(Slot::GetRecordFieldSlot(
      thread(), compiler::target::Record::field_offset(field_index)));
  return instructions;
}

Fragment StreamingFlowGraphBuilder::BuildFunctionExpression() {
  const intptr_t offset = ReaderOffset() - 1;  // Include the tag.
  ReadPosition();                              // read position.
  return BuildFunctionNode(offset);
}

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

  const TokenPosition position = ReadPosition();  // read position.
  if (p != nullptr) *p = position;
  Fragment instructions;
  instructions += EnterScope(offset);
  instructions += BuildVariableDeclaration(nullptr);  // read variable.
  instructions += BuildExpression();                  // read body.
  instructions += ExitScope(offset);
  return instructions;
}

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

  Fragment instructions;

  instructions += EnterScope(offset);

  ReadPosition();                                 // ignore file 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) {
  ReadPosition();  // ignore file offset.
  if (position != nullptr) *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()) {
    const auto& script = Script::Handle(Z, Script());
    H.ReportError(script, TokenPosition::kNoSource,
                  "Integer literal %s is out of range", value.ToCString());
    UNREACHABLE();
  }
  return Constant(integer);
}

Fragment StreamingFlowGraphBuilder::BuildStringLiteral(
    TokenPosition* position) {
  ReadPosition();  // ignore file offset.
  if (position != nullptr) *position = TokenPosition::kNoSource;

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

Fragment StreamingFlowGraphBuilder::BuildIntLiteral(uint8_t payload,
                                                    TokenPosition* position) {
  ReadPosition();  // ignore file offset.
  if (position != nullptr) *position = TokenPosition::kNoSource;

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

Fragment StreamingFlowGraphBuilder::BuildIntLiteral(bool is_negative,
                                                    TokenPosition* position) {
  ReadPosition();  // ignore file offset.
  if (position != nullptr) *position = TokenPosition::kNoSource;

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

Fragment StreamingFlowGraphBuilder::BuildDoubleLiteral(
    TokenPosition* position) {
  ReadPosition();  // ignore file offset.
  if (position != nullptr) *position = TokenPosition::kNoSource;

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

Fragment StreamingFlowGraphBuilder::BuildBoolLiteral(bool value,
                                                     TokenPosition* position) {
  ReadPosition();  // ignore file offset.
  if (position != nullptr) *position = TokenPosition::kNoSource;

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

Fragment StreamingFlowGraphBuilder::BuildNullLiteral(TokenPosition* position) {
  ReadPosition();  // ignore file offset.
  if (position != nullptr) *position = TokenPosition::kNoSource;

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

Fragment StreamingFlowGraphBuilder::BuildFutureNullValue(
    TokenPosition* position) {
  if (position != nullptr) *position = TokenPosition::kNoSource;
  const Class& future = Class::Handle(Z, IG->object_store()->future_class());
  ASSERT(!future.IsNull());
  const auto& error = future.EnsureIsFinalized(thread());
  ASSERT(error == Error::null());
  Function& constructor = Function::ZoneHandle(
      Z, Resolver::ResolveFunction(Z, future, 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();
  } else if (tag == kFileUriConstantExpression) {
    // TODO(alexmarkov): Use file offset together with file uri.
    ReadPosition();
    ReadUInt();
    SkipDartType();
  }
  if (position != nullptr) *position = p;
  const intptr_t constant_index = ReadUInt();
  Fragment result = Constant(
      Object::ZoneHandle(Z, constant_reader_.ReadConstant(constant_index)));
  return result;
}

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

  // Create a copy of the closure.

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

  // Load the target function and context and allocate the closure.
  instructions += LoadLocal(original_closure);
  instructions +=
      flow_graph_builder_->LoadNativeField(Slot::Closure_function());
  instructions += LoadLocal(original_closure);
  instructions += flow_graph_builder_->LoadNativeField(Slot::Closure_context());
  instructions += LoadLocal(original_closure);
  instructions += flow_graph_builder_->LoadNativeField(
      Slot::Closure_instantiator_type_arguments());
  instructions += flow_graph_builder_->AllocateClosure(
      position, /*has_instantiator_type_args=*/true, /*is_generic=*/false,
      /*is_tear_off=*/false);
  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("type_args");

  // 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_->StoreNativeField(
      Slot::Closure_delayed_type_arguments(),
      StoreFieldInstr::Kind::kInitializing);
  instructions += DropTemporary(&type_args_vec);

  // 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_->StoreNativeField(
      Slot::Closure_function_type_arguments(),
      StoreFieldInstr::Kind::kInitializing);

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

  return instructions;
}

Fragment StreamingFlowGraphBuilder::BuildLibraryPrefixAction(
    TokenPosition* position,
    const String& selector) {
  const TokenPosition pos = ReadPosition();  // read position.
  if (position != nullptr) *position = pos;

  const intptr_t dependency_index = ReadUInt();
  const Library& current_library = Library::Handle(
      Z, Class::Handle(Z, parsed_function()->function().Owner()).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(pos, function, 1, ICData::kStatic);
  return instructions;
}

Fragment StreamingFlowGraphBuilder::BuildAwaitExpression(
    TokenPosition* position) {
  ASSERT(parsed_function()->function().IsAsyncFunction() ||
         parsed_function()->function().IsAsyncGenerator());
  Fragment instructions;

  const TokenPosition pos = ReadPosition();  // read file offset.
  if (position != nullptr) *position = pos;

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

  SuspendInstr::StubId stub_id = SuspendInstr::StubId::kAwait;
  if (ReadTag() == kSomething) {
    const AbstractType& type = T.BuildType();  // read runtime check type.
    if (!type.IsType() ||
        !Class::Handle(Z, type.type_class()).IsFutureClass()) {
      FATAL("Unexpected type for runtime check in await: %s", type.ToCString());
    }
    ASSERT(type.IsFinalized());
    const auto& type_args =
        TypeArguments::ZoneHandle(Z, Type::Cast(type).arguments());
    if (!type_args.IsNull()) {
      const auto& type_arg = AbstractType::Handle(Z, type_args.TypeAt(0));
      if (!type_arg.IsTopTypeForSubtyping()) {
        instructions += TranslateInstantiatedTypeArguments(type_args);
        stub_id = SuspendInstr::StubId::kAwaitWithTypeCheck;
      }
    }
  }

  if (NeedsDebugStepCheck(parsed_function()->function(), pos)) {
    instructions += DebugStepCheck(pos);
  }
  instructions += B->Suspend(pos, stub_id);
  return instructions;
}

Fragment StreamingFlowGraphBuilder::BuildFileUriExpression(
    TokenPosition* position) {
  ReadUInt();  // read uri

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

  return BuildExpression(position);  // read expression.
}

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

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

  Fragment instructions;

  instructions += EnterScope(offset);
  const TokenPosition pos = ReadPosition();  // read file offset.
  if (position != nullptr) *position = pos;

  ReadPosition();  // read file end 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(TokenPosition* position) {
  if (!IG->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()) {
      // read ith statement.
      instructions += BuildStatement(i == 0 ? position : nullptr);
    } else {
      SkipStatement();  // read ith statement.
    }
  }
  instructions += ExitScope(offset);

  return instructions;
}

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

  TargetEntryInstr* then;
  TargetEntryInstr* otherwise;

  Fragment instructions;
  instructions += BuildExpression(position);  // read condition.

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

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

  const Class& klass =
      Class::ZoneHandle(Z, Library::LookupCoreClass(Symbols::AssertionError()));
  ASSERT(!klass.IsNull());
  const auto& error = klass.EnsureIsFinalized(thread());
  ASSERT(error == Error::null());

  Fragment otherwise_fragment(otherwise);
  if (CompilerState::Current().is_aot()) {
    // When in AOT, figure out start line, end line, line fragment needed for
    // the message now, because it won't be available at runtime.
    const Function& target = Function::ZoneHandle(
        Z, klass.LookupStaticFunctionAllowPrivate(Symbols::ThrowNewSource()));
    ASSERT(!target.IsNull());

    auto& script = Script::ZoneHandle(Z, Script());

    auto& condition_text = String::ZoneHandle(Z);
    intptr_t from_line = -1, from_column = -1;
    if (script.GetTokenLocation(condition_start_offset, &from_line,
                                &from_column)) {
      // Extract the assertion condition text (if source is available).
      intptr_t to_line, to_column;
      script.GetTokenLocation(condition_end_offset, &to_line, &to_column);
      condition_text =
          script.GetSnippet(from_line, from_column, to_line, to_column);
      condition_text = Symbols::New(thread(), condition_text);
    } else {
      condition_text = Symbols::OptimizedOut().ptr();
    }

    otherwise_fragment += Constant(condition_text);
    otherwise_fragment += Constant(String::ZoneHandle(Z, script.url()));
    otherwise_fragment += IntConstant(from_line);    // line
    otherwise_fragment += IntConstant(from_column);  // 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.
    }
    otherwise_fragment +=
        StaticCall(condition_start_offset, target, 5, ICData::kStatic);
  } else {
    const Function& target = Function::ZoneHandle(
        Z, klass.LookupStaticFunctionAllowPrivate(Symbols::ThrowNew()));
    ASSERT(!target.IsNull());

    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 += Drop();
  ASSERT(otherwise_fragment.is_closed());

  return Fragment(instructions.entry, then);
}

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

  // There can be several 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(position);  // 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) {
  const TokenPosition pos = ReadPosition();  // read position.
  if (position != nullptr) *position = pos;

  intptr_t target_index = ReadUInt();  // read target index.

  TryFinallyBlock* outer_finally = nullptr;
  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(), pos)) {
    instructions += DebugStepCheck(pos);
  }
  instructions +=
      TranslateFinallyFinalizers(outer_finally, target_context_depth);
  if (instructions.is_open()) {
    instructions += Goto(destination);
  }
  return instructions;
}

Fragment StreamingFlowGraphBuilder::BuildWhileStatement(
    TokenPosition* position) {
  loop_depth_inc();
  const TokenPosition pos = ReadPosition();  // read position.
  if (position != nullptr) *position = pos;

  TestFragment condition = TranslateConditionForControl();   // read condition.
  const Fragment body = BuildStatementWithBranchCoverage();  // 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);
    loop += CheckStackOverflow(pos);  // may have non-empty stack
    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(TokenPosition* position) {
  loop_depth_inc();
  const TokenPosition pos = ReadPosition();  // read position.
  if (position != nullptr) *position = pos;

  Fragment body = BuildStatementWithBranchCoverage();  // read body.

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

  TestFragment condition = TranslateConditionForControl();

  JoinEntryInstr* join = BuildJoinEntry();
  Fragment loop(join);
  loop += CheckStackOverflow(pos);  // may have non-empty stack
  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(TokenPosition* position) {
  intptr_t offset = ReaderOffset() - 1;  // Include the tag.

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

  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(nullptr);  // 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 += BuildStatementWithBranchCoverage();  // 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(pos);  // 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::BuildSwitchStatement(
    TokenPosition* position) {
  const TokenPosition pos = ReadPosition();  // read position.
  if (position != nullptr) *position = pos;
  const bool is_exhaustive = ReadBool();  // read exhaustive flag.

  // We need the number of cases. So start by getting that, then go back.
  const intptr_t offset = ReaderOffset();
  SkipExpression();                        // temporarily skip condition
  SkipOptionalDartType();                  // temporarily skip expression type
  intptr_t case_count = ReadListLength();  // read number of cases.
  SetOffset(offset);

  SwitchBlock block(flow_graph_builder_, case_count);

  Fragment instructions = BuildExpression();  // read condition.
  const AbstractType* expression_type = &Object::dynamic_type();
  if (ReadTag() == kSomething) {
    expression_type = &T.BuildType();  // read expression type.
  }
  instructions +=
      StoreLocal(TokenPosition::kNoSource, scopes()->switch_variable);
  instructions += Drop();

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

  SwitchHelper helper(Z, pos, is_exhaustive, *expression_type, &block,
                      case_count);

  // Build the case bodies and collect the expressions into the helper
  // for the next step.
  for (intptr_t i = 0; i < case_count; ++i) {
    helper.AddCaseBody(BuildSwitchCase(&helper, i));
  }

  // Build the code to dispatch to the case bodies.
  switch (helper.SelectDispatchStrategy()) {
    case kSwitchDispatchAuto:
      UNREACHABLE();
    case kSwitchDispatchLinearScan:
      instructions += BuildLinearScanSwitch(&helper);
      break;
    case kSwitchDispatchBinarySearch:
      instructions += BuildBinarySearchSwitch(&helper);
      break;
    case kSwitchDispatchJumpTable:
      instructions += BuildJumpTableSwitch(&helper);
      break;
  }

  return instructions;
}

Fragment StreamingFlowGraphBuilder::BuildSwitchCase(SwitchHelper* helper,
                                                    intptr_t case_index) {
  // Generate case body and try to find out whether the body will be target
  // of a jump due to:
  //   * `continue case_label`
  //   * `case e1: case e2: body`
  //
  // Also collect switch expressions into helper.

  ReadPosition();                                 // read file offset.
  const int expression_count = ReadListLength();  // read number of expressions.
  for (intptr_t j = 0; j < expression_count; ++j) {
    const TokenPosition pos = ReadPosition();  // read jth position.
    // read jth expression.
    const Instance& value =
        Instance::ZoneHandle(Z, constant_reader_.ReadConstantExpression());
    helper->AddExpression(case_index, pos, value);
  }

  const bool is_default = ReadBool();  // read is_default.
  if (is_default) helper->set_default_case(case_index);
  Fragment body_fragment = BuildStatementWithBranchCoverage();  // read body.

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

  if (!is_default && body_fragment.is_open() &&
      (case_index < (helper->case_count() - 1))) {
    body_fragment += B->Stop("Unreachable end of case");
  }

  // 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) {
    helper->switch_block()->DestinationDirect(case_index);
  }

  return body_fragment;
}

Fragment StreamingFlowGraphBuilder::BuildLinearScanSwitch(
    SwitchHelper* helper) {
  // Build a switch using a sequence of equality tests.
  //
  // From a test:
  // * 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.

  SwitchBlock* block = helper->switch_block();
  const intptr_t case_count = helper->case_count();
  const intptr_t default_case = helper->default_case();
  const GrowableArray<Fragment>& case_bodies = helper->case_bodies();
  Fragment current_instructions;
  intptr_t expression_index = 0;

  for (intptr_t i = 0; i < case_count; ++i) {
    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 += case_bodies[i];
      } else {
        current_instructions += case_bodies[i];
      }
    } else {
      JoinEntryInstr* body_join = nullptr;
      if (block->HadJumper(i)) {
        body_join = block->DestinationDirect(i);
        case_bodies[i] = Fragment(body_join) + case_bodies[i];
      }

      const intptr_t expression_count = helper->case_expression_counts().At(i);
      for (intptr_t j = 0; j < expression_count; ++j) {
        TargetEntryInstr* then;
        TargetEntryInstr* otherwise;

        const SwitchExpression& expression =
            helper->expressions().At(expression_index++);
        current_instructions += Constant(expression.value());
        current_instructions += LoadLocal(scopes()->switch_variable);
        current_instructions += InstanceCall(
            expression.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 != nullptr) {
          // 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 single branch to the body, so we will just append
          // the body fragment.
          then_fragment += case_bodies[i];
        }

        current_instructions = Fragment(current_instructions.entry, otherwise);
      }
    }
  }

  if (case_count > 0 && !helper->has_default()) {
    // 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 = case_bodies[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(current_instructions.entry, 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.
  }

  return current_instructions;
}

Fragment StreamingFlowGraphBuilder::BuildOptimizedSwitchPrelude(
    SwitchHelper* helper,
    JoinEntryInstr* join) {
  const TokenPosition pos = helper->position();
  Fragment instructions;

  if (helper->is_enum_switch()) {
    // For an enum switch, we need to load the enum index from the switch
    // variable.

    instructions += LoadLocal(scopes()->switch_variable);
    const Field& enum_index_field =
        Field::ZoneHandle(Z, IG->object_store()->enum_index_field());
    instructions += B->LoadField(enum_index_field, /*calls_initializer=*/false);
    instructions += StoreLocal(pos, scopes()->switch_variable);
    instructions += Drop();
  }

  return instructions;
}

Fragment StreamingFlowGraphBuilder::BuildBinarySearchSwitch(
    SwitchHelper* helper) {
  // * We build a binary tree of conditional branches where each branch bisects
  //   the remaining cases.
  //   * At holes in the switch expression range we need to add additional
  //     bound checks.
  // * At each leaf we add the body of the case or a goto, if the case has
  //   jumpers.
  //   * Leafs at the bounds of the switch expression range might need to
  //     do a bound check.

  SwitchBlock* block = helper->switch_block();
  const intptr_t case_count = helper->case_count();
  const intptr_t default_case = helper->default_case();
  const GrowableArray<Fragment>& case_bodies = helper->case_bodies();
  const intptr_t expression_count = helper->expressions().length();
  const GrowableArray<SwitchExpression*>& sorted_expressions =
      helper->sorted_expressions();
  TargetEntryInstr* then_entry;
  TargetEntryInstr* otherwise_entry;

  // Entry to the default case or the exit of the switch, if there is no
  // default case.
  JoinEntryInstr* join;
  if (helper->has_default()) {
    join = block->DestinationDirect(default_case);
  } else {
    join = BuildJoinEntry();
  }

  Fragment join_instructions(join);
  if (helper->has_default()) {
    join_instructions += case_bodies.At(default_case);
  }

  Fragment current_instructions = BuildOptimizedSwitchPrelude(helper, join);

  GrowableArray<SwitchRange> stack;
  stack.Add(SwitchRange::Branch(0, expression_count - 1, current_instructions));

  while (!stack.is_empty()) {
    const SwitchRange range = stack.RemoveLast();
    Fragment branch_instructions = range.branch_instructions();

    if (range.is_leaf()) {
      const intptr_t expression_index = range.min();
      const SwitchExpression& expression =
          *sorted_expressions.At(expression_index);

      if (!range.is_bounds_checked() &&
          ((helper->RequiresLowerBoundCheck() && expression_index == 0) ||
           (helper->RequiresUpperBoundCheck() &&
            expression_index == expression_count - 1))) {
        // This leaf needs a bound check.

        branch_instructions += LoadLocal(scopes()->switch_variable);
        branch_instructions += Constant(expression.integer());
        branch_instructions +=
            StrictCompare(expression.position(), Token::kEQ_STRICT,
                          /*number_check=*/true);
        branch_instructions +=
            BranchIfTrue(&then_entry, &otherwise_entry, /*negate=*/false);

        Fragment otherwise_instructions(otherwise_entry);
        otherwise_instructions += Goto(join);

        stack.Add(SwitchRange::Leaf(expression_index, Fragment(then_entry),
                                    /*is_bounds_checked=*/true));
      } else {
        // We are at a leaf where we can add the body of the case or a goto to
        // [join].

        const intptr_t case_index = expression.case_index();

        if (case_index == default_case) {
          branch_instructions += Goto(join);
        } else {
          if (block->HadJumper(case_index)) {
            JoinEntryInstr* join = block->DestinationDirect(case_index);
            branch_instructions += Goto(join);

            if (join->next() == nullptr) {
              // The first time we reach an expression that jumps to a case
              // body we emit the body.
              branch_instructions = Fragment(join);
              branch_instructions += case_bodies.At(case_index);
            }
          } else {
            branch_instructions += case_bodies.At(case_index);
          }

          if (!helper->has_default() && case_index == case_count - 1) {
            if (branch_instructions.is_open()) {
              branch_instructions += Goto(join);
            }
          }
        }

        ASSERT(branch_instructions.is_closed());
      }
    } else {
      // Add a conditional to bisect the range.

      const intptr_t middle = range.min() + (range.max() - range.min()) / 2;
      const intptr_t next = middle + 1;
      const SwitchExpression& middle_expression =
          *sorted_expressions.At(middle);
      const SwitchExpression& next_expression = *sorted_expressions.At(next);

      branch_instructions += LoadLocal(scopes()->switch_variable);
      branch_instructions += Constant(middle_expression.integer());
      branch_instructions +=
          B->IntRelationalOp(middle_expression.position(), Token::kLTE);
      branch_instructions +=
          BranchIfTrue(&then_entry, &otherwise_entry, /*negate=*/false);

      Fragment lower_branch_instructions(then_entry);
      Fragment upper_branch_instructions(otherwise_entry);

      if (next_expression.integer().Value() >
          middle_expression.integer().Value() + 1) {
        // The upper branch is not contiguous with the lower branch.
        // Before continuing in the upper branch we add a bound check.

        upper_branch_instructions += LoadLocal(scopes()->switch_variable);
        upper_branch_instructions += Constant(next_expression.integer());
        upper_branch_instructions +=
            B->IntRelationalOp(next_expression.position(), Token::kGTE);
        upper_branch_instructions +=
            BranchIfTrue(&then_entry, &otherwise_entry, /*negate=*/false);

        Fragment otherwise_instructions(otherwise_entry);
        otherwise_instructions += Goto(join);

        upper_branch_instructions = Fragment(then_entry);
      }

      stack.Add(
          SwitchRange::Branch(next, range.max(), upper_branch_instructions));
      stack.Add(
          SwitchRange::Branch(range.min(), middle, lower_branch_instructions));
    }

    if (current_instructions.is_empty()) {
      current_instructions = branch_instructions;
    }
  }

  return Fragment(current_instructions.entry, join_instructions.current);
}

Fragment StreamingFlowGraphBuilder::BuildJumpTableSwitch(SwitchHelper* helper) {
  // * If input value is not integer or enum value, goto default case or
  //   switch exit.
  // * If value is enum value, load its index.
  // * If input integer is outside of jump table range, goto default case
  //   or switch exit.
  // * Jump to case with jump table.
  //     * For each expression, add entry to jump to case.
  //     * For each hole in the integer range, add entry to jump to default
  //       cause or switch exit.

  SwitchBlock* block = helper->switch_block();
  const TokenPosition pos = helper->position();
  const intptr_t case_count = helper->case_count();
  const intptr_t default_case = helper->default_case();
  const GrowableArray<Fragment>& case_bodies = helper->case_bodies();
  const Integer& expression_min = helper->expression_min();
  const Integer& expression_max = helper->expression_max();
  TargetEntryInstr* then_entry;
  TargetEntryInstr* otherwise_entry;

  // Entry to the default case or the exit of the switch, if there is no
  // default case.
  JoinEntryInstr* join;
  if (helper->has_default()) {
    join = block->DestinationDirect(default_case);
  } else {
    join = BuildJoinEntry();
  }

  Fragment join_instructions(join);

  Fragment current_instructions = BuildOptimizedSwitchPrelude(helper, join);

  if (helper->RequiresLowerBoundCheck()) {
    current_instructions += LoadLocal(scopes()->switch_variable);
    current_instructions += Constant(expression_min);
    current_instructions += B->IntRelationalOp(pos, Token::kGTE);
    current_instructions += BranchIfTrue(&then_entry, &otherwise_entry,
                                         /*negate=*/false);
    Fragment otherwise_instructions(otherwise_entry);
    otherwise_instructions += Goto(join);

    current_instructions = Fragment(current_instructions.entry, then_entry);
  }

  if (helper->RequiresUpperBoundCheck()) {
    current_instructions += LoadLocal(scopes()->switch_variable);
    current_instructions += Constant(expression_max);
    current_instructions += B->IntRelationalOp(pos, Token::kLTE);
    current_instructions += BranchIfTrue(&then_entry, &otherwise_entry,
                                         /*negate=*/false);
    Fragment otherwise_instructions(otherwise_entry);
    otherwise_instructions += Goto(join);

    current_instructions = Fragment(current_instructions.entry, then_entry);
  }

  current_instructions += LoadLocal(scopes()->switch_variable);

  if (expression_min.Value() != 0) {
    // Adjust for the range of the jump table, which starts at 0.
    current_instructions += Constant(expression_min);
    current_instructions +=
        InstanceCall(pos, Symbols::Minus(), Token::kSUB, /*argument_count=*/2,
                     /*checked_argument_count=*/2);
  }

  const intptr_t table_size = helper->ExpressionRange();
  IndirectGotoInstr* indirect_goto = IndirectGoto(table_size);
  current_instructions <<= indirect_goto;
  current_instructions = current_instructions.closed();

  GrowableArray<TargetEntryInstr*> table_entries(table_size);
  table_entries.FillWith(nullptr, 0, table_size);

  // Generate the jump table entries for the switch cases.
  intptr_t expression_index = 0;
  for (intptr_t i = 0; i < case_count; ++i) {
    const int expression_count = helper->case_expression_counts().At(i);

    // Generate jump table entries for each case expression.
    if (i != default_case) {
      for (intptr_t j = 0; j < expression_count; ++j) {
        const SwitchExpression& expression =
            helper->expressions().At(expression_index++);
        const intptr_t table_offset =
            expression.integer().Value() - expression_min.Value();

        IndirectEntryInstr* indirect_entry =
            B->BuildIndirectEntry(table_offset, CurrentTryIndex());
        Fragment indirect_entry_instructions(indirect_entry);
        indirect_entry_instructions += Goto(block->DestinationDirect(i));

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

        table_entries[table_offset] = entry;
      }
    }

    // Connect the case body to its join entry.
    if (i == default_case) {
      join_instructions += case_bodies.At(i);
    } else {
      Fragment case_instructions(block->DestinationDirect(i));
      case_instructions += case_bodies.At(i);

      if (i == case_count - 1) {
        // If the last case is not the default case and it is still open
        // close it by going to the exit of the switch.
        if (case_instructions.is_open()) {
          case_instructions += Goto(join);
        }
      }

      ASSERT(case_instructions.is_closed());
    }
  }

  // Generate the jump table entries for holes in the integer range.
  for (intptr_t i = 0; i < table_size; i++) {
    if (table_entries.At(i) == nullptr) {
      IndirectEntryInstr* indirect_entry =
          B->BuildIndirectEntry(i, CurrentTryIndex());
      Fragment indirect_entry_instructions(indirect_entry);
      indirect_entry_instructions += Goto(join);

      TargetEntryInstr* entry = flow_graph_builder_->BuildTargetEntry();
      Fragment entry_instructions(entry);
      entry_instructions += Goto(indirect_entry);

      table_entries[i] = entry;
    }
  }

  // Add the jump table entries to the jump table.
  for (intptr_t i = 0; i < table_size; i++) {
    indirect_goto->AddSuccessor(table_entries.At(i));
  }

  return Fragment(current_instructions.entry, join_instructions.current);
}

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

  intptr_t target_index = ReadUInt();  // read target index.

  TryFinallyBlock* outer_finally = nullptr;
  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(), pos)) {
      instructions += DebugStepCheck(pos);
    }
    instructions += Goto(entry);
  }
  return instructions;
}

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

  TestFragment condition = TranslateConditionForControl();

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

  Fragment otherwise_fragment(
      condition.CreateFalseSuccessor(flow_graph_builder_));
  otherwise_fragment += BuildStatementWithBranchCoverage();  // 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) {
  const TokenPosition pos = ReadPosition();  // read position.
  if (position != nullptr) *position = pos;

  Tag tag = ReadTag();  // read first part of expression.

  bool inside_try_finally = try_finally_block() != nullptr;

  Fragment instructions;
  if (parsed_function()->function().IsSyncGenerator()) {
    // Return false from sync* function to indicate the end of iteration.
    instructions += Constant(Bool::False());
    if (tag != kNothing) {
      ASSERT(PeekTag() == kNullLiteral);
      SkipExpression();
    }
  } else {
    instructions +=
        (tag == kNothing ? NullConstant()
                         : BuildExpression());  // read rest of expression.
  }

  if (instructions.is_open()) {
    if (inside_try_finally) {
      LocalVariable* const finally_return_variable =
          scopes()->finally_return_variable;
      ASSERT(finally_return_variable != nullptr);
      const Function& function = parsed_function()->function();
      if (NeedsDebugStepCheck(function, pos)) {
        instructions += DebugStepCheck(pos);
      }
      instructions += StoreLocal(pos, finally_return_variable);
      instructions += Drop();
      const intptr_t target_context_depth =
          finally_return_variable->is_captured()
              ? finally_return_variable->owner()->context_level()
              : -1;
      instructions += TranslateFinallyFinalizers(nullptr, target_context_depth);
      if (instructions.is_open()) {
        const intptr_t saved_context_depth = B->context_depth_;
        if (finally_return_variable->is_captured()) {
          B->context_depth_ = target_context_depth;
        }
        instructions += LoadLocal(finally_return_variable);
        instructions += Return(TokenPosition::kNoSource);
        B->context_depth_ = saved_context_depth;
      }
    } else {
      instructions += Return(pos);
    }
  } else {
    Pop();
  }

  return instructions;
}

Fragment StreamingFlowGraphBuilder::BuildTryCatch(TokenPosition* position) {
  ASSERT(block_expression_depth() == 0);  // no try-catch in block-expr
  InlineBailout("kernel::FlowgraphBuilder::VisitTryCatch");

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

  // [try entry, try_body=B1, catch=B3]
  // B1: [try body, try_index = <n>]
  //   goto B2
  // B3: [catch entry, try_handler_index = <n>]
  //   goto B2
  // B2: [join]
  //   ...
  intptr_t try_handler_index = AllocateTryIndex();
  Fragment try_body = TryEntry(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 += BuildStatementWithBranchCoverage(position);  // 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 pos = 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 += BuildStatementWithBranchCoverage();  // 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(pos, 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(TokenPosition* position) {
  // 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");

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

  // 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 = TryEntry(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 += BuildStatementWithBranchCoverage(position);  // 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 += BuildStatementWithBranchCoverage();  // 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);

  // Try/finally might occur in control flow collections with non-empty
  // expression stack (via desugaring of 'await for'). Note that catch-block
  // generated for finally always throws so there is no merge.
  // Save and reset expression stack around catch body in order to maintain
  // correct stack depth, as catch entry drops expression stack.
  Value* const saved_stack_top = stack();
  set_stack(nullptr);

  finally_body += BuildStatementWithBranchCoverage();  // read finalizer
  if (finally_body.is_open()) {
    finally_body += LoadLocal(CurrentException());
    finally_body += LoadLocal(CurrentStackTrace());
    finally_body +=
        RethrowException(TokenPosition::kNoSource, try_handler_index);
    Drop();
  }

  ASSERT(stack() == nullptr);
  set_stack(saved_stack_top);
  catch_depth_dec();

  return Fragment(try_body.entry, after_try);
}

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

  const uint8_t flags = ReadByte();  // read flags.

  Fragment instructions;
  const bool is_yield_star = (flags & kYieldStatementFlagYieldStar) != 0;

  // Load :suspend_state variable using low-level FP-relative load
  // in order to avoid confusing SSA construction (which cannot
  // track its value as it is modified implicitly by stubs).
  LocalVariable* suspend_state = parsed_function()->suspend_state_var();
  ASSERT(suspend_state != nullptr);
  instructions += IntConstant(0);
  instructions += B->LoadFpRelativeSlot(
      compiler::target::frame_layout.FrameSlotForVariable(suspend_state) *
          compiler::target::kWordSize,
      CompileType::Dynamic(), kTagged);
  instructions += LoadNativeField(Slot::SuspendState_function_data());

  instructions += BuildExpression();  // read expression.
  if (NeedsDebugStepCheck(parsed_function()->function(), pos)) {
    instructions += DebugStepCheck(pos);
  }

  if (parsed_function()->function().IsAsyncGenerator()) {
    // In the async* functions, generate the following code for yield <expr>:
    //
    // _AsyncStarStreamController controller = :suspend_state._functionData;
    // if (controller.add(<expr>)) {
    //   return;
    // }
    // if (suspend()) {
    //   return;
    // }
    //
    // Generate the following code for yield* <expr>:
    //
    // _AsyncStarStreamController controller = :suspend_state._functionData;
    // if (controller.addStream(<expr>)) {
    //   return;
    // }
    // if (suspend()) {
    //   return;
    // }
    //

    auto& add_method = Function::ZoneHandle(Z);
    if (is_yield_star) {
      add_method =
          IG->object_store()->async_star_stream_controller_add_stream();
    } else {
      add_method = IG->object_store()->async_star_stream_controller_add();
    }
    instructions +=
        StaticCall(TokenPosition::kNoSource, add_method, 2, ICData::kNoRebind);

    TargetEntryInstr *return1, *continue1;
    instructions += BranchIfTrue(&return1, &continue1, false);
    JoinEntryInstr* return_join = BuildJoinEntry();
    Fragment(return1) + Goto(return_join);
    instructions = Fragment(instructions.entry, continue1);

    // Suspend and test value passed to the resumed async* body.
    instructions += NullConstant();
    instructions += B->Suspend(pos, SuspendInstr::StubId::kYieldAsyncStar);

    TargetEntryInstr *return2, *continue2;
    instructions += BranchIfTrue(&return2, &continue2, false);
    Fragment(return2) + Goto(return_join);
    instructions = Fragment(instructions.entry, continue2);

    Fragment do_return(return_join);
    do_return += TranslateFinallyFinalizers(nullptr, -1);
    do_return += NullConstant();
    do_return += Return(TokenPosition::kNoSource);

  } else if (parsed_function()->function().IsSyncGenerator()) {
    // In the sync* functions, generate the following code for yield <expr>:
    //
    // _SyncStarIterator iterator = :suspend_state._functionData;
    // iterator._current = <expr>;
    // suspend();
    //
    // Generate the following code for yield* <expr>:
    //
    // _SyncStarIterator iterator = :suspend_state._functionData;
    // iterator._yieldStarIterable = <expr>;
    // suspend();
    //
    auto& field = Field::ZoneHandle(Z);
    if (is_yield_star) {
      field = IG->object_store()->sync_star_iterator_yield_star_iterable();
    } else {
      field = IG->object_store()->sync_star_iterator_current();
    }
    instructions += B->StoreFieldGuarded(field);
    instructions += B->Constant(Bool::True());
    instructions +=
        B->Suspend(pos, SuspendInstr::StubId::kSuspendSyncStarAtYield);
    instructions += Drop();
  } else {
    UNREACHABLE();
  }

  return instructions;
}

Fragment StreamingFlowGraphBuilder::BuildVariableDeclaration(
    TokenPosition* position) {
  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 {
    // 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.
  const TokenPosition debug_position = helper.equals_position_.IsReal()
                                           ? helper.equals_position_
                                           : helper.position_;
  if (position != nullptr) *position = helper.position_;
  if (debug_position.IsDebugPause() && !helper.IsHoisted() &&
      // We always make it possible to add a breakpoint on the equals sign if it
      // exists.
      (helper.equals_position_.IsReal() ||
       NeedsDebugStepCheck(stack(), debug_position))) {
    instructions = DebugStepCheck(debug_position) + instructions;
  }
  instructions += StoreLocal(helper.position_, variable);
  instructions += Drop();
  return instructions;
}

Fragment StreamingFlowGraphBuilder::BuildFunctionDeclaration(
    TokenPosition* position) {
  const intptr_t offset = ReaderOffset() - 1;  // Include the tag.
  const TokenPosition pos = ReadPosition();
  if (position != nullptr) *position = pos;

  const intptr_t variable_offset = ReaderOffset() + data_program_offset_;
  SkipVariableDeclaration();

  Fragment instructions = DebugStepCheck(pos);
  instructions += BuildFunctionNode(offset);
  instructions += StoreLocal(pos, LookupVariable(variable_offset));
  instructions += Drop();
  return instructions;
}

Fragment StreamingFlowGraphBuilder::BuildFunctionNode(
    intptr_t func_decl_offset) {
  const intptr_t func_node_offset = ReaderOffset();
  const auto& member_function =
      Function::Handle(Z, parsed_function()->function().GetOutermostFunction());
  const Function& function = Function::ZoneHandle(
      Z, KernelLoader::GetClosureFunction(
             thread(), func_decl_offset, member_function,
             parsed_function()->function(), closure_owner_));

  if (function.context_scope() == ContextScope::null()) {
    SafepointWriteRwLocker ml(thread(),
                              thread()->isolate_group()->program_lock());
    if (function.context_scope() == ContextScope::null()) {
      for (intptr_t i = 0; i < scopes()->function_scopes.length(); ++i) {
        if (scopes()->function_scopes[i].kernel_offset !=
            function.kernel_offset()) {
          continue;
        }

        LocalScope* scope = scopes()->function_scopes[i].scope;
        const ContextScope& context_scope = ContextScope::Handle(
            Z, scope->PreserveOuterScope(function,
                                         flow_graph_builder_->context_depth_));
        function.set_context_scope(context_scope);
      }
    }
  }

  ASSERT(function.kernel_offset() == func_node_offset);
  SkipFunctionNode();

  Fragment instructions;
  instructions += Constant(function);
  if (scopes()->IsClosureWithEmptyContext(func_node_offset)) {
    instructions += NullConstant();
  } else {
    instructions += LoadLocal(parsed_function()->current_context_var());
  }
  // The function signature can have uninstantiated class type parameters.
  const bool has_instantiator_type_args =
      !function.HasInstantiatedSignature(kCurrentClass);
  if (has_instantiator_type_args) {
    instructions += LoadInstantiatorTypeArguments();
  }
  instructions += flow_graph_builder_->AllocateClosure(
      function.token_pos(), has_instantiator_type_args, function.IsGeneric(),
      /*is_tear_off=*/false);
  LocalVariable* closure = MakeTemporary();

  // 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_->StoreNativeField(
      Slot::Closure_function_type_arguments(),
      StoreFieldInstr::Kind::kInitializing);

  return instructions;
}

Fragment StreamingFlowGraphBuilder::BuildNativeEffect() {
  const intptr_t argc = ReadUInt();  // Read argument count.
  ASSERT(argc == 1);                 // Native side effect to ignore.
  const intptr_t list_length = ReadListLength();  // Read types list length.
  ASSERT(list_length == 0);

  const intptr_t positional_count =
      ReadListLength();  // Read positional argument count.
  ASSERT(positional_count == 1);

  BuildExpression();  // Consume expression but don't save the fragment.
  Pop();              // Restore the stack.

  const intptr_t named_args_len =
      ReadListLength();  // Skip empty named arguments.
  ASSERT(named_args_len == 0);

  Fragment code;
  code += NullConstant();  // Return type is void.
  return code;
}

Fragment StreamingFlowGraphBuilder::BuildReachabilityFence() {
  const intptr_t argc = ReadUInt();               // Read argument count.
  ASSERT(argc == 1);                              // LoadField, can be late.
  const intptr_t list_length = ReadListLength();  // Read types list length.
  ASSERT(list_length == 0);

  const intptr_t positional_count = ReadListLength();
  ASSERT(positional_count == 1);

  // The CFE transform only generates a subset of argument expressions:
  // either variable get or `this`. However, subsequent transforms can
  // generate different expressions, including: constant expressions.
  // So, build an arbitrary expression here instead.
  TokenPosition* position = nullptr;
  Fragment code = BuildExpression(position);

  const intptr_t named_args_len = ReadListLength();
  ASSERT(named_args_len == 0);

  code <<= new (Z) ReachabilityFenceInstr(Pop());
  code += NullConstant();  // Return type is void.
  return code;
}

static void ReportIfNotNull(const char* error) {
  if (error != nullptr) {
    const auto& language_error = Error::Handle(
        LanguageError::New(String::Handle(String::New(error, Heap::kOld)),
                           Report::kError, Heap::kOld));
    Report::LongJump(language_error);
  }
}

Fragment StreamingFlowGraphBuilder::BuildLoadStoreAbiSpecificInt(
    bool is_store,
    bool at_index) {
  const intptr_t argument_count = ReadUInt();  // Read argument count.
  const intptr_t expected_argument_count = 2   // TypedDataBase, offset
                                           + (at_index ? 1 : 0)   // index
                                           + (is_store ? 1 : 0);  // value
  ASSERT_EQUAL(argument_count, expected_argument_count);
  const intptr_t list_length = ReadListLength();
  ASSERT_EQUAL(list_length, 1);
  // Read types.
  const TypeArguments& type_arguments = T.BuildTypeArguments(list_length);
  const AbstractType& type_argument =
      AbstractType::Handle(type_arguments.TypeAt(0));

  // AbiSpecificTypes can have an incomplete mapping.
  const char* error = nullptr;
  const auto* native_type =
      compiler::ffi::NativeType::FromAbstractType(zone_, type_argument, &error);
  ReportIfNotNull(error);

  Fragment code;
  // Read positional argument count.
  const intptr_t positional_count = ReadListLength();
  ASSERT(positional_count == argument_count);
  code += BuildExpression();  // Argument 1: typedDataBase.
  code += BuildExpression();  // Argument 2: offsetInBytes
  if (at_index) {
    code += BuildExpression();  // Argument 3: index
    code += IntConstant(native_type->SizeInBytes());
    code += B->BinaryIntegerOp(Token::kMUL, kTagged, /*is_truncating=*/true);
    code += B->BinaryIntegerOp(Token::kADD, kTagged, /*is_truncating=*/true);
  }
  if (is_store) {
    code += BuildExpression();  // Argument 4: value
  }

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

  // This call site is not guaranteed to be optimized. So, do a call to the
  // correct force optimized function instead of compiling the body.
  MethodRecognizer::Kind kind;
  if (is_store) {
    kind = compiler::ffi::FfiStore(*native_type);
  } else {
    kind = compiler::ffi::FfiLoad(*native_type);
  }
  const char* function_name = MethodRecognizer::KindToFunctionNameCString(kind);
  const Library& ffi_library = Library::Handle(Z, Library::FfiLibrary());
  const Function& target = Function::ZoneHandle(
      Z, ffi_library.LookupFunctionAllowPrivate(
             String::Handle(Z, String::New(function_name))));
  ASSERT(!target.IsNull());
  Array& argument_names = Array::ZoneHandle(Z);
  const intptr_t static_call_arg_count = 2 + (is_store ? 1 : 0);
  code += StaticCall(TokenPosition::kNoSource, target, static_call_arg_count,
                     argument_names, ICData::kStatic);

  return code;
}

Fragment StreamingFlowGraphBuilder::BuildFfiCall() {
  const intptr_t argc = ReadUInt();               // Read argument count.
  ASSERT(argc == 1);                              // Target pointer.
  const intptr_t list_length = ReadListLength();  // Read types list length.
  T.BuildTypeArguments(list_length);              // Read types.
  // Read positional argument count.
  const intptr_t positional_count = ReadListLength();
  ASSERT(positional_count == argc);

  Fragment code;
  // Push the target function pointer passed as Pointer object.
  code += BuildExpression();
  // This can only be Pointer, so the data field points to unmanaged memory.
  code += LoadNativeField(Slot::PointerBase_data(),
                          InnerPointerAccess::kCannotBeInnerPointer);

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

  const auto& native_type = FunctionType::ZoneHandle(
      Z, parsed_function()->function().FfiCSignature());

  // AbiSpecificTypes can have an incomplete mapping.
  const char* error = nullptr;
  compiler::ffi::NativeFunctionTypeFromFunctionType(Z, native_type, &error);
  if (error != nullptr) {
    const auto& language_error = Error::Handle(
        LanguageError::New(String::Handle(String::New(error, Heap::kOld)),
                           Report::kError, Heap::kOld));
    Report::LongJump(language_error);
  }

  code += B->FfiCallFunctionBody(parsed_function()->function(), native_type,
                                 /*first_argument_parameter_offset=*/1);

  ASSERT(code.is_closed());

  NullConstant();  // Maintain stack balance.

  return code;
}

Fragment StreamingFlowGraphBuilder::BuildArgumentsCachableIdempotentCall(
    intptr_t* argument_count) {
  *argument_count = ReadUInt();  // read arguments count.

  // List of types.
  const intptr_t types_list_length = ReadListLength();
  if (types_list_length != 0) {
    FATAL("Type arguments for vm:cachable-idempotent not (yet) supported.");
  }

  Fragment code;
  // List of positional.
  intptr_t positional_list_length = ReadListLength();
  for (intptr_t i = 0; i < positional_list_length; ++i) {
    code += BuildExpression();
    Definition* target_def = B->Peek();
    if (!target_def->IsConstant()) {
      FATAL(
          "Arguments for vm:cachable-idempotent must be const, argument on "
          "index %" Pd " is not.",
          i);
    }
  }

  // List of named.
  const intptr_t named_args_len = ReadListLength();
  if (named_args_len != 0) {
    FATAL("Named arguments for vm:cachable-idempotent not (yet) supported.");
  }

  return code;
}

Fragment StreamingFlowGraphBuilder::BuildCachableIdempotentCall(
    TokenPosition position,
    const Function& target) {
  // The call site must me fore optimized because the cache is untagged.
  if (!parsed_function()->function().ForceOptimize()) {
    FATAL(
        "vm:cachable-idempotent functions can only be called from "
        "vm:force-optimize functions.");
  }
  const auto& target_result_type = AbstractType::Handle(target.result_type());
  if (!target_result_type.IsIntType()) {
    FATAL("The return type vm:cachable-idempotent functions must be int.")
  }

  Fragment code;
  Array& argument_names = Array::ZoneHandle(Z);
  intptr_t argument_count;
  code += BuildArgumentsCachableIdempotentCall(&argument_count);

  code += flow_graph_builder_->CachableIdempotentCall(
      position, kUnboxedAddress, target, argument_count, argument_names,
      /*type_args_len=*/0);

  return code;
}

Fragment StreamingFlowGraphBuilder::BuildFfiNativeCallbackFunction(
    FfiCallbackKind kind) {
  // The call-site must look like this (guaranteed by the FE which inserts it):
  //
  // FfiCallbackKind::kIsolateLocalStaticCallback:
  //   _nativeCallbackFunction<NativeSignatureType>(target, exceptionalReturn)
  //
  // FfiCallbackKind::kIsolateGroupBoundStaticCallback:
  //   _nativeCallbackFunction<NativeSignatureType>(target, exceptionalReturn)
  //
  // FfiCallbackKind::kAsyncCallback:
  //   _nativeAsyncCallbackFunction<NativeSignatureType>()
  //
  // FfiCallbackKind::kIsolateLocalClosureCallback:
  //   _nativeIsolateLocalCallbackFunction<NativeSignatureType>(
  //       exceptionalReturn)
  //
  // FfiCallbackKind::kIsolateGroupBoundClosureCallback:
  //   _nativeIsolateGroupBoundCallbackFunction<NativeSignatureType>(
  //       exceptionalReturn)
  //
  // The FE also guarantees that the arguments are constants.

  const bool has_target =
      kind == FfiCallbackKind::kIsolateLocalStaticCallback ||
      kind == FfiCallbackKind::kIsolateGroupBoundStaticCallback;
  const bool has_exceptional_return = kind != FfiCallbackKind::kAsyncCallback;
  const intptr_t expected_argc =
      static_cast<int>(has_target) + static_cast<int>(has_exceptional_return);

  const intptr_t argc = ReadUInt();  // Read argument count.
  ASSERT(argc == expected_argc);

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

  Fragment code;
  const intptr_t positional_count =
      ReadListLength();  // Read positional argument count.
  ASSERT(positional_count == expected_argc);

  // Read target expression and extract the target function.
  Function& target = Function::Handle(Z, Function::null());
  Instance& exceptional_return = Instance::ZoneHandle(Z, Instance::null());

  if (has_target) {
    // Build target argument.
    code += BuildExpression();
    Definition* target_def = B->Peek();
    ASSERT(target_def->IsConstant());
    const Closure& target_closure =
        Closure::Cast(target_def->AsConstant()->value());
    ASSERT(!target_closure.IsNull());
    target = target_closure.function();
    ASSERT(!target.IsNull() && target.IsImplicitClosureFunction());
    target = target.parent_function();
    code += Drop();
  }

  if (has_exceptional_return) {
    // Build exceptionalReturn argument.
    code += BuildExpression();
    Definition* exceptional_return_def = B->Peek();
    ASSERT(exceptional_return_def->IsConstant());
    exceptional_return ^= exceptional_return_def->AsConstant()->value().ptr();
    code += Drop();
  }

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

  // AbiSpecificTypes can have an incomplete mapping.
  const char* error = nullptr;
  compiler::ffi::NativeFunctionTypeFromFunctionType(zone_, native_sig, &error);
  ReportIfNotNull(error);

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

  return code;
}

Fragment StreamingFlowGraphBuilder::BuildFfiNativeAddressOf() {
  const intptr_t argc = ReadUInt();
  ASSERT(argc == 1);
  const intptr_t types_length = ReadListLength();
  ASSERT(types_length == 1);
  T.BuildTypeArguments(types_length);
  const intptr_t positional_count = ReadListLength();
  ASSERT(positional_count == 1);

  Fragment frag = BuildExpression();
  ASSERT(frag.entry->IsConstant());
  const auto& native_annotation =
      Instance::Cast(frag.entry->AsConstant()->value());
  Drop();

  const auto& pointer_class =
      Class::ZoneHandle(Z, IG->object_store()->ffi_pointer_class());
  const auto& type_arguments =
      TypeArguments::ZoneHandle(Z, IG->object_store()->type_argument_never());
  Fragment code = Constant(type_arguments);
  code += AllocateObject(TokenPosition::kNoSource, pointer_class, 1);
  code += LoadLocal(MakeTemporary());  // Duplicate Pointer.
  // FfiNativeLookupAddress pushes an unboxed value, which is safe even in
  // unoptimized mode because then there is no reordering and we're consuming
  // the value directly.
  code += flow_graph_builder_->FfiNativeLookupAddress(native_annotation);
  code += flow_graph_builder_->StoreNativeField(
      Slot::PointerBase_data(), InnerPointerAccess::kCannotBeInnerPointer,
      StoreFieldInstr::Kind::kInitializing);

  const intptr_t named_arg_count = ReadListLength();
  ASSERT(named_arg_count == 0);
  return code;
}

}  // namespace kernel
}  // namespace dart
