Reapply "[vm, interpreter] Bytecode support for dynamic invocation forwarders."

Add missing entries to RAW_CLASSES_AND_FIELDS.

Change-Id: Ib90f4878d3eff81a6a059f7e38f1d6593cd85cfc
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/105820
Reviewed-by: Alexander Markov <alexmarkov@google.com>
Commit-Queue: Ryan Macnak <rmacnak@google.com>
diff --git a/runtime/vm/class_id.h b/runtime/vm/class_id.h
index f95d77f..4e23dea 100644
--- a/runtime/vm/class_id.h
+++ b/runtime/vm/class_id.h
@@ -36,6 +36,7 @@
   V(ExceptionHandlers)                                                         \
   V(Context)                                                                   \
   V(ContextScope)                                                              \
+  V(ParameterTypeCheck)                                                        \
   V(SingleTargetCache)                                                         \
   V(UnlinkedCall)                                                              \
   V(ICData)                                                                    \
diff --git a/runtime/vm/clustered_snapshot.cc b/runtime/vm/clustered_snapshot.cc
index a71b9cb..39249519 100644
--- a/runtime/vm/clustered_snapshot.cc
+++ b/runtime/vm/clustered_snapshot.cc
@@ -2104,6 +2104,71 @@
 };
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
+class ParameterTypeCheckSerializationCluster : public SerializationCluster {
+ public:
+  ParameterTypeCheckSerializationCluster()
+      : SerializationCluster("ParameterTypeCheck") {}
+  ~ParameterTypeCheckSerializationCluster() {}
+
+  void Trace(Serializer* s, RawObject* object) {
+    RawParameterTypeCheck* unlinked = ParameterTypeCheck::RawCast(object);
+    objects_.Add(unlinked);
+    PushFromTo(unlinked);
+  }
+
+  void WriteAlloc(Serializer* s) {
+    s->WriteCid(kParameterTypeCheckCid);
+    intptr_t count = objects_.length();
+    s->WriteUnsigned(count);
+    for (intptr_t i = 0; i < count; i++) {
+      RawParameterTypeCheck* check = objects_[i];
+      s->AssignRef(check);
+    }
+  }
+
+  void WriteFill(Serializer* s) {
+    intptr_t count = objects_.length();
+    for (intptr_t i = 0; i < count; i++) {
+      RawParameterTypeCheck* check = objects_[i];
+      s->Write<intptr_t>(check->ptr()->index_);
+      WriteFromTo(check);
+    }
+  }
+
+ private:
+  GrowableArray<RawParameterTypeCheck*> objects_;
+};
+#endif  // !DART_PRECOMPILED_RUNTIME
+
+class ParameterTypeCheckDeserializationCluster : public DeserializationCluster {
+ public:
+  ParameterTypeCheckDeserializationCluster() {}
+  ~ParameterTypeCheckDeserializationCluster() {}
+
+  void ReadAlloc(Deserializer* d) {
+    start_index_ = d->next_index();
+    PageSpace* old_space = d->heap()->old_space();
+    intptr_t count = d->ReadUnsigned();
+    for (intptr_t i = 0; i < count; i++) {
+      d->AssignRef(
+          AllocateUninitialized(old_space, ParameterTypeCheck::InstanceSize()));
+    }
+    stop_index_ = d->next_index();
+  }
+
+  void ReadFill(Deserializer* d) {
+    for (intptr_t id = start_index_; id < stop_index_; id++) {
+      RawParameterTypeCheck* check =
+          reinterpret_cast<RawParameterTypeCheck*>(d->Ref(id));
+      Deserializer::InitializeHeader(check, kParameterTypeCheckCid,
+                                     ParameterTypeCheck::InstanceSize());
+      check->ptr()->index_ = d->Read<intptr_t>();
+      ReadFromTo(check);
+    }
+  }
+};
+
+#if !defined(DART_PRECOMPILED_RUNTIME)
 class UnlinkedCallSerializationCluster : public SerializationCluster {
  public:
   UnlinkedCallSerializationCluster() : SerializationCluster("UnlinkedCall") {}
@@ -4275,6 +4340,8 @@
       return new (Z) ContextSerializationCluster();
     case kContextScopeCid:
       return new (Z) ContextScopeSerializationCluster();
+    case kParameterTypeCheckCid:
+      return new (Z) ParameterTypeCheckSerializationCluster();
     case kUnlinkedCallCid:
       return new (Z) UnlinkedCallSerializationCluster();
     case kICDataCid:
@@ -4712,6 +4779,8 @@
                 "<invoke field>");
   AddBaseObject(Object::nsm_dispatcher_bytecode().raw(), "Bytecode",
                 "<nsm dispatcher>");
+  AddBaseObject(Object::dynamic_invocation_forwarder_bytecode().raw(),
+                "Bytecode", "<dyn forwarder>");
 
   for (intptr_t i = 0; i < ArgumentsDescriptor::kCachedDescriptorCount; i++) {
     AddBaseObject(ArgumentsDescriptor::cached_args_descriptors_[i],
@@ -4905,6 +4974,8 @@
       return new (Z) ContextDeserializationCluster();
     case kContextScopeCid:
       return new (Z) ContextScopeDeserializationCluster();
+    case kParameterTypeCheckCid:
+      return new (Z) ParameterTypeCheckDeserializationCluster();
     case kUnlinkedCallCid:
       return new (Z) UnlinkedCallDeserializationCluster();
     case kICDataCid:
@@ -5174,6 +5245,7 @@
   AddBaseObject(Object::invoke_closure_bytecode().raw());
   AddBaseObject(Object::invoke_field_bytecode().raw());
   AddBaseObject(Object::nsm_dispatcher_bytecode().raw());
+  AddBaseObject(Object::dynamic_invocation_forwarder_bytecode().raw());
 
   for (intptr_t i = 0; i < ArgumentsDescriptor::kCachedDescriptorCount; i++) {
     AddBaseObject(ArgumentsDescriptor::cached_args_descriptors_[i]);
diff --git a/runtime/vm/compiler/frontend/bytecode_reader.cc b/runtime/vm/compiler/frontend/bytecode_reader.cc
index c180689..c747fbd 100644
--- a/runtime/vm/compiler/frontend/bytecode_reader.cc
+++ b/runtime/vm/compiler/frontend/bytecode_reader.cc
@@ -53,6 +53,7 @@
       (function.kind() != RawFunction::kImplicitStaticGetter) &&
       (function.kind() != RawFunction::kMethodExtractor) &&
       (function.kind() != RawFunction::kInvokeFieldDispatcher) &&
+      (function.kind() != RawFunction::kDynamicInvocationForwarder) &&
       (function.kind() != RawFunction::kNoSuchMethodDispatcher)) {
     return;
   }
@@ -269,6 +270,142 @@
   }
 }
 
