Revert "[vm/compiler] Initial implementation of IL binary serialization"

This reverts commit 97004589756b0022bfdbb127c4ae0bc275f07b4b.

Reason for revert: breaks Dart SDK build using gcc and dart-sdk-linux-main bot.

Original change's description:
> [vm/compiler] Initial implementation of IL binary serialization
>
> This change adds binary serialization/deserialization of flow graphs.
> It supports all IL instructions and certain objects which can be
> referenced from IL instructions. IL binary serialization is a useful
> machanism which would allow us to split compilation into multiple parts
> in order to parallelize AOT compilation.
>
> The program structure (libraries/classes/functions/fields) is not
> serialized. It is assumed that reader and writer use the same
> program structure.
>
> Caveats:
> * FFI callbacks are not supported yet.
> * Closure functions are not re-created when reading flow graph.
> * Flow graph should be in SSA form (unoptimized flow graphs are not
>   supported).
> * JIT mode is not supported (serializer currently assumes lazy
>   linking of native methods and empty ICData).
>
> In order to test IL serialization, --test_il_serialization VM option is
> added to serialize and deserialize flow graph before generating code.
>
> TEST=vm/dart/splay_test now runs with --test_il_serialization.
>
> TEST=Manual run of vm-kernel-precomp-linux-debug-x64-try with
> --test_il_serialization enabled (only ffi tests failed).
>
> Issue: https://github.com/dart-lang/sdk/issues/43299
> Change-Id: I7bbfd9e3a301e00c9cfbffa06b8f1f6c78a78470
> Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/254941
> Reviewed-by: Ryan Macnak <rmacnak@google.com>
> Commit-Queue: Alexander Markov <alexmarkov@google.com>
> Reviewed-by: Slava Egorov <vegorov@google.com>

TBR=vegorov@google.com,kustermann@google.com,rmacnak@google.com,alexmarkov@google.com

Change-Id: Iae4e4868f183815a8fc3cd79597141b3896e23d7
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Issue: https://github.com/dart-lang/sdk/issues/43299
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/255780
Reviewed-by: Alexander Markov <alexmarkov@google.com>
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
Commit-Queue: Alexander Markov <alexmarkov@google.com>
diff --git a/runtime/tests/vm/dart/splay_test.dart b/runtime/tests/vm/dart/splay_test.dart
index 25b7d98..ef51ede 100644
--- a/runtime/tests/vm/dart/splay_test.dart
+++ b/runtime/tests/vm/dart/splay_test.dart
@@ -31,7 +31,6 @@
 // VMOptions=--no_load_cse
 // VMOptions=--no_dead_store_elimination
 // VMOptions=--no_load_cse --no_dead_store_elimination
-// VMOptions=--test_il_serialization
 
 import "dart:math";
 import 'package:benchmark_harness/benchmark_harness.dart';
diff --git a/runtime/tests/vm/dart_2/splay_test.dart b/runtime/tests/vm/dart_2/splay_test.dart
index d6a349f..6cd3050 100644
--- a/runtime/tests/vm/dart_2/splay_test.dart
+++ b/runtime/tests/vm/dart_2/splay_test.dart
@@ -35,7 +35,6 @@
 // VMOptions=--no_load_cse
 // VMOptions=--no_dead_store_elimination
 // VMOptions=--no_load_cse --no_dead_store_elimination
-// VMOptions=--test_il_serialization
 
 import "dart:math";
 import 'package:benchmark_harness/benchmark_harness.dart';
diff --git a/runtime/vm/bitmap.cc b/runtime/vm/bitmap.cc
index a79912af..06119e3 100644
--- a/runtime/vm/bitmap.cc
+++ b/runtime/vm/bitmap.cc
@@ -149,26 +149,4 @@
   }
 }
 
-void BitmapBuilder::Write(BaseWriteStream* stream) const {
-  const intptr_t payload_size =
-      Utils::Minimum(Utils::RoundUp(Length(), kBitsPerByte) / kBitsPerByte,
-                     data_size_in_bytes_);
-  stream->Write<intptr_t>(Length());
-  stream->Write<intptr_t>(payload_size);
-  stream->WriteBytes(BackingStore(), payload_size);
-}
-
-void BitmapBuilder::Read(ReadStream* stream) {
-  length_ = stream->Read<intptr_t>();
-  const intptr_t payload_size = stream->Read<intptr_t>();
-  if (payload_size > data_size_in_bytes_) {
-    data_size_in_bytes_ = payload_size;
-    data_.ptr_ = AllocBackingStore(data_size_in_bytes_);
-  } else {
-    memset(BackingStore() + payload_size, 0,
-           data_size_in_bytes_ - payload_size);
-  }
-  stream->ReadBytes(BackingStore(), payload_size);
-}
-
 }  // namespace dart
diff --git a/runtime/vm/bitmap.h b/runtime/vm/bitmap.h
index 2c18ba5..74c4c5b 100644
--- a/runtime/vm/bitmap.h
+++ b/runtime/vm/bitmap.h
@@ -54,9 +54,6 @@
   void Print() const;
   void AppendAsBytesTo(BaseWriteStream* stream) const;
 
-  void Write(BaseWriteStream* stream) const;
-  void Read(ReadStream* stream);
-
  private:
   static constexpr intptr_t kIncrementSizeInBytes = 16;
   static constexpr intptr_t kInlineCapacityInBytes = 16;
diff --git a/runtime/vm/code_descriptors.h b/runtime/vm/code_descriptors.h
index 6ca2430..47ced6f 100644
--- a/runtime/vm/code_descriptors.h
+++ b/runtime/vm/code_descriptors.h
@@ -107,7 +107,7 @@
     ASSERT(list_[try_index].pc_offset == ExceptionHandlers::kInvalidPcOffset);
     list_[try_index].pc_offset = pc_offset;
     list_[try_index].is_generated = is_generated;
-    ASSERT(handler_types.IsNotTemporaryScopedHandle());
+    ASSERT(handler_types.IsZoneHandle());
     list_[try_index].handler_types = &handler_types;
     list_[try_index].needs_stacktrace |= needs_stacktrace;
   }
diff --git a/runtime/vm/compiler/aot/dispatch_table_generator.cc b/runtime/vm/compiler/aot/dispatch_table_generator.cc
index 1245c38..bb5faac 100644
--- a/runtime/vm/compiler/aot/dispatch_table_generator.cc
+++ b/runtime/vm/compiler/aot/dispatch_table_generator.cc
@@ -375,10 +375,6 @@
 const TableSelector* SelectorMap::GetSelector(
     const Function& interface_target) const {
   const int32_t sid = SelectorId(interface_target);
-  return GetSelector(sid);
-}
-
-const TableSelector* SelectorMap::GetSelector(int32_t sid) const {
   if (sid == kInvalidSelectorId) return nullptr;
   const TableSelector* selector = &selectors_[sid];
   if (!selector->IsUsed()) return nullptr;
diff --git a/runtime/vm/compiler/aot/dispatch_table_generator.h b/runtime/vm/compiler/aot/dispatch_table_generator.h
index 770d880..e916a3c 100644
--- a/runtime/vm/compiler/aot/dispatch_table_generator.h
+++ b/runtime/vm/compiler/aot/dispatch_table_generator.h
@@ -61,8 +61,6 @@
   // not have a selector assigned.
   const TableSelector* GetSelector(const Function& interface_target) const;
 
-  const TableSelector* GetSelector(int32_t sid) const;
-
  private:
   static const int32_t kInvalidSelectorId =
       kernel::ProcedureAttributesMetadata::kInvalidSelectorId;
diff --git a/runtime/vm/compiler/backend/compile_type.h b/runtime/vm/compiler/backend/compile_type.h
index bc9c6e5..1eeb89c 100644
--- a/runtime/vm/compiler/backend/compile_type.h
+++ b/runtime/vm/compiler/backend/compile_type.h
@@ -18,8 +18,6 @@
 class AbstractType;
 class BaseTextBuffer;
 class Definition;
-class FlowGraphDeserializer;
-class FlowGraphSerializer;
 
 template <typename T>
 class GrowableArray;
@@ -283,9 +281,6 @@
   void set_owner(Definition* owner) { owner_ = owner; }
   Definition* owner() const { return owner_; }
 
-  void Write(FlowGraphSerializer* s) const;
-  explicit CompileType(FlowGraphDeserializer* d);
-
  private:
   bool can_be_null_;
   bool can_be_sentinel_;
diff --git a/runtime/vm/compiler/backend/flow_graph.cc b/runtime/vm/compiler/backend/flow_graph.cc
index 2459014..fbefe32 100644
--- a/runtime/vm/compiler/backend/flow_graph.cc
+++ b/runtime/vm/compiler/backend/flow_graph.cc
@@ -2896,120 +2896,4 @@
   FlowGraphPrinter::PrintGraph(phase, this);
 }
 
-class SSACompactor : public ValueObject {
- public:
-  SSACompactor(intptr_t num_blocks,
-               intptr_t num_ssa_vars,
-               ZoneGrowableArray<Definition*>* detached_defs)
-      : block_num_(num_blocks),
-        ssa_num_(num_ssa_vars),
-        detached_defs_(detached_defs) {
-    block_num_.EnsureLength(num_blocks, -1);
-    ssa_num_.EnsureLength(num_ssa_vars, -1);
-  }
-
-  void RenumberGraph(FlowGraph* graph) {
-    for (auto block : graph->reverse_postorder()) {
-      block_num_[block->block_id()] = 1;
-      CollectDetachedMaterializations(block->env());
-
-      if (auto* block_with_idefs = block->AsBlockEntryWithInitialDefs()) {
-        for (Definition* def : *block_with_idefs->initial_definitions()) {
-          RenumberDefinition(def);
-          CollectDetachedMaterializations(def->env());
-        }
-      }
-      if (auto* join = block->AsJoinEntry()) {
-        for (PhiIterator it(join); !it.Done(); it.Advance()) {
-          RenumberDefinition(it.Current());
-        }
-      }
-      for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
-        Instruction* instr = it.Current();
-        if (Definition* def = instr->AsDefinition()) {
-          RenumberDefinition(def);
-        }
-        CollectDetachedMaterializations(instr->env());
-      }
-    }
-    for (auto* def : (*detached_defs_)) {
-      RenumberDefinition(def);
-    }
-    graph->set_current_ssa_temp_index(current_ssa_index_);
-
-    // Preserve order between block ids to as predecessors are sorted
-    // by block ids.
-    intptr_t current_block_index = 0;
-    for (intptr_t i = 0, n = block_num_.length(); i < n; ++i) {
-      if (block_num_[i] >= 0) {
-        block_num_[i] = current_block_index++;
-      }
-    }
-    for (auto block : graph->reverse_postorder()) {
-      block->set_block_id(block_num_[block->block_id()]);
-    }
-    graph->set_max_block_id(current_block_index - 1);
-  }
-
- private:
-  void RenumberDefinition(Definition* def) {
-    if (def->HasSSATemp()) {
-      const intptr_t old_index = def->ssa_temp_index();
-      intptr_t new_index = ssa_num_[old_index];
-      if (new_index < 0) {
-        ssa_num_[old_index] = new_index = current_ssa_index_++;
-      }
-      def->set_ssa_temp_index(new_index);
-    }
-  }
-
-  bool IsDetachedDefinition(Definition* def) {
-    return def->IsMaterializeObject() && (def->next() == nullptr);
-  }
-
-  void AddDetachedDefinition(Definition* def) {
-    for (intptr_t i = 0, n = detached_defs_->length(); i < n; ++i) {
-      if ((*detached_defs_)[i] == def) {
-        return;
-      }
-    }
-    detached_defs_->Add(def);
-    // Follow inputs as detached definitions can reference other
-    // detached definitions.
-    for (intptr_t i = 0, n = def->InputCount(); i < n; ++i) {
-      Definition* input = def->InputAt(i)->definition();
-      if (IsDetachedDefinition(input)) {
-        AddDetachedDefinition(input);
-      }
-    }
-    ASSERT(def->env() == nullptr);
-  }
-
-  void CollectDetachedMaterializations(Environment* env) {
-    if (env == nullptr) {
-      return;
-    }
-    for (Environment::DeepIterator it(env); !it.Done(); it.Advance()) {
-      Definition* def = it.CurrentValue()->definition();
-      if (IsDetachedDefinition(def)) {
-        AddDetachedDefinition(def);
-      }
-    }
-  }
-
-  GrowableArray<intptr_t> block_num_;
-  GrowableArray<intptr_t> ssa_num_;
-  intptr_t current_ssa_index_ = 0;
-  ZoneGrowableArray<Definition*>* detached_defs_;
-};
-
-void FlowGraph::CompactSSA(ZoneGrowableArray<Definition*>* detached_defs) {
-  if (detached_defs == nullptr) {
-    detached_defs = new (Z) ZoneGrowableArray<Definition*>(Z, 0);
-  }
-  SSACompactor compactor(max_block_id() + 1, current_ssa_temp_index(),
-                         detached_defs);
-  compactor.RenumberGraph(this);
-}
-
 }  // namespace dart
diff --git a/runtime/vm/compiler/backend/flow_graph.h b/runtime/vm/compiler/backend/flow_graph.h
index 354e2fa..354e15f 100644
--- a/runtime/vm/compiler/backend/flow_graph.h
+++ b/runtime/vm/compiler/backend/flow_graph.h
@@ -208,9 +208,6 @@
   const GrowableArray<BlockEntryInstr*>& reverse_postorder() const {
     return reverse_postorder_;
   }
-  const GrowableArray<BlockEntryInstr*>& optimized_block_order() const {
-    return optimized_block_order_;
-  }
   static bool ShouldReorderBlocks(const Function& function, bool is_optimized);
   GrowableArray<BlockEntryInstr*>* CodegenBlockOrder(bool is_optimized);
 
@@ -536,14 +533,6 @@
   const Array& coverage_array() const { return *coverage_array_; }
   void set_coverage_array(const Array& array) { coverage_array_ = &array; }
 
-  // Renumbers SSA values and basic blocks to make numbering dense.
-  // Preserves order among block ids.
-  //
-  // Also collects definitions which are detached from the flow graph
-  // but still referenced (currently only MaterializeObject instructions
-  // can be detached).
-  void CompactSSA(ZoneGrowableArray<Definition*>* detached_defs = nullptr);
-
  private:
   friend class FlowGraphCompiler;  // TODO(ajcbik): restructure
   friend class FlowGraphChecker;
diff --git a/runtime/vm/compiler/backend/flow_graph_checker.cc b/runtime/vm/compiler/backend/flow_graph_checker.cc
index 6fad4a1..e3f8fdd 100644
--- a/runtime/vm/compiler/backend/flow_graph_checker.cc
+++ b/runtime/vm/compiler/backend/flow_graph_checker.cc
@@ -403,13 +403,6 @@
     ASSERT1(def->previous() != nullptr, def);
     // Skip checks below for common constants as checking them could be slow.
     if (IsCommonConstant(def)) return;
-  } else if (def->IsMaterializeObject()) {
-    // Materializations can be both linked into graph and detached.
-    if (def->next() != nullptr) {
-      ASSERT1(def->previous() != nullptr, def);
-    } else {
-      ASSERT1(def->previous() == nullptr, def);
-    }
   } else {
     // Others are fully linked into graph.
     ASSERT1(def->next() != nullptr, def);
@@ -460,14 +453,6 @@
     ASSERT1(instruction->IsGraphEntry() || instruction->next() != nullptr,
             instruction);
     ASSERT2(DefDominatesUse(def, instruction), def, instruction);
-  } else if (instruction->IsMaterializeObject()) {
-    // Materializations can be both linked into graph and detached.
-    if (instruction->next() != nullptr) {
-      ASSERT1(instruction->previous() != nullptr, instruction);
-      ASSERT2(DefDominatesUse(def, instruction), def, instruction);
-    } else {
-      ASSERT1(instruction->previous() == nullptr, instruction);
-    }
   } else {
     // Others are fully linked into graph.
     ASSERT1(IsControlFlow(instruction) || instruction->next() != nullptr,
diff --git a/runtime/vm/compiler/backend/il.cc b/runtime/vm/compiler/backend/il.cc
index 7182992..0dcade7 100644
--- a/runtime/vm/compiler/backend/il.cc
+++ b/runtime/vm/compiler/backend/il.cc
@@ -1057,11 +1057,6 @@
          (needs_number_check() == other_op->needs_number_check());
 }
 
-const RuntimeEntry& CaseInsensitiveCompareInstr::TargetFunction() const {
-  return handle_surrogates_ ? kCaseInsensitiveCompareUTF16RuntimeEntry
-                            : kCaseInsensitiveCompareUCS2RuntimeEntry;
-}
-
 bool MathMinMaxInstr::AttributesEqual(const Instruction& other) const {
   auto const other_op = other.AsMathMinMax();
   ASSERT(other_op != NULL);
@@ -3148,10 +3143,10 @@
     }
   }
 
-  if ((SpeculativeModeOfInput(0) == kGuardInputs) && !ComputeCanDeoptimize()) {
+  if ((speculative_mode_ == kGuardInputs) && !ComputeCanDeoptimize()) {
     // Remember if we ever learn out input doesn't require checking, as
     // the input Value might be later changed that would make us forget.
-    set_speculative_mode(kNotSpeculative);
+    speculative_mode_ = kNotSpeculative;
   }
 
   return this;
diff --git a/runtime/vm/compiler/backend/il.h b/runtime/vm/compiler/backend/il.h
index e8023e6..878c309 100644
--- a/runtime/vm/compiler/backend/il.h
+++ b/runtime/vm/compiler/backend/il.h
@@ -11,13 +11,11 @@
 
 #include <memory>
 #include <tuple>
-#include <type_traits>
 #include <utility>
 
 #include "vm/allocation.h"
 #include "vm/code_descriptors.h"
 #include "vm/compiler/backend/compile_type.h"
-#include "vm/compiler/backend/il_serializer.h"
 #include "vm/compiler/backend/locations.h"
 #include "vm/compiler/backend/slot.h"
 #include "vm/compiler/compiler_pass.h"
@@ -590,63 +588,6 @@
   DECLARE_INSTRUCTION_NO_BACKEND(type)                                         \
   DECLARE_COMPARISON_METHODS
 
-template <typename T, bool is_enum>
-struct unwrap_enum {};
-
-template <typename T>
-struct unwrap_enum<T, true> {
-  using type = std::underlying_type_t<T>;
-};
-
-template <typename T>
-struct unwrap_enum<T, false> {
-  using type = T;
-};
-
-template <typename T>
-using serializable_type_t =
-    typename unwrap_enum<std::remove_cv_t<T>, std::is_enum<T>::value>::type;
-
-#define WRITE_INSTRUCTION_FIELD(type, name)                                    \
-  s->Write<serializable_type_t<type>>(                                         \
-      static_cast<serializable_type_t<type>>(name));
-#define READ_INSTRUCTION_FIELD(type, name)                                     \
-  , name(static_cast<std::remove_cv_t<type>>(                                  \
-        d->Read<serializable_type_t<type>>()))
-#define DECLARE_INSTRUCTION_FIELD(type, name) type name;
-
-// Every instruction class should declare its serialization via
-// DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS, DECLARE_EMPTY_SERIALIZATION
-// or DECLARE_CUSTOM_SERIALIZATION.
-// If instruction class has fields which reference other instructions,
-// then it should also use DECLARE_EXTRA_SERIALIZATION and serialize
-// those references in WriteExtra/ReadExtra methods.
-#define DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(Instr, BaseClass, FieldList)   \
- public:                                                                       \
-  virtual void WriteTo(FlowGraphSerializer* s) {                               \
-    BaseClass::WriteTo(s);                                                     \
-    FieldList(WRITE_INSTRUCTION_FIELD)                                         \
-  }                                                                            \
-  explicit Instr(FlowGraphDeserializer* d)                                     \
-      : BaseClass(d) FieldList(READ_INSTRUCTION_FIELD) {}                      \
-                                                                               \
- private:                                                                      \
-  FieldList(DECLARE_INSTRUCTION_FIELD)
-
-#define DECLARE_CUSTOM_SERIALIZATION(Instr)                                    \
- public:                                                                       \
-  virtual void WriteTo(FlowGraphSerializer* s);                                \
-  explicit Instr(FlowGraphDeserializer* d);
-
-#define DECLARE_EMPTY_SERIALIZATION(Instr, BaseClass)                          \
- public:                                                                       \
-  explicit Instr(FlowGraphDeserializer* d) : BaseClass(d) {}
-
-#define DECLARE_EXTRA_SERIALIZATION                                            \
- public:                                                                       \
-  virtual void WriteExtra(FlowGraphSerializer* s);                             \
-  virtual void ReadExtra(FlowGraphDeserializer* d);
-
 #if defined(INCLUDE_IL_PRINTER)
 #define PRINT_TO_SUPPORT virtual void PrintTo(BaseTextBuffer* f) const;
 #define PRINT_OPERANDS_TO_SUPPORT                                              \
@@ -775,9 +716,6 @@
     return true;
   }
 
-  void Write(FlowGraphSerializer* s) const;
-  explicit CallTargets(FlowGraphDeserializer* d);
-
  private:
   void CreateHelper(Zone* zone, const ICData& ic_data);
   void MergeIntoRanges();
@@ -1332,9 +1270,6 @@
     return Location::kRegister;
   }
 
-  DECLARE_CUSTOM_SERIALIZATION(Instruction)
-  DECLARE_EXTRA_SERIALIZATION
-
  protected:
   // GetDeoptId and/or CopyDeoptIdFrom.
   friend class CallSiteInliner;
@@ -1353,12 +1288,6 @@
     deopt_id_ = instr.deopt_id_;
   }
 
-  // Write/read locs and environment, but not inputs.
-  // Used when one instruction embeds another and reuses their inputs
-  // (e.g. Branch/IfThenElse/CheckCondition wrap Comparison).
-  void WriteExtraWithoutInputs(FlowGraphSerializer* s);
-  void ReadExtraWithoutInputs(FlowGraphDeserializer* d);
-
  private:
   friend class BranchInstr;          // For RawSetInputAt.
   friend class IfThenElseInstr;      // For RawSetInputAt.
@@ -1411,8 +1340,6 @@
 
   virtual bool AllowsCSE() const { return true; }
   virtual bool HasUnknownSideEffects() const { return false; }
-
-  DECLARE_EMPTY_SERIALIZATION(PureInstruction, Instruction)
 };
 
 // Types to be used as ThrowsTrait for TemplateInstruction/TemplateDefinition.
@@ -1457,8 +1384,6 @@
 
   virtual bool MayThrow() const { return ThrowsTrait::kCanThrow; }
 
-  DECLARE_EMPTY_SERIALIZATION(TemplateInstruction, BaseClass)
-
  protected:
   EmbeddedArray<Value*, N> inputs_;
 
@@ -1559,8 +1484,6 @@
   }
 
   PRINT_TO_SUPPORT
-  DECLARE_EMPTY_SERIALIZATION(ParallelMoveInstr, TemplateInstruction)
-  DECLARE_EXTRA_SERIALIZATION
 
  private:
   GrowableArray<MoveOperands*> moves_;  // Elements cannot be null.
@@ -1701,9 +1624,6 @@
 
   DECLARE_ABSTRACT_INSTRUCTION(BlockEntry)
 
-  DECLARE_CUSTOM_SERIALIZATION(BlockEntryInstr)
-  DECLARE_EXTRA_SERIALIZATION
-
  protected:
   BlockEntryInstr(intptr_t block_id,
                   intptr_t try_index,
@@ -1854,9 +1774,6 @@
     return this;
   }
 
-  DECLARE_CUSTOM_SERIALIZATION(BlockEntryWithInitialDefs)
-  DECLARE_EXTRA_SERIALIZATION
-
  protected:
   void PrintInitialDefinitionsTo(BaseTextBuffer* f) const;
 
@@ -1939,8 +1856,6 @@
   }
 
   PRINT_TO_SUPPORT
-  DECLARE_CUSTOM_SERIALIZATION(GraphEntryInstr)
-  DECLARE_EXTRA_SERIALIZATION
 
  private:
   GraphEntryInstr(const ParsedFunction& parsed_function,
@@ -1973,9 +1888,8 @@
                  intptr_t deopt_id,
                  intptr_t stack_depth = 0)
       : BlockEntryInstr(block_id, try_index, deopt_id, stack_depth),
-        phis_(nullptr),
-        predecessors_(2)  // Two is the assumed to be the common case.
-  {}
+        predecessors_(2),  // Two is the assumed to be the common case.
+        phis_(NULL) {}
 
   DECLARE_INSTRUCTION(JoinEntry)
 
@@ -1999,14 +1913,6 @@
 
   PRINT_TO_SUPPORT
 
-#define FIELD_LIST(F) F(ZoneGrowableArray<PhiInstr*>*, phis_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(JoinEntryInstr,
-                                          BlockEntryInstr,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-  DECLARE_EXTRA_SERIALIZATION
-
  private:
   // Classes that have access to predecessors_ when inlining.
   friend class BlockEntryInstr;
@@ -2022,6 +1928,7 @@
   virtual void AddPredecessor(BlockEntryInstr* predecessor);
 
   GrowableArray<BlockEntryInstr*> predecessors_;
+  ZoneGrowableArray<PhiInstr*>* phis_;
 
   DISALLOW_COPY_AND_ASSIGN(JoinEntryInstr);
 };
@@ -2054,6 +1961,7 @@
                    intptr_t deopt_id,
                    intptr_t stack_depth = 0)
       : BlockEntryInstr(block_id, try_index, deopt_id, stack_depth),
+        predecessor_(NULL),
         edge_weight_(0.0) {}
 
   DECLARE_INSTRUCTION(TargetEntry)
