[vm] Support new kernel AST invocation nodes in the VM

TEST=Manual testing with new invocation nodes enabled.

Issue: https://github.com/dart-lang/sdk/issues/45340
Change-Id: I7eb5f03b9d9ac16c911812a5dbcd92ad43220278
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/197585
Commit-Queue: Alexander Markov <alexmarkov@google.com>
Reviewed-by: Aske Simon Christensen <askesc@google.com>
Reviewed-by: Johnni Winther <johnniwinther@google.com>
diff --git a/pkg/kernel/binary.md b/pkg/kernel/binary.md
index c891128..e501474 100644
--- a/pkg/kernel/binary.md
+++ b/pkg/kernel/binary.md
@@ -788,7 +788,6 @@
   Byte tag = 126;
   FileOffset fileOffset;
   Expression receiver;
-  DartType functionType;
 }
 
 type LocalFunctionInvocation extends Expression {
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
index 123a0a2..2ce3561 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
@@ -1131,8 +1131,20 @@
       return BuildVariableSet(payload, position);
     case kPropertyGet:
       return BuildPropertyGet(position);
+    case kInstanceGet:
+      return BuildInstanceGet(position);
+    case kDynamicGet:
+      return BuildDynamicGet(position);
+    case kInstanceTearOff:
+      return BuildInstanceTearOff(position);
+    case kFunctionTearOff:
+      return BuildFunctionTearOff(position);
     case kPropertySet:
       return BuildPropertySet(position);
+    case kInstanceSet:
+      return BuildInstanceSet(position);
+    case kDynamicSet:
+      return BuildDynamicSet(position);
     case kSuperPropertyGet:
       return BuildSuperPropertyGet(position);
     case kSuperPropertySet:
@@ -1142,7 +1154,17 @@
     case kStaticSet:
       return BuildStaticSet(position);
     case kMethodInvocation:
-      return BuildMethodInvocation(position);
+    case kInstanceInvocation:
+    case kDynamicInvocation:
+      return BuildMethodInvocation(position, tag);
+    case kLocalFunctionInvocation:
+      return BuildLocalFunctionInvocation(position);
+    case kFunctionInvocation:
+      return BuildFunctionInvocation(position);
+    case kEqualsCall:
+      return BuildEqualsCall(position);
+    case kEqualsNull:
+      return BuildEqualsNull(position);
     case kSuperMethodInvocation:
       return BuildSuperMethodInvocation(position);
     case kStaticInvocation:
@@ -1218,15 +1240,13 @@
     case kConstSetLiteral:
     case kConstMapLiteral:
     case kSymbolLiteral:
-      // Const invocations and const literals are removed by the
-      // constant evaluator.
     case kListConcatenation:
     case kSetConcatenation:
     case kMapConcatenation:
     case kInstanceCreation:
     case kFileUriExpression:
-      // Collection concatenation, instance creation operations and
-      // in-expression URI changes are internal to the front end and
+    case kStaticTearOff:
+      // These nodes are internal to the front end and
       // removed by the constant evaluator.
     default:
       ReportUnexpectedTag("expression", tag);
@@ -2155,6 +2175,7 @@
 
   return instructions;
 }
+
 Fragment StreamingFlowGraphBuilder::BuildPropertyGet(TokenPosition* p) {
   const intptr_t offset = ReaderOffset() - 1;     // Include the tag.
   const TokenPosition position = ReadPosition();  // read position.
@@ -2227,6 +2248,212 @@
   return instructions;
 }
 