+static intptr_t IndexFor(Zone* zone,
+                         const Function& function,
+                         const String& name) {
+  const Bytecode& bc = Bytecode::Handle(zone, function.bytecode());
+  const ObjectPool& pool = ObjectPool::Handle(zone, bc.object_pool());
+  const KBCInstr* pc = reinterpret_cast<const KBCInstr*>(bc.PayloadStart());
+
+  ASSERT(KernelBytecode::IsEntryOptionalOpcode(pc));
+  ASSERT(KernelBytecode::DecodeB(pc) ==
+         function.NumOptionalPositionalParameters());
+  ASSERT(KernelBytecode::DecodeC(pc) == function.NumOptionalNamedParameters());
+  pc = KernelBytecode::Next(pc);
+
+  const intptr_t num_opt_params = function.NumOptionalParameters();
+  const intptr_t num_fixed_params = function.num_fixed_parameters();
+  for (intptr_t i = 0; i < num_opt_params; i++) {
+    const KBCInstr* load_name = pc;
+    const KBCInstr* load_value = KernelBytecode::Next(load_name);
+    pc = KernelBytecode::Next(load_value);
+    ASSERT(KernelBytecode::IsLoadConstantOpcode(load_name));
+    ASSERT(KernelBytecode::IsLoadConstantOpcode(load_value));
+    if (pool.ObjectAt(KernelBytecode::DecodeE(load_name)) == name.raw()) {
+      return num_fixed_params + i;
+    }
+  }
+
+  UNREACHABLE();
+  return -1;
+}
+
+RawArray* BytecodeReaderHelper::CreateForwarderChecks(
+    const Function& function) {
+  ASSERT(function.kind() != RawFunction::kDynamicInvocationForwarder);
+  ASSERT(function.is_declared_in_bytecode());
+
+  TypeArguments& default_args = TypeArguments::Handle(Z);
+  if (function.bytecode_offset() != 0) {
+    AlternativeReadingScope alt(&reader_, function.bytecode_offset());
+
+    const intptr_t flags = reader_.ReadUInt();
+    const bool has_parameters_flags =
+        (flags & Code::kHasParameterFlagsFlag) != 0;
+    const bool has_forwarding_stub_target =
+        (flags & Code::kHasForwardingStubTargetFlag) != 0;
+    const bool has_default_function_type_args =
+        (flags & Code::kHasDefaultFunctionTypeArgsFlag) != 0;
+
+    if (has_parameters_flags) {
+      intptr_t num_params = reader_.ReadUInt();
+      ASSERT(num_params ==
+             function.NumParameters() - function.NumImplicitParameters());
+      for (intptr_t i = 0; i < num_params; ++i) {
+        reader_.ReadUInt();
+      }
+    }
+
+    if (has_forwarding_stub_target) {
+      reader_.ReadUInt();
+    }
+
+    if (has_default_function_type_args) {
+      const intptr_t index = reader_.ReadUInt();
+      const Bytecode& code = Bytecode::Handle(Z, function.bytecode());
+      const ObjectPool& pool = ObjectPool::Handle(Z, code.object_pool());
+      default_args ^= pool.ObjectAt(index);
+    }
+  }
+
+  auto& name = String::Handle(Z);
+  auto& check = ParameterTypeCheck::Handle(Z);
+  auto& checks = GrowableObjectArray::Handle(Z, GrowableObjectArray::New());
+
+  checks.Add(function);
+  checks.Add(default_args);
+
+  const auto& type_params =
+      TypeArguments::Handle(Z, function.type_parameters());
+  if (!type_params.IsNull()) {
+    auto& type_param = TypeParameter::Handle(Z);
+    auto& bound = AbstractType::Handle(Z);
+    for (intptr_t i = 0, n = type_params.Length(); i < n; ++i) {
+      type_param ^= type_params.TypeAt(i);
+      bound = type_param.bound();
+      if (!bound.IsTopType() && !type_param.IsGenericCovariantImpl()) {
+        name = type_param.name();
+        ASSERT(type_param.IsFinalized());
+        check = ParameterTypeCheck::New();
+        check.set_param(type_param);
+        check.set_type_or_bound(bound);
+        check.set_name(name);
+        checks.Add(check);
+      }
+    }
+  }
+
+  const intptr_t num_params = function.NumParameters();
+  const intptr_t num_pos_params = function.HasOptionalNamedParameters()
+                                      ? function.num_fixed_parameters()
+                                      : num_params;
+
+  BitVector is_covariant(Z, num_params);
+  BitVector is_generic_covariant_impl(Z, num_params);
+  ReadParameterCovariance(function, &is_covariant, &is_generic_covariant_impl);
+
+  auto& type = AbstractType::Handle(Z);
+  auto& cache = SubtypeTestCache::Handle(Z);
+  const bool has_optional_parameters = function.HasOptionalParameters();
+  for (intptr_t i = function.NumImplicitParameters(); i < num_params; ++i) {
+    type = function.ParameterTypeAt(i);
+    if (!type.IsTopType() && !is_generic_covariant_impl.Contains(i) &&
+        !is_covariant.Contains(i)) {
+      name = function.ParameterNameAt(i);
+      intptr_t index;
+      if (i >= num_pos_params) {
+        // Named parameter.
+        index = IndexFor(Z, function, name);
+      } else if (has_optional_parameters) {
+        // Fixed or optional parameter.
+        index = i;
+      } else {
+        // Fixed parameter.
+        index = -kKBCParamEndSlotFromFp - num_params + i;
+      }
+      check = ParameterTypeCheck::New();
+      check.set_index(index);
+      check.set_type_or_bound(type);
+      check.set_name(name);
+      cache = SubtypeTestCache::New();
+      check.set_cache(cache);
+      checks.Add(check);
+    }
+  }
+
+  return Array::MakeFixedLength(checks);
+}
+
 void BytecodeReaderHelper::ReadClosureDeclaration(const Function& function,
                                                   intptr_t closureIndex) {
   // Closure flags, must be in sync with ClosureDeclaration constants in
@@ -2096,7 +2233,7 @@
   VMTagScope tagScope(thread, VMTag::kLoadBytecodeTagId);
 
 #if defined(SUPPORT_TIMELINE)
-  TimelineDurationScope tds(Thread::Current(), Timeline::GetCompilerStream(),
+  TimelineDurationScope tds(thread, Timeline::GetCompilerStream(),
                             "BytecodeReader::ReadFunctionBytecode");
   // This increases bytecode reading time by ~7%, so only keep it around for
   // debugging.
@@ -2130,7 +2267,7 @@
         bytecode = Object::method_extractor_bytecode().raw();
         break;
       case RawFunction::kInvokeFieldDispatcher:
-        if (Class::Handle(function.Owner()).id() == kClosureCid) {
+        if (Class::Handle(zone, function.Owner()).id() == kClosureCid) {
           bytecode = Object::invoke_closure_bytecode().raw();
         } else {
           bytecode = Object::invoke_field_bytecode().raw();
@@ -2139,6 +2276,36 @@
       case RawFunction::kNoSuchMethodDispatcher:
         bytecode = Object::nsm_dispatcher_bytecode().raw();
         break;
+      case RawFunction::kDynamicInvocationForwarder: {
+        const Function& target =
+            Function::Handle(zone, function.ForwardingTarget());
+        if (!target.HasBytecode()) {
+          // The forwarder will use the target's bytecode to handle optional
+          // parameters.
+          const Error& error =
+              Error::Handle(zone, ReadFunctionBytecode(thread, target));
+          if (!error.IsNull()) {
+            return error.raw();
+          }
+        }
+        {
+          const Script& script = Script::Handle(zone, target.script());
+          TranslationHelper translation_helper(thread);
+          translation_helper.InitFromScript(script);
+
+          ActiveClass active_class;
+          BytecodeComponentData bytecode_component(
+              Array::Handle(zone, translation_helper.GetBytecodeComponent()));
+          ASSERT(!bytecode_component.IsNull());
+          BytecodeReaderHelper bytecode_reader(
+              &translation_helper, &active_class, &bytecode_component);
+
+          const Array& checks = Array::Handle(
+              zone, bytecode_reader.CreateForwarderChecks(target));
+          function.SetForwardingChecks(checks);
+        }
+        bytecode = Object::dynamic_invocation_forwarder_bytecode().raw();
+      } break;
       default:
         break;
     }
diff --git a/runtime/vm/compiler/frontend/bytecode_reader.h b/runtime/vm/compiler/frontend/bytecode_reader.h
index 753bff9..830bf95 100644
--- a/runtime/vm/compiler/frontend/bytecode_reader.h
+++ b/runtime/vm/compiler/frontend/bytecode_reader.h
@@ -54,6 +54,8 @@
 
   void ReadCode(const Function& function, intptr_t code_offset);
 
+  RawArray* CreateForwarderChecks(const Function& function);
+
   void ReadMembers(const Class& cls,
                    intptr_t members_offset,
                    bool discard_fields);
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.cc b/runtime/vm/compiler/frontend/kernel_to_il.cc
index 2668c17..0306907 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.cc
+++ b/runtime/vm/compiler/frontend/kernel_to_il.cc
@@ -2234,7 +2234,13 @@
                          function.IsImplicitSetterFunction();
   const bool is_method = !function.IsStaticFunction();
 
-  Field& field = Field::ZoneHandle(Z, function.accessor_field());
+  Field& field = Field::ZoneHandle(Z);
+  if (function.IsDynamicInvocationForwarder()) {
+    Function& target = Function::Handle(function.ForwardingTarget());
+    field = target.accessor_field();
+  } else {
+    field = function.accessor_field();
+  }
 
   graph_entry_ =
       new (Z) GraphEntryInstr(*parsed_function_, Compiler::kNoOSRDeoptId);
diff --git a/runtime/vm/interpreter.cc b/runtime/vm/interpreter.cc
index e188c08..2f823c5 100644
--- a/runtime/vm/interpreter.cc
+++ b/runtime/vm/interpreter.cc
@@ -1186,6 +1186,120 @@
   }
 #endif  // PRODUCT
 
+bool Interpreter::CopyParameters(Thread* thread,
+                                 const KBCInstr** pc,
+                                 RawObject*** FP,
+                                 RawObject*** SP,
+                                 const intptr_t num_fixed_params,
+                                 const intptr_t num_opt_pos_params,
+                                 const intptr_t num_opt_named_params) {
+  const intptr_t min_num_pos_args = num_fixed_params;
+  const intptr_t max_num_pos_args = num_fixed_params + num_opt_pos_params;
+
+  // Decode arguments descriptor.
+  const intptr_t arg_count = InterpreterHelpers::ArgDescArgCount(argdesc_);
+  const intptr_t pos_count = InterpreterHelpers::ArgDescPosCount(argdesc_);
+  const intptr_t named_count = (arg_count - pos_count);
+
+  // Check that got the right number of positional parameters.
+  if ((min_num_pos_args > pos_count) || (pos_count > max_num_pos_args)) {
+    return false;
+  }
+
+  // Copy all passed position arguments.
+  RawObject** first_arg = FrameArguments(*FP, arg_count);
+  memmove(*FP, first_arg, pos_count * kWordSize);
+
+  if (num_opt_named_params != 0) {
+    // This is a function with named parameters.
+    // Walk the list of named parameters and their
+    // default values encoded as pairs of LoadConstant instructions that
+    // follows the entry point and find matching values via arguments
+    // descriptor.
+    RawObject** argdesc_data = argdesc_->ptr()->data();
+
+    intptr_t i = 0;  // argument position
+    intptr_t j = 0;  // parameter position
+    while ((j < num_opt_named_params) && (i < named_count)) {
+      // Fetch formal parameter information: name, default value, target slot.
+      const KBCInstr* load_name = *pc;
+      const KBCInstr* load_value = KernelBytecode::Next(load_name);
+      *pc = KernelBytecode::Next(load_value);
+      ASSERT(KernelBytecode::IsLoadConstantOpcode(load_name));
+      ASSERT(KernelBytecode::IsLoadConstantOpcode(load_value));
+      const uint8_t reg = KernelBytecode::DecodeA(load_name);
+      ASSERT(reg == KernelBytecode::DecodeA(load_value));
+
+      RawString* name = static_cast<RawString*>(
+          LOAD_CONSTANT(KernelBytecode::DecodeE(load_name)));
+      if (name == argdesc_data[ArgumentsDescriptor::name_index(i)]) {
+        // Parameter was passed. Fetch passed value.
+        const intptr_t arg_index = Smi::Value(static_cast<RawSmi*>(
+            argdesc_data[ArgumentsDescriptor::position_index(i)]));
+        (*FP)[reg] = first_arg[arg_index];
+        ++i;  // Consume passed argument.
+      } else {
+        // Parameter was not passed. Fetch default value.
+        (*FP)[reg] = LOAD_CONSTANT(KernelBytecode::DecodeE(load_value));
+      }
+      ++j;  // Next formal parameter.
+    }
+
+    // If we have unprocessed formal parameters then initialize them all
+    // using default values.
+    while (j < num_opt_named_params) {
+      const KBCInstr* load_name = *pc;
+      const KBCInstr* load_value = KernelBytecode::Next(load_name);
+      *pc = KernelBytecode::Next(load_value);
+      ASSERT(KernelBytecode::IsLoadConstantOpcode(load_name));
+      ASSERT(KernelBytecode::IsLoadConstantOpcode(load_value));
+      const uint8_t reg = KernelBytecode::DecodeA(load_name);
+      ASSERT(reg == KernelBytecode::DecodeA(load_value));
+
+      (*FP)[reg] = LOAD_CONSTANT(KernelBytecode::DecodeE(load_value));
+      ++j;
+    }
+
+    // If we have unprocessed passed arguments that means we have mismatch
+    // between formal parameters and concrete arguments. This can only
+    // occur if the current function is a closure.
+    if (i < named_count) {
+      return false;
+    }
+
+    // SP points past copied arguments.
+    *SP = *FP + num_fixed_params + num_opt_named_params - 1;
+  } else {
+    ASSERT(num_opt_pos_params != 0);
+    if (named_count != 0) {
+      // Function can't have both named and optional positional parameters.
+      // This kind of mismatch can only occur if the current function
+      // is a closure.
+      return false;
+    }
+
+    // Process the list of default values encoded as a sequence of
+    // LoadConstant instructions after EntryOpt bytecode.
+    // Execute only those that correspond to parameters that were not passed.
+    for (intptr_t i = num_fixed_params; i < pos_count; ++i) {
+      ASSERT(KernelBytecode::IsLoadConstantOpcode(*pc));
+      *pc = KernelBytecode::Next(*pc);
+    }
+    for (intptr_t i = pos_count; i < max_num_pos_args; ++i) {
+      const KBCInstr* load_value = *pc;
+      *pc = KernelBytecode::Next(load_value);
+      ASSERT(KernelBytecode::IsLoadConstantOpcode(load_value));
+      ASSERT(KernelBytecode::DecodeA(load_value) == i);
+      (*FP)[i] = LOAD_CONSTANT(KernelBytecode::DecodeE(load_value));
+    }
+
+    // SP points past the last copied parameter.
+    *SP = *FP + max_num_pos_args - 1;
+  }
+
+  return true;
+}
+
 bool Interpreter::AssertAssignable(Thread* thread,
                                    const KBCInstr* pc,
                                    RawObject** FP,
@@ -1651,114 +1765,11 @@
 
   {
     BYTECODE(EntryOptional, A_B_C);
-    const intptr_t num_fixed_params = rA;
-    const intptr_t num_opt_pos_params = rB;
-    const intptr_t num_opt_named_params = rC;
-    const intptr_t min_num_pos_args = num_fixed_params;
-    const intptr_t max_num_pos_args = num_fixed_params + num_opt_pos_params;
-
-    // Decode arguments descriptor.
-    const intptr_t arg_count = InterpreterHelpers::ArgDescArgCount(argdesc_);
-    const intptr_t pos_count = InterpreterHelpers::ArgDescPosCount(argdesc_);
-    const intptr_t named_count = (arg_count - pos_count);
-
-    // Check that got the right number of positional parameters.
-    if ((min_num_pos_args > pos_count) || (pos_count > max_num_pos_args)) {
+    if (CopyParameters(thread, &pc, &FP, &SP, rA, rB, rC)) {
+      DISPATCH();
+    } else {
       goto NoSuchMethodFromPrologue;
     }
-
-    // Copy all passed position arguments.
-    RawObject** first_arg = FrameArguments(FP, arg_count);
-    memmove(FP, first_arg, pos_count * kWordSize);
-
-    if (num_opt_named_params != 0) {
-      // This is a function with named parameters.
-      // Walk the list of named parameters and their
-      // default values encoded as pairs of LoadConstant instructions that
-      // follows the entry point and find matching values via arguments
-      // descriptor.
-      RawObject** argdesc_data = argdesc_->ptr()->data();
-
-      intptr_t i = 0;  // argument position
-      intptr_t j = 0;  // parameter position
-      while ((j < num_opt_named_params) && (i < named_count)) {
-        // Fetch formal parameter information: name, default value, target slot.
-        const KBCInstr* load_name = pc;
-        const KBCInstr* load_value = KernelBytecode::Next(load_name);
-        pc = KernelBytecode::Next(load_value);
-        ASSERT(KernelBytecode::IsLoadConstantOpcode(load_name));
-        ASSERT(KernelBytecode::IsLoadConstantOpcode(load_value));
-        const uint8_t reg = KernelBytecode::DecodeA(load_name);
-        ASSERT(reg == KernelBytecode::DecodeA(load_value));
-
-        RawString* name = static_cast<RawString*>(
-            LOAD_CONSTANT(KernelBytecode::DecodeE(load_name)));
-        if (name == argdesc_data[ArgumentsDescriptor::name_index(i)]) {
-          // Parameter was passed. Fetch passed value.
-          const intptr_t arg_index = Smi::Value(static_cast<RawSmi*>(
-              argdesc_data[ArgumentsDescriptor::position_index(i)]));
-          FP[reg] = first_arg[arg_index];
-          ++i;  // Consume passed argument.
-        } else {
-          // Parameter was not passed. Fetch default value.
-          FP[reg] = LOAD_CONSTANT(KernelBytecode::DecodeE(load_value));
-        }
-        ++j;  // Next formal parameter.
-      }
-
-      // If we have unprocessed formal parameters then initialize them all
-      // using default values.
-      while (j < num_opt_named_params) {
-        const KBCInstr* load_name = pc;
-        const KBCInstr* load_value = KernelBytecode::Next(load_name);
-        pc = KernelBytecode::Next(load_value);
-        ASSERT(KernelBytecode::IsLoadConstantOpcode(load_name));
-        ASSERT(KernelBytecode::IsLoadConstantOpcode(load_value));
-        const uint8_t reg = KernelBytecode::DecodeA(load_name);
-        ASSERT(reg == KernelBytecode::DecodeA(load_value));
-
-        FP[reg] = LOAD_CONSTANT(KernelBytecode::DecodeE(load_value));
-        ++j;
-      }
-
-      // If we have unprocessed passed arguments that means we have mismatch
-      // between formal parameters and concrete arguments. This can only
-      // occur if the current function is a closure.
-      if (i < named_count) {
-        goto NoSuchMethodFromPrologue;
-      }
-
-      // SP points past copied arguments.
-      SP = FP + num_fixed_params + num_opt_named_params - 1;
-    } else {
-      ASSERT(num_opt_pos_params != 0);
-      if (named_count != 0) {
-        // Function can't have both named and optional positional parameters.
-        // This kind of mismatch can only occur if the current function
-        // is a closure.
-        goto NoSuchMethodFromPrologue;
-      }
-
-      // Process the list of default values encoded as a sequence of
-      // LoadConstant instructions after EntryOpt bytecode.
-      // Execute only those that correspond to parameters that were not passed.
-      for (intptr_t i = num_fixed_params; i < pos_count; ++i) {
-        ASSERT(KernelBytecode::IsLoadConstantOpcode(pc));
-        pc = KernelBytecode::Next(pc);
-      }
-      for (intptr_t i = pos_count; i < max_num_pos_args; ++i) {
-        const KBCInstr* load_value = pc;
-        pc = KernelBytecode::Next(load_value);
-        ASSERT(KernelBytecode::IsLoadConstantOpcode(load_value));
-        ASSERT(KernelBytecode::DecodeA(load_value) == i);
-        FP[i] = LOAD_CONSTANT(KernelBytecode::DecodeE(load_value));
-      }
-
-      // SP points past the last copied parameter.
-      SP = FP + max_num_pos_args - 1;
-    }
-
-    DISPATCH();
   }
 
   {
@@ -3469,8 +3480,101 @@
     RawFunction* function = FrameFunction(FP);
     ASSERT(Function::kind(function) ==
            RawFunction::kDynamicInvocationForwarder);
-    UNIMPLEMENTED();
-    DISPATCH();
+
+    BUMP_USAGE_COUNTER_ON_ENTRY(function);
+
+    RawArray* checks = Array::RawCast(function->ptr()->data_);
+    RawFunction* target = Function::RawCast(checks->ptr()->data()[0]);
+    ASSERT(Function::kind(target) != RawFunction::kDynamicInvocationForwarder);
+    RawBytecode* target_bytecode = target->ptr()->bytecode_;
+    ASSERT(target_bytecode != Bytecode::null());
+    ASSERT(target_bytecode->IsBytecode());
+
+    const KBCInstr* pc2 = reinterpret_cast<const KBCInstr*>(
+        target_bytecode->ptr()->instructions_);
+    if (KernelBytecode::IsEntryOptionalOpcode(pc2)) {
+      pp_ = target_bytecode->ptr()->object_pool_;
+      uint32_t rA, rB, rC;
+      rA = KernelBytecode::DecodeA(pc2);
+      rB = KernelBytecode::DecodeB(pc2);
+      rC = KernelBytecode::DecodeC(pc2);
+      pc2 = KernelBytecode::Next(pc2);
+      if (!CopyParameters(thread, &pc2, &FP, &SP, rA, rB, rC)) {
+        goto NoSuchMethodFromPrologue;
+      }
+    }
+
+    intptr_t len = Smi::Value(checks->ptr()->length_);
+    SP[1] = checks;
+    SP[2] = argdesc_;
+
+    const intptr_t type_args_len =
+        InterpreterHelpers::ArgDescTypeArgsLen(argdesc_);
+    const intptr_t receiver_idx = type_args_len > 0 ? 1 : 0;
+    const intptr_t argc =
+        InterpreterHelpers::ArgDescArgCount(argdesc_) + receiver_idx;
+
+    RawInstance* receiver =
+        Instance::RawCast(FrameArguments(FP, argc)[receiver_idx]);
+    SP[5] = InterpreterHelpers::GetTypeArguments(thread, receiver);
+
+    if (type_args_len > 0) {
+      SP[6] = FrameArguments(FP, argc)[0];
+    } else {
+      SP[6] = TypeArguments::RawCast(checks->ptr()->data()[1]);
+      if (SP[5] != null_value && SP[6] != null_value) {
+        SP[7] = SP[6];       // type_arguments
+        SP[8] = SP[5];       // instantiator_type_args
+        SP[9] = null_value;  // function_type_args
+        Exit(thread, FP, SP + 10, pc);
+        NativeArguments args(thread, 3, SP + 7, SP + 7);
+        INVOKE_RUNTIME(DRT_InstantiateTypeArguments, args);
+        SP[6] = SP[7];
+      }
+    }
+
+    for (intptr_t i = 2; i < len; i++) {
+      RawParameterTypeCheck* check =
+          ParameterTypeCheck::RawCast(checks->ptr()->data()[i]);
+
+      if (LIKELY(check->ptr()->index_ != 0)) {
+        ASSERT(&FP[check->ptr()->index_] <= SP);
+        SP[3] = Instance::RawCast(FP[check->ptr()->index_]);
+        if (SP[3] == null_value) {
+          continue;  // Not handled by AssertAssignable for some reason...
+        }
+        SP[4] = check->ptr()->type_or_bound_;
+        // SP[5]: Instantiator type args.
+        // SP[6]: Function type args.
+        SP[7] = check->ptr()->name_;
+        if (!AssertAssignable(thread, pc, FP, SP, SP + 3,
+                              check->ptr()->cache_)) {
+          HANDLE_EXCEPTION;
+        }
+      } else {
+        SP[3] = 0;
+        SP[4] = 0;
+        // SP[5]: Instantiator type args.
+        // SP[6]: Function type args.
+        SP[7] = check->ptr()->param_;
+        SP[8] = check->ptr()->type_or_bound_;
+        SP[9] = check->ptr()->name_;
+        SP[10] = 0;
+        Exit(thread, FP, SP + 11, pc);
+        NativeArguments native_args(thread, 5, SP + 5, SP + 10);
+        INVOKE_RUNTIME(DRT_SubtypeCheck, native_args);
+      }
+
+      checks = Array::RawCast(SP[1]);  // Reload after runtime call.
+    }
+
+    target = Function::RawCast(checks->ptr()->data()[0]);
+    argdesc_ = Array::RawCast(SP[2]);
+
+    SP = FP - 1;  // Unmarshall optional parameters.
+
+    SP[1] = target;
+    goto TailCallSP1;
   }
 
   {
diff --git a/runtime/vm/interpreter.h b/runtime/vm/interpreter.h
index a47eecc..a8e393f 100644
--- a/runtime/vm/interpreter.h
+++ b/runtime/vm/interpreter.h
@@ -209,6 +209,14 @@
                      RawObject*** SP,
                      bool optimized);
 
+  bool CopyParameters(Thread* thread,
+                      const KBCInstr** pc,
+                      RawObject*** FP,
+                      RawObject*** SP,
+                      const intptr_t num_fixed_params,
+                      const intptr_t num_opt_pos_params,
+                      const intptr_t num_opt_named_params);
+
   bool AssertAssignable(Thread* thread,
                         const KBCInstr* pc,
                         RawObject** FP,
diff --git a/runtime/vm/kernel.cc b/runtime/vm/kernel.cc
index 946135e..b16d1b3 100644
--- a/runtime/vm/kernel.cc
+++ b/runtime/vm/kernel.cc
@@ -11,6 +11,7 @@
 #include "vm/longjump.h"
 #include "vm/object_store.h"
 #include "vm/parser.h"  // For Parser::kParameter* constants.
+#include "vm/stack_frame.h"
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
 
diff --git a/runtime/vm/kernel.h b/runtime/vm/kernel.h
index 4e66b89..32f975f 100644
--- a/runtime/vm/kernel.h
+++ b/runtime/vm/kernel.h
@@ -208,6 +208,11 @@
 // as such function already checks all of its parameters.
 bool NeedsDynamicInvocationForwarder(const Function& function);
 
+// Returns a list of ParameterTypeChecks needed by a dynamic invocation
+// forwarder that targets [function]. Indices in these checks correspond to
+// bytecode frame indices.
+RawArray* CollectDynamicInvocationChecks(const Function& function);
+
 ProcedureAttributesMetadata ProcedureAttributesOf(const Function& function,
                                                   Zone* zone);
 
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index f914e28..6066a17 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -153,6 +153,8 @@
     reinterpret_cast<RawClass*>(RAW_NULL);
 RawClass* Object::context_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
 RawClass* Object::context_scope_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
+RawClass* Object::dyncalltypecheck_class_ =
+    reinterpret_cast<RawClass*>(RAW_NULL);
 RawClass* Object::singletargetcache_class_ =
     reinterpret_cast<RawClass*>(RAW_NULL);
 RawClass* Object::unlinkedcall_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
@@ -648,6 +650,9 @@
   cls = Class::New<ContextScope>();
   context_scope_class_ = cls.raw();
 
+  cls = Class::New<ParameterTypeCheck>();
+  dyncalltypecheck_class_ = cls.raw();
+
   cls = Class::New<SingleTargetCache>();
   singletargetcache_class_ = cls.raw();
 
@@ -907,6 +912,9 @@
   *nsm_dispatcher_bytecode_ = CreateVMInternalBytecode(
       KernelBytecode::kVMInternal_NoSuchMethodDispatcher);
 
+  *dynamic_invocation_forwarder_bytecode_ = CreateVMInternalBytecode(
+      KernelBytecode::kVMInternal_ForwardDynamicInvocation);
+
   // Some thread fields need to be reinitialized as null constants have not been
   // initialized until now.
   Thread* thr = Thread::Current();
@@ -978,6 +986,8 @@
   ASSERT(invoke_field_bytecode_->IsBytecode());
   ASSERT(!nsm_dispatcher_bytecode_->IsSmi());
   ASSERT(nsm_dispatcher_bytecode_->IsBytecode());
+  ASSERT(!dynamic_invocation_forwarder_bytecode_->IsSmi());
+  ASSERT(dynamic_invocation_forwarder_bytecode_->IsBytecode());
 }
 
 void Object::FinishInit(Isolate* isolate) {
@@ -1021,6 +1031,7 @@
   exception_handlers_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
   context_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
   context_scope_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
+  dyncalltypecheck_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
   singletargetcache_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
   unlinkedcall_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
   icdata_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
@@ -1120,6 +1131,7 @@
   SET_CLASS_NAME(exception_handlers, ExceptionHandlers);
   SET_CLASS_NAME(context, Context);
   SET_CLASS_NAME(context_scope, ContextScope);
+  SET_CLASS_NAME(dyncalltypecheck, ParameterTypeCheck);
   SET_CLASS_NAME(singletargetcache, SingleTargetCache);
   SET_CLASS_NAME(unlinkedcall, UnlinkedCall);
   SET_CLASS_NAME(icdata, ICData);
@@ -3058,6 +3070,10 @@
 
   forwarder.InheritBinaryDeclarationFrom(*this);
 
+  const Array& checks = Array::Handle(zone, Array::New(1));
+  checks.SetAt(0, *this);
+  forwarder.SetForwardingChecks(checks);
+
   return forwarder.raw();
 }
 
@@ -3893,6 +3909,8 @@
       return Symbols::Context().raw();
     case kContextScopeCid:
       return Symbols::ContextScope().raw();
+    case kParameterTypeCheckCid:
+      return Symbols::ParameterTypeCheck().raw();
     case kSingleTargetCacheCid:
       return Symbols::SingleTargetCache().raw();
     case kICDataCid:
@@ -5655,6 +5673,7 @@
   }
   switch (kind()) {
     case RawFunction::kDynamicInvocationForwarder:
+      return is_declared_in_bytecode();
     case RawFunction::kImplicitClosureFunction:
     case RawFunction::kIrregexpFunction:
     case RawFunction::kFfiTrampoline:
@@ -5877,8 +5896,7 @@
   ASSERT(kind() == RawFunction::kImplicitGetter ||
          kind() == RawFunction::kImplicitSetter ||
          kind() == RawFunction::kImplicitStaticGetter ||
-         kind() == RawFunction::kStaticFieldInitializer ||
-         kind() == RawFunction::kDynamicInvocationForwarder);
+         kind() == RawFunction::kStaticFieldInitializer);
   return Field::RawCast(raw_ptr()->data_);
 }
 
@@ -6217,6 +6235,20 @@
   RedirectionData::Cast(obj).set_target(target);
 }
 
+RawFunction* Function::ForwardingTarget() const {
+  ASSERT(kind() == RawFunction::kDynamicInvocationForwarder);
+  Array& checks = Array::Handle();
+  checks ^= raw_ptr()->data_;
+  return Function::RawCast(checks.At(0));
+}
+
+void Function::SetForwardingChecks(const Array& checks) const {
+  ASSERT(kind() == RawFunction::kDynamicInvocationForwarder);
+  ASSERT(checks.Length() >= 1);
+  ASSERT(Object::Handle(checks.At(0)).IsFunction());
+  set_data(checks);
+}
+
 // This field is heavily overloaded:
 //   eval function:           Script expression source
 //   kernel eval function:    Array[0] = Script
@@ -6238,6 +6270,9 @@
 //                            Array[1] = Function implicit closure function
 //   regular function:        Function for implicit closure function
 //   ffi trampoline function: FfiTrampolineData  (Dart->C)
+//   dyn inv forwarder:       Array[0] = Function target
+//                            Array[1] = TypeArguments default type args
+//                            Array[i] = ParameterTypeCheck
 void Function::set_data(const Object& value) const {
   StorePointer(&raw_ptr()->data_, value.raw());
 }
@@ -13186,6 +13221,43 @@
 #undef FORMAT2
 }
 