@@ -2072,12 +1980,6 @@
 
   PRINT_TO_SUPPORT
 
-#define FIELD_LIST(F) F(double, edge_weight_)
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(TargetEntryInstr,
-                                          BlockEntryInstr,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  private:
   friend class BlockEntryInstr;  // Access to predecessor_ when inlining.
 
@@ -2087,8 +1989,8 @@
     predecessor_ = predecessor;
   }
 
-  // Not serialized, set in DiscoverBlocks.
-  BlockEntryInstr* predecessor_ = nullptr;
+  BlockEntryInstr* predecessor_;
+  double edge_weight_;
 
   DISALLOW_COPY_AND_ASSIGN(TargetEntryInstr);
 };
@@ -2127,7 +2029,6 @@
   GraphEntryInstr* graph_entry() const { return graph_entry_; }
 
   PRINT_TO_SUPPORT
-  DECLARE_CUSTOM_SERIALIZATION(FunctionEntryInstr)
 
  private:
   virtual void ClearPredecessors() { graph_entry_ = nullptr; }
@@ -2161,19 +2062,13 @@
 
   PRINT_TO_SUPPORT
 
-#define FIELD_LIST(F)                                                          \
-  F(const intptr_t, callback_id_)                                              \
-  F(const compiler::ffi::CallbackMarshaller&, marshaller_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(NativeEntryInstr,
-                                          FunctionEntryInstr,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  private:
   void SaveArguments(FlowGraphCompiler* compiler) const;
   void SaveArgument(FlowGraphCompiler* compiler,
                     const compiler::ffi::NativeLocation& loc) const;
+
+  const intptr_t callback_id_;
+  const compiler::ffi::CallbackMarshaller& marshaller_;
 };
 
 // Represents an OSR entrypoint to a function.
@@ -2202,7 +2097,6 @@
   GraphEntryInstr* graph_entry() const { return graph_entry_; }
 
   PRINT_TO_SUPPORT
-  DECLARE_CUSTOM_SERIALIZATION(OsrEntryInstr)
 
  private:
   virtual void ClearPredecessors() { graph_entry_ = nullptr; }
@@ -2231,12 +2125,8 @@
 
   PRINT_TO_SUPPORT
 
-#define FIELD_LIST(F) F(const intptr_t, indirect_id_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(IndirectEntryInstr,
-                                          JoinEntryInstr,
-                                          FIELD_LIST)
-#undef FIELD_LIST
+ private:
+  const intptr_t indirect_id_;
 };
 
 class CatchBlockEntryInstr : public BlockEntryWithInitialDefs {
@@ -2297,7 +2187,6 @@
   intptr_t catch_try_index() const { return catch_try_index_; }
 
   PRINT_TO_SUPPORT
-  DECLARE_CUSTOM_SERIALIZATION(CatchBlockEntryInstr)
 
  private:
   friend class BlockEntryInstr;  // Access to predecessor_ when inlining.
@@ -2312,6 +2201,7 @@
   BlockEntryInstr* predecessor_;
   const Array& catch_handler_types_;
   const intptr_t catch_try_index_;
+  GrowableArray<Definition*> initial_definitions_;
   const LocalVariable* exception_var_;
   const LocalVariable* stacktrace_var_;
   const LocalVariable* raw_exception_var_;
@@ -2376,9 +2266,6 @@
     return *this;
   }
 
-  void Write(FlowGraphSerializer* s) const;
-  explicit AliasIdentity(FlowGraphDeserializer* d);
-
  private:
   explicit AliasIdentity(intptr_t value) : value_(value) {}
 
@@ -2573,8 +2460,6 @@
   virtual Definition* AsDefinition() { return this; }
   virtual const Definition* AsDefinition() const { return this; }
 
-  DECLARE_CUSTOM_SERIALIZATION(Definition)
-
  protected:
   friend class RangeAnalysis;
   friend class Value;
@@ -2625,8 +2510,6 @@
 
   virtual bool AllowsCSE() const { return true; }
   virtual bool HasUnknownSideEffects() const { return false; }
-
-  DECLARE_EMPTY_SERIALIZATION(PureDefinition, Definition)
 };
 
 template <intptr_t N,
@@ -2647,7 +2530,6 @@
 
   virtual bool MayThrow() const { return ThrowsTrait::kCanThrow; }
 
-  DECLARE_EMPTY_SERIALIZATION(TemplateDefinition, BaseClass)
  protected:
   EmbeddedArray<Value*, N> inputs_;
 
@@ -2690,8 +2572,6 @@
   intptr_t InputCount() const { return inputs_.length(); }
   Value* InputAt(intptr_t i) const { return inputs_[i]; }
 
-  DECLARE_CUSTOM_SERIALIZATION(VariadicDefinition)
-
  protected:
   InputsArray inputs_;
 
@@ -2768,7 +2648,6 @@
   virtual Definition* Canonicalize(FlowGraph* flow_graph);
 
   PRINT_TO_SUPPORT
-  DECLARE_CUSTOM_SERIALIZATION(PhiInstr)
 
   enum ReceiverType { kUnknownReceiver = -1, kNotReceiver = 0, kReceiver = 1 };
 
@@ -2843,23 +2722,17 @@
 
   PRINT_OPERANDS_TO_SUPPORT
 
-#define FIELD_LIST(F)                                                          \
-  F(const intptr_t, index_)                                                    \
-  /* The offset (in words) of the last slot of the parameter, relative */      \
-  /* to the first parameter. */                                                \
-  /* It is used in the FlowGraphAllocator when it sets the assigned */         \
-  /* location and spill slot for the parameter definition. */                  \
-  F(const intptr_t, param_offset_)                                             \
-  F(const Register, base_reg_)                                                 \
-  F(const Representation, representation_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(ParameterInstr,
-                                          TemplateDefinition,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  private:
-  BlockEntryInstr* block_ = nullptr;
+  const intptr_t index_;
+
+  // The offset (in words) of the last slot of the parameter, relative
+  // to the first parameter.
+  // It is used in the FlowGraphAllocator when it sets the assigned location
+  // and spill slot for the parameter definition.
+  const intptr_t param_offset_;
+  const Register base_reg_;
+  const Representation representation_;
+  BlockEntryInstr* block_;
 
   DISALLOW_COPY_AND_ASSIGN(ParameterInstr);
 };
@@ -2892,16 +2765,10 @@
 
   PRINT_OPERANDS_TO_SUPPORT
 
-#define FIELD_LIST(F)                                                          \
-  F(const compiler::ffi::CallbackMarshaller&, marshaller_)                     \
-  F(const intptr_t, def_index_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(NativeParameterInstr,
-                                          TemplateDefinition,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  private:
+  const compiler::ffi::CallbackMarshaller& marshaller_;
+  const intptr_t def_index_;
+
   DISALLOW_COPY_AND_ASSIGN(NativeParameterInstr);
 };
 
@@ -2948,14 +2815,9 @@
 
   PRINT_OPERANDS_TO_SUPPORT
 
-#define FIELD_LIST(F) F(const intptr_t, offset_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(StoreIndexedUnsafeInstr,
-                                          TemplateInstruction,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  private:
+  const intptr_t offset_;
+
   DISALLOW_COPY_AND_ASSIGN(StoreIndexedUnsafeInstr);
 };
 
@@ -3003,16 +2865,10 @@
 
   PRINT_OPERANDS_TO_SUPPORT
 
-#define FIELD_LIST(F)                                                          \
-  F(const intptr_t, offset_)                                                   \
-  F(const Representation, representation_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(LoadIndexedUnsafeInstr,
-                                          TemplateDefinition,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  private:
+  const intptr_t offset_;
+  const Representation representation_;
+
   DISALLOW_COPY_AND_ASSIGN(LoadIndexedUnsafeInstr);
 };
 
@@ -3065,16 +2921,6 @@
   Value* dest_start() const { return inputs_[kDestStartPos]; }
   Value* length() const { return inputs_[kLengthPos]; }
 
-#define FIELD_LIST(F)                                                          \
-  F(classid_t, src_cid_)                                                       \
-  F(classid_t, dest_cid_)                                                      \
-  F(intptr_t, element_size_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(MemoryCopyInstr,
-                                          TemplateInstruction,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  private:
   // Set array_reg to point to the index indicated by start (contained in
   // start_reg) of the typed data or string in array (contained in array_reg).
@@ -3099,6 +2945,10 @@
     }
   }
 
+  classid_t src_cid_;
+  classid_t dest_cid_;
+  intptr_t element_size_;
+
   DISALLOW_COPY_AND_ASSIGN(MemoryCopyInstr);
 };
 
@@ -3133,14 +2983,9 @@
 
   PRINT_OPERANDS_TO_SUPPORT
 
-#define FIELD_LIST(F) F(const Code&, code_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(TailCallInstr,
-                                          TemplateInstruction,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  private:
+  const Code& code_;
+
   DISALLOW_COPY_AND_ASSIGN(TailCallInstr);
 };
 
@@ -3174,14 +3019,9 @@
 
   PRINT_OPERANDS_TO_SUPPORT
 
-#define FIELD_LIST(F) F(const Representation, representation_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(PushArgumentInstr,
-                                          TemplateDefinition,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  private:
+  const Representation representation_;
+
   DISALLOW_COPY_AND_ASSIGN(PushArgumentInstr);
 };
 
@@ -3249,17 +3089,11 @@
 
   PRINT_OPERANDS_TO_SUPPORT
 
-#define FIELD_LIST(F)                                                          \
-  F(const TokenPosition, token_pos_)                                           \
-  F(const intptr_t, yield_index_)                                              \
-  F(const Representation, representation_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(ReturnInstr,
-                                          TemplateInstruction,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  private:
+  const TokenPosition token_pos_;
+  const intptr_t yield_index_;
+  const Representation representation_;
+
   const Code& GetReturnStub(FlowGraphCompiler* compiler) const;
 
   DISALLOW_COPY_AND_ASSIGN(ReturnInstr);
@@ -3289,14 +3123,9 @@
     return false;
   }
 
-#define FIELD_LIST(F) F(const compiler::ffi::CallbackMarshaller&, marshaller_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(NativeReturnInstr,
-                                          ReturnInstr,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  private:
+  const compiler::ffi::CallbackMarshaller& marshaller_;
+
   void EmitReturnMoves(FlowGraphCompiler* compiler);
 
   DISALLOW_COPY_AND_ASSIGN(NativeReturnInstr);
@@ -3322,14 +3151,9 @@
 
   virtual bool HasUnknownSideEffects() const { return false; }
 
-#define FIELD_LIST(F) F(const TokenPosition, token_pos_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(ThrowInstr,
-                                          TemplateInstruction,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  private:
+  const TokenPosition token_pos_;
+
   DISALLOW_COPY_AND_ASSIGN(ThrowInstr);
 };
 
@@ -3362,16 +3186,10 @@
 
   virtual bool HasUnknownSideEffects() const { return false; }
 
-#define FIELD_LIST(F)                                                          \
-  F(const TokenPosition, token_pos_)                                           \
-  F(const intptr_t, catch_try_index_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(ReThrowInstr,
-                                          TemplateInstruction,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  private:
+  const TokenPosition token_pos_;
+  const intptr_t catch_try_index_;
+
   DISALLOW_COPY_AND_ASSIGN(ReThrowInstr);
 };
 
@@ -3389,14 +3207,9 @@
 
   virtual bool HasUnknownSideEffects() const { return false; }
 
-#define FIELD_LIST(F) F(const char*, message_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(StopInstr,
-                                          TemplateInstruction,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  private:
+  const char* message_;
+
   DISALLOW_COPY_AND_ASSIGN(StopInstr);
 };
 
@@ -3404,9 +3217,10 @@
  public:
   explicit GotoInstr(JoinEntryInstr* entry, intptr_t deopt_id)
       : TemplateInstruction(deopt_id),
+        block_(NULL),
+        successor_(entry),
         edge_weight_(0.0),
-        parallel_move_(nullptr),
-        successor_(entry) {}
+        parallel_move_(NULL) {}
 
   DECLARE_INSTRUCTION(Goto)
 
@@ -3456,23 +3270,14 @@
 
   PRINT_TO_SUPPORT
 