+Fragment StreamingFlowGraphBuilder::BuildInstanceGet(TokenPosition* p) {
+  const intptr_t offset = ReaderOffset() - 1;     // Include the tag.
+  ReadByte();                                     // read kind.
+  const TokenPosition position = ReadPosition();  // read position.
+  if (p != nullptr) *p = position;
+
+  const DirectCallMetadata direct_call =
+      direct_call_metadata_helper_.GetDirectTargetForPropertyGet(offset);
+  const InferredTypeMetadata result_type =
+      inferred_type_metadata_helper_.GetInferredType(offset);
+
+  Fragment instructions = BuildExpression();  // read receiver.
+
+  LocalVariable* receiver = nullptr;
+  if (direct_call.check_receiver_for_null_) {
+    // Duplicate receiver for CheckNull before it is consumed by PushArgument.
+    receiver = MakeTemporary();
+    instructions += LoadLocal(receiver);
+  }
+
+  const String& getter_name = ReadNameAsGetterName();  // read name.
+  SkipDartType();                                      // read result_type.
+  const NameIndex itarget_name =
+      ReadInterfaceMemberNameReference();  // read interface_target_reference.
+  ASSERT(!H.IsRoot(itarget_name) && H.IsGetter(itarget_name));
+  const auto& interface_target = Function::ZoneHandle(
+      Z, H.LookupMethodByMember(itarget_name, H.DartGetterName(itarget_name)));
+  ASSERT(getter_name.ptr() == interface_target.name());
+
+  if (direct_call.check_receiver_for_null_) {
+    instructions += CheckNull(position, receiver, getter_name);
+  }
+
+  if (!direct_call.target_.IsNull()) {
+    ASSERT(CompilerState::Current().is_aot());
+    instructions +=
+        StaticCall(position, direct_call.target_, 1, Array::null_array(),
+                   ICData::kNoRebind, &result_type);
+  } else {
+    const intptr_t kTypeArgsLen = 0;
+    const intptr_t kNumArgsChecked = 1;
+    instructions +=
+        InstanceCall(position, getter_name, Token::kGET, kTypeArgsLen, 1,
+                     Array::null_array(), kNumArgsChecked, interface_target,
+                     Function::null_function(), &result_type);
+  }
+
+  if (direct_call.check_receiver_for_null_) {
+    instructions += DropTempsPreserveTop(1);  // Drop receiver, preserve result.
+  }
+
+  return instructions;
+}
+
+Fragment StreamingFlowGraphBuilder::BuildDynamicGet(TokenPosition* p) {
+  const intptr_t offset = ReaderOffset() - 1;     // Include the tag.
+  ReadByte();                                     // read kind.
+  const TokenPosition position = ReadPosition();  // read position.
+  if (p != nullptr) *p = position;
+
+  const DirectCallMetadata direct_call =
+      direct_call_metadata_helper_.GetDirectTargetForPropertyGet(offset);
+  const InferredTypeMetadata result_type =
+      inferred_type_metadata_helper_.GetInferredType(offset);
+
+  Fragment instructions = BuildExpression();  // read receiver.
+
+  LocalVariable* receiver = nullptr;
+  if (direct_call.check_receiver_for_null_) {
+    // Duplicate receiver for CheckNull before it is consumed by PushArgument.
+    receiver = MakeTemporary();
+    instructions += LoadLocal(receiver);
+  }
+
+  const String& getter_name = ReadNameAsGetterName();  // read name.
+
+  if (direct_call.check_receiver_for_null_) {
+    instructions += CheckNull(position, receiver, getter_name);
+  }
+
+  const auto& mangled_name = String::ZoneHandle(
+      Z, Function::CreateDynamicInvocationForwarderName(getter_name));
+  const Function* direct_call_target = &direct_call.target_;
+  if (!direct_call_target->IsNull()) {
+    direct_call_target = &Function::ZoneHandle(
+        direct_call.target_.GetDynamicInvocationForwarder(mangled_name));
+  }
+
+  if (!direct_call_target->IsNull()) {
+    ASSERT(CompilerState::Current().is_aot());
+    instructions +=
+        StaticCall(position, *direct_call_target, 1, Array::null_array(),
+                   ICData::kNoRebind, &result_type);
+  } else {
+    const intptr_t kTypeArgsLen = 0;
+    const intptr_t kNumArgsChecked = 1;
+    instructions += InstanceCall(position, mangled_name, Token::kGET,
+                                 kTypeArgsLen, 1, Array::null_array(),
+                                 kNumArgsChecked, Function::null_function(),
+                                 Function::null_function(), &result_type);
+  }
+
+  if (direct_call.check_receiver_for_null_) {
+    instructions += DropTempsPreserveTop(1);  // Drop receiver, preserve result.
+  }
+
+  return instructions;
+}
+
+Fragment StreamingFlowGraphBuilder::BuildInstanceTearOff(TokenPosition* p) {
+  const intptr_t offset = ReaderOffset() - 1;     // Include the tag.
+  ReadByte();                                     // read kind.
+  const TokenPosition position = ReadPosition();  // read position.
+  if (p != nullptr) *p = position;
+
+  const DirectCallMetadata direct_call =
+      direct_call_metadata_helper_.GetDirectTargetForPropertyGet(offset);
+  const InferredTypeMetadata result_type =
+      inferred_type_metadata_helper_.GetInferredType(offset);
+
+  Fragment instructions = BuildExpression();  // read receiver.
+
+  LocalVariable* receiver = nullptr;
+  if (direct_call.check_receiver_for_null_) {
+    // Duplicate receiver for CheckNull before it is consumed by PushArgument.
+    receiver = MakeTemporary();
+    instructions += LoadLocal(receiver);
+  }
+
+  const String& getter_name = ReadNameAsGetterName();  // read name.
+  SkipDartType();                                      // read result_type.
+  const NameIndex itarget_name =
+      ReadInterfaceMemberNameReference();  // read interface_target_reference.
+  ASSERT(!H.IsRoot(itarget_name) && H.IsMethod(itarget_name));
+  const auto& tearoff_interface_target = Function::ZoneHandle(
+      Z, H.LookupMethodByMember(itarget_name, H.DartMethodName(itarget_name)));
+
+  if (direct_call.check_receiver_for_null_) {
+    instructions += CheckNull(position, receiver, getter_name);
+  }
+
+  if (!direct_call.target_.IsNull()) {
+    ASSERT(CompilerState::Current().is_aot());
+    instructions +=
+        StaticCall(position, direct_call.target_, 1, Array::null_array(),
+                   ICData::kNoRebind, &result_type);
+  } else {
+    const intptr_t kTypeArgsLen = 0;
+    const intptr_t kNumArgsChecked = 1;
+    instructions += InstanceCall(position, getter_name, Token::kGET,
+                                 kTypeArgsLen, 1, Array::null_array(),
+                                 kNumArgsChecked, Function::null_function(),
+                                 tearoff_interface_target, &result_type);
+  }
+
+  if (direct_call.check_receiver_for_null_) {
+    instructions += DropTempsPreserveTop(1);  // Drop receiver, preserve result.
+  }
+
+  return instructions;
+}
+
+Fragment StreamingFlowGraphBuilder::BuildFunctionTearOff(TokenPosition* p) {
+  const intptr_t offset = ReaderOffset() - 1;     // Include the tag.
+  const TokenPosition position = ReadPosition();  // read position.
+  if (p != nullptr) *p = position;
+
+  const DirectCallMetadata direct_call =
+      direct_call_metadata_helper_.GetDirectTargetForPropertyGet(offset);
+  const InferredTypeMetadata result_type =
+      inferred_type_metadata_helper_.GetInferredType(offset);
+
+  Fragment instructions = BuildExpression();  // read receiver.
+
+  LocalVariable* receiver = nullptr;
+  if (direct_call.check_receiver_for_null_) {
+    // Duplicate receiver for CheckNull before it is consumed by PushArgument.
+    receiver = MakeTemporary();
+    instructions += LoadLocal(receiver);
+  }
+
+  if (direct_call.check_receiver_for_null_) {
+    instructions += CheckNull(position, receiver, Symbols::GetCall());
+  }
+
+  if (!direct_call.target_.IsNull()) {
+    ASSERT(CompilerState::Current().is_aot());
+    instructions +=
+        StaticCall(position, direct_call.target_, 1, Array::null_array(),
+                   ICData::kNoRebind, &result_type);
+  } else {
+    const intptr_t kTypeArgsLen = 0;
+    const intptr_t kNumArgsChecked = 1;
+    instructions += InstanceCall(position, Symbols::GetCall(), Token::kGET,
+                                 kTypeArgsLen, 1, Array::null_array(),
+                                 kNumArgsChecked, Function::null_function(),
+                                 Function::null_function(), &result_type);
+  }
+
+  if (direct_call.check_receiver_for_null_) {
+    instructions += DropTempsPreserveTop(1);  // Drop receiver, preserve result.
+  }
+
+  return instructions;
+}
+
 Fragment StreamingFlowGraphBuilder::BuildPropertySet(TokenPosition* p) {
   const intptr_t offset = ReaderOffset() - 1;  // Include the tag.
 
@@ -2322,6 +2549,171 @@
   return instructions;
 }
 