+void ParameterTypeCheck::set_type_or_bound(const AbstractType& value) const {
+  StorePointer(&raw_ptr()->type_or_bound_, value.raw());
+}
+
+void ParameterTypeCheck::set_param(const AbstractType& value) const {
+  StorePointer(&raw_ptr()->param_, value.raw());
+}
+
+void ParameterTypeCheck::set_name(const String& value) const {
+  StorePointer(&raw_ptr()->name_, value.raw());
+}
+
+void ParameterTypeCheck::set_cache(const SubtypeTestCache& value) const {
+  StorePointer(&raw_ptr()->cache_, value.raw());
+}
+
+const char* ParameterTypeCheck::ToCString() const {
+  Zone* zone = Thread::Current()->zone();
+  return zone->PrintToString("ParameterTypeCheck(%" Pd " %s %s %s)", index(),
+                             Object::Handle(zone, param()).ToCString(),
+                             Object::Handle(zone, type_or_bound()).ToCString(),
+                             Object::Handle(zone, name()).ToCString());
+}
+
+RawParameterTypeCheck* ParameterTypeCheck::New() {
+  ParameterTypeCheck& result = ParameterTypeCheck::Handle();
+  {
+    RawObject* raw =
+        Object::Allocate(ParameterTypeCheck::kClassId,
+                         ParameterTypeCheck::InstanceSize(), Heap::kOld);
+    NoSafepointScope no_safepoint;
+    result ^= raw;
+  }
+  result.set_index(0);
+  return result.raw();
+}
+
 void SingleTargetCache::set_target(const Code& value) const {
   StorePointer(&raw_ptr()->target_, value.raw());
 }