-#define FIELD_LIST(F)                                                          \
-  F(double, edge_weight_)                                                      \
-  /* Parallel move that will be used by linear scan register allocator to */   \
-  /* connect live ranges at the end of the block and resolve phis. */          \
-  F(ParallelMoveInstr*, parallel_move_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(GotoInstr,
-                                          TemplateInstruction,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-  DECLARE_EXTRA_SERIALIZATION
-
  private:
-  BlockEntryInstr* block_ = nullptr;
-  JoinEntryInstr* successor_ = nullptr;
+  BlockEntryInstr* block_;
+  JoinEntryInstr* successor_;
+  double edge_weight_;
 
-  DISALLOW_COPY_AND_ASSIGN(GotoInstr);
+  // Parallel move that will be used by linear scan register allocator to
+  // connect live ranges at the end of the block and resolve phis.
+  ParallelMoveInstr* parallel_move_;
 };
 
 // IndirectGotoInstr represents a dynamically computed jump. Only
@@ -3534,14 +3339,9 @@
 
   PRINT_TO_SUPPORT
 
-  DECLARE_CUSTOM_SERIALIZATION(IndirectGotoInstr)
-  DECLARE_EXTRA_SERIALIZATION
-
  private:
   GrowableArray<TargetEntryInstr*> successors_;
   const TypedData& offsets_;
-
-  DISALLOW_COPY_AND_ASSIGN(IndirectGotoInstr);
 };
 
 class ComparisonInstr : public Definition {
@@ -3593,17 +3393,6 @@
 
   DECLARE_ABSTRACT_INSTRUCTION(Comparison)
 
-#define FIELD_LIST(F)                                                          \
-  F(const TokenPosition, token_pos_)                                           \
-  F(Token::Kind, kind_)                                                        \
-  /* Set by optimizer. */                                                      \
-  F(intptr_t, operation_cid_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(ComparisonInstr,
-                                          Definition,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  protected:
   ComparisonInstr(const InstructionSource& source,
                   Token::Kind kind,
@@ -3614,6 +3403,10 @@
         operation_cid_(kIllegalCid) {}
 
  private:
+  const TokenPosition token_pos_;
+  Token::Kind kind_;
+  intptr_t operation_cid_;  // Set by optimizer.
+
   DISALLOW_COPY_AND_ASSIGN(ComparisonInstr);
 };
 
@@ -3622,7 +3415,6 @@
   virtual bool AllowsCSE() const { return true; }
   virtual bool HasUnknownSideEffects() const { return false; }
 
-  DECLARE_EMPTY_SERIALIZATION(PureComparison, ComparisonInstr)
  protected:
   PureComparison(const InstructionSource& source,
                  Token::Kind kind,
@@ -3636,20 +3428,17 @@
 class TemplateComparison
     : public CSETrait<ComparisonInstr, PureComparison>::Base {
  public:
-  using BaseClass = typename CSETrait<ComparisonInstr, PureComparison>::Base;
-
   TemplateComparison(const InstructionSource& source,
                      Token::Kind kind,
                      intptr_t deopt_id = DeoptId::kNone)
-      : BaseClass(source, kind, deopt_id), inputs_() {}
+      : CSETrait<ComparisonInstr, PureComparison>::Base(source, kind, deopt_id),
+        inputs_() {}
 
   virtual intptr_t InputCount() const { return N; }
   virtual Value* InputAt(intptr_t i) const { return inputs_[i]; }
 
   virtual bool MayThrow() const { return ThrowsTrait::kCanThrow; }
 
-  DECLARE_EMPTY_SERIALIZATION(TemplateComparison, BaseClass)
-
  protected:
   EmbeddedArray<Value*, N> inputs_;
 
@@ -3660,7 +3449,7 @@
 class BranchInstr : public Instruction {
  public:
   explicit BranchInstr(ComparisonInstr* comparison, intptr_t deopt_id)
-      : Instruction(deopt_id), comparison_(comparison) {
+      : Instruction(deopt_id), comparison_(comparison), constant_target_(NULL) {
     ASSERT(comparison->env() == NULL);
     for (intptr_t i = comparison->InputCount() - 1; i >= 0; --i) {
       comparison->InputAt(i)->set_instruction(this);
@@ -3740,20 +3529,15 @@
 
   PRINT_TO_SUPPORT
 
-#define FIELD_LIST(F) F(ComparisonInstr*, comparison_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(BranchInstr, Instruction, FIELD_LIST)
-#undef FIELD_LIST
-  DECLARE_EXTRA_SERIALIZATION
-
  private:
   virtual void RawSetInputAt(intptr_t i, Value* value) {
     comparison()->RawSetInputAt(i, value);
   }
 
-  TargetEntryInstr* true_successor_ = nullptr;
-  TargetEntryInstr* false_successor_ = nullptr;
-  TargetEntryInstr* constant_target_ = nullptr;
+  TargetEntryInstr* true_successor_;
+  TargetEntryInstr* false_successor_;
+  ComparisonInstr* comparison_;
+  TargetEntryInstr* constant_target_;
 
   DISALLOW_COPY_AND_ASSIGN(BranchInstr);
 };
@@ -3769,14 +3553,9 @@
 
   DECLARE_INSTRUCTION(Deoptimize)
 
-#define FIELD_LIST(F) F(const ICData::DeoptReasonId, deopt_reason_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(DeoptimizeInstr,
-                                          TemplateInstruction,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  private:
+  const ICData::DeoptReasonId deopt_reason_;
+
   DISALLOW_COPY_AND_ASSIGN(DeoptimizeInstr);
 };
 
@@ -3805,14 +3584,8 @@
 
   PRINT_OPERANDS_TO_SUPPORT
 
-#define FIELD_LIST(F) F(CompileType*, constrained_type_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(RedefinitionInstr,
-                                          TemplateDefinition,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  private:
+  CompileType* constrained_type_;
   DISALLOW_COPY_AND_ASSIGN(RedefinitionInstr);
 };
 
@@ -3836,15 +3609,14 @@
 
   PRINT_OPERANDS_TO_SUPPORT
 
-  DECLARE_EMPTY_SERIALIZATION(ReachabilityFenceInstr, TemplateInstruction)
-
  private:
   DISALLOW_COPY_AND_ASSIGN(ReachabilityFenceInstr);
 };
 
 class ConstraintInstr : public TemplateDefinition<1, NoThrow> {
  public:
-  ConstraintInstr(Value* value, Range* constraint) : constraint_(constraint) {
+  ConstraintInstr(Value* value, Range* constraint)
+      : constraint_(constraint), target_(NULL) {
     SetInputAt(0, value);
   }
 
@@ -3874,16 +3646,9 @@
 
   PRINT_OPERANDS_TO_SUPPORT
 
-#define FIELD_LIST(F) F(Range*, constraint_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(ConstraintInstr,
-                                          TemplateDefinition,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-  DECLARE_EXTRA_SERIALIZATION
-
  private:
-  TargetEntryInstr* target_ = nullptr;
+  Range* constraint_;
+  TargetEntryInstr* target_;
 
   DISALLOW_COPY_AND_ASSIGN(ConstraintInstr);
 };
@@ -3935,16 +3700,10 @@
 
   PRINT_OPERANDS_TO_SUPPORT
 
-#define FIELD_LIST(F)                                                          \
-  F(const Object&, value_)                                                     \
-  F(const TokenPosition, token_pos_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(ConstantInstr,
-                                          TemplateDefinition,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  private:
+  const Object& value_;
+  const TokenPosition token_pos_;
+
   DISALLOW_COPY_AND_ASSIGN(ConstantInstr);
 };
 
@@ -3962,7 +3721,6 @@
   uword constant_address() const { return constant_address_; }
 
   DECLARE_INSTRUCTION(UnboxedConstant)
-  DECLARE_CUSTOM_SERIALIZATION(UnboxedConstantInstr)
 
  private:
   const Representation representation_;
@@ -4027,14 +3785,9 @@
 
   PRINT_OPERANDS_TO_SUPPORT
 
-#define FIELD_LIST(F) F(const TokenPosition, token_pos_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(AssertSubtypeInstr,
-                                          TemplateInstruction,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  private:
+  const TokenPosition token_pos_;
+
   DISALLOW_COPY_AND_ASSIGN(AssertSubtypeInstr);
 };
 
@@ -4128,17 +3881,11 @@
 
   PRINT_OPERANDS_TO_SUPPORT
 
-#define FIELD_LIST(F)                                                          \
-  F(const TokenPosition, token_pos_)                                           \
-  F(const String&, dst_name_)                                                  \
-  F(const Kind, kind_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(AssertAssignableInstr,
-                                          TemplateDefinition,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  private:
+  const TokenPosition token_pos_;
+  const String& dst_name_;
+  const Kind kind_;
+
   DISALLOW_COPY_AND_ASSIGN(AssertAssignableInstr);
 };
 
@@ -4173,14 +3920,9 @@
 
   PRINT_OPERANDS_TO_SUPPORT
 
-#define FIELD_LIST(F) F(const TokenPosition, token_pos_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(AssertBooleanInstr,
-                                          TemplateDefinition,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  private:
+  const TokenPosition token_pos_;
+
   DISALLOW_COPY_AND_ASSIGN(AssertBooleanInstr);
 };
 
@@ -4232,16 +3974,9 @@
 
   PRINT_OPERANDS_TO_SUPPORT
 
-#define FIELD_LIST(F) F(const SpecialParameterKind, kind_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(SpecialParameterInstr,
-                                          TemplateDefinition,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-  DECLARE_EXTRA_SERIALIZATION
-
  private:
-  BlockEntryInstr* block_ = nullptr;
+  const SpecialParameterKind kind_;
+  BlockEntryInstr* block_;
   DISALLOW_COPY_AND_ASSIGN(SpecialParameterInstr);
 };
 
@@ -4348,19 +4083,11 @@
         ArgumentsSizeWithoutTypeArgs(), argument_names());
   }
 
-#define FIELD_LIST(F)                                                          \
-  F(const intptr_t, type_args_len_)                                            \
-  F(const Array&, argument_names_)                                             \
-  F(const TokenPosition, token_pos_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(TemplateDartCall,
-                                          VariadicDefinition,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-  DECLARE_EXTRA_SERIALIZATION
-
  private:
+  intptr_t type_args_len_;
+  const Array& argument_names_;
   PushArgumentsArray* push_arguments_ = nullptr;
+  TokenPosition token_pos_;
 
   DISALLOW_COPY_AND_ASSIGN(TemplateDartCall);
 };
@@ -4386,7 +4113,6 @@
   virtual bool HasUnknownSideEffects() const { return true; }
 
   PRINT_OPERANDS_TO_SUPPORT
-  DECLARE_EMPTY_SERIALIZATION(ClosureCallInstr, TemplateDartCall)
 
  private:
   DISALLOW_COPY_AND_ASSIGN(ClosureCallInstr);
@@ -4417,10 +4143,7 @@
         interface_target_(interface_target),
         tearoff_interface_target_(tearoff_interface_target),
         result_type_(nullptr),
-        has_unique_selector_(false),
-        entry_kind_(Code::EntryKind::kNormal),
-        receiver_is_not_smi_(false),
-        is_call_on_this_(false) {
+        has_unique_selector_(false) {
     ASSERT(function_name.IsNotTemporaryScopedHandle());
     ASSERT(interface_target.IsNotTemporaryScopedHandle());
     ASSERT(tearoff_interface_target.IsNotTemporaryScopedHandle());
@@ -4515,31 +4238,23 @@
 
   virtual Representation representation() const;
 
-#define FIELD_LIST(F)                                                          \
-  F(const ICData*, ic_data_)                                                   \
-  F(const String&, function_name_)                                             \
-  /* Binary op, unary op, kGET or kILLEGAL. */                                 \
-  F(const Token::Kind, token_kind_)                                            \
-  F(const Function&, interface_target_)                                        \
-  F(const Function&, tearoff_interface_target_)                                \
-  /* Inferred result type. */                                                  \
-  F(CompileType*, result_type_)                                                \
-  F(bool, has_unique_selector_)                                                \
-  F(Code::EntryKind, entry_kind_)                                              \
-  F(bool, receiver_is_not_smi_)                                                \
-  F(bool, is_call_on_this_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(InstanceCallBaseInstr,
-                                          TemplateDartCall,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  protected:
   friend class CallSpecializer;
   void set_ic_data(ICData* value) { ic_data_ = value; }
   void set_result_type(CompileType* result_type) { result_type_ = result_type; }
 
  private:
+  const ICData* ic_data_;
+  const String& function_name_;
+  const Token::Kind token_kind_;  // Binary op, unary op, kGET or kILLEGAL.
+  const Function& interface_target_;
+  const Function& tearoff_interface_target_;
+  CompileType* result_type_;  // Inferred result type.
+  bool has_unique_selector_;
+  Code::EntryKind entry_kind_ = Code::EntryKind::kNormal;
+  bool receiver_is_not_smi_ = false;
+  bool is_call_on_this_ = false;
+
   DISALLOW_COPY_AND_ASSIGN(InstanceCallBaseInstr);
 };
 
@@ -4568,8 +4283,7 @@
             deopt_id,
             interface_target,
             tearoff_interface_target),
-        checked_argument_count_(checked_argument_count),
-        receivers_static_type_(nullptr) {}
+        checked_argument_count_(checked_argument_count) {}
 
   InstanceCallInstr(
       const InstructionSource& source,
@@ -4592,8 +4306,7 @@
                               deopt_id,
                               interface_target,
                               tearoff_interface_target),
-        checked_argument_count_(checked_argument_count),
-        receivers_static_type_(nullptr) {}
+        checked_argument_count_(checked_argument_count) {}
 
   DECLARE_INSTRUCTION(InstanceCall)
 
@@ -4622,18 +4335,11 @@
   const CallTargets& Targets();
   void SetTargets(const CallTargets* targets) { targets_ = targets; }
 
-#define FIELD_LIST(F)                                                          \
-  F(const intptr_t, checked_argument_count_)                                   \
-  F(const AbstractType*, receivers_static_type_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(InstanceCallInstr,
-                                          InstanceCallBaseInstr,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  private:
   const CallTargets* targets_ = nullptr;
   const class BinaryFeedback* binary_ = nullptr;
+  const intptr_t checked_argument_count_;
+  const AbstractType* receivers_static_type_ = nullptr;
 
   DISALLOW_COPY_AND_ASSIGN(InstanceCallInstr);
 };
@@ -4696,16 +4402,6 @@
 
   PRINT_OPERANDS_TO_SUPPORT
 
-#define FIELD_LIST(F)                                                          \
-  F(const CallTargets&, targets_)                                              \
-  F(const bool, complete_)                                                     \
-  F(intptr_t, total_call_count_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(PolymorphicInstanceCallInstr,
-                                          InstanceCallBaseInstr,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  private:
   PolymorphicInstanceCallInstr(const InstructionSource& source,
                                const String& function_name,
@@ -4735,6 +4431,10 @@
     total_call_count_ = CallCount();
   }
 
+  const CallTargets& targets_;
+  const bool complete_;
+  intptr_t total_call_count_;
+
   friend class PolymorphicInliner;
 
   DISALLOW_COPY_AND_ASSIGN(PolymorphicInstanceCallInstr);
@@ -4810,16 +4510,10 @@
 
   PRINT_OPERANDS_TO_SUPPORT
 
-#define FIELD_LIST(F)                                                          \
-  F(const Function&, interface_target_)                                        \
-  F(const compiler::TableSelector*, selector_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(DispatchTableCallInstr,
-                                          TemplateDartCall,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  private:
+  const Function& interface_target_;
+  const compiler::TableSelector* selector_;
+
   DISALLOW_COPY_AND_ASSIGN(DispatchTableCallInstr);
 };
 
@@ -4849,16 +4543,6 @@
 
   PRINT_OPERANDS_TO_SUPPORT;
 
-#define FIELD_LIST(F)                                                          \
-  /* True if the comparison must check for double or Mint and */               \
-  /* use value comparison instead. */                                          \
-  F(bool, needs_number_check_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(StrictCompareInstr,
-                                          TemplateComparison,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  private:
   Condition EmitComparisonCodeRegConstant(FlowGraphCompiler* compiler,
                                           BranchLabels labels,
@@ -4870,6 +4554,10 @@
                        const Object& obj,
                        Condition* condition_out);
 
+  // True if the comparison must check for double or Mint and
+  // use value comparison instead.
+  bool needs_number_check_;
+
   DISALLOW_COPY_AND_ASSIGN(StrictCompareInstr);
 };
 
@@ -4899,8 +4587,6 @@
     return kTagged;
   }
 
-  DECLARE_EMPTY_SERIALIZATION(TestSmiInstr, TemplateComparison)
-
  private:
   DISALLOW_COPY_AND_ASSIGN(TestSmiInstr);
 };
@@ -4946,16 +4632,9 @@
 
   PRINT_OPERANDS_TO_SUPPORT
 
-#define FIELD_LIST(F)                                                          \
-  F(const ZoneGrowableArray<intptr_t>&, cid_results_)                          \
-  F(bool, licm_hoisted_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(TestCidsInstr,
-                                          TemplateComparison,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  private:
+  const ZoneGrowableArray<intptr_t>& cid_results_;
+  bool licm_hoisted_;
   DISALLOW_COPY_AND_ASSIGN(TestCidsInstr);
 };
 
@@ -5011,16 +4690,9 @@
 
   PRINT_OPERANDS_TO_SUPPORT
 
-#define FIELD_LIST(F)                                                          \
-  F(bool, null_aware_)                                                         \
-  F(const SpeculativeMode, speculative_mode_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(EqualityCompareInstr,
-                                          TemplateComparison,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  private:
+  bool null_aware_;
+  const SpeculativeMode speculative_mode_;
   DISALLOW_COPY_AND_ASSIGN(EqualityCompareInstr);
 };
 
@@ -5067,14 +4739,8 @@
 
   PRINT_OPERANDS_TO_SUPPORT
 
-#define FIELD_LIST(F) F(const SpeculativeMode, speculative_mode_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(RelationalOpInstr,
-                                          TemplateComparison,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  private:
+  const SpeculativeMode speculative_mode_;
   DISALLOW_COPY_AND_ASSIGN(RelationalOpInstr);
 };
 
@@ -5149,22 +4815,15 @@
 
   PRINT_OPERANDS_TO_SUPPORT
 
-#define FIELD_LIST(F)                                                          \
-  F(ComparisonInstr*, comparison_)                                             \
-  F(const intptr_t, if_true_)                                                  \
-  F(const intptr_t, if_false_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(IfThenElseInstr,
-                                          Definition,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-  DECLARE_EXTRA_SERIALIZATION
-
  private:
   virtual void RawSetInputAt(intptr_t i, Value* value) {
     comparison()->RawSetInputAt(i, value);
   }
 
+  ComparisonInstr* comparison_;
+  const intptr_t if_true_;
+  const intptr_t if_false_;
+
   DISALLOW_COPY_AND_ASSIGN(IfThenElseInstr);
 };
 
@@ -5189,7 +4848,6 @@
         rebind_rule_(rebind_rule),
         result_type_(NULL),
         is_known_list_constructor_(false),
-        entry_kind_(Code::EntryKind::kNormal),
         identity_(AliasIdentity::Unknown()) {
     ASSERT(function.IsZoneHandle());
     ASSERT(!function.IsNull());
@@ -5214,7 +4872,6 @@
         rebind_rule_(rebind_rule),
         result_type_(NULL),
         is_known_list_constructor_(false),
-        entry_kind_(Code::EntryKind::kNormal),
         identity_(AliasIdentity::Unknown()) {
     ASSERT(function.IsZoneHandle());
     ASSERT(!function.IsNull());
@@ -5333,26 +4990,21 @@
 
   PRINT_OPERANDS_TO_SUPPORT
 
-#define FIELD_LIST(F)                                                          \
-  F(const ICData*, ic_data_)                                                   \
-  F(const intptr_t, call_count_)                                               \
-  F(const Function&, function_)                                                \
-  F(const ICData::RebindRule, rebind_rule_)                                    \
-  /* Known or inferred result type. */                                         \
-  F(CompileType*, result_type_)                                                \
-  /* 'True' for recognized list constructors. */                               \
-  F(bool, is_known_list_constructor_)                                          \
-  F(Code::EntryKind, entry_kind_)                                              \
-  F(AliasIdentity, identity_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(StaticCallInstr,
-                                          TemplateDartCall,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  private:
+  const ICData* ic_data_;
   const CallTargets* targets_ = nullptr;
   const class BinaryFeedback* binary_ = nullptr;
+  const intptr_t call_count_;
+  const Function& function_;
+  const ICData::RebindRule rebind_rule_;
+  CompileType* result_type_;  // Known or inferred result type.
+
+  // 'True' for recognized list constructors.
+  bool is_known_list_constructor_;
+
+  Code::EntryKind entry_kind_ = Code::EntryKind::kNormal;
+
+  AliasIdentity identity_;
 
   DISALLOW_COPY_AND_ASSIGN(StaticCallInstr);
 };
@@ -5384,17 +5036,11 @@
 
   PRINT_OPERANDS_TO_SUPPORT
 
-#define FIELD_LIST(F)                                                          \
-  F(const LocalVariable&, local_)                                              \
-  F(bool, is_last_)                                                            \
-  F(const TokenPosition, token_pos_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(LoadLocalInstr,
-                                          TemplateDefinition,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  private:
+  const LocalVariable& local_;
+  bool is_last_;
+  const TokenPosition token_pos_;
+
   DISALLOW_COPY_AND_ASSIGN(LoadLocalInstr);
 };
 
@@ -5434,21 +5080,14 @@
 
   PRINT_OPERANDS_TO_SUPPORT
 
-#define FIELD_LIST(F)                                                          \
-  F(const intptr_t, num_temps_)                                                \
-  F(const bool, has_input_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(DropTempsInstr,
-                                          Definition,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  private:
   virtual void RawSetInputAt(intptr_t i, Value* value) {
     ASSERT(has_input_);
     value_ = value;
   }
 
+  const intptr_t num_temps_;
+  const bool has_input_;
   Value* value_ = nullptr;
 
   DISALLOW_COPY_AND_ASSIGN(DropTempsInstr);
@@ -5490,15 +5129,9 @@
 
   PRINT_OPERANDS_TO_SUPPORT
 
-#define FIELD_LIST(F) F(ConstantInstr*, null_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(MakeTempInstr,
-                                          TemplateDefinition,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-  DECLARE_EXTRA_SERIALIZATION
-
  private:
+  ConstantInstr* null_;
+
   DISALLOW_COPY_AND_ASSIGN(MakeTempInstr);
 };
 
@@ -5538,18 +5171,12 @@
 
   PRINT_OPERANDS_TO_SUPPORT
 
-#define FIELD_LIST(F)                                                          \
-  F(const LocalVariable&, local_)                                              \
-  F(bool, is_dead_)                                                            \
-  F(bool, is_last_)                                                            \
-  F(const TokenPosition, token_pos_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(StoreLocalInstr,
-                                          TemplateDefinition,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  private:
+  const LocalVariable& local_;
+  bool is_dead_;
+  bool is_last_;
+  const TokenPosition token_pos_;
+
   DISALLOW_COPY_AND_ASSIGN(StoreLocalInstr);
 };
 
@@ -5567,8 +5194,11 @@
                          source),
         native_name_(name),
         function_(function),
-        token_pos_(source.token_pos),
-        link_lazily_(link_lazily) {
+        native_c_function_(NULL),
+        is_bootstrap_native_(false),
+        is_auto_scope_(true),
+        link_lazily_(link_lazily),
+        token_pos_(source.token_pos) {
     ASSERT(name.IsZoneHandle());
     ASSERT(function.IsZoneHandle());
   }
@@ -5594,16 +5224,6 @@
 
   PRINT_OPERANDS_TO_SUPPORT
 
-#define FIELD_LIST(F)                                                          \
-  F(const String&, native_name_)                                               \
-  F(const Function&, function_)                                                \
-  F(const TokenPosition, token_pos_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(NativeCallInstr,
-                                          TemplateDartCall,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  private:
   void set_native_c_function(NativeFunction value) {
     native_c_function_ = value;
@@ -5612,12 +5232,13 @@
   void set_is_bootstrap_native(bool value) { is_bootstrap_native_ = value; }
   void set_is_auto_scope(bool value) { is_auto_scope_ = value; }
 
-  // These fields are not serialized.
-  // IL serialization only supports lazy linking of native functions.
-  NativeFunction native_c_function_ = nullptr;
-  bool is_bootstrap_native_ = false;
-  bool is_auto_scope_ = true;
-  bool link_lazily_ = true;
+  const String& native_name_;
+  const Function& function_;
+  NativeFunction native_c_function_;
+  bool is_bootstrap_native_;
+  bool is_auto_scope_;
+  bool link_lazily_;
+  const TokenPosition token_pos_;
 
   DISALLOW_COPY_AND_ASSIGN(NativeCallInstr);
 };
@@ -5682,15 +5303,6 @@
 
   PRINT_OPERANDS_TO_SUPPORT
 
-#define FIELD_LIST(F)                                                          \
-  F(const compiler::ffi::CallMarshaller&, marshaller_)                         \
-  F(bool, is_leaf_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(FfiCallInstr,
-                                          VariadicDefinition,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  private:
   LocationSummary* MakeLocationSummaryInternal(Zone* zone,
                                                bool is_optimizing,
@@ -5708,6 +5320,9 @@
                        const Register temp0,
                        const Register temp1);
 
+  const compiler::ffi::CallMarshaller& marshaller_;
+  bool is_leaf_;
+
   DISALLOW_COPY_AND_ASSIGN(FfiCallInstr);
 };
 
@@ -5745,15 +5360,9 @@
 
   PRINT_OPERANDS_TO_SUPPORT
 
-#define FIELD_LIST(F)                                                          \
-  F(const compiler::ffi::NativeCallingConvention&, native_calling_convention_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(CCallInstr,
-                                          VariadicDefinition,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  private:
+  const compiler::ffi::NativeCallingConvention& native_calling_convention_;
+
   DISALLOW_COPY_AND_ASSIGN(CCallInstr);
 };
 
@@ -5781,14 +5390,9 @@
   virtual bool ComputeCanDeoptimize() const { return false; }
   virtual bool HasUnknownSideEffects() const { return false; }
 
-#define FIELD_LIST(F) F(const int32_t, offset_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(RawStoreFieldInstr,
-                                          TemplateInstruction,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  private:
+  const int32_t offset_;
+
   DISALLOW_COPY_AND_ASSIGN(RawStoreFieldInstr);
 };
 
@@ -5808,16 +5412,10 @@
   virtual bool HasUnknownSideEffects() const { return true; }
   virtual Instruction* Canonicalize(FlowGraph* flow_graph);
 
-#define FIELD_LIST(F)                                                          \
-  F(const TokenPosition, token_pos_)                                           \
-  F(const UntaggedPcDescriptors::Kind, stub_kind_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(DebugStepCheckInstr,
-                                          TemplateInstruction,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  private:
+  const TokenPosition token_pos_;
+  const UntaggedPcDescriptors::Kind stub_kind_;
+
   DISALLOW_COPY_AND_ASSIGN(DebugStepCheckInstr);
 };
 
@@ -5968,19 +5566,6 @@
 
   PRINT_OPERANDS_TO_SUPPORT
 
-#define FIELD_LIST(F)                                                          \
-  F(const Slot&, slot_)                                                        \
-  F(StoreBarrierType, emit_store_barrier_)                                     \
-  F(compiler::Assembler::MemoryOrder, memory_order_)                           \
-  F(const TokenPosition, token_pos_)                                           \
-  /* Marks initializing stores. E.g. in the constructor. */                    \
-  F(const bool, is_initialization_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(StoreFieldInstr,
-                                          TemplateInstruction,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  private:
   friend class JitCallSpecializer;  // For ASSERT(initialization_).
 
@@ -5993,6 +5578,13 @@
                                        : compiler::Assembler::kValueIsNotSmi;
   }
 
+  const Slot& slot_;
+  StoreBarrierType emit_store_barrier_;
+  compiler::Assembler::MemoryOrder memory_order_;
+  const TokenPosition token_pos_;
+  // Marks initializing stores. E.g. in the constructor.
+  const bool is_initialization_;
+
   DISALLOW_COPY_AND_ASSIGN(StoreFieldInstr);
 };
 
@@ -6016,14 +5608,9 @@
 
   PRINT_OPERANDS_TO_SUPPORT
 
-#define FIELD_LIST(F) F(const Field&, field_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(GuardFieldInstr,
-                                          TemplateInstruction,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  private:
+  const Field& field_;
+
   DISALLOW_COPY_AND_ASSIGN(GuardFieldInstr);
 };
 
@@ -6040,8 +5627,6 @@
 
   virtual bool AttributesEqual(const Instruction& other) const;
 
-  DECLARE_EMPTY_SERIALIZATION(GuardFieldClassInstr, GuardFieldInstr)
-
  private:
   DISALLOW_COPY_AND_ASSIGN(GuardFieldClassInstr);
 };
@@ -6059,8 +5644,6 @@
 
   virtual bool AttributesEqual(const Instruction& other) const;
 
-  DECLARE_EMPTY_SERIALIZATION(GuardFieldLengthInstr, GuardFieldInstr)
-
  private:
   DISALLOW_COPY_AND_ASSIGN(GuardFieldLengthInstr);
 };
@@ -6084,8 +5667,6 @@
 
   virtual bool AttributesEqual(const Instruction& other) const;
 
-  DECLARE_EMPTY_SERIALIZATION(GuardFieldTypeInstr, GuardFieldInstr)
-
  private:
   DISALLOW_COPY_AND_ASSIGN(GuardFieldTypeInstr);
 };
@@ -6144,15 +5725,11 @@
   virtual bool CanTriggerGC() const { return calls_initializer(); }
   virtual bool MayThrow() const { return calls_initializer(); }
 
-#define FIELD_LIST(F)                                                          \
-  F(const TokenPosition, token_pos_)                                           \
-  F(const bool, throw_exception_on_initialization_)                            \
-  F(bool, calls_initializer_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(TemplateLoadField, Base, FIELD_LIST)
-#undef FIELD_LIST
-
  private:
+  const TokenPosition token_pos_;
+  const bool throw_exception_on_initialization_;
+  bool calls_initializer_;
+
   DISALLOW_COPY_AND_ASSIGN(TemplateLoadField);
 };
 
@@ -6187,14 +5764,9 @@
 
   PRINT_OPERANDS_TO_SUPPORT
 
-#define FIELD_LIST(F) F(const Field&, field_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(LoadStaticFieldInstr,
-                                          TemplateLoadField,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  private:
+  const Field& field_;
+
   DISALLOW_COPY_AND_ASSIGN(LoadStaticFieldInstr);
 };
 
@@ -6229,15 +5801,6 @@
 
   PRINT_OPERANDS_TO_SUPPORT
 
-#define FIELD_LIST(F)                                                          \
-  F(const Field&, field_)                                                      \
-  F(const TokenPosition, token_pos_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(StoreStaticFieldInstr,
-                                          TemplateDefinition,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  private:
   compiler::Assembler::CanBeSmi CanValueBeSmi() const {
     ASSERT(value()->Type()->ToNullableCid() != kSmiCid);
@@ -6245,6 +5808,9 @@
                                        : compiler::Assembler::kValueIsNotSmi;
   }
 
+  const Field& field_;
+  const TokenPosition token_pos_;
+
   DISALLOW_COPY_AND_ASSIGN(StoreStaticFieldInstr);
 };
 
@@ -6315,21 +5881,14 @@
 
   virtual Definition* Canonicalize(FlowGraph* flow_graph);
 
-#define FIELD_LIST(F)                                                          \
-  F(const bool, index_unboxed_)                                                \
-  F(const intptr_t, index_scale_)                                              \
-  F(const intptr_t, class_id_)                                                 \
-  F(const AlignmentType, alignment_)                                           \
-  F(const TokenPosition, token_pos_)                                           \
-  /* derived from call */                                                      \
-  F(CompileType*, result_type_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(LoadIndexedInstr,
-                                          TemplateDefinition,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  private:
+  const bool index_unboxed_;
+  const intptr_t index_scale_;
+  const intptr_t class_id_;
+  const AlignmentType alignment_;
+  const TokenPosition token_pos_;
+  CompileType* result_type_;  // derived from call
+
   DISALLOW_COPY_AND_ASSIGN(LoadIndexedInstr);
 };
 
@@ -6403,18 +5962,12 @@
     return !can_pack_into_smi() && (representation() == kTagged);
   }
 
-#define FIELD_LIST(F)                                                          \
-  F(const intptr_t, class_id_)                                                 \
-  F(const TokenPosition, token_pos_)                                           \
-  F(const intptr_t, element_count_)                                            \
-  F(Representation, representation_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(LoadCodeUnitsInstr,
-                                          TemplateDefinition,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  private:
+  const intptr_t class_id_;
+  const TokenPosition token_pos_;
+  const intptr_t element_count_;
+  Representation representation_;
+
   DISALLOW_COPY_AND_ASSIGN(LoadCodeUnitsInstr);
 };
 
@@ -6434,9 +5987,6 @@
 
   virtual bool AttributesEqual(const Instruction& other) const { return true; }
 
-  DECLARE_EMPTY_SERIALIZATION(OneByteStringFromCharCodeInstr,
-                              TemplateDefinition)
-
  private:
   DISALLOW_COPY_AND_ASSIGN(OneByteStringFromCharCodeInstr);
 };
@@ -6459,14 +6009,9 @@
     return other.AsStringToCharCode()->cid_ == cid_;
   }
 
-#define FIELD_LIST(F) F(const intptr_t, cid_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(StringToCharCodeInstr,
-                                          TemplateDefinition,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  private:
+  const intptr_t cid_;
+
   DISALLOW_COPY_AND_ASSIGN(StringToCharCodeInstr);
 };
 
@@ -6538,14 +6083,9 @@
 
   PRINT_TO_SUPPORT
 
-#define FIELD_LIST(F) F(const Slot&, scan_flags_field_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(Utf8ScanInstr,
-                                          TemplateDefinition,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  private:
+  const Slot& scan_flags_field_;
+
   DISALLOW_COPY_AND_ASSIGN(Utf8ScanInstr);
 };
 
@@ -6619,25 +6159,19 @@
 
   virtual Instruction* Canonicalize(FlowGraph* flow_graph);
 
-#define FIELD_LIST(F)                                                          \
-  F(StoreBarrierType, emit_store_barrier_)                                     \
-  F(const bool, index_unboxed_)                                                \
-  F(const intptr_t, index_scale_)                                              \
-  F(const intptr_t, class_id_)                                                 \
-  F(const AlignmentType, alignment_)                                           \
-  F(const TokenPosition, token_pos_)                                           \
-  F(const SpeculativeMode, speculative_mode_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(StoreIndexedInstr,
-                                          TemplateInstruction,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  private:
   compiler::Assembler::CanBeSmi CanValueBeSmi() const {
     return compiler::Assembler::kValueCanBeSmi;
   }
 
+  StoreBarrierType emit_store_barrier_;
+  const bool index_unboxed_;
+  const intptr_t index_scale_;
+  const intptr_t class_id_;
+  const AlignmentType alignment_;
+  const TokenPosition token_pos_;
+  const SpeculativeMode speculative_mode_;
+
   DISALLOW_COPY_AND_ASSIGN(StoreIndexedInstr);
 };
 
@@ -6658,17 +6192,11 @@
   virtual bool HasUnknownSideEffects() const { return false; }
   virtual Instruction* Canonicalize(FlowGraph* flow_graph);
 
-#define FIELD_LIST(F)                                                          \
-  F(const Array&, coverage_array_)                                             \
-  F(const intptr_t, coverage_index_)                                           \
-  F(const TokenPosition, token_pos_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(RecordCoverageInstr,
-                                          TemplateInstruction,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  private:
+  const Array& coverage_array_;
+  const intptr_t coverage_index_;
+  const TokenPosition token_pos_;
+
   DISALLOW_COPY_AND_ASSIGN(RecordCoverageInstr);
 };
 
@@ -6688,8 +6216,6 @@
 
   virtual Definition* Canonicalize(FlowGraph* flow_graph);
 
-  DECLARE_EMPTY_SERIALIZATION(BooleanNegateInstr, TemplateDefinition)
-
  private:
   DISALLOW_COPY_AND_ASSIGN(BooleanNegateInstr);
 };
@@ -6729,16 +6255,12 @@
 
   PRINT_OPERANDS_TO_SUPPORT
 
-#define FIELD_LIST(F)                                                          \
-  F(const TokenPosition, token_pos_)                                           \
-  F(const AbstractType&, type_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(InstanceOfInstr,
-                                          TemplateDefinition,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  private:
+  const TokenPosition token_pos_;
+  Value* value_;
+  Value* type_arguments_;
+  const AbstractType& type_;
+
   DISALLOW_COPY_AND_ASSIGN(InstanceOfInstr);
 };
 
@@ -6802,16 +6324,10 @@
 
   DECLARE_ABSTRACT_INSTRUCTION(Allocation);
 
-#define FIELD_LIST(F)                                                          \
-  F(const TokenPosition, token_pos_)                                           \
-  F(AliasIdentity, identity_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(AllocationInstr,
-                                          Definition,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  private:
+  const TokenPosition token_pos_;
+  AliasIdentity identity_;
+
   DISALLOW_COPY_AND_ASSIGN(AllocationInstr);
 };
 
@@ -6825,8 +6341,6 @@
   virtual intptr_t InputCount() const { return N; }
   virtual Value* InputAt(intptr_t i) const { return inputs_[i]; }
 
-  DECLARE_EMPTY_SERIALIZATION(TemplateAllocation, AllocationInstr)
-
  protected:
   EmbeddedArray<Value*, N> inputs_;
 
@@ -6848,7 +6362,6 @@
       : AllocationInstr(source, deopt_id),
         cls_(cls),
         has_type_arguments_(type_arguments != nullptr),
-        type_arguments_slot_(nullptr),
         type_arguments_(type_arguments) {
     ASSERT(cls.IsZoneHandle());
     ASSERT(!cls.IsNull());
@@ -6888,23 +6401,16 @@
 
   PRINT_OPERANDS_TO_SUPPORT
 
-#define FIELD_LIST(F)                                                          \
-  F(const Class&, cls_)                                                        \
-  F(const bool, has_type_arguments_)                                           \
-  F(const Slot*, type_arguments_slot_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(AllocateObjectInstr,
-                                          AllocationInstr,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  private:
   virtual void RawSetInputAt(intptr_t i, Value* value) {
     ASSERT(has_type_arguments_ && (i == kTypeArgumentsPos));
     type_arguments_ = value;
   }
 
-  Value* type_arguments_ = nullptr;
+  const Class& cls_;
+  const bool has_type_arguments_;
+  Value* type_arguments_;
+  const Slot* type_arguments_slot_ = nullptr;
 
   DISALLOW_COPY_AND_ASSIGN(AllocateObjectInstr);
 };
@@ -6956,8 +6462,6 @@
         compiler::target::Closure::InstanceSize());
   }
 
-  DECLARE_EMPTY_SERIALIZATION(AllocateClosureInstr, TemplateAllocation)
-
  private:
   DISALLOW_COPY_AND_ASSIGN(AllocateClosureInstr);
 };
@@ -6984,14 +6488,9 @@
 
   PRINT_OPERANDS_TO_SUPPORT
 
-#define FIELD_LIST(F) F(const intptr_t, num_context_variables_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(AllocateUninitializedContextInstr,
-                                          TemplateAllocation,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  private:
+  const intptr_t num_context_variables_;
+
   DISALLOW_COPY_AND_ASSIGN(AllocateUninitializedContextInstr);
 };
 
@@ -7006,11 +6505,13 @@
                          const ZoneGrowableArray<const Slot*>& slots,
                          InputsArray&& values)
       : VariadicDefinition(std::move(values)),
+        allocation_(allocation),
         cls_(cls),
         num_elements_(num_elements),
         slots_(slots),
-        registers_remapped_(false),
-        allocation_(allocation) {
+        locations_(nullptr),
+        visited_for_liveness_(false),
+        registers_remapped_(false) {
     ASSERT(slots_.length() == InputCount());
   }
 
@@ -7023,10 +6524,7 @@
     return slots_[i]->offset_in_bytes();
   }
 
-  const Location& LocationAt(intptr_t i) {
-    ASSERT(0 <= i && i < InputCount());
-    return locations_[i];
-  }
+  const Location& LocationAt(intptr_t i) { return locations_[i]; }
 
   DECLARE_INSTRUCTION(MaterializeObject)
 
@@ -7055,24 +6553,15 @@
 
   PRINT_OPERANDS_TO_SUPPORT
 
-#define FIELD_LIST(F)                                                          \
-  F(const Class&, cls_)                                                        \
-  F(intptr_t, num_elements_)                                                   \
-  F(const ZoneGrowableArray<const Slot*>&, slots_)                             \
-  F(bool, registers_remapped_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(MaterializeObjectInstr,
-                                          VariadicDefinition,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-  DECLARE_EXTRA_SERIALIZATION
-
  private:
-  Location* locations_ = nullptr;
+  AllocationInstr* allocation_;
+  const Class& cls_;
+  intptr_t num_elements_;
+  const ZoneGrowableArray<const Slot*>& slots_;
+  Location* locations_;
 
-  // Not serialized.
-  AllocationInstr* allocation_ = nullptr;
-  bool visited_for_liveness_ = false;
+  bool visited_for_liveness_;
+  bool registers_remapped_;
 
   DISALLOW_COPY_AND_ASSIGN(MaterializeObjectInstr);
 };
@@ -7094,8 +6583,6 @@
 
   DECLARE_ABSTRACT_INSTRUCTION(ArrayAllocation);
 
-  DECLARE_EMPTY_SERIALIZATION(ArrayAllocationInstr, AllocationInstr)
-
  private:
   DISALLOW_COPY_AND_ASSIGN(ArrayAllocationInstr);
 };
@@ -7110,15 +6597,11 @@
   virtual intptr_t InputCount() const { return N; }
   virtual Value* InputAt(intptr_t i) const { return inputs_[i]; }
 
-  DECLARE_EMPTY_SERIALIZATION(TemplateArrayAllocation, ArrayAllocationInstr)
-
  protected:
   EmbeddedArray<Value*, N> inputs_;
 
  private:
   virtual void RawSetInputAt(intptr_t i, Value* value) { inputs_[i] = value; }
-
-  DISALLOW_COPY_AND_ASSIGN(TemplateArrayAllocation);
 };
 
 class CreateArrayInstr : public TemplateArrayAllocation<2> {
@@ -7160,8 +6643,6 @@
     }
   }
 
-  DECLARE_EMPTY_SERIALIZATION(CreateArrayInstr, TemplateArrayAllocation)
-
  private:
   DISALLOW_COPY_AND_ASSIGN(CreateArrayInstr);
 };
@@ -7200,14 +6681,9 @@
     }
   }
 
-#define FIELD_LIST(F) F(const classid_t, class_id_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(AllocateTypedDataInstr,
-                                          TemplateArrayAllocation,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  private:
+  const classid_t class_id_;
+
   DISALLOW_COPY_AND_ASSIGN(AllocateTypedDataInstr);
 };
 
@@ -7244,14 +6720,9 @@
 
   PRINT_OPERANDS_TO_SUPPORT
 
-#define FIELD_LIST(F) F(const intptr_t, offset_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(LoadUntaggedInstr,
-                                          TemplateDefinition,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  private:
+  intptr_t offset_;
+
   DISALLOW_COPY_AND_ASSIGN(LoadUntaggedInstr);
 };
 
@@ -7283,16 +6754,10 @@
 
   PRINT_OPERANDS_TO_SUPPORT
 
-#define FIELD_LIST(F)                                                          \
-  F(const Representation, representation_)                                     \
-  F(const bool, input_can_be_smi_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(LoadClassIdInstr,
-                                          TemplateDefinition,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  private:
+  const Representation representation_;
+  const bool input_can_be_smi_;
+
   DISALLOW_COPY_AND_ASSIGN(LoadClassIdInstr);
 };
 
@@ -7372,13 +6837,6 @@
 
   PRINT_OPERANDS_TO_SUPPORT
 
-#define FIELD_LIST(F) F(const Slot&, slot_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(LoadFieldInstr,
-                                          TemplateLoadField,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  private:
   intptr_t OffsetInBytes() const { return slot().offset_in_bytes(); }
 
@@ -7386,6 +6844,8 @@
   // calls initializer if it is not. Field value is already loaded.
   void EmitNativeCodeForInitializerCall(FlowGraphCompiler* compiler);
 
+  const Slot& slot_;
+
   DISALLOW_COPY_AND_ASSIGN(LoadFieldInstr);
 };
 
@@ -7423,16 +6883,10 @@
 
   PRINT_OPERANDS_TO_SUPPORT
 
-#define FIELD_LIST(F)                                                          \
-  F(const TokenPosition, token_pos_)                                           \
-  F(const AbstractType&, type_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(InstantiateTypeInstr,
-                                          TemplateDefinition,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  private:
+  const TokenPosition token_pos_;
+  const AbstractType& type_;
+
   DISALLOW_COPY_AND_ASSIGN(InstantiateTypeInstr);
 };
 
@@ -7515,17 +6969,11 @@
 
   PRINT_OPERANDS_TO_SUPPORT
 
-#define FIELD_LIST(F)                                                          \
-  F(const TokenPosition, token_pos_)                                           \
-  F(const Class&, instantiator_class_)                                         \
-  F(const Function&, function_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(InstantiateTypeArgumentsInstr,
-                                          TemplateDefinition,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  private:
+  const TokenPosition token_pos_;
+  const Class& instantiator_class_;
+  const Function& function_;
+
   DISALLOW_COPY_AND_ASSIGN(InstantiateTypeArgumentsInstr);
 };
 
@@ -7558,14 +7006,9 @@
 
   PRINT_OPERANDS_TO_SUPPORT
 
-#define FIELD_LIST(F) F(const ZoneGrowableArray<const Slot*>&, context_slots_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(AllocateContextInstr,
-                                          TemplateAllocation,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  private:
+  const ZoneGrowableArray<const Slot*>& context_slots_;
+
   DISALLOW_COPY_AND_ASSIGN(AllocateContextInstr);
 };
 
@@ -7606,16 +7049,10 @@
 
   virtual bool HasUnknownSideEffects() const { return false; }
 
-#define FIELD_LIST(F)                                                          \
-  F(const TokenPosition, token_pos_)                                           \
-  F(const ZoneGrowableArray<const Slot*>&, context_slots_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(CloneContextInstr,
-                                          TemplateDefinition,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  private:
+  const TokenPosition token_pos_;
+  const ZoneGrowableArray<const Slot*>& context_slots_;
+
   DISALLOW_COPY_AND_ASSIGN(CloneContextInstr);
 };
 
@@ -7640,14 +7077,9 @@
 
   void set_licm_hoisted(bool value) { licm_hoisted_ = value; }
 
-#define FIELD_LIST(F) F(bool, licm_hoisted_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(CheckEitherNonSmiInstr,
-                                          TemplateInstruction,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  private:
+  bool licm_hoisted_;
+
   DISALLOW_COPY_AND_ASSIGN(CheckEitherNonSmiInstr);
 };
 
@@ -7698,13 +7130,6 @@
     return kNotSpeculative;
   }
 
-#define FIELD_LIST(F) F(const Representation, from_representation_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(BoxInstr,
-                                          TemplateDefinition,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  protected:
   BoxInstr(Representation from_representation, Value* value)
       : from_representation_(from_representation) {
@@ -7716,6 +7141,8 @@
     return Boxing::ValueOffset(from_representation());
   }
 
+  const Representation from_representation_;
+
   DISALLOW_COPY_AND_ASSIGN(BoxInstr);
 };
 
@@ -7737,8 +7164,6 @@
 
   DECLARE_ABSTRACT_INSTRUCTION(BoxInteger)
 
-  DECLARE_EMPTY_SERIALIZATION(BoxIntegerInstr, BoxInstr)
-
  private:
   DISALLOW_COPY_AND_ASSIGN(BoxIntegerInstr);
 };
@@ -7755,8 +7180,6 @@
 
   DECLARE_INSTRUCTION(BoxSmallInt)
 
-  DECLARE_EMPTY_SERIALIZATION(BoxSmallIntInstr, BoxIntegerInstr)
-
  private:
   DISALLOW_COPY_AND_ASSIGN(BoxSmallIntInstr);
 };
@@ -7768,8 +7191,6 @@
 
   DECLARE_INSTRUCTION_BACKEND()
 
-  DECLARE_EMPTY_SERIALIZATION(BoxInteger32Instr, BoxIntegerInstr)
-
  private:
   DISALLOW_COPY_AND_ASSIGN(BoxInteger32Instr);
 };
@@ -7781,8 +7202,6 @@
 
   DECLARE_INSTRUCTION_NO_BACKEND(BoxInt32)
 
-  DECLARE_EMPTY_SERIALIZATION(BoxInt32Instr, BoxInteger32Instr)
-
  private:
   DISALLOW_COPY_AND_ASSIGN(BoxInt32Instr);
 };
@@ -7794,8 +7213,6 @@
 
   DECLARE_INSTRUCTION_NO_BACKEND(BoxUint32)
 
-  DECLARE_EMPTY_SERIALIZATION(BoxUint32Instr, BoxInteger32Instr)
-
  private:
   DISALLOW_COPY_AND_ASSIGN(BoxUint32Instr);
 };
@@ -7809,8 +7226,6 @@
 
   DECLARE_INSTRUCTION(BoxInt64)
 
-  DECLARE_EMPTY_SERIALIZATION(BoxInt64Instr, BoxIntegerInstr)
-
  private:
   DISALLOW_COPY_AND_ASSIGN(BoxInt64Instr);
 };