+Fragment StreamingFlowGraphBuilder::BuildInstanceSet(TokenPosition* p) {
+  const intptr_t offset = ReaderOffset() - 1;  // Include the tag.
+  ReadByte();                                  // read kind.
+
+  const DirectCallMetadata direct_call =
+      direct_call_metadata_helper_.GetDirectTargetForPropertySet(offset);
+  const CallSiteAttributesMetadata call_site_attributes =
+      call_site_attributes_metadata_helper_.GetCallSiteAttributes(offset);
+  const InferredTypeMetadata inferred_type =
+      inferred_type_metadata_helper_.GetInferredType(offset);
+
+  // True if callee can skip argument type checks.
+  bool is_unchecked_call = inferred_type.IsSkipCheck();
+  if (call_site_attributes.receiver_type != nullptr &&
+      call_site_attributes.receiver_type->HasTypeClass() &&
+      !Class::Handle(call_site_attributes.receiver_type->type_class())
+           .IsGeneric()) {
+    is_unchecked_call = true;
+  }
+
+  Fragment instructions(MakeTemp());
+  LocalVariable* variable = MakeTemporary();
+
+  const TokenPosition position = ReadPosition();  // read position.
+  if (p != nullptr) *p = position;
+
+  if (PeekTag() == kThisExpression) {
+    is_unchecked_call = true;
+  }
+  instructions += BuildExpression();  // read receiver.
+
+  LocalVariable* receiver = nullptr;
+  if (direct_call.check_receiver_for_null_) {
+    // Duplicate receiver for CheckNull before it is consumed by PushArgument.
+    receiver = MakeTemporary();
+    instructions += LoadLocal(receiver);
+  }
+
+  const String& setter_name = ReadNameAsSetterName();  // read name.
+
+  instructions += BuildExpression();  // read value.
+  instructions += StoreLocal(TokenPosition::kNoSource, variable);
+
+  const NameIndex itarget_name =
+      ReadInterfaceMemberNameReference();  // read interface_target_reference.
+  ASSERT(!H.IsRoot(itarget_name));
+  const auto& interface_target = Function::ZoneHandle(
+      Z, H.LookupMethodByMember(itarget_name, H.DartSetterName(itarget_name)));
+  ASSERT(setter_name.ptr() == interface_target.name());
+
+  if (direct_call.check_receiver_for_null_) {
+    instructions += CheckNull(position, receiver, setter_name);
+  }
+
+  if (!direct_call.target_.IsNull()) {
+    ASSERT(CompilerState::Current().is_aot());
+    instructions +=
+        StaticCall(position, direct_call.target_, 2, Array::null_array(),
+                   ICData::kNoRebind, /*result_type=*/nullptr,
+                   /*type_args_count=*/0,
+                   /*use_unchecked_entry=*/is_unchecked_call);
+  } else {
+    const intptr_t kTypeArgsLen = 0;
+    const intptr_t kNumArgsChecked = 1;
+
+    instructions += InstanceCall(
+        position, setter_name, Token::kSET, kTypeArgsLen, 2,
+        Array::null_array(), kNumArgsChecked, interface_target,
+        Function::null_function(),
+        /*result_type=*/nullptr,
+        /*use_unchecked_entry=*/is_unchecked_call, &call_site_attributes);
+  }
+
+  instructions += Drop();  // Drop result of the setter invocation.
+
+  if (direct_call.check_receiver_for_null_) {
+    instructions += Drop();  // Drop receiver.
+  }
+
+  return instructions;
+}
+
+Fragment StreamingFlowGraphBuilder::BuildDynamicSet(TokenPosition* p) {
+  const intptr_t offset = ReaderOffset() - 1;  // Include the tag.
+  ReadByte();                                  // read kind.
+
+  const DirectCallMetadata direct_call =
+      direct_call_metadata_helper_.GetDirectTargetForPropertySet(offset);
+  const CallSiteAttributesMetadata call_site_attributes =
+      call_site_attributes_metadata_helper_.GetCallSiteAttributes(offset);
+  const InferredTypeMetadata inferred_type =
+      inferred_type_metadata_helper_.GetInferredType(offset);
+
+  // True if callee can skip argument type checks.
+  bool is_unchecked_call = inferred_type.IsSkipCheck();
+  if (call_site_attributes.receiver_type != nullptr &&
+      call_site_attributes.receiver_type->HasTypeClass() &&
+      !Class::Handle(call_site_attributes.receiver_type->type_class())
+           .IsGeneric()) {
+    is_unchecked_call = true;
+  }
+
+  Fragment instructions(MakeTemp());
+  LocalVariable* variable = MakeTemporary();
+
+  const TokenPosition position = ReadPosition();  // read position.
+  if (p != nullptr) *p = position;
+
+  if (PeekTag() == kThisExpression) {
+    is_unchecked_call = true;
+  }
+  instructions += BuildExpression();  // read receiver.
+
+  LocalVariable* receiver = nullptr;
+  if (direct_call.check_receiver_for_null_) {
+    // Duplicate receiver for CheckNull before it is consumed by PushArgument.
+    receiver = MakeTemporary();
+    instructions += LoadLocal(receiver);
+  }
+
+  const String& setter_name = ReadNameAsSetterName();  // read name.
+
+  instructions += BuildExpression();  // read value.
+  instructions += StoreLocal(TokenPosition::kNoSource, variable);
+
+  if (direct_call.check_receiver_for_null_) {
+    instructions += CheckNull(position, receiver, setter_name);
+  }
+
+  const Function* direct_call_target = &direct_call.target_;
+  const auto& mangled_name = String::ZoneHandle(
+      Z, Function::CreateDynamicInvocationForwarderName(setter_name));
+  if (!direct_call_target->IsNull()) {
+    direct_call_target = &Function::ZoneHandle(
+        direct_call.target_.GetDynamicInvocationForwarder(mangled_name));
+  }
+
+  if (!direct_call_target->IsNull()) {
+    ASSERT(CompilerState::Current().is_aot());
+    instructions +=
+        StaticCall(position, *direct_call_target, 2, Array::null_array(),
+                   ICData::kNoRebind, /*result_type=*/nullptr,
+                   /*type_args_count=*/0,
+                   /*use_unchecked_entry=*/is_unchecked_call);
+  } else {
+    const intptr_t kTypeArgsLen = 0;
+    const intptr_t kNumArgsChecked = 1;
+
+    instructions += InstanceCall(
+        position, mangled_name, Token::kSET, kTypeArgsLen, 2,
+        Array::null_array(), kNumArgsChecked, Function::null_function(),
+        Function::null_function(),
+        /*result_type=*/nullptr,
+        /*use_unchecked_entry=*/is_unchecked_call, &call_site_attributes);
+  }
+
+  instructions += Drop();  // Drop result of the setter invocation.
+
+  if (direct_call.check_receiver_for_null_) {
+    instructions += Drop();  // Drop receiver.
+  }
+
+  return instructions;
+}
+
 static Function& GetNoSuchMethodOrDie(Thread* thread,
                                       Zone* zone,
                                       const Class& klass) {
@@ -2641,10 +3033,20 @@
   }
 }
 