@@ -13252,14 +13324,14 @@
 }
 
 const char* ICData::ToCString() const {
-  const String& name = String::Handle(target_name());
+  Zone* zone = Thread::Current()->zone();
+  const String& name = String::Handle(zone, target_name());
   const intptr_t num_args = NumArgsTested();
   const intptr_t num_checks = NumberOfChecks();
   const intptr_t type_args_len = TypeArgsLen();
-  return OS::SCreate(Thread::Current()->zone(),
-                     "ICData target:'%s' num-args: %" Pd " num-checks: %" Pd
-                     " type-args-len: %" Pd "",
-                     name.ToCString(), num_args, num_checks, type_args_len);
+  return zone->PrintToString(
+      "ICData(%s num-args: %" Pd " num-checks: %" Pd " type-args-len: %" Pd ")",
+      name.ToCString(), num_args, num_checks, type_args_len);
 }
 
 RawFunction* ICData::Owner() const {
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 33261da..82b27a0 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -403,6 +403,7 @@
   V(Bytecode, invoke_closure_bytecode)                                         \
   V(Bytecode, invoke_field_bytecode)                                           \
   V(Bytecode, nsm_dispatcher_bytecode)                                         \
+  V(Bytecode, dynamic_invocation_forwarder_bytecode)                           \
   V(Instance, sentinel)                                                        \
   V(Instance, transition_sentinel)                                             \
   V(Instance, unknown_constant)                                                \
@@ -468,6 +469,7 @@
     return unhandled_exception_class_;
   }
   static RawClass* unwind_error_class() { return unwind_error_class_; }
+  static RawClass* dyncalltypecheck_class() { return dyncalltypecheck_class_; }
   static RawClass* singletargetcache_class() {
     return singletargetcache_class_;
   }
@@ -705,6 +707,7 @@
   static RawClass* deopt_info_class_;          // Class of DeoptInfo.
   static RawClass* context_class_;        // Class of the Context vm object.
   static RawClass* context_scope_class_;  // Class of ContextScope vm object.
+  static RawClass* dyncalltypecheck_class_;     // Class of ParameterTypeCheck.
   static RawClass* singletargetcache_class_;    // Class of SingleTargetCache.
   static RawClass* unlinkedcall_class_;         // Class of UnlinkedCall.
   static RawClass* icdata_class_;               // Class of ICData.
@@ -1491,6 +1494,41 @@
   friend class Class;
 };
 