@@ -7864,15 +7279,6 @@
 
   virtual TokenPosition token_pos() const { return TokenPosition::kBox; }
 
-#define FIELD_LIST(F)                                                          \
-  F(const Representation, representation_)                                     \
-  F(SpeculativeMode, speculative_mode_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(UnboxInstr,
-                                          TemplateDefinition,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  protected:
   UnboxInstr(Representation representation,
              Value* value,
@@ -7884,10 +7290,6 @@
     SetInputAt(0, value);
   }
 
-  void set_speculative_mode(SpeculativeMode value) {
-    speculative_mode_ = value;
-  }
-
  private:
   bool CanConvertSmi() const;
   void EmitLoadFromBox(FlowGraphCompiler* compiler);
@@ -7900,6 +7302,10 @@
 
   intptr_t ValueOffset() const { return Boxing::ValueOffset(representation_); }
 
+ protected:
+  const Representation representation_;
+  SpeculativeMode speculative_mode_;
+
   DISALLOW_COPY_AND_ASSIGN(UnboxInstr);
 };
 
@@ -7933,14 +7339,9 @@
 
   PRINT_OPERANDS_TO_SUPPORT
 
-#define FIELD_LIST(F) F(bool, is_truncating_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(UnboxIntegerInstr,
-                                          UnboxInstr,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  private:
+  bool is_truncating_;
+
   DISALLOW_COPY_AND_ASSIGN(UnboxIntegerInstr);
 };
 
@@ -7959,8 +7360,6 @@
 
   DECLARE_INSTRUCTION_BACKEND()
 
-  DECLARE_EMPTY_SERIALIZATION(UnboxInteger32Instr, UnboxIntegerInstr)
-
  private:
   DISALLOW_COPY_AND_ASSIGN(UnboxInteger32Instr);
 };
@@ -7984,8 +7383,6 @@
 
   DECLARE_INSTRUCTION_NO_BACKEND(UnboxUint32)
 
-  DECLARE_EMPTY_SERIALIZATION(UnboxUint32Instr, UnboxInteger32Instr)
-
  private:
   DISALLOW_COPY_AND_ASSIGN(UnboxUint32Instr);
 };
@@ -8010,8 +7407,6 @@
 
   DECLARE_INSTRUCTION_NO_BACKEND(UnboxInt32)
 
-  DECLARE_EMPTY_SERIALIZATION(UnboxInt32Instr, UnboxInteger32Instr)
-
  private:
   DISALLOW_COPY_AND_ASSIGN(UnboxInt32Instr);
 };
@@ -8041,8 +7436,6 @@
 
   DECLARE_INSTRUCTION_NO_BACKEND(UnboxInt64)
 
-  DECLARE_EMPTY_SERIALIZATION(UnboxInt64Instr, UnboxIntegerInstr)
-
  private:
   DISALLOW_COPY_AND_ASSIGN(UnboxInt64Instr);
 };
@@ -8101,21 +7494,16 @@
 
   PRINT_OPERANDS_TO_SUPPORT
 
-#define FIELD_LIST(F) F(const MathUnaryKind, kind_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(MathUnaryInstr,
-                                          TemplateDefinition,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  private:
+  const MathUnaryKind kind_;
+
   DISALLOW_COPY_AND_ASSIGN(MathUnaryInstr);
 };
 
 // Calls into the runtime and performs a case-insensitive comparison of the
 // UTF16 strings (i.e. TwoByteString or ExternalTwoByteString) located at
 // str[lhs_index:lhs_index + length] and str[rhs_index:rhs_index + length].
-// Depending on [handle_surrogates], we will treat the strings as either
+// Depending on the runtime entry passed, we will treat the strings as either
 // UCS2 (no surrogate handling) or UTF16 (surrogates handled appropriately).
 class CaseInsensitiveCompareInstr
     : public TemplateDefinition<4, NoThrow, Pure> {
@@ -8124,9 +7512,9 @@
                               Value* lhs_index,
                               Value* rhs_index,
                               Value* length,
-                              bool handle_surrogates,
+                              const RuntimeEntry& entry,
                               intptr_t cid)
-      : handle_surrogates_(handle_surrogates), cid_(cid) {
+      : entry_(entry), cid_(cid) {
     ASSERT(cid == kTwoByteStringCid || cid == kExternalTwoByteStringCid);
     ASSERT(index_scale() == 2);
     SetInputAt(0, str);
@@ -8140,7 +7528,7 @@
   Value* rhs_index() const { return inputs_[2]; }
   Value* length() const { return inputs_[3]; }
 
-  const RuntimeEntry& TargetFunction() const;
+  const RuntimeEntry& TargetFunction() const { return entry_; }
   bool IsExternal() const { return cid_ == kExternalTwoByteStringCid; }
   intptr_t class_id() const { return cid_; }
 
@@ -8156,21 +7544,13 @@
   virtual CompileType ComputeType() const;
 
   virtual bool AttributesEqual(const Instruction& other) const {
-    const auto* other_compare = other.AsCaseInsensitiveCompare();
-    return (other_compare->handle_surrogates_ == handle_surrogates_) &&
-           (other_compare->cid_ == cid_);
+    return other.AsCaseInsensitiveCompare()->cid_ == cid_;
   }
 
-#define FIELD_LIST(F)                                                          \
-  F(const bool, handle_surrogates_)                                            \
-  F(const intptr_t, cid_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(CaseInsensitiveCompareInstr,
-                                          TemplateDefinition,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  private:
+  const RuntimeEntry& entry_;
+  const intptr_t cid_;
+
   DISALLOW_COPY_AND_ASSIGN(CaseInsensitiveCompareInstr);
 };
 
@@ -8225,16 +7605,10 @@
   virtual CompileType ComputeType() const;
   virtual bool AttributesEqual(const Instruction& other) const;
 
-#define FIELD_LIST(F)                                                          \
-  F(const MethodRecognizer::Kind, op_kind_)                                    \
-  F(const intptr_t, result_cid_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(MathMinMaxInstr,
-                                          TemplateDefinition,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  private:
+  const MethodRecognizer::Kind op_kind_;
+  const intptr_t result_cid_;
+
   DISALLOW_COPY_AND_ASSIGN(MathMinMaxInstr);
 };
 
@@ -8293,17 +7667,11 @@
            (speculative_mode_ == other_bin_op->speculative_mode_);
   }
 
-#define FIELD_LIST(F)                                                          \
-  F(const Token::Kind, op_kind_)                                               \
-  F(const TokenPosition, token_pos_)                                           \
-  F(const SpeculativeMode, speculative_mode_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(BinaryDoubleOpInstr,
-                                          TemplateDefinition,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  private:
+  const Token::Kind op_kind_;
+  const TokenPosition token_pos_;
+  const SpeculativeMode speculative_mode_;
+
   DISALLOW_COPY_AND_ASSIGN(BinaryDoubleOpInstr);
 };
 
@@ -8343,14 +7711,9 @@
 
   virtual ComparisonInstr* CopyWithNewOperands(Value* left, Value* right);
 
-#define FIELD_LIST(F) F(const MethodRecognizer::Kind, op_kind_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(DoubleTestOpInstr,
-                                          TemplateComparison,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  private:
+  const MethodRecognizer::Kind op_kind_;
+
   DISALLOW_COPY_AND_ASSIGN(DoubleTestOpInstr);
 };
 
@@ -8385,15 +7748,8 @@
 
   DECLARE_ABSTRACT_INSTRUCTION(UnaryIntegerOp)
 
-#define FIELD_LIST(F) F(const Token::Kind, op_kind_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(UnaryIntegerOpInstr,
-                                          TemplateDefinition,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  private:
-  DISALLOW_COPY_AND_ASSIGN(UnaryIntegerOpInstr);
+  const Token::Kind op_kind_;
 };
 
 // Handles both Smi operations: BIT_OR and NEGATE.
@@ -8410,8 +7766,6 @@
 
   DECLARE_INSTRUCTION(UnarySmiOp)
 
-  DECLARE_EMPTY_SERIALIZATION(UnarySmiOpInstr, UnaryIntegerOpInstr)
-
  private:
   DISALLOW_COPY_AND_ASSIGN(UnarySmiOpInstr);
 };
@@ -8440,8 +7794,6 @@
 
   DECLARE_INSTRUCTION(UnaryUint32Op)
 
-  DECLARE_EMPTY_SERIALIZATION(UnaryUint32OpInstr, UnaryIntegerOpInstr)
-
  private:
   DISALLOW_COPY_AND_ASSIGN(UnaryUint32OpInstr);
 };
@@ -8480,14 +7832,8 @@
 
   DECLARE_INSTRUCTION(UnaryInt64Op)
 
-#define FIELD_LIST(F) F(const SpeculativeMode, speculative_mode_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(UnaryInt64OpInstr,
-                                          UnaryIntegerOpInstr,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  private:
+  const SpeculativeMode speculative_mode_;
   DISALLOW_COPY_AND_ASSIGN(UnaryInt64OpInstr);
 };
 
@@ -8556,16 +7902,6 @@
 
   DECLARE_ABSTRACT_INSTRUCTION(BinaryIntegerOp)
 
-#define FIELD_LIST(F)                                                          \
-  F(const Token::Kind, op_kind_)                                               \
-  F(bool, can_overflow_)                                                       \
-  F(bool, is_truncating_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(BinaryIntegerOpInstr,
-                                          TemplateDefinition,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  protected:
   void InferRangeHelper(const Range* left_range,
                         const Range* right_range,
@@ -8574,6 +7910,11 @@
  private:
   Definition* CreateConstantResult(FlowGraph* graph, const Integer& result);
 
+  const Token::Kind op_kind_;
+
+  bool can_overflow_;
+  bool is_truncating_;
+
   DISALLOW_COPY_AND_ASSIGN(BinaryIntegerOpInstr);
 };
 
@@ -8597,14 +7938,9 @@
 
   Range* right_range() const { return right_range_; }
 
-#define FIELD_LIST(F) F(Range*, right_range_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(BinarySmiOpInstr,
-                                          BinaryIntegerOpInstr,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  private:
+  Range* right_range_;
+
   DISALLOW_COPY_AND_ASSIGN(BinarySmiOpInstr);
 };
 
@@ -8660,8 +7996,6 @@
 
   DECLARE_INSTRUCTION(BinaryInt32Op)
 
-  DECLARE_EMPTY_SERIALIZATION(BinaryInt32OpInstr, BinaryIntegerOpInstr)
-
  private:
   DISALLOW_COPY_AND_ASSIGN(BinaryInt32OpInstr);
 };
@@ -8704,8 +8038,6 @@
 
   DECLARE_INSTRUCTION(BinaryUint32Op)
 
-  DECLARE_EMPTY_SERIALIZATION(BinaryUint32OpInstr, BinaryIntegerOpInstr)
-
  private:
   DISALLOW_COPY_AND_ASSIGN(BinaryUint32OpInstr);
 };
@@ -8751,14 +8083,8 @@
 
   DECLARE_INSTRUCTION(BinaryInt64Op)
 
-#define FIELD_LIST(F) F(const SpeculativeMode, speculative_mode_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(BinaryInt64OpInstr,
-                                          BinaryIntegerOpInstr,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  private:
+  const SpeculativeMode speculative_mode_;
   DISALLOW_COPY_AND_ASSIGN(BinaryInt64OpInstr);
 };
 
@@ -8787,13 +8113,6 @@
 
   DECLARE_ABSTRACT_INSTRUCTION(ShiftIntegerOp)
 
-#define FIELD_LIST(F) F(Range*, shift_range_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(ShiftIntegerOpInstr,
-                                          BinaryIntegerOpInstr,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  protected:
   static const intptr_t kShiftCountLimit = 63;
 
@@ -8802,6 +8121,8 @@
   bool IsShiftCountInRange(int64_t max = kShiftCountLimit) const;
 
  private:
+  Range* shift_range_;
+
   DISALLOW_COPY_AND_ASSIGN(ShiftIntegerOpInstr);
 };
 
@@ -8833,8 +8154,6 @@
 
   DECLARE_INSTRUCTION(ShiftInt64Op)
 
-  DECLARE_EMPTY_SERIALIZATION(ShiftInt64OpInstr, ShiftIntegerOpInstr)
-
  private:
   DISALLOW_COPY_AND_ASSIGN(ShiftInt64OpInstr);
 };
@@ -8866,8 +8185,6 @@
 
   DECLARE_INSTRUCTION(SpeculativeShiftInt64Op)
 
-  DECLARE_EMPTY_SERIALIZATION(SpeculativeShiftInt64OpInstr, ShiftIntegerOpInstr)
-
  private:
   DISALLOW_COPY_AND_ASSIGN(SpeculativeShiftInt64OpInstr);
 };
@@ -8900,8 +8217,6 @@
 
   DECLARE_INSTRUCTION(ShiftUint32Op)
 
-  DECLARE_EMPTY_SERIALIZATION(ShiftUint32OpInstr, ShiftIntegerOpInstr)
-
  private:
   static const intptr_t kUint32ShiftCountLimit = 31;
 
@@ -8932,9 +8247,6 @@
 
   virtual CompileType ComputeType() const;
 
-  DECLARE_EMPTY_SERIALIZATION(SpeculativeShiftUint32OpInstr,
-                              ShiftIntegerOpInstr)
-
  private:
   static const intptr_t kUint32ShiftCountLimit = 31;
 
@@ -8986,16 +8298,10 @@
 
   PRINT_OPERANDS_TO_SUPPORT
 
-#define FIELD_LIST(F)                                                          \
-  F(const Token::Kind, op_kind_)                                               \
-  F(const SpeculativeMode, speculative_mode_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(UnaryDoubleOpInstr,
-                                          TemplateDefinition,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  private:
+  const Token::Kind op_kind_;
+  const SpeculativeMode speculative_mode_;
+
   DISALLOW_COPY_AND_ASSIGN(UnaryDoubleOpInstr);
 };
 
@@ -9046,18 +8352,12 @@
 
   PRINT_OPERANDS_TO_SUPPORT
 
-#define FIELD_LIST(F)                                                          \
-  F(const TokenPosition, token_pos_)                                           \
-  F(const intptr_t, stack_depth_)                                              \
-  F(const intptr_t, loop_depth_)                                               \
-  F(const Kind, kind_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(CheckStackOverflowInstr,
-                                          TemplateInstruction,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  private:
+  const TokenPosition token_pos_;
+  const intptr_t stack_depth_;
+  const intptr_t loop_depth_;
+  const Kind kind_;
+
   DISALLOW_COPY_AND_ASSIGN(CheckStackOverflowInstr);
 };
 
@@ -9081,14 +8381,9 @@
 
   virtual bool AttributesEqual(const Instruction& other) const { return true; }
 
-#define FIELD_LIST(F) F(const TokenPosition, token_pos_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(SmiToDoubleInstr,
-                                          TemplateDefinition,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  private:
+  const TokenPosition token_pos_;
+
   DISALLOW_COPY_AND_ASSIGN(SmiToDoubleInstr);
 };
 
@@ -9112,8 +8407,6 @@
 
   virtual bool AttributesEqual(const Instruction& other) const { return true; }
 
-  DECLARE_EMPTY_SERIALIZATION(Int32ToDoubleInstr, TemplateDefinition)
-
  private:
   DISALLOW_COPY_AND_ASSIGN(Int32ToDoubleInstr);
 };
