Version 2.13.0-124.0.dev

Merge commit '73f9d0cd26176f128edcde491644bb911f1178c7' into 'dev'
diff --git a/pkg/_fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart b/pkg/_fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart
index fe7cfc1..6c06628 100644
--- a/pkg/_fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart
@@ -232,11 +232,6 @@
             '{${_info.keys.map((k) => '$k (${k.hashCode})').join(',')}}'));
   }
 
-  /// Indicates whether information is stored for the given [node].
-  bool _hasInfoForNode(Node node) {
-    return _info[node] != null;
-  }
-
   void _printOn(StringBuffer sb) {
     sb.write('_info=$_info,');
     sb.write('_stack=$_stack,');
@@ -894,11 +889,7 @@
 
   /// Call this method just after visiting a "try/finally" statement.
   /// See [tryFinallyStatement_bodyBegin] for details.
-  ///
-  /// [finallyBlock] should be the same node that was passed to
-  /// [AssignedVariables.endNode] for the "finally" part of the try/finally
-  /// statement.
-  void tryFinallyStatement_end(Node finallyBlock);
+  void tryFinallyStatement_end();
 
   /// Call this method just before visiting the finally block of a "try/finally"
   /// statement.  See [tryFinallyStatement_bodyBegin] for details.
@@ -1439,9 +1430,9 @@
   }
 
   @override
-  void tryFinallyStatement_end(Node finallyBlock) {
-    return _wrap('tryFinallyStatement_end($finallyBlock)',
-        () => _wrapped.tryFinallyStatement_end(finallyBlock));
+  void tryFinallyStatement_end() {
+    return _wrap(
+        'tryFinallyStatement_end()', () => _wrapped.tryFinallyStatement_end());
   }
 
   @override
@@ -4095,10 +4086,7 @@
   }
 
   @override
-  void tryFinallyStatement_end(Node finallyBlock) {
-    // We used to need info for `finally` blocks but we don't anymore.
-    assert(!_assignedVariables._hasInfoForNode(finallyBlock),
-        'No assigned variables info should have been stored for $finallyBlock');
+  void tryFinallyStatement_end() {
     _TryFinallyContext<Variable, Type> context =
         _stack.removeLast() as _TryFinallyContext<Variable, Type>;
     _current = context._afterBodyAndCatches!
@@ -4741,7 +4729,7 @@
   void tryFinallyStatement_bodyBegin() {}
 
   @override
-  void tryFinallyStatement_end(Node finallyBlock) {}
+  void tryFinallyStatement_end() {}
 
   @override
   void tryFinallyStatement_finallyBegin(Node body) {}
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/flow_analysis_mini_ast.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/flow_analysis_mini_ast.dart
index 024a4c6..afd3020 100644
--- a/pkg/_fe_analyzer_shared/test/flow_analysis/flow_analysis_mini_ast.dart
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/flow_analysis_mini_ast.dart
@@ -1640,7 +1640,6 @@
   final List<Statement> body;
   final List<Statement> finally_;
   final Node _bodyNode = Node._();
-  final Node _finallyNode = Node._();
 
   _TryFinally(this.body, this.finally_) : super._();
 
@@ -1662,7 +1661,7 @@
     body._visit(h, flow);
     flow.tryFinallyStatement_finallyBegin(_bodyNode);
     finally_._visit(h, flow);
-    flow.tryFinallyStatement_end(_finallyNode);
+    flow.tryFinallyStatement_end();
   }
 }
 
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index b061fe0..e7dd7cf 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -2055,7 +2055,7 @@
       flow.tryFinallyStatement_finallyBegin(
           catchClauses.isNotEmpty ? node : body);
       finallyBlock.accept(this);
-      flow.tryFinallyStatement_end(finallyBlock);
+      flow.tryFinallyStatement_end();
     }
   }
 
diff --git a/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart b/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
index 3b061ee..05af526 100644
--- a/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
@@ -6325,7 +6325,7 @@
       inferrer.flowAnalysis.tryFinallyStatement_finallyBegin(
           node.catchBlocks.isNotEmpty ? node : tryBodyWithAssignedInfo);
       finalizerResult = inferrer.inferStatement(node.finallyBlock);
-      inferrer.flowAnalysis.tryFinallyStatement_end(node.finallyBlock);
+      inferrer.flowAnalysis.tryFinallyStatement_end();
     }
     Statement result =
         tryBlockResult.hasChanged ? tryBlockResult.statement : node.tryBlock;
diff --git a/pkg/nnbd_migration/lib/src/edge_builder.dart b/pkg/nnbd_migration/lib/src/edge_builder.dart
index 850669e..5b97ce5 100644
--- a/pkg/nnbd_migration/lib/src/edge_builder.dart
+++ b/pkg/nnbd_migration/lib/src/edge_builder.dart
@@ -1776,7 +1776,7 @@
       _flowAnalysis.tryFinallyStatement_finallyBegin(
           catchClauses.isNotEmpty ? node : body);
       _dispatch(finallyBlock);
-      _flowAnalysis.tryFinallyStatement_end(finallyBlock);
+      _flowAnalysis.tryFinallyStatement_end();
     }
     return null;
   }
diff --git a/runtime/tests/vm/dart/base_il_serialization_test.dart b/runtime/tests/vm/dart/base_il_serialization_test.dart
deleted file mode 100644
index 569b661..0000000
--- a/runtime/tests/vm/dart/base_il_serialization_test.dart
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright (c) 2019, 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.
-
-// VMOptions=--serialize_flow_graphs_to=il_tmp.txt
-// VMOptions=--serialize_flow_graphs_to=il_tmp.txt --populate_llvm_constant_pool
-// VMOptions=--serialize_flow_graphs_to=il_tmp.txt --no_serialize_flow_graph_types
-// VMOptions=--serialize_flow_graphs_to=il_tmp.txt --verbose_flow_graph_serialization
-// VMOptions=--serialize_flow_graphs_to=il_tmp.txt --no_serialize_flow_graph_types --verbose_flow_graph_serialization
-
-// Just use the existing hello world test.
-import 'hello_world_test.dart' as test;
-
-main(args) {
-  test.main();
-}
diff --git a/runtime/tests/vm/dart/regress_38661_test.dart b/runtime/tests/vm/dart/regress_38661_test.dart
deleted file mode 100644
index 2e1ba13..0000000
--- a/runtime/tests/vm/dart/regress_38661_test.dart
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright (c) 2019, 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.
-
-// VMOptions=--serialize_flow_graphs_to=il_tmp.txt
-// VMOptions=--serialize_flow_graphs_to=il_tmp.txt --populate_llvm_constant_pool
-// VMOptions=--serialize_flow_graphs_to=il_tmp.txt --no_serialize_flow_graph_types
-// VMOptions=--serialize_flow_graphs_to=il_tmp.txt --verbose_flow_graph_serialization
-// VMOptions=--serialize_flow_graphs_to=il_tmp.txt --no_serialize_flow_graph_types --verbose_flow_graph_serialization
-
-class A {
-  const A();
-}
-
-class B {
-  Object a = const A();
-}
-
-foo(int i) {
-  if (i == 3) {
-    new B();
-  }
-}
-
-main(args) {
-  foo(4);
-}
diff --git a/runtime/tests/vm/dart_2/base_il_serialization_test.dart b/runtime/tests/vm/dart_2/base_il_serialization_test.dart
deleted file mode 100644
index 569b661..0000000
--- a/runtime/tests/vm/dart_2/base_il_serialization_test.dart
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright (c) 2019, 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.
-
-// VMOptions=--serialize_flow_graphs_to=il_tmp.txt
-// VMOptions=--serialize_flow_graphs_to=il_tmp.txt --populate_llvm_constant_pool
-// VMOptions=--serialize_flow_graphs_to=il_tmp.txt --no_serialize_flow_graph_types
-// VMOptions=--serialize_flow_graphs_to=il_tmp.txt --verbose_flow_graph_serialization
-// VMOptions=--serialize_flow_graphs_to=il_tmp.txt --no_serialize_flow_graph_types --verbose_flow_graph_serialization
-
-// Just use the existing hello world test.
-import 'hello_world_test.dart' as test;
-
-main(args) {
-  test.main();
-}
diff --git a/runtime/tests/vm/dart_2/regress_38661_test.dart b/runtime/tests/vm/dart_2/regress_38661_test.dart
deleted file mode 100644
index 2e1ba13..0000000
--- a/runtime/tests/vm/dart_2/regress_38661_test.dart
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright (c) 2019, 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.
-
-// VMOptions=--serialize_flow_graphs_to=il_tmp.txt
-// VMOptions=--serialize_flow_graphs_to=il_tmp.txt --populate_llvm_constant_pool
-// VMOptions=--serialize_flow_graphs_to=il_tmp.txt --no_serialize_flow_graph_types
-// VMOptions=--serialize_flow_graphs_to=il_tmp.txt --verbose_flow_graph_serialization
-// VMOptions=--serialize_flow_graphs_to=il_tmp.txt --no_serialize_flow_graph_types --verbose_flow_graph_serialization
-
-class A {
-  const A();
-}
-
-class B {
-  Object a = const A();
-}
-
-foo(int i) {
-  if (i == 3) {
-    new B();
-  }
-}
-
-main(args) {
-  foo(4);
-}
diff --git a/runtime/vm/compiler/aot/precompiler.cc b/runtime/vm/compiler/aot/precompiler.cc
index 460c9e0..abb8ad0 100644
--- a/runtime/vm/compiler/aot/precompiler.cc
+++ b/runtime/vm/compiler/aot/precompiler.cc
@@ -18,7 +18,6 @@
 #include "vm/compiler/backend/flow_graph.h"
 #include "vm/compiler/backend/flow_graph_compiler.h"
 #include "vm/compiler/backend/il_printer.h"
-#include "vm/compiler/backend/il_serializer.h"
 #include "vm/compiler/backend/inliner.h"
 #include "vm/compiler/backend/linearscan.h"
 #include "vm/compiler/backend/range_analysis.h"
@@ -87,17 +86,6 @@
 DECLARE_FLAG(int, inlining_constant_arguments_min_size_threshold);
 DECLARE_FLAG(bool, print_instruction_stats);
 
-DEFINE_FLAG(charp,
-            serialize_flow_graphs_to,
-            nullptr,
-            "Serialize flow graphs to the given file");
-
-DEFINE_FLAG(bool,
-            populate_llvm_constant_pool,
-            false,
-            "Add constant pool entries from flow graphs to a special pool "
-            "serialized in AOT snapshots (with --serialize_flow_graphs_to)");
-
 Precompiler* Precompiler::singleton_ = nullptr;
 
 #if defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_IA32)
@@ -234,8 +222,7 @@
       consts_to_retain_(),
       seen_table_selectors_(),
       error_(Error::Handle()),
-      get_runtime_type_is_unique_(false),
-      il_serialization_stream_(nullptr) {
+      get_runtime_type_is_unique_(false) {
   ASSERT(Precompiler::singleton_ == NULL);
   Precompiler::singleton_ = this;
 }
@@ -307,32 +294,6 @@
       ClassFinalizer::ClearAllCode(
           /*including_nonchanging_cids=*/FLAG_use_bare_instructions);
 
-      // After this point, it should be safe to serialize flow graphs produced
-      // during compilation and add constants to the LLVM constant pool.
-      //
-      // Check that both the file open and write callbacks are available, though
-      // we only use the latter during IL processing.
-      if (FLAG_serialize_flow_graphs_to != nullptr &&
-          Dart::file_write_callback() != nullptr) {
-        if (auto file_open = Dart::file_open_callback()) {
-          auto file = file_open(FLAG_serialize_flow_graphs_to, /*write=*/true);
-          set_il_serialization_stream(file);
-        }
-        if (FLAG_populate_llvm_constant_pool) {
-          auto const object_store = IG->object_store();
-          auto& llvm_constants = GrowableObjectArray::Handle(
-              Z, GrowableObjectArray::New(16, Heap::kOld));
-          auto& llvm_functions = GrowableObjectArray::Handle(
-              Z, GrowableObjectArray::New(16, Heap::kOld));
-          auto& llvm_constant_hash_table = Array::Handle(
-              Z, HashTables::New<FlowGraphSerializer::LLVMPoolMap>(16,
-                                                                   Heap::kOld));
-          object_store->set_llvm_constant_pool(llvm_constants);
-          object_store->set_llvm_function_pool(llvm_functions);
-          object_store->set_llvm_constant_hash_table(llvm_constant_hash_table);
-        }
-      }
-
       tracer_ = PrecompilerTracer::StartTracingIfRequested(this);
 
       // All stubs have already been generated, all of them share the same pool.
@@ -412,45 +373,6 @@
         }
       }
 
-      if (FLAG_serialize_flow_graphs_to != nullptr &&
-          Dart::file_write_callback() != nullptr) {
-        if (auto file_close = Dart::file_close_callback()) {
-          file_close(il_serialization_stream());
-        }
-        set_il_serialization_stream(nullptr);
-        if (FLAG_populate_llvm_constant_pool) {
-          // We don't want the Array backing for any mappings in the snapshot,
-          // only the pools themselves.
-          IG->object_store()->set_llvm_constant_hash_table(Array::null_array());
-
-          // Keep any functions, classes, etc. referenced from the LLVM pools,
-          // even if they could have been dropped due to not being otherwise
-          // needed at runtime.
-          const auto& constant_pool = GrowableObjectArray::Handle(
-              Z, IG->object_store()->llvm_constant_pool());
-          auto& object = Object::Handle(Z);
-          for (intptr_t i = 0; i < constant_pool.Length(); i++) {
-            object = constant_pool.At(i);
-            if (object.IsNull()) continue;
-            if (object.IsInstance()) {
-              AddConstObject(Instance::Cast(object));
-            } else if (object.IsField()) {
-              AddField(Field::Cast(object));
-            } else if (object.IsFunction()) {
-              AddFunction(Function::Cast(object), RetainReasons::kLLVMPool);
-            }
-          }
-
-          const auto& function_pool = GrowableObjectArray::Handle(
-              Z, IG->object_store()->llvm_function_pool());
-          auto& function = Function::Handle(Z);
-          for (intptr_t i = 0; i < function_pool.Length(); i++) {
-            function ^= function_pool.At(i);
-            AddFunction(function, RetainReasons::kLLVMPool);
-          }
-        }
-      }
-
       if (tracer_ != nullptr) {
         tracer_->Finalize();
         tracer_ = nullptr;
diff --git a/runtime/vm/compiler/aot/precompiler.h b/runtime/vm/compiler/aot/precompiler.h
index 01e2892..48613ee 100644
--- a/runtime/vm/compiler/aot/precompiler.h
+++ b/runtime/vm/compiler/aot/precompiler.h
@@ -250,8 +250,6 @@
     return dispatch_table_generator_->selector_map();
   }
 
-  void* il_serialization_stream() const { return il_serialization_stream_; }
-
   static Precompiler* Instance() { return singleton_; }
 
   void AddField(const Field& field);
@@ -348,10 +346,6 @@
 
   void FinalizeAllClasses();
 
-  void set_il_serialization_stream(void* file) {
-    il_serialization_stream_ = file;
-  }
-
   Thread* thread() const { return thread_; }
   Zone* zone() const { return zone_; }
   Isolate* isolate() const { return isolate_; }
@@ -431,7 +425,6 @@
   compiler::DispatchTableGenerator* dispatch_table_generator_;
 
   bool get_runtime_type_is_unique_;
-  void* il_serialization_stream_;
 
   Phase phase_ = Phase::kPreparation;
   PrecompilerTracer* tracer_ = nullptr;
diff --git a/runtime/vm/compiler/backend/compile_type.h b/runtime/vm/compiler/backend/compile_type.h
index 3a7d6aa..192d541 100644
--- a/runtime/vm/compiler/backend/compile_type.h
+++ b/runtime/vm/compiler/backend/compile_type.h
@@ -18,9 +18,6 @@
 class AbstractType;
 class BaseTextBuffer;
 class Definition;
-class FlowGraphSerializer;
-class SExpression;
-class SExpList;
 
 template <typename T>
 class GrowableArray;
@@ -248,8 +245,6 @@
   bool Specialize(GrowableArray<intptr_t>* class_ids);
 
   void PrintTo(BaseTextBuffer* f) const;
-  SExpression* ToSExpression(FlowGraphSerializer* s) const;
-  void AddExtraInfoToSExpression(SExpList* sexp, FlowGraphSerializer* s) const;
 
   const char* ToCString() const;
 
diff --git a/runtime/vm/compiler/backend/il.h b/runtime/vm/compiler/backend/il.h
index 38006b2..3cf8ffc 100644
--- a/runtime/vm/compiler/backend/il.h
+++ b/runtime/vm/compiler/backend/il.h
@@ -49,7 +49,6 @@
 class Environment;
 class FlowGraph;
 class FlowGraphCompiler;
-class FlowGraphSerializer;
 class FlowGraphVisitor;
 class ForwardInstructionIterator;
 class Instruction;
@@ -59,8 +58,6 @@
 class Range;
 class RangeAnalysis;
 class RangeBoundary;
-class SExpList;
-class SExpression;
 class SuccessorsIterable;
 class TypeUsageInfo;
 class UnboxIntegerInstr;
@@ -150,8 +147,6 @@
   void PrintTo(BaseTextBuffer* f) const;
 #endif  // defined(INCLUDE_IL_PRINTER)
 
-  SExpression* ToSExpression(FlowGraphSerializer* s) const;
-
   const char* ToCString() const;
 
   bool IsSmiValue() { return Type()->ToCid() == kSmiCid; }
@@ -569,17 +564,6 @@
 #define PRINT_OPERANDS_TO_SUPPORT
 #endif  // defined(INCLUDE_IL_PRINTER)
 
-#define TO_S_EXPRESSION_SUPPORT                                                \
-  virtual SExpression* ToSExpression(FlowGraphSerializer* s) const;
-
-#define ADD_OPERANDS_TO_S_EXPRESSION_SUPPORT                                   \
-  virtual void AddOperandsToSExpression(SExpList* sexp,                        \
-                                        FlowGraphSerializer* s) const;
-
-#define ADD_EXTRA_INFO_TO_S_EXPRESSION_SUPPORT                                 \
-  virtual void AddExtraInfoToSExpression(SExpList* sexp,                       \
-                                         FlowGraphSerializer* s) const;
-
 // Together with CidRange, this represents a mapping from a range of class-ids
 // to a method for a given selector (method name).  Also can contain an
 // indication of how frequently a given method has been called at a call site.
@@ -932,11 +916,6 @@
   const char* ToCString() const;
   PRINT_TO_SUPPORT
   PRINT_OPERANDS_TO_SUPPORT
-  virtual SExpression* ToSExpression(FlowGraphSerializer* s) const;
-  virtual void AddOperandsToSExpression(SExpList* sexp,
-                                        FlowGraphSerializer* s) const;
-  virtual void AddExtraInfoToSExpression(SExpList* sexp,
-                                         FlowGraphSerializer* s) const;
 
 #define DECLARE_INSTRUCTION_TYPE_CHECK(Name, Type)                             \
   bool Is##Name() const { return (As##Name() != nullptr); }                    \
@@ -1519,9 +1498,6 @@
 
   DEFINE_INSTRUCTION_TYPE_CHECK(BlockEntry)
 
-  TO_S_EXPRESSION_SUPPORT
-  ADD_OPERANDS_TO_S_EXPRESSION_SUPPORT
-  ADD_EXTRA_INFO_TO_S_EXPRESSION_SUPPORT
 
  protected:
   BlockEntryInstr(intptr_t block_id,
@@ -1822,7 +1798,6 @@
   virtual bool HasUnknownSideEffects() const { return false; }
 
   PRINT_TO_SUPPORT
-  ADD_OPERANDS_TO_S_EXPRESSION_SUPPORT
 
  private:
   // Classes that have access to predecessors_ when inlining.
@@ -2269,7 +2244,6 @@
 
   PRINT_OPERANDS_TO_SUPPORT
   PRINT_TO_SUPPORT
-  TO_S_EXPRESSION_SUPPORT
 
   bool UpdateType(CompileType new_type) {
     if (type_ == nullptr) {
@@ -2382,7 +2356,6 @@
  protected:
   friend class RangeAnalysis;
   friend class Value;
-  friend class FlowGraphSerializer;  // To access type_ directly.
 
   Range* range_ = nullptr;
 
@@ -2617,7 +2590,6 @@
   virtual bool MayThrow() const { return false; }
 
   PRINT_OPERANDS_TO_SUPPORT
-  ADD_OPERANDS_TO_S_EXPRESSION_SUPPORT
 
  private:
   virtual void RawSetInputAt(intptr_t i, Value* value) { UNREACHABLE(); }
@@ -2723,7 +2695,6 @@
   intptr_t offset() const { return offset_; }
 
   PRINT_OPERANDS_TO_SUPPORT
-  ADD_EXTRA_INFO_TO_S_EXPRESSION_SUPPORT
 
  private:
   const intptr_t offset_;
@@ -2774,7 +2745,6 @@
   intptr_t offset() const { return offset_; }
 
   PRINT_OPERANDS_TO_SUPPORT
-  ADD_EXTRA_INFO_TO_S_EXPRESSION_SUPPORT
 
  private:
   const intptr_t offset_;
@@ -2906,7 +2876,6 @@
   virtual bool ComputeCanDeoptimize() const { return false; }
 
   PRINT_OPERANDS_TO_SUPPORT
-  ADD_OPERANDS_TO_S_EXPRESSION_SUPPORT
 
  private:
   const Code& code_;
@@ -3188,7 +3157,6 @@
   }
 
   PRINT_TO_SUPPORT
-  ADD_OPERANDS_TO_S_EXPRESSION_SUPPORT
 
  private:
   BlockEntryInstr* block_;
@@ -3299,7 +3267,6 @@
            (operation_cid() == other_comparison->operation_cid());
   }
 
-  ADD_OPERANDS_TO_S_EXPRESSION_SUPPORT
 
   DEFINE_INSTRUCTION_TYPE_CHECK(Comparison)
 
@@ -3438,7 +3405,6 @@
   virtual BlockEntryInstr* SuccessorAt(intptr_t index) const;
 
   PRINT_TO_SUPPORT
-  ADD_OPERANDS_TO_S_EXPRESSION_SUPPORT
 
  private:
   virtual void RawSetInputAt(intptr_t i, Value* value) {
@@ -3592,7 +3558,6 @@
                           Register tmp = kNoRegister);
 
   PRINT_OPERANDS_TO_SUPPORT
-  ADD_OPERANDS_TO_S_EXPRESSION_SUPPORT
 
  private:
   const Object& value_;
@@ -3759,7 +3724,6 @@
   virtual Value* RedefinedValue() const;
 
   PRINT_OPERANDS_TO_SUPPORT
-  ADD_EXTRA_INFO_TO_S_EXPRESSION_SUPPORT
 
  private:
   const TokenPosition token_pos_;
@@ -3850,7 +3814,6 @@
   const char* ToCString() const;
 
   PRINT_OPERANDS_TO_SUPPORT
-  ADD_OPERANDS_TO_S_EXPRESSION_SUPPORT
 
  private:
   const SpecialParameterKind kind_;
@@ -3960,7 +3923,6 @@
         ArgumentsSizeWithoutTypeArgs(), argument_names());
   }
 