+class ParameterTypeCheck : public Object {
+ public:
+  // The FP-relative index of the parameter in a bytecode frame (after optional
+  // parameter marshalling) whose assignability needs to be checked, or 0 if
+  // this is a type parameter check.
+  intptr_t index() const { return raw_ptr()->index_; }
+  void set_index(intptr_t i) const { StoreNonPointer(&raw_ptr()->index_, i); }
+
+  // The type parameter to whose bound needs to be checked, or null if this is
+  // an ordinary parameter check.
+  RawAbstractType* param() const { return raw_ptr()->param_; }
+  void set_param(const AbstractType& t) const;
+
+  // FP[index] assignable to type, OR param is subtype of bound.
+  RawAbstractType* type_or_bound() const { return raw_ptr()->type_or_bound_; }
+  void set_type_or_bound(const AbstractType& t) const;
+
+  // The parameter or type parameter's name to use in an error message.
+  RawString* name() const { return raw_ptr()->name_; }
+  void set_name(const String& n) const;
+
+  RawSubtypeTestCache* cache() const { return raw_ptr()->cache_; }
+  void set_cache(const SubtypeTestCache& c) const;
+
+  static intptr_t InstanceSize() {
+    return RoundedAllocationSize(sizeof(RawParameterTypeCheck));
+  }
+
+  static RawParameterTypeCheck* New();
+
+ private:
+  FINAL_HEAP_OBJECT_IMPLEMENTATION(ParameterTypeCheck, Object);
+  friend class Class;
+};
+
 class SingleTargetCache : public Object {
  public:
   RawCode* target() const { return raw_ptr()->target_; }
@@ -2249,6 +2287,9 @@
   RawFunction* RedirectionTarget() const;
   void SetRedirectionTarget(const Function& target) const;
 
+  RawFunction* ForwardingTarget() const;
+  void SetForwardingChecks(const Array& checks) const;
+
   RawFunction::Kind kind() const {
     return KindBits::decode(raw_ptr()->kind_tag_);
   }
@@ -3002,7 +3043,6 @@
   void set_num_optional_parameters(intptr_t value) const;  // Encoded value.
   void set_kind_tag(uint32_t value) const;
   void set_data(const Object& value) const;
-
   static RawFunction* New(Heap::Space space = Heap::kOld);
 
   RawString* QualifiedName(NameVisibility name_visibility) const;
diff --git a/runtime/vm/object_service.cc b/runtime/vm/object_service.cc
index 3616d4e..e95e14e 100644
--- a/runtime/vm/object_service.cc
+++ b/runtime/vm/object_service.cc
@@ -729,6 +729,10 @@
   Object::PrintJSONImpl(stream, ref);
 }
 
+void ParameterTypeCheck::PrintJSONImpl(JSONStream* stream, bool ref) const {
+  Object::PrintJSONImpl(stream, ref);
+}
+
 void SingleTargetCache::PrintJSONImpl(JSONStream* stream, bool ref) const {
   JSONObject jsobj(stream);
   AddCommonObjectProperties(&jsobj, "Object", ref);
diff --git a/runtime/vm/raw_object.cc b/runtime/vm/raw_object.cc
index 0658a6d..24a79f8 100644
--- a/runtime/vm/raw_object.cc
+++ b/runtime/vm/raw_object.cc
@@ -438,6 +438,7 @@
 REGULAR_VISITOR(Library)
 REGULAR_VISITOR(LibraryPrefix)
 REGULAR_VISITOR(Namespace)
+REGULAR_VISITOR(ParameterTypeCheck)
 REGULAR_VISITOR(SingleTargetCache)
 REGULAR_VISITOR(UnlinkedCall)
 REGULAR_VISITOR(ICData)
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index 1028af1..91ff01e 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -1705,6 +1705,18 @@
   friend class SnapshotReader;
 };
 
+class RawParameterTypeCheck : public RawObject {
+  RAW_HEAP_OBJECT_IMPLEMENTATION(ParameterTypeCheck);
+  intptr_t index_;
+  VISIT_FROM(RawObject*, param_);
+  RawAbstractType* param_;
+  RawAbstractType* type_or_bound_;
+  RawString* name_;
+  RawSubtypeTestCache* cache_;
+  VISIT_TO(RawObject*, cache_);
+  RawObject** to_snapshot(Snapshot::Kind kind) { return to(); }
+};
+
 class RawSingleTargetCache : public RawObject {
   RAW_HEAP_OBJECT_IMPLEMENTATION(SingleTargetCache);
   VISIT_FROM(RawObject*, target_);
diff --git a/runtime/vm/raw_object_fields.cc b/runtime/vm/raw_object_fields.cc
index c4aac7c..35d4fdc 100644
--- a/runtime/vm/raw_object_fields.cc
+++ b/runtime/vm/raw_object_fields.cc
@@ -112,6 +112,10 @@
   F(Bytecode, closures_)                                                       \
   F(ExceptionHandlers, handled_types_data_)                                    \
   F(Context, parent_)                                                          \
+  F(ParameterTypeCheck, param_)                                                \
+  F(ParameterTypeCheck, type_or_bound_)                                        \
+  F(ParameterTypeCheck, name_)                                                 \
+  F(ParameterTypeCheck, cache_)                                                \
   F(SingleTargetCache, target_)                                                \
   F(UnlinkedCall, target_name_)                                                \
   F(UnlinkedCall, args_descriptor_)                                            \
diff --git a/runtime/vm/raw_object_snapshot.cc b/runtime/vm/raw_object_snapshot.cc
index d734dbb..22a7016 100644
--- a/runtime/vm/raw_object_snapshot.cc
+++ b/runtime/vm/raw_object_snapshot.cc
@@ -71,22 +71,6 @@
   }
 }
 
-RawAbstractType* AbstractType::ReadFrom(SnapshotReader* reader,
-                                        intptr_t object_id,
-                                        intptr_t tags,
-                                        Snapshot::Kind kind,
-                                        bool as_reference) {
-  UNREACHABLE();  // AbstractType is an abstract class.
-  return NULL;
-}
-
-void RawAbstractType::WriteTo(SnapshotWriter* writer,
-                              intptr_t object_id,
-                              Snapshot::Kind kind,
-                              bool as_reference) {
-  UNREACHABLE();  // AbstractType is an abstract class.
-}
-
 RawType* Type::ReadFrom(SnapshotReader* reader,
                         intptr_t object_id,
                         intptr_t tags,
@@ -364,22 +348,6 @@
   }
 }
 
-RawPatchClass* PatchClass::ReadFrom(SnapshotReader* reader,
-                                    intptr_t object_id,
-                                    intptr_t tags,
-                                    Snapshot::Kind kind,
-                                    bool as_reference) {
-  UNREACHABLE();
-  return PatchClass::null();
-}
-
-void RawPatchClass::WriteTo(SnapshotWriter* writer,
-                            intptr_t object_id,
-                            Snapshot::Kind kind,
-                            bool as_reference) {
-  UNREACHABLE();
-}
-
 RawClosure* Closure::ReadFrom(SnapshotReader* reader,
                               intptr_t object_id,
                               intptr_t tags,
@@ -407,326 +375,6 @@
   UNREACHABLE();
 }
 