@@ -9155,14 +8448,9 @@
     return speculative_mode_ == other.AsInt64ToDouble()->speculative_mode_;
   }
 
-#define FIELD_LIST(F) F(const SpeculativeMode, speculative_mode_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(Int64ToDoubleInstr,
-                                          TemplateDefinition,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  private:
+  const SpeculativeMode speculative_mode_;
+
   DISALLOW_COPY_AND_ASSIGN(Int64ToDoubleInstr);
 };
 
@@ -9207,14 +8495,9 @@
     return other.AsDoubleToInteger()->recognized_kind() == recognized_kind();
   }
 
-#define FIELD_LIST(F) F(const MethodRecognizer::Kind, recognized_kind_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(DoubleToIntegerInstr,
-                                          TemplateDefinition,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  private:
+  const MethodRecognizer::Kind recognized_kind_;
+
   DISALLOW_COPY_AND_ASSIGN(DoubleToIntegerInstr);
 };
 
@@ -9243,8 +8526,6 @@
 
   virtual bool AttributesEqual(const Instruction& other) const { return true; }
 
-  DECLARE_EMPTY_SERIALIZATION(DoubleToSmiInstr, TemplateDefinition)
-
  private:
   DISALLOW_COPY_AND_ASSIGN(DoubleToSmiInstr);
 };
@@ -9288,14 +8569,9 @@
     return other.AsDoubleToDouble()->recognized_kind() == recognized_kind();
   }
 
-#define FIELD_LIST(F) F(const MethodRecognizer::Kind, recognized_kind_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(DoubleToDoubleInstr,
-                                          TemplateDefinition,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  private:
+  const MethodRecognizer::Kind recognized_kind_;
+
   DISALLOW_COPY_AND_ASSIGN(DoubleToDoubleInstr);
 };
 
@@ -9333,14 +8609,9 @@
 
   virtual Definition* Canonicalize(FlowGraph* flow_graph);
 
-#define FIELD_LIST(F) F(const SpeculativeMode, speculative_mode_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(DoubleToFloatInstr,
-                                          TemplateDefinition,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  private:
+  const SpeculativeMode speculative_mode_;
+
   DISALLOW_COPY_AND_ASSIGN(DoubleToFloatInstr);
 };
 
@@ -9372,8 +8643,6 @@
 
   virtual Definition* Canonicalize(FlowGraph* flow_graph);
 
-  DECLARE_EMPTY_SERIALIZATION(FloatToDoubleInstr, TemplateDefinition)
-
  private:
   DISALLOW_COPY_AND_ASSIGN(FloatToDoubleInstr);
 };
@@ -9429,16 +8698,10 @@
 
   PRINT_OPERANDS_TO_SUPPORT
 