-  ADD_EXTRA_INFO_TO_S_EXPRESSION_SUPPORT
 
  private:
   virtual void RawSetInputAt(intptr_t i, Value* value) {
@@ -4005,7 +3967,6 @@
   Code::EntryKind entry_kind() const { return entry_kind_; }
 
   PRINT_OPERANDS_TO_SUPPORT
-  ADD_EXTRA_INFO_TO_S_EXPRESSION_SUPPORT
 
  private:
   const Code::EntryKind entry_kind_;
@@ -4103,8 +4064,6 @@
   Code::EntryKind entry_kind() const { return entry_kind_; }
   void set_entry_kind(Code::EntryKind value) { entry_kind_ = value; }
 
-  ADD_OPERANDS_TO_S_EXPRESSION_SUPPORT
-  ADD_EXTRA_INFO_TO_S_EXPRESSION_SUPPORT
   DEFINE_INSTRUCTION_TYPE_CHECK(InstanceCallBase);
 
   bool receiver_is_not_smi() const { return receiver_is_not_smi_; }
@@ -4220,7 +4179,6 @@
   virtual Definition* Canonicalize(FlowGraph* flow_graph);
 
   PRINT_OPERANDS_TO_SUPPORT
-  ADD_EXTRA_INFO_TO_S_EXPRESSION_SUPPORT
 
   bool MatchesCoreName(const String& name);
 
@@ -4295,7 +4253,6 @@
   static TypePtr ComputeRuntimeType(const CallTargets& targets);
 
   PRINT_OPERANDS_TO_SUPPORT
-  ADD_EXTRA_INFO_TO_S_EXPRESSION_SUPPORT
 
  private:
   PolymorphicInstanceCallInstr(const InstructionSource& source,
@@ -4434,8 +4391,7 @@
 
   bool AttributesEqual(Instruction* other) const;
 
-  PRINT_OPERANDS_TO_SUPPORT
-  ADD_EXTRA_INFO_TO_S_EXPRESSION_SUPPORT;
+  PRINT_OPERANDS_TO_SUPPORT;
 
  private:
   Condition EmitComparisonCodeRegConstant(FlowGraphCompiler* compiler,
@@ -4868,8 +4824,6 @@
   const class BinaryFeedback& BinaryFeedback();
 
   PRINT_OPERANDS_TO_SUPPORT
-  ADD_OPERANDS_TO_S_EXPRESSION_SUPPORT
-  ADD_EXTRA_INFO_TO_S_EXPRESSION_SUPPORT
 
  private:
   const ICData* ic_data_;
@@ -4916,7 +4870,6 @@
   virtual TokenPosition token_pos() const { return token_pos_; }
 
   PRINT_OPERANDS_TO_SUPPORT
-  ADD_OPERANDS_TO_S_EXPRESSION_SUPPORT
 
  private:
   const LocalVariable& local_;
@@ -5048,7 +5001,6 @@
   virtual TokenPosition token_pos() const { return token_pos_; }
 
   PRINT_OPERANDS_TO_SUPPORT
-  ADD_OPERANDS_TO_S_EXPRESSION_SUPPORT
 
  private:
   const LocalVariable& local_;
@@ -5098,8 +5050,6 @@
   void SetupNative();
 
   PRINT_OPERANDS_TO_SUPPORT
-  ADD_OPERANDS_TO_S_EXPRESSION_SUPPORT
-  ADD_EXTRA_INFO_TO_S_EXPRESSION_SUPPORT
 
  private:
   void set_native_c_function(NativeFunction value) {
@@ -5292,7 +5242,6 @@
   virtual bool HasUnknownSideEffects() const { return true; }
   virtual Instruction* Canonicalize(FlowGraph* flow_graph);
 
-  ADD_EXTRA_INFO_TO_S_EXPRESSION_SUPPORT
 
  private:
   const TokenPosition token_pos_;
@@ -5423,8 +5372,6 @@
   virtual Instruction* Canonicalize(FlowGraph* flow_graph);
 
   PRINT_OPERANDS_TO_SUPPORT
-  ADD_OPERANDS_TO_S_EXPRESSION_SUPPORT
-  ADD_EXTRA_INFO_TO_S_EXPRESSION_SUPPORT
 
  private:
   friend class JitCallSpecializer;  // For ASSERT(initialization_).
@@ -5684,7 +5631,6 @@
 
   virtual Definition* Canonicalize(FlowGraph* flow_graph);
 
-  ADD_EXTRA_INFO_TO_S_EXPRESSION_SUPPORT
 
  private:
   const bool index_unboxed_;
@@ -5988,7 +5934,6 @@
 
   virtual Instruction* Canonicalize(FlowGraph* flow_graph);
 
-  ADD_EXTRA_INFO_TO_S_EXPRESSION_SUPPORT
 
  private:
   compiler::Assembler::CanBeSmi CanValueBeSmi() const {
@@ -6170,8 +6115,6 @@
   }
 
   PRINT_OPERANDS_TO_SUPPORT
-  ADD_OPERANDS_TO_S_EXPRESSION_SUPPORT
-  ADD_EXTRA_INFO_TO_S_EXPRESSION_SUPPORT
 
  private:
   virtual void RawSetInputAt(intptr_t i, Value* value) {
@@ -6639,8 +6582,6 @@
   virtual bool AttributesEqual(Instruction* other) const;
 
   PRINT_OPERANDS_TO_SUPPORT
-  ADD_OPERANDS_TO_S_EXPRESSION_SUPPORT
-  ADD_EXTRA_INFO_TO_S_EXPRESSION_SUPPORT
 
  private:
   intptr_t OffsetInBytes() const { return slot().offset_in_bytes(); }
@@ -7469,7 +7410,6 @@
   }
 
   PRINT_OPERANDS_TO_SUPPORT
-  ADD_OPERANDS_TO_S_EXPRESSION_SUPPORT
 
   DECLARE_COMPARISON_INSTRUCTION(DoubleTestOp)
 
@@ -7642,7 +7582,6 @@
   virtual Definition* Canonicalize(FlowGraph* flow_graph);
 
   PRINT_OPERANDS_TO_SUPPORT
-  ADD_OPERANDS_TO_S_EXPRESSION_SUPPORT
 
   DECLARE_INSTRUCTION(CheckedSmiOp)
 
@@ -7767,7 +7706,6 @@
   virtual void InferRange(RangeAnalysis* analysis, Range* range);
 
   PRINT_OPERANDS_TO_SUPPORT
-  ADD_OPERANDS_TO_S_EXPRESSION_SUPPORT
 
   DEFINE_INSTRUCTION_TYPE_CHECK(BinaryIntegerOp)
 
@@ -8220,7 +8158,6 @@
   }
 
   PRINT_OPERANDS_TO_SUPPORT
-  ADD_EXTRA_INFO_TO_S_EXPRESSION_SUPPORT
 
  private:
   const TokenPosition token_pos_;
@@ -8792,7 +8729,6 @@
 
   virtual Value* RedefinedValue() const;
 
-  ADD_EXTRA_INFO_TO_S_EXPRESSION_SUPPORT
 
   PRINT_OPERANDS_TO_SUPPORT
 
@@ -9323,8 +9259,6 @@
 
   DECLARE_INSTRUCTION(SimdOp)
   PRINT_OPERANDS_TO_SUPPORT
-  ADD_OPERANDS_TO_S_EXPRESSION_SUPPORT
-  ADD_EXTRA_INFO_TO_S_EXPRESSION_SUPPORT
 
  private:
   SimdOpInstr(Kind kind, intptr_t deopt_id)
@@ -9539,7 +9473,6 @@
                        Definition* result) const;
 
   void PrintTo(BaseTextBuffer* f) const;
-  SExpression* ToSExpression(FlowGraphSerializer* s) const;
   const char* ToCString() const;
 
   // Deep copy an environment.  The 'length' parameter may be less than the
diff --git a/runtime/vm/compiler/backend/il_deserializer.cc b/runtime/vm/compiler/backend/il_deserializer.cc
deleted file mode 100644
index eb7f1fa..0000000
--- a/runtime/vm/compiler/backend/il_deserializer.cc
+++ /dev/null
@@ -1,2520 +0,0 @@
-// Copyright (c) 2019, 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_deserializer.h"
-
-#include "vm/compiler/backend/il_serializer.h"
-#include "vm/compiler/backend/range_analysis.h"
-#include "vm/compiler/call_specializer.h"
-#include "vm/compiler/frontend/base_flow_graph_builder.h"
-#include "vm/compiler/jit/compiler.h"
-#include "vm/flags.h"
-#include "vm/json_writer.h"
-#include "vm/os.h"
-
-namespace dart {
-
-DEFINE_FLAG(bool,
-            trace_round_trip_serialization,
-            false,
-            "Print out tracing information during round trip serialization.");
-DEFINE_FLAG(bool,
-            print_json_round_trip_results,
-            false,
-            "Print out results of each round trip serialization in JSON form.");
-
-// Contains the contents of a single round-trip result.
-struct RoundTripResults : public ValueObject {
-  explicit RoundTripResults(Zone* zone, const Function& func)
-      : function(func), unhandled(zone, 2) {}
-
-  // The function for which a flow graph was being parsed.
-  const Function& function;
-  // Whether the round trip succeeded.
-  bool success = false;
-  // An array of unhandled instructions found in the flow graph.
-  GrowableArray<Instruction*> unhandled;
-  // The serialized form of the flow graph, if computed.
-  SExpression* serialized = nullptr;
-  // The error information from the deserializer, if an error occurred.
-  const char* error_message = nullptr;
-  SExpression* error_sexp = nullptr;
-};
-
-// Return a textual description of how to find the sub-expression [to_find]
-// inside a [root] S-Expression.
-static const char* GetSExpressionPosition(Zone* zone,
-                                          SExpression* root,
-                                          SExpression* to_find) {
-  // The S-expression to find _is_ the root, so no description is needed.
-  if (root == to_find) return "";
-  // The S-expression to find cannot be a sub-expression of the given root,
-  // so return nullptr to signal this.
-  if (!root->IsList()) return nullptr;
-  auto const list = root->AsList();
-  for (intptr_t i = 0, n = list->Length(); i < n; i++) {
-    if (auto const str = GetSExpressionPosition(zone, list->At(i), to_find)) {
-      return OS::SCreate(zone, "element %" Pd "%s%s", i,
-                         *str == '\0' ? "" : " -> ", str);
-    }
-  }
-  auto it = list->ExtraIterator();
-  while (auto kv = it.Next()) {
-    if (auto const str = GetSExpressionPosition(zone, kv->value, to_find)) {
-      return OS::SCreate(zone, "label %s%s%s", kv->key,
-                         *str == '\0' ? "" : " -> ", str);
-    }
-  }
-  return nullptr;
-}
-
-static void PrintRoundTripResults(Zone* zone, const RoundTripResults& results) {
-  // A few checks to make sure we'll print out enough info. First, if there are
-  // no unhandled instructions, then we should have serialized the flow graph.
-  ASSERT(!results.unhandled.is_empty() || results.serialized != nullptr);
-  // If we failed, then either there are unhandled instructions or we have
-  // an appropriate error message and sexp from the FlowGraphDeserializer.
-  ASSERT(results.success || !results.unhandled.is_empty() ||
-         (results.error_message != nullptr && results.error_sexp != nullptr));
-
-  JSONWriter js;
-
-  js.OpenObject();
-  js.PrintProperty("function", results.function.ToFullyQualifiedCString());
-  js.PrintPropertyBool("success", results.success);
-
-  if (!results.unhandled.is_empty()) {
-    CStringMap<intptr_t> count_map(zone);
-    for (auto inst : results.unhandled) {
-      auto const name = inst->DebugName();
-      auto const old_count = count_map.LookupValue(name);
-      count_map.Update({name, old_count + 1});
-    }
-
-    auto count_it = count_map.GetIterator();
-    js.OpenObject("unhandled");
-    while (auto kv = count_it.Next()) {
-      js.PrintProperty64(kv->key, kv->value);
-    }
-    js.CloseObject();
-  }
-
-  if (results.serialized != nullptr) {
-    TextBuffer buf(1000);
-    results.serialized->SerializeTo(zone, &buf, "");
-    js.PrintProperty("serialized", buf.buffer());
-  }
-
-  if (results.error_message != nullptr) {
-    js.OpenObject("error");
-    js.PrintProperty("message", results.error_message);
-
-    ASSERT(results.error_sexp != nullptr);
-    TextBuffer buf(1000);
-    results.error_sexp->SerializeTo(zone, &buf, "");
-    js.PrintProperty("expression", buf.buffer());
-
-    auto const sexp_position =
-        GetSExpressionPosition(zone, results.serialized, results.error_sexp);
-    js.PrintProperty("path", sexp_position);
-    js.CloseObject();
-  }
-
-  js.CloseObject();
-  THR_Print("Results of round trip serialization: %s\n", js.buffer()->buffer());
-}
-
-void FlowGraphDeserializer::RoundTripSerialization(CompilerPassState* state) {
-  auto const flow_graph = state->flow_graph();
-
-  // The deserialized flow graph must be in the same zone as the original flow
-  // graph, to ensure it has the right lifetime. Thus, we leave an explicit
-  // use of [flow_graph->zone()] in the deserializer construction.
-  //
-  // Otherwise, it would be nice to use a StackZone to limit the lifetime of the
-  // serialized form (and other values created with this [zone] variable), since
-  // it only needs to live for the dynamic extent of this method.
-  //
-  // However, creating a StackZone for it also changes the zone associated with
-  // the thread. Also, some parts of the VM used in later updates to the
-  // deserializer implicitly pick up the zone to use either from a passed-in
-  // thread or the current thread instead of taking an explicit zone.
-  //
-  // For now, just serialize into the same zone as the original flow graph, and
-  // we can revisit this if this causes a performance issue or if we can ensure
-  // that those VM parts mentioned can be passed an explicit zone.
-  Zone* const zone = flow_graph->zone();
-
-  // Final flow graph, if we successfully serialize and deserialize.
-  FlowGraph* new_graph = nullptr;
-
-  // Stored information for printing results if requested.
-  RoundTripResults results(zone, flow_graph->function());
-
-  FlowGraphDeserializer::AllUnhandledInstructions(flow_graph,
-                                                  &results.unhandled);
-  if (results.unhandled.is_empty()) {
-    results.serialized = FlowGraphSerializer::SerializeToSExp(zone, flow_graph);
-
-    if (FLAG_trace_round_trip_serialization && results.serialized != nullptr) {
-      TextBuffer buf(1000);
-      results.serialized->SerializeTo(zone, &buf, "");
-      THR_Print("Serialized flow graph:\n%s\n", buf.buffer());
-    }
-
-    // For the deserializer, use the thread from the compiler pass and zone
-    // associated with the existing flow graph to make sure the new flow graph
-    // has the right lifetime.
-    FlowGraphDeserializer d(state->thread, flow_graph->zone(),
-                            results.serialized, &flow_graph->parsed_function());
-    new_graph = d.ParseFlowGraph();
-    if (new_graph == nullptr) {
-      ASSERT(d.error_message() != nullptr && d.error_sexp() != nullptr);
-      if (FLAG_trace_round_trip_serialization) {
-        THR_Print("Failure during deserialization: %s\n", d.error_message());
-        THR_Print("At S-expression %s\n", d.error_sexp()->ToCString(zone));
-        if (auto const pos = GetSExpressionPosition(zone, results.serialized,
-                                                    d.error_sexp())) {
-          THR_Print("Path from root: %s\n", pos);
-        }
-      }
-      results.error_message = d.error_message();
-      results.error_sexp = d.error_sexp();
-    } else {
-      if (FLAG_trace_round_trip_serialization) {
-        THR_Print("Successfully deserialized graph for %s\n",
-                  results.serialized->AsList()->At(1)->AsSymbol()->value());
-      }
-      results.success = true;
-    }
-  } else if (FLAG_trace_round_trip_serialization) {
-    THR_Print("Cannot serialize graph due to instruction: %s\n",
-              results.unhandled.At(0)->DebugName());
-  }
-
-  if (FLAG_print_json_round_trip_results) PrintRoundTripResults(zone, results);
-
-  if (new_graph != nullptr) {
-    state->set_flow_graph(new_graph);
-  }
-}
-
-#define HANDLED_CASE(name)                                                     \
-  if (inst->Is##name()) return true;
-bool FlowGraphDeserializer::IsHandledInstruction(Instruction* inst) {
-  if (auto const const_inst = inst->AsConstant()) {
-    return IsHandledConstant(const_inst->value());
-  }
-  FOR_EACH_HANDLED_BLOCK_TYPE_IN_DESERIALIZER(HANDLED_CASE)
-  FOR_EACH_HANDLED_INSTRUCTION_IN_DESERIALIZER(HANDLED_CASE)
-  return false;
-}
-#undef HANDLED_CASE
-
-void FlowGraphDeserializer::AllUnhandledInstructions(
-    const FlowGraph* graph,
-    GrowableArray<Instruction*>* unhandled) {
-  ASSERT(graph != nullptr);
-  ASSERT(unhandled != nullptr);
-  for (auto block_it = graph->reverse_postorder_iterator(); !block_it.Done();
-       block_it.Advance()) {
-    auto const entry = block_it.Current();
-    if (!IsHandledInstruction(entry)) unhandled->Add(entry);
-    // Check that the Phi instructions in JoinEntrys do not have pair
-    // representation.
-    if (auto const join_block = entry->AsJoinEntry()) {
-      auto const phis = join_block->phis();
-      auto const length = ((phis == nullptr) ? 0 : phis->length());
-      for (intptr_t i = 0; i < length; i++) {
-        auto const current = phis->At(i);
-        for (intptr_t j = 0; j < current->InputCount(); j++) {
-          if (current->InputAt(j)->definition()->HasPairRepresentation()) {
-            unhandled->Add(current);
-          }
-        }
-      }
-    }
-    if (auto const def_block = entry->AsBlockEntryWithInitialDefs()) {
-      auto const defs = def_block->initial_definitions();
-      for (intptr_t i = 0; i < defs->length(); i++) {
-        auto const current = defs->At(i);
-        if (!IsHandledInstruction(current)) unhandled->Add(current);
-      }
-    }
-    for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) {
-      auto current = it.Current();
-      // We handle branches, so we need to check the comparison instruction.
-      if (current->IsBranch()) current = current->AsBranch()->comparison();
-      if (!IsHandledInstruction(current)) unhandled->Add(current);
-    }
-  }
-}
-
-// Keep in sync with work in ParseDartValue. Right now, this is just a shallow
-// check, not a deep one.
-bool FlowGraphDeserializer::IsHandledConstant(const Object& obj) {
-  if (obj.IsArray()) return Array::Cast(obj).IsImmutable();
-  return obj.IsNull() || obj.IsClass() || obj.IsFunction() || obj.IsField() ||
-         obj.IsInstance();
-}
-
-SExpression* FlowGraphDeserializer::Retrieve(SExpList* list, intptr_t index) {
-  if (list == nullptr) return nullptr;
-  if (list->Length() <= index) {
-    StoreError(list, "expected at least %" Pd " element(s) in list", index + 1);
-    return nullptr;
-  }
-  auto const elem = list->At(index);
-  if (elem == nullptr) {
-    StoreError(list, "null value at index %" Pd "", index);
-  }
-  return elem;
-}
-
-SExpression* FlowGraphDeserializer::Retrieve(SExpList* list, const char* key) {
-  if (list == nullptr) return nullptr;
-  if (!list->ExtraHasKey(key)) {
-    StoreError(list, "expected an extra info entry for key %s", key);
-    return nullptr;
-  }
-  auto const elem = list->ExtraLookupValue(key);
-  if (elem == nullptr) {
-    StoreError(list, "null value for key %s", key);
-  }
-  return elem;
-}
-
-FlowGraph* FlowGraphDeserializer::ParseFlowGraph() {
-  auto const root = CheckTaggedList(root_sexp_, "FlowGraph");
-  if (root == nullptr) return nullptr;
-
-  intptr_t deopt_id = DeoptId::kNone;
-  if (auto const deopt_id_sexp =
-          CheckInteger(root->ExtraLookupValue("deopt_id"))) {
-    deopt_id = deopt_id_sexp->value();
-  }
-  EntryInfo common_info = {0, kInvalidTryIndex, deopt_id};
-
-  auto const graph = DeserializeGraphEntry(root, common_info);
-
-  PrologueInfo pi(-1, -1);
-  flow_graph_ = new (zone()) FlowGraph(*parsed_function_, graph, 0, pi);
-  flow_graph_->CreateCommonConstants();
-
-  intptr_t pos = 2;
-  if (auto const pool = CheckTaggedList(Retrieve(root, pos), "Constants")) {
-    if (!ParseConstantPool(pool)) return nullptr;
-    pos++;
-  }
-
-  // The deopt environment for the graph entry may use entries from the
-  // constant pool, so that must be parsed first.
-  if (auto const env_sexp = CheckList(root->ExtraLookupValue("env"))) {
-    current_block_ = graph;
-    auto const env = ParseEnvironment(env_sexp);
-    if (env == nullptr) return nullptr;
-    env->DeepCopyTo(zone(), graph);
-  }
-
-  auto const entries_sexp = CheckTaggedList(Retrieve(root, pos), "Entries");
-  if (!ParseEntries(entries_sexp)) return nullptr;
-  pos++;
-
-  // Now prime the block worklist with entries. We keep the block worklist
-  // in reverse order so that we can just pop the next block for content
-  // parsing off the end.
-  BlockWorklist block_worklist(zone(), entries_sexp->Length() - 1);
-
-  const auto& indirect_entries = graph->indirect_entries();
-  for (auto indirect_entry : indirect_entries) {
-    block_worklist.Add(indirect_entry->block_id());
-  }
-
-  const auto& catch_entries = graph->catch_entries();
-  for (auto catch_entry : catch_entries) {
-    block_worklist.Add(catch_entry->block_id());
-  }
-
-  if (auto const osr_entry = graph->osr_entry()) {
-    block_worklist.Add(osr_entry->block_id());
-  }
-  if (auto const unchecked_entry = graph->unchecked_entry()) {
-    block_worklist.Add(unchecked_entry->block_id());
-  }
-  if (auto const normal_entry = graph->normal_entry()) {
-    block_worklist.Add(normal_entry->block_id());
-  }
-
-  if (!ParseBlocks(root, pos, &block_worklist)) return nullptr;
-
-  // Before we return the new graph, make sure all definitions were found for
-  // all pending values.
-  if (values_map_.Length() > 0) {
-    auto it = values_map_.GetIterator();
-    auto const kv = it.Next();
-    ASSERT(kv->value->length() > 0);
-    const auto& value_info = kv->value->At(0);
-    StoreError(value_info.sexp, "no definition found for use in flow graph");
-    return nullptr;
-  }
-
-  flow_graph_->set_max_block_id(max_block_id_);
-  // The highest numbered SSA temp might need two slots (e.g. for unboxed
-  // integers on 32-bit platforms), so we add 2 to the highest seen SSA temp
-  // index to get to the new current SSA temp index. In cases where the highest
-  // numbered SSA temp originally had only one slot assigned, this can result
-  // in different SSA temp numbering in later passes between the original and
-  // deserialized graphs.
-  flow_graph_->set_current_ssa_temp_index(max_ssa_index_ + 2);
-  // Now that the deserializer has finished re-creating all the blocks in the
-  // flow graph, the blocks must be rediscovered. In addition, if ComputeSSA
-  // has already been run, dominators must be recomputed as well.
-  flow_graph_->DiscoverBlocks();
-  // Currently we only handle SSA graphs, so always do this.
-  GrowableArray<BitVector*> dominance_frontier;
-  flow_graph_->ComputeDominators(&dominance_frontier);
-
-  return flow_graph_;
-}
-
-bool FlowGraphDeserializer::ParseConstantPool(SExpList* pool) {
-  ASSERT(flow_graph_ != nullptr);
-  if (pool == nullptr) return false;
-  // Definitions in the constant pool may refer to later definitions. However,
-  // there should be no cycles possible between constant objects, so using a
-  // worklist algorithm we should always be able to make progress.
-  // Since we will not be adding new definitions, we make the initial size of
-  // the worklist the number of definitions in the constant pool.
-  GrowableArray<SExpList*> worklist(zone(), pool->Length() - 1);
-  // In order to ensure that the definition order is the same in the original
-  // flow graph, we can't just simply call GetConstant() whenever we
-  // successfully parse a constant. Instead, we'll create a stand-in
-  // ConstantInstr that we can temporarily stick in the definition_map_, and
-  // then once finished we'll go back through, add the constants via
-  // GetConstant() and parse any extra information.
-  DirectChainedHashMap<RawPointerKeyValueTrait<SExpList, ConstantInstr*>>
-      parsed_constants(zone());
-  // We keep old_worklist in reverse order so that we can just RemoveLast
-  // to get elements in their original order.
-  for (intptr_t i = pool->Length() - 1; i > 0; i--) {
-    const auto def_sexp = CheckTaggedList(pool->At(i), "def");
-    if (def_sexp == nullptr) return false;
-    worklist.Add(def_sexp);
-  }
-  while (true) {
-    const intptr_t worklist_len = worklist.length();
-    GrowableArray<SExpList*> parse_failures(zone(), worklist_len);
-    while (!worklist.is_empty()) {
-      const auto def_sexp = worklist.RemoveLast();
-      auto& obj = Object::ZoneHandle(zone());
-      if (!ParseDartValue(Retrieve(def_sexp, 2), &obj)) {
-        parse_failures.Add(def_sexp);
-        continue;
-      }
-      ConstantInstr* def = new (zone()) ConstantInstr(obj);
-      // Instead of parsing the whole definition, just get the SSA index so
-      // we can insert it into the definition_map_.
-      intptr_t index;
-      auto const name_sexp = CheckSymbol(Retrieve(def_sexp, 1));
-      if (!ParseSSATemp(name_sexp, &index)) return false;
-      def->set_ssa_temp_index(index);
-      ASSERT(!definition_map_.HasKey(index));
-      definition_map_.Insert(index, def);
-      parsed_constants.Insert({def_sexp, def});
-    }
-    if (parse_failures.is_empty()) break;
-    // We've gone through the whole worklist without success, so return
-    // the last error we encountered.
-    if (parse_failures.length() == worklist_len) return false;
-    // worklist was added to in order, so we need to reverse its contents
-    // when we add them to old_worklist.
-    while (!parse_failures.is_empty()) {
-      worklist.Add(parse_failures.RemoveLast());
-    }
-  }
-  // Now loop back through the constant pool definition S-expressions and
-  // get the real ConstantInstrs the flow graph will be using and finish
-  // parsing.
-  for (intptr_t i = 1; i < pool->Length(); i++) {
-    auto const def_sexp = CheckTaggedList(pool->At(i));
-    auto const temp_def = parsed_constants.LookupValue(def_sexp);
-    ASSERT(temp_def != nullptr);
-    // Remove the temporary definition from definition_map_ so this doesn't get
-    // flagged as a redefinition.
-    definition_map_.Remove(temp_def->ssa_temp_index());
-    ConstantInstr* real_def = flow_graph_->GetConstant(temp_def->value());
-    if (!ParseDefinitionWithParsedBody(def_sexp, real_def)) return false;
-    ASSERT(temp_def->ssa_temp_index() == real_def->ssa_temp_index());
-  }
-  return true;
-}
-
-bool FlowGraphDeserializer::ParseEntries(SExpList* list) {
-  ASSERT(flow_graph_ != nullptr);
-  if (list == nullptr) return false;
-  for (intptr_t i = 1; i < list->Length(); i++) {
-    const auto entry = CheckTaggedList(Retrieve(list, i));
-    if (entry == nullptr) return false;
-    intptr_t block_id;
-    if (!ParseBlockId(CheckSymbol(Retrieve(entry, 1)), &block_id)) {
-      return false;
-    }
-    if (block_map_.LookupValue(block_id) != nullptr) {
-      StoreError(entry->At(1), "multiple entries for block found");
-      return false;
-    }
-    const auto tag = entry->Tag();
-    if (ParseBlockHeader(entry, block_id, tag) == nullptr) return false;
-  }
-  return true;
-}
-
-bool FlowGraphDeserializer::ParseBlocks(SExpList* list,
-                                        intptr_t pos,
-                                        BlockWorklist* worklist) {
-  // First, ensure that all the block headers have been parsed. Set up a
-  // map from block IDs to S-expressions and the max_block_id while we're at it.
-  IntMap<SExpList*> block_sexp_map(zone());
-  for (intptr_t i = pos, n = list->Length(); i < n; i++) {
-    auto const block_sexp = CheckTaggedList(Retrieve(list, i), "Block");
-    intptr_t block_id;
-    if (!ParseBlockId(CheckSymbol(Retrieve(block_sexp, 1)), &block_id)) {
-      return false;
-    }
-    if (block_sexp_map.LookupValue(block_id) != nullptr) {
-      StoreError(block_sexp->At(1), "multiple definitions of block found");
-      return false;
-    }
-    block_sexp_map.Insert(block_id, block_sexp);
-    auto const type_tag =
-        CheckSymbol(block_sexp->ExtraLookupValue("block_type"));
-    // Entry block headers are already parsed, but others aren't.
-    if (block_map_.LookupValue(block_id) == nullptr) {
-      if (ParseBlockHeader(block_sexp, block_id, type_tag) == nullptr) {
-        return false;
-      }
-    }
-    if (max_block_id_ < block_id) max_block_id_ = block_id;
-  }
-
-  // Now start parsing the contents of blocks from the worklist. We use an
-  // IntMap to keep track of what blocks have already been fully parsed.
-  IntMap<bool> fully_parsed_block_map(zone());
-  while (!worklist->is_empty()) {
-    auto const block_id = worklist->RemoveLast();
-
-    // If we've already encountered this block, skip it.
-    if (fully_parsed_block_map.LookupValue(block_id)) continue;
-
-    auto const block_sexp = block_sexp_map.LookupValue(block_id);
-    ASSERT(block_sexp != nullptr);
-
-    current_block_ = block_map_.LookupValue(block_id);
-    ASSERT(current_block_ != nullptr);
-    ASSERT(current_block_->PredecessorCount() > 0);
-
-    if (!ParseBlockContents(block_sexp, worklist)) return false;
-
-    // Mark this block as done.
-    fully_parsed_block_map.Insert(block_id, true);
-  }
-
-  // Double-check that all blocks were reached by the worklist algorithm.
-  auto it = block_sexp_map.GetIterator();
-  while (auto kv = it.Next()) {
-    if (!fully_parsed_block_map.LookupValue(kv->key)) {
-      StoreError(kv->value, "block unreachable in flow graph");
-      return false;
-    }
-  }
-
-  return true;
-}
-
-bool FlowGraphDeserializer::ParseInitialDefinitions(SExpList* list) {
-  ASSERT(current_block_ != nullptr);
-  ASSERT(current_block_->IsBlockEntryWithInitialDefs());
-  auto const block = current_block_->AsBlockEntryWithInitialDefs();
-  if (list == nullptr) return false;
-  for (intptr_t i = 2; i < list->Length(); i++) {
-    const auto def_sexp = CheckTaggedList(Retrieve(list, i), "def");
-    const auto def = ParseDefinition(def_sexp);
-    if (def == nullptr) return false;
-    flow_graph_->AddToInitialDefinitions(block, def);
-  }
-  return true;
-}
-
-BlockEntryInstr* FlowGraphDeserializer::ParseBlockHeader(SExpList* list,
-                                                         intptr_t block_id,
-                                                         SExpSymbol* tag) {
-  ASSERT(flow_graph_ != nullptr);
-  // We should only parse block headers once.
-  ASSERT(block_map_.LookupValue(block_id) == nullptr);
-  if (list == nullptr) return nullptr;
-
-#if defined(DEBUG)
-  intptr_t parsed_block_id;
-  auto const id_sexp = CheckSymbol(Retrieve(list, 1));
-  if (!ParseBlockId(id_sexp, &parsed_block_id)) return nullptr;
-  ASSERT(block_id == parsed_block_id);
-#endif
-
-  auto const kind = FlowGraphSerializer::BlockEntryTagToKind(tag);
-
-  intptr_t deopt_id = DeoptId::kNone;
-  if (auto const deopt_int = CheckInteger(list->ExtraLookupValue("deopt_id"))) {
-    deopt_id = deopt_int->value();
-  }
-  intptr_t try_index = kInvalidTryIndex;
-  if (auto const try_int = CheckInteger(list->ExtraLookupValue("try_index"))) {
-    try_index = try_int->value();
-  }
-
-  BlockEntryInstr* block = nullptr;
-  EntryInfo common_info = {block_id, try_index, deopt_id};
-  switch (kind) {
-    case FlowGraphSerializer::kTarget:
-      block = DeserializeTargetEntry(list, common_info);
-      break;
-    case FlowGraphSerializer::kNormal:
-      block = DeserializeFunctionEntry(list, common_info);
-      if (block != nullptr) {
-        auto const graph = flow_graph_->graph_entry();
-        graph->set_normal_entry(block->AsFunctionEntry());
-      }
-      break;
-    case FlowGraphSerializer::kUnchecked: {
-      block = DeserializeFunctionEntry(list, common_info);
-      if (block != nullptr) {
-        auto const graph = flow_graph_->graph_entry();
-        graph->set_unchecked_entry(block->AsFunctionEntry());
-      }
-      break;
-    }
-    case FlowGraphSerializer::kJoin:
-      block = DeserializeJoinEntry(list, common_info);
-      break;
-    case FlowGraphSerializer::kInvalid:
-      StoreError(tag, "invalid block entry tag");
-      return nullptr;
-    default:
-      StoreError(tag, "unhandled block type");
-      return nullptr;
-  }
-  if (block == nullptr) return nullptr;
-
-  block_map_.Insert(block_id, block);
-  return block;
-}
-
-bool FlowGraphDeserializer::ParsePhis(SExpList* list) {
-  ASSERT(current_block_ != nullptr && current_block_->IsJoinEntry());
-  auto const join = current_block_->AsJoinEntry();
-  const intptr_t start_pos = 2;
-  auto const end_pos = SkipPhis(list);
-  if (end_pos < start_pos) return false;
-
-  for (intptr_t i = start_pos; i < end_pos; i++) {
-    auto const def_sexp = CheckTaggedList(Retrieve(list, i), "def");
-    auto const phi_sexp = CheckTaggedList(Retrieve(def_sexp, 2), "Phi");
-    // SkipPhis should already have checked which instructions, if any,
-    // are Phi definitions.
-    ASSERT(phi_sexp != nullptr);
-
-    // This is a generalization of FlowGraph::AddPhi where we let ParseValue
-    // create the values (as they may contain type information).
-    auto const phi = new (zone()) PhiInstr(join, phi_sexp->Length() - 1);
-    phi->mark_alive();
-    for (intptr_t i = 0, n = phi_sexp->Length() - 1; i < n; i++) {
-      auto const val = ParseValue(Retrieve(phi_sexp, i + 1));
-      if (val == nullptr) return false;
-      phi->SetInputAt(i, val);
-      val->definition()->AddInputUse(val);
-    }
-    join->InsertPhi(phi);
-
-    if (!ParseDefinitionWithParsedBody(def_sexp, phi)) return false;
-  }
-
-  return true;
-}
-
-intptr_t FlowGraphDeserializer::SkipPhis(SExpList* list) {
-  // All blocks are S-exps of the form (Block B# inst...), so skip the first
-  // two entries and then skip any Phi definitions.
-  for (intptr_t i = 2, n = list->Length(); i < n; i++) {
-    auto const def_sexp = CheckTaggedList(Retrieve(list, i), "def");
-    if (def_sexp == nullptr) return i;
-    auto const phi_sexp = CheckTaggedList(Retrieve(def_sexp, 2), "Phi");
-    if (phi_sexp == nullptr) return i;
-  }
-
-  StoreError(list, "block is empty or contains only Phi definitions");
-  return -1;
-}
-
-bool FlowGraphDeserializer::ParseBlockContents(SExpList* list,
-                                               BlockWorklist* worklist) {
-  ASSERT(current_block_ != nullptr);
-
-  // Parse any Phi definitions now before parsing the block environment.
-  if (current_block_->IsJoinEntry()) {
-    if (!ParsePhis(list)) return false;
-  }
-
-  // For blocks with initial definitions or phi definitions, this needs to be
-  // done after those are parsed. In addition, block environments can also use
-  // definitions from dominating blocks, so we need the contents of dominating
-  // blocks to first be parsed.
-  //
-  // However, we must parse the environment before parsing any instructions
-  // in the body of the block to ensure we don't mistakenly allow local
-  // definitions to appear in the environment.
-  if (auto const env_sexp = CheckList(list->ExtraLookupValue("env"))) {
-    auto const env = ParseEnvironment(env_sexp);
-    if (env == nullptr) return false;
-    env->DeepCopyTo(zone(), current_block_);
-  }
-
-  auto const pos = SkipPhis(list);
-  if (pos < 2) return false;
-  Instruction* last_inst = current_block_;
-  for (intptr_t i = pos, n = list->Length(); i < n; i++) {
-    auto const inst = ParseInstruction(CheckTaggedList(Retrieve(list, i)));
-    if (inst == nullptr) return false;
-    last_inst = last_inst->AppendInstruction(inst);
-  }
-
-  ASSERT(last_inst != nullptr && last_inst != current_block_);
-  if (last_inst->SuccessorCount() > 0) {
-    for (intptr_t i = last_inst->SuccessorCount() - 1; i >= 0; i--) {
-      auto const succ_block = last_inst->SuccessorAt(i);
-      succ_block->AddPredecessor(current_block_);
-      worklist->Add(succ_block->block_id());
-    }
-  }
-
-  return true;
-}
-
-bool FlowGraphDeserializer::ParseDefinitionWithParsedBody(SExpList* list,
-                                                          Definition* def) {
-  if (auto const type_sexp =
-          CheckTaggedList(list->ExtraLookupValue("type"), "CompileType")) {
-    CompileType* typ = ParseCompileType(type_sexp);
-    if (typ == nullptr) return false;
-    def->UpdateType(*typ);
-  }
-
-  if (auto const range_sexp =
-          CheckTaggedList(list->ExtraLookupValue("range"), "Range")) {
-    Range range;
-    if (!ParseRange(range_sexp, &range)) return false;
-    def->set_range(range);
-  }
-
-  auto const name_sexp = CheckSymbol(Retrieve(list, 1));
-  if (name_sexp == nullptr) return false;
-
-  // If the name is "_", this is a subclass of Definition where there's no real
-  // "result" that's being bound. We were just here to add Definition-specific
-  // extra info.
-  if (name_sexp->Equals("_")) return true;
-
-  intptr_t index;
-  if (ParseSSATemp(name_sexp, &index)) {
-    if (definition_map_.HasKey(index)) {
-      StoreError(list, "multiple definitions for the same SSA index");
-      return false;
-    }
-    def->set_ssa_temp_index(index);
-    if (index > max_ssa_index_) max_ssa_index_ = index;
-  } else {
-    // TODO(sstrickl): Add temp support for non-SSA computed graphs.
-    StoreError(list, "unhandled name for definition");
-    return false;
-  }
-
-  definition_map_.Insert(index, def);
-  if (!FixPendingValues(index, def)) return false;
-  return true;
-}
-
-Definition* FlowGraphDeserializer::ParseDefinition(SExpList* list) {
-  if (list == nullptr) return nullptr;
-  ASSERT(list->Tag() != nullptr && list->Tag()->Equals("def"));
-  auto const inst_sexp = CheckTaggedList(Retrieve(list, 2));
-  auto const inst = ParseInstruction(inst_sexp);
-  if (inst == nullptr) return nullptr;
-  if (auto const def = inst->AsDefinition()) {
-    if (!ParseDefinitionWithParsedBody(list, def)) return nullptr;
-    return def;
-  } else {
-    StoreError(list, "instruction cannot be body of definition");
-    return nullptr;
-  }
-}
-
-Instruction* FlowGraphDeserializer::ParseInstruction(SExpList* list) {
-  if (list == nullptr) return nullptr;
-  auto const tag = list->Tag();
-  if (tag->Equals("def")) return ParseDefinition(list);
-
-  intptr_t deopt_id = DeoptId::kNone;
-  if (auto const deopt_int = CheckInteger(list->ExtraLookupValue("deopt_id"))) {
-    deopt_id = deopt_int->value();
-  }
-  TokenPosition token_pos = TokenPosition::kNoSource;
-  if (auto const token_int =
-          CheckInteger(list->ExtraLookupValue("token_pos"))) {
-    token_pos = TokenPosition::Deserialize(token_int->value());
-  }
-  intptr_t inlining_id = -1;
-  if (auto const inlining_int =
-          CheckInteger(list->ExtraLookupValue("inlining_id"))) {
-    inlining_id = inlining_int->value();
-  }
-  InstrInfo common_info = {deopt_id, InstructionSource(token_pos, inlining_id)};
-
-  // Parse the environment before handling the instruction, as we may have
-  // references to PushArguments and parsing the instruction may pop
-  // PushArguments off the stack.
-  // TODO(alexmarkov): revise as it may not be needed anymore.
-  Environment* env = nullptr;
-  if (auto const env_sexp = CheckList(list->ExtraLookupValue("env"))) {
-    env = ParseEnvironment(env_sexp);
-    if (env == nullptr) return nullptr;
-  }
-
-  Instruction* inst = nullptr;
-
-#define HANDLE_CASE(name)                                                      \
-  case kHandled##name:                                                         \
-    inst = Deserialize##name(list, common_info);                               \
-    break;
-  switch (HandledInstructionForTag(tag)) {
-    FOR_EACH_HANDLED_INSTRUCTION_IN_DESERIALIZER(HANDLE_CASE)
-    case kHandledInvalid:
-      StoreError(tag, "unhandled instruction");
-      return nullptr;
-  }
-#undef HANDLE_CASE
-
-  if (inst == nullptr) return nullptr;
-  if (env != nullptr) env->DeepCopyTo(zone(), inst);
-  return inst;
-}
-
-FunctionEntryInstr* FlowGraphDeserializer::DeserializeFunctionEntry(
-    SExpList* sexp,
-    const EntryInfo& info) {
-  ASSERT(flow_graph_ != nullptr);
-  auto const graph = flow_graph_->graph_entry();
-  auto const block = new (zone())
-      FunctionEntryInstr(graph, info.block_id, info.try_index, info.deopt_id);
-  current_block_ = block;
-  if (!ParseInitialDefinitions(sexp)) return nullptr;
-  return block;
-}
-
-GraphEntryInstr* FlowGraphDeserializer::DeserializeGraphEntry(
-    SExpList* sexp,
-    const EntryInfo& info) {
-  auto const name_sexp = CheckSymbol(Retrieve(sexp, 1));
-  // TODO(sstrickl): If the FlowGraphDeserializer was constructed with a
-  // non-null ParsedFunction, we should check that the name matches here.
-  // If not, then we should create an appropriate ParsedFunction here.
-  if (name_sexp == nullptr) return nullptr;
-
-  intptr_t osr_id = Compiler::kNoOSRDeoptId;
-  if (auto const osr_id_sexp = CheckInteger(sexp->ExtraLookupValue("osr_id"))) {
-    osr_id = osr_id_sexp->value();
-  }
-
-  ASSERT(parsed_function_ != nullptr);
-  return new (zone()) GraphEntryInstr(*parsed_function_, osr_id, info.deopt_id);
-}
-
-JoinEntryInstr* FlowGraphDeserializer::DeserializeJoinEntry(
-    SExpList* sexp,
-    const EntryInfo& info) {
-  return new (zone())
-      JoinEntryInstr(info.block_id, info.try_index, info.deopt_id);
-}
-
-TargetEntryInstr* FlowGraphDeserializer::DeserializeTargetEntry(
-    SExpList* sexp,
-    const EntryInfo& info) {
-  return new (zone())
-      TargetEntryInstr(info.block_id, info.try_index, info.deopt_id);
-}
-
-AllocateObjectInstr* FlowGraphDeserializer::DeserializeAllocateObject(
-    SExpList* sexp,
-    const InstrInfo& info) {
-  auto& cls = Class::ZoneHandle(zone());
-  auto const cls_sexp = CheckTaggedList(Retrieve(sexp, 1), "Class");
-  if (!ParseClass(cls_sexp, &cls)) return nullptr;
-
-  Value* type_arguments = nullptr;
-  if (cls.NumTypeArguments() > 0) {
-    type_arguments = ParseValue(Retrieve(sexp, 2));
-    if (type_arguments == nullptr) return nullptr;
-  }
-
-  auto const inst =
-      new (zone()) AllocateObjectInstr(info.source, cls, type_arguments);
-
-  if (auto const closure_sexp = CheckTaggedList(
-          sexp->ExtraLookupValue("closure_function"), "Function")) {
-    auto& closure_function = Function::Handle(zone());
-    if (!ParseFunction(closure_sexp, &closure_function)) return nullptr;
-    inst->set_closure_function(closure_function);
-  }
-
-  if (auto const ident_sexp = CheckSymbol(sexp->ExtraLookupValue("identity"))) {
-    auto id = AliasIdentity::Unknown();
-    if (!AliasIdentity::Parse(ident_sexp->value(), &id)) {
-      return nullptr;
-    }
-    inst->SetIdentity(id);
-  }
-
-  return inst;
-}
-
-AssertAssignableInstr* FlowGraphDeserializer::DeserializeAssertAssignable(
-    SExpList* sexp,
-    const InstrInfo& info) {
-  auto const val = ParseValue(Retrieve(sexp, 1));
-  if (val == nullptr) return nullptr;
-
-  auto const dst_type = ParseValue(Retrieve(sexp, 2));
-  if (dst_type == nullptr) return nullptr;
-
-  auto const inst_type_args = ParseValue(Retrieve(sexp, 3));
-  if (inst_type_args == nullptr) return nullptr;
-
-  auto const func_type_args = ParseValue(Retrieve(sexp, 4));
-  if (func_type_args == nullptr) return nullptr;
-
-  auto& dst_name = String::ZoneHandle(zone());
-  auto const dst_name_sexp = Retrieve(sexp, "name");
-  if (!ParseDartValue(dst_name_sexp, &dst_name)) return nullptr;
-
-  auto kind = AssertAssignableInstr::Kind::kUnknown;
-  if (auto const kind_sexp = CheckSymbol(sexp->ExtraLookupValue("kind"))) {
-    if (!AssertAssignableInstr::ParseKind(kind_sexp->value(), &kind)) {
-      StoreError(kind_sexp, "unknown AssertAssignable kind");
-      return nullptr;
-    }
-  }
-
-  return new (zone())
-      AssertAssignableInstr(info.source, val, dst_type, inst_type_args,
-                            func_type_args, dst_name, info.deopt_id, kind);
-}
-
-AssertBooleanInstr* FlowGraphDeserializer::DeserializeAssertBoolean(
-    SExpList* sexp,
-    const InstrInfo& info) {
-  auto const val = ParseValue(Retrieve(sexp, 1));
-  if (val == nullptr) return nullptr;
-
-  return new (zone()) AssertBooleanInstr(info.source, val, info.deopt_id);
-}
-
-BooleanNegateInstr* FlowGraphDeserializer::DeserializeBooleanNegate(
-    SExpList* sexp,
-    const InstrInfo& info) {
-  auto const value = ParseValue(Retrieve(sexp, 1));
-  if (value == nullptr) return nullptr;
-
-  return new (zone()) BooleanNegateInstr(value);
-}
-
-BranchInstr* FlowGraphDeserializer::DeserializeBranch(SExpList* sexp,
-                                                      const InstrInfo& info) {
-  auto const comp_sexp = CheckTaggedList(Retrieve(sexp, 1));
-  auto const comp_inst = ParseInstruction(comp_sexp);
-  if (comp_inst == nullptr) return nullptr;
-  if (!comp_inst->IsComparison()) {
-    StoreError(sexp->At(1), "expected comparison instruction");
-    return nullptr;
-  }
-  auto const comparison = comp_inst->AsComparison();
-
-  auto const true_block = FetchBlock(CheckSymbol(Retrieve(sexp, 2)));
-  if (true_block == nullptr) return nullptr;
-  if (!true_block->IsTargetEntry()) {
-    StoreError(sexp->At(2), "true successor is not a target block");
-    return nullptr;
-  }
-
-  auto const false_block = FetchBlock(CheckSymbol(Retrieve(sexp, 3)));
-  if (false_block == nullptr) return nullptr;
-  if (!false_block->IsTargetEntry()) {
-    StoreError(sexp->At(3), "false successor is not a target block");
-    return nullptr;
-  }
-
-  auto const branch = new (zone()) BranchInstr(comparison, info.deopt_id);
-  *branch->true_successor_address() = true_block->AsTargetEntry();
-  *branch->false_successor_address() = false_block->AsTargetEntry();
-  return branch;
-}
-
-CheckNullInstr* FlowGraphDeserializer::DeserializeCheckNull(
-    SExpList* sexp,
-    const InstrInfo& info) {
-  auto const val = ParseValue(Retrieve(sexp, 1));
-  if (val == nullptr) return nullptr;
-
-  auto& func_name = String::ZoneHandle(zone());
-  if (auto const name_sexp =
-          CheckString(sexp->ExtraLookupValue("function_name"))) {
-    func_name = String::New(name_sexp->value(), Heap::kOld);
-  }
-
-  return new (zone())
-      CheckNullInstr(val, func_name, info.deopt_id, info.source);
-}
-
-CheckStackOverflowInstr* FlowGraphDeserializer::DeserializeCheckStackOverflow(
-    SExpList* sexp,
-    const InstrInfo& info) {
-  intptr_t stack_depth = 0;
-  if (auto const stack_sexp =
-          CheckInteger(sexp->ExtraLookupValue("stack_depth"))) {
-    stack_depth = stack_sexp->value();
-  }
-
-  intptr_t loop_depth = 0;
-  if (auto const loop_sexp =
-          CheckInteger(sexp->ExtraLookupValue("loop_depth"))) {
-    loop_depth = loop_sexp->value();
-  }
-
-  auto kind = CheckStackOverflowInstr::kOsrAndPreemption;
-  if (auto const kind_sexp = CheckSymbol(sexp->ExtraLookupValue("kind"))) {
-    ASSERT(kind_sexp->Equals("OsrOnly"));
-    kind = CheckStackOverflowInstr::kOsrOnly;
-  }
-
-  return new (zone()) CheckStackOverflowInstr(info.source, stack_depth,
-                                              loop_depth, info.deopt_id, kind);
-}
-
-ConstantInstr* FlowGraphDeserializer::DeserializeConstant(
-    SExpList* sexp,
-    const InstrInfo& info) {
-  Object& obj = Object::ZoneHandle(zone());
-  if (!ParseDartValue(Retrieve(sexp, 1), &obj)) return nullptr;
-  return new (zone()) ConstantInstr(obj, info.source);
-}
-
-DebugStepCheckInstr* FlowGraphDeserializer::DeserializeDebugStepCheck(
-    SExpList* sexp,
-    const InstrInfo& info) {
-  auto kind = UntaggedPcDescriptors::kAnyKind;
-  if (auto const kind_sexp = CheckSymbol(Retrieve(sexp, "stub_kind"))) {
-    if (!UntaggedPcDescriptors::ParseKind(kind_sexp->value(), &kind)) {
-      StoreError(kind_sexp, "not a valid UntaggedPcDescriptors::Kind name");
-      return nullptr;
-    }
-  }
-  return new (zone()) DebugStepCheckInstr(info.source, kind, info.deopt_id);
-}
-
-GotoInstr* FlowGraphDeserializer::DeserializeGoto(SExpList* sexp,
-                                                  const InstrInfo& info) {
-  auto const block = FetchBlock(CheckSymbol(Retrieve(sexp, 1)));
-  if (block == nullptr) return nullptr;
-  if (!block->IsJoinEntry()) {
-    StoreError(sexp->At(1), "target of goto must be join entry");
-    return nullptr;
-  }
-  return new (zone()) GotoInstr(block->AsJoinEntry(), info.deopt_id);
-}
-
-InstanceCallInstr* FlowGraphDeserializer::DeserializeInstanceCall(
-    SExpList* sexp,
-    const InstrInfo& info) {
-  auto& interface_target = Function::ZoneHandle(zone());
-  auto& tearoff_interface_target = Function::ZoneHandle(zone());
-  if (!ParseDartValue(Retrieve(sexp, "interface_target"), &interface_target)) {
-    return nullptr;
-  }
-  if (!ParseDartValue(Retrieve(sexp, "tearoff_interface_target"),
-                      &tearoff_interface_target)) {
-    return nullptr;
-  }
-  auto& function_name = String::ZoneHandle(zone());
-  // If we have an explicit function_name value, then use that value. Otherwise,
-  // if we have an non-null interface_target, use its name.
-  if (auto const name_sexp = sexp->ExtraLookupValue("function_name")) {
-    if (!ParseDartValue(name_sexp, &function_name)) return nullptr;
-  } else if (!interface_target.IsNull()) {
-    function_name = interface_target.name();
-  } else if (!tearoff_interface_target.IsNull()) {
-    function_name = tearoff_interface_target.name();
-  }
-
-  auto token_kind = Token::Kind::kILLEGAL;
-  if (auto const kind_sexp =
-          CheckSymbol(sexp->ExtraLookupValue("token_kind"))) {
-    if (!Token::FromStr(kind_sexp->value(), &token_kind)) {
-      StoreError(kind_sexp, "unexpected token kind");
-      return nullptr;
-    }
-  }
-
-  CallInfo call_info(zone());
-  if (!ParseCallInfo(sexp, &call_info)) return nullptr;
-
-  intptr_t checked_arg_count = 0;
-  if (auto const checked_sexp =
-          CheckInteger(sexp->ExtraLookupValue("checked_arg_count"))) {
-    checked_arg_count = checked_sexp->value();
-  }
-
-  auto const inst = new (zone()) InstanceCallInstr(
-      info.source, function_name, token_kind, call_info.inputs,
-      call_info.type_args_len, call_info.argument_names, checked_arg_count,
-      info.deopt_id, interface_target, tearoff_interface_target);
-
-  if (call_info.result_type != nullptr) {
-    inst->SetResultType(zone(), *call_info.result_type);
-  }
-
-  inst->set_entry_kind(call_info.entry_kind);
-
-  if (auto const ic_data_sexp =
-          CheckTaggedList(Retrieve(sexp, "ic_data"), "ICData")) {
-    if (!CreateICData(ic_data_sexp, inst)) return nullptr;
-  }
-
-  return inst;
-}
-
-LoadClassIdInstr* FlowGraphDeserializer::DeserializeLoadClassId(
-    SExpList* sexp,
-    const InstrInfo& info) {
-  auto const val = ParseValue(Retrieve(sexp, 1));
-  if (val == nullptr) return nullptr;
-
-  return new (zone()) LoadClassIdInstr(val);
-}
-
-LoadFieldInstr* FlowGraphDeserializer::DeserializeLoadField(
-    SExpList* sexp,
-    const InstrInfo& info) {
-  auto const instance = ParseValue(Retrieve(sexp, 1));
-  if (instance == nullptr) return nullptr;
-
-  const Slot* slot;
-  if (!ParseSlot(CheckTaggedList(Retrieve(sexp, 2)), &slot)) return nullptr;
-
-  bool calls_initializer = false;
-  if (auto const calls_initializer_sexp =
-          CheckBool(sexp->ExtraLookupValue("calls_initializer"))) {
-    calls_initializer = calls_initializer_sexp->value();
-  }
-
-  return new (zone()) LoadFieldInstr(instance, *slot, info.source,
-                                     calls_initializer, info.deopt_id);
-}
-
-NativeCallInstr* FlowGraphDeserializer::DeserializeNativeCall(
-    SExpList* sexp,
-    const InstrInfo& info) {
-  auto& function = Function::ZoneHandle(zone());
-  if (!ParseDartValue(Retrieve(sexp, "function"), &function)) return nullptr;
-  if (!function.IsFunction()) {
-    StoreError(sexp->At(1), "expected a Function value");
-    return nullptr;
-  }
-
-  auto const name_sexp = CheckString(Retrieve(sexp, "name"));
-  if (name_sexp == nullptr) return nullptr;
-  const auto& name =
-      String::ZoneHandle(zone(), String::New(name_sexp->value()));
-
-  bool link_lazily = false;
-  if (auto const link_sexp = CheckBool(sexp->ExtraLookupValue("link_lazily"))) {
-    link_lazily = link_sexp->value();
-  }
-
-  CallInfo call_info(zone());
-  if (!ParseCallInfo(sexp, &call_info)) return nullptr;
-
-  return new (zone()) NativeCallInstr(&name, &function, link_lazily,
-                                      info.source, call_info.inputs);
-}
-
-ParameterInstr* FlowGraphDeserializer::DeserializeParameter(
-    SExpList* sexp,
-    const InstrInfo& info) {
-  ASSERT(current_block_ != nullptr);
-  if (auto const index_sexp = CheckInteger(Retrieve(sexp, 1))) {
-    const auto param_offset_sexp =
-        CheckInteger(sexp->ExtraLookupValue("param_offset"));
-    ASSERT(param_offset_sexp != nullptr);
-    const auto representation_sexp =
-        CheckSymbol(sexp->ExtraLookupValue("representation"));
-    Representation representation;
-    if (!Location::ParseRepresentation(representation_sexp->value(),
-                                       &representation)) {
-      StoreError(representation_sexp, "unknown parameter representation");
-    }
-    return new (zone())
-        ParameterInstr(index_sexp->value(), param_offset_sexp->value(),
-                       current_block_, representation);
-  }
-  return nullptr;
-}
-
-ReturnInstr* FlowGraphDeserializer::DeserializeReturn(SExpList* list,
-                                                      const InstrInfo& info) {
-  Value* val = ParseValue(Retrieve(list, 1));
-  if (val == nullptr) return nullptr;
-  return new (zone()) ReturnInstr(info.source, val, info.deopt_id);
-}
-
-SpecialParameterInstr* FlowGraphDeserializer::DeserializeSpecialParameter(
-    SExpList* sexp,
-    const InstrInfo& info) {
-  ASSERT(current_block_ != nullptr);
-  auto const kind_sexp = CheckSymbol(Retrieve(sexp, 1));
-  if (kind_sexp == nullptr) return nullptr;
-  SpecialParameterInstr::SpecialParameterKind kind;
-  if (!SpecialParameterInstr::ParseKind(kind_sexp->value(), &kind)) {
-    StoreError(kind_sexp, "unknown special parameter kind");
-    return nullptr;
-  }
-  return new (zone())
-      SpecialParameterInstr(kind, info.deopt_id, current_block_);
-}
-
-StaticCallInstr* FlowGraphDeserializer::DeserializeStaticCall(
-    SExpList* sexp,
-    const InstrInfo& info) {
-  auto& function = Function::ZoneHandle(zone());
-  auto const function_sexp =
-      CheckTaggedList(Retrieve(sexp, "function"), "Function");
-  if (!ParseFunction(function_sexp, &function)) return nullptr;
-
-  CallInfo call_info(zone());
-  if (!ParseCallInfo(sexp, &call_info)) return nullptr;
-
-  intptr_t call_count = 0;
-  if (auto const call_count_sexp =
-          CheckInteger(sexp->ExtraLookupValue("call_count"))) {
-    call_count = call_count_sexp->value();
-  }
-
-  auto rebind_rule = ICData::kStatic;
-  if (auto const rebind_sexp =
-          CheckSymbol(sexp->ExtraLookupValue("rebind_rule"))) {
-    if (!ICData::ParseRebindRule(rebind_sexp->value(), &rebind_rule)) {
-      StoreError(rebind_sexp, "unknown rebind rule value");
-      return nullptr;
-    }
-  }
-
-  auto const inst = new (zone()) StaticCallInstr(
-      info.source, function, call_info.type_args_len, call_info.argument_names,
-      call_info.inputs, info.deopt_id, call_count, rebind_rule);
-
-  if (call_info.result_type != nullptr) {
-    inst->SetResultType(zone(), *call_info.result_type);
-  }
-
-  inst->set_entry_kind(call_info.entry_kind);
-
-  if (auto const ic_data_sexp =
-          CheckTaggedList(sexp->ExtraLookupValue("ic_data"), "ICData")) {
-    if (!CreateICData(ic_data_sexp, inst)) return nullptr;
-  }
-
-  return inst;
-}
-
-StoreInstanceFieldInstr* FlowGraphDeserializer::DeserializeStoreInstanceField(
-    SExpList* sexp,
-    const InstrInfo& info) {
-  auto const instance = ParseValue(Retrieve(sexp, 1));
-  if (instance == nullptr) return nullptr;
-
-  const Slot* slot = nullptr;
-  if (!ParseSlot(CheckTaggedList(Retrieve(sexp, 2), "Slot"), &slot)) {
-    return nullptr;
-  }
-
-  auto const value = ParseValue(Retrieve(sexp, 3));
-  if (value == nullptr) return nullptr;
-
-  auto barrier_type = kNoStoreBarrier;
-  if (auto const bar_sexp = CheckBool(sexp->ExtraLookupValue("emit_barrier"))) {
-    if (bar_sexp->value()) barrier_type = kEmitStoreBarrier;
-  }
-
-  auto kind = StoreInstanceFieldInstr::Kind::kOther;
-  if (auto const init_sexp = CheckBool(sexp->ExtraLookupValue("is_init"))) {
-    if (init_sexp->value()) kind = StoreInstanceFieldInstr::Kind::kInitializing;
-  }
-
-  return new (zone()) StoreInstanceFieldInstr(*slot, instance, value,
-                                              barrier_type, info.source, kind);
-}
-
-StrictCompareInstr* FlowGraphDeserializer::DeserializeStrictCompare(
-    SExpList* sexp,
-    const InstrInfo& info) {
-  auto const token_sexp = CheckSymbol(Retrieve(sexp, 1));
-  if (token_sexp == nullptr) return nullptr;
-  Token::Kind kind;
-  if (!Token::FromStr(token_sexp->value(), &kind)) return nullptr;
-
-  auto const left = ParseValue(Retrieve(sexp, 2));
-  if (left == nullptr) return nullptr;
-
-  auto const right = ParseValue(Retrieve(sexp, 3));
-  if (right == nullptr) return nullptr;
-
-  bool needs_check = false;
-  if (auto const check_sexp = CheckBool(Retrieve(sexp, "needs_check"))) {
-    needs_check = check_sexp->value();
-  }
-
-  return new (zone()) StrictCompareInstr(info.source, kind, left, right,
-                                         needs_check, info.deopt_id);
-}
-
-ThrowInstr* FlowGraphDeserializer::DeserializeThrow(SExpList* sexp,
-                                                    const InstrInfo& info) {
-  Value* exception = ParseValue(Retrieve(sexp, 1));
-  if (exception == nullptr) return nullptr;
-  return new (zone()) ThrowInstr(info.source, info.deopt_id, exception);
-}
-
-bool FlowGraphDeserializer::ParseCallInfo(SExpList* call,
-                                          CallInfo* out,
-                                          intptr_t num_extra_inputs) {
-  ASSERT(out != nullptr);
-
-  if (auto const len_sexp =
-          CheckInteger(call->ExtraLookupValue("type_args_len"))) {
-    out->type_args_len = len_sexp->value();
-  }
-
-  if (auto const arg_names_sexp =
-          CheckList(call->ExtraLookupValue("arg_names"))) {
-    out->argument_names = Array::New(arg_names_sexp->Length(), Heap::kOld);
-    for (intptr_t i = 0, n = arg_names_sexp->Length(); i < n; i++) {
-      auto name_sexp = CheckString(Retrieve(arg_names_sexp, i));
-      if (name_sexp == nullptr) return false;
-      tmp_string_ = String::New(name_sexp->value(), Heap::kOld);
-      out->argument_names.SetAt(i, tmp_string_);
-    }
-  }
-
-  if (auto const args_len_sexp =
-          CheckInteger(call->ExtraLookupValue("args_len"))) {
-    out->args_len = args_len_sexp->value();
-  }
-
-  if (auto const result_sexp = CheckTaggedList(
-          call->ExtraLookupValue("result_type"), "CompileType")) {
-    out->result_type = ParseCompileType(result_sexp);
-  }
-
-  if (auto const kind_sexp =
-          CheckSymbol(call->ExtraLookupValue("entry_kind"))) {
-    if (!Code::ParseEntryKind(kind_sexp->value(), &out->entry_kind))
-      return false;
-  }
-
-  // Type arguments are wrapped in a TypeArguments array, so no matter how
-  // many there are, they are contained in a single pushed argument.
-  auto const all_args_len = (out->type_args_len > 0 ? 1 : 0) + out->args_len;
-
-  const intptr_t num_inputs = all_args_len + num_extra_inputs;
-  out->inputs = new (zone()) InputsArray(zone(), num_inputs);
-  for (intptr_t i = 0; i < num_inputs; ++i) {
-    auto const input = ParseValue(Retrieve(call, 1 + i));
-    if (input == nullptr) return false;
-    out->inputs->Add(input);
-  }
-
-  return true;
-}
-
-Value* FlowGraphDeserializer::ParseValue(SExpression* sexp,
-                                         bool allow_pending) {
-  CompileType* type = nullptr;
-  bool inherit_type = false;
-  auto name = sexp->AsSymbol();
-  if (name == nullptr) {
-    auto const list = CheckTaggedList(sexp, "value");
-    name = CheckSymbol(Retrieve(list, 1));
-    if (auto const type_sexp =
-            CheckTaggedList(list->ExtraLookupValue("type"), "CompileType")) {
-      type = ParseCompileType(type_sexp);
-      if (type == nullptr) return nullptr;
-    } else if (auto const inherit_sexp =
-                   CheckBool(list->ExtraLookupValue("inherit_type"))) {
-      inherit_type = inherit_sexp->value();
-    } else {
-      // We assume that the type should be inherited from the definition for
-      // for (value ...) forms without an explicit type.
-      inherit_type = true;
-    }
-  }
-  intptr_t index;
-  if (!ParseUse(name, &index)) return nullptr;
-  auto const def = definition_map_.LookupValue(index);
-  Value* val;
-  if (def == nullptr) {
-    if (!allow_pending) {
-      StoreError(sexp, "found use prior to definition");
-      return nullptr;
-    }
-    val = AddNewPendingValue(sexp, index, inherit_type);
-  } else {
-    val = new (zone()) Value(def);
-    if (inherit_type) {
-      if (def->HasType()) {
-        val->reaching_type_ = def->Type();
-      } else {
-        StoreError(sexp, "value inherits type, but no type found");
-        return nullptr;
-      }
-    }
-  }
-  if (type != nullptr) val->SetReachingType(type);
-  return val;
-}
-
-CompileType* FlowGraphDeserializer::ParseCompileType(SExpList* sexp) {
-  // TODO(sstrickl): Currently we only print out nullable if it's false
-  // (or during verbose printing). Switch this when NNBD is the standard.
-  bool nullable = CompileType::kNullable;
-  if (auto const nullable_sexp =
-          CheckBool(sexp->ExtraLookupValue("nullable"))) {
-    nullable = nullable_sexp->value() ? CompileType::kNullable
-                                      : CompileType::kNonNullable;
-  }
-
-  intptr_t cid = kIllegalCid;
-  if (auto const cid_sexp = CheckInteger(sexp->ExtraLookupValue("cid"))) {
-    // TODO(sstrickl): Check that the cid is a valid concrete cid, or a cid
-    // otherwise found in CompileTypes like kIllegalCid or kDynamicCid.
-    cid = cid_sexp->value();
-  }
-
-  AbstractType* type = nullptr;
-  if (auto const type_sexp = sexp->ExtraLookupValue("type")) {
-    auto& type_handle = AbstractType::ZoneHandle(zone());
-    if (!ParseAbstractType(type_sexp, &type_handle)) return nullptr;
-    type = &type_handle;
-  }
-  return new (zone()) CompileType(nullable, cid, type);
-}
-
-Environment* FlowGraphDeserializer::ParseEnvironment(SExpList* list) {
-  if (list == nullptr) return nullptr;
-  intptr_t fixed_param_count = 0;
-  if (auto const fpc_sexp =
-          CheckInteger(list->ExtraLookupValue("fixed_param_count"))) {
-    fixed_param_count = fpc_sexp->value();
-  }
-  Environment* outer_env = nullptr;
-  if (auto const outer_sexp = CheckList(list->ExtraLookupValue("outer"))) {
-    outer_env = ParseEnvironment(outer_sexp);
-    if (outer_env == nullptr) return nullptr;
-    if (auto const deopt_sexp =
-            CheckInteger(outer_sexp->ExtraLookupValue("deopt_id"))) {
-      outer_env->deopt_id_ = deopt_sexp->value();
-    }
-  }
-
-  ASSERT(parsed_function_ != nullptr);
-  auto const env = new (zone()) Environment(list->Length(), fixed_param_count,
-                                            *parsed_function_, outer_env);
-
-  for (intptr_t i = 0; i < list->Length(); i++) {
-    auto const elem_sexp = Retrieve(list, i);
-    if (elem_sexp == nullptr) return nullptr;
-    auto val = ParseValue(elem_sexp, /*allow_pending=*/false);
-    if (val == nullptr) return nullptr;
-    env->PushValue(val);
-  }
-
-  return env;
-}
-
-bool FlowGraphDeserializer::ParseDartValue(SExpression* sexp, Object* out) {
-  ASSERT(out != nullptr);
-  if (sexp == nullptr) return false;
-  *out = Object::null();
-
-  if (auto const sym = sexp->AsSymbol()) {
-    // We'll use the null value in *out as a marker later, so go ahead and exit
-    // early if we parse one.
-    if (sym->Equals("null")) return true;
-    if (sym->Equals("sentinel")) {
-      *out = Object::sentinel().ptr();
-      return true;
-    }
-
-    // The only other symbols that should appear in Dart value position are
-    // names of constant definitions.
-    auto const val = ParseValue(sym, /*allow_pending=*/false);
-    if (val == nullptr) return false;
-    if (!val->BindsToConstant()) {
-      StoreError(sym, "not a reference to a constant definition");
-      return false;
-    }
-    *out = val->BoundConstant().ptr();
-    // Values used in constant definitions have already been canonicalized,
-    // so just exit.
-    return true;
-  }
-
-  // Other instance values may need to be canonicalized, so do that before
-  // returning.
-  if (auto const b = sexp->AsBool()) {
-    *out = Bool::Get(b->value()).ptr();
-  } else if (auto const str = sexp->AsString()) {
-    *out = String::New(str->value(), Heap::kOld);
-  } else if (auto const i = sexp->AsInteger()) {
-    *out = Integer::New(i->value(), Heap::kOld);
-  } else if (auto const d = sexp->AsDouble()) {
-    *out = Double::New(d->value(), Heap::kOld);
-  } else if (auto const list = CheckTaggedList(sexp)) {
-    auto const tag = list->Tag();
-    if (tag->Equals("Class")) {
-      return ParseClass(list, out);
-    } else if (tag->Equals("Type")) {
-      return ParseType(list, out);
-    } else if (tag->Equals("TypeArguments")) {
-      return ParseTypeArguments(list, out);
-    } else if (tag->Equals("Field")) {
-      return ParseField(list, out);
-    } else if (tag->Equals("Function")) {
-      return ParseFunction(list, out);
-    } else if (tag->Equals("FunctionType")) {
-      return ParseFunctionType(list, out);
-    } else if (tag->Equals("TypeParameter")) {
-      return ParseTypeParameter(list, out);
-    } else if (tag->Equals("Array")) {
-      return ParseArray(list, out);
-    } else if (tag->Equals("ImmutableList")) {
-      return ParseImmutableList(list, out);
-    } else if (tag->Equals("Instance")) {
-      return ParseInstance(list, out);
-    } else if (tag->Equals("Closure")) {
-      return ParseClosure(list, out);
-    } else if (tag->Equals("TypeRef")) {
-      return ParseTypeRef(list, out);
-    }
-  }
-
-  // If we're here and still haven't gotten a non-null value, then something
-  // went wrong. (Likely an unrecognized value.)
-  if (out->IsNull()) {
-    StoreError(sexp, "unhandled Dart value");
-    return false;
-  }
-
-  if (!out->IsInstance()) return true;
-  return CanonicalizeInstance(sexp, out);
-}
-
-bool FlowGraphDeserializer::CanonicalizeInstance(SExpression* sexp,
-                                                 Object* out) {
-  ASSERT(out != nullptr);
-  if (!out->IsInstance()) return true;
-  // Instance::Canonicalize uses the current zone for the passed in thread,
-  // not an explicitly provided zone. This means we cannot be run in a context
-  // where [thread()->zone()] does not match [zone()] (e.g., due to StackZone)
-  // until this is addressed.
-  *out = Instance::Cast(*out).Canonicalize(thread());
-  return true;
-}
-
-bool FlowGraphDeserializer::ParseAbstractType(SExpression* sexp, Object* out) {
-  ASSERT(out != nullptr);
-  if (sexp == nullptr) return false;
-
-  // If it's a symbol, it should be a reference to a constant definition, which
-  // is handled in ParseType.
-  if (auto const sym = sexp->AsSymbol()) {
-    return ParseType(sexp, out);
-  } else if (auto const list = CheckTaggedList(sexp)) {
-    auto const tag = list->Tag();
-    if (tag->Equals("Type")) {
-      return ParseType(list, out);
-    } else if (tag->Equals("TypeParameter")) {
-      return ParseTypeParameter(list, out);
-    } else if (tag->Equals("TypeRef")) {
-      return ParseTypeRef(list, out);
-    }
-  }
-
-  StoreError(sexp, "not an AbstractType");
-  return false;
-}
-
-bool FlowGraphDeserializer::ParseClass(SExpList* list, Object* out) {
-  ASSERT(out != nullptr);
-  if (list == nullptr) return false;
-
-  auto const ref_sexp = Retrieve(list, 1);
-  if (ref_sexp == nullptr) return false;
-  if (auto const cid_sexp = ref_sexp->AsInteger()) {
-    ClassTable* table = thread()->isolate_group()->class_table();
-    if (!table->HasValidClassAt(cid_sexp->value())) {
-      StoreError(cid_sexp, "no valid class found for cid");
-      return false;
-    }
-    *out = table->At(cid_sexp->value());
-  } else if (auto const name_sexp = ref_sexp->AsSymbol()) {
-    if (!ParseCanonicalName(name_sexp, out)) return false;
-    if (!out->IsClass()) {
-      StoreError(name_sexp, "expected the name of a class");
-      return false;
-    }
-  }
-  return true;
-}
-
-bool FlowGraphDeserializer::ParseClosure(SExpList* list, Object* out) {
-  ASSERT(out != nullptr);
-  if (list == nullptr) return false;
-
-  auto& function = Function::ZoneHandle(zone());
-  auto const function_sexp = CheckTaggedList(Retrieve(list, 1), "Function");
-  if (!ParseFunction(function_sexp, &function)) return false;
-
-  auto& context = Context::ZoneHandle(zone());
-  if (list->ExtraLookupValue("context") != nullptr) {
-    StoreError(list, "closures with contexts currently unhandled");
-    return false;
-  }
-
-  auto& inst_type_args = TypeArguments::ZoneHandle(zone());
-  if (auto const type_args_sexp = Retrieve(list, "inst_type_args")) {
-    if (!ParseTypeArguments(type_args_sexp, &inst_type_args)) return false;
-  }
-
-  auto& func_type_args = TypeArguments::ZoneHandle(zone());
-  if (auto const type_args_sexp = Retrieve(list, "func_type_args")) {
-    if (!ParseTypeArguments(type_args_sexp, &func_type_args)) return false;
-  }
-
-  auto& delayed_type_args = TypeArguments::ZoneHandle(zone());
-  if (auto const type_args_sexp = Retrieve(list, "delayed_type_args")) {
-    if (!ParseTypeArguments(type_args_sexp, &delayed_type_args)) {
-      return false;
-    }
-  }
-
-  *out = Closure::New(inst_type_args, func_type_args, delayed_type_args,
-                      function, context, Heap::kOld);
-  return CanonicalizeInstance(list, out);
-}
-
-bool FlowGraphDeserializer::ParseField(SExpList* list, Object* out) {
-  auto const name_sexp = CheckSymbol(Retrieve(list, 1));
-  if (!ParseCanonicalName(name_sexp, out)) return false;
-  if (!out->IsField()) {
-    StoreError(list, "expected a Field name");
-    return false;
-  }
-  return true;
-}
-
-bool FlowGraphDeserializer::ParseFunction(SExpList* list, Object* out) {
-  ASSERT(out != nullptr);
-  if (list == nullptr) return false;
-
-  auto const name_sexp = CheckSymbol(Retrieve(list, 1));
-  if (!ParseCanonicalName(name_sexp, out)) return false;
-  if (!out->IsFunction()) {
-    StoreError(list, "expected a Function name");
-    return false;
-  }
-  auto& function = Function::Cast(*out);
-  // Check the kind expected by the S-expression if one was specified.
-  if (auto const kind_sexp = CheckSymbol(list->ExtraLookupValue("kind"))) {
-    UntaggedFunction::Kind kind;
-    if (!UntaggedFunction::ParseKind(kind_sexp->value(), &kind)) {
-      StoreError(kind_sexp, "unexpected function kind");
-      return false;
-    }
-    if (function.kind() != kind) {
-      auto const kind_str = UntaggedFunction::KindToCString(function.kind());
-      StoreError(list, "retrieved function has kind %s", kind_str);
-      return false;
-    }
-  }
-  return true;
-}
-
-bool FlowGraphDeserializer::ParseFunctionType(SExpList* list, Object* out) {
-  ASSERT(out != nullptr);
-  if (list == nullptr) return false;
-  auto& type_params = TypeArguments::ZoneHandle(zone());
-  if (auto const type_params_sexp = Retrieve(list, "type_params")) {
-    if (!ParseTypeArguments(type_params_sexp, &type_params)) return false;
-  }
-  auto& result_type = AbstractType::ZoneHandle(zone());
-  if (auto const result_type_sexp = Retrieve(list, "result_type")) {
-    if (!ParseAbstractType(result_type_sexp, &result_type)) return false;
-  }
-  auto& parameter_types = Array::ZoneHandle(zone());
-  if (auto const parameter_types_sexp = Retrieve(list, "parameter_types")) {
-    if (!ParseDartValue(parameter_types_sexp, &parameter_types)) return false;
-  }
-  auto& parameter_names = Array::ZoneHandle(zone());
-  if (auto const parameter_names_sexp = Retrieve(list, "parameter_names")) {
-    if (!ParseDartValue(parameter_names_sexp, &parameter_names)) return false;
-  }
-  intptr_t packed_fields;
-  if (auto const packed_fields_sexp =
-          CheckInteger(list->ExtraLookupValue("packed_fields"))) {
-    packed_fields = packed_fields_sexp->value();
-  } else {
-    return false;
-  }
-  auto& sig = FunctionType::ZoneHandle(zone(), FunctionType::New());
-  sig.set_type_parameters(type_params);
-  sig.set_result_type(result_type);
-  sig.set_parameter_types(parameter_types);
-  sig.set_parameter_names(parameter_names);
-  sig.set_packed_fields(packed_fields);
-  *out = sig.ptr();
-  return true;
-}
-
-bool FlowGraphDeserializer::ParseArray(SExpList* list, Object* out) {
-  ASSERT(out != nullptr);
-  if (list == nullptr) return false;
-
-  *out = Array::New(list->Length() - 1, Heap::kOld);
-  auto& arr = Array::Cast(*out);
-  // Arrays may contain other arrays, so we'll need a new handle in which to
-  // store elements.
-  auto& elem = Object::Handle(zone());
-  for (intptr_t i = 1; i < list->Length(); i++) {
-    if (!ParseDartValue(Retrieve(list, i), &elem)) return false;
-    arr.SetAt(i - 1, elem);
-  }
-  if (auto type_args_sexp = list->ExtraLookupValue("type_args")) {
-    if (!ParseTypeArguments(type_args_sexp, &array_type_args_)) return false;
-    arr.SetTypeArguments(array_type_args_);
-  }
-  return true;
-}
-
-bool FlowGraphDeserializer::ParseImmutableList(SExpList* list, Object* out) {
-  if (!ParseArray(list, out)) return false;
-
-  Array::Cast(*out).MakeImmutable();
-  return CanonicalizeInstance(list, out);
-}
-
-bool FlowGraphDeserializer::ParseInstance(SExpList* list, Object* out) {
-  ASSERT(out != nullptr);
-  if (list == nullptr) return false;
-  auto const cid_sexp = CheckInteger(Retrieve(list, 1));
-  if (cid_sexp == nullptr) return false;
-
-  auto const table = thread()->isolate_group()->class_table();
-  if (!table->HasValidClassAt(cid_sexp->value())) {
-    StoreError(cid_sexp, "cid is not valid");
-    return false;
-  }
-
-  ASSERT(cid_sexp->value() != kNullCid);  // Must use canonical instances.
-  ASSERT(cid_sexp->value() != kBoolCid);  // Must use canonical instances.
-  instance_class_ = table->At(cid_sexp->value());
-  *out = Instance::New(instance_class_, Heap::kOld);
-  auto& instance = Instance::Cast(*out);
-
-  if (auto const type_args = list->ExtraLookupValue("type_args")) {
-    instance_type_args_ = TypeArguments::null();
-    if (!ParseTypeArguments(type_args, &instance_type_args_)) return false;
-    if (!instance_class_.IsGeneric()) {
-      StoreError(list,
-                 "type arguments provided for an instance of a "
-                 "non-generic class");
-      return false;
-    }
-    instance.SetTypeArguments(instance_type_args_);
-  }
-
-  // Pick out and store the final instance fields of the class, as values must
-  // be provided for them. Error if there are any non-final instance fields.
-  instance_fields_array_ = instance_class_.fields();
-  auto const field_count = instance_fields_array_.Length();
-  GrowableArray<const Field*> final_fields(zone(), field_count);
-  for (intptr_t i = 0, n = field_count; i < n; i++) {
-    instance_field_ = Field::RawCast(instance_fields_array_.At(i));
-    if (!instance_field_.is_instance()) continue;
-    if (!instance_field_.is_final()) {
-      StoreError(list, "class for instance has non-final instance fields");
-      return false;
-    }
-    auto& fresh_handle = Field::Handle(zone(), instance_field_.ptr());
-    final_fields.Add(&fresh_handle);
-  }
-
-  // If there is no (Fields...) sub-expression or it has no extra info, then
-  // ensure there are no final fields before returning the canonicalized form.
-  SExpList* fields_sexp = nullptr;
-  bool fields_provided = list->Length() > 2;
-  if (fields_provided) {
-    fields_sexp = CheckTaggedList(Retrieve(list, 2), "Fields");
-    if (fields_sexp == nullptr) return false;
-    fields_provided = fields_sexp->ExtraLength() != 0;
-  }
-  if (!fields_provided) {
-    if (!final_fields.is_empty()) {
-      StoreError(list, "values not provided for final fields of instance");
-      return false;
-    }
-    return CanonicalizeInstance(list, out);
-  }
-
-  // At this point, we have final instance field values to set on the new
-  // instance before canonicalization. When setting instance fields, we may
-  // cause field guards to be invalidated. Because of this, we must either be
-  // running on the mutator thread or be at a safepoint when calling `SetField`.
-  //
-  // For IR round-trips, the constants we create have already existed before in
-  // the VM heap, which means field invalidation cannot occur. Thus, we create a
-  // closure that sets the fields of the instance and then conditionally run
-  // that closure at a safepoint if not in the mutator thread.
-  //
-  // TODO(dartbug.com/36882): When deserializing IR that was not generated
-  // during the RoundTripSerialization pass, we are no longer guaranteed that
-  // deserialization of instances will not invalidate field guards. Thus, we may
-  // need to support invalidating field guards on non-mutator threads or fall
-  // back onto forcing the deserialization to happen on the mutator thread.
-  auto set_instance_fields = [&]() {
-    auto& inst = Instance::Cast(*out);
-    // We'll need to allocate a handle for the parsed value as we may have
-    // instances as field values and so this function may be re-entered.
-    auto& value = Object::Handle(zone());
-    for (auto field : final_fields) {
-      tmp_string_ = field->UserVisibleName();
-      auto const name = tmp_string_.ToCString();
-      auto const value_sexp = Retrieve(fields_sexp, name);
-      if (value_sexp == nullptr) {
-        StoreError(list, "no value provided for final instance field %s", name);
-        return false;
-      }
-      if (!ParseDartValue(value_sexp, &value)) return false;
-      inst.SetField(*field, value);
-    }
-    return true;
-  };
-
-  auto const t = Thread::Current();
-  if (!t->IsMutatorThread()) {
-    SafepointOperationScope safepoint_scope(t);
-    if (!set_instance_fields()) return false;
-  } else {
-    if (!set_instance_fields()) return false;
-  }
-
-  return CanonicalizeInstance(list, out);
-}
-
-bool FlowGraphDeserializer::ParseType(SExpression* sexp, Object* out) {
-  ASSERT(out != nullptr);
-  if (sexp == nullptr) return false;
-
-  if (auto const sym = sexp->AsSymbol()) {
-    auto const val = ParseValue(sexp, /*allow_pending=*/false);
-    if (val == nullptr) {
-      StoreError(sexp, "expected type or reference to constant definition");
-      return false;
-    }
-    if (!val->BindsToConstant()) {
-      StoreError(sexp, "reference to non-constant definition");
-      return false;
-    }
-    *out = val->BoundConstant().ptr();
-    if (!out->IsType()) {
-      StoreError(sexp, "expected Type constant");
-      return false;
-    }
-    return true;
-  }
-  auto const list = CheckTaggedList(sexp, "Type");
-  if (list == nullptr) return false;
-
-  const auto hash_sexp = CheckInteger(list->ExtraLookupValue("hash"));
-  const auto is_recursive = hash_sexp != nullptr;
-  // This isn't necessary the hash value we will have in the new FlowGraph, but
-  // it will be how this type is referred to by TypeRefs in the serialized one.
-  auto const old_hash = is_recursive ? hash_sexp->value() : 0;
-  ZoneGrowableArray<TypeRef*>* pending_typerefs = nullptr;
-  if (is_recursive) {
-    if (pending_typeref_map_.LookupValue(old_hash) != nullptr) {
-      StoreError(sexp, "already parsing a type with hash %" Pd64 "",
-                 hash_sexp->value());
-      return false;
-    }
-    pending_typerefs = new (zone()) ZoneGrowableArray<TypeRef*>(zone(), 2);
-    pending_typeref_map_.Insert(old_hash, pending_typerefs);
-  }
-
-  const auto cls_sexp = CheckTaggedList(Retrieve(list, 1), "Class");
-  if (cls_sexp == nullptr) {
-    // TODO(sstrickl): Handle types not derived from classes.
-    StoreError(list, "non-class types not currently handled");
-    return false;
-  }
-  TokenPosition token_pos = TokenPosition::kNoSource;
-  if (const auto pos_sexp = CheckInteger(list->ExtraLookupValue("token_pos"))) {
-    token_pos = TokenPosition::Deserialize(pos_sexp->value());
-  }
-  auto type_args_ptr = &Object::null_type_arguments();
-  if (const auto ta_sexp = list->ExtraLookupValue("type_args")) {
-    // ParseTypeArguments may re-enter ParseType after setting the contents of
-    // the passed in handle, so we need to allocate a new handle here.
-    auto& type_args = TypeArguments::Handle(zone());
-    if (!ParseTypeArguments(ta_sexp, &type_args)) return false;
-    type_args_ptr = &type_args;
-  }
-  // Guaranteed not to re-enter ParseType.
-  if (!ParseClass(cls_sexp, &type_class_)) return false;
-  const Nullability nullability =
-      type_class_.IsNullClass() ? Nullability::kNullable : Nullability::kLegacy;
-  *out = Type::New(type_class_, *type_args_ptr, nullability);
-  auto& type = Type::Cast(*out);
-  if (is_recursive) {
-    while (!pending_typerefs->is_empty()) {
-      auto const ref = pending_typerefs->RemoveLast();
-      ASSERT(ref != nullptr);
-      ref->set_type(type);
-    }
-    pending_typeref_map_.Remove(old_hash);
-
-    // If there are still pending typerefs, we can't canonicalize yet until
-    // an enclosing type where we have resolved them. This is a conservative
-    // check, as we do not ensure that any of the still-pending typerefs are
-    // found within this type.
-    //
-    // This is within the is_recursive check because if this type was
-    // non-recursive, then even if there are pending type refs, we are
-    // guaranteed that none of them are in this type.
-    if (ArePendingTypeRefs()) return true;
-  }
-
-  // Need to set this for canonicalization. We ensure in the serializer
-  // that only finalized types are successfully serialized.
-  type.SetIsFinalized();
-  return CanonicalizeInstance(list, out);
-}
-
-bool FlowGraphDeserializer::ParseTypeArguments(SExpression* sexp, Object* out) {
-  ASSERT(out != nullptr);
-  if (sexp == nullptr) return false;
-
-  if (auto const sym = sexp->AsSymbol()) {
-    auto const val = ParseValue(sexp, /*allow_pending=*/false);
-    if (val == nullptr) {
-      StoreError(sexp,
-                 "expected type arguments or reference to constant definition");
-      return false;
-    }
-    if (!val->BindsToConstant()) {
-      StoreError(sexp, "reference to non-constant definition");
-      return false;
-    }
-    *out = val->BoundConstant().ptr();
-    if (!out->IsTypeArguments()) {
-      StoreError(sexp, "expected TypeArguments constant");
-      return false;
-    }
-    return true;
-  }
-  auto const list = CheckTaggedList(sexp, "TypeArguments");
-  if (list == nullptr) return false;
-
-  *out = TypeArguments::New(list->Length() - 1, Heap::kOld);
-  auto& type_args = TypeArguments::Cast(*out);
-  // We may reenter ParseTypeArguments while parsing one of the elements, so we
-  // need a fresh handle here.
-  auto& elem = AbstractType::Handle(zone());
-  for (intptr_t i = 1, n = list->Length(); i < n; i++) {
-    if (!ParseAbstractType(Retrieve(list, i), &elem)) return false;
-    type_args.SetTypeAt(i - 1, elem);
-  }
-
-  // If there are still pending typerefs, we can't canonicalize yet.
-  if (ArePendingTypeRefs()) return true;
-
-  return CanonicalizeInstance(list, out);
-}
-
-bool FlowGraphDeserializer::ParseTypeParameter(SExpList* list, Object* out) {
-  ASSERT(out != nullptr);
-  if (list == nullptr) return false;
-
-  Class& cls = Class::Handle();
-  if (auto const cid_sexp = CheckInteger(list->ExtraLookupValue("cid"))) {
-    const intptr_t cid = cid_sexp->value();
-    ClassTable* table = thread()->isolate_group()->class_table();
-    if (!table->HasValidClassAt(cid)) {
-      StoreError(cid_sexp, "no valid class found for cid");
-      return false;
-    }
-    cls = table->At(cid);
-  } else {
-    return false;
-  }
-  auto const base_sexp = CheckInteger(list->ExtraLookupValue("base"));
-  if (base_sexp == nullptr) return false;
-  intptr_t base = base_sexp->value();
-  auto const index_sexp = CheckInteger(list->ExtraLookupValue("index"));
-  if (index_sexp == nullptr) return false;
-  intptr_t index = index_sexp->value();
-  auto const name_sexp = CheckSymbol(Retrieve(list, 1));
-  if (name_sexp == nullptr) return false;
-  tmp_string_ = String::New(name_sexp->value());
-
-  *out =
-      TypeParameter::New(cls, base, index, tmp_string_, Object::dynamic_type(),
-                         false, Nullability::kLegacy);
-  TypeParameter::Cast(*out).SetIsFinalized();
-  return CanonicalizeInstance(list, out);
-}
-
-bool FlowGraphDeserializer::ParseTypeRef(SExpList* list, Object* out) {
-  ASSERT(out != nullptr);
-  if (list == nullptr) return false;
-
-  const bool contains_type = list->Length() > 1;
-  if (contains_type) {
-    auto& type = Type::Handle(zone());
-    if (!ParseAbstractType(Retrieve(list, 1), &type)) return false;
-    *out = TypeRef::New(type);
-    // If the TypeRef appears outside the referrent, then the referrent
-    // should be already canonicalized. This serves as a double-check that
-    // is the case.
-    return CanonicalizeInstance(list, out);
-  }
-  // If there is no type in the body, then this must be a referrent to
-  // a Type containing this TypeRef. That means we must have a hash value.
-  auto const hash_sexp = CheckInteger(Retrieve(list, "hash"));
-  if (hash_sexp == nullptr) return false;
-  auto const old_hash = hash_sexp->value();
-  auto const pending = pending_typeref_map_.LookupValue(old_hash);
-  if (pending == nullptr) {
-    StoreError(list, "reference to recursive type found outside type");
-    return false;
-  }
-  *out = TypeRef::New(Object::null_abstract_type());
-  pending->Add(static_cast<TypeRef*>(out));
-
-  // We can only canonicalize TypeRefs appearing within their referrent
-  // when its containing value is canonicalized.
-  return true;
-}
-
-bool FlowGraphDeserializer::ParseCanonicalName(SExpSymbol* sym, Object* obj) {
-  ASSERT(obj != nullptr);
-  if (sym == nullptr) return false;
-  auto const name = sym->value();
-  // TODO(sstrickl): No library URL, handle this better.
-  if (*name == ':') {
-    StoreError(sym, "expected non-empty library");
-    return false;
-  }
-  const char* lib_end = nullptr;
-  if (auto const first = strchr(name, ':')) {
-    lib_end = strchr(first + 1, ':');
-    if (lib_end == nullptr) lib_end = strchr(first + 1, '\0');
-  } else {
-    StoreError(sym, "malformed library");
-    return false;
-  }
-  tmp_string_ =
-      String::FromUTF8(reinterpret_cast<const uint8_t*>(name), lib_end - name);
-  name_library_ = Library::LookupLibrary(thread(), tmp_string_);
-  if (*lib_end == '\0') {
-    *obj = name_library_.ptr();
-    return true;
-  }
-  const char* const class_start = lib_end + 1;
-  if (*class_start == '\0') {
-    StoreError(sym, "no class found after colon");
-    return false;
-  }
-  // If classes are followed by another part, it's either a function
-  // (separated by ':') or a field (separated by '.').
-  const char* class_end = strchr(class_start, ':');
-  if (class_end == nullptr) class_end = strchr(class_start, '.');
-  if (class_end == nullptr) class_end = strchr(class_start, '\0');
-  const bool empty_name = class_end == class_start;
-  name_class_ = Class::null();
-  if (empty_name) {
-    name_class_ = name_library_.toplevel_class();
-  } else {
-    tmp_string_ = String::FromUTF8(
-        reinterpret_cast<const uint8_t*>(class_start), class_end - class_start);
-    name_class_ = name_library_.LookupClassAllowPrivate(tmp_string_);
-  }
-  if (name_class_.IsNull()) {
-    StoreError(sym, "failure looking up class %s in library %s",
-               empty_name ? "at top level" : tmp_string_.ToCString(),
-               name_library_.ToCString());
-    return false;
-  }
-  if (*class_end == '\0') {
-    *obj = name_class_.ptr();
-    return true;
-  }
-  if (*class_end == '.') {
-    if (class_end[1] == '\0') {
-      StoreError(sym, "no field name found after period");
-      return false;
-    }
-    const char* const field_start = class_end + 1;
-    const char* field_end = strchr(field_start, '\0');
-    tmp_string_ = String::FromUTF8(
-        reinterpret_cast<const uint8_t*>(field_start), field_end - field_start);
-    name_field_ = name_class_.LookupFieldAllowPrivate(tmp_string_);
-    if (name_field_.IsNull()) {
-      StoreError(sym, "failure looking up field %s in class %s",
-                 tmp_string_.ToCString(),
-                 empty_name ? "at top level" : name_class_.ToCString());
-      return false;
-    }
-    *obj = name_field_.ptr();
-    return true;
-  }
-  if (class_end[1] == '\0') {
-    StoreError(sym, "no function name found after final colon");
-    return false;
-  }
-  const char* func_start = class_end + 1;
-  name_function_ = Function::null();
-  while (true) {
-    const char* func_end = strchr(func_start, ':');
-    intptr_t name_len = func_end - func_start;
-    bool is_forwarder = false;
-    if (func_end != nullptr && name_len == 3) {
-      // Special case for getters/setters, where they are prefixed with "get:"
-      // or "set:", as those colons should not be used as separators.
-      if (strncmp(func_start, "get", 3) == 0 ||
-          strncmp(func_start, "set", 3) == 0) {
-        func_end = strchr(func_end + 1, ':');
-      } else if (strncmp(func_start, "dyn", 3) == 0) {
-        // Dynamic invocation forwarders start with "dyn:" and we'll need to
-        // look up the base function and then retrieve the forwarder from it.
-        is_forwarder = true;
-        func_start = func_end + 1;
-        func_end = strchr(func_end + 1, ':');
-      }
-    }
-    if (func_end == nullptr) func_end = strchr(func_start, '\0');
-    name_len = func_end - func_start;
-
-    // Check for tearoff names before we overwrite the contents of tmp_string_.
-    if (!name_function_.IsNull()) {
-      ASSERT(!tmp_string_.IsNull());
-      auto const parent_name = tmp_string_.ToCString();
-      // ImplicitClosureFunctions (tearoffs) have the same name as the Function
-      // to which they are attached. We currently don't handle any other kinds
-      // of local functions.
-      if (name_function_.HasImplicitClosureFunction() && *func_end == '\0' &&
-          strncmp(parent_name, func_start, name_len) == 0) {
-        *obj = name_function_.ImplicitClosureFunction();
-        return true;
-      }
-      StoreError(sym, "no handling for local functions");
-      return false;
-    }
-
-    // Check for the prefix "<anonymous ..." in the name and fail if found,
-    // since we can't resolve these.
-    static auto const anon_prefix = "<anonymous ";
-    static const intptr_t prefix_len = strlen(anon_prefix);
-    if ((name_len > prefix_len) &&
-        strncmp(anon_prefix, func_start, prefix_len) == 0) {
-      StoreError(sym, "cannot resolve anonymous values");
-      return false;
-    }
-
-    tmp_string_ = String::FromUTF8(reinterpret_cast<const uint8_t*>(func_start),
-                                   name_len);
-    name_function_ = name_class_.LookupFunctionAllowPrivate(tmp_string_);
-    if (name_function_.IsNull()) {
-      StoreError(sym, "failure looking up function %s in class %s",
-                 tmp_string_.ToCString(), name_class_.ToCString());
-      return false;
-    }
-    if (is_forwarder) {
-      tmp_string_ = name_function_.name();
-      tmp_string_ = Function::CreateDynamicInvocationForwarderName(tmp_string_);
-      name_function_ =
-          name_function_.GetDynamicInvocationForwarder(tmp_string_);
-    }
-    if (func_end[0] == '\0') break;
-    if (func_end[1] == '\0') {
-      StoreError(sym, "no function name found after final colon");
-      return false;
-    }
-    func_start = func_end + 1;
-  }
-  *obj = name_function_.ptr();
-  return true;
-}
-
-bool FlowGraphDeserializer::ParseSlot(SExpList* list, const Slot** out) {
-  ASSERT(out != nullptr);
-  const auto offset_sexp = CheckInteger(Retrieve(list, 1));
-  if (offset_sexp == nullptr) return false;
-  const auto offset = offset_sexp->value();
-
-  const auto kind_sexp = CheckSymbol(Retrieve(list, "kind"));
-  if (kind_sexp == nullptr) return false;
-  Slot::Kind kind;
-  if (!Slot::ParseKind(kind_sexp->value(), &kind)) {
-    StoreError(kind_sexp, "unknown Slot kind");
-    return false;
-  }
-
-  switch (kind) {
-    case Slot::Kind::kDartField: {
-      auto& field = Field::ZoneHandle(zone());
-      const auto field_sexp = CheckTaggedList(Retrieve(list, "field"), "Field");
-      if (!ParseDartValue(field_sexp, &field)) return false;
-      ASSERT(parsed_function_ != nullptr);
-      *out =
-          &Slot::Get(kernel::BaseFlowGraphBuilder::MayCloneField(zone(), field),
-                     parsed_function_);
-      break;
-    }
-    case Slot::Kind::kTypeArguments:
-      *out = &Slot::GetTypeArgumentsSlotAt(thread(), offset);
-      break;
-    case Slot::Kind::kTypeArgumentsIndex:
-      *out = &Slot::GetTypeArgumentsIndexSlot(thread(), offset);
-      break;
-    case Slot::Kind::kArrayElement:
-      *out = &Slot::GetArrayElementSlot(thread(), offset);
-      break;
-    case Slot::Kind::kCapturedVariable:
-      StoreError(kind_sexp, "unhandled Slot kind");
-      return false;
-    default:
-      *out = &Slot::GetNativeSlot(kind);
-      break;
-  }
-  return true;
-}
-
-bool FlowGraphDeserializer::ParseRange(SExpList* list, Range* out) {
-  if (list == nullptr) return false;
-  RangeBoundary min, max;
-  if (!ParseRangeBoundary(Retrieve(list, 1), &min)) return false;
-  if (list->Length() == 2) {
-    max = min;
-  } else {
-    if (!ParseRangeBoundary(Retrieve(list, 2), &max)) return false;
-  }
-  out->min_ = min;
-  out->max_ = max;
-  return true;
-}
-
-bool FlowGraphDeserializer::ParseRangeBoundary(SExpression* sexp,
-                                               RangeBoundary* out) {
-  if (sexp == nullptr) return false;
-  if (auto const int_sexp = sexp->AsInteger()) {
-    out->kind_ = RangeBoundary::Kind::kConstant;
-    out->value_ = int_sexp->value();
-  } else if (auto const sym_sexp = sexp->AsSymbol()) {
-    if (!RangeBoundary::ParseKind(sym_sexp->value(), &out->kind_)) return false;
-  } else if (auto const list_sexp = sexp->AsList()) {
-    intptr_t index;
-    if (!ParseUse(CheckSymbol(Retrieve(list_sexp, 1)), &index)) return false;
-    auto const def = definition_map_.LookupValue(index);
-    if (def == nullptr) {
-      StoreError(list_sexp, "no definition for symbolic range boundary");
-      return false;
-    }
-    out->kind_ = RangeBoundary::Kind::kSymbol;
-    out->value_ = reinterpret_cast<intptr_t>(def);
-    if (auto const offset_sexp =
-            CheckInteger(list_sexp->ExtraLookupValue("offset"))) {
-      auto const offset = offset_sexp->value();
-      if (!RangeBoundary::IsValidOffsetForSymbolicRangeBoundary(offset)) {
-        StoreError(sexp, "invalid offset for symbolic range boundary");
-        return false;
-      }
-      out->offset_ = offset;
-    }
-  } else {
-    StoreError(sexp, "unexpected value for range boundary");
-    return false;
-  }
-  return true;
-}
-
-bool FlowGraphDeserializer::ParseBlockId(SExpSymbol* sym, intptr_t* out) {
-  return ParseSymbolAsPrefixedInt(sym, 'B', out);
-}
-
-bool FlowGraphDeserializer::ParseSSATemp(SExpSymbol* sym, intptr_t* out) {
-  return ParseSymbolAsPrefixedInt(sym, 'v', out);
-}
-
-bool FlowGraphDeserializer::ParseUse(SExpSymbol* sym, intptr_t* out) {
-  // TODO(sstrickl): Handle non-SSA temp uses.
-  return ParseSSATemp(sym, out);
-}
-
-bool FlowGraphDeserializer::ParseSymbolAsPrefixedInt(SExpSymbol* sym,
-                                                     char prefix,
-                                                     intptr_t* out) {
-  ASSERT(out != nullptr);
-  if (sym == nullptr) return false;
-  auto const name = sym->value();
-  if (*name != prefix) {
-    StoreError(sym, "expected symbol starting with '%c'", prefix);
-    return false;
-  }
-  int64_t i;
-  if (!OS::StringToInt64(name + 1, &i)) {
-    StoreError(sym, "expected number following symbol prefix '%c'", prefix);
-    return false;
-  }
-  *out = i;
-  return true;
-}
-
-bool FlowGraphDeserializer::ArePendingTypeRefs() const {
-  // We'll do a deep check, because while there may be recursive types still
-  // being parsed, if there are no pending type refs to those recursive types,
-  // we're still good to canonicalize.
-  if (pending_typeref_map_.IsEmpty()) return false;
-  auto it = pending_typeref_map_.GetIterator();
-  while (auto kv = it.Next()) {
-    if (!kv->value->is_empty()) return true;
-  }
-  return false;
-}
-
-bool FlowGraphDeserializer::CreateICData(SExpList* list, Instruction* inst) {
-  ASSERT(inst != nullptr);
-  if (list == nullptr) return false;
-
-  const String* function_name = nullptr;
-  Array& arguments_descriptor = Array::Handle(zone());
-  intptr_t num_args_checked;
-  ICData::RebindRule rebind_rule;
-
-  if (auto const call = inst->AsInstanceCall()) {
-    function_name = &call->function_name();
-    arguments_descriptor = call->GetArgumentsDescriptor();
-    num_args_checked = call->checked_argument_count();
-    rebind_rule = ICData::RebindRule::kInstance;
-  } else if (auto const call = inst->AsStaticCall()) {
-    function_name = &String::Handle(zone(), call->function().name());
-    arguments_descriptor = call->GetArgumentsDescriptor();
-    num_args_checked =
-        MethodRecognizer::NumArgsCheckedForStaticCall(call->function());
-    rebind_rule = ICData::RebindRule::kStatic;
-  } else {
-    StoreError(list, "unexpected instruction type for ICData");
-    return false;
-  }
-
-  auto type_ptr = &Object::null_abstract_type();
-  if (auto const type_sexp = list->ExtraLookupValue("receivers_static_type")) {
-    auto& type = AbstractType::ZoneHandle(zone());
-    if (!ParseAbstractType(type_sexp, &type)) return false;
-    type_ptr = &type;
-  }
-
-  ASSERT(parsed_function_ != nullptr);
-  auto& ic_data = ICData::ZoneHandle(
-      zone(), ICData::New(parsed_function_->function(), *function_name,
-                          arguments_descriptor, inst->deopt_id(),
-                          num_args_checked, rebind_rule, *type_ptr));
-
-  if (auto const is_mega_sexp =
-          CheckBool(list->ExtraLookupValue("is_megamorphic"))) {
-    ic_data.set_is_megamorphic(is_mega_sexp->value());
-  }
-
-  auto const class_table = thread()->isolate_group()->class_table();
-  GrowableArray<intptr_t> class_ids(zone(), 2);
-  for (intptr_t i = 1, n = list->Length(); i < n; i++) {
-    auto const entry = CheckList(Retrieve(list, i));
-    if (entry == nullptr) return false;
-    ASSERT(ic_data.NumArgsTested() == entry->Length());
-
-    intptr_t count = 0;
-    if (auto const count_sexp =
-            CheckInteger(entry->ExtraLookupValue("count"))) {
-      count = count_sexp->value();
-    }
-
-    auto& target = Function::ZoneHandle(zone());
-    if (!ParseDartValue(Retrieve(entry, "target"), &target)) return false;
-
-    // We can't use AddCheck for NumArgsTested < 2. We'll handle 0 here, and
-    // 1 after the for loop.
-    if (entry->Length() == 0) {
-      if (count != 0) {
-        StoreError(entry, "expected a zero count for no checked args");
-        return false;
-      }
-      ic_data = ICData::NewForStaticCall(parsed_function_->function(), target,
-                                         arguments_descriptor, inst->deopt_id(),
-                                         num_args_checked, rebind_rule);
-      continue;
-    }
-
-    class_ids.Clear();
-    for (intptr_t j = 0, num_cids = entry->Length(); j < num_cids; j++) {
-      auto const cid_sexp = CheckInteger(Retrieve(entry, j));
-      if (cid_sexp == nullptr) return false;
-      const intptr_t cid = cid_sexp->value();
-      // kObjectCid is a special case used for AddTarget() entries with
-      // a non-zero number of checked arguments.
-      if (cid != kObjectCid && !class_table->HasValidClassAt(cid)) {
-        StoreError(cid_sexp, "cid is not a valid class");
-        return false;
-      }
-      class_ids.Add(cid);
-    }
-
-    if (entry->Length() == 1) {
-      ic_data.AddReceiverCheck(class_ids.At(0), target, count);
-    } else {
-      ic_data.AddCheck(class_ids, target, count);
-    }
-  }
-
-  if (auto const call = inst->AsInstanceCall()) {
-    call->set_ic_data(const_cast<const ICData*>(&ic_data));
-  } else if (auto const call = inst->AsStaticCall()) {
-    call->set_ic_data(&ic_data);
-  }
-
-  return true;
-}
-
-Value* FlowGraphDeserializer::AddNewPendingValue(SExpression* sexp,
-                                                 intptr_t index,
-                                                 bool inherit_type) {
-  ASSERT(flow_graph_ != nullptr);
-  auto const value = new (zone()) Value(flow_graph_->constant_null());
-  ASSERT(!definition_map_.HasKey(index));
-  auto list = values_map_.LookupValue(index);
-  if (list == nullptr) {
-    list = new (zone()) ZoneGrowableArray<PendingValue>(zone(), 2);
-    values_map_.Insert(index, list);
-  }
-  list->Add({sexp, value, inherit_type});
-  return value;
-}
-
-bool FlowGraphDeserializer::FixPendingValues(intptr_t index, Definition* def) {
-  if (auto value_list = values_map_.LookupValue(index)) {
-    for (intptr_t i = 0; i < value_list->length(); i++) {
-      const auto& value_info = value_list->At(i);
-      auto const value = value_info.value;
-      const bool inherit_type = value_info.inherit_type;
-      value->BindTo(def);
-      if (!inherit_type) continue;
-      if (def->HasType()) {
-        value->reaching_type_ = def->Type();
-      } else {
-        StoreError(value_info.sexp, "value inherits type, but no type found");
-        return false;
-      }
-    }
-    values_map_.Remove(index);
-  }
-  return true;
-}
-
-BlockEntryInstr* FlowGraphDeserializer::FetchBlock(SExpSymbol* sym) {
-  if (sym == nullptr) return nullptr;
-  intptr_t block_id;
-  if (!ParseBlockId(sym, &block_id)) return nullptr;
-  auto const entry = block_map_.LookupValue(block_id);
-  if (entry == nullptr) {
-    StoreError(sym, "reference to undefined block");
-    return nullptr;
-  }
-  return entry;
-}
-
-#define BASE_CHECK_DEF(name, type)                                             \
-  SExp##name* FlowGraphDeserializer::Check##name(SExpression* sexp) {          \
-    if (sexp == nullptr) return nullptr;                                       \
-    if (!sexp->Is##name()) {                                                   \
-      StoreError(sexp, "expected " #name);                                     \
-      return nullptr;                                                          \
-    }                                                                          \
-    return sexp->As##name();                                                   \
-  }
-
-FOR_EACH_S_EXPRESSION(BASE_CHECK_DEF)
-
-#undef BASE_CHECK_DEF
-
-bool FlowGraphDeserializer::IsTag(SExpression* sexp, const char* label) {
-  auto const sym = CheckSymbol(sexp);
-  if (sym == nullptr) return false;
-  if (label != nullptr && !sym->Equals(label)) {
-    StoreError(sym, "expected symbol %s", label);
-    return false;
-  }
-  return true;
-}
-
-SExpList* FlowGraphDeserializer::CheckTaggedList(SExpression* sexp,
-                                                 const char* label) {
-  auto const list = CheckList(sexp);
-  const intptr_t tag_pos = 0;
-  if (!IsTag(Retrieve(list, tag_pos), label)) return nullptr;
-  return list;
-}
-
-void FlowGraphDeserializer::StoreError(SExpression* sexp,
-                                       const char* format,
-                                       ...) {
-  va_list args;
-  va_start(args, format);
-  const char* const message = OS::VSCreate(zone(), format, args);
-  va_end(args);
-  error_sexp_ = sexp;
-  error_message_ = message;
-}
-
-void FlowGraphDeserializer::ReportError() const {
-  ASSERT(error_sexp_ != nullptr);
-  ASSERT(error_message_ != nullptr);
-  OS::PrintErr("Unable to deserialize flow_graph: %s\n", error_message_);
-  OS::PrintErr("Error at S-expression %s\n", error_sexp_->ToCString(zone()));
-  OS::Abort();
-}
-
-}  // namespace dart
diff --git a/runtime/vm/compiler/backend/il_deserializer.h b/runtime/vm/compiler/backend/il_deserializer.h
deleted file mode 100644
index 5049850..0000000
--- a/runtime/vm/compiler/backend/il_deserializer.h
+++ /dev/null
@@ -1,421 +0,0 @@
-// Copyright (c) 2019, 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_DESERIALIZER_H_
-#define RUNTIME_VM_COMPILER_BACKEND_IL_DESERIALIZER_H_
-
-#if defined(DART_PRECOMPILED_RUNTIME)
-#error "AOT runtime should not use compiler sources (including header files)"
-#endif  // defined(DART_PRECOMPILED_RUNTIME)
-
-#include "platform/assert.h"
-
-#include "vm/allocation.h"
-#include "vm/compiler/backend/flow_graph.h"
-#include "vm/compiler/backend/il.h"
-#include "vm/compiler/backend/sexpression.h"
-#include "vm/compiler/compiler_pass.h"
-#include "vm/object.h"
-#include "vm/parser.h"
-#include "vm/thread.h"
-#include "vm/zone.h"
-
-namespace dart {
-
-// Deserializes FlowGraphs from S-expressions.
-class FlowGraphDeserializer : ValueObject {
- public:
-  // Adds to the given array all the instructions in the flow graph that are
-  // guaranteed not to be handled by the current implementation of the
-  // FlowGraphDeserializer. This way, we can filter out graphs that are
-  // guaranteed not to be deserializable before going through the round-trip
-  // serialization process.
-  //
-  // Note that there may be other reasons that the deserializer may fail on
-  // a given flow graph, so no new members of the array is necessary, but not
-  // sufficient, for a successful round-trip pass.
-  static void AllUnhandledInstructions(const FlowGraph* graph,
-                                       GrowableArray<Instruction*>* out);
-
-  // Takes the FlowGraph from [state] and runs it through the serializer
-  // and deserializer. If the deserializer successfully deserializes the
-  // graph, then the FlowGraph in [state] is replaced with the new one.
-  static void RoundTripSerialization(CompilerPassState* state);
-
-  FlowGraphDeserializer(Thread* thread,
-                        Zone* zone,
-                        SExpression* root,
-                        const ParsedFunction* pf = nullptr)
-      : thread_(ASSERT_NOTNULL(thread)),
-        zone_(ASSERT_NOTNULL(zone)),
-        root_sexp_(ASSERT_NOTNULL(root)),
-        parsed_function_(pf),
-        block_map_(zone),
-        definition_map_(zone),
-        values_map_(zone),
-        recursive_types_map_(zone),
-        pending_typeref_map_(zone),
-        array_type_args_(TypeArguments::Handle(zone)),
-        instance_class_(Class::Handle(zone)),
-        instance_field_(Field::Handle(zone)),
-        instance_fields_array_(Array::Handle(zone)),
-        instance_type_args_(TypeArguments::Handle(zone)),
-        name_class_(Class::Handle(zone)),
-        name_field_(Field::Handle(zone)),
-        name_function_(Function::Handle(zone)),
-        name_library_(Library::Handle(zone)),
-        type_class_(Class::Handle(zone)),
-        type_param_class_(Class::Handle(zone)),
-        tmp_string_(String::Handle(zone)) {
-    // See canonicalization comment in ParseDartValue as to why this is
-    // currently necessary.
-    ASSERT(thread->zone() == zone);
-  }
-
-  // Walks [root_sexp_] and constructs a new FlowGraph.
-  FlowGraph* ParseFlowGraph();
-
-  const char* error_message() const { return error_message_; }
-  SExpression* error_sexp() const { return error_sexp_; }
-
-  // Prints the current error information to stderr and aborts.
-  DART_NORETURN void ReportError() const;
-
- private:
-#define FOR_EACH_HANDLED_BLOCK_TYPE_IN_DESERIALIZER(M)                         \
-  M(FunctionEntry)                                                             \
-  M(GraphEntry)                                                                \
-  M(JoinEntry)                                                                 \
-  M(TargetEntry)
-
-#define FOR_EACH_HANDLED_INSTRUCTION_IN_DESERIALIZER(M)                        \
-  M(AllocateObject)                                                            \
-  M(AssertAssignable)                                                          \
-  M(AssertBoolean)                                                             \
-  M(BooleanNegate)                                                             \
-  M(Branch)                                                                    \
-  M(CheckNull)                                                                 \
-  M(CheckStackOverflow)                                                        \
-  M(Constant)                                                                  \
-  M(DebugStepCheck)                                                            \
-  M(Goto)                                                                      \
-  M(InstanceCall)                                                              \
-  M(LoadClassId)                                                               \
-  M(LoadField)                                                                 \
-  M(NativeCall)                                                                \
-  M(Parameter)                                                                 \
-  M(Return)                                                                    \
-  M(SpecialParameter)                                                          \
-  M(StaticCall)                                                                \
-  M(StoreInstanceField)                                                        \
-  M(StrictCompare)                                                             \
-  M(Throw)
-
-  // Helper methods for AllUnhandledInstructions.
-  static bool IsHandledInstruction(Instruction* inst);
-  static bool IsHandledConstant(const Object& obj);
-
-  // **GENERAL DESIGN NOTES FOR PARSING METHODS**
-  //
-  // For functions that take an SExpression or a subclass, they should return
-  // an error signal (false, nullptr, etc.) without changing the error state if
-  // passed in nullptr. This way, methods can be chained without intermediate
-  // checking.
-  //
-  // Also, for parsing methods for expressions that are known to be of a certain
-  // form, they will take the appropriate subclass of SExpression and assume
-  // that the form was already pre-checked by the caller. For forms that are
-  // tagged lists, this includes the fact that there is at least one element
-  // and the first element is a symbol. If the form can only have one possible
-  // tag, they also assume the tag has already been checked.
-
-  // Helper functions that do length/key exists checking and also check that
-  // the retrieved element is not nullptr. Notably, do not use these if the
-  // retrieved element is optional, to avoid changing the error state
-  // unnecessarily.
-  SExpression* Retrieve(SExpList* list, intptr_t index);
-  SExpression* Retrieve(SExpList* list, const char* key);
-
-  bool ParseConstantPool(SExpList* pool);
-  bool ParseEntries(SExpList* list);
-
-  using BlockWorklist = GrowableArray<intptr_t>;
-
-  // Starts parsing the contents of [list], where the blocks begin at position
-  // [pos] and [worklist] contains the blocks whose body instructions should
-  // be parsed first.
-  bool ParseBlocks(SExpList* list, intptr_t pos, BlockWorklist* worklist);
-
-  // Block parsing is split into two passes. This pass adds function entries
-  // to the flow graph and also parses initial definitions found in the Entries
-  // list. The block is added to the [block_map_] before returning.
-  BlockEntryInstr* ParseBlockHeader(SExpList* list,
-                                    intptr_t block_id,
-                                    SExpSymbol* tag);
-
-  // Expects [current_block_] to be set before calling.
-  bool ParseInitialDefinitions(SExpList* list);
-
-  // Expects [current_block_] to be set before calling.
-  // Takes the tagged list to parse and the index where parsing should start.
-  // Attempts to parse Phi definitions until the first non-Phi instruction.
-  bool ParsePhis(SExpList* list);
-
-  // Expects [current_block_] to be set before calling.
-  // Returns the position of the first non-Phi instruction in a block.
-  intptr_t SkipPhis(SExpList* list);
-
-  // Parses the deopt environment, Phi definitions for JoinEntrys, and the
-  // instructions in the body of the block. Adds the IDs of the block successors
-  // to the worklist, if any. [current_block_] and [pushed_stack_] must be set
-  // before calling.
-  bool ParseBlockContents(SExpList* list, BlockWorklist* worklist);
-
-  // Helper function used by ParseConstantPool, ParsePhis, and ParseDefinition.
-  // This handles all the extra information stored in (def ...) expressions,
-  // and also ensures the index of the definition is appropriately adjusted to
-  // match those found in the serialized form.
-  bool ParseDefinitionWithParsedBody(SExpList* list, Definition* def);
-
-  Definition* ParseDefinition(SExpList* list);
-  Instruction* ParseInstruction(SExpList* list);
-
-  struct EntryInfo {
-    intptr_t block_id;
-    intptr_t try_index;
-    intptr_t deopt_id;
-  };
-
-#define HANDLER_DECL(name)                                                     \
-  name##Instr* Deserialize##name(SExpList* list, const EntryInfo& info);
-
-  FOR_EACH_HANDLED_BLOCK_TYPE_IN_DESERIALIZER(HANDLER_DECL);
-
-#undef HANDLER_DECL
-
-  struct InstrInfo {
-    const intptr_t deopt_id;
-    const InstructionSource source;
-  };
-
-  enum HandledInstruction {
-#define HANDLED_INST_DECL(name) kHandled##name,
-    FOR_EACH_HANDLED_INSTRUCTION_IN_DESERIALIZER(HANDLED_INST_DECL)
-#undef HANDLED_INST_DECL
-    // clang-format off
-    kHandledInvalid = -1,
-    // clang-format on
-  };
-
-#define HANDLE_CASE(name)                                                      \
-  if (strcmp(tag->value(), #name) == 0) return kHandled##name;
-  HandledInstruction HandledInstructionForTag(SExpSymbol* tag) {
-    ASSERT(tag != nullptr);
-    FOR_EACH_HANDLED_INSTRUCTION_IN_DESERIALIZER(HANDLE_CASE)
-    return kHandledInvalid;
-  }
-#undef HANDLE_CASE
-
-#define HANDLER_DECL(name)                                                     \
-  name##Instr* Deserialize##name(SExpList* list, const InstrInfo& info);
-
-  FOR_EACH_HANDLED_INSTRUCTION_IN_DESERIALIZER(HANDLER_DECL);
-
-#undef HANDLER_DECL
-
-  // Common information parsed from call instruction S-expressions.
-  struct CallInfo : public ValueObject {
-    explicit CallInfo(Zone* zone) : argument_names(Array::ZoneHandle(zone)) {}
-
-    Array& argument_names;
-    intptr_t type_args_len = 0;
-    intptr_t args_len = 0;
-    InputsArray* inputs = nullptr;
-    CompileType* result_type = nullptr;
-    Code::EntryKind entry_kind = Code::EntryKind::kNormal;
-  };
-
-  // Helper function for parsing call instructions that returns a structure
-  // of information common to all calls.
-  bool ParseCallInfo(SExpList* call,
-                     CallInfo* out,
-                     intptr_t num_extra_inputs = 0);
-
-  // Parses [sexp] as a value form, that is, either the binding name for
-  // a definition as a symbol or the form (value <name> { ... }).
-  // If [allow_pending], then values for definitions not already in the
-  // [definition_map_] will be added to the [values_map_], otherwise,
-  // values for definitions not yet seen cause an error to be stored and
-  // nullptr to be returned.
-  Value* ParseValue(SExpression* sexp, bool allow_pending = true);
-  CompileType* ParseCompileType(SExpList* list);
-
-  // Parses [list] as an environment form: a list containing either binding
-  // names for definitions or a# for pushed arguments (where # is the depth
-  // of the argument from the top of the stack). Requires [pushed_stack_] to
-  // be set if any references to pushed arguments are found.
-  Environment* ParseEnvironment(SExpList* list);
-
-  // Parsing functions for which there are no good distinguished error
-  // values, so use out parameters and a boolean return instead.
-
-  // Parses a Dart value and returns a canonicalized result.
-  bool ParseDartValue(SExpression* sexp, Object* out);
-
-  // Canonicalizes and replaces the original contents of the handle pointed to
-  // by [inst] if [inst] is an Instance (if not, it trivially succeeds). The
-  // replacement happens whether successful or not. [sexp] is the SExpression
-  // to be used for error reporting.
-  bool CanonicalizeInstance(SExpression* sexp, Object* inst);
-
-  // Helper functions for ParseDartValue for parsing particular type of values.
-  // If necessary, they canonicalize the returned value, and so may be used
-  // directly by other code as well. Helpers that take SExpression* take either
-  // serialized constants or references to constant definitions.
-  //
-  // Due to particulars of operator=() on non-Object values, for a given X,
-  // ParseX takes Object* instead of X* for the out parameter.
-  bool ParseAbstractType(SExpression* sexp, Object* out);
-  bool ParseClass(SExpList* list, Object* out);
-  bool ParseClosure(SExpList* list, Object* out);
-  bool ParseField(SExpList* list, Object* out);
-  bool ParseFunction(SExpList* list, Object* out);
-  bool ParseSignature(SExpList* list, Object* out);
-  bool ParseArray(SExpList* list, Object* out);
-  bool ParseImmutableList(SExpList* list, Object* out);
-  bool ParseInstance(SExpList* list, Object* out);
-  bool ParseType(SExpression* sexp, Object* out);
-  bool ParseFunctionType(SExpList* list, Object* out);
-  bool ParseTypeParameter(SExpList* list, Object* out);
-  bool ParseTypeArguments(SExpression* sexp, Object* out);
-  bool ParseTypeRef(SExpList* list, Object* out);
-
-  bool ParseCanonicalName(SExpSymbol* sym, Object* out);
-
-  const Field& MayCloneField(const Field& field) const;
-  bool ParseSlot(SExpList* list, const Slot** out);
-  bool ParseRange(SExpList* list, Range* out);
-  bool ParseRangeBoundary(SExpression* sexp, RangeBoundary* out);
-
-  bool ParseBlockId(SExpSymbol* sym, intptr_t* out);
-  bool ParseSSATemp(SExpSymbol* sym, intptr_t* out);
-  bool ParseUse(SExpSymbol* sym, intptr_t* out);
-  bool ParseSymbolAsPrefixedInt(SExpSymbol* sym, char prefix, intptr_t* out);
-
-  bool ArePendingTypeRefs() const;
-
-  // Allocates a new ICData structure. [list] is the ICData S-expression, while
-  // [inst] is the Instruction generated from the instruction S-expression
-  // containing [list].
-  bool CreateICData(SExpList* list, Instruction* inst);
-
-  // Helper function for creating a placeholder value when the definition
-  // with index [i] has not yet been seen. If [inherit_type], then the type of
-  // the definition should be used as the reaching type for the use. [s] is used
-  // for any errors that occur when resolving the pending value.
-  Value* AddNewPendingValue(SExpression* s, intptr_t i, bool inherit_type);
-
-  // Helper function for rebinding values pending on this definition.
-  bool FixPendingValues(intptr_t index, Definition* def);
-
-  // Retrieves the block corresponding to the given block ID symbol from
-  // [block_map_]. Assumes all blocks have had their header parsed.
-  BlockEntryInstr* FetchBlock(SExpSymbol* sym);
-
-  // Utility functions for checking the shape of an S-expression.
-  // If these functions return nullptr for a non-null argument, they have the
-  // side effect of setting the stored error message.
-#define BASE_CHECK_DECL(name, type) SExp##name* Check##name(SExpression* sexp);
-  FOR_EACH_S_EXPRESSION(BASE_CHECK_DECL)
-#undef BASE_CHECK_DECL
-
-  // Checks whether [sexp] is a symbol with the given label.
-  bool IsTag(SExpression* sexp, const char* label);
-
-  // A version of CheckList that also checks that the list has at least one
-  // element and that the first element is a symbol. If [label] is non-null,
-  // then the initial symbol element is checked against it.
-  SExpList* CheckTaggedList(SExpression* sexp, const char* label = nullptr);
-
-  // Stores appropriate error information using the SExpression as the location
-  // and the rest of the arguments as an error message for the user.
-  void StoreError(SExpression* s, const char* fmt, ...) PRINTF_ATTRIBUTE(3, 4);
-
-  Thread* thread() const { return thread_; }
-  Zone* zone() const { return zone_; }
-
-  Thread* const thread_;
-  Zone* const zone_;
-  SExpression* const root_sexp_;
-  const ParsedFunction* parsed_function_;
-
-  FlowGraph* flow_graph_ = nullptr;
-  BlockEntryInstr* current_block_ = nullptr;
-  intptr_t max_block_id_ = -1;
-  intptr_t max_ssa_index_ = -1;
-
-  // Map from block IDs to blocks. Does not contain an entry for block 0
-  // (the graph entry), since it is only used at known points and is already
-  // available via [flow_graph_].
-  IntMap<BlockEntryInstr*> block_map_;
-
-  // Map from variable indexes to definitions.
-  IntMap<Definition*> definition_map_;
-
-  // Information needed to handle uses seen prior to their definitions.
-  struct PendingValue {
-    // SExpression used for error reporting.
-    SExpression* sexp;
-    // Value to be rebound once the right definition is found.
-    Value* value;
-    // Whether the type should inherit the type of the found definition.
-    bool inherit_type;
-  };
-
-  // Map from variable indices to lists of values. The list of values are
-  // values that were parsed prior to the corresponding definition being found.
-  IntMap<ZoneGrowableArray<PendingValue>*> values_map_;
-
-  // Map from hash values to SExpLists. This is used by ParseTypeRef to
-  // determine whether or not the recursive type it refers to is being currently
-  // built. The SExpList can be used to report hash collisions.
-  IntMap<SExpList*> recursive_types_map_;
-
-  // Map from hash values to arrays of TypeRefs. This is used by ParseType and
-  // ParseTypeRef to store and later fill in TypeRefs pending on the type being
-  // constructed. Since entries are added at the start of parsing recursive
-  // Type S-exps and removed before the resulting Type is successfully returned,
-  // this map should be empty outside of parsing recursive types.
-  IntMap<ZoneGrowableArray<TypeRef*>*> pending_typeref_map_;
-
-  // Temporary handles used by functions that are not re-entrant or where the
-  // handle is not live after the re-entrant call. Comments show which handles
-  // are expected to only be used within a single method.
-  TypeArguments& array_type_args_;     // ParseImmutableList
-  Class& instance_class_;              // ParseInstance
-  Field& instance_field_;              // ParseInstance
-  Array& instance_fields_array_;       // ParseInstance
-  TypeArguments& instance_type_args_;  // ParseInstance
-  Class& name_class_;                  // ParseCanonicalName
-  Field& name_field_;                  // ParseCanonicalName
-  Function& name_function_;            // ParseCanonicalName
-  Library& name_library_;              // ParseCanonicalName
-  Class& type_class_;                  // ParseType
-  Class& type_param_class_;            // ParseTypeParameter
-  // Uses of string handles tend to be immediate, so we only need one.
-  String& tmp_string_;
-
-  // Stores a message appropriate to surfacing to the user when an error
-  // occurs.
-  const char* error_message_ = nullptr;
-  // Stores the location of the deserialization error by containing the
-  // S-expression which caused the failure.
-  SExpression* error_sexp_ = nullptr;
-
-  DISALLOW_COPY_AND_ASSIGN(FlowGraphDeserializer);
-};
-
-}  // namespace dart
-
-#endif  // RUNTIME_VM_COMPILER_BACKEND_IL_DESERIALIZER_H_
diff --git a/runtime/vm/compiler/backend/il_serializer.cc b/runtime/vm/compiler/backend/il_serializer.cc
deleted file mode 100644
index 31fd469..0000000
--- a/runtime/vm/compiler/backend/il_serializer.cc
+++ /dev/null
@@ -1,1508 +0,0 @@
-// Copyright (c) 2019, 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/compiler/backend/flow_graph.h"
-#include "vm/compiler/backend/il.h"
-#include "vm/compiler/backend/range_analysis.h"
-#include "vm/compiler/method_recognizer.h"
-#include "vm/object_store.h"
-#include "vm/os.h"
-#include "vm/zone_text_buffer.h"
-
-namespace dart {
-
-DEFINE_FLAG(bool,
-            serialize_flow_graph_types,
-            true,
-            "Serialize inferred type information in flow graphs");
-
-DEFINE_FLAG(bool,
-            verbose_flow_graph_serialization,
-            false,
-            "Serialize extra information useful for debugging");
-
-DEFINE_FLAG(bool,
-            pretty_print_serialization,
-            false,
-            "Format serialized output nicely");
-
-DECLARE_FLAG(bool, populate_llvm_constant_pool);
-
-const char* const FlowGraphSerializer::initial_indent = "";
-
-FlowGraphSerializer::FlowGraphSerializer(Zone* zone,
-                                         const FlowGraph* flow_graph)
-    : flow_graph_(ASSERT_NOTNULL(flow_graph)),
-      zone_(zone),
-      object_store_(flow_graph->thread()->isolate_group()->object_store()),
-      open_recursive_types_(zone_),
-      llvm_constants_(
-          GrowableObjectArray::Handle(zone_,
-                                      object_store_->llvm_constant_pool())),
-      llvm_functions_(
-          GrowableObjectArray::Handle(zone_,
-                                      object_store_->llvm_function_pool())),
-      llvm_constant_map_(zone_, object_store_->llvm_constant_hash_table()),
-      llvm_index_(Smi::Handle(zone_)),
-      tmp_string_(String::Handle(zone_)),
-      array_type_args_((TypeArguments::Handle(zone_))),
-      closure_context_(Context::Handle(zone_)),
-      closure_function_(Function::Handle(zone_)),
-      closure_type_args_(TypeArguments::Handle(zone_)),
-      code_owner_(Object::Handle(zone_)),
-      context_parent_(Context::Handle(zone_)),
-      context_elem_(Object::Handle(zone_)),
-      function_type_args_(TypeArguments::Handle(zone_)),
-      ic_data_target_(Function::Handle(zone_)),
-      ic_data_type_(AbstractType::Handle(zone_)),
-      instance_field_(Field::Handle(zone_)),
-      instance_type_args_(TypeArguments::Handle(zone_)),
-      serialize_library_(Library::Handle(zone_)),
-      serialize_owner_(Class::Handle(zone_)),
-      serialize_parent_(Function::Handle(zone_)),
-      type_arguments_elem_(AbstractType::Handle(zone_)),
-      type_class_(Class::Handle(zone_)),
-      type_signature_(FunctionType::Handle(zone_)),
-      type_ref_type_(AbstractType::Handle(zone_)) {
-  // Double-check that the zone in the flow graph is a parent of the
-  // zone we'll be using for serialization.
-  ASSERT(flow_graph->zone()->ContainsNestedZone(zone));
-}
-
-FlowGraphSerializer::~FlowGraphSerializer() {
-  object_store_->set_llvm_constant_hash_table(llvm_constant_map_.Release());
-}
-
-void FlowGraphSerializer::SerializeToBuffer(Zone* zone,
-                                            const FlowGraph* flow_graph,
-                                            BaseTextBuffer* buffer) {
-  ASSERT(buffer != nullptr);
-  auto const sexp = SerializeToSExp(zone, flow_graph);
-  if (FLAG_pretty_print_serialization) {
-    sexp->SerializeTo(zone, buffer, initial_indent);
-  } else {
-    sexp->SerializeToLine(buffer);
-  }
-  buffer->AddString("\n\n");
-}
-
-SExpression* FlowGraphSerializer::SerializeToSExp(Zone* zone,
-                                                  const FlowGraph* flow_graph) {
-  FlowGraphSerializer serializer(zone, flow_graph);
-  return serializer.FlowGraphToSExp();
-}
-
-#define KIND_STR(name) #name,
-static const char* block_entry_kind_tags[FlowGraphSerializer::kNumEntryKinds] =
-    {FOR_EACH_BLOCK_ENTRY_KIND(KIND_STR)};
-#undef KIND_STR
-
-FlowGraphSerializer::BlockEntryKind FlowGraphSerializer::BlockEntryTagToKind(
-    SExpSymbol* tag) {
-  if (tag == nullptr) return kTarget;
-  auto const str = tag->value();
-  for (intptr_t i = 0; i < kNumEntryKinds; i++) {
-    auto const current = block_entry_kind_tags[i];
-    if (strcmp(str, current) == 0) return static_cast<BlockEntryKind>(i);
-  }
-  return kInvalid;
-}
-
-void FlowGraphSerializer::AddBool(SExpList* sexp, bool b) {
-  sexp->Add(new (zone()) SExpBool(b));
-}
-
-void FlowGraphSerializer::AddInteger(SExpList* sexp, intptr_t i) {
-  sexp->Add(new (zone()) SExpInteger(i));
-}
-
-void FlowGraphSerializer::AddString(SExpList* sexp, const char* cstr) {
-  sexp->Add(new (zone()) SExpString(cstr));
-}
-
-void FlowGraphSerializer::AddSymbol(SExpList* sexp, const char* cstr) {
-  sexp->Add(new (zone()) SExpSymbol(cstr));
-}
-
-void FlowGraphSerializer::AddExtraBool(SExpList* sexp,
-                                       const char* label,
-                                       bool b) {
-  sexp->AddExtra(label, new (zone()) SExpBool(b));
-}
-
-void FlowGraphSerializer::AddExtraInteger(SExpList* sexp,
-                                          const char* label,
-                                          intptr_t i) {
-  sexp->AddExtra(label, new (zone()) SExpInteger(i));
-}
-
-void FlowGraphSerializer::AddExtraString(SExpList* sexp,
-                                         const char* label,
-                                         const char* cstr) {
-  sexp->AddExtra(label, new (zone()) SExpString(cstr));
-}
-
-void FlowGraphSerializer::AddExtraSymbol(SExpList* sexp,
-                                         const char* label,
-                                         const char* cstr) {
-  sexp->AddExtra(label, new (zone()) SExpSymbol(cstr));
-}
-
-SExpression* FlowGraphSerializer::BlockIdToSExp(intptr_t block_id) {
-  return new (zone()) SExpSymbol(OS::SCreate(zone(), "B%" Pd "", block_id));
-}
-
-void FlowGraphSerializer::SerializeCanonicalName(BaseTextBuffer* b,
-                                                 const Object& obj) {
-  ASSERT(!obj.IsNull());
-  if (obj.IsFunction()) {
-    const auto& function = Function::Cast(obj);
-    tmp_string_ = function.name();
-    // We only want private keys removed, no other changes.
-    tmp_string_ = String::RemovePrivateKey(tmp_string_);
-    const char* function_name = tmp_string_.ToCString();
-    // If this function is an inner closure then the parent points to its
-    // containing function, which will also be part of the canonical name.
-    //
-    // We retrieve the owner before retrieving the parent function, as the
-    // inner closure chain may be arbitrarily deep and serialize_parent_ is
-    // passed in on recursive calls. When it is, then changing serialize_parent_
-    // to the parent function also changes the contents of obj and thus we'd
-    // no longer be able to retrieve the child function or its owner.
-    //
-    // This does mean that serialize_owner_ gets overwritten for each recursive
-    // call until we reach the end of the chain, but we only use its contents at
-    // the end of the chain anyway.
-    serialize_owner_ = function.Owner();
-    serialize_parent_ = function.parent_function();
-    if (!serialize_parent_.IsNull()) {
-      SerializeCanonicalName(b, serialize_parent_);
-    } else {
-      ASSERT(!serialize_owner_.IsNull());
-      SerializeCanonicalName(b, serialize_owner_);
-    }
-    b->Printf(":%s", function_name);
-  } else if (obj.IsClass()) {
-    const auto& cls = Class::Cast(obj);
-    tmp_string_ = cls.ScrubbedName();
-    const char* class_name = tmp_string_.ToCString();
-    serialize_library_ = cls.library();
-    if (!serialize_library_.IsNull()) {
-      SerializeCanonicalName(b, serialize_library_);
-    }
-    b->Printf(":%s", class_name);
-  } else if (obj.IsLibrary()) {
-    const Library& lib = Library::Cast(obj);
-    tmp_string_ = lib.url();
-    const char* lib_name = tmp_string_.ToCString();
-    if (lib_name[0] == '\0') return;
-    b->AddString(lib_name);
-  } else if (obj.IsField()) {
-    const auto& field = Field::Cast(obj);
-    tmp_string_ = field.UserVisibleName();
-    const char* field_name = tmp_string_.ToCString();
-    serialize_owner_ = field.Owner();
-    ASSERT(!serialize_owner_.IsNull());
-    SerializeCanonicalName(b, serialize_owner_);
-    b->Printf(".%s", field_name);
-  } else {
-    UNREACHABLE();
-  }
-}
-
-SExpression* FlowGraphSerializer::CanonicalNameToSExp(const Object& obj) {
-  ASSERT(!obj.IsNull());
-  ZoneTextBuffer b(zone_, 100);
-  SerializeCanonicalName(&b, obj);
-  return new (zone()) SExpSymbol(b.buffer());
-}
-
-SExpSymbol* FlowGraphSerializer::BlockEntryKindToTag(BlockEntryKind k) {
-  ASSERT(k >= 0 && k < kNumEntryKinds);
-  return new (zone()) SExpSymbol(block_entry_kind_tags[k]);
-}
-
-#define KIND_TAG(name) block_entry_kind_tags[k##name]
-SExpSymbol* FlowGraphSerializer::BlockEntryTag(const BlockEntryInstr* entry) {
-  if (entry == nullptr) return nullptr;
-  if (entry->IsGraphEntry()) {
-    return BlockEntryKindToTag(kGraph);
-  }
-  if (entry->IsOsrEntry()) {
-    return BlockEntryKindToTag(kOSR);
-  }
-  if (entry->IsCatchBlockEntry()) {
-    return BlockEntryKindToTag(kCatch);
-  }
-  if (entry->IsIndirectEntry()) {
-    return BlockEntryKindToTag(kIndirect);
-  }
-  if (entry->IsFunctionEntry()) {
-    if (entry == flow_graph()->graph_entry()->normal_entry()) {
-      return BlockEntryKindToTag(kNormal);
-    }
-    if (entry == flow_graph()->graph_entry()->unchecked_entry()) {
-      return BlockEntryKindToTag(kUnchecked);
-    }
-  }
-  if (entry->IsJoinEntry()) {
-    return BlockEntryKindToTag(kJoin);
-  }
-  return nullptr;
-}
-#undef KIND_TAG
-
-SExpression* FlowGraphSerializer::FunctionEntryToSExp(
-    const BlockEntryInstr* entry) {
-  if (entry == nullptr) return nullptr;
-  auto sexp = new (zone()) SExpList(zone());
-  sexp->Add(BlockEntryTag(entry));
-  sexp->Add(BlockIdToSExp(entry->block_id()));
-  if (auto const with_defs = entry->AsBlockEntryWithInitialDefs()) {
-    auto const initial_defs = with_defs->initial_definitions();
-    for (intptr_t i = 0; i < initial_defs->length(); i++) {
-      sexp->Add(initial_defs->At(i)->ToSExpression(this));
-    }
-  }
-
-  // Also include the extra info here, to avoid having to find the
-  // corresponding block to get it.
-  entry->BlockEntryInstr::AddExtraInfoToSExpression(sexp, this);
-
-  return sexp;
-}
-
-SExpression* FlowGraphSerializer::EntriesToSExp(const GraphEntryInstr* start) {
-  auto sexp = new (zone()) SExpList(zone());
-  AddSymbol(sexp, "Entries");
-  if (auto const normal = FunctionEntryToSExp(start->normal_entry())) {
-    sexp->Add(normal);
-  }
-  if (auto const unchecked = FunctionEntryToSExp(start->unchecked_entry())) {
-    sexp->Add(unchecked);
-  }
-  if (auto const osr = FunctionEntryToSExp(start->osr_entry())) {
-    sexp->Add(osr);
-  }
-  for (intptr_t i = 0; i < start->catch_entries().length(); i++) {
-    sexp->Add(FunctionEntryToSExp(start->catch_entries().At(i)));
-  }
-  for (intptr_t i = 0; i < start->indirect_entries().length(); i++) {
-    sexp->Add(FunctionEntryToSExp(start->indirect_entries().At(i)));
-  }
-  return sexp;
-}
-
-SExpression* FlowGraphSerializer::FlowGraphToSExp() {
-  auto const start = flow_graph()->graph_entry();
-  auto const sexp = new (zone()) SExpList(zone());
-  AddSymbol(sexp, "FlowGraph");
-  sexp->Add(CanonicalNameToSExp(flow_graph()->function()));
-  AddExtraInteger(sexp, "deopt_id", start->deopt_id());
-  if (start->env() != nullptr) {
-    sexp->AddExtra("env", start->env()->ToSExpression(this));
-  }
-  if (start->IsCompiledForOsr()) {
-    AddExtraInteger(sexp, "osr_id", start->osr_id());
-  }
-  if (auto const constants = ConstantPoolToSExp(start)) {
-    sexp->Add(constants);
-  }
-  sexp->Add(EntriesToSExp(start));
-  auto& block_order = flow_graph()->reverse_postorder();
-  // Skip the first block, which will be the graph entry block (B0). We
-  // output all its information as part of the function expression, so it'll
-  // just show up as an empty block here.
-  ASSERT(block_order[0]->IsGraphEntry());
-  for (intptr_t i = 1; i < block_order.length(); ++i) {
-    sexp->Add(block_order[i]->ToSExpression(this));
-  }
-  if (FLAG_populate_llvm_constant_pool) {
-    auto const new_index = llvm_functions_.Length();
-    llvm_functions_.Add(flow_graph_->function());
-    AddExtraInteger(sexp, "llvm_index", new_index);
-  }
-  return sexp;
-}
-
-SExpression* FlowGraphSerializer::UseToSExp(const Definition* definition) {
-  ASSERT(definition != nullptr);
-  ASSERT(definition->HasSSATemp() || definition->HasTemp());
-  if (definition->HasSSATemp()) {
-    const intptr_t temp_index = definition->ssa_temp_index();
-    const auto name_cstr = OS::SCreate(zone(), "v%" Pd "", temp_index);
-    if (definition->HasPairRepresentation()) {
-      auto sexp = new (zone()) SExpList(zone());
-      AddSymbol(sexp, name_cstr);
-      AddSymbol(sexp, OS::SCreate(zone(), "v%" Pd "", temp_index + 1));
-      return sexp;
-    } else {
-      return new (zone()) SExpSymbol(name_cstr);
-    }
-  } else if (definition->HasTemp()) {
-    const intptr_t temp_index = definition->temp_index();
-    return new (zone()) SExpSymbol(OS::SCreate(zone(), "t%" Pd "", temp_index));
-  }
-  UNREACHABLE();
-}
-
-SExpression* FlowGraphSerializer::ClassToSExp(const Class& cls) {
-  if (cls.IsNull()) return nullptr;
-  auto sexp = new (zone()) SExpList(zone());
-  AddSymbol(sexp, "Class");
-  AddInteger(sexp, cls.id());
-  if (FLAG_verbose_flow_graph_serialization) {
-    sexp->AddExtra("name", CanonicalNameToSExp(cls));
-    // Currently, AbstractTypeToSExp assumes that serializing a class cannot
-    // re-enter it. If we make that possible by serializing parts of a class
-    // that can contain AbstractTypes, especially types that are not type
-    // parameters or type references, fix AbstractTypeToSExp appropriately.
-  }
-  return sexp;
-}
-
-static bool ShouldSerializeType(CompileType* type) {
-  return (FLAG_verbose_flow_graph_serialization ||
-          FLAG_serialize_flow_graph_types) &&
-         type != nullptr;
-}
-
-SExpression* FlowGraphSerializer::FieldToSExp(const Field& field) {
-  if (field.IsNull()) return nullptr;
-  auto sexp = new (zone()) SExpList(zone());
-  AddSymbol(sexp, "Field");
-  sexp->Add(CanonicalNameToSExp(field));
-  CompileType t(field.is_nullable(), field.guarded_cid(), nullptr);
-  if (ShouldSerializeType(&t)) {
-    sexp->AddExtra("type", t.ToSExpression(this));
-  }
-  return sexp;
-}
-
-SExpression* FlowGraphSerializer::AbstractTypeToSExp(const AbstractType& t) {
-  if (t.IsNull()) return nullptr;
-  ASSERT(t.IsFinalized());
-  auto sexp = new (zone()) SExpList(zone());
-  if (t.IsTypeParameter()) {
-    const auto& param = TypeParameter::Cast(t);
-    AddSymbol(sexp, "TypeParameter");
-    AddExtraInteger(sexp, "cid", param.parameterized_class_id());
-    AddExtraInteger(sexp, "base", param.base());
-    AddExtraInteger(sexp, "index", param.index());
-    tmp_string_ = param.name();
-    AddSymbol(sexp, tmp_string_.ToCString());
-    // TODO(regis): bound, default argument, flags, nullability, hash.
-    return sexp;
-  }
-  if (t.IsTypeRef()) {
-    const auto& ref = TypeRef::Cast(t);
-    AddSymbol(sexp, "TypeRef");
-    type_ref_type_ = ref.type();
-    auto const hash = type_ref_type_.Hash();
-    // Check to see if this is a TypeRef to a type we're currently serializing.
-    // If it is not, then we need to serialize the underlying type, as it
-    // otherwise won't be available when deserializing.
-    auto const open_type = open_recursive_types_.LookupValue(hash);
-    if (open_type == nullptr) {
-      // Allocate a new handle as we may re-enter the TypeRef branch.
-      auto& type = AbstractType::Handle(zone(), ref.type());
-      sexp->Add(AbstractTypeToSExp(type));
-      // If we serialized the referrent, then we don't need this information,
-      // but it may be useful for debugging so add it in verbose mode.
-      if (FLAG_verbose_flow_graph_serialization) {
-        AddExtraInteger(sexp, "hash", hash);
-      }
-    } else {
-      // Make sure we didn't have a hash collision.
-      ASSERT(open_type->Equals(type_ref_type_));
-      AddExtraInteger(sexp, "hash", hash);
-    }
-    if (FLAG_verbose_flow_graph_serialization) {
-      AddExtraString(sexp, "type", type_ref_type_.ToCString());
-    }
-    return sexp;
-  }
-  // We want to check for the type being recursive before we may serialize
-  // any sub-parts that include possible TypeRefs to this type.
-  const bool is_recursive = t.IsRecursive();
-  intptr_t hash = 0;
-  if (is_recursive) {
-    hash = t.Hash();
-    AddExtraInteger(sexp, "hash", hash);
-    open_recursive_types_.Insert(hash, &t);
-  }
-  if (t.IsFunctionType()) {
-    const auto& sig = FunctionType::Handle(zone(), FunctionType::Cast(t).ptr());
-    AddSymbol(sexp, "FunctionType");
-    function_type_args_ = sig.type_parameters();
-    if (auto const ta_sexp = NonEmptyTypeArgumentsToSExp(function_type_args_)) {
-      sexp->AddExtra("type_params", ta_sexp);
-    }
-    auto& type = AbstractType::Handle(zone(), sig.result_type());
-    sexp->AddExtra("result_type", AbstractTypeToSExp(type));
-    auto& parameter_types = Array::Handle(zone(), sig.parameter_types());
-    sexp->AddExtra("parameter_types", ArrayToSExp(parameter_types));
-    auto& parameter_names = Array::Handle(zone(), sig.parameter_names());
-    sexp->AddExtra("parameter_names", ArrayToSExp(parameter_names));
-    AddExtraInteger(sexp, "packed_fields", sig.packed_fields());
-    // If we were parsing a recursive type, we're now done building it, so
-    // remove it from the open recursive types.
-    if (is_recursive) open_recursive_types_.Remove(hash);
-    return sexp;
-  }
-  ASSERT(t.IsType());
-  AddSymbol(sexp, "Type");
-  const auto& type = Type::Cast(t);
-  if (type.HasTypeClass()) {
-    type_class_ = type.type_class();
-    // This avoids re-entry as long as serializing a class doesn't involve
-    // serializing concrete (non-parameter, non-reference) types.
-    sexp->Add(DartValueToSExp(type_class_));
-  } else {
-    // TODO(dartbug.com/36882): Actually structure non-class types instead of
-    // just printing out this version.
-    AddExtraString(sexp, "name", type.ToCString());
-  }
-  // Since type arguments may themselves be instantiations of generic
-  // types, we may call back into this function in the middle of printing
-  // the TypeArguments and so we must allocate a fresh handle here.
-  const auto& args = TypeArguments::Handle(zone(), type.arguments());
-  if (auto const args_sexp = NonEmptyTypeArgumentsToSExp(args)) {
-    sexp->AddExtra("type_args", args_sexp);
-  }
-  // If we were parsing a recursive type, we're now done building it, so
-  // remove it from the open recursive types.
-  if (is_recursive) open_recursive_types_.Remove(hash);
-  return sexp;
-}
-
-SExpression* FlowGraphSerializer::CodeToSExp(const Code& code) {
-  if (code.IsNull()) return nullptr;
-  auto sexp = new (zone()) SExpList(zone());
-  AddSymbol(sexp, "Code");
-  if (code.IsStubCode()) {
-    AddSymbol(sexp, StubCode::NameOfStub(code.EntryPoint()));
-    if (FLAG_verbose_flow_graph_serialization) {
-      AddExtraSymbol(sexp, "kind", "stub");
-    }
-    return sexp;
-  }
-  code_owner_ = code.owner();
-  if (!code_owner_.IsNull() && FLAG_verbose_flow_graph_serialization) {
-    if (code_owner_.IsClass()) {
-      AddExtraSymbol(sexp, "kind", "allocate");
-    } else if (code_owner_.IsAbstractType()) {
-      AddExtraSymbol(sexp, "kind", "type_test");
-    } else {
-      ASSERT(code_owner_.IsFunction());
-      AddExtraSymbol(sexp, "kind", "function");
-    }
-  }
-  sexp->Add(DartValueToSExp(code_owner_));
-  return sexp;
-}
-
-SExpression* FlowGraphSerializer::TypeArgumentsToSExp(const TypeArguments& ta) {
-  if (ta.IsNull()) return nullptr;
-  auto sexp = new (zone()) SExpList(zone());
-  AddSymbol(sexp, "TypeArguments");
-  for (intptr_t i = 0; i < ta.Length(); i++) {
-    type_arguments_elem_ = ta.TypeAt(i);
-    sexp->Add(DartValueToSExp(type_arguments_elem_));
-  }
-  if (FLAG_verbose_flow_graph_serialization && ta.IsRecursive()) {
-    AddExtraInteger(sexp, "hash", ta.Hash());
-  }
-  return sexp;
-}
-
-SExpression* FlowGraphSerializer::InstanceToSExp(const Instance& inst) {
-  if (inst.IsNull()) return nullptr;
-
-  // Since InstanceToSExp may use ObjectToSExp (via DartValueToSExp) for field
-  // values that aren't entries in the constant pool, and ObjectToSExp may
-  // re-enter InstanceToSExp, allocate fresh handles here for the argument to
-  // DartValueToSExp and other handles that are live across the call.
-  const auto& instance_class = Class::Handle(zone(), inst.clazz());
-  const auto& instance_fields_array =
-      Array::Handle(zone(), instance_class.fields());
-  auto& instance_field_value = Object::Handle(zone());
-
-  auto const sexp = new (zone()) SExpList(zone());
-  AddSymbol(sexp, "Instance");
-  AddInteger(sexp, instance_class.id());
-  auto const fields = new (zone()) SExpList(zone());
-  AddSymbol(fields, "Fields");
-  for (intptr_t i = 0; i < instance_fields_array.Length(); i++) {
-    instance_field_ = Field::RawCast(instance_fields_array.At(i));
-    // We don't need to serialize static fields, since they're shared by
-    // all instances.
-    if (instance_field_.is_static()) continue;
-    // We should only be getting const instances, which means that we
-    // should only see final instance fields.
-    ASSERT(instance_field_.is_final());
-    tmp_string_ = instance_field_.UserVisibleName();
-    auto const label = tmp_string_.ToCString();
-    instance_field_value = inst.GetField(instance_field_);
-    fields->AddExtra(label, DartValueToSExp(instance_field_value));
-  }
-  if (fields->ExtraLength() != 0 || FLAG_verbose_flow_graph_serialization) {
-    sexp->Add(fields);
-  }
-  if (instance_class.IsGeneric()) {
-    instance_type_args_ = inst.GetTypeArguments();
-    if (auto const args = NonEmptyTypeArgumentsToSExp(instance_type_args_)) {
-      sexp->AddExtra("type_args", args);
-    }
-  }
-  if (FLAG_verbose_flow_graph_serialization) {
-    AddExtraInteger(sexp, "size", inst.InstanceSize());
-    // We know the following won't call back into InstanceToSExp because we're
-    // providing it a class.
-    if (auto const cls = DartValueToSExp(instance_class)) {
-      sexp->AddExtra("class", cls);
-    }
-  }
-  return sexp;
-}
-
-SExpression* FlowGraphSerializer::FunctionToSExp(const Function& func) {
-  if (func.IsNull()) return nullptr;
-  auto const sexp = new (zone()) SExpList(zone());
-  AddSymbol(sexp, "Function");
-  sexp->Add(CanonicalNameToSExp(func));
-  if (func.IsRecognized()) {
-    AddExtraSymbol(sexp, "recognized",
-                   MethodRecognizer::KindToCString(func.recognized_kind()));
-  }
-  if (func.is_native()) {
-    tmp_string_ = func.native_name();
-    if (!tmp_string_.IsNull()) {
-      AddExtraSymbol(sexp, "native_name", tmp_string_.ToCString());
-    }
-  }
-  if (func.kind() != UntaggedFunction::Kind::kRegularFunction ||
-      FLAG_verbose_flow_graph_serialization) {
-    AddExtraSymbol(sexp, "kind", UntaggedFunction::KindToCString(func.kind()));
-  }
-  function_type_args_ = func.type_parameters();
-  if (auto const ta_sexp = NonEmptyTypeArgumentsToSExp(function_type_args_)) {
-    sexp->AddExtra("type_args", ta_sexp);
-  }
-  return sexp;
-}
-
-SExpression* FlowGraphSerializer::ImmutableListToSExp(const Array& arr) {
-  if (arr.IsNull()) return nullptr;
-  // We should only be getting immutable lists when serializing Dart values
-  // in flow graphs.
-  ASSERT(arr.IsImmutable());
-  auto sexp = new (zone()) SExpList(zone());
-  AddSymbol(sexp, "ImmutableList");
-  // We allocate a new Object handle to use for the calls to DartValueToSExp
-  // in case any Array elements contain non-constant-pool, non-empty Arrays.
-  auto& array_elem = Object::Handle(zone());
-  for (intptr_t i = 0; i < arr.Length(); i++) {
-    array_elem = arr.At(i);
-    sexp->Add(DartValueToSExp(array_elem));
-  }
-  array_type_args_ = arr.GetTypeArguments();
-  if (auto const type_args_sexp = TypeArgumentsToSExp(array_type_args_)) {
-    sexp->AddExtra("type_args", type_args_sexp);
-  }
-  return sexp;
-}
-
-SExpression* FlowGraphSerializer::ArrayToSExp(const Array& arr) {
-  if (arr.IsNull()) return nullptr;
-  auto sexp = new (zone()) SExpList(zone());
-  AddSymbol(sexp, "Array");
-  auto& array_elem = Object::Handle(zone());
-  for (intptr_t i = 0; i < arr.Length(); i++) {
-    array_elem = arr.At(i);
-    sexp->Add(DartValueToSExp(array_elem));
-  }
-  return sexp;
-}
-
-SExpression* FlowGraphSerializer::ClosureToSExp(const Closure& c) {
-  if (c.IsNull()) return nullptr;
-  auto sexp = new (zone()) SExpList(zone());
-  AddSymbol(sexp, "Closure");
-  closure_function_ = c.function();
-  if (auto const func = FunctionToSExp(closure_function_)) {
-    sexp->Add(func);
-  }
-  closure_context_ = c.context();
-  if (auto const context = ContextToSExp(closure_context_)) {
-    sexp->AddExtra("context", context);
-  }
-  closure_type_args_ = c.function_type_arguments();
-  if (auto const type_args = NonEmptyTypeArgumentsToSExp(closure_type_args_)) {
-    sexp->AddExtra("func_type_args", type_args);
-  }
-  closure_type_args_ = c.instantiator_type_arguments();
-  if (auto const type_args = NonEmptyTypeArgumentsToSExp(closure_type_args_)) {
-    sexp->AddExtra("inst_type_args", type_args);
-  }
-  closure_type_args_ = c.delayed_type_arguments();
-  if (auto const type_args = NonEmptyTypeArgumentsToSExp(closure_type_args_)) {
-    sexp->AddExtra("delayed_type_args", type_args);
-  }
-  return sexp;
-}
-
-SExpression* FlowGraphSerializer::ContextToSExp(const Context& c) {
-  if (c.IsNull()) return nullptr;
-  auto sexp = new (zone()) SExpList(zone());
-  AddSymbol(sexp, "Context");
-  for (intptr_t i = 0; i < c.num_variables(); i++) {
-    context_elem_ = c.At(i);
-    auto const elem_sexp = DartValueToSExp(context_elem_);
-    if (elem_sexp == nullptr) return nullptr;
-    sexp->Add(elem_sexp);
-  }
-  context_parent_ = c.parent();
-  if (auto const parent_sexp = ContextToSExp(context_parent_)) {
-    sexp->AddExtra("parent", parent_sexp);
-  }
-  return sexp;
-}
-
-SExpression* FlowGraphSerializer::ObjectToSExp(const Object& dartval) {
-  if (dartval.IsNull()) {
-    return new (zone()) SExpSymbol("null");
-  }
-  if (dartval.ptr() == Object::sentinel().ptr()) {
-    return new (zone()) SExpSymbol("sentinel");
-  }
-  if (dartval.IsString()) {
-    return new (zone()) SExpString(dartval.ToCString());
-  }
-  if (dartval.IsSmi()) {
-    return new (zone()) SExpInteger(Smi::Cast(dartval).Value());
-  }
-  if (dartval.IsMint()) {
-    return new (zone()) SExpInteger(Mint::Cast(dartval).value());
-  }
-  if (dartval.IsBool()) {
-    return new (zone()) SExpBool(Bool::Cast(dartval).value());
-  }
-  if (dartval.IsDouble()) {
-    return new (zone()) SExpDouble(Double::Cast(dartval).value());
-  }
-  if (dartval.IsField()) {
-    return FieldToSExp(Field::Cast(dartval));
-  }
-  if (dartval.IsClass()) {
-    return ClassToSExp(Class::Cast(dartval));
-  }
-  if (dartval.IsTypeArguments()) {
-    return TypeArgumentsToSExp(TypeArguments::Cast(dartval));
-  }
-  if (dartval.IsCode()) {
-    return CodeToSExp(Code::Cast(dartval));
-  }
-  if (dartval.IsArray()) {
-    return ImmutableListToSExp(Array::Cast(dartval));
-  }
-  if (dartval.IsFunction()) {
-    return FunctionToSExp(Function::Cast(dartval));
-  }
-  if (dartval.IsClosure()) {
-    return ClosureToSExp(Closure::Cast(dartval));
-  }
-  if (dartval.IsAbstractType()) {
-    return AbstractTypeToSExp(AbstractType::Cast(dartval));
-  }
-  ASSERT(dartval.IsInstance());
-  return InstanceToSExp(Instance::Cast(dartval));
-}
-
-SExpression* FlowGraphSerializer::DartValueToSExp(const Object& obj) {
-  if (auto const def = flow_graph()->GetExistingConstant(obj)) {
-    ASSERT(def->IsDefinition());
-    return UseToSExp(def->AsDefinition());
-  }
-  return ObjectToSExp(obj);
-}
-
-SExpression* FlowGraphSerializer::NonEmptyTypeArgumentsToSExp(
-    const TypeArguments& ta) {
-  if (ta.IsNull() || ta.Length() == 0) return nullptr;
-  return DartValueToSExp(ta);
-}
-
-SExpression* FlowGraphSerializer::ConstantPoolToSExp(
-    const GraphEntryInstr* start) {
-  auto const initial_defs = start->initial_definitions();
-  if (initial_defs == nullptr || initial_defs->is_empty()) return nullptr;
-  auto constant_list = new (zone()) SExpList(zone());
-  AddSymbol(constant_list, "Constants");
-  for (intptr_t i = 0; i < initial_defs->length(); i++) {
-    ASSERT(initial_defs->At(i)->IsConstant());
-    auto const definition = initial_defs->At(i)->AsDefinition();
-    auto elem = new (zone()) SExpList(zone());
-    AddSymbol(elem, "def");
-    elem->Add(UseToSExp(definition));
-    // Use ObjectToSExp here, not DartValueToSExp!
-    const auto& value = definition->AsConstant()->value();
-    elem->Add(ObjectToSExp(value));
-    AddDefinitionExtraInfoToSExp(definition, elem);
-    // Only add constants to the LLVM constant pool that are actually used in
-    // the flow graph.
-    if (FLAG_populate_llvm_constant_pool && definition->HasUses()) {
-      auto const pool_len = llvm_constants_.Length();
-      llvm_index_ = Smi::New(pool_len);
-      llvm_index_ ^= llvm_constant_map_.InsertOrGetValue(value, llvm_index_);
-      if (llvm_index_.Value() == pool_len) {
-        llvm_constants_.Add(value);
-      }
-      AddExtraInteger(elem, "llvm_index", llvm_index_.Value());
-    }
-    constant_list->Add(elem);
-  }
-  return constant_list;
-}
-
-SExpression* Instruction::ToSExpression(FlowGraphSerializer* s) const {
-  auto sexp = new (s->zone()) SExpList(s->zone());
-  s->AddSymbol(sexp, DebugName());
-  AddOperandsToSExpression(sexp, s);
-  AddExtraInfoToSExpression(sexp, s);
-  return sexp;
-}
-
-SExpression* BlockEntryInstr::ToSExpression(FlowGraphSerializer* s) const {
-  auto sexp = new (s->zone()) SExpList(s->zone());
-  s->AddSymbol(sexp, "Block");
-  sexp->Add(s->BlockIdToSExp(block_id()));
-  AddOperandsToSExpression(sexp, s);
-  AddExtraInfoToSExpression(sexp, s);
-  return sexp;
-}
-
-void BlockEntryInstr::AddExtraInfoToSExpression(SExpList* sexp,
-                                                FlowGraphSerializer* s) const {
-  Instruction::AddExtraInfoToSExpression(sexp, s);
-  if (try_index() != kInvalidTryIndex) {
-    s->AddExtraInteger(sexp, "try_index", try_index());
-  }
-  if (auto const entry_tag = s->BlockEntryTag(this)) {
-    sexp->AddExtra("block_type", entry_tag);
-  }
-  if (FLAG_verbose_flow_graph_serialization) {
-    if (PredecessorCount() > 0) {
-      auto const preds = new (s->zone()) SExpList(s->zone());
-      for (intptr_t i = 0; i < PredecessorCount(); i++) {
-        preds->Add(s->BlockIdToSExp(PredecessorAt(i)->block_id()));
-      }
-      sexp->AddExtra("predecessors", preds);
-    }
-  }
-}
-
-void BlockEntryInstr::AddOperandsToSExpression(SExpList* sexp,
-                                               FlowGraphSerializer* s) const {
-  for (const auto* inst = next_; inst != nullptr; inst = inst->next_) {
-    sexp->Add(inst->ToSExpression(s));
-  }
-}
-
-void JoinEntryInstr::AddOperandsToSExpression(SExpList* sexp,
-                                              FlowGraphSerializer* s) const {
-  if (auto phi_list = phis()) {
-    for (intptr_t i = 0; i < phi_list->length(); i++) {
-      sexp->Add(phi_list->At(i)->ToSExpression(s));
-    }
-  }
-  BlockEntryInstr::AddOperandsToSExpression(sexp, s);
-}
-
-void Instruction::AddOperandsToSExpression(SExpList* sexp,
-                                           FlowGraphSerializer* s) const {
-  for (intptr_t i = 0; i < InputCount(); ++i) {
-    if (InputAt(i) == nullptr) continue;
-    sexp->Add(InputAt(i)->ToSExpression(s));
-  }
-}
-
-void Instruction::AddExtraInfoToSExpression(SExpList* sexp,
-                                            FlowGraphSerializer* s) const {
-  if (GetDeoptId() != DeoptId::kNone) {
-    s->AddExtraInteger(sexp, "deopt_id", GetDeoptId());
-  }
-  if (env() != nullptr) {
-    sexp->AddExtra("env", env()->ToSExpression(s));
-  }
-  if (!token_pos().IsNoSource()) {
-    s->AddExtraInteger(sexp, "token_pos", token_pos().Serialize());
-  }
-  if (has_inlining_id()) {
-    s->AddExtraInteger(sexp, "inlining_id", inlining_id());
-  }
-}
-
-SExpression* Range::ToSExpression(FlowGraphSerializer* s) {
-  auto const sexp = new (s->zone()) SExpList(s->zone());
-  s->AddSymbol(sexp, "Range");
-  sexp->Add(min_.ToSExpression(s));
-  if (!max_.Equals(min_)) sexp->Add(max_.ToSExpression(s));
-  return sexp;
-}
-
-SExpression* RangeBoundary::ToSExpression(FlowGraphSerializer* s) {
-  switch (kind_) {
-    case kSymbol: {
-      auto const sexp = new (s->zone()) SExpList(s->zone());
-      sexp->Add(s->UseToSExp(symbol()));
-      if (offset() != 0) {
-        s->AddExtraInteger(sexp, "offset", offset());
-      }
-      return sexp;
-    }
-    case kConstant:
-      return new (s->zone()) SExpInteger(value_);
-    default:
-      return new (s->zone()) SExpSymbol(RangeBoundary::KindToCString(kind_));
-  }
-}
-
-bool FlowGraphSerializer::HasDefinitionExtraInfo(const Definition* def) {
-  return ShouldSerializeType(def->type_) || def->range() != nullptr;
-}
-
-void FlowGraphSerializer::AddDefinitionExtraInfoToSExp(const Definition* def,
-                                                       SExpList* sexp) {
-  // Type() isn't a const method as it can cause changes to the type_
-  // field, so access type_ directly instead.
-  if (ShouldSerializeType(def->type_)) {
-    sexp->AddExtra("type", def->type_->ToSExpression(this));
-  }
-  if (def->range() != nullptr) {
-    sexp->AddExtra("range", def->range()->ToSExpression(this));
-  }
-}
-
-SExpression* Definition::ToSExpression(FlowGraphSerializer* s) const {
-  // If we don't have a temp index, then this is a Definition that has no
-  // usable result.
-  const bool binds_name = HasSSATemp() || HasTemp();
-  // Don't serialize non-binding definitions as definitions unless we either
-  // have Definition-specific extra info or we're in verbose mode.
-  if (!binds_name && !FLAG_verbose_flow_graph_serialization &&
-      !s->HasDefinitionExtraInfo(this)) {
-    return Instruction::ToSExpression(s);
-  }
-  auto sexp = new (s->zone()) SExpList(s->zone());
-  s->AddSymbol(sexp, "def");
-  if (binds_name) {
-    sexp->Add(s->UseToSExp(this));
-  } else {
-    // Since there is Definition-specific extra info to serialize, we use "_"
-    // as the bound name, which lets the deserializer know the result is unused.
-    s->AddSymbol(sexp, "_");
-  }
-  // Add only Definition-specific extra info to this form. Any extra info
-  // that is Instruction-specific or specific to the actual instruction type is
-  // added to the nested instruction form.
-  s->AddDefinitionExtraInfoToSExp(this, sexp);
-  sexp->Add(Instruction::ToSExpression(s));
-  return sexp;
-}
-
-void AssertAssignableInstr::AddExtraInfoToSExpression(
-    SExpList* sexp,
-    FlowGraphSerializer* s) const {
-  Instruction::AddExtraInfoToSExpression(sexp, s);
-  sexp->AddExtra("name", s->DartValueToSExp(dst_name()));
-}
-
-void ConstantInstr::AddOperandsToSExpression(SExpList* sexp,
-                                             FlowGraphSerializer* s) const {
-  sexp->Add(s->DartValueToSExp(value()));
-}
-
-void BranchInstr::AddOperandsToSExpression(SExpList* sexp,
-                                           FlowGraphSerializer* s) const {
-  sexp->Add(comparison()->ToSExpression(s));
-  sexp->Add(s->BlockIdToSExp(true_successor()->block_id()));
-  sexp->Add(s->BlockIdToSExp(false_successor()->block_id()));
-}
-
-void ParameterInstr::AddOperandsToSExpression(SExpList* sexp,
-                                              FlowGraphSerializer* s) const {
-  s->AddInteger(sexp, index());
-  s->AddExtraInteger(sexp, "param_offset", param_offset());
-  s->AddExtraSymbol(sexp, "representation",
-                    Location::RepresentationToCString(representation()));
-}
-
-void SpecialParameterInstr::AddOperandsToSExpression(
-    SExpList* sexp,
-    FlowGraphSerializer* s) const {
-  ASSERT(kind() < SpecialParameterInstr::kNumKinds);
-  s->AddSymbol(sexp, KindToCString(kind()));
-}
-
-SExpression* FlowGraphSerializer::LocalVariableToSExp(const LocalVariable& v) {
-  auto const sexp = new (zone()) SExpList(zone());
-  AddSymbol(sexp, "LocalVariable");
-  if (!v.name().IsNull()) {
-    AddSymbol(sexp, v.name().ToCString());
-  }
-  if (v.index().IsValid()) {
-    AddExtraInteger(sexp, "index", v.index().value());
-  }
-  return sexp;
-}
-
-void LoadLocalInstr::AddOperandsToSExpression(SExpList* sexp,
-                                              FlowGraphSerializer* s) const {
-  sexp->Add(s->LocalVariableToSExp(local()));
-}
-
-void StoreLocalInstr::AddOperandsToSExpression(SExpList* sexp,
-                                               FlowGraphSerializer* s) const {
-  sexp->Add(s->LocalVariableToSExp(local()));
-}
-
-SExpression* FlowGraphSerializer::SlotToSExp(const Slot& slot) {
-  auto sexp = new (zone()) SExpList(zone());
-  AddSymbol(sexp, "Slot");
-  AddInteger(sexp, slot.offset_in_bytes());
-  AddExtraSymbol(sexp, "kind", Slot::KindToCString(slot.kind()));
-  if (slot.IsDartField()) {
-    sexp->AddExtra("field", DartValueToSExp(slot.field()));
-  }
-  return sexp;
-}
-
-void LoadFieldInstr::AddOperandsToSExpression(SExpList* sexp,
-                                              FlowGraphSerializer* s) const {
-  sexp->Add(instance()->ToSExpression(s));
-  sexp->Add(s->SlotToSExp(slot()));
-}
-
-void LoadFieldInstr::AddExtraInfoToSExpression(SExpList* sexp,
-                                               FlowGraphSerializer* s) const {
-  Instruction::AddExtraInfoToSExpression(sexp, s);
-  if (calls_initializer() || FLAG_verbose_flow_graph_serialization) {
-    s->AddExtraBool(sexp, "calls_initializer", calls_initializer());
-  }
-}
-
-void StoreInstanceFieldInstr::AddOperandsToSExpression(
-    SExpList* sexp,
-    FlowGraphSerializer* s) const {
-  sexp->Add(instance()->ToSExpression(s));
-  sexp->Add(s->SlotToSExp(slot()));
-  sexp->Add(value()->ToSExpression(s));
-}
-
-void StoreInstanceFieldInstr::AddExtraInfoToSExpression(
-    SExpList* sexp,
-    FlowGraphSerializer* s) const {
-  Instruction::AddExtraInfoToSExpression(sexp, s);
-  if (is_initialization_ || FLAG_verbose_flow_graph_serialization) {
-    s->AddExtraBool(sexp, "is_init", is_initialization_);
-  }
-  if (emit_store_barrier_ != kNoStoreBarrier ||
-      FLAG_verbose_flow_graph_serialization) {
-    // Make sure that we aren't seeing a new value added to the StoreBarrierType
-    // enum that isn't handled by the serializer.
-    ASSERT(emit_store_barrier_ == kNoStoreBarrier ||
-           emit_store_barrier_ == kEmitStoreBarrier);
-    s->AddExtraBool(sexp, "emit_barrier",
-                    emit_store_barrier_ != kNoStoreBarrier);
-  }
-}
-
-void LoadIndexedUnsafeInstr::AddExtraInfoToSExpression(
-    SExpList* sexp,
-    FlowGraphSerializer* s) const {
-  Instruction::AddExtraInfoToSExpression(sexp, s);
-  if (offset() > 0 || FLAG_verbose_flow_graph_serialization) {
-    s->AddExtraInteger(sexp, "offset", offset());
-  }
-}
-
-void StoreIndexedUnsafeInstr::AddExtraInfoToSExpression(
-    SExpList* sexp,
-    FlowGraphSerializer* s) const {
-  Instruction::AddExtraInfoToSExpression(sexp, s);
-  if (offset() > 0 || FLAG_verbose_flow_graph_serialization) {
-    s->AddExtraInteger(sexp, "offset", offset());
-  }
-}
-
-void ComparisonInstr::AddOperandsToSExpression(SExpList* sexp,
-                                               FlowGraphSerializer* s) const {
-  s->AddSymbol(sexp, Token::Str(kind()));
-  Instruction::AddOperandsToSExpression(sexp, s);
-}
-
-void StrictCompareInstr::AddExtraInfoToSExpression(
-    SExpList* sexp,
-    FlowGraphSerializer* s) const {
-  Instruction::AddExtraInfoToSExpression(sexp, s);
-  if (needs_number_check_ || FLAG_verbose_flow_graph_serialization) {
-    s->AddExtraBool(sexp, "needs_check", needs_number_check_);
-  }
-}
-
-void DoubleTestOpInstr::AddOperandsToSExpression(SExpList* sexp,
-                                                 FlowGraphSerializer* s) const {
-  const bool negated = kind() != Token::kEQ;
-  switch (op_kind()) {
-    case MethodRecognizer::kDouble_getIsNaN:
-      s->AddSymbol(sexp, negated ? "IsNotNaN" : "IsNaN");
-      break;
-    case MethodRecognizer::kDouble_getIsInfinite:
-      s->AddSymbol(sexp, negated ? "IsNotInfinite" : "IsInfinite");
-      break;
-    default:
-      UNREACHABLE();
-  }
-  sexp->Add(value()->ToSExpression(s));
-}
-
-void GotoInstr::AddOperandsToSExpression(SExpList* sexp,
-                                         FlowGraphSerializer* s) const {
-  sexp->Add(s->BlockIdToSExp(successor()->block_id()));
-}
-
-void DebugStepCheckInstr::AddExtraInfoToSExpression(
-    SExpList* sexp,
-    FlowGraphSerializer* s) const {
-  Instruction::AddExtraInfoToSExpression(sexp, s);
-  if (stub_kind_ != UntaggedPcDescriptors::kAnyKind ||
-      FLAG_verbose_flow_graph_serialization) {
-    auto const stub_kind_name =
-        UntaggedPcDescriptors::KindToCString(stub_kind_);
-    ASSERT(stub_kind_name != nullptr);
-    s->AddExtraSymbol(sexp, "stub_kind", stub_kind_name);
-  }
-}
-
-SExpression* FlowGraphSerializer::ICDataToSExp(const ICData* ic_data) {
-  auto const sexp = new (zone()) SExpList(zone());
-  AddSymbol(sexp, "ICData");
-
-  if (ic_data->is_tracking_exactness()) {
-    ic_data_type_ = ic_data->receivers_static_type();
-    sexp->AddExtra("receivers_static_type", AbstractTypeToSExp(ic_data_type_));
-  }
-
-  if (ic_data->is_megamorphic() || FLAG_verbose_flow_graph_serialization) {
-    AddExtraBool(sexp, "is_megamorphic", ic_data->is_megamorphic());
-  }
-
-  auto const num_checks = ic_data->NumberOfChecks();
-  GrowableArray<intptr_t> class_ids(zone(), 2);
-  for (intptr_t i = 0; i < num_checks; i++) {
-    auto const entry = new (zone()) SExpList(zone());
-
-    auto const count = ic_data->GetCountAt(i);
-    if (count > 0 || FLAG_verbose_flow_graph_serialization) {
-      AddExtraInteger(entry, "count", count);
-    }
-
-    class_ids.Clear();
-    ic_data->GetCheckAt(i, &class_ids, &ic_data_target_);
-    entry->AddExtra("target", DartValueToSExp(ic_data_target_));
-    for (auto const cid : class_ids) {
-      entry->Add(new (zone()) SExpInteger(cid));
-    }
-
-    sexp->Add(entry);
-  }
-
-  if (FLAG_verbose_flow_graph_serialization) {
-    AddExtraSymbol(sexp, "rebind_rule",
-                   ICData::RebindRuleToCString(ic_data->rebind_rule()));
-    tmp_string_ = ic_data->target_name();
-    AddExtraString(sexp, "target_name", tmp_string_.ToCString());
-    ic_data_target_ = ic_data->Owner();
-    sexp->AddExtra("owner", DartValueToSExp(ic_data_target_));
-    AddExtraInteger(sexp, "num_args_tested", ic_data->NumArgsTested());
-    auto& args_desc = Array::Handle(zone(), ic_data->arguments_descriptor());
-    sexp->AddExtra("arguments_descriptor", DartValueToSExp(args_desc));
-  }
-
-  return sexp;
-}
-
-void TailCallInstr::AddOperandsToSExpression(SExpList* sexp,
-                                             FlowGraphSerializer* s) const {
-  if (auto const code = s->DartValueToSExp(code_)) {
-    sexp->Add(code);
-  }
-  Instruction::AddOperandsToSExpression(sexp, s);
-}
-
-void NativeCallInstr::AddOperandsToSExpression(SExpList* sexp,
-                                               FlowGraphSerializer* s) const {
-  Instruction::AddOperandsToSExpression(sexp, s);
-}
-
-void NativeCallInstr::AddExtraInfoToSExpression(SExpList* sexp,
-                                                FlowGraphSerializer* s) const {
-  TemplateDartCall<0>::AddExtraInfoToSExpression(sexp, s);
-  if (auto const func = s->DartValueToSExp(function())) {
-    sexp->AddExtra("function", func);
-  }
-  if (!native_name().IsNull()) {
-    s->AddExtraString(sexp, "name", native_name().ToCString());
-  }
-  if (link_lazily() || FLAG_verbose_flow_graph_serialization) {
-    s->AddExtraBool(sexp, "link_lazily", link_lazily());
-  }
-}
-
-template <intptr_t kExtraInputs>
-void TemplateDartCall<kExtraInputs>::AddExtraInfoToSExpression(
-    SExpList* sexp,
-    FlowGraphSerializer* s) const {
-  Instruction::AddExtraInfoToSExpression(sexp, s);
-  if (type_args_len() > 0 || FLAG_verbose_flow_graph_serialization) {
-    s->AddExtraInteger(sexp, "type_args_len", type_args_len());
-  }
-  s->AddExtraInteger(sexp, "args_len", ArgumentCountWithoutTypeArgs());
-
-  const auto& arg_names = argument_names();
-  if (!arg_names.IsNull()) {
-    auto arg_names_sexp = new (s->zone()) SExpList(s->zone());
-    auto& str = String::Handle(s->zone());
-    for (intptr_t i = 0; i < arg_names.Length(); i++) {
-      str = String::RawCast(arg_names.At(i));
-      arg_names_sexp->Add(s->ObjectToSExp(str));
-    }
-    sexp->AddExtra("arg_names", arg_names_sexp);
-  }
-
-  ASSERT(!HasPushArguments());
-}
-
-void ClosureCallInstr::AddExtraInfoToSExpression(SExpList* sexp,
-                                                 FlowGraphSerializer* s) const {
-  // For now, just here to ensure TemplateDartCall<1>::AddExtraInfoToSExpression
-  // gets instantiated.
-  TemplateDartCall<1>::AddExtraInfoToSExpression(sexp, s);
-}
-
-void StaticCallInstr::AddOperandsToSExpression(SExpList* sexp,
-                                               FlowGraphSerializer* s) const {
-  Instruction::AddOperandsToSExpression(sexp, s);
-}
-
-void StaticCallInstr::AddExtraInfoToSExpression(SExpList* sexp,
-                                                FlowGraphSerializer* s) const {
-  TemplateDartCall<0>::AddExtraInfoToSExpression(sexp, s);
-
-  if (auto const func = s->DartValueToSExp(function())) {
-    sexp->AddExtra("function", func);
-  }
-
-  if (HasICData()) {
-    sexp->AddExtra("ic_data", s->ICDataToSExp(ic_data()));
-  } else if (CallCount() > 0 || FLAG_verbose_flow_graph_serialization) {
-    s->AddExtraInteger(sexp, "call_count", CallCount());
-  }
-
-  if (rebind_rule_ != ICData::kStatic ||
-      FLAG_verbose_flow_graph_serialization) {
-    auto const str = ICData::RebindRuleToCString(rebind_rule_);
-    ASSERT(str != nullptr);
-    s->AddExtraSymbol(sexp, "rebind_rule", str);
-  }
-
-  if (ShouldSerializeType(result_type())) {
-    sexp->AddExtra("result_type", result_type()->ToSExpression(s));
-  }
-
-  if (entry_kind() != Code::EntryKind::kNormal ||
-      FLAG_verbose_flow_graph_serialization) {
-    auto const kind_str = Code::EntryKindToCString(entry_kind());
-    s->AddExtraSymbol(sexp, "entry_kind", kind_str);
-  }
-}
-
-void InstanceCallBaseInstr::AddOperandsToSExpression(
-    SExpList* sexp,
-    FlowGraphSerializer* s) const {
-  Instruction::AddOperandsToSExpression(sexp, s);
-}
-
-void InstanceCallBaseInstr::AddExtraInfoToSExpression(
-    SExpList* sexp,
-    FlowGraphSerializer* s) const {
-  TemplateDartCall<0>::AddExtraInfoToSExpression(sexp, s);
-
-  if (auto const target = s->DartValueToSExp(interface_target())) {
-    sexp->AddExtra("interface_target", target);
-  }
-
-  if (auto const target = s->DartValueToSExp(tearoff_interface_target())) {
-    sexp->AddExtra("tearoff_interface_target", target);
-  }
-
-  if (HasICData()) {
-    sexp->AddExtra("ic_data", s->ICDataToSExp(ic_data()));
-  }
-
-  if (function_name().IsNull()) {
-    if (!interface_target().IsNull() || !tearoff_interface_target().IsNull()) {
-      s->AddExtraSymbol(sexp, "function_name", "null");
-    }
-  } else {
-    if (interface_target().IsNull() ||
-        (function_name().ptr() != interface_target().name() &&
-         function_name().ptr() != tearoff_interface_target().name())) {
-      s->AddExtraString(sexp, "function_name", function_name().ToCString());
-    }
-  }
-
-  if (token_kind() != Token::kILLEGAL) {
-    s->AddExtraSymbol(sexp, "token_kind", Token::Str(token_kind()));
-  }
-
-  if (ShouldSerializeType(result_type())) {
-    sexp->AddExtra("result_type", result_type()->ToSExpression(s));
-  }
-
-  if (entry_kind() != Code::EntryKind::kNormal ||
-      FLAG_verbose_flow_graph_serialization) {
-    auto const kind_str = Code::EntryKindToCString(entry_kind());
-    s->AddExtraSymbol(sexp, "entry_kind", kind_str);
-  }
-}
-
-void InstanceCallInstr::AddExtraInfoToSExpression(
-    SExpList* sexp,
-    FlowGraphSerializer* s) const {
-  InstanceCallBaseInstr::AddExtraInfoToSExpression(sexp, s);
-
-  if (checked_argument_count() > 0 || FLAG_verbose_flow_graph_serialization) {
-    s->AddExtraInteger(sexp, "checked_arg_count", checked_argument_count());
-  }
-}
-
-void PolymorphicInstanceCallInstr::AddExtraInfoToSExpression(
-    SExpList* sexp,
-    FlowGraphSerializer* s) const {
-  InstanceCallBaseInstr::AddExtraInfoToSExpression(sexp, s);
-
-  if (targets().length() > 0 || FLAG_verbose_flow_graph_serialization) {
-    auto elem_list = new (s->zone()) SExpList(s->zone());
-    for (intptr_t i = 0; i < targets().length(); i++) {
-      auto elem = new (s->zone()) SExpList(s->zone());
-      const TargetInfo* ti = targets().TargetAt(i);
-      if (ti->cid_start == ti->cid_end) {
-        s->AddInteger(elem, ti->cid_start);
-      } else {
-        auto range = new (s->zone()) SExpList(s->zone());
-        s->AddInteger(range, ti->cid_start);
-        s->AddInteger(range, ti->cid_end);
-        elem->Add(range);
-      }
-      if (auto const target = s->DartValueToSExp(*ti->target)) {
-        elem->Add(target);
-      }
-      elem_list->Add(elem);
-    }
-    sexp->AddExtra("targets", elem_list);
-  }
-}
-
-void AllocateObjectInstr::AddOperandsToSExpression(
-    SExpList* sexp,
-    FlowGraphSerializer* s) const {
-  if (auto const sexp_cls = s->DartValueToSExp(cls())) {
-    sexp->Add(sexp_cls);
-  }
-  if (type_arguments() != nullptr) {
-    sexp->Add(type_arguments()->ToSExpression(s));
-  }
-}
-
-void AllocateObjectInstr::AddExtraInfoToSExpression(
-    SExpList* sexp,
-    FlowGraphSerializer* s) const {
-  Instruction::AddExtraInfoToSExpression(sexp, s);
-  s->AddExtraInteger(sexp, "size", cls().target_instance_size());
-  if (auto const closure = s->DartValueToSExp(closure_function())) {
-    sexp->AddExtra("closure_function", closure);
-  }
-  if (!Identity().IsUnknown() || FLAG_verbose_flow_graph_serialization) {
-    s->AddExtraSymbol(sexp, "identity", Identity().ToCString());
-  }
-}
-
-void BinaryIntegerOpInstr::AddOperandsToSExpression(
-    SExpList* sexp,
-    FlowGraphSerializer* s) const {
-  s->AddSymbol(sexp, Token::Str(op_kind()));
-  sexp->Add(left()->ToSExpression(s));
-  sexp->Add(right()->ToSExpression(s));
-}
-
-void CheckedSmiOpInstr::AddOperandsToSExpression(SExpList* sexp,
-                                                 FlowGraphSerializer* s) const {
-  s->AddSymbol(sexp, Token::Str(op_kind()));
-  sexp->Add(left()->ToSExpression(s));
-  sexp->Add(right()->ToSExpression(s));
-}
-
-// clang-format off
-static const char* simd_op_kind_string[] = {
-#define CASE(Arity, Mask, Name, ...) #Name,
-  SIMD_OP_LIST(CASE, CASE)
-#undef CASE
-  "IllegalSimdOp",
-};
-// clang-format on
-
-void SimdOpInstr::AddOperandsToSExpression(SExpList* sexp,
-                                           FlowGraphSerializer* s) const {
-  s->AddSymbol(sexp, simd_op_kind_string[kind()]);
-  Instruction::AddOperandsToSExpression(sexp, s);
-}
-
-void SimdOpInstr::AddExtraInfoToSExpression(SExpList* sexp,
-                                            FlowGraphSerializer* s) const {
-  Instruction::AddExtraInfoToSExpression(sexp, s);
-  if (HasMask()) {
-    s->AddExtraInteger(sexp, "mask", mask());
-  }
-}
-
-void LoadIndexedInstr::AddExtraInfoToSExpression(SExpList* sexp,
-                                                 FlowGraphSerializer* s) const {
-  Instruction::AddExtraInfoToSExpression(sexp, s);
-  if (aligned() || FLAG_verbose_flow_graph_serialization) {
-    s->AddExtraBool(sexp, "aligned", aligned());
-  }
-  if (index_scale() > 1 || FLAG_verbose_flow_graph_serialization) {
-    s->AddExtraInteger(sexp, "scale", index_scale());
-  }
-  if (class_id() != kDynamicCid || FLAG_verbose_flow_graph_serialization) {
-    s->AddExtraInteger(sexp, "cid", class_id());
-  }
-}
-
-void StoreIndexedInstr::AddExtraInfoToSExpression(
-    SExpList* sexp,
-    FlowGraphSerializer* s) const {
-  Instruction::AddExtraInfoToSExpression(sexp, s);
-  if (aligned() || FLAG_verbose_flow_graph_serialization) {
-    s->AddExtraBool(sexp, "aligned", aligned());
-  }
-  if (index_scale() > 1 || FLAG_verbose_flow_graph_serialization) {
-    s->AddExtraInteger(sexp, "scale", index_scale());
-  }
-  if (class_id() != kDynamicCid || FLAG_verbose_flow_graph_serialization) {
-    s->AddExtraInteger(sexp, "cid", class_id());
-  }
-}
-
-void CheckStackOverflowInstr::AddExtraInfoToSExpression(
-    SExpList* sexp,
-    FlowGraphSerializer* s) const {
-  Instruction::AddExtraInfoToSExpression(sexp, s);
-  if (stack_depth() > 0 || FLAG_verbose_flow_graph_serialization) {
-    s->AddExtraInteger(sexp, "stack_depth", stack_depth());
-  }
-  if (in_loop() || FLAG_verbose_flow_graph_serialization) {
-    s->AddExtraInteger(sexp, "loop_depth", loop_depth());
-  }
-  if (kind_ != kOsrAndPreemption) {
-    ASSERT(kind_ == kOsrOnly);
-    s->AddExtraSymbol(sexp, "kind", "OsrOnly");
-  }
-}
-
-void CheckNullInstr::AddExtraInfoToSExpression(SExpList* sexp,
-                                               FlowGraphSerializer* s) const {
-  Instruction::AddExtraInfoToSExpression(sexp, s);
-  if (!function_name_.IsNull()) {
-    s->AddExtraString(sexp, "function_name", function_name_.ToCString());
-  }
-}
-
-SExpression* Value::ToSExpression(FlowGraphSerializer* s) const {
-  auto name = s->UseToSExp(definition());
-  // If we're not serializing types or there is no reaching type for this use,
-  // just serialize the use as the bound name.
-  if (!ShouldSerializeType(reaching_type_)) return name;
-
-  auto sexp = new (s->zone()) SExpList(s->zone());
-  s->AddSymbol(sexp, "value");
-  sexp->Add(name);
-  // If there is no owner for the type, then serialize the type in full.
-  // Otherwise the owner should be the definition, so we'll inherit the type
-  // from it. (That is, (value v<X>) with no explicit type info means the
-  // reaching type comes from the definition of v<X>.) We'll serialize an
-  // "inherit_type" extra info field to make this explicit when in verbose mode.
-  if (reaching_type_->owner() == nullptr) {
-    sexp->AddExtra("type", reaching_type_->ToSExpression(s));
-  } else {
-    ASSERT(reaching_type_->owner() == definition());
-  }
-  if (FLAG_verbose_flow_graph_serialization) {
-    s->AddExtraBool(sexp, "inherit_type",
-                    reaching_type_->owner() == definition());
-  }
-  return sexp;
-}
-
-SExpression* CompileType::ToSExpression(FlowGraphSerializer* s) const {
-  ASSERT(FLAG_verbose_flow_graph_serialization ||
-         FLAG_serialize_flow_graph_types);
-
-  auto sexp = new (s->zone()) SExpList(s->zone());
-  s->AddSymbol(sexp, "CompileType");
-  AddExtraInfoToSExpression(sexp, s);
-  return sexp;
-}
-
-void CompileType::AddExtraInfoToSExpression(SExpList* sexp,
-                                            FlowGraphSerializer* s) const {
-  if (cid_ != kIllegalCid || FLAG_verbose_flow_graph_serialization) {
-    s->AddExtraInteger(sexp, "cid", cid_);
-  }
-  // TODO(sstrickl): Currently we only print out nullable if it's false
-  // (or during verbose printing). Switch this when NNBD is the standard.
-  if (!is_nullable() || FLAG_verbose_flow_graph_serialization) {
-    s->AddExtraBool(sexp, "nullable", is_nullable());
-  }
-  if (type_ != nullptr) {
-    sexp->AddExtra("type", s->DartValueToSExp(*type_));
-  }
-}
-
-SExpression* Environment::ToSExpression(FlowGraphSerializer* s) const {
-  auto sexp = new (s->zone()) SExpList(s->zone());
-  for (intptr_t i = 0; i < values_.length(); ++i) {
-    ASSERT(!values_[i]->definition()->IsPushArgument());
-    sexp->Add(values_[i]->ToSExpression(s));
-    // TODO(sstrickl): This currently assumes that there are no locations in the
-    // environment (e.g. before register allocation). If we ever want to print
-    // out environments on steps after AllocateRegisters, we'll need to handle
-    // locations as well.
-    ASSERT(locations_ == nullptr || locations_[i].IsInvalid());
-  }
-  if (outer_ != NULL) {
-    auto outer_sexp = outer_->ToSExpression(s)->AsList();
-    if (outer_->deopt_id_ != DeoptId::kNone) {
-      s->AddExtraInteger(outer_sexp, "deopt_id", outer_->deopt_id_);
-    }
-    sexp->AddExtra("outer", outer_sexp);
-  }
-  return sexp;
-}
-
-}  // 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 fda5731..0000000
--- a/runtime/vm/compiler/backend/il_serializer.h
+++ /dev/null
@@ -1,198 +0,0 @@
-// Copyright (c) 2019, 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 "platform/assert.h"
-#include "platform/text_buffer.h"
-
-#include "vm/allocation.h"
-#include "vm/compiler/backend/flow_graph.h"
-#include "vm/compiler/backend/il.h"
-#include "vm/compiler/backend/sexpression.h"
-#include "vm/hash_table.h"
-#include "vm/object.h"
-#include "vm/zone.h"
-
-namespace dart {
-
-// Flow graph serialization.
-class FlowGraphSerializer : ValueObject {
- public:
-#define FOR_EACH_BLOCK_ENTRY_KIND(M)                                           \
-  M(Target)                                                                    \
-  M(Join)                                                                      \
-  M(Graph)                                                                     \
-  M(Normal)                                                                    \
-  M(Unchecked)                                                                 \
-  M(OSR)                                                                       \
-  M(Catch)                                                                     \
-  M(Indirect)
-
-  enum BlockEntryKind {
-#define KIND_DECL(name) k##name,
-    FOR_EACH_BLOCK_ENTRY_KIND(KIND_DECL)
-#undef KIND_DECL
-    // clang-format off
-    kNumEntryKinds,
-    kInvalid = -1,
-    // clang-format on
-  };
-
-  // Special case: returns kTarget for a nullptr input.
-  static BlockEntryKind BlockEntryTagToKind(SExpSymbol* tag);
-  SExpSymbol* BlockEntryKindToTag(BlockEntryKind k);
-  static bool BlockEntryKindHasInitialDefs(BlockEntryKind kind);
-
-  static void SerializeToBuffer(Zone* zone,
-                                const FlowGraph* flow_graph,
-                                BaseTextBuffer* buffer);
-  static SExpression* SerializeToSExp(Zone* zone, const FlowGraph* flow_graph);
-
-  const FlowGraph* flow_graph() const { return flow_graph_; }
-  Zone* zone() const { return zone_; }
-
-  SExpression* FlowGraphToSExp();
-
-  SExpSymbol* BlockEntryTag(const BlockEntryInstr* entry);
-  SExpression* BlockIdToSExp(intptr_t block_id);
-  SExpression* CanonicalNameToSExp(const Object& obj);
-  SExpression* UseToSExp(const Definition* definition);
-
-  // Helper method for creating canonical names.
-  void SerializeCanonicalName(BaseTextBuffer* b, const Object& obj);
-
-  // Methods for serializing Dart values. If the argument
-  // value is the null object, the null pointer is returned.
-  SExpression* AbstractTypeToSExp(const AbstractType& typ);
-  SExpression* ArrayToSExp(const Array& arr);
-  SExpression* ImmutableListToSExp(const Array& arr);
-  SExpression* ClassToSExp(const Class& cls);
-  SExpression* ClosureToSExp(const Closure& c);
-  SExpression* ContextToSExp(const Context& c);
-  SExpression* CodeToSExp(const Code& c);
-  SExpression* FieldToSExp(const Field& f);
-  SExpression* FunctionToSExp(const Function& f);
-  SExpression* InstanceToSExp(const Instance& obj);
-  SExpression* TypeArgumentsToSExp(const TypeArguments& ta);
-
-  // A method for serializing a Dart value of arbitrary type. Unlike the
-  // type-specific methods, this returns the symbol "null" for the null object.
-  SExpression* ObjectToSExp(const Object& obj);
-
-  // A wrapper method for ObjectToSExp that first checks and sees if
-  // the provided value is in the constant pool. If it is, then it
-  // returns a reference to the constant definition via UseToSExp.
-  SExpression* DartValueToSExp(const Object& obj);
-
-  // A wrapper method for TypeArgumentsToSExp that also returns nullptr if the
-  // type arguments are empty and checks against the constant pool.
-  SExpression* NonEmptyTypeArgumentsToSExp(const TypeArguments& ta);
-
-  // Methods for serializing IL-specific values.
-  SExpression* LocalVariableToSExp(const LocalVariable& v);
-  SExpression* SlotToSExp(const Slot& s);
-  SExpression* ICDataToSExp(const ICData* ic_data);
-
-  // Helper methods for adding Definition-specific extra info.
-  bool HasDefinitionExtraInfo(const Definition* def);
-  void AddDefinitionExtraInfoToSExp(const Definition* def, SExpList* sexp);
-
-  // Helper methods for adding atoms to S-expression lists
-  void AddBool(SExpList* sexp, bool b);
-  void AddInteger(SExpList* sexp, intptr_t i);
-  void AddString(SExpList* sexp, const char* cstr);
-  void AddSymbol(SExpList* sexp, const char* cstr);
-  void AddExtraBool(SExpList* sexp, const char* label, bool b);
-  void AddExtraInteger(SExpList* sexp, const char* label, intptr_t i);
-  void AddExtraString(SExpList* sexp, const char* label, const char* cstr);
-  void AddExtraSymbol(SExpList* sexp, const char* label, const char* cstr);
-
- private:
-  friend class Precompiler;  // For LLVMConstantsMap.
-
-  FlowGraphSerializer(Zone* zone, const FlowGraph* flow_graph);
-  ~FlowGraphSerializer();
-
-  static const char* const initial_indent;
-
-  // Helper methods for the function level that are not used by any
-  // instruction serialization methods.
-  SExpression* FunctionEntryToSExp(const BlockEntryInstr* entry);
-  SExpression* EntriesToSExp(const GraphEntryInstr* start);
-  SExpression* ConstantPoolToSExp(const GraphEntryInstr* start);
-
-  const FlowGraph* const flow_graph_;
-  Zone* const zone_;
-  ObjectStore* const object_store_;
-
-  // A map of currently open (being serialized) recursive types. We use this
-  // to determine whether to serialize the referred types in TypeRefs.
-  IntMap<const AbstractType*> open_recursive_types_;
-
-  // Used for --populate-llvm-constant-pool in ConstantPoolToSExp.
-  class LLVMPoolMapKeyEqualsTraits : public AllStatic {
-   public:
-    static const char* Name() { return "LLVMPoolMapKeyEqualsTraits"; }
-    static bool ReportStats() { return false; }
-
-    static bool IsMatch(const Object& a, const Object& b) {
-      return a.ptr() == b.ptr();
-    }
-    static uword Hash(const Object& obj) {
-      if (obj.IsSmi()) return static_cast<uword>(obj.ptr());
-      if (obj.IsInstance()) return Instance::Cast(obj).CanonicalizeHash();
-      return obj.GetClassId();
-    }
-  };
-  typedef UnorderedHashMap<LLVMPoolMapKeyEqualsTraits> LLVMPoolMap;
-
-  GrowableObjectArray& llvm_constants_;
-  GrowableObjectArray& llvm_functions_;
-  LLVMPoolMap llvm_constant_map_;
-  Smi& llvm_index_;
-
-  // Handles used across functions, where the contained value is used
-  // immediately and does not need to live across calls to other serializer
-  // functions.
-  String& tmp_string_;
-
-  // Handles for use within a single function in the following cases:
-  //
-  // * The function is guaranteed to not be re-entered during execution.
-  // * The contained value is not live across any possible re-entry.
-  //
-  // Generally, the most likely source of possible re-entry is calling
-  // DartValueToSExp with a sub-element of type Object, but any call to a
-  // FlowGraphSerializer method that may eventually enter one of the methods
-  // listed below should be examined with care.
-  TypeArguments& array_type_args_;     // ArrayToSExp
-  Context& closure_context_;           // ClosureToSExp
-  Function& closure_function_;         // ClosureToSExp
-  TypeArguments& closure_type_args_;   // ClosureToSExp
-  Object& code_owner_;                 // CodeToSExp
-  Context& context_parent_;            // ContextToSExp
-  Object& context_elem_;               // ContextToSExp
-  TypeArguments& function_type_args_;  // FunctionToSExp
-  Function& ic_data_target_;           // ICDataToSExp
-  AbstractType& ic_data_type_;         // ICDataToSExp
-  Field& instance_field_;              // InstanceToSExp
-  TypeArguments& instance_type_args_;  // InstanceToSExp
-  Library& serialize_library_;         // SerializeCanonicalName
-  Class& serialize_owner_;             // SerializeCanonicalName
-  Function& serialize_parent_;         // SerializeCanonicalName
-  AbstractType& type_arguments_elem_;  // TypeArgumentsToSExp
-  Class& type_class_;                  // AbstractTypeToSExp
-  FunctionType& type_signature_;       // AbstractTypeToSExp
-  AbstractType& type_ref_type_;        // AbstractTypeToSExp
-};
-
-}  // namespace dart
-
-#endif  // RUNTIME_VM_COMPILER_BACKEND_IL_SERIALIZER_H_
diff --git a/runtime/vm/compiler/backend/range_analysis.h b/runtime/vm/compiler/backend/range_analysis.h
index 7491def..ab21d74 100644
--- a/runtime/vm/compiler/backend/range_analysis.h
+++ b/runtime/vm/compiler/backend/range_analysis.h
@@ -14,9 +14,6 @@
 
 namespace dart {
 
-class SExpression;
-class FlowGraphSerializer;
-
 class RangeBoundary : public ValueObject {
  public:
 #define FOR_EACH_RANGE_BOUNDARY_KIND(V)                                        \
@@ -246,7 +243,6 @@
 
   void PrintTo(BaseTextBuffer* f) const;
   const char* ToCString() const;
-  SExpression* ToSExpression(FlowGraphSerializer* s);
 
   static RangeBoundary Add(const RangeBoundary& a,
                            const RangeBoundary& b,
@@ -347,7 +343,6 @@
 
   void PrintTo(BaseTextBuffer* f) const;
   static const char* ToCString(const Range* range);
-  SExpression* ToSExpression(FlowGraphSerializer* s);
 
   bool Equals(const Range* other) {
     ASSERT(min_.IsUnknown() == max_.IsUnknown());
diff --git a/runtime/vm/compiler/backend/sexpression.cc b/runtime/vm/compiler/backend/sexpression.cc
deleted file mode 100644
index 7307ef3..0000000
--- a/runtime/vm/compiler/backend/sexpression.cc
+++ /dev/null
@@ -1,686 +0,0 @@
-// Copyright (c) 2019, 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/sexpression.h"
-
-#include <ctype.h>
-#include "platform/utils.h"
-#include "vm/double_conversion.h"
-#include "vm/zone_text_buffer.h"
-
-namespace dart {
-
-SExpression* SExpression::FromCString(Zone* zone, const char* str) {
-  SExpParser parser(zone, str);
-  auto sexp = parser.Parse();
-  if (sexp == nullptr) parser.ReportError();
-  return sexp;
-}
-
-const char* SExpression::ToCString(Zone* zone) const {
-  ZoneTextBuffer buf(zone, 1 * KB);
-  SerializeToLine(&buf);
-  return buf.buffer();
-}
-
-bool SExpBool::Equals(SExpression* sexp) const {
-  if (auto const b = sexp->AsBool()) return b->Equals(value());
-  return false;
-}
-
-bool SExpBool::Equals(bool val) const {
-  return value() == val;
-}
-
-void SExpBool::SerializeToLine(BaseTextBuffer* buffer) const {
-  buffer->AddString(value() ? SExpParser::kBoolTrueSymbol
-                            : SExpParser::kBoolFalseSymbol);
-}
-
-bool SExpDouble::Equals(SExpression* sexp) const {
-  if (auto const d = sexp->AsDouble()) return d->Equals(value());
-  return false;
-}
-
-bool SExpDouble::Equals(double val) const {
-  return value() == val;
-}
-
-void SExpDouble::SerializeToLine(BaseTextBuffer* buffer) const {
-  // Use existing Dart serialization for Doubles.
-  const intptr_t kBufSize = 128;
-  char strbuf[kBufSize];
-  DoubleToCString(value(), strbuf, kBufSize);
-  buffer->Printf("%s", strbuf);
-}
-
-bool SExpInteger::Equals(SExpression* sexp) const {
-  if (auto const i = sexp->AsInteger()) return i->Equals(value());
-  return false;
-}
-
-bool SExpInteger::Equals(int64_t val) const {
-  return value() == val;
-}
-
-void SExpInteger::SerializeToLine(BaseTextBuffer* buffer) const {
-  buffer->Printf("%" Pd64 "", value());
-}
-
-bool SExpString::Equals(SExpression* sexp) const {
-  if (auto const s = sexp->AsString()) return s->Equals(value());
-  return false;
-}
-
-bool SExpString::Equals(const char* str) const {
-  return strcmp(value(), str) == 0;
-}
-
-void SExpString::SerializeToLine(BaseTextBuffer* buffer) const {
-  TextBuffer buf(80);
-  buf.AddChar('"');
-  buf.AddEscapedString(value());
-  buf.AddChar('"');
-  buffer->AddString(buf.buffer());
-}
-
-bool SExpSymbol::Equals(SExpression* sexp) const {
-  if (auto const s = sexp->AsSymbol()) return s->Equals(value());
-  return false;
-}
-
-bool SExpSymbol::Equals(const char* str) const {
-  return strcmp(value(), str) == 0;
-}
-
-void SExpSymbol::SerializeToLine(BaseTextBuffer* buffer) const {
-  buffer->AddString(value());
-}
-
-void SExpList::Add(SExpression* sexp) {
-  contents_.Add(sexp);
-}
-
-void SExpList::AddExtra(const char* label, SExpression* value) {
-  ASSERT(!extra_info_.HasKey(label));
-  extra_info_.Insert({label, value});
-}
-
-bool SExpList::Equals(SExpression* sexp) const {
-  if (!sexp->IsList()) return false;
-  auto list = sexp->AsList();
-  if (Length() != list->Length()) return false;
-  if (ExtraLength() != list->ExtraLength()) return false;
-  for (intptr_t i = 0; i < Length(); i++) {
-    if (!At(i)->Equals(list->At(i))) return false;
-  }
-  auto this_it = ExtraIterator();
-  while (auto kv = this_it.Next()) {
-    if (!list->ExtraHasKey(kv->key)) return false;
-    if (!kv->value->Equals(list->ExtraLookupValue(kv->key))) return false;
-  }
-  return true;
-}
-
-const char* const SExpList::kElemIndent = " ";
-const char* const SExpList::kExtraIndent = "  ";
-
-static intptr_t HandleLineBreaking(Zone* zone,
-                                   BaseTextBuffer* buffer,
-                                   SExpression* element,
-                                   BaseTextBuffer* line_buffer,
-                                   const char* sub_indent,
-                                   intptr_t width,
-                                   bool leading_space,
-                                   intptr_t remaining) {
-  element->SerializeToLine(line_buffer);
-  const intptr_t single_line_width = line_buffer->length();
-  const intptr_t leading_length = leading_space ? 1 : 0;
-
-  if ((leading_length + single_line_width) < remaining) {
-    if (leading_space) buffer->AddChar(' ');
-    buffer->AddString(line_buffer->buffer());
-    line_buffer->Clear();
-    return remaining - (leading_length + single_line_width);
-  }
-  const intptr_t old_length = buffer->length();
-  buffer->Printf("\n%s", sub_indent);
-  const intptr_t line_used = buffer->length() - old_length + 1;
-  remaining = width - line_used;
-  if ((single_line_width < remaining) || element->IsAtom()) {
-    buffer->AddString(line_buffer->buffer());
-    line_buffer->Clear();
-    return remaining - single_line_width;
-  }
-  line_buffer->Clear();
-  element->SerializeTo(zone, buffer, sub_indent, width);
-  return 0;
-}
-
-// Assumes that we are starting on a line after [indent] amount of space.
-void SExpList::SerializeTo(Zone* zone,
-                           BaseTextBuffer* buffer,
-                           const char* indent,
-                           intptr_t width) const {
-  TextBuffer single_line(width);
-  const char* sub_indent = OS::SCreate(zone, "%s%s", indent, kElemIndent);
-
-  buffer->AddChar('(');
-  intptr_t remaining = width - strlen(indent) - 1;
-  for (intptr_t i = 0; i < contents_.length(); i++) {
-    remaining = HandleLineBreaking(zone, buffer, contents_.At(i), &single_line,
-                                   sub_indent, width, i != 0, remaining);
-  }
-
-  if (!extra_info_.IsEmpty()) {
-    SerializeExtraInfoToLine(&single_line);
-    if (single_line.length() < remaining - 1) {
-      buffer->Printf(" %s", single_line.buffer());
-    } else {
-      const intptr_t old_length = buffer->length();
-      buffer->Printf("\n%s", sub_indent);
-      const intptr_t line_used = buffer->length() - old_length + 1;
-      remaining = width - line_used;
-      if (single_line.length() < remaining) {
-        buffer->AddString(single_line.buffer());
-      } else {
-        SerializeExtraInfoTo(zone, buffer, sub_indent, width);
-      }
-    }
-  }
-  buffer->AddChar(')');
-}
-
-void SExpList::SerializeToLine(BaseTextBuffer* buffer) const {
-  buffer->AddChar('(');
-  for (intptr_t i = 0; i < contents_.length(); i++) {
-    if (i != 0) buffer->AddChar(' ');
-    contents_.At(i)->SerializeToLine(buffer);
-  }
-  if (!extra_info_.IsEmpty()) {
-    buffer->AddChar(' ');
-    SerializeExtraInfoToLine(buffer);
-  }
-  buffer->AddChar(')');
-}
-
-void SExpList::SerializeExtraInfoTo(Zone* zone,
-                                    BaseTextBuffer* buffer,
-                                    const char* indent,
-                                    int width) const {
-  const char* sub_indent = OS::SCreate(zone, "%s%s", indent, kExtraIndent);
-  TextBuffer single_line(width);
-
-  buffer->AddChar('{');
-  auto it = ExtraIterator();
-  while (auto kv = it.Next()) {
-    const intptr_t old_length = buffer->length();
-    buffer->Printf("\n%s%s", sub_indent, kv->key);
-    const intptr_t remaining = width - (buffer->length() - old_length + 1);
-    HandleLineBreaking(zone, buffer, kv->value, &single_line, sub_indent, width,
-                       /*leading_space=*/true, remaining);
-    buffer->AddChar(',');
-  }
-  buffer->Printf("\n%s}", indent);
-}
-
-void SExpList::SerializeExtraInfoToLine(BaseTextBuffer* buffer) const {
-  buffer->AddString("{");
-  auto it = ExtraIterator();
-  while (auto kv = it.Next()) {
-    buffer->Printf(" %s ", kv->key);
-    kv->value->SerializeToLine(buffer);
-    buffer->AddChar(',');
-  }
-  buffer->AddString(" }");
-}
-
-const char* const SExpParser::kBoolTrueSymbol = "true";
-const char* const SExpParser::kBoolFalseSymbol = "false";
-char const SExpParser::kDoubleExponentChar =
-    DoubleToStringConstants::kExponentChar;
-const char* const SExpParser::kDoubleInfinitySymbol =
-    DoubleToStringConstants::kInfinitySymbol;
-const char* const SExpParser::kDoubleNaNSymbol =
-    DoubleToStringConstants::kNaNSymbol;
-
-const char* const SExpParser::ErrorStrings::kOpenString =
-    "unterminated quoted string starting at position %" Pd "";
-const char* const SExpParser::ErrorStrings::kBadUnicodeEscape =
-    "malformed Unicode escape";
-const char* const SExpParser::ErrorStrings::kOpenSExpList =
-    "unterminated S-expression list starting at position %" Pd "";
-const char* const SExpParser::ErrorStrings::kOpenMap =
-    "unterminated extra info map starting at position %" Pd "";
-const char* const SExpParser::ErrorStrings::kNestedMap =
-    "extra info map start when already within extra info map";
-const char* const SExpParser::ErrorStrings::kMapOutsideList =
-    "extra info map start not within S-expression list";
-const char* const SExpParser::ErrorStrings::kNonSymbolLabel =
-    "non-symbol in label position for extra info map";
-const char* const SExpParser::ErrorStrings::kNoMapLabel =
-    "no extra info map label provided";
-const char* const SExpParser::ErrorStrings::kRepeatedMapLabel =
-    "extra info map label %s provided more than once";
-const char* const SExpParser::ErrorStrings::kNoMapValue =
-    "no value provided for extra info map label %s";
-const char* const SExpParser::ErrorStrings::kExtraMapValue =
-    "extra value following label %s in extra info map";
-const char* const SExpParser::ErrorStrings::kUnexpectedComma =
-    "comma found outside extra info map";
-const char* const SExpParser::ErrorStrings::kUnexpectedRightParen =
-    "unexpected closing parenthesis";
-const char* const SExpParser::ErrorStrings::kUnexpectedRightCurly =
-    "unexpected closing curly brace";
-
-#define PARSE_ERROR(x, ...)                                                    \
-  StoreError(x, __VA_ARGS__);                                                  \
-  return nullptr
-
-SExpression* SExpParser::Parse() {
-  Reset();
-  while (auto token = GetNextToken()) {
-    const intptr_t start_pos = token->cstr() - buffer_;
-    switch (token->type()) {
-      case kLeftParen: {
-        if (in_extra_) {
-          if (cur_label_ == nullptr) {
-            PARSE_ERROR(start_pos, ErrorStrings::kNonSymbolLabel);
-          } else if (cur_value_ != nullptr) {
-            PARSE_ERROR(start_pos, ErrorStrings::kExtraMapValue, cur_label_);
-          }
-        }
-        auto sexp = new (zone_) SExpList(zone_, start_pos);
-        list_stack_.Add(sexp);
-        in_extra_stack_.Add(in_extra_);
-        extra_start_stack_.Add(extra_start_);
-        cur_label_stack_.Add(cur_label_);
-        in_extra_ = false;
-        extra_start_ = -1;
-        cur_label_ = nullptr;
-        break;
-      }
-      case kRightParen: {
-        if (list_stack_.is_empty()) {
-          PARSE_ERROR(start_pos, ErrorStrings::kUnexpectedRightParen);
-        }
-        if (in_extra_) {
-          PARSE_ERROR(start_pos, ErrorStrings::kOpenMap, extra_start_);
-        }
-        auto sexp = list_stack_.RemoveLast();
-        in_extra_ = in_extra_stack_.RemoveLast();
-        extra_start_ = extra_start_stack_.RemoveLast();
-        cur_label_ = cur_label_stack_.RemoveLast();
-        if (list_stack_.is_empty()) return sexp;
-        if (in_extra_) {
-          if (cur_label_ == nullptr) {
-            PARSE_ERROR(start_pos, ErrorStrings::kOpenMap, extra_start_);
-          }
-          cur_value_ = sexp;
-        } else {
-          list_stack_.Last()->Add(sexp);
-        }
-        break;
-      }
-      case kLeftCurly:
-        if (in_extra_) {
-          PARSE_ERROR(start_pos, ErrorStrings::kNestedMap);
-        }
-        if (list_stack_.is_empty()) {
-          PARSE_ERROR(start_pos, ErrorStrings::kMapOutsideList);
-        }
-        extra_start_ = start_pos;
-        in_extra_ = true;
-        break;
-      case kRightCurly:
-        if (!in_extra_ || list_stack_.is_empty()) {
-          PARSE_ERROR(start_pos, ErrorStrings::kUnexpectedRightCurly);
-        }
-        if (cur_label_ != nullptr) {
-          if (cur_value_ == nullptr) {
-            PARSE_ERROR(start_pos, ErrorStrings::kNoMapValue, cur_label_);
-          }
-          list_stack_.Last()->AddExtra(cur_label_, cur_value_);
-          cur_label_ = nullptr;
-          cur_value_ = nullptr;
-        }
-        in_extra_ = false;
-        extra_start_ = -1;
-        break;
-      case kComma: {
-        if (!in_extra_ || list_stack_.is_empty()) {
-          PARSE_ERROR(start_pos, ErrorStrings::kUnexpectedComma);
-        }
-        if (cur_label_ == nullptr) {
-          PARSE_ERROR(start_pos, ErrorStrings::kNoMapLabel);
-        } else if (cur_value_ == nullptr) {
-          PARSE_ERROR(start_pos, ErrorStrings::kNoMapValue, cur_label_);
-        }
-        list_stack_.Last()->AddExtra(cur_label_, cur_value_);
-        cur_label_ = nullptr;
-        cur_value_ = nullptr;
-        break;
-      }
-      case kSymbol: {
-        auto sexp = TokenToSExpression(token);
-        ASSERT(sexp->IsSymbol());
-        if (in_extra_) {
-          if (cur_value_ != nullptr) {
-            PARSE_ERROR(start_pos, ErrorStrings::kExtraMapValue, cur_label_);
-          }
-          if (cur_label_ == nullptr) {
-            const char* const label = sexp->AsSymbol()->value();
-            if (list_stack_.Last()->ExtraHasKey(label)) {
-              PARSE_ERROR(start_pos, ErrorStrings::kRepeatedMapLabel, label);
-            }
-            cur_label_ = sexp->AsSymbol()->value();
-          } else {
-            cur_value_ = sexp;
-          }
-        } else if (!list_stack_.is_empty()) {
-          list_stack_.Last()->Add(sexp);
-        } else {
-          return sexp;
-        }
-        break;
-      }
-      case kBoolean:
-      case kInteger:
-      case kDouble:
-      case kQuotedString: {
-        auto sexp = TokenToSExpression(token);
-        // TokenToSExpression has already set the error info, so just return.
-        if (sexp == nullptr) return nullptr;
-        if (in_extra_) {
-          if (cur_label_ == nullptr) {
-            PARSE_ERROR(start_pos, ErrorStrings::kNonSymbolLabel);
-          } else if (cur_value_ != nullptr) {
-            PARSE_ERROR(start_pos, ErrorStrings::kExtraMapValue, cur_label_);
-          }
-          cur_value_ = sexp;
-        } else if (!list_stack_.is_empty()) {
-          list_stack_.Last()->Add(sexp);
-        } else {
-          return sexp;
-        }
-        break;
-      }
-      default:
-        UNREACHABLE();
-    }
-  }
-  if (in_extra_) {
-    PARSE_ERROR(buffer_size_, ErrorStrings::kOpenMap, extra_start_);
-  } else if (!list_stack_.is_empty()) {
-    const intptr_t list_start = list_stack_.Last()->start();
-    PARSE_ERROR(buffer_size_, ErrorStrings::kOpenSExpList, list_start);
-  }
-  UNREACHABLE();
-}
-
-SExpression* SExpParser::TokenToSExpression(Token* token) {
-  const intptr_t start_pos = token->cstr() - buffer_;
-  switch (token->type()) {
-    case kSymbol:
-      return new (zone_) SExpSymbol(token->ToCString(zone_), start_pos);
-    case kInteger: {
-      const char* cstr = token->ToCString(zone_);
-      int64_t val;
-      if (!OS::StringToInt64(cstr, &val)) return nullptr;
-      return new (zone_) SExpInteger(val, start_pos);
-    }
-    case kBoolean: {
-      const bool is_true =
-          strncmp(token->cstr(), kBoolTrueSymbol, token->length()) == 0;
-      ASSERT(is_true ||
-             strncmp(token->cstr(), kBoolFalseSymbol, token->length()) == 0);
-      return new (zone_) SExpBool(is_true, start_pos);
-    }
-    case kDouble: {
-      double val;
-      if (!CStringToDouble(token->cstr(), token->length(), &val)) {
-        return nullptr;
-      }
-      return new (zone_) SExpDouble(val, start_pos);
-    }
-    case kQuotedString: {
-      const char* const cstr = token->cstr();
-      char* const buf = zone_->Alloc<char>(token->length());
-      // Skip the initial quote
-      ASSERT(cstr[0] == '"');
-      intptr_t old_pos = 1;
-      intptr_t new_pos = 0;
-      // The string _should_ end in a quote.
-      while (old_pos < token->length() - 1) {
-        if (cstr[old_pos] == '"') break;
-        if (cstr[old_pos] != '\\') {
-          buf[new_pos++] = cstr[old_pos++];
-          continue;
-        }
-        old_pos++;
-        if (old_pos >= token->length()) {
-          PARSE_ERROR(start_pos + old_pos, ErrorStrings::kOpenString,
-                      start_pos);
-        }
-        const intptr_t escape_pos = start_pos + old_pos - 1;
-        switch (cstr[old_pos]) {
-          case 'b':
-            buf[new_pos] = '\b';
-            break;
-          case 'f':
-            buf[new_pos] = '\f';
-            break;
-          case 'n':
-            buf[new_pos] = '\n';
-            break;
-          case 'r':
-            buf[new_pos] = '\r';
-            break;
-          case 't':
-            buf[new_pos] = '\t';
-            break;
-          case 'u': {
-            const intptr_t first = old_pos + 1;
-            const intptr_t last = old_pos + 4;
-            if (last >= token->length()) {
-              PARSE_ERROR(escape_pos, ErrorStrings::kBadUnicodeEscape);
-            }
-            intptr_t val = 0;
-            for (const char *cursor = cstr + first, *end = cstr + last + 1;
-                 cursor < end; cursor++) {
-              val *= 16;
-              if (!Utils::IsHexDigit(*cursor)) {
-                PARSE_ERROR(escape_pos, ErrorStrings::kBadUnicodeEscape);
-              }
-              val += Utils::HexDigitToInt(*cursor);
-            }
-            // Currently, just handle encoded ASCII instead of doing
-            // handling Unicode characters.
-            // (TextBuffer::AddEscapedString uses this for characters < 0x20.)
-            ASSERT(val <= 0x7F);
-            old_pos = last;
-            buf[new_pos] = val;
-            break;
-          }
-          default:
-            // Identity escapes.
-            buf[new_pos] = cstr[old_pos];
-            break;
-        }
-        old_pos++;
-        new_pos++;
-      }
-      if (cstr[old_pos] != '"') {
-        PARSE_ERROR(start_pos + token->length(), ErrorStrings::kOpenString,
-                    start_pos);
-      }
-      buf[new_pos] = '\0';
-      return new (zone_) SExpString(buf, start_pos);
-    }
-    default:
-      UNREACHABLE();
-  }
-}
-
-#undef PARSE_ERROR
-
-SExpParser::Token* SExpParser::GetNextToken() {
-  intptr_t start_pos = cur_pos_;
-  while (start_pos < buffer_size_) {
-    if (isspace(buffer_[start_pos]) == 0) break;
-    start_pos++;
-  }
-  if (start_pos >= buffer_size_) return nullptr;
-  const char* start = buffer_ + start_pos;
-  switch (*start) {
-    case '(':
-      cur_pos_ = start_pos + 1;
-      return new (zone_) Token(kLeftParen, start, 1);
-    case ')':
-      cur_pos_ = start_pos + 1;
-      return new (zone_) Token(kRightParen, start, 1);
-    case ',':
-      cur_pos_ = start_pos + 1;
-      return new (zone_) Token(kComma, start, 1);
-    case '{':
-      cur_pos_ = start_pos + 1;
-      return new (zone_) Token(kLeftCurly, start, 1);
-    case '}':
-      cur_pos_ = start_pos + 1;
-      return new (zone_) Token(kRightCurly, start, 1);
-    case '"': {
-      intptr_t len = 1;
-      while (start_pos + len < buffer_size_) {
-        char curr = start[len];
-        len++;  // Length should include the quote, if any.
-        if (curr == '\\') {
-          // Skip past next character (if any), since it cannot
-          // end the quoted string due to being escaped.
-          if (start_pos + len >= buffer_size_) break;
-          len++;
-          continue;
-        }
-        if (curr == '"') break;
-      }
-      cur_pos_ = start_pos + len;
-      return new (zone_) Token(kQuotedString, start, len);
-    }
-    default:
-      break;
-  }
-  intptr_t len = 0;
-  // Start number detection after possible negation sign.
-  if (start[len] == '-') {
-    len++;
-    if ((start_pos + len) >= buffer_size_) {
-      cur_pos_ = start_pos + len;
-      return new (zone_) Token(kSymbol, start, len);
-    }
-  }
-  // Keep the currently detected token type. Start off by assuming we have
-  // an integer, then fall back to doubles if we see parts appropriate for
-  // those but not integers, and fall back to symbols otherwise.
-  TokenType type = kInteger;
-  bool saw_exponent = false;
-  while ((start_pos + len) < buffer_size_) {
-    // Both numbers and symbols cannot contain these values, so we are at the
-    // end of whichever one we're in.
-    if (!IsSymbolContinue(start[len])) break;
-    if (type == kInteger && start[len] == '.') {
-      type = kDouble;
-      len++;
-      continue;
-    }
-    if (type != kSymbol && !saw_exponent && start[len] == kDoubleExponentChar) {
-      saw_exponent = true;
-      type = kDouble;
-      len++;
-      // Skip past negation in exponent if any.
-      if ((start_pos + len) < buffer_size_ && start[len] == '-') len++;
-      continue;
-    }
-    // If we find a character that can't appear in a number, then fall back
-    // to symbol-ness.
-    if (isdigit(start[len]) == 0) type = kSymbol;
-    len++;
-  }
-  cur_pos_ = start_pos + len;
-  // Skip special symbol detection if we don't have a symbol.
-  if (type != kSymbol) return new (zone_) Token(type, start, len);
-  // Check for special symbols used for booleans and certain Double values.
-  switch (len) {
-    case 3:
-      if (strncmp(start, kDoubleNaNSymbol, len) == 0) type = kDouble;
-      break;
-    case 4:
-      if (strncmp(start, kBoolTrueSymbol, len) == 0) type = kBoolean;
-      break;
-    case 5:
-      if (strncmp(start, kBoolFalseSymbol, len) == 0) type = kBoolean;
-      break;
-    case 8:
-      if (strncmp(start, kDoubleInfinitySymbol, len) == 0) type = kDouble;
-      break;
-    case 9:
-      if (start[0] == '-' &&
-          strncmp(start + 1, kDoubleInfinitySymbol, len - 1) == 0) {
-        type = kDouble;
-      }
-      break;
-    default:
-      break;
-  }
-  return new (zone_) Token(type, start, len);
-}
-
-bool SExpParser::IsSymbolContinue(char c) {
-  return (isspace(c) == 0) && c != '(' && c != ')' && c != ',' && c != '{' &&
-         c != '}' && c != '"';
-}
-
-const char* const SExpParser::Token::TokenNames[kMaxTokens] = {
-#define S_EXP_TOKEN_NAME_STRING(name) #name,
-    S_EXP_TOKEN_LIST(S_EXP_TOKEN_NAME_STRING)
-#undef S_EXP_TOKEN_NAME_STRING
-};
-
-const char* SExpParser::Token::ToCString(Zone* zone) {
-  char* const buffer = zone->Alloc<char>(len_ + 1);
-  strncpy(buffer, cstr_, len_);
-  buffer[len_] = '\0';
-  return buffer;
-}
-
-void SExpParser::Reset() {
-  cur_pos_ = 0;
-  in_extra_ = false;
-  extra_start_ = -1;
-  cur_label_ = nullptr;
-  cur_value_ = nullptr;
-  list_stack_.Clear();
-  in_extra_stack_.Clear();
-  extra_start_stack_.Clear();
-  cur_label_stack_.Clear();
-  error_pos_ = -1;
-  error_message_ = nullptr;
-}
-
-void SExpParser::StoreError(intptr_t pos, const char* format, ...) {
-  va_list args;
-  va_start(args, format);
-  const char* const message = OS::VSCreate(zone_, format, args);
-  va_end(args);
-  error_pos_ = pos;
-  error_message_ = message;
-}
-
-void SExpParser::ReportError() const {
-  ASSERT(error_message_ != nullptr);
-  ASSERT(error_pos_ >= 0);
-  OS::PrintErr("Unable to parse s-expression: %s\n", buffer_);
-  OS::PrintErr("Error at character %" Pd ": %s\n", error_pos_, error_message_);
-  OS::Abort();
-}
-
-}  // namespace dart
diff --git a/runtime/vm/compiler/backend/sexpression.h b/runtime/vm/compiler/backend/sexpression.h
deleted file mode 100644
index 6bdc36e..0000000
--- a/runtime/vm/compiler/backend/sexpression.h
+++ /dev/null
@@ -1,305 +0,0 @@
-// Copyright (c) 2019, 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_SEXPRESSION_H_
-#define RUNTIME_VM_COMPILER_BACKEND_SEXPRESSION_H_
-
-#if defined(DART_PRECOMPILED_RUNTIME)
-#error "AOT runtime should not use compiler sources (including header files)"
-#endif  // defined(DART_PRECOMPILED_RUNTIME)
-
-#include "platform/text_buffer.h"
-
-#include "vm/allocation.h"
-#include "vm/growable_array.h"
-#include "vm/hash_map.h"
-#include "vm/zone.h"
-
-namespace dart {
-
-#define FOR_EACH_S_EXPRESSION_ATOM(M)                                          \
-  M(Bool, bool)                                                                \
-  M(Double, double)                                                            \
-  M(Integer, int64_t)                                                          \
-  M(String, const char*)                                                       \
-  M(Symbol, const char*)
-
-#define FOR_EACH_S_EXPRESSION(M)                                               \
-  FOR_EACH_S_EXPRESSION_ATOM(M)                                                \
-  M(List, _)
-
-#define FOR_EACH_ABSTRACT_S_EXPRESSION(M) M(Atom, _)
-
-#define FORWARD_DECLARATION(name, value_type) class SExp##name;
-FOR_EACH_S_EXPRESSION(FORWARD_DECLARATION)
-FOR_EACH_ABSTRACT_S_EXPRESSION(FORWARD_DECLARATION)
-#undef FORWARD_DECLARATION
-
-// Abstract base class for S-expressions used as an intermediate form for the
-// IL serializer. These aren't true (LISP-like) S-expressions, as the atoms
-// are more restricted and the lists have extra information. Here is an
-// illustrative BNF-style grammar of the current serialized form of
-// S-expressions that includes non-whitespace literal tokens:
-//
-// <s-exp>      ::= <atom> | <list>
-// <atom>       ::= <bool> | <integer> | <string> | <symbol>
-// <list>       ::= '(' <s-exp>* <extra-info>? ')'
-// <extra-info> ::= '{' <extra-elem>* '}'
-// <extra-elem> ::= <symbol> <s-exp> ','
-//
-// Here, <string>s are double-quoted strings with backslash escaping and
-// <symbol>s are sequences of consecutive non-whitespace characters that do not
-// include commas (,), parentheses (()), curly braces ({}), or the double-quote
-// character (").
-//
-// In addition, the <extra-info> is considered a map from symbol labels to
-// S-expression values, and as such each symbol used as a key in an <extra-info>
-// block should only appear once as a key within that block.
-class SExpression : public ZoneAllocated {
- public:
-  explicit SExpression(intptr_t start = kInvalidPos) : start_(start) {}
-  virtual ~SExpression() {}
-
-  static intptr_t const kInvalidPos = -1;
-
-  static SExpression* FromCString(Zone* zone, const char* cstr);
-  const char* ToCString(Zone* zone) const;
-  intptr_t start() const { return start_; }
-
-#define S_EXPRESSION_TYPE_CHECK(name, value_type)                              \
-  bool Is##name() const { return (As##name() != nullptr); }                    \
-  SExp##name* As##name() {                                                     \
-    auto const const_this = const_cast<const SExpression*>(this);              \
-    return const_cast<SExp##name*>(const_this->As##name());                    \
-  }                                                                            \
-  virtual const SExp##name* As##name() const { return nullptr; }
-
-  FOR_EACH_S_EXPRESSION(S_EXPRESSION_TYPE_CHECK)
-  FOR_EACH_ABSTRACT_S_EXPRESSION(S_EXPRESSION_TYPE_CHECK)
-
-  virtual const char* DebugName() const = 0;
-  virtual bool Equals(SExpression* sexp) const = 0;
-  virtual void SerializeTo(Zone* zone,
-                           BaseTextBuffer* buffer,
-                           const char* indent,
-                           intptr_t width = 80) const = 0;
-  virtual void SerializeToLine(BaseTextBuffer* buffer) const = 0;
-
- private:
-  // Starting character position of the s-expression in the original
-  // serialization, if it was deserialized.
-  intptr_t const start_;
-  DISALLOW_COPY_AND_ASSIGN(SExpression);
-};
-
-class SExpAtom : public SExpression {
- public:
-  explicit SExpAtom(intptr_t start = kInvalidPos) : SExpression(start) {}
-
-  virtual const SExpAtom* AsAtom() const { return this; }
-  // No atoms have sub-elements, so they always print to a single line.
-  virtual void SerializeTo(Zone* zone,
-                           BaseTextBuffer* buffer,
-                           const char* indent,
-                           intptr_t width = 80) const {
-    SerializeToLine(buffer);
-  }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(SExpAtom);
-};
-
-#define DEFINE_S_EXPRESSION_TYPE_CHECK(name)                                   \
-  virtual const SExp##name* As##name() const { return this; }                  \
-  virtual const char* DebugName() const { return #name; }
-
-// The various concrete S-expression atom classes are thin wrappers around
-// their contained value that includes serialization and type check methods.
-#define DEFINE_S_EXPRESSION_ATOM_CLASS(name, value_type)                       \
-  class SExp##name : public SExpAtom {                                         \
-   public:                                                                     \
-    explicit SExp##name(value_type val, intptr_t start = kInvalidPos)          \
-        : SExpAtom(start), val_(val) {}                                        \
-    value_type value() const { return val_; }                                  \
-    virtual bool Equals(SExpression* sexp) const;                              \
-    bool Equals(value_type val) const;                                         \
-    virtual void SerializeToLine(BaseTextBuffer* buffer) const;                \
-    DEFINE_S_EXPRESSION_TYPE_CHECK(name)                                       \
-   private:                                                                    \
-    value_type const val_;                                                     \
-    DISALLOW_COPY_AND_ASSIGN(SExp##name);                                      \
-  };
-
-FOR_EACH_S_EXPRESSION_ATOM(DEFINE_S_EXPRESSION_ATOM_CLASS)
-
-// A list of S-expressions. Unlike normal S-expressions, an S-expression list
-// also contains a hash map kept separate from the elements, which we use for
-// extra non-argument information for IL instructions.
-class SExpList : public SExpression {
- public:
-  explicit SExpList(Zone* zone, intptr_t start = kInvalidPos)
-      : SExpression(start), contents_(zone, 2), extra_info_(zone) {}
-
-  using ExtraInfoHashMap = CStringMap<SExpression*>;
-
-  void Add(SExpression* sexp);
-  void AddExtra(const char* label, SExpression* value);
-
-  SExpression* At(intptr_t i) const { return contents_.At(i); }
-  intptr_t Length() const { return contents_.length(); }
-
-  intptr_t ExtraLength() const { return extra_info_.Length(); }
-  ExtraInfoHashMap::Iterator ExtraIterator() const {
-    return extra_info_.GetIterator();
-  }
-  bool ExtraHasKey(const char* cstr) const { return extra_info_.HasKey(cstr); }
-  SExpression* ExtraLookupValue(const char* cstr) const {
-    return extra_info_.LookupValue(cstr);
-  }
-
-  // Shortcut for retrieving the tag from a tagged list (list that contains an
-  // initial symbol). Returns nullptr if the list is not a tagged list.
-  SExpSymbol* Tag() const {
-    if (Length() == 0 || !At(0)->IsSymbol()) return nullptr;
-    return At(0)->AsSymbol();
-  }
-
-  DEFINE_S_EXPRESSION_TYPE_CHECK(List)
-  virtual bool Equals(SExpression* sexp) const;
-  virtual void SerializeTo(Zone* zone,
-                           BaseTextBuffer* buffer,
-                           const char* indent,
-                           intptr_t width = 80) const;
-  virtual void SerializeToLine(BaseTextBuffer* buffer) const;
-
- private:
-  static const char* const kElemIndent;
-  static const char* const kExtraIndent;
-
-  void SerializeExtraInfoTo(Zone* zone,
-                            BaseTextBuffer* buffer,
-                            const char* indent,
-                            int width) const;
-  void SerializeExtraInfoToLine(BaseTextBuffer* buffer) const;
-
-  ZoneGrowableArray<SExpression*> contents_;
-  ExtraInfoHashMap extra_info_;
-
-  DISALLOW_COPY_AND_ASSIGN(SExpList);
-};
-
-class SExpParser : public ValueObject {
- public:
-  SExpParser(Zone* zone, const char* cstr)
-      : SExpParser(zone, cstr, strlen(cstr)) {}
-  SExpParser(Zone* zone, const char* cstr, intptr_t len)
-      : zone_(zone),
-        buffer_(ASSERT_NOTNULL(cstr)),
-        buffer_size_(strnlen(cstr, len)),
-        cur_label_(nullptr),
-        cur_value_(nullptr),
-        list_stack_(zone, 2),
-        in_extra_stack_(zone, 2),
-        extra_start_stack_(zone, 2),
-        cur_label_stack_(zone, 2),
-        error_message_(nullptr) {}
-
-  // Constants used in serializing and deserializing S-expressions.
-  static const char* const kBoolTrueSymbol;
-  static const char* const kBoolFalseSymbol;
-  static char const kDoubleExponentChar;
-  static const char* const kDoubleInfinitySymbol;
-  static const char* const kDoubleNaNSymbol;
-
-  struct ErrorStrings : AllStatic {
-    static const char* const kOpenString;
-    static const char* const kBadUnicodeEscape;
-    static const char* const kOpenSExpList;
-    static const char* const kOpenMap;
-    static const char* const kNestedMap;
-    static const char* const kMapOutsideList;
-    static const char* const kNonSymbolLabel;
-    static const char* const kNoMapLabel;
-    static const char* const kRepeatedMapLabel;
-    static const char* const kNoMapValue;
-    static const char* const kExtraMapValue;
-    static const char* const kUnexpectedComma;
-    static const char* const kUnexpectedRightParen;
-    static const char* const kUnexpectedRightCurly;
-  };
-
-  intptr_t error_pos() const { return error_pos_; }
-  const char* error_message() const { return error_message_; }
-
-  const char* Input() const { return buffer_; }
-  SExpression* Parse();
-  DART_NORETURN void ReportError() const;
-
- private:
-#define S_EXP_TOKEN_LIST(M)                                                    \
-  M(LeftParen)                                                                 \
-  M(RightParen)                                                                \
-  M(Comma)                                                                     \
-  M(LeftCurly)                                                                 \
-  M(RightCurly)                                                                \
-  M(QuotedString)                                                              \
-  M(Integer)                                                                   \
-  M(Double)                                                                    \
-  M(Boolean)                                                                   \
-  M(Symbol)
-
-  // clang-format off
-#define DEFINE_S_EXP_TOKEN_ENUM_LINE(name) k##name,
-  enum TokenType {
-    S_EXP_TOKEN_LIST(DEFINE_S_EXP_TOKEN_ENUM_LINE)
-    kMaxTokens,
-  };
-#undef DEFINE_S_EXP_TOKEN_ENUM
-  // clang-format on
-
-  class Token : public ZoneAllocated {
-   public:
-    Token(TokenType type, const char* cstr, intptr_t len)
-        : type_(type), cstr_(cstr), len_(len) {}
-
-    TokenType type() const { return type_; }
-    intptr_t length() const { return len_; }
-    const char* cstr() const { return cstr_; }
-    const char* DebugName() const { return TokenNames[type()]; }
-    const char* ToCString(Zone* zone);
-
-   private:
-    static const char* const TokenNames[kMaxTokens];
-
-    TokenType const type_;
-    const char* const cstr_;
-    intptr_t const len_;
-  };
-
-  SExpression* TokenToSExpression(Token* token);
-  Token* GetNextToken();
-  void Reset();
-  void StoreError(intptr_t pos, const char* format, ...) PRINTF_ATTRIBUTE(3, 4);
-
-  static bool IsSymbolContinue(char c);
-
-  Zone* const zone_;
-  const char* const buffer_;
-  intptr_t const buffer_size_;
-  intptr_t cur_pos_ = 0;
-  bool in_extra_ = false;
-  intptr_t extra_start_ = -1;
-  const char* cur_label_;
-  SExpression* cur_value_;
-  ZoneGrowableArray<SExpList*> list_stack_;
-  ZoneGrowableArray<bool> in_extra_stack_;
-  ZoneGrowableArray<intptr_t> extra_start_stack_;
-  ZoneGrowableArray<const char*> cur_label_stack_;
-  intptr_t error_pos_ = -1;
-  const char* error_message_;
-};
-
-}  // namespace dart
-
-#endif  // RUNTIME_VM_COMPILER_BACKEND_SEXPRESSION_H_
diff --git a/runtime/vm/compiler/backend/sexpression_test.cc b/runtime/vm/compiler/backend/sexpression_test.cc
deleted file mode 100644
index 8c0edac..0000000
--- a/runtime/vm/compiler/backend/sexpression_test.cc
+++ /dev/null
@@ -1,355 +0,0 @@
-// Copyright (c) 2019, 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/sexpression.h"
-
-#include <cmath>
-#include "platform/assert.h"
-#include "vm/unit_test.h"
-
-namespace dart {
-
-#define EXPECT_SEXP_PARSE_ERROR(sexp, parser, pos, message)                    \
-  do {                                                                         \
-    if (sexp != nullptr) {                                                     \
-      dart::Expect(__FILE__, __LINE__)                                         \
-          .Fail("parse unexpectedly succeeded for \"%s\"", parser.Input());    \
-    }                                                                          \
-    EXPECT_EQ(pos, parser.error_pos());                                        \
-    EXPECT_STREQ(message, parser.error_message());                             \
-  } while (false);
-
-#define EXPECT_SEXP_PARSE_SUCCESS(sexp, parser)                                \
-  do {                                                                         \
-    if (sexp == nullptr) {                                                     \
-      EXPECT_NOTNULL(parser.error_message());                                  \
-      dart::Expect(__FILE__, __LINE__)                                         \
-          .Fail("parse unexpectedly failed at \"%s\": %" Pd ": %s",            \
-                parser.Input() + parser.error_pos(), parser.error_pos(),       \
-                parser.error_message());                                       \
-    }                                                                          \
-  } while (false);
-
-static const char* const shared_sexp_cstr =
-    "(def v0 (Constant 3) { type (CompileType 147 { nullable false, name "
-    "\"T{Smi}\"}), })";
-
-static void CheckDeserializedSExpParts(SExpression* sexp) {
-  EXPECT_NOTNULL(sexp);
-  EXPECT(sexp->IsList());
-  SExpList* list = sexp->AsList();
-  EXPECT_EQ(3, list->Length());
-  EXPECT_NOTNULL(list->At(0));
-  EXPECT(list->At(0)->IsSymbol());
-  EXPECT_STREQ("def", list->At(0)->AsSymbol()->value());
-  EXPECT_NOTNULL(list->At(1));
-  EXPECT(list->At(1)->IsSymbol());
-  EXPECT_STREQ("v0", list->At(1)->AsSymbol()->value());
-  EXPECT_NOTNULL(list->At(2));
-  EXPECT(list->At(2)->IsList());
-
-  SExpList* sublist = list->At(2)->AsList();
-  EXPECT_EQ(2, sublist->Length());
-  EXPECT_NOTNULL(sublist->At(0));
-  EXPECT(sublist->At(0)->IsSymbol());
-  EXPECT_STREQ("Constant", sublist->At(0)->AsSymbol()->value());
-  EXPECT_NOTNULL(sublist->At(1));
-  EXPECT(sublist->At(1)->IsInteger());
-  EXPECT_EQ(3, sublist->At(1)->AsInteger()->value());
-  EXPECT_EQ(0, sublist->ExtraLength());
-
-  EXPECT_EQ(1, list->ExtraLength());
-  EXPECT(list->ExtraHasKey("type"));
-  EXPECT(list->ExtraLookupValue("type")->IsList());
-
-  SExpList* ctype = list->ExtraLookupValue("type")->AsList();
-  EXPECT_EQ(2, ctype->Length());
-  EXPECT_NOTNULL(ctype->At(0));
-  EXPECT(ctype->At(0)->IsSymbol());
-  EXPECT_STREQ("CompileType", ctype->At(0)->AsSymbol()->value());
-  EXPECT_NOTNULL(ctype->At(1));
-  EXPECT(ctype->At(1)->IsInteger());
-  EXPECT_EQ(147, ctype->At(1)->AsInteger()->value());
-
-  EXPECT_EQ(2, ctype->ExtraLength());
-  EXPECT(ctype->ExtraHasKey("nullable"));
-  EXPECT(ctype->ExtraLookupValue("nullable")->IsBool());
-  EXPECT(!ctype->ExtraLookupValue("nullable")->AsBool()->value());
-  EXPECT(ctype->ExtraHasKey("name"));
-  EXPECT(ctype->ExtraLookupValue("name")->IsString());
-  EXPECT_STREQ(ctype->ExtraLookupValue("name")->AsString()->value(), "T{Smi}");
-}
-
-ISOLATE_UNIT_TEST_CASE(DeserializeSExp) {
-  Zone* const zone = Thread::Current()->zone();
-  SExpression* sexp = SExpression::FromCString(zone, shared_sexp_cstr);
-  CheckDeserializedSExpParts(sexp);
-
-  // Treating escaped backslash appropriately so string is terminated.
-  {
-    const char* const cstr = "(def v0 (Constant 3) { foo \"123\\\\\" })";
-    SExpParser parser(zone, cstr, strlen(cstr));
-    SExpression* const sexp = parser.Parse();
-    EXPECT_SEXP_PARSE_SUCCESS(sexp, parser);
-    EXPECT(sexp->IsList());
-    EXPECT_EQ(1, sexp->AsList()->ExtraLength());
-    EXPECT(sexp->AsList()->ExtraHasKey("foo"));
-    auto val = sexp->AsList()->ExtraLookupValue("foo");
-    EXPECT(val->IsString());
-    EXPECT_STREQ("123\\", val->AsString()->value());
-  }
-  // Valid unicode escapes are properly handled.
-  {
-    const char* const cstr =
-        "(def v0 (Constant 3) { foo \"\\u0001\\u0020\\u0054\" })";
-    SExpParser parser(zone, cstr, strlen(cstr));
-    SExpression* const sexp = parser.Parse();
-    EXPECT_SEXP_PARSE_SUCCESS(sexp, parser);
-    EXPECT(sexp->IsList());
-    EXPECT_EQ(1, sexp->AsList()->ExtraLength());
-    EXPECT(sexp->AsList()->ExtraHasKey("foo"));
-    auto val = sexp->AsList()->ExtraLookupValue("foo");
-    EXPECT(val->IsString());
-    EXPECT_STREQ("\x01 T", val->AsString()->value());
-  }
-}
-
-ISOLATE_UNIT_TEST_CASE(DeserializeSExpNumbers) {
-  Zone* const zone = Thread::Current()->zone();
-
-  // Negative integers are handled.
-  {
-    const char* const cstr = "(-4 -50 -1414243)";
-    SExpParser parser(zone, cstr, strlen(cstr));
-    SExpression* const sexp = parser.Parse();
-    EXPECT_SEXP_PARSE_SUCCESS(sexp, parser);
-    EXPECT(sexp->IsList());
-    auto list = sexp->AsList();
-    EXPECT_EQ(3, list->Length());
-    EXPECT_EQ(0, list->ExtraLength());
-    for (intptr_t i = 0; i < list->Length(); i++) {
-      EXPECT(list->At(i)->IsInteger());
-      EXPECT(list->At(i)->AsInteger()->value() < 0);
-    }
-  }
-
-  // Various decimal/exponent Doubles are appropriately handled.
-  {
-    const char* const cstr = "(1.05 0.05 .03 1e100 1e-100)";
-    SExpParser parser(zone, cstr, strlen(cstr));
-    SExpression* const sexp = parser.Parse();
-    EXPECT_SEXP_PARSE_SUCCESS(sexp, parser);
-    EXPECT(sexp->IsList());
-    auto list = sexp->AsList();
-    EXPECT_EQ(5, list->Length());
-    EXPECT_EQ(0, list->ExtraLength());
-    EXPECT(list->At(0)->IsDouble());
-    double val = list->At(0)->AsDouble()->value();
-    EXPECT(val > 1.04 && val < 1.06);
-    EXPECT(list->At(1)->IsDouble());
-    val = list->At(1)->AsDouble()->value();
-    EXPECT(val > 0.04 && val < 0.06);
-    EXPECT(list->At(2)->IsDouble());
-    val = list->At(2)->AsDouble()->value();
-    EXPECT(val > 0.02 && val < 0.04);
-    EXPECT(list->At(3)->IsDouble());
-    val = list->At(3)->AsDouble()->value();
-    EXPECT(val > 0.9e100 && val < 1.1e100);
-    EXPECT(list->At(4)->IsDouble());
-    val = list->At(4)->AsDouble()->value();
-    EXPECT(val > 0.9e-100 && val < 1.1e-100);
-  }
-
-  // Special Double symbols are appropriately handled.
-  {
-    const char* const cstr = "(NaN Infinity -Infinity)";
-    SExpParser parser(zone, cstr, strlen(cstr));
-    SExpression* const sexp = parser.Parse();
-    EXPECT_SEXP_PARSE_SUCCESS(sexp, parser);
-    EXPECT(sexp->IsList());
-    auto list = sexp->AsList();
-    EXPECT_EQ(3, list->Length());
-    EXPECT_EQ(0, list->ExtraLength());
-    EXPECT(list->At(0)->IsDouble());
-    double val = list->At(0)->AsDouble()->value();
-    EXPECT(isnan(val));
-    EXPECT(list->At(1)->IsDouble());
-    val = list->At(1)->AsDouble()->value();
-    EXPECT(val > 0.0);
-    EXPECT(isinf(val));
-    EXPECT(list->At(2)->IsDouble());
-    val = list->At(2)->AsDouble()->value();
-    EXPECT(val < 0.0);
-    EXPECT(isinf(val));
-  }
-}
-
-ISOLATE_UNIT_TEST_CASE(DeserializeSExpRoundTrip) {
-  Zone* const zone = Thread::Current()->zone();
-  SExpression* sexp = SExpression::FromCString(zone, shared_sexp_cstr);
-
-  TextBuffer buf(100);
-  sexp->SerializeTo(zone, &buf, "", 9999);
-  SExpression* round_trip = SExpression::FromCString(zone, buf.buffer());
-  CheckDeserializedSExpParts(round_trip);
-  EXPECT(sexp->Equals(round_trip));
-
-  char* const old_serialization = buf.Steal();
-  round_trip->SerializeTo(zone, &buf, "", 9999);
-  char* const new_serialization = buf.buffer();
-  EXPECT_STREQ(old_serialization, new_serialization);
-  free(old_serialization);
-}
-
-ISOLATE_UNIT_TEST_CASE(DeserializeSExpMapsJoined) {
-  Zone* const zone = Thread::Current()->zone();
-  // Same as shared_sexp_cstr except we split the map on the CompileType into
-  // two parts.
-  const char* const cstr =
-      "(def v0 (Constant 3) { type (CompileType { nullable false } 147 { name "
-      "\"T{Smi}\"}), })";
-  SExpression* sexp = SExpression::FromCString(zone, cstr);
-  CheckDeserializedSExpParts(sexp);
-}
-
-ISOLATE_UNIT_TEST_CASE(DeserializeSExpFailures) {
-  Zone* const zone = Thread::Current()->zone();
-  // Unterminated s-exp list
-  {
-    const char* const before_start = "(def v0 ";
-    const char* const after_start = "(Constant 3";
-    const char* const cstr =
-        OS::SCreate(zone, "%s%s", before_start, after_start);
-    const intptr_t start_pos = strlen(before_start);
-    const intptr_t error_pos = strlen(cstr);
-    SExpParser parser(zone, cstr, strlen(cstr));
-    SExpression* const sexp = parser.Parse();
-    const char* const expected_message =
-        OS::SCreate(zone, SExpParser::ErrorStrings::kOpenSExpList, start_pos);
-    EXPECT_SEXP_PARSE_ERROR(sexp, parser, error_pos, expected_message);
-  }
-  // Non-symbol label in map pair
-  {
-    const char* const before_error = "(def v0 (Constant 3) { ";
-    const intptr_t error_pos = strlen(before_error);
-    const char* const error = "3 4 })";
-    const char* const cstr = OS::SCreate(zone, "%s%s", before_error, error);
-    SExpParser parser(zone, cstr, strlen(cstr));
-    SExpression* const sexp = parser.Parse();
-    const char* const expected_message =
-        SExpParser::ErrorStrings::kNonSymbolLabel;
-    EXPECT_SEXP_PARSE_ERROR(sexp, parser, error_pos, expected_message);
-  }
-  // No values in a map pair
-  {
-    const char* const label = "foo";
-    const char* const before_error =
-        OS::SCreate(zone, "(def v0 (Constant 3) { %s ", label);
-    const intptr_t error_pos = strlen(before_error);
-    const char* const error = "})";
-    const char* const cstr = OS::SCreate(zone, "%s%s", before_error, error);
-    SExpParser parser(zone, cstr, strlen(cstr));
-    SExpression* const sexp = parser.Parse();
-    const char* const expected_message =
-        OS::SCreate(zone, SExpParser::ErrorStrings::kNoMapValue, label);
-    EXPECT_SEXP_PARSE_ERROR(sexp, parser, error_pos, expected_message);
-  }
-  // Multiple values in a map pair
-  {
-    const char* const label = "foo";
-    const char* const before_error =
-        OS::SCreate(zone, "(def v0 (Constant 3) { %s 4 ", label);
-    const intptr_t error_pos = strlen(before_error);
-    const char* const error = "5, })";
-    const char* const cstr = OS::SCreate(zone, "%s%s", before_error, error);
-    SExpParser parser(zone, cstr, strlen(cstr));
-    SExpression* const sexp = parser.Parse();
-    const char* const expected_message =
-        OS::SCreate(zone, SExpParser::ErrorStrings::kExtraMapValue, label);
-    EXPECT_SEXP_PARSE_ERROR(sexp, parser, error_pos, expected_message);
-  }
-  // Unterminated quoted string
-  {
-    const char* const before_string =
-        OS::SCreate(zone, "(def v0 (Constant 3) { foo ");
-    const intptr_t string_pos = strlen(before_string);
-    const char* const error = "\"abc })";
-    const char* const cstr = OS::SCreate(zone, "%s%s", before_string, error);
-    const intptr_t error_pos = strlen(cstr);
-    SExpParser parser(zone, cstr, strlen(cstr));
-    SExpression* const sexp = parser.Parse();
-    const char* const expected_message =
-        OS::SCreate(zone, SExpParser::ErrorStrings::kOpenString, string_pos);
-    EXPECT_SEXP_PARSE_ERROR(sexp, parser, error_pos, expected_message);
-  }
-  // Unterminated extra info map
-  {
-    const char* const before_map = "(def v0 (Constant 3) ";
-    const intptr_t map_pos = strlen(before_map);
-    const char* const map_start = "{ foo 3, ";
-    const char* const before_error =
-        OS::SCreate(zone, "%s%s", before_map, map_start);
-    const intptr_t error_pos = strlen(before_error);
-    const char* const error = ")";
-    const char* const cstr = OS::SCreate(zone, "%s%s", before_error, error);
-    SExpParser parser(zone, cstr, strlen(cstr));
-    SExpression* const sexp = parser.Parse();
-    const char* const expected_message =
-        OS::SCreate(zone, SExpParser::ErrorStrings::kOpenMap, map_pos);
-    EXPECT_SEXP_PARSE_ERROR(sexp, parser, error_pos, expected_message);
-  }
-  // Repeated extra info map label
-  {
-    const char* const label = "foo";
-    const char* const before_error =
-        OS::SCreate(zone, "(def v0 (Constant 3) { %s 3, ", label);
-    const intptr_t error_pos = strlen(before_error);
-    const char* const error = OS::SCreate(zone, "%s 4, })", label);
-    const char* const cstr = OS::SCreate(zone, "%s%s", before_error, error);
-    SExpParser parser(zone, cstr, strlen(cstr));
-    SExpression* const sexp = parser.Parse();
-    const char* const expected_message =
-        OS::SCreate(zone, SExpParser::ErrorStrings::kRepeatedMapLabel, label);
-    EXPECT_SEXP_PARSE_ERROR(sexp, parser, error_pos, expected_message);
-  }
-  // Unicode escape with non-hex digits.
-  {
-    const char* const before_error = "(def v0 (Constant 3) { foo \"123";
-    const intptr_t error_pos = strlen(before_error);
-    const char* const error = "\\u12FG\" })";
-    const char* const cstr = OS::SCreate(zone, "%s%s", before_error, error);
-    SExpParser parser(zone, cstr, strlen(cstr));
-    SExpression* const sexp = parser.Parse();
-    const char* const expected_message =
-        SExpParser::ErrorStrings::kBadUnicodeEscape;
-    EXPECT_SEXP_PARSE_ERROR(sexp, parser, error_pos, expected_message);
-  }
-  // Unicode escape with less than four hex digits.
-  {
-    const char* const before_error = "(def v0 (Constant 3) { foo \"123";
-    const intptr_t error_pos = strlen(before_error);
-    const char* const error = "\\u12\" })";
-    const char* const cstr = OS::SCreate(zone, "%s%s", before_error, error);
-    SExpParser parser(zone, cstr, strlen(cstr));
-    SExpression* const sexp = parser.Parse();
-    const char* const expected_message =
-        SExpParser::ErrorStrings::kBadUnicodeEscape;
-    EXPECT_SEXP_PARSE_ERROR(sexp, parser, error_pos, expected_message);
-  }
-  // Treating backslashed quote appropriately to detect unterminated string
-  {
-    const char* const before_string = "(def v0 (Constant 3) { foo ";
-    const intptr_t string_pos = strlen(before_string);
-    const char* const error = "\"123\\\" })";
-    const char* const cstr = OS::SCreate(zone, "%s%s", before_string, error);
-    const intptr_t error_pos = strlen(cstr);
-    SExpParser parser(zone, cstr, strlen(cstr));
-    SExpression* const sexp = parser.Parse();
-    const char* const expected_message =
-        OS::SCreate(zone, SExpParser::ErrorStrings::kOpenString, string_pos);
-    EXPECT_SEXP_PARSE_ERROR(sexp, parser, error_pos, expected_message);
-  }
-}
-
-}  // namespace dart
diff --git a/runtime/vm/compiler/compiler_pass.cc b/runtime/vm/compiler/compiler_pass.cc
index 2a6f91f..1dfcdce 100644
--- a/runtime/vm/compiler/compiler_pass.cc
+++ b/runtime/vm/compiler/compiler_pass.cc
@@ -8,9 +8,7 @@
 #include "vm/compiler/backend/branch_optimizer.h"
 #include "vm/compiler/backend/constant_propagator.h"
 #include "vm/compiler/backend/flow_graph_checker.h"
-#include "vm/compiler/backend/il_deserializer.h"
 #include "vm/compiler/backend/il_printer.h"
-#include "vm/compiler/backend/il_serializer.h"
 #include "vm/compiler/backend/inliner.h"
 #include "vm/compiler/backend/linearscan.h"
 #include "vm/compiler/backend/range_analysis.h"
@@ -80,14 +78,6 @@
                       "List of comma separated compilation passes flags. "
                       "Use -Name to disable a pass, Name to print IL after it. "
                       "Do --compiler-passes=help for more information.");
-DEFINE_FLAG(bool,
-            early_round_trip_serialization,
-            false,
-            "Perform early round trip serialization compiler pass.");
-DEFINE_FLAG(bool,
-            late_round_trip_serialization,
-            false,
-            "Perform late round trip serialization compiler pass.");
 DECLARE_FLAG(bool, print_flow_graph);
 DECLARE_FLAG(bool, print_flow_graph_optimized);
 
@@ -286,9 +276,6 @@
     PipelineMode mode,
     CompilerPassState* pass_state) {
   INVOKE_PASS(ComputeSSA);
-  if (FLAG_early_round_trip_serialization) {
-    INVOKE_PASS(RoundTripSerialization);
-  }
   INVOKE_PASS(SetOuterInliningId);
   INVOKE_PASS(TypePropagation);
   INVOKE_PASS(Canonicalize);
@@ -309,10 +296,6 @@
   INVOKE_PASS_AOT(DelayAllocations);
   INVOKE_PASS(EliminateWriteBarriers);
   INVOKE_PASS(FinalizeGraph);
-  INVOKE_PASS_AOT(SerializeGraph);
-  if (FLAG_late_round_trip_serialization) {
-    INVOKE_PASS(RoundTripSerialization);
-  }
   INVOKE_PASS(AllocateRegisters);
   INVOKE_PASS(ReorderBlocks);
   return pass_state->flow_graph();
@@ -321,9 +304,6 @@
 FlowGraph* CompilerPass::RunPipeline(PipelineMode mode,
                                      CompilerPassState* pass_state) {
   INVOKE_PASS(ComputeSSA);
-  if (FLAG_early_round_trip_serialization) {
-    INVOKE_PASS(RoundTripSerialization);
-  }
   INVOKE_PASS_AOT(ApplyClassIds);
   INVOKE_PASS_AOT(TypePropagation);
   INVOKE_PASS(ApplyICData);
@@ -382,12 +362,6 @@
   INVOKE_PASS(AllocationSinking_DetachMaterializations);
   INVOKE_PASS(EliminateWriteBarriers);
   INVOKE_PASS(FinalizeGraph);
-  // If we are serializing the flow graph, do it now before we start
-  // doing register allocation.
-  INVOKE_PASS_AOT(SerializeGraph);
-  if (FLAG_late_round_trip_serialization) {
-    INVOKE_PASS(RoundTripSerialization);
-  }
   INVOKE_PASS(AllocateRegisters);
   INVOKE_PASS(ReorderBlocks);
   return pass_state->flow_graph();
@@ -576,27 +550,4 @@
   flow_graph->RemoveRedefinitions();
 });
 
-#if defined(DART_PRECOMPILER)
-COMPILER_PASS(SerializeGraph, {
-  if (state->precompiler == nullptr) return false;
-  if (auto stream = state->precompiler->il_serialization_stream()) {
-    auto file_write = Dart::file_write_callback();
-    ASSERT(file_write != nullptr);
-
-    const intptr_t kInitialBufferSize = 1 * MB;
-    TextBuffer buffer(kInitialBufferSize);
-    StackZone stack_zone(Thread::Current());
-    FlowGraphSerializer::SerializeToBuffer(stack_zone.GetZone(), flow_graph,
-                                           &buffer);
-
-    file_write(buffer.buffer(), buffer.length(), stream);
-  }
-});
-#endif
-
-COMPILER_PASS(RoundTripSerialization, {
-  FlowGraphDeserializer::RoundTripSerialization(state);
-  ASSERT(state->flow_graph() != nullptr);
-})
-
 }  // namespace dart
diff --git a/runtime/vm/compiler/compiler_pass.h b/runtime/vm/compiler/compiler_pass.h
index 1904561..39dc9bd 100644
--- a/runtime/vm/compiler/compiler_pass.h
+++ b/runtime/vm/compiler/compiler_pass.h
@@ -44,9 +44,7 @@
   V(OptimizeTypedDataAccesses)                                                 \
   V(RangeAnalysis)                                                             \
   V(ReorderBlocks)                                                             \
-  V(RoundTripSerialization)                                                    \
   V(SelectRepresentations)                                                     \
-  V(SerializeGraph)                                                            \
   V(SetOuterInliningId)                                                        \
   V(TryCatchOptimization)                                                      \
   V(TryOptimizePatterns)                                                       \
diff --git a/runtime/vm/compiler/compiler_sources.gni b/runtime/vm/compiler/compiler_sources.gni
index edfa863..8cc4b39 100644
--- a/runtime/vm/compiler/compiler_sources.gni
+++ b/runtime/vm/compiler/compiler_sources.gni
@@ -57,13 +57,9 @@
   "backend/il.h",
   "backend/il_arm.cc",
   "backend/il_arm64.cc",
-  "backend/il_deserializer.cc",
-  "backend/il_deserializer.h",
   "backend/il_ia32.cc",
   "backend/il_printer.cc",
   "backend/il_printer.h",
-  "backend/il_serializer.cc",
-  "backend/il_serializer.h",
   "backend/il_x64.cc",
   "backend/inliner.cc",
   "backend/inliner.h",
@@ -79,8 +75,6 @@
   "backend/range_analysis.h",
   "backend/redundancy_elimination.cc",
   "backend/redundancy_elimination.h",
-  "backend/sexpression.cc",
-  "backend/sexpression.h",
   "backend/slot.cc",
   "backend/slot.h",
   "backend/type_propagator.cc",
@@ -175,7 +169,6 @@
   "backend/range_analysis_test.cc",
   "backend/reachability_fence_test.cc",
   "backend/redundancy_elimination_test.cc",
-  "backend/sexpression_test.cc",
   "backend/slot_test.cc",
   "backend/type_propagator_test.cc",
   "backend/typed_data_aot_test.cc",
diff --git a/runtime/vm/dart.cc b/runtime/vm/dart.cc
index 65332f5..3835109 100644
--- a/runtime/vm/dart.cc
+++ b/runtime/vm/dart.cc
@@ -53,10 +53,6 @@
 DEFINE_FLAG(bool, trace_shutdown, false, "Trace VM shutdown on stderr");
 DECLARE_FLAG(bool, strong);
 
-#if defined(DART_PRECOMPILED_RUNTIME)
-DEFINE_FLAG(bool, print_llvm_constant_pool, false, "Print LLVM constant pool");
-#endif
-
 Isolate* Dart::vm_isolate_ = NULL;
 int64_t Dart::start_time_micros_ = 0;
 ThreadPool* Dart::thread_pool_ = NULL;
@@ -811,52 +807,6 @@
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
 }
 
-#if defined(DART_PRECOMPILED_RUNTIME)
-static void PrintLLVMConstantPool(Thread* T, Isolate* I) {
-  StackZone printing_zone(T);
-  HandleScope printing_scope(T);
-  TextBuffer b(1000);
-  const auto& constants = GrowableObjectArray::Handle(
-      I->group()->object_store()->llvm_constant_pool());
-  if (constants.IsNull()) {
-    b.AddString("No constant pool information in snapshot.\n\n");
-  } else {
-    auto const len = constants.Length();
-    b.Printf("Constant pool contents (length %" Pd "):\n", len);
-    auto& obj = Object::Handle();
-    for (intptr_t i = 0; i < len; i++) {
-      obj = constants.At(i);
-      b.Printf("  %5" Pd ": ", i);
-      if (obj.IsString()) {
-        b.AddChar('"');
-        b.AddEscapedString(obj.ToCString());
-        b.AddChar('"');
-      } else {
-        b.AddString(obj.ToCString());
-      }
-      b.AddChar('\n');
-    }
-    b.AddString("End of constant pool.\n\n");
-  }
-  const auto& functions = GrowableObjectArray::Handle(
-      I->group()->object_store()->llvm_function_pool());
-  if (functions.IsNull()) {
-    b.AddString("No function pool information in snapshot.\n\n");
-  } else {
-    auto const len = functions.Length();
-    b.Printf("Function pool contents (length %" Pd "):\n", len);
-    auto& obj = Function::Handle();
-    for (intptr_t i = 0; i < len; i++) {
-      obj ^= functions.At(i);
-      ASSERT(!obj.IsNull());
-      b.Printf("  %5" Pd ": %s\n", i, obj.ToFullyQualifiedCString());
-    }
-    b.AddString("End of function pool.\n\n");
-  }
-  THR_Print("%s", b.buffer());
-}
-#endif
-
 ErrorPtr Dart::InitializeIsolate(const uint8_t* snapshot_data,
                                  const uint8_t* snapshot_instructions,
                                  const uint8_t* kernel_buffer,
@@ -913,11 +863,6 @@
 #if !defined(TARGET_ARCH_IA32)
     ASSERT(IG->object_store()->build_method_extractor_code() != Code::null());
 #endif
-#if defined(DART_PRECOMPILED_RUNTIME)
-    if (FLAG_print_llvm_constant_pool) {
-      PrintLLVMConstantPool(T, I);
-    }
-#endif  // defined(DART_PRECOMPILED_RUNTIME)
   } else {
 #if !defined(TARGET_ARCH_IA32)
     if (I != Dart::vm_isolate()) {
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 19f8743..cdda785 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -2256,8 +2256,6 @@
   }
 
  private:
-  friend class FlowGraphSerializer;  // For is_megamorphic()
-
   static ICDataPtr New();
 
   // Grows the array and also sets the argument to the index that should be used
diff --git a/runtime/vm/object_store.h b/runtime/vm/object_store.h
index 7554f4d..55f8b6d 100644
--- a/runtime/vm/object_store.h
+++ b/runtime/vm/object_store.h
@@ -169,9 +169,6 @@
   RW(Function, complete_on_async_return)                                       \
   RW(Function, complete_on_async_error)                                        \
   RW(Class, async_star_stream_controller)                                      \
-  RW(GrowableObjectArray, llvm_constant_pool)                                  \
-  RW(GrowableObjectArray, llvm_function_pool)                                  \
-  RW(Array, llvm_constant_hash_table)                                          \
   RW(CompressedStackMaps, canonicalized_stack_map_entries)                     \
   RW(ObjectPool, global_object_pool)                                           \
   RW(Array, unique_dynamic_targets)                                            \
diff --git a/tools/VERSION b/tools/VERSION
index 8f43000..cf2e335 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 13
 PATCH 0
-PRERELEASE 123
+PRERELEASE 124
 PRERELEASE_PATCH 0
\ No newline at end of file