-Fragment StreamingFlowGraphBuilder::BuildMethodInvocation(TokenPosition* p) {
+Fragment StreamingFlowGraphBuilder::BuildMethodInvocation(TokenPosition* p,
+                                                          Tag tag) {
+  ASSERT((tag == kMethodInvocation) || (tag == kInstanceInvocation) ||
+         (tag == kDynamicInvocation));
   const intptr_t offset = ReaderOffset() - 1;  // Include the tag.
 
-  const uint8_t flags = ReadFlags();  // read flags.
+  if ((tag == kInstanceInvocation) || (tag == kDynamicInvocation)) {
+    ReadByte();  // read kind.
+  }
+
+  // read flags.
+  const uint8_t flags =
+      ((tag == kMethodInvocation) || (tag == kInstanceInvocation)) ? ReadFlags()
+                                                                   : 0;
   const bool is_invariant = (flags & kMethodInvocationFlagInvariant) != 0;
 
   const TokenPosition position = ReadPosition();  // read position.
@@ -2759,9 +3161,15 @@
     checked_argument_count = argument_count;
   }
 
+  if (tag == kInstanceInvocation) {
+    SkipDartType();  // read function_type.
+  }
+
   const Function* interface_target = &Function::null_function();
   const NameIndex itarget_name =
-      ReadInterfaceMemberNameReference();  // read interface_target_reference.
+      ((tag == kMethodInvocation) || (tag == kInstanceInvocation))
+          ? ReadInterfaceMemberNameReference()
+          : NameIndex();  // read interface_target_reference.
   // TODO(dartbug.com/34497): Once front-end desugars calls via
   // fields/getters, filtering of field and getter interface targets here
   // can be turned into assertions.
@@ -2846,6 +3254,191 @@
   return instructions;
 }
 