-#define FIELD_LIST(F)                                                          \
-  F(const MethodRecognizer::Kind, recognized_kind_)                            \
-  F(const TokenPosition, token_pos_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(InvokeMathCFunctionInstr,
-                                          VariadicDefinition,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  private:
+  const MethodRecognizer::Kind recognized_kind_;
+  const TokenPosition token_pos_;
+
   DISALLOW_COPY_AND_ASSIGN(InvokeMathCFunctionInstr);
 };
 
@@ -9483,17 +8746,10 @@
 
   PRINT_OPERANDS_TO_SUPPORT
 
-#define FIELD_LIST(F)                                                          \
-  F(const intptr_t, index_)                                                    \
-  F(const Representation, definition_rep_)                                     \
-  F(const intptr_t, definition_cid_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(ExtractNthOutputInstr,
-                                          TemplateDefinition,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  private:
+  const intptr_t index_;
+  const Representation definition_rep_;
+  const intptr_t definition_cid_;
   DISALLOW_COPY_AND_ASSIGN(ExtractNthOutputInstr);
 };
 
@@ -9522,8 +8778,6 @@
 
   PRINT_OPERANDS_TO_SUPPORT
 
-  DECLARE_EMPTY_SERIALIZATION(TruncDivModInstr, TemplateDefinition)
-
  private:
   Range* divisor_range() const {
     // Note: this range is only used to remove check for zero divisor from
@@ -9578,18 +8832,12 @@
 
   PRINT_OPERANDS_TO_SUPPORT
 
-#define FIELD_LIST(F)                                                          \
-  F(const Cids&, cids_)                                                        \
-  F(bool, licm_hoisted_)                                                       \
-  F(bool, is_bit_test_)                                                        \
-  F(const TokenPosition, token_pos_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(CheckClassInstr,
-                                          TemplateInstruction,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  private:
+  const Cids& cids_;
+  bool licm_hoisted_;
+  bool is_bit_test_;
+  const TokenPosition token_pos_;
+
   int EmitCheckCid(FlowGraphCompiler* compiler,
                    int bias,
                    intptr_t cid_start,
@@ -9633,16 +8881,10 @@
   bool licm_hoisted() const { return licm_hoisted_; }
   void set_licm_hoisted(bool value) { licm_hoisted_ = value; }
 
-#define FIELD_LIST(F)                                                          \
-  F(const TokenPosition, token_pos_)                                           \
-  F(bool, licm_hoisted_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(CheckSmiInstr,
-                                          TemplateInstruction,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  private:
+  const TokenPosition token_pos_;
+  bool licm_hoisted_;
+
   DISALLOW_COPY_AND_ASSIGN(CheckSmiInstr);
 };
 
@@ -9702,17 +8944,11 @@
 
   PRINT_OPERANDS_TO_SUPPORT
 
-#define FIELD_LIST(F)                                                          \
-  F(const TokenPosition, token_pos_)                                           \
-  F(const String&, function_name_)                                             \
-  F(const ExceptionType, exception_type_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(CheckNullInstr,
-                                          TemplateDefinition,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  private:
+  const TokenPosition token_pos_;
+  const String& function_name_;
+  const ExceptionType exception_type_;
+
   DISALLOW_COPY_AND_ASSIGN(CheckNullInstr);
 };
 
@@ -9741,16 +8977,11 @@
 
   PRINT_OPERANDS_TO_SUPPORT
 
-#define FIELD_LIST(F) F(CidRangeValue, cids_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(CheckClassIdInstr,
-                                          TemplateInstruction,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  private:
   bool Contains(intptr_t cid) const;
 
+  CidRangeValue cids_;
+
   DISALLOW_COPY_AND_ASSIGN(CheckClassIdInstr);
 };
 
@@ -9780,8 +9011,6 @@
   // Give a name to the location/input indices.
   enum { kLengthPos = 0, kIndexPos = 1 };
 
-  DECLARE_EMPTY_SERIALIZATION(CheckBoundBase, TemplateDefinition)
-
  private:
   DISALLOW_COPY_AND_ASSIGN(CheckBoundBase);
 };
@@ -9816,16 +9045,10 @@
 
   void set_licm_hoisted(bool value) { licm_hoisted_ = value; }
 
-#define FIELD_LIST(F)                                                          \
-  F(bool, generalized_)                                                        \
-  F(bool, licm_hoisted_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(CheckArrayBoundInstr,
-                                          CheckBoundBase,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  private:
+  bool generalized_;
+  bool licm_hoisted_;
+
   DISALLOW_COPY_AND_ASSIGN(CheckArrayBoundInstr);
 };
 
@@ -9879,8 +9102,6 @@
     return SlowPathSharingSupported(is_optimizing);
   }
 
-  DECLARE_EMPTY_SERIALIZATION(GenericCheckBoundInstr, CheckBoundBase)
-
  private:
   DISALLOW_COPY_AND_ASSIGN(GenericCheckBoundInstr);
 };
@@ -9906,8 +9127,6 @@
 
   virtual bool ComputeCanDeoptimize() const { return false; }
 
-  DECLARE_EMPTY_SERIALIZATION(CheckWritableInstr, TemplateDefinition)
-
  private:
   DISALLOW_COPY_AND_ASSIGN(CheckWritableInstr);
 };
@@ -9948,19 +9167,13 @@
 
   PRINT_OPERANDS_TO_SUPPORT
 
-#define FIELD_LIST(F) F(ComparisonInstr*, comparison_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(CheckConditionInstr,
-                                          Instruction,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-  DECLARE_EXTRA_SERIALIZATION
-
  private:
   virtual void RawSetInputAt(intptr_t i, Value* value) {
     comparison()->RawSetInputAt(i, value);
   }
 
+  ComparisonInstr* comparison_;
+
   DISALLOW_COPY_AND_ASSIGN(CheckConditionInstr);
 };
 
@@ -10025,17 +9238,11 @@
 
   PRINT_OPERANDS_TO_SUPPORT
 
-#define FIELD_LIST(F)                                                          \
-  F(const Representation, from_representation_)                                \
-  F(const Representation, to_representation_)                                  \
-  F(bool, is_truncating_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(IntConverterInstr,
-                                          TemplateDefinition,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  private:
+  const Representation from_representation_;
+  const Representation to_representation_;
+  bool is_truncating_;
+
   DISALLOW_COPY_AND_ASSIGN(IntConverterInstr);
 };
 
@@ -10082,16 +9289,10 @@
 
   PRINT_OPERANDS_TO_SUPPORT
 
-#define FIELD_LIST(F)                                                          \
-  F(const Representation, from_representation_)                                \
-  F(const Representation, to_representation_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(BitCastInstr,
-                                          TemplateDefinition,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  private:
+  const Representation from_representation_;
+  const Representation to_representation_;
+
   DISALLOW_COPY_AND_ASSIGN(BitCastInstr);
 };
 
@@ -10117,8 +9318,6 @@
 
   DECLARE_INSTRUCTION(LoadThread);
 
-  DECLARE_EMPTY_SERIALIZATION(LoadThreadInstr, TemplateDefinition)
-
  private:
   DISALLOW_COPY_AND_ASSIGN(LoadThreadInstr);
 };
@@ -10327,13 +9526,6 @@
   DECLARE_INSTRUCTION(SimdOp)
   PRINT_OPERANDS_TO_SUPPORT
 
-#define FIELD_LIST(F)                                                          \
-  F(const Kind, kind_)                                                         \
-  F(intptr_t, mask_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(SimdOpInstr, Definition, FIELD_LIST)
-#undef FIELD_LIST
-
  private:
   SimdOpInstr(Kind kind, intptr_t deopt_id)
       : Definition(deopt_id), kind_(kind) {}
@@ -10357,7 +9549,9 @@
   // We consider SimdOpInstr to be very uncommon so we don't optimize them for
   // size. Any instance of SimdOpInstr has enough space to fit any variation.
   // TODO(dartbug.com/30949) optimize this for size.
+  const Kind kind_;
   Value* inputs_[4];
+  intptr_t mask_;
 
   DISALLOW_COPY_AND_ASSIGN(SimdOpInstr);
 };
@@ -10396,16 +9590,10 @@
   DECLARE_INSTRUCTION(Call1ArgStub);
   PRINT_OPERANDS_TO_SUPPORT
 
-#define FIELD_LIST(F)                                                          \
-  F(const StubId, stub_id_)                                                    \
-  F(const TokenPosition, token_pos_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(Call1ArgStubInstr,
-                                          TemplateDefinition,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  private:
+  const StubId stub_id_;
+  const TokenPosition token_pos_;
+
   DISALLOW_COPY_AND_ASSIGN(Call1ArgStubInstr);
 };
 
@@ -10446,17 +9634,11 @@
   DECLARE_INSTRUCTION(Suspend);
   PRINT_OPERANDS_TO_SUPPORT
 
-#define FIELD_LIST(F)                                                          \
-  F(const StubId, stub_id_)                                                    \
-  F(const intptr_t, resume_deopt_id_)                                          \
-  F(const TokenPosition, token_pos_)
-
-  DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS(SuspendInstr,
-                                          TemplateDefinition,
-                                          FIELD_LIST)
-#undef FIELD_LIST
-
  private:
+  const StubId stub_id_;
+  const intptr_t resume_deopt_id_;
+  const TokenPosition token_pos_;
+
   DISALLOW_COPY_AND_ASSIGN(SuspendInstr);
 };
 
@@ -10669,9 +9851,6 @@
   // from the copy.
   Environment* DeepCopy(Zone* zone, intptr_t length) const;
 
-  void Write(FlowGraphSerializer* s) const;
-  explicit Environment(FlowGraphDeserializer* d);
-
  private:
   friend class ShallowIterator;
   friend class compiler::BlockBuilder;  // For Environment constructor.
@@ -10790,9 +9969,6 @@
   ConstantInstr* constant = definition()->AsConstant();
   return (constant == nullptr) || constant->value().ptr() == value.ptr();
 }
-#undef DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS
-#undef DECLARE_CUSTOM_SERIALIZATION
-#undef DECLARE_EMPTY_SERIALIZATION
 
 }  // namespace dart
 
diff --git a/runtime/vm/compiler/backend/il_serializer.cc b/runtime/vm/compiler/backend/il_serializer.cc
deleted file mode 100644
index 6fb76fc..0000000
--- a/runtime/vm/compiler/backend/il_serializer.cc
+++ /dev/null
@@ -1,2305 +0,0 @@
-// 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/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/ffi/call.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()),
-      isolate_group_(IsolateGroup::Current()),
-      heap_(IsolateGroup::Current()->heap()) {}
-
-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()) {}
-
-ClassPtr FlowGraphDeserializer::GetClassById(classid_t id) const {
-  return isolate_group()->class_table()->At(id);
-}
-
-template <>
-void FlowGraphSerializer::Write<const AbstractType*>(const AbstractType* x) {
-  if (x == nullptr) {
-    Write<bool>(false);
-  } else {
-    Write<bool>(true);
-    Write<const AbstractType&>(*x);
-  }
-}
-
-template <>
-const AbstractType* FlowGraphDeserializer::Read<const AbstractType*>() {
-  if (!Read<bool>()) {
-    return nullptr;
-  }
-  return &Read<const AbstractType&>();
-}
-
-template <>
-void FlowGraphSerializer::Write<AliasIdentity>(AliasIdentity x) {
-  x.Write(this);
-}
-
-template <>
-AliasIdentity FlowGraphDeserializer::Read<AliasIdentity>() {
-  return AliasIdentity(this);
-}
-
-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::WriteRef<BlockEntryInstr*>(BlockEntryInstr* x) {
-  ASSERT(can_write_refs());
-  if (x == nullptr) {
-    Write<intptr_t>(-1);
-    return;
-  }
-  const intptr_t id = x->block_id();
-  ASSERT(id >= 0);
-  Write<intptr_t>(id);
-}
-
-template <>
-BlockEntryInstr* FlowGraphDeserializer::ReadRef<BlockEntryInstr*>() {
-  const intptr_t id = Read<intptr_t>();
-  if (id < 0) {
-    return nullptr;
-  }
-  return 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)
-
-#define SERIALIZABLE_AS_BLOCK_ENTRY(name, type)                                \
-  template <>                                                                  \
-  void FlowGraphSerializer::WriteRef<type*>(type * x) {                        \
-    WriteRef<BlockEntryInstr*>(x);                                             \
-  }                                                                            \
-  template <>                                                                  \
-  type* FlowGraphDeserializer::ReadRef<type*>() {                              \
-    BlockEntryInstr* instr = 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::Write<bool>(bool x) {
-  stream_->Write<uint8_t>(x ? 1 : 0);
-}
-
-template <>
-bool FlowGraphDeserializer::Read<bool>() {
-  return (stream_->Read<uint8_t>() != 0);
-}
-
-void BranchInstr::WriteExtra(FlowGraphSerializer* s) {
-  // Branch reuses inputs from its embedded Comparison.
-  // Instruction::WriteExtra is not called to avoid
-  // writing/reading inputs twice.
-  WriteExtraWithoutInputs(s);
-  comparison_->WriteExtra(s);
-  s->WriteRef<TargetEntryInstr*>(true_successor_);
-  s->WriteRef<TargetEntryInstr*>(false_successor_);
-  s->WriteRef<TargetEntryInstr*>(constant_target_);
-}
-
-void BranchInstr::ReadExtra(FlowGraphDeserializer* d) {
-  ReadExtraWithoutInputs(d);
-  comparison_->ReadExtra(d);
-  for (intptr_t i = comparison_->InputCount() - 1; i >= 0; --i) {
-    comparison_->InputAt(i)->set_instruction(this);
-  }
-  true_successor_ = d->ReadRef<TargetEntryInstr*>();
-  false_successor_ = d->ReadRef<TargetEntryInstr*>();
-  constant_target_ = d->ReadRef<TargetEntryInstr*>();
-}
-
-template <>
-void FlowGraphSerializer::Write<const compiler::ffi::CallbackMarshaller&>(
-    const compiler::ffi::CallbackMarshaller& x) {
-  UNIMPLEMENTED();
-}
-
-template <>
-const compiler::ffi::CallbackMarshaller&
-FlowGraphDeserializer::Read<const compiler::ffi::CallbackMarshaller&>() {
-  UNIMPLEMENTED();
-  return *compiler::ffi::CallbackMarshaller::FromFunction(
-      Z, Function::null_function(), nullptr);
-}
-
-template <>
-void FlowGraphSerializer::Write<const compiler::ffi::CallMarshaller&>(
-    const compiler::ffi::CallMarshaller& x) {
-  Write<const Function&>(x.dart_signature());
-}
-
-template <>
-const compiler::ffi::CallMarshaller&
-FlowGraphDeserializer::Read<const compiler::ffi::CallMarshaller&>() {
-  const Function& dart_signature = Read<const Function&>();
-  const char* error = nullptr;
-  return *compiler::ffi::CallMarshaller::FromFunction(Z, dart_signature,
-                                                      &error);
-}
-
-template <>
-void FlowGraphSerializer::Write<const CallTargets&>(const CallTargets& x) {
-  x.Write(this);
-}
-
-template <>
-const CallTargets& FlowGraphDeserializer::Read<const CallTargets&>() {
-  return *(new (Z) CallTargets(this));
-}
-
-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 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),
-      graph_entry_(d->graph_entry()),
-      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::Write<const char*>(const char* x) {
-  ASSERT(x != nullptr);
-  const intptr_t len = strlen(x);
-  Write<intptr_t>(len);
-  stream_->WriteBytes(x, len);
-}
-
-template <>
-const char* FlowGraphDeserializer::Read<const char*>() {
-  const intptr_t len = Read<intptr_t>();
-  char* str = zone()->Alloc<char>(len + 1);
-  stream_->ReadBytes(str, len);
-  str[len] = 0;
-  return str;
-}
-
-void CheckConditionInstr::WriteExtra(FlowGraphSerializer* s) {
-  // CheckCondition reuses inputs from its embedded Comparison.
-  // Instruction::WriteExtra is not called to avoid
-  // writing/reading inputs twice.
-  WriteExtraWithoutInputs(s);
-  comparison_->WriteExtra(s);
-}
-
-void CheckConditionInstr::ReadExtra(FlowGraphDeserializer* d) {
-  ReadExtraWithoutInputs(d);
-  comparison_->ReadExtra(d);
-  for (intptr_t i = comparison_->InputCount() - 1; i >= 0; --i) {
-    comparison_->InputAt(i)->set_instruction(this);
-  }
-}
-
-template <>
-void FlowGraphSerializer::Write<CidRangeValue>(CidRangeValue x) {
-  Write<intptr_t>(x.cid_start);
-  Write<intptr_t>(x.cid_end);
-}
-
-template <>
-CidRangeValue FlowGraphDeserializer::Read<CidRangeValue>() {
-  const intptr_t cid_start = Read<intptr_t>();
-  const intptr_t cid_end = Read<intptr_t>();
-  return CidRangeValue(cid_start, cid_end);
-}
-
-template <>
-void FlowGraphSerializer::Write<const Cids&>(const Cids& x) {
-  const intptr_t len = x.length();
-  Write<intptr_t>(len);
-  for (intptr_t i = 0; i < len; ++i) {
-    const CidRange* r = x.At(i);
-    Write<intptr_t>(r->cid_start);
-    Write<intptr_t>(r->cid_end);
-  }
-}
-
-template <>
-const Cids& FlowGraphDeserializer::Read<const Cids&>() {
-  Cids* cids = new (Z) Cids(Z);
-  const intptr_t len = Read<intptr_t>();
-  for (intptr_t i = 0; i < len; ++i) {
-    const intptr_t cid_start = Read<intptr_t>();
-    const intptr_t cid_end = Read<intptr_t>();
-    CidRange* r = new (Z) CidRange(cid_start, cid_end);
-    cids->Add(r);
-  }
-  return *cids;
-}
-
-template <>
-void FlowGraphSerializer::Write<const Class&>(const Class& x) {
-  if (x.IsNull()) {
-    Write<classid_t>(kIllegalCid);
-    return;
-  }
-  Write<classid_t>(x.id());
-}
-
-template <>
-const Class& FlowGraphDeserializer::Read<const Class&>() {
-  const classid_t cid = Read<classid_t>();
-  if (cid == kIllegalCid) {
-    return Class::ZoneHandle(Z);
-  }
-  return Class::ZoneHandle(Z, 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::Write<const Code&>(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()) {
-      Write<intptr_t>(i);
-      return;
-    }
-  }
-  intptr_t index = StubCode::NumEntries();
-  ObjectStore* object_store = isolate_group()->object_store();
-#define MATCH(member, name)                                                    \
-  if (object_store->member() == x.ptr()) {                                     \
-    Write<intptr_t>(index);                                                    \
-    return;                                                                    \
-  }                                                                            \
-  ++index;
-  OBJECT_STORE_STUB_CODE_LIST(MATCH)
-#undef MATCH
-  UNIMPLEMENTED();
-}
-
-template <>
-const Code& FlowGraphDeserializer::Read<const Code&>() {
-  const intptr_t stub_id = Read<intptr_t>();
-  if (stub_id < StubCode::NumEntries()) {
-    return StubCode::EntryAt(stub_id);
-  }
-  intptr_t index = StubCode::NumEntries();
-  ObjectStore* object_store = isolate_group()->object_store();
-#define MATCH(member, name)                                                    \
-  if (index == stub_id) {                                                      \
-    return Code::ZoneHandle(Z, object_store->member());                        \
-  }                                                                            \
-  ++index;
-  OBJECT_STORE_STUB_CODE_LIST(MATCH)
-#undef MATCH
-  UNIMPLEMENTED();
-}
-
-template <>
-void FlowGraphSerializer::Write<CompileType*>(CompileType* x) {
-  if (x == nullptr) {
-    Write<bool>(false);
-  } else {
-    Write<bool>(true);
-    x->Write(this);
-  }
-}
-
-template <>
-CompileType* FlowGraphDeserializer::Read<CompileType*>() {
-  if (!Read<bool>()) {
-    return nullptr;
-  }
-  return new (Z) CompileType(this);
-}
-
-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::WriteRef<Definition*>(Definition* x) {
-  if (!x->HasSSATemp()) {
-    if (auto* push_arg = x->AsPushArgument()) {
-      // Environments of the calls can reference PushArgument instructions
-      // and they don't have SSA temps.
-      // Write a reference to the original definition.
-      // When reading it is restored using RepairPushArgsInEnvironment.
-      x = push_arg->value()->definition();
-    } else {
-      UNREACHABLE();
-    }
-  }
-  ASSERT(x->HasSSATemp());
-  ASSERT(can_write_refs());
-  Write<intptr_t>(x->ssa_temp_index());
-}
-
-template <>
-Definition* FlowGraphDeserializer::ReadRef<Definition*>() {
-  return definition(Read<intptr_t>());
-}
-
-template <>
-void FlowGraphSerializer::Write<double>(double x) {
-  stream_->Write<int64_t>(bit_cast<int64_t>(x));
-}
-
-template <>
-double FlowGraphDeserializer::Read<double>() {
-  return bit_cast<double>(stream_->Read<int64_t>());
-}
-
-template <>
-void FlowGraphSerializer::Write<Environment*>(Environment* x) {
-  ASSERT(can_write_refs());
-  if (x == nullptr) {
-    Write<bool>(false);
-  } else {
-    Write<bool>(true);
-    x->Write(this);
-  }
-}
-
-template <>
-Environment* FlowGraphDeserializer::Read<Environment*>() {
-  if (!Read<bool>()) {
-    return nullptr;
-  }
-  return new (Z) Environment(this);
-}
-
-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<intptr_t>(flow_graph.inlining_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 (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
-      Instruction* current = it.Current();
-      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 (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
-      Instruction* current = it.Current();
-      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]);
-  }
-
-  const auto* captured_parameters = flow_graph.captured_parameters();
-  if (captured_parameters->IsEmpty()) {
-    Write<bool>(false);
-  } else {
-    Write<bool>(true);
-    // Captured parameters are rare so write their bit numbers
-    // instead of writing BitVector.
-    GrowableArray<intptr_t> indices(Z, 0);
-    for (intptr_t i = 0, n = captured_parameters->length(); i < n; ++i) {
-      if (captured_parameters->Contains(i)) {
-        indices.Add(i);
-      }
-    }
-    Write<GrowableArray<intptr_t>>(indices);
-  }
-}
-
-FlowGraph* FlowGraphDeserializer::ReadFlowGraph() {
-  const intptr_t current_ssa_temp_index = Read<intptr_t>();
-  const intptr_t max_block_id = Read<intptr_t>();
-  const intptr_t inlining_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);
-  flow_graph->set_current_ssa_temp_index(current_ssa_temp_index);
-  flow_graph->CreateCommonConstants();
-  flow_graph->disallow_licm();
-  flow_graph->set_inlining_id(inlining_id);
-  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(true);
-      ASSERT(codegen_block_order == &flow_graph->optimized_block_order());
-      for (intptr_t i = 0; i < num_blocks; ++i) {
-        codegen_block_order->Add(ReadRef<BlockEntryInstr*>());
-      }
-    }
-  }
-
-  if (Read<bool>()) {
-    GrowableArray<intptr_t> indices = Read<GrowableArray<intptr_t>>();
-    for (intptr_t i : indices) {
-      flow_graph->captured_parameters()->Add(i);
-    }
-  }
-
-  return flow_graph;
-}
-
-template <>
-void FlowGraphSerializer::Write<const Function&>(const Function& x) {
-  if (x.IsNull()) {
-    Write<int8_t>(-1);
-    return;
-  }
-  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(Z, x.Owner());
-      Write<classid_t>(owner.id());
-      const intptr_t function_index = owner.FindFunctionIndex(x);
-      ASSERT(function_index >= 0);
-      Write<intptr_t>(function_index);
-      return;
-    }
-    case UntaggedFunction::kImplicitClosureFunction: {
-      const auto& parent = Function::Handle(Z, x.parent_function());
-      Write<const Function&>(parent);
-      return;
-    }
-    case UntaggedFunction::kFieldInitializer: {
-      const auto& field = Field::Handle(Z, x.accessor_field());
-      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.
-      Write<intptr_t>(ClosureFunctionsCache::FindClosureIndex(x));
-      return;
-    case UntaggedFunction::kMethodExtractor: {
-      Function& function = Function::Handle(Z, x.extracted_method_closure());
-      ASSERT(function.IsImplicitClosureFunction());
-      function = function.parent_function();
-      Write<const Function&>(function);
-      Write<const String&>(String::Handle(Z, x.name()));
-      return;
-    }
-    case UntaggedFunction::kInvokeFieldDispatcher: {
-      Write<const Class&>(Class::Handle(Z, x.Owner()));
-      Write<const String&>(String::Handle(Z, x.name()));
-      Write<const Array&>(Array::Handle(Z, x.saved_args_desc()));
-      return;
-    }
-    case UntaggedFunction::kDynamicInvocationForwarder: {
-      const auto& target = Function::Handle(Z, x.ForwardingTarget());
-      Write<const Function&>(target);
-      return;
-    }
-    case UntaggedFunction::kFfiTrampoline: {
-      if (x.FfiCallbackTarget() != Object::null()) {
-        UNIMPLEMENTED();
-      }
-      Write<const String&>(String::Handle(Z, x.name()));
-      Write<const FunctionType&>(FunctionType::Handle(Z, x.signature()));
-      Write<const FunctionType&>(FunctionType::Handle(Z, x.FfiCSignature()));
-      Write<bool>(x.FfiIsLeaf());
-      return;
-    }
-    default:
-      break;
-  }
-  switch (x.kind()) {
-#define UNIMPLEMENTED_FUNCTION_KIND(kind)                                      \
-  case UntaggedFunction::k##kind:                                              \
-    FATAL("Unimplemented Write<const Function&> for " #kind);
-    FOR_EACH_RAW_FUNCTION_KIND(UNIMPLEMENTED_FUNCTION_KIND)
-#undef UNIMPLEMENTED_FUNCTION_KIND
-  }
-  UNREACHABLE();
-}
-
-template <>
-const Function& FlowGraphDeserializer::Read<const Function&>() {
-  const int8_t raw_kind = Read<int8_t>();
-  if (raw_kind < 0) {
-    return Object::null_function();
-  }
-  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 = Read<classid_t>();
-      const intptr_t function_index = Read<intptr_t>();
-      const auto& owner = Class::Handle(Z, GetClassById(owner_class_id));
-      const auto& result =
-          Function::ZoneHandle(Z, owner.FunctionFromIndex(function_index));
-      ASSERT(!result.IsNull());
-      return result;
-    }
-    case UntaggedFunction::kImplicitClosureFunction: {
-      const auto& parent = Read<const Function&>();
-      return Function::ZoneHandle(Z, parent.ImplicitClosureFunction());
-    }
-    case UntaggedFunction::kFieldInitializer: {
-      const auto& field = Read<const Field&>();
-      return Function::ZoneHandle(Z, field.EnsureInitializerFunction());
-    }
-    case UntaggedFunction::kClosureFunction: {
-      const intptr_t index = Read<intptr_t>();
-      return Function::ZoneHandle(
-          Z, ClosureFunctionsCache::ClosureFunctionFromIndex(index));
-    }
-    case UntaggedFunction::kMethodExtractor: {
-      const Function& function = Read<const Function&>();
-      const String& name = Read<const String&>();
-      return Function::ZoneHandle(Z, function.GetMethodExtractor(name));
-    }
-    case UntaggedFunction::kInvokeFieldDispatcher: {
-      const Class& owner = Read<const Class&>();
-      const String& target_name = Read<const String&>();
-      const Array& args_desc = Read<const Array&>();
-      return Function::ZoneHandle(
-          Z,
-          owner.GetInvocationDispatcher(
-              target_name, args_desc, UntaggedFunction::kInvokeFieldDispatcher,
-              /*create_if_absent=*/true));
-    }
-    case UntaggedFunction::kDynamicInvocationForwarder: {
-      const auto& target = Read<const Function&>();
-      auto& name = String::Handle(Z, target.name());
-      name = Function::CreateDynamicInvocationForwarderName(name);
-      return Function::ZoneHandle(Z,
-                                  target.GetDynamicInvocationForwarder(name));
-    }
-    case UntaggedFunction::kFfiTrampoline: {
-      const String& name = Read<const String&>();
-      const FunctionType& signature = Read<const FunctionType&>();
-      const FunctionType& c_signature = Read<const FunctionType&>();
-      const bool is_leaf = Read<bool>();
-      return Function::ZoneHandle(
-          Z, compiler::ffi::TrampolineFunction(name, signature, c_signature,
-                                               is_leaf));
-    }
-    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<CatchBlockEntryInstr*>(catch_entries_);
-  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*>();
-  catch_entries_ = d->ReadGrowableArrayOfRefs<CatchBlockEntryInstr*>();
-  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::Write<const ICData*>(const ICData* x) {
-  if (x == nullptr) {
-    Write<bool>(false);
-  } else {
-    Write<bool>(true);
-    ASSERT(!x->IsNull());
-    Write<const Object&>(*x);
-  }
-}
-
-template <>
-const ICData* FlowGraphDeserializer::Read<const ICData*>() {
-  if (!Read<bool>()) {
-    return nullptr;
-  }
-  return &ICData::Cast(Read<const Object&>());
-}
-
-void IfThenElseInstr::WriteExtra(FlowGraphSerializer* s) {
-  // IfThenElse reuses inputs from its embedded Comparison.
-  // Definition::WriteExtra is not called to avoid
-  // writing/reading inputs twice.
-  WriteExtraWithoutInputs(s);
-  comparison_->WriteExtra(s);
-}
-
-void IfThenElseInstr::ReadExtra(FlowGraphDeserializer* d) {
-  ReadExtraWithoutInputs(d);
-  comparison_->ReadExtra(d);
-  for (intptr_t i = comparison_->InputCount() - 1; i >= 0; --i) {
-    comparison_->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::Write<Instruction*>(Instruction* x) {
-  if (x == nullptr) {
-    Write<uint8_t>(Instruction::kNumInstructions);
-  } else {
-    Write<uint8_t>(static_cast<uint8_t>(x->tag()));
-    x->WriteTo(this);
-  }
-}
-
-template <>
-Instruction* FlowGraphDeserializer::Read<Instruction*>() {
-  const uint8_t tag = Read<uint8_t>();
-  switch (tag) {
-#define READ_INSTRUCTION(type, attrs)                                          \
-  case Instruction::k##type:                                                   \
-    return new (Z) type##Instr(this);
-    FOR_EACH_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(Comparison, ComparisonInstr)                                               \
-  V(Constant, ConstantInstr)                                                   \
-  V(Definition, Definition)                                                    \
-  V(ParallelMove, ParallelMoveInstr)                                           \
-  V(Phi, PhiInstr)
-
-#define SERIALIZABLE_AS_INSTRUCTION(name, type)                                \
-  template <>                                                                  \
-  void FlowGraphSerializer::Write<type*>(type * x) {                           \
-    Write<Instruction*>(x);                                                    \
-  }                                                                            \
-  template <>                                                                  \
-  type* FlowGraphDeserializer::Read<type*>() {                                 \
-    Instruction* instr = 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::Write<int8_t>(int8_t x) {
-  stream_->Write<int8_t>(x);
-}
-
-template <>
-int8_t FlowGraphDeserializer::Read<int8_t>() {
-  return stream_->Read<int8_t>();
-}
-
-template <>
-void FlowGraphSerializer::Write<int16_t>(int16_t x) {
-  stream_->Write<int16_t>(x);
-}
-
-template <>
-int16_t FlowGraphDeserializer::Read<int16_t>() {
-  return stream_->Read<int16_t>();
-}
-
-template <>
-void FlowGraphSerializer::Write<int32_t>(int32_t x) {
-  stream_->Write<int32_t>(x);
-}
-
-template <>
-int32_t FlowGraphDeserializer::Read<int32_t>() {
-  return stream_->Read<int32_t>();
-}
-
-template <>
-void FlowGraphSerializer::Write<int64_t>(int64_t x) {
-  stream_->Write<int64_t>(x);
-}
-
-template <>
-int64_t FlowGraphDeserializer::Read<int64_t>() {
-  return 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::Write<const LocalVariable&>(const LocalVariable& x) {
-  UNIMPLEMENTED();
-}
-
-template <>
-const LocalVariable& FlowGraphDeserializer::Read<const LocalVariable&>() {
-  UNIMPLEMENTED();
-  return *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) {
-    return Location::Pair(Location::Read(d), Location::Read(d));
-  } 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::Write<LocationSummary*>(LocationSummary* x) {
-  ASSERT(can_write_refs());
-  if (x == nullptr) {
-    Write<bool>(false);
-  } else {
-    Write<bool>(true);
-    x->Write(this);
-  }
-}
-
-template <>
-LocationSummary* FlowGraphDeserializer::Read<LocationSummary*>() {
-  if (!Read<bool>()) {
-    return nullptr;
-  }
-  return new (Z) LocationSummary(this);
-}
-
-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::Write<MoveOperands*>(MoveOperands* x) {
-  ASSERT(x != nullptr);
-  x->src().Write(this);
-  x->dest().Write(this);
-}
-
-template <>
-MoveOperands* FlowGraphDeserializer::Read<MoveOperands*>() {
-  Location src = Location::Read(this);
-  Location dest = Location::Read(this);
-  return new (Z) MoveOperands(dest, src);
-}
-
-template <>
-void FlowGraphSerializer::Write<const compiler::ffi::NativeCallingConvention&>(
-    const compiler::ffi::NativeCallingConvention& x) {
-  // A subset of NativeCallingConvention currently used by CCallInstr.
-  const auto& args = x.argument_locations();
-  for (intptr_t i = 0, n = args.length(); i < n; ++i) {
-    if (args.At(i)->payload_type().AsRepresentation() != kUnboxedFfiIntPtr) {
-      UNIMPLEMENTED();
-    }
-  }
-  if (x.return_location().payload_type().AsRepresentation() !=
-      kUnboxedFfiIntPtr) {
-    UNIMPLEMENTED();
-  }
-  Write<intptr_t>(args.length());
-}
-
-template <>
-const compiler::ffi::NativeCallingConvention&
-FlowGraphDeserializer::Read<const compiler::ffi::NativeCallingConvention&>() {
-  const intptr_t num_args = Read<intptr_t>();
-  const auto& native_function_type =
-      *compiler::ffi::NativeFunctionType::FromUnboxedRepresentation(
-          Z, num_args, kUnboxedFfiIntPtr);
-  return compiler::ffi::NativeCallingConvention::FromSignature(
-      Z, native_function_type);
-}
-
-template <>
-void FlowGraphSerializer::Write<const Object&>(const Object& x) {
-  const intptr_t cid = x.GetClassId();
-  ASSERT(cid != kIllegalCid);
-  // Do not write objects repeatedly.
-  const intptr_t object_id = heap_->GetObjectId(x.ptr());
-  if (object_id != 0) {
-    const intptr_t object_index = object_id - 1;
-    Write<intptr_t>(kIllegalCid);
-    Write<intptr_t>(object_index);
-    return;
-  }
-  const intptr_t object_index = object_counter_++;
-  heap_->SetObjectId(x.ptr(), object_index + 1);
-  Write<intptr_t>(cid);
-  WriteObjectImpl(x, cid, object_index);
-}
-
-template <>
-const Object& FlowGraphDeserializer::Read<const Object&>() {
-  const intptr_t cid = Read<intptr_t>();
-  if (cid == kIllegalCid) {
-    const intptr_t object_index = Read<intptr_t>();
-    return *objects_[object_index];
-  }
-  const intptr_t object_index = object_counter_;
-  object_counter_++;
-  const Object& result = ReadObjectImpl(cid, object_index);
-  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;
-}
-
-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.context() != 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 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());
-      TypeScope type_scope(this, type.IsRecursive());
-      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()));
-      AbstractType& t = AbstractType::Handle(Z, type.result_type());
-      Write<const AbstractType&>(t);
-      // Do not write parameter types as Array to avoid eager canonicalization
-      // when reading.
-      const Array& param_types = Array::Handle(Z, type.parameter_types());
-      ASSERT(param_types.Length() == type.NumParameters());
-      for (intptr_t i = 0, n = type.NumParameters(); i < n; ++i) {
-        t ^= param_types.At(i);
-        Write<const AbstractType&>(t);
-      }
-      Write<const Array&>(Array::Handle(Z, type.named_parameter_names()));
-      Write<bool>(type_scope.CanBeCanonicalized());
-      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 kImmutableLinkedHashMapCid:
-    case kImmutableLinkedHashSetCid: {
-      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 == kImmutableLinkedHashMapCid) {
-        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).AsInt64Value());
-      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 kSentinelCid:
-      if (x.ptr() == Object::sentinel().ptr()) {
-        Write<bool>(true);
-      } else if (x.ptr() == Object::transition_sentinel().ptr()) {
-        Write<bool>(false);
-      } 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());
-      const auto& cls = Class::Handle(Z, type.type_class());
-      TypeScope type_scope(this, type.IsRecursive() && cls.IsGeneric());
-      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);
-      }
-      Write<bool>(type_scope.CanBeCanonicalized());
-      break;
-    }
-    case kTypeArgumentsCid: {
-      const auto& type_args = TypeArguments::Cast(x);
-      ASSERT(type_args.IsFinalized());
-      TypeScope type_scope(this, type_args.IsRecursive());
-      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);
-      }
-      Write<bool>(type_scope.CanBeCanonicalized());
-      break;
-    }
-    case kTypeParameterCid: {
-      const auto& tp = TypeParameter::Cast(x);
-      ASSERT(tp.IsFinalized());
-      TypeScope type_scope(this, tp.IsRecursive());
-      Write<classid_t>(tp.parameterized_class_id());
-      Write<intptr_t>(tp.base());
-      Write<intptr_t>(tp.index());
-      Write<int8_t>(static_cast<int8_t>(tp.nullability()));
-      Write<const AbstractType&>(AbstractType::Handle(Z, tp.bound()));
-      Write<bool>(type_scope.CanBeCanonicalized());
-      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;
-    }
-    case kTypeRefCid: {
-      const auto& tr = TypeRef::Cast(x);
-      ASSERT(tr.IsFinalized());
-      TypeScope type_scope(this, tr.IsRecursive());
-      Write<const AbstractType&>(AbstractType::Handle(Z, tr.type()));
-      Write<bool>(type_scope.CanBeCanonicalized());
-      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()->shared_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, Context::Handle(Z)));
-      closure ^= closure.Canonicalize(thread());
-      return closure;
-    }
-    case kDoubleCid:
-      return Double::ZoneHandle(Z, Double::NewCanonical(Read<double>()));
-    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 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&>());
-      const Array& param_types =
-          Array::Handle(Z, Array::New(result.NumParameters(), Heap::kOld));
-      for (intptr_t i = 0, n = result.NumParameters(); i < n; ++i) {
-        param_types.SetAt(i, Read<const AbstractType&>());
-      }
-      result.set_parameter_types(param_types);
-      result.set_named_parameter_names(Read<const Array&>());
-      result.SetIsFinalized();
-      result ^= MaybeCanonicalize(result, object_index, Read<bool>());
-      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 kImmutableLinkedHashMapCid:
-    case kImmutableLinkedHashSetCid: {
-      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 == kImmutableLinkedHashMapCid) {
-        result = ImmutableLinkedHashMap::NewUninitialized(Heap::kOld);
-        used_data = (length << 1);
-      } else {
-        result = ImmutableLinkedHashSet::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 kSentinelCid:
-      return Read<bool>() ? Object::sentinel() : Object::transition_sentinel();
-    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 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 ^= MaybeCanonicalize(result, object_index, Read<bool>());
-      return result;
-    }
-    case kTypeArgumentsCid: {
-      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 ^= MaybeCanonicalize(type_args, object_index, Read<bool>());
-      return type_args;
-    }
-    case kTypeParameterCid: {
-      const classid_t parameterized_class_id = Read<classid_t>();
-      const intptr_t base = Read<intptr_t>();
-      const intptr_t index = Read<intptr_t>();
-      const Nullability nullability = static_cast<Nullability>(Read<int8_t>());
-      const auto& parameterized_class =
-          Class::Handle(Z, (parameterized_class_id == kFunctionCid)
-                               ? Class::null()
-                               : GetClassById(parameterized_class_id));
-      auto& tp = TypeParameter::ZoneHandle(
-          Z, TypeParameter::New(parameterized_class, base, index,
-                                /*bound=*/Object::null_abstract_type(),
-                                nullability));
-      SetObjectAt(object_index, tp);
-      const auto& bound = Read<const AbstractType&>();
-      tp.set_bound(bound);
-      tp.SetIsFinalized();
-      tp ^= MaybeCanonicalize(tp, object_index, Read<bool>());
-      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;
-    }
-    case kTypeRefCid: {
-      auto& tr =
-          TypeRef::ZoneHandle(Z, TypeRef::New(Object::null_abstract_type()));
-      SetObjectAt(object_index, tr);
-      const auto& type = Read<const AbstractType&>();
-      ASSERT(!type.IsNull());
-      tr.set_type(type);
-      tr ^= MaybeCanonicalize(tr, object_index, Read<bool>());
-      return tr;
-    }
-    default:
-      if ((cid >= kNumPredefinedCids) || (cid == kInstanceCid)) {
-        const auto& cls = Class::Handle(Z, GetClassById(cid));
-        const auto unboxed_fields_bitmap =
-            isolate_group()->shared_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();
-}
-
-InstancePtr FlowGraphDeserializer::MaybeCanonicalize(
-    const Instance& obj,
-    intptr_t object_index,
-    bool can_be_canonicalized) {
-  if (can_be_canonicalized) {
-    intptr_t remaining = 0;
-    for (intptr_t idx : pending_canonicalization_) {
-      if (idx < object_index) {
-        pending_canonicalization_[remaining++] = idx;
-      } else {
-        objects_[idx] = &Instance::ZoneHandle(
-            Z, Instance::Cast(*objects_[idx]).Canonicalize(thread()));
-      }
-    }
-    pending_canonicalization_.TruncateTo(remaining);
-    return obj.Canonicalize(thread());
-  } else {
-    ASSERT(objects_[object_index]->ptr() == obj.ptr());
-    pending_canonicalization_.Add(object_index);
-    return obj.ptr();
-  }
-}
-
-#define HANDLES_SERIALIZABLE_AS_OBJECT(V)                                      \
-  V(AbstractType, Object::null_abstract_type())                                \
-  V(Array, Object::null_array())                                               \
-  V(Field, Field::Handle(Z))                                                   \
-  V(FunctionType, Object::null_function_type())                                \
-  V(String, Object::null_string())                                             \
-  V(TypeArguments, Object::null_type_arguments())                              \
-  V(TypeParameters, TypeParameters::Handle(Z))
-
-#define SERIALIZE_HANDLE_AS_OBJECT(handle, null_handle)                        \
-  template <>                                                                  \
-  void FlowGraphSerializer::Write<const handle&>(const handle& x) {            \
-    Write<const Object&>(x);                                                   \
-  }                                                                            \
-  template <>                                                                  \
-  const handle& FlowGraphDeserializer::Read<const handle&>() {                 \
-    const Object& result = 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_);
-}
-
-void ParallelMoveInstr::ReadExtra(FlowGraphDeserializer* d) {
-  Instruction::ReadExtra(d);
-  moves_ = d->Read<GrowableArray<MoveOperands*>>();
-}
-
-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>()) {}
-
-template <>
-void FlowGraphSerializer::Write<Range*>(Range* x) {
-  if (x == nullptr) {
-    Write<bool>(false);
-  } else {
-    Write<bool>(true);
-    x->Write(this);
-  }
-}
-
-template <>
-Range* FlowGraphDeserializer::Read<Range*>() {
-  if (!Read<bool>()) {
-    return nullptr;
-  }
-  return new (Z) Range(this);
-}
-
-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>()) {}
-
-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::Write<Representation>(Representation x) {
-  Write<uint8_t>(x);
-}
-
-template <>
-Representation FlowGraphDeserializer::Read<Representation>() {
-  return static_cast<Representation>(Read<uint8_t>());
-}
-
-template <>
-void FlowGraphSerializer::Write<const Slot&>(const Slot& x) {
-  x.Write(this);
-}
-
-template <>
-const Slot& FlowGraphDeserializer::Read<const Slot&>() {
-  return Slot::Read(this);
-}
-
-template <>
-void FlowGraphSerializer::Write<const Slot*>(const Slot* x) {
-  if (x == nullptr) {
-    Write<bool>(false);
-    return;
-  }
-  Write<bool>(true);
-  x->Write(this);
-}
-
-template <>
-const Slot* FlowGraphDeserializer::Read<const Slot*>() {
-  if (!Read<bool>()) {
-    return nullptr;
-  }
-  return &Slot::Read(this);
-}
-
-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::kCapturedVariable:
-      s->Write<int8_t>(flags_);
-      s->Write<intptr_t>(offset_in_bytes_);
-      s->Write<const String&>(*DataAs<const String>());
-      s->Write<const AbstractType&>(*static_type_);
-      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;
-  ClassIdTagType cid = kDynamicCid;
-  intptr_t offset = -1;
-  const void* data = nullptr;
-  const AbstractType* static_type = nullptr;
-  Representation representation = kTagged;
-
-  switch (kind) {
-    case Kind::kTypeArguments:
-      flags = d->Read<int8_t>();
-      offset = d->Read<intptr_t>();
-      cid = kTypeArgumentsCid;
-      data = ":type_arguments";
-      break;
-    case Kind::kTypeArgumentsIndex:
-      flags =
-          IsImmutableBit::encode(true) |
-          IsCompressedBit::encode(TypeArguments::ContainsCompressedPointers());
-      offset = d->Read<intptr_t>();
-      data = ":argument";
-      break;
-    case Kind::kArrayElement:
-      flags = IsNullableBit::encode(true) |
-              IsCompressedBit::encode(Array::ContainsCompressedPointers());
-      offset = d->Read<intptr_t>();
-      data = ":array_element";
-      break;
-    case Kind::kCapturedVariable:
-      flags = d->Read<int8_t>();
-      offset = d->Read<intptr_t>();
-      data = &d->Read<const String&>();
-      static_type = &d->Read<const AbstractType&>();
-      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, cid, offset, data,
-                          static_type, representation);
-}
-
-template <>
-void FlowGraphSerializer::Write<const compiler::TableSelector*>(
-    const compiler::TableSelector* x) {
-#if defined(DART_PRECOMPILER)
-  ASSERT(x != nullptr);
-  Write<int32_t>(x->id);
-#else
-  UNREACHABLE();
-#endif
-}
-
-template <>
-const compiler::TableSelector*
-FlowGraphDeserializer::Read<const compiler::TableSelector*>() {
-#if defined(DART_PRECOMPILER)
-  const int32_t id = Read<int32_t>();
-  const compiler::TableSelector* selector =
-      Precompiler::Instance()->selector_map()->GetSelector(id);
-  ASSERT(selector != nullptr);
-  return selector;
-#else
-  UNREACHABLE();
-#endif
-}
-
-void SpecialParameterInstr::WriteExtra(FlowGraphSerializer* s) {
-  TemplateDefinition::WriteExtra(s);
-  s->WriteRef<BlockEntryInstr*>(block_);
-}
-
-void SpecialParameterInstr::ReadExtra(FlowGraphDeserializer* d) {
-  TemplateDefinition::ReadExtra(d);
-  block_ = d->ReadRef<BlockEntryInstr*>();
-}
-
-template <intptr_t kExtraInputs>
-void TemplateDartCall<kExtraInputs>::WriteExtra(FlowGraphSerializer* s) {
-  VariadicDefinition::WriteExtra(s);
-  if (push_arguments_ == nullptr) {
-    s->Write<intptr_t>(-1);
-  } else {
-    s->Write<intptr_t>(push_arguments_->length());
-#if defined(DEBUG)
-    // Verify that PushArgument instructions are inserted immediately
-    // before this instruction. ReadExtra below relies on
-    // that when restoring push_arguments_.
-    Instruction* instr = this;
-    for (intptr_t i = push_arguments_->length() - 1; i >= 0; --i) {
-      do {
-        instr = instr->previous();
-        ASSERT(instr != nullptr);
-      } while (!instr->IsPushArgument());
-      ASSERT(instr == (*push_arguments_)[i]);
-    }
-#endif
-  }
-}
-
-template <intptr_t kExtraInputs>
-void TemplateDartCall<kExtraInputs>::ReadExtra(FlowGraphDeserializer* d) {
-  VariadicDefinition::ReadExtra(d);
-  const intptr_t num_push_args = d->Read<intptr_t>();
-  if (num_push_args >= 0) {
-    push_arguments_ =
-        new (d->zone()) PushArgumentsArray(d->zone(), num_push_args);
-    push_arguments_->EnsureLength(num_push_args, nullptr);
-    Instruction* instr = this;
-    for (int i = num_push_args - 1; i >= 0; --i) {
-      do {
-        instr = instr->previous();
-        ASSERT(instr != nullptr);
-      } while (!instr->IsPushArgument());
-      (*push_arguments_)[i] = instr->AsPushArgument();
-    }
-    if (env() != nullptr) {
-      RepairPushArgsInEnvironment();
-    }
-  }
-}
-
-// Explicit template instantiations, needed for the methods above.
-template class TemplateDartCall<0>;
-template class TemplateDartCall<1>;
-
-template <>
-void FlowGraphSerializer::Write<TokenPosition>(TokenPosition x) {
-  Write<int32_t>(x.Serialize());
-}
-
-template <>
-TokenPosition FlowGraphDeserializer::Read<TokenPosition>() {
-  return TokenPosition::Deserialize(Read<int32_t>());
-}
-
-template <>
-void FlowGraphSerializer::Write<uint8_t>(uint8_t x) {
-  stream_->Write<uint8_t>(x);
-}
-
-template <>
-uint8_t FlowGraphDeserializer::Read<uint8_t>() {
-  return stream_->Read<uint8_t>();
-}
-
-template <>
-void FlowGraphSerializer::Write<uint16_t>(uint16_t x) {
-  stream_->Write<uint16_t>(x);
-}
-
-template <>
-uint16_t FlowGraphDeserializer::Read<uint16_t>() {
-  return stream_->Read<uint16_t>();
-}
-
-template <>
-void FlowGraphSerializer::Write<uint32_t>(uint32_t x) {
-  stream_->Write<int32_t>(static_cast<int32_t>(x));
-}
-
-template <>
-uint32_t FlowGraphDeserializer::Read<uint32_t>() {
-  return static_cast<uint32_t>(stream_->Read<int32_t>());
-}
-
-template <>
-void FlowGraphSerializer::Write<uint64_t>(uint64_t x) {
-  stream_->Write<int64_t>(static_cast<int64_t>(x));
-}
-
-template <>
-uint64_t FlowGraphDeserializer::Read<uint64_t>() {
-  return static_cast<uint64_t>(stream_->Read<int64_t>());
-}
-
-void UnboxedConstantInstr::WriteTo(FlowGraphSerializer* s) {
-  ConstantInstr::WriteTo(s);
-  s->Write<Representation>(representation_);
-  // constant_address_ is not written - it is restored when reading.
-}
-
-UnboxedConstantInstr::UnboxedConstantInstr(FlowGraphDeserializer* d)
-    : ConstantInstr(d),
-      representation_(d->Read<Representation>()),
-      constant_address_(0) {
-  if (representation_ == kUnboxedDouble) {
-    ASSERT(value().IsDouble());
-    constant_address_ = FindDoubleConstant(Double::Cast(value()).value());
-  }
-}
-
-template <>
-void FlowGraphSerializer::Write<Value*>(Value* x) {
-  ASSERT(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;
-  }
-  Write<CompileType*>(reaching_type);
-  WriteRef<Definition*>(def);
-}
-
-template <>
-Value* FlowGraphDeserializer::Read<Value*>() {
-  CompileType* type = Read<CompileType*>();
-  Definition* def = ReadRef<Definition*>();
-  Value* value = new (Z) 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
diff --git a/runtime/vm/compiler/backend/il_serializer.h b/runtime/vm/compiler/backend/il_serializer.h
deleted file mode 100644
index 07948c2..0000000
--- a/runtime/vm/compiler/backend/il_serializer.h
+++ /dev/null
@@ -1,473 +0,0 @@
-// 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.
-
-#ifndef RUNTIME_VM_COMPILER_BACKEND_IL_SERIALIZER_H_
-#define RUNTIME_VM_COMPILER_BACKEND_IL_SERIALIZER_H_
-
-#if defined(DART_PRECOMPILED_RUNTIME)
-#error "AOT runtime should not use compiler sources (including header files)"
-#endif  // defined(DART_PRECOMPILED_RUNTIME)
-
-#include <utility>  // For std::move.
-
-#include "platform/globals.h"
-#include "vm/allocation.h"
-#include "vm/compiler/backend/locations.h"
-
-namespace dart {
-
-class AliasIdentity;
-class BlockEntryInstr;
-class CallTargets;
-class CatchBlockEntryInstr;
-struct CidRangeValue;
-class Cids;
-class Code;
-class ComparisonInstr;
-class CompileType;
-class Definition;
-class Environment;
-class FunctionEntryInstr;
-class Instruction;
-class FlowGraph;
-class GraphEntryInstr;
-class Heap;
-class IndirectEntryInstr;
-class JoinEntryInstr;
-class LocalVariable;
-class LocationSummary;
-class MoveOperands;
-class NonStreamingWriteStream;
-class OsrEntryInstr;
-class ParsedFunction;
-class ParallelMoveInstr;
-class PhiInstr;
-class Range;
-class ReadStream;
-class TargetEntryInstr;
-class TokenPosition;
-
-namespace compiler {
-struct TableSelector;
-
-namespace ffi {
-class CallbackMarshaller;
-class CallMarshaller;
-class NativeCallingConvention;
-}  // namespace ffi
-}  // namespace compiler
-
-// The list of types which are handled by flow graph serializer/deserializer.
-// For each type there is a corresponding Write<T>(T) and Read<T>() methods.
-//
-// This list includes all types of fields of IL instructions
-// which are serialized via DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS macro,
-// except enum types which are unwrapped with serializable_type_t.
-//
-// The list is sorted alphabetically by type name.
-#define IL_SERIALIZABLE_TYPE_LIST(V)                                           \
-  V(AliasIdentity)                                                             \
-  V(const AbstractType&)                                                       \
-  V(const AbstractType*)                                                       \
-  V(const Array&)                                                              \
-  V(bool)                                                                      \
-  V(const compiler::ffi::CallbackMarshaller&)                                  \
-  V(const compiler::ffi::CallMarshaller&)                                      \
-  V(const CallTargets&)                                                        \
-  V(const char*)                                                               \
-  V(CidRangeValue)                                                             \
-  V(const Cids&)                                                               \
-  V(const Class&)                                                              \
-  V(const Code&)                                                               \
-  V(ComparisonInstr*)                                                          \
-  V(CompileType*)                                                              \
-  V(ConstantInstr*)                                                            \
-  V(Definition*)                                                               \
-  V(double)                                                                    \
-  V(Environment*)                                                              \
-  V(const Field&)                                                              \
-  V(const ICData*)                                                             \
-  V(int8_t)                                                                    \
-  V(int16_t)                                                                   \
-  V(int32_t)                                                                   \
-  V(int64_t)                                                                   \
-  V(const Function&)                                                           \
-  V(const FunctionType&)                                                       \
-  V(Instruction*)                                                              \
-  V(const LocalVariable&)                                                      \
-  V(LocationSummary*)                                                          \
-  V(MoveOperands*)                                                             \
-  V(const compiler::ffi::NativeCallingConvention&)                             \
-  V(const Object&)                                                             \
-  V(ParallelMoveInstr*)                                                        \
-  V(PhiInstr*)                                                                 \
-  V(Range*)                                                                    \
-  V(Representation)                                                            \
-  V(const Slot&)                                                               \
-  V(const Slot*)                                                               \
-  V(const String&)                                                             \
-  V(const compiler::TableSelector*)                                            \
-  V(TokenPosition)                                                             \
-  V(const TypeArguments&)                                                      \
-  V(const TypeParameters&)                                                     \
-  V(uint8_t)                                                                   \
-  V(uint16_t)                                                                  \
-  V(uint32_t)                                                                  \
-  V(uint64_t)                                                                  \
-  V(Value*)
-
-// List of types serializable as references.
-#define IL_SERIALIZABLE_REF_TYPE_LIST(V)                                       \
-  V(BlockEntryInstr*)                                                          \
-  V(CatchBlockEntryInstr*)                                                     \
-  V(Definition*)                                                               \
-  V(FunctionEntryInstr*)                                                       \
-  V(IndirectEntryInstr*)                                                       \
-  V(JoinEntryInstr*)                                                           \
-  V(OsrEntryInstr*)                                                            \
-  V(TargetEntryInstr*)
-
-// Serializes flow graph, including constants and references
-// to objects of program structure.
-//
-// Each IL instruction is serialized in 2 step:
-// - the main step (T::WriteTo / T::T()) serializes
-//   instruction fields, basically everything required to
-//   re-create instruction object.
-// - the extra step (T::WriteExtra / T::ReadExtra) serializes
-//   references to other instructions, including inputs,
-//   environments, locations (may reference constants) and successors.
-//
-class FlowGraphSerializer : public ValueObject {
- public:
-  explicit FlowGraphSerializer(NonStreamingWriteStream* stream);
-  ~FlowGraphSerializer();
-
-  // Writes [flow_graph] into the stream.
-  // The graph should be compacted via CompactSSA().
-  // [detached_defs] should contain all definitions which are
-  // detached from the graph but can still be referenced from
-  // environments.
-  void WriteFlowGraph(const FlowGraph& flow_graph,
-                      const ZoneGrowableArray<Definition*>& detached_defs);
-
-  // Default implementation of 'Write' method, when
-  // specialization for a particular type is not provided.
-  // This struct is used for the partial template instantiations below.
-  template <typename T>
-  struct WriteTrait {
-    using ArgType = T;
-  };
-
-  template <typename T>
-  struct WriteTrait<GrowableArray<T>> {
-    using ArgType = const GrowableArray<T>&;
-    static void Write(FlowGraphSerializer* s, ArgType x) {
-      const intptr_t len = x.length();
-      s->Write<intptr_t>(len);
-      for (intptr_t i = 0; i < len; ++i) {
-        s->Write<T>(x[i]);
-      }
-    }
-  };
-
-  template <typename T>
-  struct WriteTrait<const GrowableArray<T>&> {
-    using ArgType = const GrowableArray<T>&;
-    static void Write(FlowGraphSerializer* s, ArgType x) {
-      WriteTrait<GrowableArray<T>>::Write(s, x);
-    }
-  };
-
-  template <typename T>
-  struct WriteTrait<ZoneGrowableArray<T>*> {
-    using ArgType = const ZoneGrowableArray<T>*;
-    static void Write(FlowGraphSerializer* s, ArgType x) {
-      if (x == nullptr) {
-        s->Write<intptr_t>(-1);
-        return;
-      }
-      const intptr_t len = x->length();
-      s->Write<intptr_t>(len);
-      for (intptr_t i = 0; i < len; ++i) {
-        s->Write<T>((*x)[i]);
-      }
-    }
-  };
-
-  template <typename T>
-  struct WriteTrait<const ZoneGrowableArray<T>&> {
-    using ArgType = const ZoneGrowableArray<T>&;
-    static void Write(FlowGraphSerializer* s, ArgType x) {
-      WriteTrait<ZoneGrowableArray<T>*>::Write(s, &x);
-    }
-  };
-
-  // Specialization in case intptr_t is not mapped to intN_t.
-  template <>
-  struct WriteTrait<intptr_t> {
-    using ArgType = intptr_t;
-    static void Write(FlowGraphSerializer* s, intptr_t x) {
-#ifdef ARCH_IS_64_BIT
-      s->Write<int64_t>(x);
-#else
-      s->Write<int32_t>(x);
-#endif
-    }
-  };
-
-  // Specialization in case uintptr_t is not mapped to uintN_t.
-  template <>
-  struct WriteTrait<uintptr_t> {
-    using ArgType = uintptr_t;
-    static void Write(FlowGraphSerializer* s, uintptr_t x) {
-#ifdef ARCH_IS_64_BIT
-      s->Write<uint64_t>(x);
-#else
-      s->Write<uint32_t>(x);
-#endif
-    }
-  };
-
-  template <typename T>
-  void Write(typename WriteTrait<T>::ArgType x) {
-    WriteTrait<T>::Write(this, x);
-  }
-
-#define DECLARE_WRITE_METHOD(type)                                             \
-  template <>                                                                  \
-  void Write<type>(type x);
-  IL_SERIALIZABLE_TYPE_LIST(DECLARE_WRITE_METHOD)
-#undef DECLARE_WRITE_METHOD
-
-  template <typename T>
-  void WriteRef(T x);
-
-#define DECLARE_WRITE_REF_METHOD(type)                                         \
-  template <>                                                                  \
-  void WriteRef<type>(type x);
-  IL_SERIALIZABLE_REF_TYPE_LIST(DECLARE_WRITE_REF_METHOD)
-#undef DECLARE_WRITE_REF_METHOD
-
-  template <typename T>
-  void WriteGrowableArrayOfRefs(const GrowableArray<T>& array) {
-    const intptr_t len = array.length();
-    Write<intptr_t>(len);
-    for (intptr_t i = 0; i < len; ++i) {
-      WriteRef<T>(array[i]);
-    }
-  }
-
-  BaseWriteStream* stream() const { return stream_; }
-  IsolateGroup* isolate_group() const { return isolate_group_; }
-  bool can_write_refs() const { return can_write_refs_; }
-
- private:
-  void WriteObjectImpl(const Object& x, intptr_t cid, intptr_t object_index);
-
-  // Used to track scopes of recursive types during serialization.
-  struct TypeScope {
-    TypeScope(FlowGraphSerializer* serializer, bool is_recursive)
-        : serializer_(serializer),
-          is_recursive_(is_recursive),
-          was_writing_recursive_type_(serializer->writing_recursive_type_) {
-      serializer->writing_recursive_type_ = is_recursive;
-    }
-
-    ~TypeScope() {
-      serializer_->writing_recursive_type_ = was_writing_recursive_type_;
-    }
-
-    // Returns true if type of the current scope can be canonicalized
-    // during deserialization. Recursive types which were not
-    // fully deserialized should not be canonicalized.
-    bool CanBeCanonicalized() const {
-      return !is_recursive_ || !was_writing_recursive_type_;
-    }
-
-    FlowGraphSerializer* const serializer_;
-    const bool is_recursive_;
-    const bool was_writing_recursive_type_;
-  };
-
-  NonStreamingWriteStream* stream_;
-  Zone* zone_;
-  IsolateGroup* isolate_group_;
-  Heap* heap_;
-  intptr_t object_counter_ = 0;
-  bool can_write_refs_ = false;
-  bool writing_recursive_type_ = false;
-};
-
-// Deserializes flow graph.
-// All constants and types are canonicalized during deserialization.
-class FlowGraphDeserializer : public ValueObject {
- public:
-  FlowGraphDeserializer(const ParsedFunction& parsed_function,
-                        ReadStream* stream);
-
-  const ParsedFunction& parsed_function() const { return parsed_function_; }
-
-  Zone* zone() const { return zone_; }
-  ReadStream* stream() const { return stream_; }
-  Thread* thread() const { return thread_; }
-  IsolateGroup* isolate_group() const { return isolate_group_; }
-
-  GraphEntryInstr* graph_entry() const { return graph_entry_; }
-  void set_graph_entry(GraphEntryInstr* entry) { graph_entry_ = entry; }
-
-  BlockEntryInstr* current_block() const { return current_block_; }
-  void set_current_block(BlockEntryInstr* block) { current_block_ = block; }
-
-  BlockEntryInstr* block(intptr_t block_id) const {
-    BlockEntryInstr* b = blocks_[block_id];
-    ASSERT(b != nullptr);
-    return b;
-  }
-  void set_block(intptr_t block_id, BlockEntryInstr* block) {
-    ASSERT(blocks_[block_id] == nullptr);
-    blocks_[block_id] = block;
-  }
-
-  Definition* definition(intptr_t ssa_temp_index) const {
-    Definition* def = definitions_[ssa_temp_index];
-    ASSERT(def != nullptr);
-    return def;
-  }
-  void set_definition(intptr_t ssa_temp_index, Definition* def) {
-    ASSERT(definitions_[ssa_temp_index] == nullptr);
-    definitions_[ssa_temp_index] = def;
-  }
-
-  FlowGraph* ReadFlowGraph();
-
-  // Default implementation of 'Read' method, when
-  // specialization for a particular type is not provided.
-  // This struct is used for the partial template instantiations below.
-  template <typename T>
-  struct ReadTrait {};
-
-  template <typename T>
-  struct ReadTrait<GrowableArray<T>> {
-    static GrowableArray<T> Read(FlowGraphDeserializer* d) {
-      const intptr_t len = d->Read<intptr_t>();
-      GrowableArray<T> array(len);
-      for (int i = 0; i < len; ++i) {
-        array.Add(d->Read<T>());
-      }
-      return array;
-    }
-  };
-
-  template <typename T>
-  struct ReadTrait<const GrowableArray<T>&> {
-    static const GrowableArray<T>& Read(FlowGraphDeserializer* d) {
-      return ReadTrait<GrowableArray<T>>::Read(d);
-    }
-  };
-
-  template <typename T>
-  struct ReadTrait<ZoneGrowableArray<T>*> {
-    static ZoneGrowableArray<T>* Read(FlowGraphDeserializer* d) {
-      const intptr_t len = d->Read<intptr_t>();
-      if (len < 0) {
-        return nullptr;
-      }
-      auto* array = new (d->zone()) ZoneGrowableArray<T>(d->zone(), len);
-      for (int i = 0; i < len; ++i) {
-        array->Add(d->Read<T>());
-      }
-      return array;
-    }
-  };
-
-  template <typename T>
-  struct ReadTrait<const ZoneGrowableArray<T>&> {
-    static const ZoneGrowableArray<T>& Read(FlowGraphDeserializer* d) {
-      return *ReadTrait<ZoneGrowableArray<T>*>::Read(d);
-    }
-  };
-
-  // Specialization in case intptr_t is not mapped to intN_t.
-  template <>
-  struct ReadTrait<intptr_t> {
-    static intptr_t Read(FlowGraphDeserializer* d) {
-#ifdef ARCH_IS_64_BIT
-      return d->Read<int64_t>();
-#else
-      return d->Read<int32_t>();
-#endif
-    }
-  };
-
-  // Specialization in case uintptr_t is not mapped to uintN_t.
-  template <>
-  struct ReadTrait<uintptr_t> {
-    static uintptr_t Read(FlowGraphDeserializer* d) {
-#ifdef ARCH_IS_64_BIT
-      return d->Read<uint64_t>();
-#else
-      return d->Read<uint32_t>();
-#endif
-    }
-  };
-
-  template <typename T>
-  T Read() {
-    return ReadTrait<T>::Read(this);
-  }
-
-#define DECLARE_READ_METHOD(type)                                              \
-  template <>                                                                  \
-  type Read<type>();
-  IL_SERIALIZABLE_TYPE_LIST(DECLARE_READ_METHOD)
-#undef DECLARE_READ_METHOD
-
-  template <typename T>
-  T ReadRef();
-
-#define DECLARE_READ_REF_METHOD(type)                                          \
-  template <>                                                                  \
-  type ReadRef<type>();
-  IL_SERIALIZABLE_REF_TYPE_LIST(DECLARE_READ_REF_METHOD)
-#undef DECLARE_READ_REF_METHOD
-
-  template <typename T>
-  GrowableArray<T> ReadGrowableArrayOfRefs() {
-    const intptr_t len = Read<intptr_t>();
-    GrowableArray<T> array(len);
-    for (int i = 0; i < len; ++i) {
-      array.Add(ReadRef<T>());
-    }
-    return std::move(array);
-  }
-
- private:
-  ClassPtr GetClassById(classid_t id) const;
-  const Object& ReadObjectImpl(intptr_t cid, intptr_t object_index);
-  void SetObjectAt(intptr_t object_index, const Object& object);
-
-  InstancePtr MaybeCanonicalize(const Instance& obj,
-                                intptr_t object_index,
-                                bool can_be_canonicalized);
-
-  const ParsedFunction& parsed_function_;
-  ReadStream* stream_;
-  Zone* zone_;
-  Thread* thread_;
-  IsolateGroup* isolate_group_;
-
-  // Deserialized objects.
-  GraphEntryInstr* graph_entry_ = nullptr;
-  BlockEntryInstr* current_block_ = nullptr;
-  GrowableArray<BlockEntryInstr*> blocks_;
-  GrowableArray<Definition*> definitions_;
-  GrowableArray<const Object*> objects_;
-  intptr_t object_counter_ = 0;
-  GrowableArray<intptr_t> pending_canonicalization_;
-};
-
-}  // namespace dart
-
-#endif  // RUNTIME_VM_COMPILER_BACKEND_IL_SERIALIZER_H_
diff --git a/runtime/vm/compiler/backend/locations.h b/runtime/vm/compiler/backend/locations.h
index c82215f..aabd12a 100644
--- a/runtime/vm/compiler/backend/locations.h
+++ b/runtime/vm/compiler/backend/locations.h
@@ -21,8 +21,6 @@
 class BaseTextBuffer;
 class ConstantInstr;
 class Definition;
-class FlowGraphDeserializer;
-class FlowGraphSerializer;
 class PairLocation;
 class Value;
 
@@ -432,8 +430,8 @@
 
   Location Copy() const;
 
-  void Write(FlowGraphSerializer* s) const;
-  static Location Read(FlowGraphDeserializer* d);
+  static Location read(uword value) { return Location(value); }
+  uword write() const { return value_; }
 
  private:
   explicit Location(uword value) : value_(value) {}
@@ -574,7 +572,8 @@
     ASSERT(kNumberOfFpuRegisters <= (kWordSize * kBitsPerByte));
   }
 
