// Copyright (c) 2022, 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/backend/il_serializer.h"

#include "vm/class_id.h"
#include "vm/closure_functions_cache.h"
#if defined(DART_PRECOMPILER)
#include "vm/compiler/aot/precompiler.h"
#endif
#include "vm/compiler/backend/flow_graph.h"
#include "vm/compiler/backend/il.h"
#include "vm/compiler/backend/range_analysis.h"
#include "vm/compiler/frontend/flow_graph_builder.h"
#include "vm/object_store.h"
#include "vm/parser.h"

#define Z zone_

// This file declares write/read methods for each type,
// sorted alphabetically by type/class name (case-insensitive).
// Each "write" method is followed by corresponding "read" method
// or constructor.

namespace dart {

FlowGraphSerializer::FlowGraphSerializer(NonStreamingWriteStream* stream)
    : stream_(stream),
      zone_(Thread::Current()->zone()),
      thread_(Thread::Current()),
      isolate_group_(IsolateGroup::Current()),
      heap_(IsolateGroup::Current()->heap()) {
  // We want to preserve the identity of these, even though they are not const.
  AddBaseObject(Object::uninitialized_index());
  AddBaseObject(Object::uninitialized_data());
}

FlowGraphSerializer::~FlowGraphSerializer() {
  heap_->ResetObjectIdTable();
}

FlowGraphDeserializer::FlowGraphDeserializer(
    const ParsedFunction& parsed_function,
    ReadStream* stream)
    : parsed_function_(parsed_function),
      stream_(stream),
      zone_(Thread::Current()->zone()),
      thread_(Thread::Current()),
      isolate_group_(IsolateGroup::Current()) {
  // We want to preserve the identity of these, even though they are not const.
  AddBaseObject(Object::uninitialized_index());
  AddBaseObject(Object::uninitialized_data());
}

ClassPtr FlowGraphDeserializer::GetClassById(classid_t id) const {
  return isolate_group()->class_table()->At(id);
}

template <>
void FlowGraphSerializer::WriteTrait<const AbstractType*>::Write(
    FlowGraphSerializer* s,
    const AbstractType* x) {
  if (x == nullptr) {
    s->Write<bool>(false);
  } else {
    s->Write<bool>(true);
    s->Write<const AbstractType&>(*x);
  }
}

template <>
const AbstractType* FlowGraphDeserializer::ReadTrait<const AbstractType*>::Read(
    FlowGraphDeserializer* d) {
  if (!d->Read<bool>()) {
    return nullptr;
  }
  return &(d->Read<const AbstractType&>());
}

template <>
void FlowGraphSerializer::WriteTrait<AliasIdentity>::Write(
    FlowGraphSerializer* s,
    AliasIdentity x) {
  x.Write(s);
}

template <>
AliasIdentity FlowGraphDeserializer::ReadTrait<AliasIdentity>::Read(
    FlowGraphDeserializer* d) {
  return AliasIdentity(d);
}

void AliasIdentity::Write(FlowGraphSerializer* s) const {
  s->Write<intptr_t>(value_);
}

AliasIdentity::AliasIdentity(FlowGraphDeserializer* d)
    : value_(d->Read<intptr_t>()) {}

void BlockEntryInstr::WriteTo(FlowGraphSerializer* s) {
  TemplateInstruction::WriteTo(s);
  s->Write<intptr_t>(block_id_);
  s->Write<intptr_t>(try_index_);
  s->Write<intptr_t>(stack_depth_);
  s->Write<ParallelMoveInstr*>(parallel_move_);
}

BlockEntryInstr::BlockEntryInstr(FlowGraphDeserializer* d)
    : TemplateInstruction(d),
      block_id_(d->Read<intptr_t>()),
      try_index_(d->Read<intptr_t>()),
      stack_depth_(d->Read<intptr_t>()),
      dominated_blocks_(1),
      parallel_move_(d->Read<ParallelMoveInstr*>()) {
  d->set_block(block_id_, this);
  d->set_current_block(this);
}

void BlockEntryInstr::WriteExtra(FlowGraphSerializer* s) {
  TemplateInstruction::WriteExtra(s);
  s->WriteRef<BlockEntryInstr*>(dominator_);
  s->WriteGrowableArrayOfRefs<BlockEntryInstr*>(dominated_blocks_);
  if (parallel_move_ != nullptr) {
    parallel_move_->WriteExtra(s);
  }
}

void BlockEntryInstr::ReadExtra(FlowGraphDeserializer* d) {
  TemplateInstruction::ReadExtra(d);
  dominator_ = d->ReadRef<BlockEntryInstr*>();
  dominated_blocks_ = d->ReadGrowableArrayOfRefs<BlockEntryInstr*>();
  if (parallel_move_ != nullptr) {
    parallel_move_->ReadExtra(d);
  }
}

template <>
void FlowGraphSerializer::WriteRefTrait<BlockEntryInstr*>::WriteRef(
    FlowGraphSerializer* s,
    BlockEntryInstr* x) {
  ASSERT(s->can_write_refs());
  if (x == nullptr) {
    s->Write<intptr_t>(-1);
    return;
  }
  const intptr_t id = x->block_id();
  ASSERT(id >= 0);
  s->Write<intptr_t>(id);
}

template <>
BlockEntryInstr* FlowGraphDeserializer::ReadRefTrait<BlockEntryInstr*>::ReadRef(
    FlowGraphDeserializer* d) {
  const intptr_t id = d->Read<intptr_t>();
  if (id < 0) {
    return nullptr;
  }
  return d->block(id);
}

#define INSTRUCTION_REFS_SERIALIZABLE_AS_BLOCK_ENTRY(V)                        \
  V(CatchBlockEntry, CatchBlockEntryInstr)                                     \
  V(FunctionEntry, FunctionEntryInstr)                                         \
  V(IndirectEntry, IndirectEntryInstr)                                         \
  V(JoinEntry, JoinEntryInstr)                                                 \
  V(OsrEntry, OsrEntryInstr)                                                   \
  V(TargetEntry, TargetEntryInstr)                                             \
  V(TryEntry, TryEntryInstr)

#define SERIALIZABLE_AS_BLOCK_ENTRY(name, type)                                \
  template <>                                                                  \
  void FlowGraphSerializer::WriteRefTrait<type*>::WriteRef(                    \
      FlowGraphSerializer* s, type* x) {                                       \
    s->WriteRef<BlockEntryInstr*>(x);                                          \
  }                                                                            \
  template <>                                                                  \
  type* FlowGraphDeserializer::ReadRefTrait<type*>::ReadRef(                   \
      FlowGraphDeserializer* d) {                                              \
    BlockEntryInstr* instr = d->ReadRef<BlockEntryInstr*>();                   \
    ASSERT((instr == nullptr) || instr->Is##name());                           \
    return static_cast<type*>(instr);                                          \
  }

INSTRUCTION_REFS_SERIALIZABLE_AS_BLOCK_ENTRY(SERIALIZABLE_AS_BLOCK_ENTRY)
#undef SERIALIZABLE_AS_BLOCK_ENTRY
#undef INSTRUCTION_REFS_SERIALIZABLE_AS_BLOCK_ENTRY

void BlockEntryWithInitialDefs::WriteTo(FlowGraphSerializer* s) {
  BlockEntryInstr::WriteTo(s);
  s->Write<GrowableArray<Definition*>>(initial_definitions_);
}

BlockEntryWithInitialDefs::BlockEntryWithInitialDefs(FlowGraphDeserializer* d)
    : BlockEntryInstr(d),
      initial_definitions_(d->Read<GrowableArray<Definition*>>()) {
  for (Definition* def : initial_definitions_) {
    def->set_previous(this);
    if (auto par = def->AsParameter()) {
      par->set_block(this);
    }
  }
}

void BlockEntryWithInitialDefs::WriteExtra(FlowGraphSerializer* s) {
  BlockEntryInstr::WriteExtra(s);
  for (Definition* def : initial_definitions_) {
    def->WriteExtra(s);
  }
}

void BlockEntryWithInitialDefs::ReadExtra(FlowGraphDeserializer* d) {
  BlockEntryInstr::ReadExtra(d);
  for (Definition* def : initial_definitions_) {
    def->ReadExtra(d);
  }
}

template <>
void FlowGraphSerializer::WriteTrait<bool>::Write(FlowGraphSerializer* s,
                                                  bool x) {
  s->stream()->Write<uint8_t>(x ? 1 : 0);
}

template <>
bool FlowGraphDeserializer::ReadTrait<bool>::Read(FlowGraphDeserializer* d) {
  return (d->stream()->Read<uint8_t>() != 0);
}

void BranchInstr::WriteExtra(FlowGraphSerializer* s) {
  // Branch reuses inputs from its embedded Condition.
  // Instruction::WriteExtra is not called to avoid
  // writing/reading inputs twice.
  WriteExtraWithoutInputs(s);
  condition_->WriteExtra(s);
  s->WriteRef<TargetEntryInstr*>(true_successor_);
  s->WriteRef<TargetEntryInstr*>(false_successor_);
  s->WriteRef<TargetEntryInstr*>(constant_target_);
}

void BranchInstr::ReadExtra(FlowGraphDeserializer* d) {
  ReadExtraWithoutInputs(d);
  condition_->ReadExtra(d);
  for (intptr_t i = condition_->InputCount() - 1; i >= 0; --i) {
    condition_->InputAt(i)->set_instruction(this);
  }
  true_successor_ = d->ReadRef<TargetEntryInstr*>();
  false_successor_ = d->ReadRef<TargetEntryInstr*>();
  constant_target_ = d->ReadRef<TargetEntryInstr*>();
}

template <>
void FlowGraphSerializer::WriteTrait<const compiler::ffi::CallbackMarshaller&>::
    Write(FlowGraphSerializer* s, const compiler::ffi::CallbackMarshaller& x) {
  s->Write<const Function&>(x.dart_signature());
}

template <>
const compiler::ffi::CallbackMarshaller& FlowGraphDeserializer::ReadTrait<
    const compiler::ffi::CallbackMarshaller&>::Read(FlowGraphDeserializer* d) {
  const Function& dart_signature = d->Read<const Function&>();
  const char* error = nullptr;
  return *compiler::ffi::CallbackMarshaller::FromFunction(
      d->zone(), dart_signature, &error);
}

template <>
void FlowGraphSerializer::WriteTrait<const compiler::ffi::CallMarshaller&>::
    Write(FlowGraphSerializer* s, const compiler::ffi::CallMarshaller& x) {
  s->Write<const Function&>(x.dart_signature());
  s->Write<int8_t>(x.dart_signature_params_start_at());
  s->Write<const FunctionType&>(x.c_signature());
}

template <>
const compiler::ffi::CallMarshaller&
FlowGraphDeserializer::ReadTrait<const compiler::ffi::CallMarshaller&>::Read(
    FlowGraphDeserializer* d) {
  const Function& dart_signature = d->Read<const Function&>();
  const intptr_t dart_signature_params_start_at = d->Read<int8_t>();
  const FunctionType& c_signature = d->Read<const FunctionType&>();
  const char* error = nullptr;
  return *compiler::ffi::CallMarshaller::FromFunction(
      d->zone(), dart_signature, dart_signature_params_start_at, c_signature,
      &error);
}

template <>
void FlowGraphSerializer::WriteTrait<const CallTargets&>::Write(
    FlowGraphSerializer* s,
    const CallTargets& x) {
  x.Write(s);
}

template <>
const CallTargets& FlowGraphDeserializer::ReadTrait<const CallTargets&>::Read(
    FlowGraphDeserializer* d) {
  return *(new (d->zone()) CallTargets(d));
}

void CallTargets::Write(FlowGraphSerializer* s) const {
  const intptr_t len = cid_ranges_.length();
  s->Write<intptr_t>(len);
  for (intptr_t i = 0; i < len; ++i) {
    TargetInfo* t = TargetAt(i);
    s->Write<intptr_t>(t->cid_start);
    s->Write<intptr_t>(t->cid_end);
    s->Write<const Function&>(*(t->target));
    s->Write<intptr_t>(t->count);
    s->Write<int8_t>(t->exactness.Encode());
  }
}

CallTargets::CallTargets(FlowGraphDeserializer* d) : Cids(d->zone()) {
  const intptr_t len = d->Read<intptr_t>();
  cid_ranges_.EnsureLength(len, nullptr);
  for (intptr_t i = 0; i < len; ++i) {
    const intptr_t cid_start = d->Read<intptr_t>();
    const intptr_t cid_end = d->Read<intptr_t>();
    const Function& target = d->Read<const Function&>();
    const intptr_t count = d->Read<intptr_t>();
    const StaticTypeExactnessState exactness =
        StaticTypeExactnessState::Decode(d->Read<int8_t>());
    TargetInfo* t = new (d->zone())
        TargetInfo(cid_start, cid_end, &target, count, exactness);
    cid_ranges_[i] = t;
  }
}

void TryEntryInstr::WriteExtra(FlowGraphSerializer* s) {
  JoinEntryInstr::WriteExtra(s);
  s->WriteRef<JoinEntryInstr*>(try_body_);
  s->WriteRef<CatchBlockEntryInstr*>(catch_target_);
}

void TryEntryInstr::ReadExtra(FlowGraphDeserializer* d) {
  JoinEntryInstr::ReadExtra(d);
  try_body_ = d->ReadRef<JoinEntryInstr*>();
  catch_target_ = d->ReadRef<CatchBlockEntryInstr*>();
}

void CatchBlockEntryInstr::WriteTo(FlowGraphSerializer* s) {
  BlockEntryWithInitialDefs::WriteTo(s);
  s->Write<const Array&>(catch_handler_types_);
  s->Write<intptr_t>(catch_try_index_);
  s->Write<bool>(needs_stacktrace_);
  s->Write<bool>(is_generated_);
}

CatchBlockEntryInstr::CatchBlockEntryInstr(FlowGraphDeserializer* d)
    : BlockEntryWithInitialDefs(d),
      predecessor_(nullptr),
      catch_handler_types_(d->Read<const Array&>()),
      catch_try_index_(d->Read<intptr_t>()),
      exception_var_(nullptr),
      stacktrace_var_(nullptr),
      raw_exception_var_(nullptr),
      raw_stacktrace_var_(nullptr),
      needs_stacktrace_(d->Read<bool>()),
      is_generated_(d->Read<bool>()) {}

template <>
void FlowGraphSerializer::WriteTrait<const char*>::Write(FlowGraphSerializer* s,
                                                         const char* x) {
  ASSERT(x != nullptr);
  const intptr_t len = strlen(x);
  s->Write<intptr_t>(len);
  s->stream()->WriteBytes(x, len);
}

template <>
const char* FlowGraphDeserializer::ReadTrait<const char*>::Read(
    FlowGraphDeserializer* d) {
  const intptr_t len = d->Read<intptr_t>();
  char* str = d->zone()->Alloc<char>(len + 1);
  d->stream()->ReadBytes(str, len);
  str[len] = 0;
  return str;
}

void CheckConditionInstr::WriteExtra(FlowGraphSerializer* s) {
  // CheckCondition reuses inputs from its embedded Condition.
  // Instruction::WriteExtra is not called to avoid
  // writing/reading inputs twice.
  WriteExtraWithoutInputs(s);
  condition_->WriteExtra(s);
}

void CheckConditionInstr::ReadExtra(FlowGraphDeserializer* d) {
  ReadExtraWithoutInputs(d);
  condition_->ReadExtra(d);
  for (intptr_t i = condition_->InputCount() - 1; i >= 0; --i) {
    condition_->InputAt(i)->set_instruction(this);
  }
}

template <>
void FlowGraphSerializer::WriteTrait<CidRangeValue>::Write(
    FlowGraphSerializer* s,
    CidRangeValue x) {
  s->Write<intptr_t>(x.cid_start);
  s->Write<intptr_t>(x.cid_end);
}

template <>
CidRangeValue FlowGraphDeserializer::ReadTrait<CidRangeValue>::Read(
    FlowGraphDeserializer* d) {
  const intptr_t cid_start = d->Read<intptr_t>();
  const intptr_t cid_end = d->Read<intptr_t>();
  return CidRangeValue(cid_start, cid_end);
}

template <>
void FlowGraphSerializer::WriteTrait<const Cids&>::Write(FlowGraphSerializer* s,
                                                         const Cids& x) {
  const intptr_t len = x.length();
  s->Write<intptr_t>(len);
  for (intptr_t i = 0; i < len; ++i) {
    const CidRange* r = x.At(i);
    s->Write<intptr_t>(r->cid_start);
    s->Write<intptr_t>(r->cid_end);
  }
}

template <>
const Cids& FlowGraphDeserializer::ReadTrait<const Cids&>::Read(
    FlowGraphDeserializer* d) {
  Zone* zone = d->zone();
  Cids* cids = new (zone) Cids(zone);
  const intptr_t len = d->Read<intptr_t>();
  for (intptr_t i = 0; i < len; ++i) {
    const intptr_t cid_start = d->Read<intptr_t>();
    const intptr_t cid_end = d->Read<intptr_t>();
    CidRange* r = new (zone) CidRange(cid_start, cid_end);
    cids->Add(r);
  }
  return *cids;
}

template <>
void FlowGraphSerializer::WriteTrait<const Class&>::Write(
    FlowGraphSerializer* s,
    const Class& x) {
  if (x.IsNull()) {
    s->Write<classid_t>(kIllegalCid);
    return;
  }
  s->Write<classid_t>(x.id());
}

template <>
const Class& FlowGraphDeserializer::ReadTrait<const Class&>::Read(
    FlowGraphDeserializer* d) {
  const classid_t cid = d->Read<classid_t>();
  if (cid == kIllegalCid) {
    return Class::ZoneHandle(d->zone());
  }
  return Class::ZoneHandle(d->zone(), d->GetClassById(cid));
}

void ConstraintInstr::WriteExtra(FlowGraphSerializer* s) {
  TemplateDefinition::WriteExtra(s);
  s->WriteRef<TargetEntryInstr*>(target_);
}

void ConstraintInstr::ReadExtra(FlowGraphDeserializer* d) {
  TemplateDefinition::ReadExtra(d);
  target_ = d->ReadRef<TargetEntryInstr*>();
}

template <>
void FlowGraphSerializer::WriteTrait<const Code&>::Write(FlowGraphSerializer* s,
                                                         const Code& x) {
  ASSERT(!x.IsNull());
  ASSERT(x.IsStubCode());
  for (intptr_t i = 0, n = StubCode::NumEntries(); i < n; ++i) {
    if (StubCode::EntryAt(i).ptr() == x.ptr()) {
      s->Write<intptr_t>(i);
      return;
    }
  }
  intptr_t index = StubCode::NumEntries();
  ObjectStore* object_store = s->isolate_group()->object_store();
#define MATCH(member, name)                                                    \
  if (object_store->member() == x.ptr()) {                                     \
    s->Write<intptr_t>(index);                                                 \
    return;                                                                    \
  }                                                                            \
  ++index;
  OBJECT_STORE_STUB_CODE_LIST(MATCH)
#undef MATCH
  UNIMPLEMENTED();
}

template <>
const Code& FlowGraphDeserializer::ReadTrait<const Code&>::Read(
    FlowGraphDeserializer* d) {
  const intptr_t stub_id = d->Read<intptr_t>();
  if (stub_id < StubCode::NumEntries()) {
    return StubCode::EntryAt(stub_id);
  }
  intptr_t index = StubCode::NumEntries();
  ObjectStore* object_store = d->isolate_group()->object_store();
#define MATCH(member, name)                                                    \
  if (index == stub_id) {                                                      \
    return Code::ZoneHandle(d->zone(), object_store->member());                \
  }                                                                            \
  ++index;
  OBJECT_STORE_STUB_CODE_LIST(MATCH)
#undef MATCH
  UNIMPLEMENTED();
}

template <>
void FlowGraphSerializer::WriteTrait<CompileType*>::Write(
    FlowGraphSerializer* s,
    CompileType* x) {
  if (x == nullptr) {
    s->Write<bool>(false);
  } else {
    s->Write<bool>(true);
    x->Write(s);
  }
}

template <>
CompileType* FlowGraphDeserializer::ReadTrait<CompileType*>::Read(
    FlowGraphDeserializer* d) {
  if (!d->Read<bool>()) {
    return nullptr;
  }
  return new (d->zone()) CompileType(d);
}

void CompileType::Write(FlowGraphSerializer* s) const {
  s->Write<bool>(can_be_null_);
  s->Write<bool>(can_be_sentinel_);
  s->Write<classid_t>(cid_);
  if (type_ == nullptr) {
    s->Write<bool>(false);
  } else {
    s->Write<bool>(true);
    s->Write<const AbstractType&>(*type_);
  }
}

CompileType::CompileType(FlowGraphDeserializer* d)
    : can_be_null_(d->Read<bool>()),
      can_be_sentinel_(d->Read<bool>()),
      cid_(d->Read<classid_t>()),
      type_(nullptr) {
  if (d->Read<bool>()) {
    type_ = &d->Read<const AbstractType&>();
  }
}

void Definition::WriteTo(FlowGraphSerializer* s) {
  Instruction::WriteTo(s);
  s->Write<Range*>(range_);
  s->Write<intptr_t>(temp_index_);
  s->Write<intptr_t>(ssa_temp_index_);
  s->Write<CompileType*>(type_);
}

Definition::Definition(FlowGraphDeserializer* d)
    : Instruction(d),
      range_(d->Read<Range*>()),
      temp_index_(d->Read<intptr_t>()),
      ssa_temp_index_(d->Read<intptr_t>()),
      type_(d->Read<CompileType*>()) {
  if (HasSSATemp()) {
    d->set_definition(ssa_temp_index(), this);
  }
  if (type_ != nullptr) {
    type_->set_owner(this);
  }
}

template <>
void FlowGraphSerializer::WriteRefTrait<Definition*>::WriteRef(
    FlowGraphSerializer* s,
    Definition* x) {
  if (!x->HasSSATemp()) {
    if (auto* move_arg = x->AsMoveArgument()) {
      // Environments of the calls can reference MoveArgument instructions
      // and they don't have SSA temps.
      // Write a reference to the original definition.
      // When reading it is restored using RepairArgumentUsesInEnvironment.
      x = move_arg->value()->definition();
    } else {
      UNREACHABLE();
    }
  }
  ASSERT(x->HasSSATemp());
  ASSERT(s->can_write_refs());
  s->Write<intptr_t>(x->ssa_temp_index());
}

template <>
Definition* FlowGraphDeserializer::ReadRefTrait<Definition*>::ReadRef(
    FlowGraphDeserializer* d) {
  return d->definition(d->Read<intptr_t>());
}

template <>
void FlowGraphSerializer::WriteTrait<double>::Write(FlowGraphSerializer* s,
                                                    double x) {
  s->stream()->Write<int64_t>(bit_cast<int64_t>(x));
}

template <>
double FlowGraphDeserializer::ReadTrait<double>::Read(
    FlowGraphDeserializer* d) {
  return bit_cast<double>(d->stream()->Read<int64_t>());
}

template <>
void FlowGraphSerializer::WriteTrait<Environment*>::Write(
    FlowGraphSerializer* s,
    Environment* x) {
  ASSERT(s->can_write_refs());
  if (x == nullptr) {
    s->Write<bool>(false);
  } else {
    s->Write<bool>(true);
    x->Write(s);
  }
}

template <>
Environment* FlowGraphDeserializer::ReadTrait<Environment*>::Read(
    FlowGraphDeserializer* d) {
  if (!d->Read<bool>()) {
    return nullptr;
  }
  return new (d->zone()) Environment(d);
}

void Environment::Write(FlowGraphSerializer* s) const {
  s->Write<GrowableArray<Value*>>(values_);
  s->Write<intptr_t>(fixed_parameter_count_);
  s->Write<uintptr_t>(bitfield_);
  s->Write<const Function&>(function_);
  s->Write<Environment*>(outer_);
  if (locations_ == nullptr) {
    s->Write<bool>(false);
  } else {
    s->Write<bool>(true);
    for (intptr_t i = 0, n = values_.length(); i < n; ++i) {
      locations_[i].Write(s);
    }
  }
}

Environment::Environment(FlowGraphDeserializer* d)
    : values_(d->Read<GrowableArray<Value*>>()),
      locations_(nullptr),
      fixed_parameter_count_(d->Read<intptr_t>()),
      bitfield_(d->Read<uintptr_t>()),
      function_(d->Read<const Function&>()),
      outer_(d->Read<Environment*>()) {
  for (intptr_t i = 0, n = values_.length(); i < n; ++i) {
    Value* value = values_[i];
    value->definition()->AddEnvUse(value);
  }
  if (d->Read<bool>()) {
    locations_ = d->zone()->Alloc<Location>(values_.length());
    for (intptr_t i = 0, n = values_.length(); i < n; ++i) {
      locations_[i] = Location::Read(d);
    }
  }
}

void FlowGraphSerializer::WriteFlowGraph(
    const FlowGraph& flow_graph,
    const ZoneGrowableArray<Definition*>& detached_defs) {
  ASSERT(!flow_graph.is_licm_allowed());

  Write<intptr_t>(flow_graph.current_ssa_temp_index());
  Write<intptr_t>(flow_graph.max_block_id());
  Write<const Array&>(flow_graph.coverage_array());

  PrologueInfo prologue_info = flow_graph.prologue_info();
  Write<intptr_t>(prologue_info.min_block_id);
  Write<intptr_t>(prologue_info.max_block_id);

  // Write instructions
  for (auto block : flow_graph.reverse_postorder()) {
    Write<Instruction*>(block);
    for (auto current : block->instructions()) {
      Write<Instruction*>(current);
    }
  }
  Write<Instruction*>(nullptr);
  Write<const ZoneGrowableArray<Definition*>&>(detached_defs);
  can_write_refs_ = true;

  // Write instructions extra info.
  // It may contain references to other instructions.
  for (auto block : flow_graph.reverse_postorder()) {
    block->WriteExtra(this);
    for (auto current : block->instructions()) {
      current->WriteExtra(this);
    }
  }
  for (auto* instr : detached_defs) {
    instr->WriteExtra(this);
  }

  const auto& optimized_block_order = flow_graph.optimized_block_order();
  Write<intptr_t>(optimized_block_order.length());
  for (intptr_t i = 0, n = optimized_block_order.length(); i < n; ++i) {
    WriteRef<BlockEntryInstr*>(optimized_block_order[i]);
  }

  Write<intptr_t>(flow_graph.inlining_id());

  const InliningInfo& inlining_info = flow_graph.inlining_info();
  Write<intptr_t>(inlining_info.inline_id_to_function.length());
  ASSERT(inlining_info.inline_id_to_function.length() ==
         inlining_info.caller_inline_id.length());
  ASSERT(inlining_info.inline_id_to_function.length() ==
         inlining_info.inline_id_to_token_pos.length() + 1);

  for (intptr_t i = 1, n = inlining_info.inline_id_to_function.length(); i < n;
       ++i) {
    Write<const Function&>(*(inlining_info.inline_id_to_function[i]));
    Write<intptr_t>(inlining_info.caller_inline_id[i]);
    Write<TokenPosition>(inlining_info.inline_id_to_token_pos[i - 1]);
  }
}

FlowGraph* FlowGraphDeserializer::ReadFlowGraph() {
  const intptr_t current_ssa_temp_index = Read<intptr_t>();
  const intptr_t max_block_id = Read<intptr_t>();
  const Array& coverage_array = Read<const Array&>();
  const PrologueInfo prologue_info(Read<intptr_t>(), Read<intptr_t>());

  definitions_.EnsureLength(current_ssa_temp_index, nullptr);
  blocks_.EnsureLength(max_block_id + 1, nullptr);

  // Read/create instructions.
  ZoneGrowableArray<Instruction*> instructions(16);
  Instruction* prev = nullptr;
  while (Instruction* instr = Read<Instruction*>()) {
    instructions.Add(instr);
    if (!instr->IsBlockEntry()) {
      ASSERT(prev != nullptr);
      prev->LinkTo(instr);
    }
    prev = instr;
  }
  ASSERT(graph_entry_ != nullptr);
  const auto& detached_defs = Read<const ZoneGrowableArray<Definition*>&>();

  // Read instructions extra info.
  // It may contain references to other instructions.
  for (Instruction* instr : instructions) {
    instr->ReadExtra(this);
  }
  for (auto* instr : detached_defs) {
    instr->ReadExtra(this);
  }

  FlowGraph* flow_graph =
      new (Z) FlowGraph(parsed_function(), graph_entry_, max_block_id,
                        prologue_info, FlowGraph::CompilationMode::kOptimized);
  flow_graph->set_current_ssa_temp_index(current_ssa_temp_index);
  flow_graph->CreateCommonConstants();
  flow_graph->disallow_licm();
  flow_graph->set_coverage_array(coverage_array);

  {
    const intptr_t num_blocks = Read<intptr_t>();
    if (num_blocks != 0) {
      auto* codegen_block_order = flow_graph->CodegenBlockOrder();
      ASSERT(codegen_block_order == &flow_graph->optimized_block_order());
      for (intptr_t i = 0; i < num_blocks; ++i) {
        codegen_block_order->Add(ReadRef<BlockEntryInstr*>());
      }
    }
  }

  flow_graph->set_inlining_id(Read<intptr_t>());

  auto& inlining_info = flow_graph->inlining_info();
  const intptr_t inlining_info_len = Read<intptr_t>();
  ASSERT(inlining_info.inline_id_to_function.length() == 1);
  ASSERT(inlining_info.caller_inline_id.length() == 1);
  ASSERT(inlining_info.inline_id_to_token_pos.length() == 0);
  for (intptr_t i = 1; i < inlining_info_len; ++i) {
    inlining_info.inline_id_to_function.Add(&Read<const Function&>());
    inlining_info.caller_inline_id.Add(Read<intptr_t>());
    inlining_info.inline_id_to_token_pos.Add(Read<TokenPosition>());
  }

  return flow_graph;
}

template <>
void FlowGraphSerializer::WriteTrait<const Function&>::Write(
    FlowGraphSerializer* s,
    const Function& x) {
  if (x.IsNull()) {
    s->Write<int8_t>(-1);
    return;
  }
  Zone* zone = s->zone();
  s->Write<int8_t>(x.kind());
  switch (x.kind()) {
    case UntaggedFunction::kRegularFunction:
    case UntaggedFunction::kGetterFunction:
    case UntaggedFunction::kSetterFunction:
    case UntaggedFunction::kImplicitGetter:
    case UntaggedFunction::kImplicitSetter:
    case UntaggedFunction::kImplicitStaticGetter:
    case UntaggedFunction::kConstructor: {
      const auto& owner = Class::Handle(zone, x.Owner());
      s->Write<classid_t>(owner.id());
      const intptr_t function_index = owner.FindFunctionIndex(x);
      ASSERT(function_index >= 0);
      s->Write<intptr_t>(function_index);
      return;
    }
    case UntaggedFunction::kImplicitClosureFunction: {
      const auto& parent = Function::Handle(zone, x.parent_function());
      s->Write<const Function&>(parent);
      return;
    }
    case UntaggedFunction::kFieldInitializer: {
      const auto& field = Field::Handle(zone, x.accessor_field());
      s->Write<const Field&>(field);
      return;
    }
    case UntaggedFunction::kClosureFunction:
      // TODO(alexmarkov): we cannot rely on ClosureFunctionsCache
      // as it is lazily populated when compiling functions.
      // We need to serialize kernel offset and re-create
      // closure functions when reading as needed.
      s->Write<intptr_t>(ClosureFunctionsCache::FindClosureIndex(x));
      return;
    case UntaggedFunction::kMethodExtractor: {
      Function& function = Function::Handle(zone, x.extracted_method_closure());
      ASSERT(function.IsImplicitClosureFunction());
      function = function.parent_function();
      s->Write<const Function&>(function);
      s->Write<const String&>(String::Handle(zone, x.name()));
      return;
    }
    case UntaggedFunction::kInvokeFieldDispatcher: {
      s->Write<const Class&>(Class::Handle(zone, x.Owner()));
      s->Write<const String&>(String::Handle(zone, x.name()));
      s->Write<const Array&>(Array::Handle(zone, x.saved_args_desc()));
      return;
    }
    case UntaggedFunction::kDynamicInvocationForwarder: {
      const auto& target = Function::Handle(zone, x.ForwardingTarget());
      s->Write<const Function&>(target);
      return;
    }
    case UntaggedFunction::kFfiTrampoline: {
      s->Write<uint8_t>(static_cast<uint8_t>(x.GetFfiCallbackKind()));
      s->Write<const FunctionType&>(
          FunctionType::Handle(zone, x.FfiCSignature()));
      s->Write<const Function&>(Function::Handle(zone, x.FfiCallbackTarget()));
      s->Write<const Instance&>(
          Instance::Handle(zone, x.FfiCallbackExceptionalReturn()));
      return;
    }
    default:
      break;
  }
  switch (x.kind()) {
#define UNIMPLEMENTED_FUNCTION_KIND(kind)                                      \
  case UntaggedFunction::k##kind:                                              \
    FATAL("Unimplemented WriteTrait<const Function&>::Write for " #kind);
    FOR_EACH_RAW_FUNCTION_KIND(UNIMPLEMENTED_FUNCTION_KIND)
#undef UNIMPLEMENTED_FUNCTION_KIND
  }
  UNREACHABLE();
}

template <>
const Function& FlowGraphDeserializer::ReadTrait<const Function&>::Read(
    FlowGraphDeserializer* d) {
  const int8_t raw_kind = d->Read<int8_t>();
  if (raw_kind < 0) {
    return Object::null_function();
  }
  Zone* zone = d->zone();
  const auto kind = static_cast<UntaggedFunction::Kind>(raw_kind);
  switch (kind) {
    case UntaggedFunction::kRegularFunction:
    case UntaggedFunction::kGetterFunction:
    case UntaggedFunction::kSetterFunction:
    case UntaggedFunction::kImplicitGetter:
    case UntaggedFunction::kImplicitSetter:
    case UntaggedFunction::kImplicitStaticGetter:
    case UntaggedFunction::kConstructor: {
      const classid_t owner_class_id = d->Read<classid_t>();
      const intptr_t function_index = d->Read<intptr_t>();
      const auto& owner = Class::Handle(zone, d->GetClassById(owner_class_id));
      const auto& result =
          Function::ZoneHandle(zone, owner.FunctionFromIndex(function_index));
      ASSERT(!result.IsNull());
      return result;
    }
    case UntaggedFunction::kImplicitClosureFunction: {
      const auto& parent = d->Read<const Function&>();
      return Function::ZoneHandle(zone, parent.ImplicitClosureFunction());
    }
    case UntaggedFunction::kFieldInitializer: {
      const auto& field = d->Read<const Field&>();
      return Function::ZoneHandle(zone, field.EnsureInitializerFunction());
    }
    case UntaggedFunction::kClosureFunction: {
      const intptr_t index = d->Read<intptr_t>();
      return Function::ZoneHandle(
          zone, ClosureFunctionsCache::ClosureFunctionFromIndex(index));
    }
    case UntaggedFunction::kMethodExtractor: {
      const Function& function = d->Read<const Function&>();
      const String& name = d->Read<const String&>();
      return Function::ZoneHandle(zone, function.GetMethodExtractor(name));
    }
    case UntaggedFunction::kInvokeFieldDispatcher: {
      const Class& owner = d->Read<const Class&>();
      const String& target_name = d->Read<const String&>();
      const Array& args_desc = d->Read<const Array&>();
      return Function::ZoneHandle(
          zone,
          owner.GetInvocationDispatcher(
              target_name, args_desc, UntaggedFunction::kInvokeFieldDispatcher,
              /*create_if_absent=*/true));
    }
    case UntaggedFunction::kDynamicInvocationForwarder: {
      const auto& target = d->Read<const Function&>();
      auto& name = String::Handle(zone, target.name());
      name = Function::CreateDynamicInvocationForwarderName(name);
      return Function::ZoneHandle(zone,
                                  target.GetDynamicInvocationForwarder(name));
    }
    case UntaggedFunction::kFfiTrampoline: {
      const FfiCallbackKind kind =
          static_cast<FfiCallbackKind>(d->Read<uint8_t>());
      const FunctionType& c_signature = d->Read<const FunctionType&>();
      const Function& callback_target = d->Read<const Function&>();
      const Instance& exceptional_return = d->Read<const Instance&>();
      return Function::ZoneHandle(
          zone, compiler::ffi::NativeCallbackFunction(
                    c_signature, callback_target, exceptional_return, kind));
    }
    default:
      UNIMPLEMENTED();
      return Object::null_function();
  }
}

void FunctionEntryInstr::WriteTo(FlowGraphSerializer* s) {
  BlockEntryWithInitialDefs::WriteTo(s);
}

FunctionEntryInstr::FunctionEntryInstr(FlowGraphDeserializer* d)
    : BlockEntryWithInitialDefs(d), graph_entry_(d->graph_entry()) {}

void GraphEntryInstr::WriteTo(FlowGraphSerializer* s) {
  BlockEntryWithInitialDefs::WriteTo(s);
  s->Write<intptr_t>(osr_id_);
  s->Write<intptr_t>(entry_count_);
  s->Write<intptr_t>(spill_slot_count_);
  s->Write<intptr_t>(fixed_slot_count_);
  s->Write<bool>(needs_frame_);
}

GraphEntryInstr::GraphEntryInstr(FlowGraphDeserializer* d)
    : BlockEntryWithInitialDefs(d),
      parsed_function_(d->parsed_function()),
      osr_id_(d->Read<intptr_t>()),
      entry_count_(d->Read<intptr_t>()),
      spill_slot_count_(d->Read<intptr_t>()),
      fixed_slot_count_(d->Read<intptr_t>()),
      needs_frame_(d->Read<bool>()) {
  d->set_graph_entry(this);
}

void GraphEntryInstr::WriteExtra(FlowGraphSerializer* s) {
  BlockEntryWithInitialDefs::WriteExtra(s);
  s->WriteRef<FunctionEntryInstr*>(normal_entry_);
  s->WriteRef<FunctionEntryInstr*>(unchecked_entry_);
  s->WriteRef<OsrEntryInstr*>(osr_entry_);
  s->WriteGrowableArrayOfRefs<IndirectEntryInstr*>(indirect_entries_);
}

void GraphEntryInstr::ReadExtra(FlowGraphDeserializer* d) {
  BlockEntryWithInitialDefs::ReadExtra(d);
  normal_entry_ = d->ReadRef<FunctionEntryInstr*>();
  unchecked_entry_ = d->ReadRef<FunctionEntryInstr*>();
  osr_entry_ = d->ReadRef<OsrEntryInstr*>();
  indirect_entries_ = d->ReadGrowableArrayOfRefs<IndirectEntryInstr*>();
}

void GotoInstr::WriteExtra(FlowGraphSerializer* s) {
  TemplateInstruction::WriteExtra(s);
  if (parallel_move_ != nullptr) {
    parallel_move_->WriteExtra(s);
  }
  s->WriteRef<JoinEntryInstr*>(successor_);
}

void GotoInstr::ReadExtra(FlowGraphDeserializer* d) {
  TemplateInstruction::ReadExtra(d);
  if (parallel_move_ != nullptr) {
    parallel_move_->ReadExtra(d);
  }
  successor_ = d->ReadRef<JoinEntryInstr*>();
}

template <>
void FlowGraphSerializer::WriteTrait<const ICData*>::Write(
    FlowGraphSerializer* s,
    const ICData* x) {
  if (x == nullptr) {
    s->Write<bool>(false);
  } else {
    s->Write<bool>(true);
    ASSERT(!x->IsNull());
    s->Write<const Object&>(*x);
  }
}

template <>
const ICData* FlowGraphDeserializer::ReadTrait<const ICData*>::Read(
    FlowGraphDeserializer* d) {
  if (!d->Read<bool>()) {
    return nullptr;
  }
  return &ICData::Cast(d->Read<const Object&>());
}

void IfThenElseInstr::WriteExtra(FlowGraphSerializer* s) {
  // IfThenElse reuses inputs from its embedded Condition.
  // Definition::WriteExtra is not called to avoid
  // writing/reading inputs twice.
  WriteExtraWithoutInputs(s);
  condition_->WriteExtra(s);
}

void IfThenElseInstr::ReadExtra(FlowGraphDeserializer* d) {
  ReadExtraWithoutInputs(d);
  condition_->ReadExtra(d);
  for (intptr_t i = condition_->InputCount() - 1; i >= 0; --i) {
    condition_->InputAt(i)->set_instruction(this);
  }
}

void IndirectGotoInstr::WriteTo(FlowGraphSerializer* s) {
  TemplateInstruction::WriteTo(s);
  s->Write<intptr_t>(offsets_.Length());
}

IndirectGotoInstr::IndirectGotoInstr(FlowGraphDeserializer* d)
    : TemplateInstruction(d),
      offsets_(TypedData::ZoneHandle(d->zone(),
                                     TypedData::New(kTypedDataInt32ArrayCid,
                                                    d->Read<intptr_t>(),
                                                    Heap::kOld))) {}

void IndirectGotoInstr::WriteExtra(FlowGraphSerializer* s) {
  TemplateInstruction::WriteExtra(s);
  s->WriteGrowableArrayOfRefs<TargetEntryInstr*>(successors_);
}

void IndirectGotoInstr::ReadExtra(FlowGraphDeserializer* d) {
  TemplateInstruction::ReadExtra(d);
  successors_ = d->ReadGrowableArrayOfRefs<TargetEntryInstr*>();
}

template <>
void FlowGraphSerializer::WriteTrait<Instruction*>::Write(
    FlowGraphSerializer* s,
    Instruction* x) {
  if (x == nullptr) {
    s->Write<uint8_t>(Instruction::kNumInstructions);
  } else {
    s->Write<uint8_t>(static_cast<uint8_t>(x->tag()));
    x->WriteTo(s);
  }
}

template <>
Instruction* FlowGraphDeserializer::ReadTrait<Instruction*>::Read(
    FlowGraphDeserializer* d) {
  const uint8_t tag = d->Read<uint8_t>();
  switch (tag) {
#define READ_INSTRUCTION(type, attrs)                                          \
  case Instruction::k##type:                                                   \
    return new (d->zone()) type##Instr(d);
    FOR_EACH_CONCRETE_INSTRUCTION(READ_INSTRUCTION)
#undef READ_INSTRUCTION
    case Instruction::kNumInstructions:
      return nullptr;
  }
  UNREACHABLE();
  return nullptr;
}

void Instruction::WriteTo(FlowGraphSerializer* s) {
  s->Write<intptr_t>(deopt_id_);
  s->Write<intptr_t>(inlining_id_);
}

Instruction::Instruction(FlowGraphDeserializer* d)
    : deopt_id_(d->Read<intptr_t>()), inlining_id_(d->Read<intptr_t>()) {}

void Instruction::WriteExtra(FlowGraphSerializer* s) {
  for (intptr_t i = 0, n = InputCount(); i < n; ++i) {
    s->Write<Value*>(InputAt(i));
  }
  WriteExtraWithoutInputs(s);
}

void Instruction::ReadExtra(FlowGraphDeserializer* d) {
  for (intptr_t i = 0, n = InputCount(); i < n; ++i) {
    SetInputAt(i, d->Read<Value*>());
  }
  for (intptr_t i = InputCount() - 1; i >= 0; --i) {
    Value* input = InputAt(i);
    input->definition()->AddInputUse(input);
  }
  ReadExtraWithoutInputs(d);
}

void Instruction::WriteExtraWithoutInputs(FlowGraphSerializer* s) {
  s->Write<Environment*>(env_);
  s->Write<LocationSummary*>(locs_);
}

void Instruction::ReadExtraWithoutInputs(FlowGraphDeserializer* d) {
  Environment* env = d->Read<Environment*>();
  SetEnvironment(env);
  locs_ = d->Read<LocationSummary*>();
}

#define INSTRUCTIONS_SERIALIZABLE_AS_INSTRUCTION(V)                            \
  V(Condition, ConditionInstr)                                                 \
  V(Constant, ConstantInstr)                                                   \
  V(Definition, Definition)                                                    \
  V(ParallelMove, ParallelMoveInstr)                                           \
  V(Phi, PhiInstr)

#define SERIALIZABLE_AS_INSTRUCTION(name, type)                                \
  template <>                                                                  \
  void FlowGraphSerializer::WriteTrait<type*>::Write(FlowGraphSerializer* s,   \
                                                     type* x) {                \
    s->Write<Instruction*>(x);                                                 \
  }                                                                            \
  template <>                                                                  \
  type* FlowGraphDeserializer::ReadTrait<type*>::Read(                         \
      FlowGraphDeserializer* d) {                                              \
    Instruction* instr = d->Read<Instruction*>();                              \
    ASSERT((instr == nullptr) || instr->Is##name());                           \
    return static_cast<type*>(instr);                                          \
  }

INSTRUCTIONS_SERIALIZABLE_AS_INSTRUCTION(SERIALIZABLE_AS_INSTRUCTION)
#undef SERIALIZABLE_AS_INSTRUCTION
#undef INSTRUCTIONS_SERIALIZABLE_AS_INSTRUCTION

template <>
void FlowGraphSerializer::WriteTrait<int8_t>::Write(FlowGraphSerializer* s,
                                                    int8_t x) {
  s->stream()->Write<int8_t>(x);
}

template <>
int8_t FlowGraphDeserializer::ReadTrait<int8_t>::Read(
    FlowGraphDeserializer* d) {
  return d->stream()->Read<int8_t>();
}

template <>
void FlowGraphSerializer::WriteTrait<int16_t>::Write(FlowGraphSerializer* s,
                                                     int16_t x) {
  s->stream()->Write<int16_t>(x);
}

template <>
int16_t FlowGraphDeserializer::ReadTrait<int16_t>::Read(
    FlowGraphDeserializer* d) {
  return d->stream()->Read<int16_t>();
}

template <>
void FlowGraphSerializer::WriteTrait<int32_t>::Write(FlowGraphSerializer* s,
                                                     int32_t x) {
  s->stream()->Write<int32_t>(x);
}

template <>
int32_t FlowGraphDeserializer::ReadTrait<int32_t>::Read(
    FlowGraphDeserializer* d) {
  return d->stream()->Read<int32_t>();
}

template <>
void FlowGraphSerializer::WriteTrait<int64_t>::Write(FlowGraphSerializer* s,
                                                     int64_t x) {
  s->stream()->Write<int64_t>(x);
}

template <>
int64_t FlowGraphDeserializer::ReadTrait<int64_t>::Read(
    FlowGraphDeserializer* d) {
  return d->stream()->Read<int64_t>();
}

void JoinEntryInstr::WriteExtra(FlowGraphSerializer* s) {
  BlockEntryInstr::WriteExtra(s);
  if (phis_ != nullptr) {
    for (PhiInstr* phi : *phis_) {
      phi->WriteExtra(s);
    }
  }
}

void JoinEntryInstr::ReadExtra(FlowGraphDeserializer* d) {
  BlockEntryInstr::ReadExtra(d);
  if (phis_ != nullptr) {
    for (PhiInstr* phi : *phis_) {
      phi->ReadExtra(d);
    }
  }
}

template <>
void FlowGraphSerializer::WriteTrait<const LocalVariable&>::Write(
    FlowGraphSerializer* s,
    const LocalVariable& x) {
  UNIMPLEMENTED();
}

template <>
const LocalVariable&
FlowGraphDeserializer::ReadTrait<const LocalVariable&>::Read(
    FlowGraphDeserializer* d) {
  UNIMPLEMENTED();
  return *d->parsed_function().receiver_var();
}

void Location::Write(FlowGraphSerializer* s) const {
  if (IsPairLocation()) {
    s->Write<uword>(value_ & kLocationTagMask);
    PairLocation* pair = AsPairLocation();
    pair->At(0).Write(s);
    pair->At(1).Write(s);
  } else if (IsConstant()) {
    s->Write<uword>(value_ & kLocationTagMask);
    s->WriteRef<Definition*>(constant_instruction());
  } else {
    s->Write<uword>(value_);
  }
}

Location Location::Read(FlowGraphDeserializer* d) {
  const uword value = d->Read<uword>();
  if (value == kPairLocationTag) {
    const Location first = Location::Read(d);
    const Location second = Location::Read(d);
    return Location::Pair(first, second);
  } else if ((value & kConstantTag) == kConstantTag) {
    ConstantInstr* instr = d->ReadRef<Definition*>()->AsConstant();
    ASSERT(instr != nullptr);
    const int pair_index = (value & kPairLocationTag) != 0 ? 1 : 0;
    return Location::Constant(instr, pair_index);
  } else {
    return Location(value);
  }
}

template <>
void FlowGraphSerializer::WriteTrait<LocationSummary*>::Write(
    FlowGraphSerializer* s,
    LocationSummary* x) {
  ASSERT(s->can_write_refs());
  if (x == nullptr) {
    s->Write<bool>(false);
  } else {
    s->Write<bool>(true);
    x->Write(s);
  }
}

template <>
LocationSummary* FlowGraphDeserializer::ReadTrait<LocationSummary*>::Read(
    FlowGraphDeserializer* d) {
  if (!d->Read<bool>()) {
    return nullptr;
  }
  return new (d->zone()) LocationSummary(d);
}

void LocationSummary::Write(FlowGraphSerializer* s) const {
  s->Write<intptr_t>(input_count());
  s->Write<intptr_t>(temp_count());
  s->Write<int8_t>(static_cast<int8_t>(contains_call_));
  live_registers_.Write(s);

  for (intptr_t i = 0, n = input_count(); i < n; ++i) {
    in(i).Write(s);
  }
  for (intptr_t i = 0, n = temp_count(); i < n; ++i) {
    temp(i).Write(s);
  }
  ASSERT(output_count() == 1);
  out(0).Write(s);

  if ((stack_bitmap_ != nullptr) && (stack_bitmap_->Length() != 0)) {
    s->Write<int8_t>(1);
    stack_bitmap_->Write(s->stream());
  } else {
    s->Write<int8_t>(0);
  }

#if defined(DEBUG)
  s->Write<intptr_t>(writable_inputs_);
#endif
}

LocationSummary::LocationSummary(FlowGraphDeserializer* d)
    : num_inputs_(d->Read<intptr_t>()),
      num_temps_(d->Read<intptr_t>()),
      output_location_(),
      stack_bitmap_(nullptr),
      contains_call_(static_cast<ContainsCall>(d->Read<int8_t>())),
      live_registers_(d) {
  input_locations_ = d->zone()->Alloc<Location>(num_inputs_);
  for (intptr_t i = 0; i < num_inputs_; ++i) {
    input_locations_[i] = Location::Read(d);
  }
  temp_locations_ = d->zone()->Alloc<Location>(num_temps_);
  for (intptr_t i = 0; i < num_temps_; ++i) {
    temp_locations_[i] = Location::Read(d);
  }
  output_location_ = Location::Read(d);

  if (d->Read<int8_t>() != 0) {
    EnsureStackBitmap().Read(d->stream());
  }

#if defined(DEBUG)
  writable_inputs_ = d->Read<intptr_t>();
#endif
}

void MakeTempInstr::WriteExtra(FlowGraphSerializer* s) {
  TemplateDefinition::WriteExtra(s);
  null_->WriteExtra(s);
}

void MakeTempInstr::ReadExtra(FlowGraphDeserializer* d) {
  TemplateDefinition::ReadExtra(d);
  null_->ReadExtra(d);
}

void MaterializeObjectInstr::WriteExtra(FlowGraphSerializer* s) {
  VariadicDefinition::WriteExtra(s);
  for (intptr_t i = 0, n = InputCount(); i < n; ++i) {
    locations_[i].Write(s);
  }
}

void MaterializeObjectInstr::ReadExtra(FlowGraphDeserializer* d) {
  VariadicDefinition::ReadExtra(d);
  locations_ = d->zone()->Alloc<Location>(InputCount());
  for (intptr_t i = 0, n = InputCount(); i < n; ++i) {
    locations_[i] = Location::Read(d);
  }
}

template <>
void FlowGraphSerializer::WriteTrait<MoveOperands*>::Write(
    FlowGraphSerializer* s,
    MoveOperands* x) {
  x->Write(s);
}

template <>
MoveOperands* FlowGraphDeserializer::ReadTrait<MoveOperands*>::Read(
    FlowGraphDeserializer* d) {
  return new (d->zone()) MoveOperands(d);
}

void MoveOperands::Write(FlowGraphSerializer* s) const {
  dest().Write(s);
  src().Write(s);
}

MoveOperands::MoveOperands(FlowGraphDeserializer* d)
    : dest_(Location::Read(d)), src_(Location::Read(d)) {}

void FlowGraphSerializer::AddBaseObject(const Object& x) {
  const intptr_t object_index = object_counter_++;
  heap()->SetObjectId(x.ptr(), object_index + 1);
}

template <>
void FlowGraphSerializer::WriteTrait<const Object&>::Write(
    FlowGraphSerializer* s,
    const Object& x) {
  const intptr_t cid = x.GetClassId();
  ASSERT(cid != kIllegalCid);
  // Do not write objects repeatedly.
  const intptr_t object_id = s->heap()->GetObjectId(x.ptr());
  if (object_id > 0) {
    const intptr_t object_index = object_id - 1;
    s->Write<intptr_t>(kIllegalCid);
    s->Write<intptr_t>(object_index);
    return;
  }
  const intptr_t object_index = s->object_counter_++;
  s->heap()->SetObjectId(x.ptr(), object_index + 1);
  s->Write<intptr_t>(cid);
  s->WriteObjectImpl(x, cid, object_index);
}

void FlowGraphDeserializer::AddBaseObject(const Object& x) {
  const intptr_t object_index = object_counter_;
  object_counter_++;
  SetObjectAt(object_index, x);
}

template <>
const Object& FlowGraphDeserializer::ReadTrait<const Object&>::Read(
    FlowGraphDeserializer* d) {
  const intptr_t cid = d->Read<intptr_t>();
  if (cid == kIllegalCid) {
    const intptr_t object_index = d->Read<intptr_t>();
    return *(d->objects_[object_index]);
  }
  const intptr_t object_index = d->object_counter_;
  d->object_counter_++;
  const Object& result = d->ReadObjectImpl(cid, object_index);
  d->SetObjectAt(object_index, result);
  return result;
}

void FlowGraphDeserializer::SetObjectAt(intptr_t object_index,
                                        const Object& object) {
  objects_.EnsureLength(object_index + 1, &Object::null_object());
  objects_[object_index] = &object;
}

bool FlowGraphSerializer::IsWritten(const Object& obj) {
  const intptr_t object_id = heap()->GetObjectId(obj.ptr());
  return (object_id != 0);
}

bool FlowGraphSerializer::HasEnclosingTypes(const Object& obj) {
  if (num_free_fun_type_params_ == 0) return false;
  if (obj.IsAbstractType()) {
    return !AbstractType::Cast(obj).IsInstantiated(kFunctions,
                                                   num_free_fun_type_params_);
  } else if (obj.IsTypeArguments()) {
    return !TypeArguments::Cast(obj).IsInstantiated(kFunctions,
                                                    num_free_fun_type_params_);
  } else {
    UNREACHABLE();
  }
}

bool FlowGraphSerializer::WriteObjectWithEnclosingTypes(const Object& obj) {
  if (HasEnclosingTypes(obj)) {
    Write<bool>(true);
    // Reset assigned object id so it could be written
    // while writing enclosing types.
    heap()->SetObjectId(obj.ptr(), -1);
    WriteEnclosingTypes(obj, num_free_fun_type_params_);
    Write<bool>(false);
    // Can write any type parameters after all enclosing types are written.
    const intptr_t saved_num_free_fun_type_params = num_free_fun_type_params_;
    num_free_fun_type_params_ = 0;
    Write<const Object&>(obj);
    num_free_fun_type_params_ = saved_num_free_fun_type_params;
    return true;
  } else {
    Write<bool>(false);
    return false;
  }
}

void FlowGraphSerializer::WriteEnclosingTypes(
    const Object& obj,
    intptr_t num_free_fun_type_params) {
  if (obj.IsType()) {
    const auto& type = Type::Cast(obj);
    if (type.arguments() != TypeArguments::null()) {
      const auto& type_args = TypeArguments::Handle(Z, type.arguments());
      WriteEnclosingTypes(type_args, num_free_fun_type_params);
    }
  } else if (obj.IsRecordType()) {
    const auto& rec = RecordType::Cast(obj);
    auto& elem = AbstractType::Handle(Z);
    for (intptr_t i = 0, n = rec.NumFields(); i < n; ++i) {
      elem = rec.FieldTypeAt(i);
      WriteEnclosingTypes(elem, num_free_fun_type_params);
    }
  } else if (obj.IsFunctionType()) {
    const auto& sig = FunctionType::Cast(obj);
    const intptr_t num_parent_type_args = sig.NumParentTypeArguments();
    if (num_free_fun_type_params > num_parent_type_args) {
      num_free_fun_type_params = num_parent_type_args;
    }
    AbstractType& elem = AbstractType::Handle(Z, sig.result_type());
    WriteEnclosingTypes(elem, num_free_fun_type_params);
    for (intptr_t i = 0, n = sig.NumParameters(); i < n; ++i) {
      elem = sig.ParameterTypeAt(i);
      WriteEnclosingTypes(elem, num_free_fun_type_params);
    }
    if (sig.IsGeneric()) {
      const TypeParameters& type_params =
          TypeParameters::Handle(Z, sig.type_parameters());
      WriteEnclosingTypes(TypeArguments::Handle(Z, type_params.bounds()),
                          num_free_fun_type_params);
    }
  } else if (obj.IsTypeParameter()) {
    const auto& tp = TypeParameter::Cast(obj);
    if (tp.IsFunctionTypeParameter() &&
        (tp.index() < num_free_fun_type_params)) {
      const auto& owner =
          FunctionType::Handle(Z, tp.parameterized_function_type());
      if (!IsWritten(owner)) {
        Write<bool>(true);
        Write<const Object&>(owner);
      }
    }
  } else if (obj.IsTypeArguments()) {
    const auto& type_args = TypeArguments::Cast(obj);
    auto& elem = AbstractType::Handle(Z);
    for (intptr_t i = 0, n = type_args.Length(); i < n; ++i) {
      elem = type_args.TypeAt(i);
      WriteEnclosingTypes(elem, num_free_fun_type_params);
    }
  }
}

const Object& FlowGraphDeserializer::ReadObjectWithEnclosingTypes() {
  if (Read<bool>()) {
    while (Read<bool>()) {
      Read<const Object&>();
    }
    return Read<const Object&>();
  } else {
    return Object::null_object();
  }
}

void FlowGraphSerializer::WriteObjectImpl(const Object& x,
                                          intptr_t cid,
                                          intptr_t object_index) {
  switch (cid) {
    case kArrayCid:
    case kImmutableArrayCid: {
      const auto& array = Array::Cast(x);
      const intptr_t len = array.Length();
      Write<intptr_t>(len);
      const auto& type_args =
          TypeArguments::Handle(Z, array.GetTypeArguments());
      Write<const TypeArguments&>(type_args);
      if ((len == 0) && type_args.IsNull()) {
        break;
      }
      Write<bool>(array.IsCanonical());
      auto& elem = Object::Handle(Z);
      for (intptr_t i = 0; i < len; ++i) {
        elem = array.At(i);
        Write<const Object&>(elem);
      }
      break;
    }
    case kBoolCid:
      Write<bool>(Bool::Cast(x).value());
      break;
    case kClosureCid: {
      const auto& closure = Closure::Cast(x);
      if (closure.RawContext() != Object::null()) {
        UNIMPLEMENTED();
      }
      ASSERT(closure.IsCanonical());
      auto& type_args = TypeArguments::Handle(Z);
      type_args = closure.instantiator_type_arguments();
      Write<const TypeArguments&>(type_args);
      type_args = closure.function_type_arguments();
      Write<const TypeArguments&>(type_args);
      type_args = closure.delayed_type_arguments();
      Write<const TypeArguments&>(type_args);
      Write<const Function&>(Function::Handle(Z, closure.function()));
      break;
    }
    case kDoubleCid:
      ASSERT(x.IsCanonical());
      Write<double>(Double::Cast(x).value());
      break;
    case kFloat32x4Cid:
      ASSERT(x.IsCanonical());
      Write<simd128_value_t>(Float32x4::Cast(x).value());
      break;
    case kFloat64x2Cid:
      ASSERT(x.IsCanonical());
      Write<simd128_value_t>(Float64x2::Cast(x).value());
      break;
    case kInt32x4Cid:
      ASSERT(x.IsCanonical());
      Write<simd128_value_t>(Int32x4::Cast(x).value());
      break;
    case kFieldCid: {
      const auto& field = Field::Cast(x);
      const auto& owner = Class::Handle(Z, field.Owner());
      Write<classid_t>(owner.id());
      const intptr_t field_index = owner.FindFieldIndex(field);
      ASSERT(field_index >= 0);
      Write<intptr_t>(field_index);
      break;
    }
    case kFunctionCid:
      Write<const Function&>(Function::Cast(x));
      break;
    case kFunctionTypeCid: {
      const auto& type = FunctionType::Cast(x);
      ASSERT(type.IsFinalized());
      if (WriteObjectWithEnclosingTypes(type)) {
        break;
      }
      const intptr_t saved_num_free_fun_type_params = num_free_fun_type_params_;
      const intptr_t num_parent_type_args = type.NumParentTypeArguments();
      if (num_free_fun_type_params_ > num_parent_type_args) {
        num_free_fun_type_params_ = num_parent_type_args;
      }
      Write<int8_t>(static_cast<int8_t>(type.nullability()));
      Write<uint32_t>(type.packed_parameter_counts());
      Write<uint16_t>(type.packed_type_parameter_counts());
      Write<const TypeParameters&>(
          TypeParameters::Handle(Z, type.type_parameters()));
      Write<const AbstractType&>(AbstractType::Handle(Z, type.result_type()));
      Write<const Array&>(Array::Handle(Z, type.parameter_types()));
      Write<const Array&>(Array::Handle(Z, type.named_parameter_names()));
      num_free_fun_type_params_ = saved_num_free_fun_type_params;
      break;
    }
    case kICDataCid: {
      const auto& icdata = ICData::Cast(x);
      Write<int8_t>(static_cast<int8_t>(icdata.rebind_rule()));
      Write<const Function&>(Function::Handle(Z, icdata.Owner()));
      Write<const Array&>(Array::Handle(Z, icdata.arguments_descriptor()));
      Write<intptr_t>(icdata.deopt_id());
      Write<intptr_t>(icdata.NumArgsTested());
      if (icdata.rebind_rule() == ICData::kStatic) {
        ASSERT(icdata.NumberOfChecks() == 1);
        Write<const Function&>(Function::Handle(Z, icdata.GetTargetAt(0)));
      } else if (icdata.rebind_rule() == ICData::kInstance) {
        if (icdata.NumberOfChecks() != 0) {
          UNIMPLEMENTED();
        }
        Write<const String&>(String::Handle(Z, icdata.target_name()));
      } else {
        UNIMPLEMENTED();
      }
      break;
    }
    case kConstMapCid:
    case kConstSetCid: {
      const auto& map = LinkedHashBase::Cast(x);
      ASSERT(map.IsCanonical());
      const intptr_t length = map.Length();
      Write<intptr_t>(length);
      Write<const TypeArguments&>(
          TypeArguments::Handle(Z, map.GetTypeArguments()));
      const auto& data = Array::Handle(Z, map.data());
      auto& elem = Object::Handle(Z);
      intptr_t used_data;
      if (cid == kConstMapCid) {
        used_data = length << 1;
      } else {
        used_data = length;
      }
      for (intptr_t i = 0; i < used_data; ++i) {
        elem = data.At(i);
        Write<const Object&>(elem);
      }
      break;
    }
    case kLibraryPrefixCid: {
      const auto& prefix = LibraryPrefix::Cast(x);
      const Library& library = Library::Handle(Z, prefix.importer());
      Write<classid_t>(Class::Handle(Z, library.toplevel_class()).id());
      Write<const String&>(String::Handle(Z, prefix.name()));
      break;
    }
    case kMintCid:
      ASSERT(x.IsCanonical());
      Write<int64_t>(Integer::Cast(x).Value());
      break;
    case kNullCid:
      break;
    case kOneByteStringCid: {
      ASSERT(x.IsCanonical());
      const auto& str = String::Cast(x);
      const intptr_t length = str.Length();
      Write<intptr_t>(length);
      NoSafepointScope no_safepoint;
      uint8_t* latin1 = OneByteString::DataStart(str);
      stream_->WriteBytes(latin1, length);
      break;
    }
    case kRecordCid: {
      ASSERT(x.IsCanonical());
      const auto& record = Record::Cast(x);
      Write<RecordShape>(record.shape());
      auto& field = Object::Handle(Z);
      for (intptr_t i = 0, n = record.num_fields(); i < n; ++i) {
        field = record.FieldAt(i);
        Write<const Object&>(field);
      }
      break;
    }
    case kRecordTypeCid: {
      const auto& rec = RecordType::Cast(x);
      ASSERT(rec.IsFinalized());
      if (WriteObjectWithEnclosingTypes(rec)) {
        break;
      }
      Write<int8_t>(static_cast<int8_t>(rec.nullability()));
      Write<RecordShape>(rec.shape());
      Write<const Array&>(Array::Handle(Z, rec.field_types()));
      break;
    }
    case kSentinelCid:
      if (x.ptr() == Object::sentinel().ptr()) {
        Write<uint8_t>(0);
      } else if (x.ptr() == Object::optimized_out().ptr()) {
        Write<uint8_t>(2);
      } else {
        UNIMPLEMENTED();
      }
      break;
    case kSmiCid:
      Write<intptr_t>(Smi::Cast(x).Value());
      break;
    case kTwoByteStringCid: {
      ASSERT(x.IsCanonical());
      const auto& str = String::Cast(x);
      const intptr_t length = str.Length();
      Write<intptr_t>(length);
      NoSafepointScope no_safepoint;
      uint16_t* utf16 = TwoByteString::DataStart(str);
      stream_->WriteBytes(reinterpret_cast<const uint8_t*>(utf16),
                          length * sizeof(uint16_t));
      break;
    }
    case kTypeCid: {
      const auto& type = Type::Cast(x);
      ASSERT(type.IsFinalized());
      if (WriteObjectWithEnclosingTypes(type)) {
        break;
      }
      const auto& cls = Class::Handle(Z, type.type_class());
      Write<int8_t>(static_cast<int8_t>(type.nullability()));
      Write<classid_t>(type.type_class_id());
      if (cls.IsGeneric()) {
        const auto& type_args = TypeArguments::Handle(Z, type.arguments());
        Write<const TypeArguments&>(type_args);
      }
      break;
    }
    case kTypeArgumentsCid: {
      const auto& type_args = TypeArguments::Cast(x);
      ASSERT(type_args.IsFinalized());
      if (WriteObjectWithEnclosingTypes(type_args)) {
        break;
      }
      const intptr_t len = type_args.Length();
      Write<intptr_t>(len);
      auto& type = AbstractType::Handle(Z);
      for (intptr_t i = 0; i < len; ++i) {
        type = type_args.TypeAt(i);
        Write<const AbstractType&>(type);
      }
      break;
    }
    case kTypeParameterCid: {
      const auto& tp = TypeParameter::Cast(x);
      ASSERT(tp.IsFinalized());
      if (WriteObjectWithEnclosingTypes(tp)) {
        break;
      }
      Write<intptr_t>(tp.base());
      Write<intptr_t>(tp.index());
      Write<int8_t>(static_cast<int8_t>(tp.nullability()));
      if (tp.IsFunctionTypeParameter()) {
        Write<bool>(true);
        Write<const FunctionType&>(
            FunctionType::Handle(Z, tp.parameterized_function_type()));
      } else {
        Write<bool>(false);
        Write<const Class&>(Class::Handle(Z, tp.parameterized_class()));
      }
      break;
    }
    case kTypeParametersCid: {
      const auto& tps = TypeParameters::Cast(x);
      Write<const Array&>(Array::Handle(Z, tps.names()));
      Write<const Array&>(Array::Handle(Z, tps.flags()));
      Write<const TypeArguments&>(TypeArguments::Handle(Z, tps.bounds()));
      Write<const TypeArguments&>(TypeArguments::Handle(Z, tps.defaults()));
      break;
    }
    default: {
      const classid_t cid = x.GetClassId();
      if ((cid >= kNumPredefinedCids) || (cid == kInstanceCid)) {
        const auto& instance = Instance::Cast(x);
        ASSERT(instance.IsCanonical());
        const auto& cls =
            Class::Handle(Z, isolate_group()->class_table()->At(cid));
        const auto unboxed_fields_bitmap =
            isolate_group()->class_table()->GetUnboxedFieldsMapAt(cid);
        const intptr_t next_field_offset = cls.host_next_field_offset();
        auto& obj = Object::Handle(Z);
        for (intptr_t offset = Instance::NextFieldOffset();
             offset < next_field_offset; offset += kCompressedWordSize) {
          if (unboxed_fields_bitmap.Get(offset / kCompressedWordSize)) {
            if (kCompressedWordSize == 8) {
              Write<int64_t>(*reinterpret_cast<int64_t*>(
                  instance.RawFieldAddrAtOffset(offset)));
            } else {
              Write<int32_t>(*reinterpret_cast<int32_t*>(
                  instance.RawFieldAddrAtOffset(offset)));
            }
          } else {
            obj = instance.RawGetFieldAtOffset(offset);
            Write<const Object&>(obj);
          }
        }
        break;
      }
      FATAL("Unimplemented WriteObjectImpl for %s", x.ToCString());
    }
  }
}

const Object& FlowGraphDeserializer::ReadObjectImpl(intptr_t cid,
                                                    intptr_t object_index) {
  switch (cid) {
    case kArrayCid:
    case kImmutableArrayCid: {
      const intptr_t len = Read<intptr_t>();
      const auto& type_args = Read<const TypeArguments&>();
      if ((len == 0) && type_args.IsNull()) {
        return Object::empty_array();
      }
      const bool canonicalize = Read<bool>();
      auto& array = Array::ZoneHandle(
          Z, Array::New(len, canonicalize ? Heap::kNew : Heap::kOld));
      if (!type_args.IsNull()) {
        array.SetTypeArguments(type_args);
      }
      for (intptr_t i = 0; i < len; ++i) {
        array.SetAt(i, Read<const Object&>());
      }
      if (cid == kImmutableArrayCid) {
        array.MakeImmutable();
      }
      if (canonicalize) {
        array ^= array.Canonicalize(thread());
      }
      return array;
    }
    case kBoolCid:
      return Bool::Get(Read<bool>());
    case kClosureCid: {
      const auto& instantiator_type_arguments = Read<const TypeArguments&>();
      const auto& function_type_arguments = Read<const TypeArguments&>();
      const auto& delayed_type_arguments = Read<const TypeArguments&>();
      const auto& function = Read<const Function&>();
      auto& closure = Closure::ZoneHandle(
          Z, Closure::New(instantiator_type_arguments, function_type_arguments,
                          delayed_type_arguments, function,
                          Object::null_object()));
      closure ^= closure.Canonicalize(thread());
      return closure;
    }
    case kDoubleCid:
      return Double::ZoneHandle(Z, Double::NewCanonical(Read<double>()));
    case kFloat32x4Cid: {
      auto& simd_value =
          Float32x4::ZoneHandle(Z, Float32x4::New(Read<simd128_value_t>()));
      simd_value ^= simd_value.Canonicalize(thread());
      return simd_value;
    }
    case kFloat64x2Cid: {
      auto& simd_value =
          Float64x2::ZoneHandle(Z, Float64x2::New(Read<simd128_value_t>()));
      simd_value ^= simd_value.Canonicalize(thread());
      return simd_value;
    }
    case kInt32x4Cid: {
      auto& simd_value =
          Int32x4::ZoneHandle(Z, Int32x4::New(Read<simd128_value_t>()));
      simd_value ^= simd_value.Canonicalize(thread());
      return simd_value;
    }
    case kFieldCid: {
      const classid_t owner_class_id = Read<classid_t>();
      const intptr_t field_index = Read<intptr_t>();
      const auto& owner = Class::Handle(Z, GetClassById(owner_class_id));
      auto& result = Field::ZoneHandle(Z, owner.FieldFromIndex(field_index));
      ASSERT(!result.IsNull());
      return result;
    }
    case kFunctionCid:
      return Read<const Function&>();
    case kFunctionTypeCid: {
      const auto& enc_type = ReadObjectWithEnclosingTypes();
      if (!enc_type.IsNull()) {
        return enc_type;
      }
      const Nullability nullability = static_cast<Nullability>(Read<int8_t>());
      auto& result =
          FunctionType::ZoneHandle(Z, FunctionType::New(0, nullability));
      SetObjectAt(object_index, result);
      result.set_packed_parameter_counts(Read<uint32_t>());
      result.set_packed_type_parameter_counts(Read<uint16_t>());
      result.SetTypeParameters(Read<const TypeParameters&>());
      result.set_result_type(Read<const AbstractType&>());
      result.set_parameter_types(Read<const Array&>());
      result.set_named_parameter_names(Read<const Array&>());
      result.SetIsFinalized();
      result ^= result.Canonicalize(thread());
      return result;
    }
    case kICDataCid: {
      const ICData::RebindRule rebind_rule =
          static_cast<ICData::RebindRule>(Read<int8_t>());
      const auto& owner = Read<const Function&>();
      const auto& arguments_descriptor = Read<const Array&>();
      const intptr_t deopt_id = Read<intptr_t>();
      const intptr_t num_args_tested = Read<intptr_t>();

      if (rebind_rule == ICData::kStatic) {
        const auto& target = Read<const Function&>();
        return ICData::ZoneHandle(
            Z,
            ICData::NewForStaticCall(owner, target, arguments_descriptor,
                                     deopt_id, num_args_tested, rebind_rule));
      } else if (rebind_rule == ICData::kInstance) {
        const auto& target_name = Read<const String&>();
        return ICData::ZoneHandle(
            Z, ICData::New(owner, target_name, arguments_descriptor, deopt_id,
                           num_args_tested, rebind_rule));
      } else {
        UNIMPLEMENTED();
      }
      break;
    }
    case kConstMapCid:
    case kConstSetCid: {
      const intptr_t length = Read<intptr_t>();
      const auto& type_args = Read<const TypeArguments&>();
      Instance& result = Instance::ZoneHandle(Z);
      intptr_t used_data;
      if (cid == kConstMapCid) {
        result = ConstMap::NewUninitialized(Heap::kOld);
        used_data = (length << 1);
      } else {
        result = ConstSet::NewUninitialized(Heap::kOld);
        used_data = length;
      }
      // LinkedHashBase is not a proper handle type, so
      // cannot create a LinkedHashBase handle upfront.
      const LinkedHashBase& map = LinkedHashBase::Cast(result);
      map.SetTypeArguments(type_args);
      map.set_used_data(used_data);
      const auto& data = Array::Handle(Z, Array::New(used_data));
      map.set_data(data);
      map.set_deleted_keys(0);
      map.ComputeAndSetHashMask();
      for (intptr_t i = 0; i < used_data; ++i) {
        data.SetAt(i, Read<const Object&>());
      }
      result ^= result.Canonicalize(thread());
      return result;
    }
    case kLibraryPrefixCid: {
      const Class& toplevel_class =
          Class::Handle(Z, GetClassById(Read<classid_t>()));
      const Library& library = Library::Handle(Z, toplevel_class.library());
      const String& name = Read<const String&>();
      const auto& prefix =
          LibraryPrefix::ZoneHandle(Z, library.LookupLocalLibraryPrefix(name));
      ASSERT(!prefix.IsNull());
      return prefix;
    }
    case kMintCid: {
      const int64_t value = Read<int64_t>();
      return Integer::ZoneHandle(Z, Integer::NewCanonical(value));
    }
    case kNullCid:
      return Object::null_object();
    case kOneByteStringCid: {
      const intptr_t length = Read<intptr_t>();
      uint8_t* latin1 = Z->Alloc<uint8_t>(length);
      stream_->ReadBytes(latin1, length);
      return String::ZoneHandle(Z,
                                Symbols::FromLatin1(thread(), latin1, length));
    }
    case kRecordCid: {
      const RecordShape shape = Read<RecordShape>();
      auto& record = Record::ZoneHandle(Z, Record::New(shape));
      for (intptr_t i = 0, n = shape.num_fields(); i < n; ++i) {
        record.SetFieldAt(i, Read<const Object&>());
      }
      record ^= record.Canonicalize(thread());
      return record;
    }
    case kRecordTypeCid: {
      const auto& enc_type = ReadObjectWithEnclosingTypes();
      if (!enc_type.IsNull()) {
        return enc_type;
      }
      const Nullability nullability = static_cast<Nullability>(Read<int8_t>());
      const RecordShape shape = Read<RecordShape>();
      const Array& field_types = Read<const Array&>();
      RecordType& rec = RecordType::ZoneHandle(
          Z, RecordType::New(shape, field_types, nullability));
      rec.SetIsFinalized();
      rec ^= rec.Canonicalize(thread());
      return rec;
    }
    case kSentinelCid:
      switch (Read<uint8_t>()) {
        case 0:
          return Object::sentinel();
        case 2:
          return Object::optimized_out();
        default:
          UNREACHABLE();
      }
    case kSmiCid:
      return Smi::ZoneHandle(Z, Smi::New(Read<intptr_t>()));
    case kTwoByteStringCid: {
      const intptr_t length = Read<intptr_t>();
      uint16_t* utf16 = Z->Alloc<uint16_t>(length);
      stream_->ReadBytes(reinterpret_cast<uint8_t*>(utf16),
                         length * sizeof(uint16_t));
      return String::ZoneHandle(Z, Symbols::FromUTF16(thread(), utf16, length));
    }
    case kTypeCid: {
      const auto& enc_type = ReadObjectWithEnclosingTypes();
      if (!enc_type.IsNull()) {
        return enc_type;
      }
      const Nullability nullability = static_cast<Nullability>(Read<int8_t>());
      const classid_t type_class_id = Read<classid_t>();
      const auto& cls = Class::Handle(Z, GetClassById(type_class_id));
      auto& result = Type::ZoneHandle(Z);
      if (cls.IsGeneric()) {
        result = Type::New(cls, Object::null_type_arguments(), nullability);
        SetObjectAt(object_index, result);
        const auto& type_args = Read<const TypeArguments&>();
        result.set_arguments(type_args);
        result.SetIsFinalized();
      } else {
        result = cls.DeclarationType();
        result = result.ToNullability(nullability, Heap::kOld);
      }
      result ^= result.Canonicalize(thread());
      return result;
    }
    case kTypeArgumentsCid: {
      const auto& enc_type_args = ReadObjectWithEnclosingTypes();
      if (!enc_type_args.IsNull()) {
        return enc_type_args;
      }
      const intptr_t len = Read<intptr_t>();
      auto& type_args = TypeArguments::ZoneHandle(Z, TypeArguments::New(len));
      SetObjectAt(object_index, type_args);
      for (intptr_t i = 0; i < len; ++i) {
        type_args.SetTypeAt(i, Read<const AbstractType&>());
      }
      type_args ^= type_args.Canonicalize(thread());
      return type_args;
    }
    case kTypeParameterCid: {
      const auto& enc_type = ReadObjectWithEnclosingTypes();
      if (!enc_type.IsNull()) {
        return enc_type;
      }
      const intptr_t base = Read<intptr_t>();
      const intptr_t index = Read<intptr_t>();
      const Nullability nullability = static_cast<Nullability>(Read<int8_t>());
      const Object* owner = nullptr;
      if (Read<bool>()) {
        owner = &Read<const FunctionType&>();
      } else {
        owner = &Read<const Class&>();
      }
      auto& tp = TypeParameter::ZoneHandle(
          Z, TypeParameter::New(*owner, base, index, nullability));
      SetObjectAt(object_index, tp);
      tp.SetIsFinalized();
      tp ^= tp.Canonicalize(thread());
      return tp;
    }
    case kTypeParametersCid: {
      const auto& tps = TypeParameters::ZoneHandle(Z, TypeParameters::New());
      tps.set_names(Read<const Array&>());
      tps.set_flags(Read<const Array&>());
      tps.set_bounds(Read<const TypeArguments&>());
      tps.set_defaults(Read<const TypeArguments&>());
      return tps;
    }
    default:
      if ((cid >= kNumPredefinedCids) || (cid == kInstanceCid)) {
        const auto& cls = Class::Handle(Z, GetClassById(cid));
        const auto unboxed_fields_bitmap =
            isolate_group()->class_table()->GetUnboxedFieldsMapAt(cid);
        const intptr_t next_field_offset = cls.host_next_field_offset();
        auto& instance = Instance::ZoneHandle(Z, Instance::New(cls));
        for (intptr_t offset = Instance::NextFieldOffset();
             offset < next_field_offset; offset += kCompressedWordSize) {
          if (unboxed_fields_bitmap.Get(offset / kCompressedWordSize)) {
            if (kCompressedWordSize == 8) {
              const int64_t v = Read<int64_t>();
              *reinterpret_cast<int64_t*>(
                  instance.RawFieldAddrAtOffset(offset)) = v;
            } else {
              const int32_t v = Read<int32_t>();
              *reinterpret_cast<int32_t*>(
                  instance.RawFieldAddrAtOffset(offset)) = v;
            }
          } else {
            const auto& obj = Read<const Object&>();
            instance.RawSetFieldAtOffset(offset, obj);
          }
        }
        instance = instance.Canonicalize(thread());
        return instance;
      }
  }
  UNIMPLEMENTED();
  return Object::null_object();
}

#define HANDLES_SERIALIZABLE_AS_OBJECT(V)                                      \
  V(AbstractType, Object::null_abstract_type())                                \
  V(Array, Object::null_array())                                               \
  V(Field, Field::Handle(d->zone()))                                           \
  V(FunctionType, Object::null_function_type())                                \
  V(Instance, Object::null_instance())                                         \
  V(String, Object::null_string())                                             \
  V(TypeArguments, Object::null_type_arguments())                              \
  V(TypeParameters, TypeParameters::Handle(d->zone()))

#define SERIALIZE_HANDLE_AS_OBJECT(handle, null_handle)                        \
  template <>                                                                  \
  void FlowGraphSerializer::WriteTrait<const handle&>::Write(                  \
      FlowGraphSerializer* s, const handle& x) {                               \
    s->Write<const Object&>(x);                                                \
  }                                                                            \
  template <>                                                                  \
  const handle& FlowGraphDeserializer::ReadTrait<const handle&>::Read(         \
      FlowGraphDeserializer* d) {                                              \
    const Object& result = d->Read<const Object&>();                           \
    if (result.IsNull()) {                                                     \
      return null_handle;                                                      \
    }                                                                          \
    return handle::Cast(result);                                               \
  }

HANDLES_SERIALIZABLE_AS_OBJECT(SERIALIZE_HANDLE_AS_OBJECT)
#undef SERIALIZE_HANDLE_AS_OBJECT
#undef HANDLES_SERIALIZABLE_AS_OBJECT

void OsrEntryInstr::WriteTo(FlowGraphSerializer* s) {
  BlockEntryWithInitialDefs::WriteTo(s);
}

OsrEntryInstr::OsrEntryInstr(FlowGraphDeserializer* d)
    : BlockEntryWithInitialDefs(d), graph_entry_(d->graph_entry()) {}

void ParallelMoveInstr::WriteExtra(FlowGraphSerializer* s) {
  Instruction::WriteExtra(s);
  s->Write<GrowableArray<MoveOperands*>>(moves_);
  s->Write<const MoveSchedule*>(move_schedule_);
}

void ParallelMoveInstr::ReadExtra(FlowGraphDeserializer* d) {
  Instruction::ReadExtra(d);
  moves_ = d->Read<GrowableArray<MoveOperands*>>();
  move_schedule_ = d->Read<const MoveSchedule*>();
}

void ParameterInstr::WriteExtra(FlowGraphSerializer* s) {
  TemplateDefinition::WriteExtra(s);
  location_.Write(s);
}

void ParameterInstr::ReadExtra(FlowGraphDeserializer* d) {
  TemplateDefinition::ReadExtra(d);
  location_ = Location::Read(d);
}

void PhiInstr::WriteTo(FlowGraphSerializer* s) {
  VariadicDefinition::WriteTo(s);
  s->Write<Representation>(representation_);
  s->Write<bool>(is_alive_);
  s->Write<int8_t>(is_receiver_);
}

PhiInstr::PhiInstr(FlowGraphDeserializer* d)
    : VariadicDefinition(d),
      block_(d->current_block()->AsJoinEntry()),
      representation_(d->Read<Representation>()),
      is_alive_(d->Read<bool>()),
      is_receiver_(d->Read<int8_t>()) {}

void LeafRuntimeCallInstr::WriteTo(FlowGraphSerializer* s) {
  VariadicDefinition::WriteTo(s);
  s->Write<Representation>(return_representation_);
  s->Write<const ZoneGrowableArray<Representation>&>(argument_representations_);
}

LeafRuntimeCallInstr::LeafRuntimeCallInstr(FlowGraphDeserializer* d)
    : VariadicDefinition(d),
      return_representation_(d->Read<Representation>()),
      argument_representations_(
          d->Read<const ZoneGrowableArray<Representation>&>()),
      native_calling_convention_(
          compiler::ffi::NativeCallingConvention::FromSignature(
              d->zone(),
              *compiler::ffi::NativeFunctionType::FromRepresentations(
                  d->zone(),
                  return_representation_,
                  argument_representations_))) {}

template <>
void FlowGraphSerializer::WriteTrait<Range*>::Write(FlowGraphSerializer* s,
                                                    Range* x) {
  if (x == nullptr) {
    s->Write<bool>(false);
  } else {
    s->Write<bool>(true);
    x->Write(s);
  }
}

template <>
Range* FlowGraphDeserializer::ReadTrait<Range*>::Read(
    FlowGraphDeserializer* d) {
  if (!d->Read<bool>()) {
    return nullptr;
  }
  return new (d->zone()) Range(d);
}

void Range::Write(FlowGraphSerializer* s) const {
  min_.Write(s);
  max_.Write(s);
}

Range::Range(FlowGraphDeserializer* d)
    : min_(RangeBoundary(d)), max_(RangeBoundary(d)) {}

void RangeBoundary::Write(FlowGraphSerializer* s) const {
  s->Write<int8_t>(kind_);
  s->Write<int64_t>(value_);
  s->Write<int64_t>(offset_);
}

RangeBoundary::RangeBoundary(FlowGraphDeserializer* d)
    : kind_(static_cast<Kind>(d->Read<int8_t>())),
      value_(d->Read<int64_t>()),
      offset_(d->Read<int64_t>()) {}

template <>
void FlowGraphSerializer::WriteTrait<RecordShape>::Write(FlowGraphSerializer* s,
                                                         RecordShape x) {
  s->Write<intptr_t>(x.num_fields());
  s->Write<const Array&>(
      Array::Handle(s->zone(), x.GetFieldNames(s->thread())));
}

template <>
RecordShape FlowGraphDeserializer::ReadTrait<RecordShape>::Read(
    FlowGraphDeserializer* d) {
  const intptr_t num_fields = d->Read<intptr_t>();
  const auto& field_names = d->Read<const Array&>();
  return RecordShape::Register(d->thread(), num_fields, field_names);
}

void RegisterSet::Write(FlowGraphSerializer* s) const {
  s->Write<uintptr_t>(cpu_registers_.data());
  s->Write<uintptr_t>(untagged_cpu_registers_.data());
  s->Write<uintptr_t>(fpu_registers_.data());
}

RegisterSet::RegisterSet(FlowGraphDeserializer* d)
    : cpu_registers_(d->Read<uintptr_t>()),
      untagged_cpu_registers_(d->Read<uintptr_t>()),
      fpu_registers_(d->Read<uintptr_t>()) {}

template <>
void FlowGraphSerializer::WriteTrait<Representation>::Write(
    FlowGraphSerializer* s,
    Representation x) {
  s->Write<uint8_t>(x);
}

template <>
Representation FlowGraphDeserializer::ReadTrait<Representation>::Read(
    FlowGraphDeserializer* d) {
  return static_cast<Representation>(d->Read<uint8_t>());
}

template <>
void FlowGraphSerializer::WriteTrait<simd128_value_t>::Write(
    FlowGraphSerializer* s,
    simd128_value_t x) {
  s->stream()->WriteBytes(&x, sizeof(simd128_value_t));
}

template <>
simd128_value_t FlowGraphDeserializer::ReadTrait<simd128_value_t>::Read(
    FlowGraphDeserializer* d) {
  simd128_value_t value;
  d->stream()->ReadBytes(&value, sizeof(simd128_value_t));
  return value;
}

template <>
void FlowGraphSerializer::WriteTrait<const Slot&>::Write(FlowGraphSerializer* s,
                                                         const Slot& x) {
  x.Write(s);
}

template <>
const Slot& FlowGraphDeserializer::ReadTrait<const Slot&>::Read(
    FlowGraphDeserializer* d) {
  return Slot::Read(d);
}

template <>
void FlowGraphSerializer::WriteTrait<const Slot*>::Write(FlowGraphSerializer* s,
                                                         const Slot* x) {
  if (x == nullptr) {
    s->Write<bool>(false);
    return;
  }
  s->Write<bool>(true);
  x->Write(s);
}

template <>
const Slot* FlowGraphDeserializer::ReadTrait<const Slot*>::Read(
    FlowGraphDeserializer* d) {
  if (!d->Read<bool>()) {
    return nullptr;
  }
  return &Slot::Read(d);
}

void Slot::Write(FlowGraphSerializer* s) const {
  s->Write<serializable_type_t<Kind>>(
      static_cast<serializable_type_t<Kind>>(kind_));

  switch (kind_) {
    case Kind::kTypeArguments:
      s->Write<int8_t>(flags_);
      s->Write<intptr_t>(offset_in_bytes_);
      break;
    case Kind::kTypeArgumentsIndex:
      s->Write<intptr_t>(offset_in_bytes_);
      break;
    case Kind::kArrayElement:
      s->Write<intptr_t>(offset_in_bytes_);
      break;
    case Kind::kRecordField:
      s->Write<intptr_t>(offset_in_bytes_);
      break;
    case Kind::kCapturedVariable:
      s->Write<int8_t>(flags_);
      s->Write<intptr_t>(offset_in_bytes_);
      s->Write<const String&>(*DataAs<const String>());
      type_.Write(s);
      break;
    case Kind::kDartField:
      s->Write<const Field&>(field());
      break;
    default:
      break;
  }
}

const Slot& Slot::Read(FlowGraphDeserializer* d) {
  const Kind kind = static_cast<Kind>(d->Read<serializable_type_t<Kind>>());
  int8_t flags = 0;
  intptr_t offset = -1;
  const void* data = nullptr;
  CompileType type = CompileType::None();
  Representation representation = kTagged;

  switch (kind) {
    case Kind::kTypeArguments:
      flags = d->Read<int8_t>();
      offset = d->Read<intptr_t>();
      data = ":type_arguments";
      type = CompileType::FromCid(kTypeArgumentsCid);
      break;
    case Kind::kTypeArgumentsIndex:
      flags =
          IsImmutableBit::encode(true) |
          IsCompressedBit::encode(TypeArguments::ContainsCompressedPointers());
      offset = d->Read<intptr_t>();
      data = ":argument";
      type = CompileType(CompileType::kCannotBeNull,
                         CompileType::kCannotBeSentinel, kDynamicCid, nullptr);
      break;
    case Kind::kArrayElement:
      flags = IsCompressedBit::encode(Array::ContainsCompressedPointers());
      offset = d->Read<intptr_t>();
      data = ":array_element";
      type = CompileType::Dynamic();
      break;
    case Kind::kRecordField:
      flags = IsCompressedBit::encode(Record::ContainsCompressedPointers());
      offset = d->Read<intptr_t>();
      data = ":record_field";
      type = CompileType::Dynamic();
      break;
    case Kind::kCapturedVariable:
      flags = d->Read<int8_t>();
      offset = d->Read<intptr_t>();
      data = &d->Read<const String&>();
      type = CompileType(d);
      break;
    case Kind::kDartField: {
      const Field& field = d->Read<const Field&>();
      return Slot::Get(field, &d->parsed_function());
    }
    default:
      return Slot::GetNativeSlot(kind);
  }

  return GetCanonicalSlot(d->thread(), kind, flags, offset, data, type,
                          representation);
}

template <>
void FlowGraphSerializer::WriteTrait<const compiler::TableSelector*>::Write(
    FlowGraphSerializer* s,
    const compiler::TableSelector* x) {
#if defined(DART_PRECOMPILER)
  ASSERT(x != nullptr);
  s->Write<int32_t>(x->id);
#else
  UNREACHABLE();
#endif
}

template <>
const compiler::TableSelector*
FlowGraphDeserializer::ReadTrait<const compiler::TableSelector*>::Read(
    FlowGraphDeserializer* d) {
#if defined(DART_PRECOMPILER)
  const int32_t id = d->Read<int32_t>();
  const compiler::TableSelector* selector =
      Precompiler::Instance()->selector_map()->GetSelector(id);
  ASSERT(selector != nullptr);
  return selector;
#else
  UNREACHABLE();
#endif
}

template <intptr_t kExtraInputs>
void TemplateDartCall<kExtraInputs>::WriteTo(FlowGraphSerializer* s) {
  VariadicDefinition::WriteTo(s);
  s->Write<intptr_t>(type_args_len_);
  s->Write<const Array&>(argument_names_);
  s->Write<TokenPosition>(token_pos_);
  if (move_arguments_ == nullptr) {
    s->Write<intptr_t>(-1);
  } else {
    s->Write<intptr_t>(move_arguments_->length());
    // Write detached MoveArgument instructions.
    for (auto move_arg : *move_arguments_) {
      if (move_arg->next() == nullptr) {
        s->Write<bool>(true);
        s->Write<Instruction*>(move_arg);
      } else {
        s->Write<bool>(false);
      }
    }
  }
}

template <intptr_t kExtraInputs>
TemplateDartCall<kExtraInputs>::TemplateDartCall(FlowGraphDeserializer* d)
    : VariadicDefinition(d),
      type_args_len_(d->Read<intptr_t>()),
      argument_names_(d->Read<const Array&>()),
      token_pos_(d->Read<TokenPosition>()) {
  const intptr_t num_move_args = d->Read<intptr_t>();
  if (num_move_args >= 0) {
    move_arguments_ =
        new (d->zone()) MoveArgumentsArray(d->zone(), num_move_args);
    move_arguments_->EnsureLength(num_move_args, nullptr);
    for (intptr_t i = 0; i < num_move_args; i++) {
      if (d->Read<bool>()) {
        auto move_arg = d->Read<Instruction*>()->AsMoveArgument();
        ASSERT(move_arg != nullptr);
        (*move_arguments_)[i] = move_arg;
      }
    }
  }
}

template <intptr_t kExtraInputs>
void TemplateDartCall<kExtraInputs>::WriteExtra(FlowGraphSerializer* s) {
  VariadicDefinition::WriteExtra(s);
  if (move_arguments_ != nullptr) {
    // Write extras for detached MoveArgument in reverse order, because
    // we are going to read them back in reverse order.
    for (intptr_t i = move_arguments_->length() - 1; i >= 0; --i) {
      auto move_arg = move_arguments_->At(i);
      if (move_arg->next() == nullptr) {
        move_arg->WriteExtra(s);
      }
    }
  }
}

template <intptr_t kExtraInputs>
void TemplateDartCall<kExtraInputs>::ReadExtra(FlowGraphDeserializer* d) {
  VariadicDefinition::ReadExtra(d);
  if (move_arguments_ != nullptr) {
    Instruction* cursor = this;
    for (intptr_t i = move_arguments_->length() - 1; i >= 0; --i) {
      if ((*move_arguments_)[i] != nullptr) {
        (*move_arguments_)[i]->ReadExtra(d);
      } else {
        // Note: IL might be serialized after ParallelMove instructions
        // were inserted between MoveArguments.
        do {
          cursor = cursor->previous();
        } while (!cursor->IsMoveArgument());
        (*move_arguments_)[i] = cursor->AsMoveArgument();
      }
    }
    if (env() != nullptr) {
      RepairArgumentUsesInEnvironment();
    }
  }
}

// Explicit template instantiations, needed for the methods above.
template class TemplateDartCall<0>;
template class TemplateDartCall<1>;

void MoveArgumentInstr::WriteExtra(FlowGraphSerializer* s) {
  TemplateDefinition::WriteExtra(s);
  location_.Write(s);
}

void MoveArgumentInstr::ReadExtra(FlowGraphDeserializer* d) {
  TemplateDefinition::ReadExtra(d);
  location_ = Location::Read(d);
}

template <>
void FlowGraphSerializer::WriteTrait<TokenPosition>::Write(
    FlowGraphSerializer* s,
    TokenPosition x) {
  s->Write<int32_t>(x.Serialize());
}

template <>
TokenPosition FlowGraphDeserializer::ReadTrait<TokenPosition>::Read(
    FlowGraphDeserializer* d) {
  return TokenPosition::Deserialize(d->Read<int32_t>());
}

template <>
void FlowGraphSerializer::WriteTrait<uint8_t>::Write(FlowGraphSerializer* s,
                                                     uint8_t x) {
  s->stream()->Write<uint8_t>(x);
}

template <>
uint8_t FlowGraphDeserializer::ReadTrait<uint8_t>::Read(
    FlowGraphDeserializer* d) {
  return d->stream()->Read<uint8_t>();
}

template <>
void FlowGraphSerializer::WriteTrait<uint16_t>::Write(FlowGraphSerializer* s,
                                                      uint16_t x) {
  s->stream()->Write<uint16_t>(x);
}

template <>
uint16_t FlowGraphDeserializer::ReadTrait<uint16_t>::Read(
    FlowGraphDeserializer* d) {
  return d->stream()->Read<uint16_t>();
}

template <>
void FlowGraphSerializer::WriteTrait<uint32_t>::Write(FlowGraphSerializer* s,
                                                      uint32_t x) {
  s->stream()->Write<int32_t>(static_cast<int32_t>(x));
}

template <>
uint32_t FlowGraphDeserializer::ReadTrait<uint32_t>::Read(
    FlowGraphDeserializer* d) {
  return static_cast<uint32_t>(d->stream()->Read<int32_t>());
}

template <>
void FlowGraphSerializer::WriteTrait<uint64_t>::Write(FlowGraphSerializer* s,
                                                      uint64_t x) {
  s->stream()->Write<int64_t>(static_cast<int64_t>(x));
}

template <>
uint64_t FlowGraphDeserializer::ReadTrait<uint64_t>::Read(
    FlowGraphDeserializer* d) {
  return static_cast<uint64_t>(d->stream()->Read<int64_t>());
}

template <>
void FlowGraphSerializer::WriteTrait<Value*>::Write(FlowGraphSerializer* s,
                                                    Value* x) {
  ASSERT(s->can_write_refs());
  CompileType* reaching_type = x->reaching_type();
  Definition* def = x->definition();
  // Omit reaching type if it is the same as definition type.
  if ((reaching_type != nullptr) && def->HasType() &&
      (reaching_type == def->Type())) {
    reaching_type = nullptr;
  }
  s->Write<CompileType*>(reaching_type);
  s->WriteRef<Definition*>(def);
}

template <>
Value* FlowGraphDeserializer::ReadTrait<Value*>::Read(
    FlowGraphDeserializer* d) {
  CompileType* type = d->Read<CompileType*>();
  Definition* def = d->ReadRef<Definition*>();
  Value* value = new (d->zone()) Value(def);
  value->SetReachingType(type);
  return value;
}

void VariadicDefinition::WriteTo(FlowGraphSerializer* s) {
  Definition::WriteTo(s);
  s->Write<intptr_t>(inputs_.length());
}

VariadicDefinition::VariadicDefinition(FlowGraphDeserializer* d)
    : Definition(d), inputs_(d->zone(), 0) {
  const intptr_t num_inputs = d->Read<intptr_t>();
  inputs_.EnsureLength(num_inputs, nullptr);
}

}  // namespace dart