+Fragment StreamingFlowGraphBuilder::BuildLocalFunctionInvocation(
+    TokenPosition* p) {
+  const TokenPosition position = ReadPosition();
+  if (p != nullptr) *p = position;
+  // read variable kernel position.
+  const intptr_t variable_kernel_position = ReadUInt();
+  ReadUInt();  // read relative variable index.
+
+  LocalVariable* variable = LookupVariable(variable_kernel_position);
+  ASSERT(!variable->is_late());
+
+  Fragment instructions;
+
+  // Type arguments.
+  intptr_t type_args_len = 0;
+  {
+    AlternativeReadingScope alt(&reader_);
+    ReadUInt();                               // read argument count.
+    intptr_t list_length = ReadListLength();  // read types list length.
+    if (list_length > 0) {
+      const TypeArguments& type_arguments =
+          T.BuildTypeArguments(list_length);  // read types.
+      instructions += TranslateInstantiatedTypeArguments(type_arguments);
+    }
+    type_args_len = list_length;
+  }
+
+  // Receiver (closure).
+  instructions += LoadLocal(variable);
+
+  intptr_t argument_count;
+  intptr_t positional_argument_count;
+  Array& argument_names = Array::ZoneHandle(Z);
+  instructions +=
+      BuildArguments(&argument_names, &argument_count,
+                     &positional_argument_count);  // read arguments.
+  ++argument_count;                                // include receiver
+
+  SkipDartType();  // read function_type.
+
+  // Lookup the function in the closure.
+  instructions += LoadLocal(variable);
+  instructions += LoadNativeField(Slot::Closure_function());
+  if (parsed_function()->function().is_debuggable()) {
+    ASSERT(!parsed_function()->function().is_native());
+    instructions += DebugStepCheck(position);
+  }
+  instructions +=
+      B->ClosureCall(position, type_args_len, argument_count, argument_names,
+                     /*use_unchecked_entry=*/true);
+  return instructions;
+}
+
+Fragment StreamingFlowGraphBuilder::BuildFunctionInvocation(TokenPosition* p) {
+  const intptr_t offset = ReaderOffset() - 1;  // Include the tag.
+  const FunctionAccessKind function_access_kind =
+      static_cast<FunctionAccessKind>(ReadByte());  // read kind.
+  const TokenPosition position = ReadPosition();    // read position.
+  if (p != nullptr) *p = position;
+
+  const InferredTypeMetadata result_type =
+      inferred_type_metadata_helper_.GetInferredType(offset);
+  const CallSiteAttributesMetadata call_site_attributes =
+      call_site_attributes_metadata_helper_.GetCallSiteAttributes(offset);
+
+  const bool is_unchecked_closure_call =
+      (function_access_kind == FunctionAccessKind::kFunctionType);
+  Fragment instructions;
+
+  instructions += BuildExpression();  // read receiver.
+  LocalVariable* receiver_temp = MakeTemporary();
+
+  // Type arguments.
+  intptr_t type_args_len = 0;
+  {
+    AlternativeReadingScope alt(&reader_);
+    ReadUInt();                               // read argument count.
+    intptr_t list_length = ReadListLength();  // read types list length.
+    if (list_length > 0) {
+      const TypeArguments& type_arguments =
+          T.BuildTypeArguments(list_length);  // read types.
+      instructions += TranslateInstantiatedTypeArguments(type_arguments);
+    }
+    type_args_len = list_length;
+  }
+
+  // Receiver (closure).
+  instructions += LoadLocal(receiver_temp);
+
+  intptr_t argument_count;
+  intptr_t positional_argument_count;
+  Array& argument_names = Array::ZoneHandle(Z);
+  instructions +=
+      BuildArguments(&argument_names, &argument_count,
+                     &positional_argument_count);  // read arguments.
+  ++argument_count;                                // include receiver
+
+  SkipDartType();  // read function_type.
+
+  if (is_unchecked_closure_call) {
+    instructions += CheckNull(position, receiver_temp, Symbols::Call(),
+                              /*clear_temp=*/false);
+    // Lookup the function in the closure.
+    instructions += LoadLocal(receiver_temp);
+    instructions += LoadNativeField(Slot::Closure_function());
+    if (parsed_function()->function().is_debuggable()) {
+      ASSERT(!parsed_function()->function().is_native());
+      instructions += DebugStepCheck(position);
+    }
+    instructions +=
+        B->ClosureCall(position, type_args_len, argument_count, argument_names,
+                       /*use_unchecked_entry=*/true);
+  } else {
+    instructions += InstanceCall(
+        position, Symbols::DynamicCall(), Token::kILLEGAL, type_args_len,
+        argument_count, argument_names, 1, Function::null_function(),
+        Function::null_function(), &result_type,
+        /*use_unchecked_entry=*/false, &call_site_attributes,
+        result_type.ReceiverNotInt());
+  }
+  instructions += DropTempsPreserveTop(1);
+  return instructions;
+}
+
+Fragment StreamingFlowGraphBuilder::BuildEqualsCall(TokenPosition* p) {
+  const intptr_t offset = ReaderOffset() - 1;     // Include the tag.
+  const TokenPosition position = ReadPosition();  // read position.
+  if (p != nullptr) *p = position;
+
+  const DirectCallMetadata direct_call =
+      direct_call_metadata_helper_.GetDirectTargetForMethodInvocation(offset);
+  ASSERT(!direct_call.check_receiver_for_null_);
+  const InferredTypeMetadata result_type =
+      inferred_type_metadata_helper_.GetInferredType(offset);
+  const CallSiteAttributesMetadata call_site_attributes =
+      call_site_attributes_metadata_helper_.GetCallSiteAttributes(offset);
+
+  Fragment instructions;
+  instructions += BuildExpression();  // read left.
+  instructions += BuildExpression();  // read right.
+  SkipDartType();                     // read function_type.
+
+  const NameIndex itarget_name =
+      ReadInterfaceMemberNameReference();  // read interface_target_reference.
+  const auto& interface_target = Function::ZoneHandle(
+      Z,
+      H.LookupMethodByMember(itarget_name, H.DartProcedureName(itarget_name)));
+  ASSERT(interface_target.name() == Symbols::EqualOperator().ptr());
+
+  const intptr_t kTypeArgsLen = 0;
+  const intptr_t kNumArgs = 2;
+  const intptr_t kNumCheckedArgs = 2;
+
+  if (!direct_call.target_.IsNull()) {
+    ASSERT(CompilerState::Current().is_aot());
+    instructions +=
+        StaticCall(position, direct_call.target_, kNumArgs, Array::null_array(),
+                   ICData::kNoRebind, &result_type, kTypeArgsLen,
+                   /*use_unchecked_entry=*/true);
+  } else {
+    instructions += InstanceCall(
+        position, Symbols::EqualOperator(), Token::kEQ, kTypeArgsLen, kNumArgs,
+        Array::null_array(), kNumCheckedArgs, interface_target,
+        Function::null_function(), &result_type,
+        /*use_unchecked_entry=*/true, &call_site_attributes,
+        result_type.ReceiverNotInt());
+  }
+
+  return instructions;
+}
+
+Fragment StreamingFlowGraphBuilder::BuildEqualsNull(TokenPosition* p) {
+  const TokenPosition position = ReadPosition();  // read position.
+  if (p != nullptr) *p = position;
+  Fragment instructions;
+  instructions += BuildExpression();  // read expression.
+  instructions += NullConstant();
+  if (parsed_function()->function().is_debuggable()) {
+    instructions += DebugStepCheck(position);
+  }
+  instructions +=
+      StrictCompare(position, Token::kEQ_STRICT, /*number_check=*/false);
+  return instructions;
+}
+
 Fragment StreamingFlowGraphBuilder::BuildSuperMethodInvocation(
     TokenPosition* p) {
   const intptr_t offset = ReaderOffset() - 1;     // Include the tag.
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
index 47f5bca..c11dc7d 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
@@ -274,7 +274,13 @@
   Fragment BuildVariableSetImpl(TokenPosition position,
                                 intptr_t variable_kernel_position);
   Fragment BuildPropertyGet(TokenPosition* position);
+  Fragment BuildInstanceGet(TokenPosition* position);
+  Fragment BuildDynamicGet(TokenPosition* position);
+  Fragment BuildInstanceTearOff(TokenPosition* position);
+  Fragment BuildFunctionTearOff(TokenPosition* position);
   Fragment BuildPropertySet(TokenPosition* position);
+  Fragment BuildInstanceSet(TokenPosition* position);
+  Fragment BuildDynamicSet(TokenPosition* position);
   Fragment BuildAllocateInvocationMirrorCall(TokenPosition position,
                                              const String& name,
                                              intptr_t num_type_arguments,
@@ -286,7 +292,11 @@
   Fragment BuildSuperPropertySet(TokenPosition* position);
   Fragment BuildStaticGet(TokenPosition* position);
   Fragment BuildStaticSet(TokenPosition* position);
-  Fragment BuildMethodInvocation(TokenPosition* position);
+  Fragment BuildMethodInvocation(TokenPosition* position, Tag tag);
+  Fragment BuildLocalFunctionInvocation(TokenPosition* position);
+  Fragment BuildFunctionInvocation(TokenPosition* position);
+  Fragment BuildEqualsCall(TokenPosition* position);
+  Fragment BuildEqualsNull(TokenPosition* position);
   Fragment BuildSuperMethodInvocation(TokenPosition* position);
   Fragment BuildStaticInvocation(TokenPosition* position);
   Fragment BuildConstructorInvocation(TokenPosition* position);
diff --git a/runtime/vm/compiler/frontend/kernel_fingerprints.cc b/runtime/vm/compiler/frontend/kernel_fingerprints.cc
index 5d5890f..4b0426c 100644
--- a/runtime/vm/compiler/frontend/kernel_fingerprints.cc
+++ b/runtime/vm/compiler/frontend/kernel_fingerprints.cc
@@ -379,6 +379,32 @@
       BuildHash(ReadNameAsGetterName().Hash());  // read name.
       CalculateGetterNameFingerprint();  // read interface_target_reference.
       return;
+    case kInstanceGet:
+      ReadByte();                                // read kind.
+      ReadPosition();                            // read position.
+      CalculateExpressionFingerprint();          // read receiver.
+      BuildHash(ReadNameAsGetterName().Hash());  // read name.
+      SkipDartType();                            // read result_type.
+      CalculateGetterNameFingerprint();  // read interface_target_reference.
+      return;
+    case kDynamicGet:
+      ReadByte();                                // read kind.
+      ReadPosition();                            // read position.
+      CalculateExpressionFingerprint();          // read receiver.
+      BuildHash(ReadNameAsGetterName().Hash());  // read name.
+      return;
+    case kInstanceTearOff:
+      ReadByte();                                // read kind.
+      ReadPosition();                            // read position.
+      CalculateExpressionFingerprint();          // read receiver.
+      BuildHash(ReadNameAsGetterName().Hash());  // read name.
+      SkipDartType();                            // read result_type.
+      CalculateGetterNameFingerprint();  // read interface_target_reference.
+      return;
+    case kFunctionTearOff:
+      ReadPosition();                    // read position.
+      CalculateExpressionFingerprint();  // read receiver.
+      return;
     case kPropertySet:
       ReadPosition();                            // read position.
       CalculateExpressionFingerprint();          // read receiver.
@@ -386,6 +412,21 @@
       CalculateExpressionFingerprint();          // read value.
       CalculateSetterNameFingerprint();  // read interface_target_reference.
       return;
+    case kInstanceSet:
+      ReadByte();                                // read kind.
+      ReadPosition();                            // read position.
+      CalculateExpressionFingerprint();          // read receiver.
+      BuildHash(ReadNameAsSetterName().Hash());  // read name.
+      CalculateExpressionFingerprint();          // read value.
+      CalculateSetterNameFingerprint();  // read interface_target_reference.
+      return;
+    case kDynamicSet:
+      ReadByte();                                // read kind.
+      ReadPosition();                            // read position.
+      CalculateExpressionFingerprint();          // read receiver.
+      BuildHash(ReadNameAsSetterName().Hash());  // read name.
+      CalculateExpressionFingerprint();          // read value.
+      return;
     case kSuperPropertyGet:
       ReadPosition();                            // read position.
       BuildHash(ReadNameAsGetterName().Hash());  // read name.
@@ -414,6 +455,48 @@
       CalculateArgumentsFingerprint();           // read arguments.
       CalculateMethodNameFingerprint();  // read interface_target_reference.
       return;
+    case kInstanceInvocation:
+      ReadByte();                                // read kind.
+      ReadFlags();                               // read flags.
+      ReadPosition();                            // read position.
+      CalculateExpressionFingerprint();          // read receiver.
+      BuildHash(ReadNameAsMethodName().Hash());  // read name.
+      CalculateArgumentsFingerprint();           // read arguments.
+      SkipDartType();                            // read function_type.
+      CalculateMethodNameFingerprint();  // read interface_target_reference.
+      return;
+    case kDynamicInvocation:
+      ReadByte();                                // read kind.
+      ReadPosition();                            // read position.
+      CalculateExpressionFingerprint();          // read receiver.
+      BuildHash(ReadNameAsMethodName().Hash());  // read name.
+      CalculateArgumentsFingerprint();           // read arguments.
+      return;
+    case kLocalFunctionInvocation:
+      ReadPosition();                   // read position.
+      ReadUInt();                       // read variable kernel position.
+      ReadUInt();                       // read relative variable index.
+      CalculateArgumentsFingerprint();  // read arguments.
+      SkipDartType();                   // read function_type.
+      return;
+    case kFunctionInvocation:
+      BuildHash(ReadByte());             // read kind.
+      ReadPosition();                    // read position.
+      CalculateExpressionFingerprint();  // read receiver.
+      CalculateArgumentsFingerprint();   // read arguments.
+      SkipDartType();                    // read function_type.
+      return;
+    case kEqualsCall:
+      ReadPosition();                    // read position.
+      CalculateExpressionFingerprint();  // read left.
+      CalculateExpressionFingerprint();  // read right.
+      SkipDartType();                    // read function_type.
+      CalculateMethodNameFingerprint();  // read interface_target_reference.
+      return;
+    case kEqualsNull:
+      ReadPosition();                    // read position.
+      CalculateExpressionFingerprint();  // read expression.
+      return;
     case kSuperMethodInvocation:
       ReadPosition();                            // read position.
       BuildHash(ReadNameAsMethodName().Hash());  // read name.
@@ -558,15 +641,13 @@
     case kConstSetLiteral:
     case kConstMapLiteral:
     case kSymbolLiteral:
-      // Const invocations and const literals are removed by the
-      // constant evaluator.
     case kListConcatenation:
     case kSetConcatenation:
     case kMapConcatenation:
     case kInstanceCreation:
     case kFileUriExpression:
-      // Collection concatenation, instance creation operations and
-      // in-expression URI changes are internal to the front end and
+    case kStaticTearOff:
+      // These nodes are internal to the front end and
       // removed by the constant evaluator.
     default:
       ReportUnexpectedTag("expression", tag);
diff --git a/runtime/vm/compiler/frontend/kernel_translation_helper.cc b/runtime/vm/compiler/frontend/kernel_translation_helper.cc
index f786a81..8dd8f8a 100644
--- a/runtime/vm/compiler/frontend/kernel_translation_helper.cc
+++ b/runtime/vm/compiler/frontend/kernel_translation_helper.cc
@@ -2315,6 +2315,32 @@
       SkipName();                    // read name.
       SkipInterfaceMemberNameReference();  // read interface_target_reference.
       return;
+    case kInstanceGet:
+      ReadByte();                          // read kind.
+      ReadPosition();                      // read position.
+      SkipExpression();                    // read receiver.
+      SkipName();                          // read name.
+      SkipDartType();                      // read result_type.
+      SkipInterfaceMemberNameReference();  // read interface_target_reference.
+      return;
+    case kDynamicGet:
+      ReadByte();        // read kind.
+      ReadPosition();    // read position.
+      SkipExpression();  // read receiver.
+      SkipName();        // read name.
+      return;
+    case kInstanceTearOff:
+      ReadByte();                          // read kind.
+      ReadPosition();                      // read position.
+      SkipExpression();                    // read receiver.
+      SkipName();                          // read name.
+      SkipDartType();                      // read result_type.
+      SkipInterfaceMemberNameReference();  // read interface_target_reference.
+      return;
+    case kFunctionTearOff:
+      ReadPosition();    // read position.
+      SkipExpression();  // read receiver.
+      return;
     case kPropertySet:
       ReadPosition();                // read position.
       SkipExpression();              // read receiver.
@@ -2322,6 +2348,21 @@
       SkipExpression();              // read value.
       SkipInterfaceMemberNameReference();  // read interface_target_reference.
       return;
+    case kInstanceSet:
+      ReadByte();                          // read kind.
+      ReadPosition();                      // read position.
+      SkipExpression();                    // read receiver.
+      SkipName();                          // read name.
+      SkipExpression();                    // read value.
+      SkipInterfaceMemberNameReference();  // read interface_target_reference.
+      return;
+    case kDynamicSet:
+      ReadByte();        // read kind.
+      ReadPosition();    // read position.
+      SkipExpression();  // read receiver.
+      SkipName();        // read name.
+      SkipExpression();  // read value.
+      return;
     case kSuperPropertyGet:
       ReadPosition();                // read position.
       SkipName();                    // read name.
@@ -2350,6 +2391,48 @@
       SkipArguments();               // read arguments.
       SkipInterfaceMemberNameReference();  // read interface_target_reference.
       return;
+    case kInstanceInvocation:
+      ReadByte();                          // read kind.
+      ReadFlags();                         // read flags.
+      ReadPosition();                      // read position.
+      SkipExpression();                    // read receiver.
+      SkipName();                          // read name.
+      SkipArguments();                     // read arguments.
+      SkipDartType();                      // read function_type.
+      SkipInterfaceMemberNameReference();  // read interface_target_reference.
+      return;
+    case kDynamicInvocation:
+      ReadByte();        // read kind.
+      ReadPosition();    // read position.
+      SkipExpression();  // read receiver.
+      SkipName();        // read name.
+      SkipArguments();   // read arguments.
+      return;
+    case kLocalFunctionInvocation:
+      ReadPosition();   // read position.
+      ReadUInt();       // read variable kernel position.
+      ReadUInt();       // read relative variable index.
+      SkipArguments();  // read arguments.
+      SkipDartType();   // read function_type.
+      return;
+    case kFunctionInvocation:
+      ReadByte();        // read kind.
+      ReadPosition();    // read position.
+      SkipExpression();  // read receiver.
+      SkipArguments();   // read arguments.
+      SkipDartType();    // read function_type.
+      return;
+    case kEqualsCall:
+      ReadPosition();                      // read position.
+      SkipExpression();                    // read left.
+      SkipExpression();                    // read right.
+      SkipDartType();                      // read function_type.
+      SkipInterfaceMemberNameReference();  // read interface_target_reference.
+      return;
+    case kEqualsNull:
+      ReadPosition();    // read position.
+      SkipExpression();  // read expression.
+      return;
     case kSuperMethodInvocation:
       ReadPosition();                // read position.
       SkipName();                    // read name.
@@ -2490,15 +2573,13 @@
     case kConstSetLiteral:
     case kConstMapLiteral:
     case kSymbolLiteral:
-      // Const invocations and const literals are removed by the
-      // constant evaluator.
     case kListConcatenation:
     case kSetConcatenation:
     case kMapConcatenation:
     case kInstanceCreation:
     case kFileUriExpression:
-      // Collection concatenation, instance creation operations and
-      // in-expression URI changes are internal to the front end and
+    case kStaticTearOff:
+      // These nodes are internal to the front end and
       // removed by the constant evaluator.
     default:
       ReportUnexpectedTag("expression", tag);
diff --git a/runtime/vm/compiler/frontend/scope_builder.cc b/runtime/vm/compiler/frontend/scope_builder.cc
index 81730a0..27be5e5 100644
--- a/runtime/vm/compiler/frontend/scope_builder.cc
+++ b/runtime/vm/compiler/frontend/scope_builder.cc
@@ -693,6 +693,34 @@
       // read interface_target_reference.
       helper_.SkipInterfaceMemberNameReference();
       return;
+    case kInstanceGet:
+      helper_.ReadByte();      // read kind.
+      helper_.ReadPosition();  // read position.
+      VisitExpression();       // read receiver.
+      helper_.SkipName();      // read name.
+      helper_.SkipDartType();  // read result_type.
+      // read interface_target_reference.
+      helper_.SkipInterfaceMemberNameReference();
+      return;
+    case kDynamicGet:
+      helper_.ReadByte();      // read kind.
+      helper_.ReadPosition();  // read position.
+      VisitExpression();       // read receiver.
+      helper_.SkipName();      // read name.
+      return;
+    case kInstanceTearOff:
+      helper_.ReadByte();      // read kind.
+      helper_.ReadPosition();  // read position.
+      VisitExpression();       // read receiver.
+      helper_.SkipName();      // read name.
+      helper_.SkipDartType();  // read result_type.
+      // read interface_target_reference.
+      helper_.SkipInterfaceMemberNameReference();
+      return;
+    case kFunctionTearOff:
+      helper_.ReadPosition();  // read position.
+      VisitExpression();       // read receiver.
+      return;
     case kPropertySet:
       helper_.ReadPosition();  // read position.
       VisitExpression();       // read receiver.
@@ -701,6 +729,22 @@
       // read interface_target_reference.
       helper_.SkipInterfaceMemberNameReference();
       return;
+    case kInstanceSet:
+      helper_.ReadByte();      // read kind.
+      helper_.ReadPosition();  // read position.
+      VisitExpression();       // read receiver.
+      helper_.SkipName();      // read name.
+      VisitExpression();       // read value.
+      // read interface_target_reference.
+      helper_.SkipInterfaceMemberNameReference();
+      return;
+    case kDynamicSet:
+      helper_.ReadByte();      // read kind.
+      helper_.ReadPosition();  // read position.
+      VisitExpression();       // read receiver.
+      helper_.SkipName();      // read name.
+      VisitExpression();       // read value.
+      return;
     case kSuperPropertyGet:
       HandleLoadReceiver();
       helper_.ReadPosition();                      // read position.
@@ -732,6 +776,53 @@
       // read interface_target_reference.
       helper_.SkipInterfaceMemberNameReference();
       return;
+    case kInstanceInvocation:
+      helper_.ReadByte();      // read kind.
+      helper_.ReadFlags();     // read flags.
+      helper_.ReadPosition();  // read position.
+      VisitExpression();       // read receiver.
+      helper_.SkipName();      // read name.
+      VisitArguments();        // read arguments.
+      helper_.SkipDartType();  // read function_type.
+      // read interface_target_reference.
+      helper_.SkipInterfaceMemberNameReference();
+      return;
+    case kDynamicInvocation:
+      helper_.ReadByte();      // read kind.
+      helper_.ReadPosition();  // read position.
+      VisitExpression();       // read receiver.
+      helper_.SkipName();      // read name.
+      VisitArguments();        // read arguments.
+      return;
+    case kLocalFunctionInvocation: {
+      helper_.ReadPosition();  // read position.
+      intptr_t variable_kernel_offset =
+          helper_.ReadUInt();  // read variable kernel position.
+      helper_.ReadUInt();      // read relative variable index.
+      VisitArguments();        // read arguments.
+      helper_.SkipDartType();  // read function_type.
+      VisitVariableGet(variable_kernel_offset);
+      return;
+    }
+    case kFunctionInvocation:
+      helper_.ReadByte();      // read kind.
+      helper_.ReadPosition();  // read position.
+      VisitExpression();       // read receiver.
+      VisitArguments();        // read arguments.
+      helper_.SkipDartType();  // read function_type.
+      return;
+    case kEqualsCall:
+      helper_.ReadPosition();  // read position.
+      VisitExpression();       // read left.
+      VisitExpression();       // read right.
+      helper_.SkipDartType();  // read function_type.
+      // read interface_target_reference.
+      helper_.SkipInterfaceMemberNameReference();
+      return;
+    case kEqualsNull:
+      helper_.ReadPosition();  // read position.
+      VisitExpression();       // read expression.
+      return;
     case kSuperMethodInvocation:
       HandleLoadReceiver();
       helper_.ReadPosition();  // read position.
@@ -914,15 +1005,13 @@
     case kConstSetLiteral:
     case kConstMapLiteral:
     case kSymbolLiteral:
-      // Const invocations and const literals are removed by the
-      // constant evaluator.
     case kListConcatenation:
     case kSetConcatenation:
     case kMapConcatenation:
     case kInstanceCreation:
     case kFileUriExpression:
-      // Collection concatenation, instance creation operations and
-      // in-expression URI changes are internal to the front end and
+    case kStaticTearOff:
+      // These nodes are internal to the front end and
       // removed by the constant evaluator.
     default:
       ReportUnexpectedTag("expression", tag);
diff --git a/runtime/vm/kernel_binary.h b/runtime/vm/kernel_binary.h
index c7b1fe5..6b6878f 100644
--- a/runtime/vm/kernel_binary.h
+++ b/runtime/vm/kernel_binary.h
@@ -214,6 +214,14 @@
   kIsRequired = 1 << 0,
 };
 
+// Keep in sync with package:kernel/lib/ast.dart
+enum class FunctionAccessKind {
+  kFunction,
+  kFunctionType,
+  kInapplicable,
+  kNullable,
+};
+
 static const int SpecializedIntLiteralBias = 3;
 static const int LibraryCountFieldCountFromEnd = 1;
 static const int KernelFormatVersionOffset = 4;