-  explicit RegisterSet(uintptr_t cpu_register_mask, uintptr_t fpu_register_mask)
+  explicit RegisterSet(uintptr_t cpu_register_mask,
+                       uintptr_t fpu_register_mask = 0)
       : RegisterSet() {
     AddTaggedRegisters(cpu_register_mask, fpu_register_mask);
   }
@@ -718,9 +717,6 @@
     untagged_cpu_registers_.Clear();
   }
 
-  void Write(FlowGraphSerializer* s) const;
-  explicit RegisterSet(FlowGraphDeserializer* d);
-
  private:
   SmallSet<Register> cpu_registers_;
   SmallSet<Register> untagged_cpu_registers_;
@@ -839,9 +835,6 @@
   void CheckWritableInputs();
 #endif
 
-  void Write(FlowGraphSerializer* s) const;
-  explicit LocationSummary(FlowGraphDeserializer* d);
-
  private:
   BitmapBuilder& EnsureStackBitmap() {
     if (stack_bitmap_ == NULL) {
diff --git a/runtime/vm/compiler/backend/range_analysis.cc b/runtime/vm/compiler/backend/range_analysis.cc
index 9025738..f2cf0ab 100644
--- a/runtime/vm/compiler/backend/range_analysis.cc
+++ b/runtime/vm/compiler/backend/range_analysis.cc
@@ -1815,7 +1815,7 @@
   int64_t value = value_boundary.ConstantValue();
 
   if (value == 0) {
-    return RangeBoundary::FromConstant(0);
+    return RangeBoundary(0);
   } else if (shift_count == 0 ||
              (limit > 0 && Utils::IsInt(static_cast<int>(limit), value))) {
     // Result stays in 64 bit range.
diff --git a/runtime/vm/compiler/backend/range_analysis.h b/runtime/vm/compiler/backend/range_analysis.h
index dc178f6..aa1f6b9 100644
--- a/runtime/vm/compiler/backend/range_analysis.h
+++ b/runtime/vm/compiler/backend/range_analysis.h
@@ -301,9 +301,6 @@
 
   int64_t SmiLowerBound() const { return LowerBound(kRangeBoundarySmi); }
 
-  void Write(FlowGraphSerializer* s) const;
-  explicit RangeBoundary(FlowGraphDeserializer* d);
-
  private:
   RangeBoundary(Kind kind, int64_t value, int64_t offset)
       : kind_(kind), value_(value), offset_(offset) {}
@@ -539,9 +536,6 @@
                        Definition* left_defn,
                        Range* result);
 
-  void Write(FlowGraphSerializer* s) const;
-  explicit Range(FlowGraphDeserializer* d);
-
  private:
   RangeBoundary min_;
   RangeBoundary max_;
diff --git a/runtime/vm/compiler/backend/range_analysis_test.cc b/runtime/vm/compiler/backend/range_analysis_test.cc
index 39b4729..ce2d3d5 100644
--- a/runtime/vm/compiler/backend/range_analysis_test.cc
+++ b/runtime/vm/compiler/backend/range_analysis_test.cc
@@ -82,14 +82,13 @@
                       RangeBoundary(compiler::target::kSmiMin),
                       RangeBoundary(compiler::target::kSmiMax));
   }
-  TEST_RANGE_OP(Range::Shl, 0, 100, 0, 64, RangeBoundary::FromConstant(0),
+  TEST_RANGE_OP(Range::Shl, 0, 100, 0, 64, RangeBoundary(0),
                 RangeBoundary::PositiveInfinity());
   TEST_RANGE_OP(Range::Shl, -100, 0, 0, 64, RangeBoundary::NegativeInfinity(),
-                RangeBoundary::FromConstant(0));
+                RangeBoundary(0));
 
   TEST_RANGE_OP(Range::Shr, -8, 8, 1, 2, RangeBoundary(-4), RangeBoundary(4));