-RawClosureData* ClosureData::ReadFrom(SnapshotReader* reader,
-                                      intptr_t object_id,
-                                      intptr_t tags,
-                                      Snapshot::Kind kind,
-                                      bool as_reference) {
-  UNREACHABLE();
-  return ClosureData::null();
-}
-
-void RawClosureData::WriteTo(SnapshotWriter* writer,
-                             intptr_t object_id,
-                             Snapshot::Kind kind,
-                             bool as_reference) {
-  UNREACHABLE();
-}
-
-RawSignatureData* SignatureData::ReadFrom(SnapshotReader* reader,
-                                          intptr_t object_id,
-                                          intptr_t tags,
-                                          Snapshot::Kind kind,
-                                          bool as_reference) {
-  UNREACHABLE();
-  return SignatureData::null();
-}
-
-void RawSignatureData::WriteTo(SnapshotWriter* writer,
-                               intptr_t object_id,
-                               Snapshot::Kind kind,
-                               bool as_reference) {
-  UNREACHABLE();
-}
-
-RawRedirectionData* RedirectionData::ReadFrom(SnapshotReader* reader,
-                                              intptr_t object_id,
-                                              intptr_t tags,
-                                              Snapshot::Kind kind,
-                                              bool as_reference) {
-  UNREACHABLE();
-  return RedirectionData::null();
-}
-
-void RawRedirectionData::WriteTo(SnapshotWriter* writer,
-                                 intptr_t object_id,
-                                 Snapshot::Kind kind,
-                                 bool as_reference) {
-  UNREACHABLE();
-}
-
-RawFfiTrampolineData* FfiTrampolineData::ReadFrom(SnapshotReader* reader,
-                                                  intptr_t object_id,
-                                                  intptr_t tags,
-                                                  Snapshot::Kind kind,
-                                                  bool as_reference) {
-  UNREACHABLE();
-  return FfiTrampolineData::null();
-}
-
-void RawFfiTrampolineData::WriteTo(SnapshotWriter* writer,
-                                   intptr_t object_id,
-                                   Snapshot::Kind kind,
-                                   bool as_reference) {
-  UNREACHABLE();
-}
-
-RawFunction* Function::ReadFrom(SnapshotReader* reader,
-                                intptr_t object_id,
-                                intptr_t tags,
-                                Snapshot::Kind kind,
-                                bool as_reference) {
-  UNREACHABLE();
-  return Function::null();
-}
-
-void RawFunction::WriteTo(SnapshotWriter* writer,
-                          intptr_t object_id,
-                          Snapshot::Kind kind,
-                          bool as_reference) {
-  UNREACHABLE();
-}
-
-RawField* Field::ReadFrom(SnapshotReader* reader,
-                          intptr_t object_id,
-                          intptr_t tags,
-                          Snapshot::Kind kind,
-                          bool as_reference) {
-  UNREACHABLE();
-  return Field::null();
-}
-
-void RawField::WriteTo(SnapshotWriter* writer,
-                       intptr_t object_id,
-                       Snapshot::Kind kind,
-                       bool as_reference) {
-  UNREACHABLE();
-}
-
-RawScript* Script::ReadFrom(SnapshotReader* reader,
-                            intptr_t object_id,
-                            intptr_t tags,
-                            Snapshot::Kind kind,
-                            bool as_reference) {
-  UNREACHABLE();
-  return Script::null();
-}
-
-void RawScript::WriteTo(SnapshotWriter* writer,
-                        intptr_t object_id,
-                        Snapshot::Kind kind,
-                        bool as_reference) {
-  UNREACHABLE();
-}
-
-RawLibrary* Library::ReadFrom(SnapshotReader* reader,
-                              intptr_t object_id,
-                              intptr_t tags,
-                              Snapshot::Kind kind,
-                              bool as_reference) {
-  UNREACHABLE();
-  return Library::null();
-}
-
-void RawLibrary::WriteTo(SnapshotWriter* writer,
-                         intptr_t object_id,
-                         Snapshot::Kind kind,
-                         bool as_reference) {
-  UNREACHABLE();
-}
-
-RawLibraryPrefix* LibraryPrefix::ReadFrom(SnapshotReader* reader,
-                                          intptr_t object_id,
-                                          intptr_t tags,
-                                          Snapshot::Kind kind,
-                                          bool as_reference) {
-  UNREACHABLE();
-  return LibraryPrefix::null();
-}
-
-void RawLibraryPrefix::WriteTo(SnapshotWriter* writer,
-                               intptr_t object_id,
-                               Snapshot::Kind kind,
-                               bool as_reference) {
-  UNREACHABLE();
-}
-
-RawNamespace* Namespace::ReadFrom(SnapshotReader* reader,
-                                  intptr_t object_id,
-                                  intptr_t tags,
-                                  Snapshot::Kind kind,
-                                  bool as_reference) {
-  UNREACHABLE();
-  return Namespace::null();
-}
-
-void RawNamespace::WriteTo(SnapshotWriter* writer,
-                           intptr_t object_id,
-                           Snapshot::Kind kind,
-                           bool as_reference) {
-  UNREACHABLE();
-}
-
-RawKernelProgramInfo* KernelProgramInfo::ReadFrom(SnapshotReader* reader,
-                                                  intptr_t object_id,
-                                                  intptr_t tags,
-                                                  Snapshot::Kind kind,
-                                                  bool as_reference) {
-  UNREACHABLE();
-  return KernelProgramInfo::null();
-}
-
-void RawKernelProgramInfo::WriteTo(SnapshotWriter* writer,
-                                   intptr_t object_id,
-                                   Snapshot::Kind kind,
-                                   bool as_reference) {
-  UNREACHABLE();
-}
-
-RawCode* Code::ReadFrom(SnapshotReader* reader,
-                        intptr_t object_id,
-                        intptr_t tags,
-                        Snapshot::Kind kind,
-                        bool as_reference) {
-  UNREACHABLE();
-  return Code::null();
-}
-
-void RawCode::WriteTo(SnapshotWriter* writer,
-                      intptr_t object_id,
-                      Snapshot::Kind kind,
-                      bool as_reference) {
-  UNREACHABLE();
-}
-
-RawBytecode* Bytecode::ReadFrom(SnapshotReader* reader,
-                                intptr_t object_id,
-                                intptr_t tags,
-                                Snapshot::Kind kind,
-                                bool as_reference) {
-  UNREACHABLE();
-  return Bytecode::null();
-}
-
-void RawBytecode::WriteTo(SnapshotWriter* writer,
-                          intptr_t object_id,
-                          Snapshot::Kind kind,
-                          bool as_reference) {
-  UNREACHABLE();
-}
-
-RawInstructions* Instructions::ReadFrom(SnapshotReader* reader,
-                                        intptr_t object_id,
-                                        intptr_t tags,
-                                        Snapshot::Kind kind,
-                                        bool as_reference) {
-  UNREACHABLE();
-  return Instructions::null();
-}
-
-void RawInstructions::WriteTo(SnapshotWriter* writer,
-                              intptr_t object_id,
-                              Snapshot::Kind kind,
-                              bool as_reference) {
-  UNREACHABLE();
-}
-
-RawObjectPool* ObjectPool::ReadFrom(SnapshotReader* reader,
-                                    intptr_t object_id,
-                                    intptr_t tags,
-                                    Snapshot::Kind kind,
-                                    bool as_reference) {
-  UNREACHABLE();
-  return ObjectPool::null();
-}
-
-void RawObjectPool::WriteTo(SnapshotWriter* writer,
-                            intptr_t object_id,
-                            Snapshot::Kind kind,
-                            bool as_reference) {
-  UNREACHABLE();
-}
-
-RawPcDescriptors* PcDescriptors::ReadFrom(SnapshotReader* reader,
-                                          intptr_t object_id,
-                                          intptr_t tags,
-                                          Snapshot::Kind kind,
-                                          bool as_reference) {
-  UNREACHABLE();
-  return PcDescriptors::null();
-}
-
-void RawPcDescriptors::WriteTo(SnapshotWriter* writer,
-                               intptr_t object_id,
-                               Snapshot::Kind kind,
-                               bool as_reference) {
-  UNREACHABLE();
-}
-
-RawCodeSourceMap* CodeSourceMap::ReadFrom(SnapshotReader* reader,
-                                          intptr_t object_id,
-                                          intptr_t tags,
-                                          Snapshot::Kind kind,
-                                          bool as_reference) {
-  UNREACHABLE();
-  return CodeSourceMap::null();
-}
-
-void RawCodeSourceMap::WriteTo(SnapshotWriter* writer,
-                               intptr_t object_id,
-                               Snapshot::Kind kind,
-                               bool as_reference) {
-  UNREACHABLE();
-}
-
-RawStackMap* StackMap::ReadFrom(SnapshotReader* reader,
-                                intptr_t object_id,
-                                intptr_t tags,
-                                Snapshot::Kind kind,
-                                bool as_reference) {
-  UNREACHABLE();
-  return StackMap::null();
-}
-
-void RawStackMap::WriteTo(SnapshotWriter* writer,
-                          intptr_t object_id,
-                          Snapshot::Kind kind,
-                          bool as_reference) {
-  UNREACHABLE();
-}
-
-RawLocalVarDescriptors* LocalVarDescriptors::ReadFrom(SnapshotReader* reader,
-                                                      intptr_t object_id,
-                                                      intptr_t tags,
-                                                      Snapshot::Kind kind,
-                                                      bool as_reference) {
-  UNREACHABLE();
-  return LocalVarDescriptors::null();
-}
-
-void RawLocalVarDescriptors::WriteTo(SnapshotWriter* writer,
-                                     intptr_t object_id,
-                                     Snapshot::Kind kind,
-                                     bool as_reference) {
-  UNREACHABLE();
-}
-
-RawExceptionHandlers* ExceptionHandlers::ReadFrom(SnapshotReader* reader,
-                                                  intptr_t object_id,
-                                                  intptr_t tags,
-                                                  Snapshot::Kind kind,
-                                                  bool as_reference) {
-  UNREACHABLE();
-  return ExceptionHandlers::null();
-}
-
-void RawExceptionHandlers::WriteTo(SnapshotWriter* writer,
-                                   intptr_t object_id,
-                                   Snapshot::Kind kind,
-                                   bool as_reference) {
-  UNREACHABLE();
-}
-
 RawContext* Context::ReadFrom(SnapshotReader* reader,
                               intptr_t object_id,
                               intptr_t tags,
@@ -836,101 +484,72 @@
   UNREACHABLE();
 }
 
-RawSingleTargetCache* SingleTargetCache::ReadFrom(SnapshotReader* reader,
-                                                  intptr_t object_id,
-                                                  intptr_t tags,
-                                                  Snapshot::Kind kind,
-                                                  bool as_reference) {
-  UNREACHABLE();
-  return SingleTargetCache::null();
-}
+#define MESSAGE_SNAPSHOT_UNREACHABLE(type)                                     \
+  Raw##type* type::ReadFrom(SnapshotReader* reader, intptr_t object_id,        \
+                            intptr_t tags, Snapshot::Kind kind,                \
+                            bool as_reference) {                               \
+    UNREACHABLE();                                                             \
+    return type::null();                                                       \
+  }                                                                            \
+  void Raw##type::WriteTo(SnapshotWriter* writer, intptr_t object_id,          \
+                          Snapshot::Kind kind, bool as_reference) {            \
+    UNREACHABLE();                                                             \
+  }
 
-void RawSingleTargetCache::WriteTo(SnapshotWriter* writer,
-                                   intptr_t object_id,
-                                   Snapshot::Kind kind,
-                                   bool as_reference) {
-  UNREACHABLE();
-}
+#define MESSAGE_SNAPSHOT_ILLEGAL(type)                                         \
+  Raw##type* type::ReadFrom(SnapshotReader* reader, intptr_t object_id,        \
+                            intptr_t tags, Snapshot::Kind kind,                \
+                            bool as_reference) {                               \
+    UNREACHABLE();                                                             \
+    return type::null();                                                       \
+  }                                                                            \
+  void Raw##type::WriteTo(SnapshotWriter* writer, intptr_t object_id,          \
+                          Snapshot::Kind kind, bool as_reference) {            \
+    writer->SetWriteException(Exceptions::kArgument,                           \
+                              "Illegal argument in isolate message"            \
+                              " : (object is a " #type ")");                   \
+  }
 
-RawUnlinkedCall* UnlinkedCall::ReadFrom(SnapshotReader* reader,
-                                        intptr_t object_id,
-                                        intptr_t tags,
-                                        Snapshot::Kind kind,
-                                        bool as_reference) {
-  UNREACHABLE();
-  return UnlinkedCall::null();
-}
+MESSAGE_SNAPSHOT_UNREACHABLE(AbstractType);
+MESSAGE_SNAPSHOT_UNREACHABLE(Bool);
+MESSAGE_SNAPSHOT_UNREACHABLE(Bytecode);
+MESSAGE_SNAPSHOT_UNREACHABLE(ClosureData);
+MESSAGE_SNAPSHOT_UNREACHABLE(Code);
+MESSAGE_SNAPSHOT_UNREACHABLE(CodeSourceMap);
+MESSAGE_SNAPSHOT_UNREACHABLE(Error);
+MESSAGE_SNAPSHOT_UNREACHABLE(ExceptionHandlers);
+MESSAGE_SNAPSHOT_UNREACHABLE(FfiTrampolineData);
+MESSAGE_SNAPSHOT_UNREACHABLE(Field);
+MESSAGE_SNAPSHOT_UNREACHABLE(Function);
+MESSAGE_SNAPSHOT_UNREACHABLE(ICData);
+MESSAGE_SNAPSHOT_UNREACHABLE(Instructions);
+MESSAGE_SNAPSHOT_UNREACHABLE(KernelProgramInfo);
+MESSAGE_SNAPSHOT_UNREACHABLE(Library);
+MESSAGE_SNAPSHOT_UNREACHABLE(LibraryPrefix);
+MESSAGE_SNAPSHOT_UNREACHABLE(LocalVarDescriptors);
+MESSAGE_SNAPSHOT_UNREACHABLE(MegamorphicCache);
+MESSAGE_SNAPSHOT_UNREACHABLE(Namespace);
+MESSAGE_SNAPSHOT_UNREACHABLE(ObjectPool);
+MESSAGE_SNAPSHOT_UNREACHABLE(ParameterTypeCheck);
+MESSAGE_SNAPSHOT_UNREACHABLE(PatchClass);
+MESSAGE_SNAPSHOT_UNREACHABLE(PcDescriptors);
+MESSAGE_SNAPSHOT_UNREACHABLE(RedirectionData);
+MESSAGE_SNAPSHOT_UNREACHABLE(Script);
+MESSAGE_SNAPSHOT_UNREACHABLE(SignatureData);
+MESSAGE_SNAPSHOT_UNREACHABLE(SingleTargetCache);
+MESSAGE_SNAPSHOT_UNREACHABLE(StackMap);
+MESSAGE_SNAPSHOT_UNREACHABLE(String);
+MESSAGE_SNAPSHOT_UNREACHABLE(SubtypeTestCache);
+MESSAGE_SNAPSHOT_UNREACHABLE(TypedDataBase);
+MESSAGE_SNAPSHOT_UNREACHABLE(UnlinkedCall);
+MESSAGE_SNAPSHOT_UNREACHABLE(UnwindError);
 
-void RawUnlinkedCall::WriteTo(SnapshotWriter* writer,
-                              intptr_t object_id,
-                              Snapshot::Kind kind,
-                              bool as_reference) {
-  UNREACHABLE();
-}
-
-RawICData* ICData::ReadFrom(SnapshotReader* reader,
-                            intptr_t object_id,
-                            intptr_t tags,
-                            Snapshot::Kind kind,
-                            bool as_reference) {
-  UNREACHABLE();
-  return ICData::null();
-}
-
-void RawICData::WriteTo(SnapshotWriter* writer,
-                        intptr_t object_id,
-                        Snapshot::Kind kind,
-                        bool as_reference) {
-  UNREACHABLE();
-}
-
-RawMegamorphicCache* MegamorphicCache::ReadFrom(SnapshotReader* reader,
-                                                intptr_t object_id,
-                                                intptr_t tags,
-                                                Snapshot::Kind kind,
-                                                bool as_reference) {
-  UNREACHABLE();
-  return MegamorphicCache::null();
-}
-
-void RawMegamorphicCache::WriteTo(SnapshotWriter* writer,
-                                  intptr_t object_id,
-                                  Snapshot::Kind kind,
-                                  bool as_reference) {
-  UNREACHABLE();
-}
-
-RawSubtypeTestCache* SubtypeTestCache::ReadFrom(SnapshotReader* reader,
-                                                intptr_t object_id,
-                                                intptr_t tags,
-                                                Snapshot::Kind kind,
-                                                bool as_reference) {
-  UNREACHABLE();
-  return SubtypeTestCache::null();
-}
-
-void RawSubtypeTestCache::WriteTo(SnapshotWriter* writer,
-                                  intptr_t object_id,
-                                  Snapshot::Kind kind,
-                                  bool as_reference) {
-  UNREACHABLE();
-}
-
-RawError* Error::ReadFrom(SnapshotReader* reader,
-                          intptr_t object_id,
-                          intptr_t tags,
-                          Snapshot::Kind kind,
-                          bool as_referenec) {
-  UNREACHABLE();
-  return Error::null();  // Error is an abstract class.
-}
-
-void RawError::WriteTo(SnapshotWriter* writer,
-                       intptr_t object_id,
-                       Snapshot::Kind kind,
-                       bool as_reference) {
-  UNREACHABLE();  // Error is an abstract class.
-}
+MESSAGE_SNAPSHOT_ILLEGAL(DynamicLibrary);
+MESSAGE_SNAPSHOT_ILLEGAL(MirrorReference);
+MESSAGE_SNAPSHOT_ILLEGAL(Pointer);
+MESSAGE_SNAPSHOT_ILLEGAL(ReceivePort);
+MESSAGE_SNAPSHOT_ILLEGAL(StackTrace);
+MESSAGE_SNAPSHOT_ILLEGAL(UserTag);
 
 RawApiError* ApiError::ReadFrom(SnapshotReader* reader,
                                 intptr_t object_id,
@@ -1047,22 +666,6 @@
   visitor.VisitPointers(from(), to());
 }
 
-RawUnwindError* UnwindError::ReadFrom(SnapshotReader* reader,
-                                      intptr_t object_id,
-                                      intptr_t tags,
-                                      Snapshot::Kind kind,
-                                      bool as_reference) {
-  UNREACHABLE();
-  return UnwindError::null();
-}
-
-void RawUnwindError::WriteTo(SnapshotWriter* writer,
-                             intptr_t object_id,
-                             Snapshot::Kind kind,
-                             bool as_reference) {
-  UNREACHABLE();
-}
-
 RawInstance* Instance::ReadFrom(SnapshotReader* reader,
                                 intptr_t object_id,
                                 intptr_t tags,
@@ -1196,22 +799,6 @@
   writer->WriteDouble(ptr()->value_);
 }
 
-RawString* String::ReadFrom(SnapshotReader* reader,
-                            intptr_t object_id,
-                            intptr_t tags,
-                            Snapshot::Kind kind,
-                            bool as_reference) {
-  UNREACHABLE();  // String is an abstract class.
-  return String::null();
-}
-
-void RawString::WriteTo(SnapshotWriter* writer,
-                        intptr_t object_id,
-                        Snapshot::Kind kind,
-                        bool as_reference) {
-  UNREACHABLE();  // String is an abstract class.
-}
-
 template <typename StringType, typename CharacterType, typename CallbackType>
 void String::ReadFromImpl(SnapshotReader* reader,
                           String* str_obj,
@@ -1365,22 +952,6 @@
                 ptr()->external_data_);
 }
 
