// 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::ResolveDynamicForReceiverClassAllowPrivate(klass, name,
                                                              args_desc));
}

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