-  TEST_RANGE_OP(Range::Shr, 1, 8, 1, 2, RangeBoundary::FromConstant(0),
-                RangeBoundary(4));
+  TEST_RANGE_OP(Range::Shr, 1, 8, 1, 2, RangeBoundary(0), RangeBoundary(4));
   TEST_RANGE_OP(Range::Shr, -16, -8, 1, 2, RangeBoundary(-8),
                 RangeBoundary(-2));
   TEST_RANGE_OP(Range::Shr, 2, 4, -1, 1, RangeBoundary(1), RangeBoundary(4));
@@ -467,26 +466,24 @@
   // [0xff, 0xfff] & [0xf, 0xf] = [0x0, 0xf].
   TEST_RANGE_AND(static_cast<int64_t>(0xff), static_cast<int64_t>(0xfff),
                  static_cast<int64_t>(0xf), static_cast<int64_t>(0xf),
-                 RangeBoundary::FromConstant(0), RangeBoundary(0xf));
+                 RangeBoundary(0), RangeBoundary(0xf));
 
   // [0xffffffff, 0xffffffff] & [0xfffffffff, 0xfffffffff] = [0x0, 0xfffffffff].
   TEST_RANGE_AND(
       static_cast<int64_t>(0xffffffff), static_cast<int64_t>(0xffffffff),
       static_cast<int64_t>(0xfffffffff), static_cast<int64_t>(0xfffffffff),
-      RangeBoundary::FromConstant(0),
-      RangeBoundary(static_cast<int64_t>(0xfffffffff)));
+      RangeBoundary(0), RangeBoundary(static_cast<int64_t>(0xfffffffff)));
 
   // [0xffffffff, 0xffffffff] & [-20, 20] = [0x0, 0xffffffff].
   TEST_RANGE_AND(static_cast<int64_t>(0xffffffff),
                  static_cast<int64_t>(0xffffffff), static_cast<int64_t>(-20),
-                 static_cast<int64_t>(20), RangeBoundary::FromConstant(0),
+                 static_cast<int64_t>(20), RangeBoundary(0),
                  RangeBoundary(static_cast<int64_t>(0xffffffff)));
 
   // [-20, 20] & [0xffffffff, 0xffffffff] = [0x0, 0xffffffff].
   TEST_RANGE_AND(static_cast<int64_t>(-20), static_cast<int64_t>(20),
                  static_cast<int64_t>(0xffffffff),
-                 static_cast<int64_t>(0xffffffff),
-                 RangeBoundary::FromConstant(0),
+                 static_cast<int64_t>(0xffffffff), RangeBoundary(0),
                  RangeBoundary(static_cast<int64_t>(0xffffffff)));
 
   // Test that [-20, 20] & [-20, 20] = [-32, 31].
diff --git a/runtime/vm/compiler/backend/redundancy_elimination.cc b/runtime/vm/compiler/backend/redundancy_elimination.cc
index 454cae9..c192500 100644
--- a/runtime/vm/compiler/backend/redundancy_elimination.cc
+++ b/runtime/vm/compiler/backend/redundancy_elimination.cc
@@ -3676,10 +3676,8 @@
 // Remove materializations from the graph. Register allocator will treat them
 // as part of the environment not as a real instruction.
 void AllocationSinking::DetachMaterializations() {
-  for (MaterializeObjectInstr* mat : materializations_) {
-    mat->previous()->LinkTo(mat->next());
-    mat->set_next(nullptr);
-    mat->set_previous(nullptr);
+  for (intptr_t i = 0; i < materializations_.length(); i++) {
+    materializations_[i]->previous()->LinkTo(materializations_[i]->next());
   }
 }
 
diff --git a/runtime/vm/compiler/backend/slot.cc b/runtime/vm/compiler/backend/slot.cc
index 46acba6..6554f8b 100644
--- a/runtime/vm/compiler/backend/slot.cc
+++ b/runtime/vm/compiler/backend/slot.cc
@@ -302,60 +302,48 @@
   const intptr_t offset =
       compiler::target::Class::TypeArgumentsFieldOffset(cls);
   ASSERT(offset != Class::kNoTypeArguments);
-  return GetCanonicalSlot(
-      thread, Kind::kTypeArguments,
-      IsImmutableBit::encode(true) |
-          IsCompressedBit::encode(
-              compiler::target::Class::HasCompressedPointers(cls)),
-      kTypeArgumentsCid, offset, ":type_arguments",
-      /*static_type=*/nullptr, kTagged);
+  return SlotCache::Instance(thread).Canonicalize(
+      Slot(Kind::kTypeArguments,
+           IsImmutableBit::encode(true) |
+               IsCompressedBit::encode(
+                   compiler::target::Class::HasCompressedPointers(cls)),
+           kTypeArgumentsCid, offset, ":type_arguments",
+           /*static_type=*/nullptr, kTagged));
 }
 
 const Slot& Slot::GetContextVariableSlotFor(Thread* thread,
                                             const LocalVariable& variable) {
   ASSERT(variable.is_captured());
-  return GetCanonicalSlot(
-      thread, Kind::kCapturedVariable,
-      IsImmutableBit::encode(variable.is_final() && !variable.is_late()) |
-          IsNullableBit::encode(true) |
-          IsCompressedBit::encode(Context::ContainsCompressedPointers()) |
-          IsSentinelVisibleBit::encode(variable.is_late()),
-      kDynamicCid,
-      compiler::target::Context::variable_offset(variable.index().value()),
-      &variable.name(), &variable.type(), kTagged);
+  return SlotCache::Instance(thread).Canonicalize(
+      Slot(Kind::kCapturedVariable,
+           IsImmutableBit::encode(variable.is_final() && !variable.is_late()) |
+               IsNullableBit::encode(true) |
+               IsCompressedBit::encode(Context::ContainsCompressedPointers()) |
+               IsSentinelVisibleBit::encode(variable.is_late()),
+           kDynamicCid,
+           compiler::target::Context::variable_offset(variable.index().value()),
+           &variable.name(), &variable.type(), kTagged));
 }
 
 const Slot& Slot::GetTypeArgumentsIndexSlot(Thread* thread, intptr_t index) {
   const intptr_t offset =
       compiler::target::TypeArguments::type_at_offset(index);
-  return GetCanonicalSlot(
-      thread, Kind::kTypeArgumentsIndex,
+  const Slot& slot = Slot(
+      Kind::kTypeArgumentsIndex,
       IsImmutableBit::encode(true) |
           IsCompressedBit::encode(TypeArguments::ContainsCompressedPointers()),
       kDynamicCid, offset, ":argument", /*static_type=*/nullptr, kTagged);
+  return SlotCache::Instance(thread).Canonicalize(slot);
 }
 
 const Slot& Slot::GetArrayElementSlot(Thread* thread,
                                       intptr_t offset_in_bytes) {
-  return GetCanonicalSlot(
-      thread, Kind::kArrayElement,
-      IsNullableBit::encode(true) |
-          IsCompressedBit::encode(Array::ContainsCompressedPointers()),
-      kDynamicCid, offset_in_bytes, ":array_element",
-      /*static_type=*/nullptr, kTagged);
-}
-
-const Slot& Slot::GetCanonicalSlot(Thread* thread,
-                                   Slot::Kind kind,
-                                   int8_t flags,
-                                   ClassIdTagType cid,
-                                   intptr_t offset_in_bytes,
-                                   const void* data,
-                                   const AbstractType* static_type,
-                                   Representation representation,
-                                   const FieldGuardState& field_guard_state) {
-  const Slot& slot = Slot(kind, flags, cid, offset_in_bytes, data, static_type,
-                          representation, field_guard_state);
+  const Slot& slot =
+      Slot(Kind::kArrayElement,
+           IsNullableBit::encode(true) |
+               IsCompressedBit::encode(Array::ContainsCompressedPointers()),
+           kDynamicCid, offset_in_bytes, ":array_element",
+           /*static_type=*/nullptr, kTagged);
   return SlotCache::Instance(thread).Canonicalize(slot);
 }
 
@@ -468,8 +456,8 @@
   }
 
   Class& owner = Class::Handle(zone, field.Owner());
-  const Slot& slot = GetCanonicalSlot(
-      thread, Kind::kDartField,
+  const Slot& slot = SlotCache::Instance(thread).Canonicalize(Slot(
+      Kind::kDartField,
       IsImmutableBit::encode((field.is_final() && !field.is_late()) ||
                              field.is_const()) |
           IsNullableBit::encode(is_nullable) |
@@ -479,7 +467,7 @@
           IsSentinelVisibleBit::encode(field.is_late() && field.is_final() &&
                                        !field.has_initializer()),
       nullable_cid, compiler::target::Field::OffsetOf(field), &field, &type,
-      rep, field_guard_state);
+      rep, field_guard_state));
 
   // If properties of this slot were based on the guarded state make sure
   // to add the field to the list of guarded fields. Note that during background
diff --git a/runtime/vm/compiler/backend/slot.h b/runtime/vm/compiler/backend/slot.h
index 90838c9..eb87355 100644
--- a/runtime/vm/compiler/backend/slot.h
+++ b/runtime/vm/compiler/backend/slot.h
@@ -357,12 +357,9 @@
   bool IsPotentialUnboxed() const;
   Representation UnboxedRepresentation() const;
 
-  void Write(FlowGraphSerializer* s) const;
-  static const Slot& Read(FlowGraphDeserializer* d);
-
  private:
   Slot(Kind kind,
-       int8_t flags,
+       int8_t bits,
        ClassIdTagType cid,
        intptr_t offset_in_bytes,
        const void* data,
@@ -370,7 +367,7 @@
        Representation representation,
        const FieldGuardState& field_guard_state = FieldGuardState())
       : kind_(kind),
-        flags_(flags),
+        flags_(bits),
         cid_(cid),
         offset_in_bytes_(offset_in_bytes),
         representation_(representation),
@@ -400,17 +397,6 @@
     return static_cast<const T*>(data_);
   }
 
-  static const Slot& GetCanonicalSlot(
-      Thread* thread,
-      Kind kind,
-      int8_t flags,
-      ClassIdTagType cid,
-      intptr_t offset_in_bytes,
-      const void* data,
-      const AbstractType* static_type,
-      Representation representation,
-      const FieldGuardState& field_guard_state = FieldGuardState());
-
   // There is a fixed statically known number of native slots so we cache
   // them statically.
   static AcqRelAtomic<Slot*> native_fields_;
diff --git a/runtime/vm/compiler/compiler_pass.cc b/runtime/vm/compiler/compiler_pass.cc
index 6486fca..f6a4dd3 100644
--- a/runtime/vm/compiler/compiler_pass.cc
+++ b/runtime/vm/compiler/compiler_pass.cc
@@ -84,7 +84,6 @@
                       "Do --compiler-passes=help for more information.");
 DECLARE_FLAG(bool, print_flow_graph);
 DECLARE_FLAG(bool, print_flow_graph_optimized);
-DEFINE_FLAG(bool, test_il_serialization, false, "Test IL serialization.");
 
 void CompilerPassState::set_flow_graph(FlowGraph* flow_graph) {
   flow_graph_ = flow_graph;
@@ -566,22 +565,6 @@
   if (state->reorder_blocks) {
     BlockScheduler::ReorderBlocks(flow_graph);
   }
-
-  // This is the last compiler pass.
-  // Test that round-trip IL serialization works before generating code.
-  if (FLAG_test_il_serialization && CompilerState::Current().is_aot()) {
-    Zone* zone = flow_graph->zone();
-    auto* detached_defs = new (zone) ZoneGrowableArray<Definition*>(zone, 0);
-    flow_graph->CompactSSA(detached_defs);
-
-    ZoneWriteStream write_stream(flow_graph->zone(), 1024);
-    FlowGraphSerializer serializer(&write_stream);
-    serializer.WriteFlowGraph(*flow_graph, *detached_defs);
-    ReadStream read_stream(write_stream.buffer(), write_stream.bytes_written());
-    FlowGraphDeserializer deserializer(flow_graph->parsed_function(),
-                                       &read_stream);
-    state->set_flow_graph(deserializer.ReadFlowGraph());
-  }
 });
 
 COMPILER_PASS(EliminateWriteBarriers, { EliminateWriteBarriers(flow_graph); });
diff --git a/runtime/vm/compiler/compiler_sources.gni b/runtime/vm/compiler/compiler_sources.gni
index ed545d6..ace9914 100644
--- a/runtime/vm/compiler/compiler_sources.gni
+++ b/runtime/vm/compiler/compiler_sources.gni
@@ -65,8 +65,6 @@
   "backend/il_printer.cc",
   "backend/il_printer.h",
   "backend/il_riscv.cc",
-  "backend/il_serializer.cc",
-  "backend/il_serializer.h",
   "backend/il_x64.cc",
   "backend/inliner.cc",
   "backend/inliner.h",
diff --git a/runtime/vm/compiler/ffi/call.cc b/runtime/vm/compiler/ffi/call.cc
index 0cee4de..be76d75 100644
--- a/runtime/vm/compiler/ffi/call.cc
+++ b/runtime/vm/compiler/ffi/call.cc
@@ -14,43 +14,6 @@
 namespace ffi {
 
 // TODO(dartbug.com/36607): Cache the trampolines.
-FunctionPtr TrampolineFunction(const String& name,
-                               const FunctionType& signature,
-                               const FunctionType& c_signature,
-                               bool is_leaf) {
-  ASSERT(signature.num_implicit_parameters() == 1);
-  Thread* thread = Thread::Current();
-  Zone* zone = thread->zone();
-  const Library& lib = Library::Handle(zone, Library::FfiLibrary());
-  const Class& owner_class = Class::Handle(zone, lib.toplevel_class());
-  Function& function = Function::Handle(
-      zone, Function::New(signature, name, UntaggedFunction::kFfiTrampoline,
-                          /*is_static=*/true,
-                          /*is_const=*/false,
-                          /*is_abstract=*/false,
-                          /*is_external=*/false,
-                          /*is_native=*/false, owner_class,
-                          TokenPosition::kMinSource));
-  function.set_is_debuggable(false);
-
-  // Create unique names for the parameters, as they are used in scope building
-  // and error messages.
-  if (signature.num_fixed_parameters() > 0) {
-    function.CreateNameArray();
-    function.SetParameterNameAt(0, Symbols::ClosureParameter());
-    auto& param_name = String::Handle(zone);
-    for (intptr_t i = 1, n = signature.num_fixed_parameters(); i < n; ++i) {
-      param_name = Symbols::NewFormatted(thread, ":ffi_param%" Pd, i);
-      function.SetParameterNameAt(i, param_name);
-    }
-  }
-
-  function.SetFfiCSignature(c_signature);
-  function.SetFfiIsLeaf(is_leaf);
-
-  return function.ptr();
-}
-
 FunctionPtr TrampolineFunction(const FunctionType& dart_signature,
                                const FunctionType& c_signature,
                                bool is_leaf,
@@ -60,19 +23,43 @@
   String& name =
       String::Handle(zone, Symbols::NewFormatted(thread, "FfiTrampoline_%s",
                                                  function_name.ToCString()));
-
-  // Trampolines have no optional arguments.
+  const Library& lib = Library::Handle(zone, Library::FfiLibrary());
+  const Class& owner_class = Class::Handle(zone, lib.toplevel_class());
   FunctionType& signature = FunctionType::Handle(zone, FunctionType::New());
+  Function& function = Function::Handle(
+      zone, Function::New(signature, name, UntaggedFunction::kFfiTrampoline,
+                          /*is_static=*/true,
+                          /*is_const=*/false,
+                          /*is_abstract=*/false,
+                          /*is_external=*/false,
+                          /*is_native=*/false, owner_class,
+                          TokenPosition::kMinSource));
+  function.set_is_debuggable(false);
+  // Trampolines have no optional arguments.
   const intptr_t num_fixed = dart_signature.num_fixed_parameters();
-  signature.set_num_implicit_parameters(1);
   signature.set_num_fixed_parameters(num_fixed);
   signature.set_result_type(
       AbstractType::Handle(zone, dart_signature.result_type()));
   signature.set_parameter_types(
       Array::Handle(zone, dart_signature.parameter_types()));
-  signature ^= ClassFinalizer::FinalizeType(signature);
 
-  return TrampolineFunction(name, signature, c_signature, is_leaf);
+  // Create unique names for the parameters, as they are used in scope building
+  // and error messages.
+  if (num_fixed > 0) {
+    function.CreateNameArray();
+    function.SetParameterNameAt(0, Symbols::ClosureParameter());
+    for (intptr_t i = 1; i < num_fixed; i++) {
+      name = Symbols::NewFormatted(thread, ":ffi_param%" Pd, i);
+      function.SetParameterNameAt(i, name);
+    }
+  }
+  function.SetFfiCSignature(c_signature);
+  signature ^= ClassFinalizer::FinalizeType(signature);
+  function.SetSignature(signature);
+
+  function.SetFfiIsLeaf(is_leaf);
+
+  return function.ptr();
 }
 
 }  // namespace ffi
diff --git a/runtime/vm/compiler/ffi/call.h b/runtime/vm/compiler/ffi/call.h
index 11c328a..aecd128 100644
--- a/runtime/vm/compiler/ffi/call.h
+++ b/runtime/vm/compiler/ffi/call.h
@@ -19,11 +19,6 @@
 
 namespace ffi {
 
-FunctionPtr TrampolineFunction(const String& name,
-                               const FunctionType& signature,
-                               const FunctionType& c_signature,
-                               bool is_leaf);
-
 FunctionPtr TrampolineFunction(const FunctionType& dart_signature,
                                const FunctionType& c_signature,
                                bool is_leaf,
diff --git a/runtime/vm/compiler/ffi/marshaller.h b/runtime/vm/compiler/ffi/marshaller.h
index 61eea68..175e12e 100644
--- a/runtime/vm/compiler/ffi/marshaller.h
+++ b/runtime/vm/compiler/ffi/marshaller.h
@@ -131,7 +131,6 @@
 
   bool ContainsHandles() const;
 
-  const Function& dart_signature() const { return dart_signature_; }
   StringPtr function_name() const { return dart_signature_.name(); }
 
  protected:
diff --git a/runtime/vm/compiler/stub_code_compiler.cc b/runtime/vm/compiler/stub_code_compiler.cc
index a4c1c5e..525dc4d 100644
--- a/runtime/vm/compiler/stub_code_compiler.cc
+++ b/runtime/vm/compiler/stub_code_compiler.cc
@@ -889,8 +889,7 @@
   // Fall through to &is_simple_case
 
   const RegisterSet caller_saved_registers(
-      TypeTestABI::kSubtypeTestCacheStubCallerSavedRegisters,
-      /*fpu_registers=*/0);
+      TypeTestABI::kSubtypeTestCacheStubCallerSavedRegisters);
 
   __ Bind(&is_simple_case);
   {
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 0aca34f..76817ed 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -3222,28 +3222,6 @@
   }
 }
 
-intptr_t Class::FindFunctionIndex(const Function& needle) const {
-  Thread* thread = Thread::Current();
-  if (EnsureIsFinalized(thread) != Error::null()) {
-    return -1;
-  }
-  REUSABLE_ARRAY_HANDLESCOPE(thread);
-  REUSABLE_FUNCTION_HANDLESCOPE(thread);
-  Array& funcs = thread->ArrayHandle();
-  Function& function = thread->FunctionHandle();
-  funcs = current_functions();
-  ASSERT(!funcs.IsNull());
-  const intptr_t len = funcs.Length();
-  for (intptr_t i = 0; i < len; i++) {
-    function ^= funcs.At(i);
-    if (needle.ptr() == function.ptr()) {
-      return i;
-    }
-  }
-  // No function found.
-  return -1;
-}
-
 FunctionPtr Class::FunctionFromIndex(intptr_t idx) const {
   const Array& funcs = Array::Handle(current_functions());
   if ((idx < 0) || (idx >= funcs.Length())) {
@@ -3256,13 +3234,20 @@
 }
 
 FunctionPtr Class::ImplicitClosureFunctionFromIndex(intptr_t idx) const {
-  Function& func = Function::Handle(FunctionFromIndex(idx));
-  if (func.IsNull() || !func.HasImplicitClosureFunction()) {
+  const Array& funcs = Array::Handle(current_functions());
+  if ((idx < 0) || (idx >= funcs.Length())) {
     return Function::null();
   }
-  func = func.ImplicitClosureFunction();
+  Function& func = Function::Handle();
+  func ^= funcs.At(idx);
   ASSERT(!func.IsNull());
-  return func.ptr();
+  if (!func.HasImplicitClosureFunction()) {
+    return Function::null();
+  }
+  const Function& closure_func =
+      Function::Handle(func.ImplicitClosureFunction());
+  ASSERT(!closure_func.IsNull());
+  return closure_func.ptr();
 }
 
 intptr_t Class::FindImplicitClosureFunctionIndex(const Function& needle) const {
@@ -4697,35 +4682,6 @@
   SetFields(new_arr);
 }
 
-intptr_t Class::FindFieldIndex(const Field& needle) const {
-  Thread* thread = Thread::Current();
-  if (EnsureIsFinalized(thread) != Error::null()) {
-    return -1;
-  }
-  REUSABLE_ARRAY_HANDLESCOPE(thread);
-  REUSABLE_FIELD_HANDLESCOPE(thread);
-  Array& fields = thread->ArrayHandle();
-  Field& field = thread->FieldHandle();
-  fields = this->fields();
-  ASSERT(!fields.IsNull());
-  for (intptr_t i = 0, n = fields.Length(); i < n; ++i) {
-    field ^= fields.At(i);
-    if (needle.ptr() == field.ptr()) {
-      return i;
-    }
-  }
-  // Not found.
-  return -1;
-}
-
-FieldPtr Class::FieldFromIndex(intptr_t idx) const {
-  Array& fields = Array::Handle(this->fields());
-  if ((idx < 0) || (idx >= fields.Length())) {
-    return Field::null();
-  }
-  return Field::RawCast(fields.At(idx));
-}
-
 bool Class::InjectCIDFields() const {
   if (library() != Library::InternalLibrary() ||
       Name() != Symbols::ClassID().ptr()) {
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 555d22c..ed7f206 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -1478,9 +1478,6 @@
   void AddField(const Field& field) const;
   void AddFields(const GrowableArray<const Field*>& fields) const;
 
-  intptr_t FindFieldIndex(const Field& needle) const;
-  FieldPtr FieldFromIndex(intptr_t idx) const;
-
   // If this is a dart:internal.ClassID class, then inject our own const
   // fields. Returns true if synthetic fields are injected and regular
   // field declarations should be ignored.
@@ -1508,7 +1505,6 @@
   }
   void SetFunctions(const Array& value) const;
   void AddFunction(const Function& function) const;
-  intptr_t FindFunctionIndex(const Function& needle) const;
   FunctionPtr FunctionFromIndex(intptr_t idx) const;
   intptr_t FindImplicitClosureFunctionIndex(const Function& needle) const;
   FunctionPtr ImplicitClosureFunctionFromIndex(intptr_t idx) const;
@@ -7776,8 +7772,6 @@
   friend class Closure;
   friend class Pointer;
   friend class DeferredObject;
-  friend class FlowGraphSerializer;
-  friend class FlowGraphDeserializer;
   friend class RegExp;
   friend class StubCode;
   friend class TypedDataView;
@@ -7904,8 +7898,6 @@
   FINAL_HEAP_OBJECT_IMPLEMENTATION(TypeParameters, Object);
   friend class Class;
   friend class ClassFinalizer;
-  friend class FlowGraphSerializer;
-  friend class FlowGraphDeserializer;
   friend class Function;
   friend class FunctionType;
   friend class Object;
@@ -9919,7 +9911,6 @@
 
   friend class Class;
   friend class ExternalOneByteString;
-  friend class FlowGraphSerializer;
   friend class ImageWriter;
   friend class String;
   friend class StringHasher;
@@ -10040,7 +10031,6 @@
   }
 
   friend class Class;
-  friend class FlowGraphSerializer;
   friend class ImageWriter;
   friend class String;
   friend class StringHasher;
diff --git a/runtime/vm/regexp_assembler_ir.cc b/runtime/vm/regexp_assembler_ir.cc
index 99440a2..2e7a7b4 100644
--- a/runtime/vm/regexp_assembler_ir.cc
+++ b/runtime/vm/regexp_assembler_ir.cc
@@ -928,9 +928,15 @@
 
     Definition* is_match_def;
 
-    is_match_def = new (Z) CaseInsensitiveCompareInstr(
-        string_value, lhs_index_value, rhs_index_value, length_value,
-        /*handle_surrogates=*/unicode, specialization_cid_);
+    if (unicode) {
+      is_match_def = new (Z) CaseInsensitiveCompareInstr(
+          string_value, lhs_index_value, rhs_index_value, length_value,
+          kCaseInsensitiveCompareUTF16RuntimeEntry, specialization_cid_);
+    } else {
+      is_match_def = new (Z) CaseInsensitiveCompareInstr(
+          string_value, lhs_index_value, rhs_index_value, length_value,
+          kCaseInsensitiveCompareUCS2RuntimeEntry, specialization_cid_);
+    }
 
     BranchOrBacktrack(Comparison(kNE, is_match_def, BoolConstant(true)),
                       on_no_match);
diff --git a/runtime/vm/type_testing_stubs.cc b/runtime/vm/type_testing_stubs.cc
index aa79b1d..41ac9d1 100644
--- a/runtime/vm/type_testing_stubs.cc
+++ b/runtime/vm/type_testing_stubs.cc
@@ -626,7 +626,7 @@
     // c) Then we'll check each value of the type argument.
     compiler::Label pop_saved_registers_on_failure;
     const RegisterSet saved_registers(
-        TTSInternalRegs::kSavedTypeArgumentRegisters, /*fpu_registers=*/0);
+        TTSInternalRegs::kSavedTypeArgumentRegisters);
     __ PushRegisters(saved_registers);
 
     AbstractType& type_arg = AbstractType::Handle();