-RawBool* Bool::ReadFrom(SnapshotReader* reader,
-                        intptr_t object_id,
-                        intptr_t tags,
-                        Snapshot::Kind kind,
-                        bool as_reference) {
-  UNREACHABLE();
-  return Bool::null();
-}
-
-void RawBool::WriteTo(SnapshotWriter* writer,
-                      intptr_t object_id,
-                      Snapshot::Kind kind,
-                      bool as_reference) {
-  UNREACHABLE();
-}
-
 RawArray* Array::ReadFrom(SnapshotReader* reader,
                           intptr_t object_id,
                           intptr_t tags,
@@ -1722,22 +1293,6 @@
   writer->Write<double>(ptr()->value_[1]);
 }
 
-RawTypedDataBase* TypedDataBase::ReadFrom(SnapshotReader* reader,
-                                          intptr_t object_id,
-                                          intptr_t tags,
-                                          Snapshot::Kind kind,
-                                          bool as_reference) {
-  UNREACHABLE();  // TypedDataBase is an abstract class.
-  return NULL;
-}
-
-void RawTypedDataBase::WriteTo(SnapshotWriter* writer,
-                               intptr_t object_id,
-                               Snapshot::Kind kind,
-                               bool as_reference) {
-  UNREACHABLE();  // TypedDataBase is an abstract class.
-}
-
 RawTypedData* TypedData::ReadFrom(SnapshotReader* reader,
                                   intptr_t object_id,
                                   intptr_t tags,
@@ -2021,38 +1576,6 @@
   return view.raw();
 }
 
-RawPointer* Pointer::ReadFrom(SnapshotReader* reader,
-                              intptr_t object_id,
-                              intptr_t tags,
-                              Snapshot::Kind kind,
-                              bool as_reference) {
-  FATAL("Snapshotting Pointers is not supported");
-  UNREACHABLE();
-}
-
-void RawPointer::WriteTo(SnapshotWriter* writer,
-                         intptr_t object_id,
-                         Snapshot::Kind kind,
-                         bool as_reference) {
-  FATAL("Snapshotting Pointers is not supported");
-}
-
-RawDynamicLibrary* DynamicLibrary::ReadFrom(SnapshotReader* reader,
-                                            intptr_t object_id,
-                                            intptr_t tags,
-                                            Snapshot::Kind kind,
-                                            bool as_reference) {
-  FATAL("Snapshotting DynamicLibraries is not supported");
-  UNREACHABLE();
-}
-
-void RawDynamicLibrary::WriteTo(SnapshotWriter* writer,
-                                intptr_t object_id,
-                                Snapshot::Kind kind,
-                                bool as_reference) {
-  FATAL("Snapshotting DynamicLibraries is not supported");
-}
-
 RawCapability* Capability::ReadFrom(SnapshotReader* reader,
                                     intptr_t object_id,
                                     intptr_t tags,
@@ -2080,29 +1603,6 @@
   writer->Write<uint64_t>(ptr()->id_);
 }
 
-RawReceivePort* ReceivePort::ReadFrom(SnapshotReader* reader,
-                                      intptr_t object_id,
-                                      intptr_t tags,
-                                      Snapshot::Kind kind,
-                                      bool as_reference) {
-  UNREACHABLE();
-  return ReceivePort::null();
-}
-
-void RawReceivePort::WriteTo(SnapshotWriter* writer,
-                             intptr_t object_id,
-                             Snapshot::Kind kind,
-                             bool as_reference) {
-  if (kind == Snapshot::kMessage) {
-    // We do not allow objects with native fields in an isolate message.
-    writer->SetWriteException(Exceptions::kArgument,
-                              "Illegal argument in isolate message"
-                              " : (object is a RawReceivePort)");
-  } else {
-    UNREACHABLE();
-  }
-}
-
 RawSendPort* SendPort::ReadFrom(SnapshotReader* reader,
                                 intptr_t object_id,
                                 intptr_t tags,
@@ -2196,25 +1696,6 @@
       });
 }
 
-RawStackTrace* StackTrace::ReadFrom(SnapshotReader* reader,
-                                    intptr_t object_id,
-                                    intptr_t tags,
-                                    Snapshot::Kind kind,
-                                    bool as_reference) {
-  UNREACHABLE();  // StackTraces are not sent in a snapshot.
-  return StackTrace::null();
-}
-
-void RawStackTrace::WriteTo(SnapshotWriter* writer,
-                            intptr_t object_id,
-                            Snapshot::Kind kind,
-                            bool as_reference) {
-  ASSERT(kind == Snapshot::kMessage);
-  writer->SetWriteException(Exceptions::kArgument,
-                            "Illegal argument in isolate message"
-                            " : (object is a stacktrace)");
-}
-
 RawRegExp* RegExp::ReadFrom(SnapshotReader* reader,
                             intptr_t object_id,
                             intptr_t tags,
@@ -2309,50 +1790,4 @@
   visitor.VisitPointers(from(), to());
 }
 
-RawMirrorReference* MirrorReference::ReadFrom(SnapshotReader* reader,
-                                              intptr_t object_id,
-                                              intptr_t tags,
-                                              Snapshot::Kind kind,
-                                              bool as_referenec) {
-  UNREACHABLE();
-  return MirrorReference::null();
-}
-
-void RawMirrorReference::WriteTo(SnapshotWriter* writer,
-                                 intptr_t object_id,
-                                 Snapshot::Kind kind,
-                                 bool as_reference) {
-  if (kind == Snapshot::kMessage) {
-    // We do not allow objects with native fields in an isolate message.
-    writer->SetWriteException(Exceptions::kArgument,
-                              "Illegal argument in isolate message"
-                              " : (object is a MirrorReference)");
-  } else {
-    UNREACHABLE();
-  }
-}
-
-RawUserTag* UserTag::ReadFrom(SnapshotReader* reader,
-                              intptr_t object_id,
-                              intptr_t tags,
-                              Snapshot::Kind kind,
-                              bool as_reference) {
-  UNREACHABLE();
-  return UserTag::null();
-}
-
-void RawUserTag::WriteTo(SnapshotWriter* writer,
-                         intptr_t object_id,
-                         Snapshot::Kind kind,
-                         bool as_reference) {
-  if (kind == Snapshot::kMessage) {
-    // We do not allow objects with native fields in an isolate message.
-    writer->SetWriteException(Exceptions::kArgument,
-                              "Illegal argument in isolate message"
-                              " : (object is a UserTag)");
-  } else {
-    UNREACHABLE();
-  }
-}
-
 }  // namespace dart
diff --git a/runtime/vm/runtime_entry.cc b/runtime/vm/runtime_entry.cc
index 674623b..e997516 100644
--- a/runtime/vm/runtime_entry.cc
+++ b/runtime/vm/runtime_entry.cc
@@ -356,7 +356,7 @@
       TypeArguments::CheckedHandle(zone, arguments.ArgAt(1));
   const TypeArguments& function_type_arguments =
       TypeArguments::CheckedHandle(zone, arguments.ArgAt(2));
-  ASSERT(!type.IsNull() && !type.IsInstantiated());
+  ASSERT(!type.IsNull());
   ASSERT(instantiator_type_arguments.IsNull() ||
          instantiator_type_arguments.IsInstantiated());
   ASSERT(function_type_arguments.IsNull() ||
diff --git a/runtime/vm/snapshot.h b/runtime/vm/snapshot.h
index 0939635e..5f6c929 100644
--- a/runtime/vm/snapshot.h
+++ b/runtime/vm/snapshot.h
@@ -5,6 +5,9 @@
 #ifndef RUNTIME_VM_SNAPSHOT_H_
 #define RUNTIME_VM_SNAPSHOT_H_
 
+#include <memory>
+#include <utility>
+
 #include "platform/assert.h"
 #include "vm/allocation.h"
 #include "vm/bitfield.h"
@@ -700,6 +703,7 @@
   friend class RawClosureData;
   friend class RawCode;
   friend class RawContextScope;
+  friend class RawDynamicLibrary;
   friend class RawExceptionHandlers;
   friend class RawField;
   friend class RawFunction;
@@ -711,6 +715,7 @@
   friend class RawLocalVarDescriptors;
   friend class RawMirrorReference;
   friend class RawObjectPool;
+  friend class RawPointer;
   friend class RawReceivePort;
   friend class RawRegExp;
   friend class RawScript;
@@ -718,10 +723,10 @@
   friend class RawSubtypeTestCache;
   friend class RawTransferableTypedData;
   friend class RawType;
-  friend class RawTypedDataView;
-  friend class RawTypeRef;
   friend class RawTypeArguments;
   friend class RawTypeParameter;
+  friend class RawTypeRef;
+  friend class RawTypedDataView;
   friend class RawUserTag;
   friend class SnapshotWriterVisitor;
   friend class WriteInlinedObjectVisitor;
diff --git a/runtime/vm/symbols.h b/runtime/vm/symbols.h
index f8b93b3..b17870e 100644
--- a/runtime/vm/symbols.h
+++ b/runtime/vm/symbols.h
@@ -18,8 +18,6 @@
 // One-character symbols are added implicitly.
 #define PREDEFINED_SYMBOLS_LIST(V)                                             \
   V(AbstractClassInstantiationError, "AbstractClassInstantiationError")        \
-  V(AddError, "addError")                                                      \
-  V(AddStream, "addStream")                                                    \
   V(AllocateInvocationMirror, "_allocateInvocationMirror")                     \
   V(AllocateInvocationMirrorForClosure, "_allocateInvocationMirrorForClosure") \
   V(AnonymousClosure, "<anonymous closure>")                                   \
@@ -29,26 +27,12 @@
   V(ArgumentError, "ArgumentError")                                            \
   V(AssertionError, "_AssertionError")                                         \
   V(AssignIndexToken, "[]=")                                                   \
-  V(Async, "async")                                                            \
-  V(AsyncAwaitHelper, "_awaitHelper")                                          \
-  V(AsyncCatchErrorCallback, ":async_op_catch_error")                          \
-  V(AsyncCatchHelper, "_asyncCatchHelper")                                     \
   V(AsyncCompleter, ":async_completer")                                        \
-  V(AsyncErrorWrapperHelper, "_asyncErrorWrapperHelper")                       \
   V(AsyncOperation, ":async_op")                                               \
-  V(AsyncOperationErrorParam, ":async_error_param")                            \
-  V(AsyncOperationParam, ":async_result")                                      \
-  V(AsyncOperationStackTraceParam, ":async_stack_trace_param")                 \
-  V(AsyncSavedTryCtxVarPrefix, ":async_saved_try_ctx_var_")                    \
-  V(AsyncStackTraceHelper, "_asyncStackTraceHelper")                           \
   V(AsyncStackTraceVar, ":async_stack_trace")                                  \
   V(AsyncStarMoveNextHelper, "_asyncStarMoveNextHelper")                       \
-  V(AsyncThenCallback, ":async_op_then")                                       \
-  V(AsyncThenWrapperHelper, "_asyncThenWrapperHelper")                         \
-  V(Await, "await")                                                            \
   V(AwaitContextVar, ":await_ctx_var")                                         \
   V(AwaitJumpVar, ":await_jump_var")                                           \
-  V(AwaitTempVarPrefix, ":await_temp_var_")                                    \
   V(Bool, "bool")                                                              \
   V(BooleanExpression, "boolean expression")                                   \
   V(BoundsCheckForPartialInstantiation, "_boundsCheckForPartialInstantiation") \
@@ -62,18 +46,13 @@
   V(Class, "Class")                                                            \
   V(ClassID, "ClassID")                                                        \
   V(ClearAsyncThreadStackTrace, "_clearAsyncThreadStackTrace")                 \
-  V(Close, "close")                                                            \
   V(ClosureData, "ClosureData")                                                \
   V(ClosureParameter, ":closure")                                              \
   V(Code, "Code")                                                              \
   V(CodeSourceMap, "CodeSourceMap")                                            \
-  V(ColonController, ":controller")                                            \
   V(ColonMatcher, ":matcher")                                                  \
-  V(ColonStream, ":stream")                                                    \
   V(CommaSpace, ", ")                                                          \
   V(Completer, "Completer")                                                    \
-  V(CompleterComplete, "complete")                                             \
-  V(CompleterCompleteError, "completeError")                                   \
   V(CompleterFuture, "future")                                                 \
   V(CompleterGetFuture, "get:future")                                          \
   V(CompleterSyncConstructor, "Completer.sync")                                \
@@ -94,7 +73,6 @@
   V(DartFfiLibName, "ffi")                                                     \
   V(DartIOLibName, "dart.io")                                                  \
   V(DartInternal, "dart:_internal")                                            \
-  V(DartInternalPackage, "package:dart_internal/")                             \
   V(DartIsVM, "dart.isVM")                                                     \
   V(DartIsolate, "dart:isolate")                                               \
   V(DartLibrary, "dart.library.")                                              \
@@ -112,7 +90,6 @@
   V(DebugProcedureName, ":Eval")                                               \
   V(Default, "Default")                                                        \
   V(DefaultLabel, ":L")                                                        \
-  V(DeoptInfo, "DeoptInfo")                                                    \
   V(DotCreate, "._create")                                                     \
   V(DotRange, ".range")                                                        \
   V(DotValue, ".value")                                                        \
@@ -159,7 +136,6 @@
   V(Float64List, "Float64List")                                                \
   V(Float64x2, "Float64x2")                                                    \
   V(Float64x2List, "Float64x2List")                                            \
-  V(ForInIter, ":for-in-iter")                                                 \
   V(FormatException, "FormatException")                                        \
   V(ForwardingCorpse, "ForwardingCorpse")                                      \
   V(FreeListElement, "FreeListElement")                                        \
@@ -181,12 +157,10 @@
   V(GrowRegExpStack, "_growRegExpStack")                                       \
   V(HandleExposedException, "_handleExposedException")                         \
   V(HaveSameRuntimeType, "_haveSameRuntimeType")                               \
-  V(Hide, "hide")                                                              \
   V(ICData, "ICData")                                                          \
   V(Identical, "identical")                                                    \
   V(ImmutableMap, "_ImmutableMap")                                             \
   V(ImmutableMapConstructor, "_ImmutableMap._create")                          \
-  V(ImplicitClosure, "<implicit closure>")                                     \
   V(InTypeCast, " in type cast")                                               \
   V(Index, "index")                                                            \
   V(IndexToken, "[]")                                                          \
@@ -216,7 +190,6 @@
   V(LibraryPrefix, "LibraryPrefix")                                            \
   V(List, "List")                                                              \
   V(ListFactory, "List.")                                                      \
-  V(ListLiteralElement, "list literal element")                                \
   V(ListLiteralFactory, "List._fromLiteral")                                   \
   V(LoadLibrary, "loadLibrary")                                                \
   V(LocalVarDescriptors, "LocalVarDescriptors")                                \
@@ -236,14 +209,13 @@
   V(Number, "num")                                                             \
   V(Object, "Object")                                                          \
   V(ObjectPool, "ObjectPool")                                                  \
-  V(Of, "of")                                                                  \
-  V(On, "on")                                                                  \
   V(OneByteString, "_OneByteString")                                           \
   V(OptimizedOut, "<optimized out>")                                           \
   V(OriginalParam, ":original:")                                               \
   V(Other, "other")                                                            \
   V(OutOfMemoryError, "OutOfMemoryError")                                      \
   V(PackageScheme, "package:")                                                 \
+  V(ParameterTypeCheck, "ParameterTypeCheck")                                  \
   V(Patch, "patch")                                                            \
   V(PatchClass, "PatchClass")                                                  \
   V(PcDescriptors, "PcDescriptors")                                            \
@@ -255,14 +227,11 @@
   V(RedirectionData, "RedirectionData")                                        \
   V(RegExp, "RegExp")                                                          \
   V(RightShiftOperator, ">>")                                                  \
-  V(SavedExceptionVar, ":saved_exception_var")                                 \
-  V(SavedStackTraceVar, ":saved_stack_trace_var")                              \
   V(SavedTryContextVar, ":saved_try_context_var")                              \
   V(Script, "Script")                                                          \
   V(Set, "set")                                                                \
   V(SetAsyncThreadStackTrace, "_setAsyncThreadStackTrace")                     \
   V(SetterPrefix, "set:")                                                      \
-  V(Show, "show")                                                              \
   V(SignatureData, "SignatureData")                                            \
   V(SingleTargetCache, "SingleTargetCache")                                    \
   V(SpaceExtendsSpace, " extends ")                                            \
@@ -281,8 +250,6 @@
   V(SwitchExpr, ":switch_expr")                                                \
   V(Symbol, "Symbol")                                                          \
   V(SymbolCtor, "Symbol.")                                                     \
-  V(Sync, "sync")                                                              \
-  V(TempParam, ":temp_param")                                                  \
   V(ThrowNew, "_throwNew")                                                     \
   V(ThrowNewInvocation, "_throwNewInvocation")                                 \
   V(TopLevel, "::")                                                            \
@@ -290,7 +257,6 @@
   V(TransferableTypedData, "TransferableTypedData")                            \
   V(TryFinallyReturnValue, ":try_finally_return_value")                        \
   V(TwoByteString, "_TwoByteString")                                           \
-  V(TwoNewlines, "\n\n")                                                       \
   V(TwoSpaces, "  ")                                                           \
   V(Type, "Type")                                                              \
   V(TypeArguments, "TypeArguments")                                            \
@@ -451,7 +417,6 @@
   V(_stackTrace, "_stackTrace")                                                \
   V(_state, "_state")                                                          \
   V(_wordCharacterMap, "_wordCharacterMap")                                    \
-  V(_yieldEachIterable, "_yieldEachIterable")                                  \
   V(add, "add")                                                                \
   V(capture_length, ":capture_length")                                         \
   V(capture_start_index, ":capture_start_index")                               \
@@ -484,8 +449,7 @@
   V(vm_entry_point, "vm:entry-point")                                          \
   V(vm_exact_result_type, "vm:exact-result-type")                              \
   V(vm_non_nullable_result_type, "vm:non-nullable-result-type")                \
-  V(vm_trace_entrypoints, "vm:testing.unsafe.trace-entrypoints-fn")            \
-  V(word_character_map, ":word_character_map")
+  V(vm_trace_entrypoints, "vm:testing.unsafe.trace-entrypoints-fn")
 
 // Contains a list of frequently used strings in a canonicalized form. This
 // list is kept in the vm_isolate in order to share the copy across isolates