[vm/bytecode] Cleanup uses of KernelReaderHelper from bytecode reader

Also, cleanup/streamline uses of BytecodeMetadataHelper where
kernel metadata is no longer involved.

Change-Id: I067c2556bbf0614a365131299140589f9e0007f4
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/105023
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Reviewed-by: RĂ©gis Crelier <regis@google.com>
Commit-Queue: Alexander Markov <alexmarkov@google.com>
diff --git a/runtime/vm/compiler/frontend/bytecode_reader.cc b/runtime/vm/compiler/frontend/bytecode_reader.cc
index e59d856..c180689 100644
--- a/runtime/vm/compiler/frontend/bytecode_reader.cc
+++ b/runtime/vm/compiler/frontend/bytecode_reader.cc
@@ -36,77 +36,6 @@
     : MetadataHelper(helper, tag(), /* precompiler_only = */ false),
       active_class_(active_class) {}
 
-bool BytecodeMetadataHelper::HasBytecode(intptr_t node_offset) {
-  const intptr_t md_offset = GetNextMetadataPayloadOffset(node_offset);
-  return (md_offset >= 0);
-}
-
-void BytecodeMetadataHelper::ReadMetadata(const Function& function) {
-#if defined(SUPPORT_TIMELINE)
-  TimelineDurationScope tds(Thread::Current(), Timeline::GetCompilerStream(),
-                            "BytecodeMetadataHelper::ReadMetadata");
-  // This increases bytecode reading time by ~7%, so only keep it around for
-  // debugging.
-#if defined(DEBUG)
-  tds.SetNumArguments(1);
-  tds.CopyArgument(0, "Function", function.ToQualifiedCString());
-#endif  // defined(DEBUG)
-#endif  // !defined(SUPPORT_TIMELINE)
-
-  switch (function.kind()) {
-    case RawFunction::kImplicitGetter:
-      function.AttachBytecode(Object::implicit_getter_bytecode());
-      return;
-    case RawFunction::kImplicitSetter:
-      function.AttachBytecode(Object::implicit_setter_bytecode());
-      return;
-    case RawFunction::kImplicitStaticGetter:
-      if (IsStaticFieldGetterGeneratedAsInitializer(function, helper_->zone_)) {
-        break;
-      }
-      function.AttachBytecode(Object::implicit_static_getter_bytecode());
-      return;
-    case RawFunction::kMethodExtractor:
-      function.AttachBytecode(Object::method_extractor_bytecode());
-      return;
-    case RawFunction::kInvokeFieldDispatcher:
-      if (Class::Handle(function.Owner()).id() == kClosureCid) {
-        function.AttachBytecode(Object::invoke_closure_bytecode());
-      } else {
-        function.AttachBytecode(Object::invoke_field_bytecode());
-      }
-      return;
-    case RawFunction::kNoSuchMethodDispatcher:
-      function.AttachBytecode(Object::nsm_dispatcher_bytecode());
-      return;
-    default:
-      break;
-  }
-
-  intptr_t code_offset = 0;
-  if (function.is_declared_in_bytecode()) {
-    code_offset = function.bytecode_offset();
-    if (code_offset == 0) {
-      return;
-    }
-  } else {
-    const intptr_t node_offset = function.kernel_offset();
-    code_offset = GetNextMetadataPayloadOffset(node_offset);
-    if (code_offset < 0) {
-      return;
-    }
-  }
-
-  ASSERT(Thread::Current()->IsMutatorThread());
-
-  BytecodeComponentData bytecode_component(
-      Array::Handle(helper_->zone_, GetBytecodeComponent()));
-  BytecodeReaderHelper bytecode_reader(helper_, active_class_,
-                                       &bytecode_component);
-
-  bytecode_reader.ReadCode(function, code_offset);
-}
-
 void BytecodeMetadataHelper::ParseBytecodeFunction(
     ParsedFunction* parsed_function) {
   TIMELINE_DURATION(Thread::Current(), CompilerVerbose,
@@ -130,8 +59,7 @@
 
   BytecodeComponentData bytecode_component(
       Array::Handle(helper_->zone_, GetBytecodeComponent()));
-  BytecodeReaderHelper bytecode_reader(helper_, active_class_,
-                                       &bytecode_component);
+  BytecodeReaderHelper bytecode_reader(&H, active_class_, &bytecode_component);
 
   bytecode_reader.ParseBytecodeFunction(parsed_function, function);
 }
@@ -152,33 +80,17 @@
 
   BytecodeComponentData bytecode_component(
       Array::Handle(helper_->zone_, GetBytecodeComponent()));
-  BytecodeReaderHelper bytecode_reader(helper_, active_class_,
-                                       &bytecode_component);
+  BytecodeReaderHelper bytecode_reader(&H, active_class_, &bytecode_component);
 
-  AlternativeReadingScope alt(&helper_->reader_, &H.metadata_payloads(),
-                              md_offset);
+  AlternativeReadingScope alt(&bytecode_reader.reader(), md_offset);
 
-  intptr_t members_offset = helper_->reader_.ReadUInt();
+  intptr_t members_offset = bytecode_reader.reader().ReadUInt();
 
   bytecode_reader.ReadMembers(cls, members_offset, discard_fields);
 
   return true;
 }
 
-RawObject* BytecodeMetadataHelper::ReadAnnotation(intptr_t annotation_offset) {
-  ASSERT(Thread::Current()->IsMutatorThread());
-
-  BytecodeComponentData bytecode_component(
-      Array::Handle(helper_->zone_, GetBytecodeComponent()));
-  BytecodeReaderHelper bytecode_reader(helper_, active_class_,
-                                       &bytecode_component);
-
-  AlternativeReadingScope alt(&helper_->reader_, &H.metadata_payloads(),
-                              annotation_offset);
-
-  return bytecode_reader.ReadObject();
-}
-
 RawLibrary* BytecodeMetadataHelper::GetMainLibrary() {
   const intptr_t md_offset = GetComponentMetadataPayloadOffset();
   if (md_offset < 0) {
@@ -192,10 +104,8 @@
     return Library::null();
   }
 
-  BytecodeReaderHelper bytecode_reader(helper_, active_class_,
-                                       &bytecode_component);
-  AlternativeReadingScope alt(&helper_->reader_, &H.metadata_payloads(),
-                              main_offset);
+  BytecodeReaderHelper bytecode_reader(&H, active_class_, &bytecode_component);
+  AlternativeReadingScope alt(&bytecode_reader.reader(), main_offset);
   return bytecode_reader.ReadMain();
 }
 
@@ -214,22 +124,23 @@
     return Array::null();
   }
 
-  BytecodeReaderHelper component_reader(helper_, nullptr, nullptr);
+  BytecodeReaderHelper component_reader(&H, nullptr, nullptr);
   return component_reader.ReadBytecodeComponent(md_offset);
 }
 
 BytecodeReaderHelper::BytecodeReaderHelper(
-    KernelReaderHelper* helper,
+    TranslationHelper* translation_helper,
     ActiveClass* active_class,
     BytecodeComponentData* bytecode_component)
-    : helper_(helper),
-      translation_helper_(helper->translation_helper_),
+    : reader_(translation_helper->metadata_payloads()),
+      translation_helper_(*translation_helper),
       active_class_(active_class),
-      zone_(helper_->zone_),
+      thread_(translation_helper->thread()),
+      zone_(translation_helper->zone()),
       bytecode_component_(bytecode_component),
-      scoped_function_(Function::Handle(helper_->zone_)),
-      scoped_function_name_(String::Handle(helper_->zone_)),
-      scoped_function_class_(Class::Handle(helper_->zone_)) {}
+      scoped_function_(Function::Handle(translation_helper->zone())),
+      scoped_function_name_(String::Handle(translation_helper->zone())),
+      scoped_function_class_(Class::Handle(translation_helper->zone())) {}
 
 void BytecodeReaderHelper::ReadCode(const Function& function,
                                     intptr_t code_offset) {
@@ -238,10 +149,9 @@
          !function.IsImplicitSetterFunction());
   ASSERT(code_offset > 0);
 
-  AlternativeReadingScope alt(&helper_->reader_, &H.metadata_payloads(),
-                              code_offset);
+  AlternativeReadingScope alt(&reader_, code_offset);
 
-  const intptr_t flags = helper_->reader_.ReadUInt();
+  const intptr_t flags = reader_.ReadUInt();
   const bool has_exceptions_table =
       (flags & Code::kHasExceptionsTableFlag) != 0;
   const bool has_source_positions =
@@ -256,23 +166,23 @@
       (flags & Code::kHasDefaultFunctionTypeArgsFlag) != 0;
 
   if (has_parameters_flags) {
-    intptr_t num_params = helper_->reader_.ReadUInt();
+    intptr_t num_params = reader_.ReadUInt();
     ASSERT(num_params ==
            function.NumParameters() - function.NumImplicitParameters());
     for (intptr_t i = 0; i < num_params; ++i) {
-      helper_->reader_.ReadUInt();
+      reader_.ReadUInt();
     }
   }
   if (has_forwarding_stub_target) {
-    helper_->reader_.ReadUInt();
+    reader_.ReadUInt();
   }
   if (has_default_function_type_args) {
-    helper_->reader_.ReadUInt();
+    reader_.ReadUInt();
   }
 
   intptr_t num_closures = 0;
   if (has_closures) {
-    num_closures = helper_->ReadListLength();
+    num_closures = reader_.ReadListLength();
     closures_ = &Array::Handle(Z, Array::New(num_closures));
     for (intptr_t i = 0; i < num_closures; i++) {
       ReadClosureDeclaration(function, i);
@@ -280,7 +190,7 @@
   }
 
   // Create object pool and read pool entries.
-  const intptr_t obj_count = helper_->reader_.ReadListLength();
+  const intptr_t obj_count = reader_.ReadListLength();
   const ObjectPool& pool = ObjectPool::Handle(Z, ObjectPool::New(obj_count));
 
   {
@@ -288,7 +198,7 @@
     // ICData objects.
     //
     // TODO(alexmarkov): allocate deopt_ids for closures separately
-    DeoptIdScope deopt_id_scope(H.thread(), 0);
+    DeoptIdScope deopt_id_scope(thread_, 0);
 
     ReadConstantPool(function, pool);
   }
@@ -296,7 +206,7 @@
   // Read bytecode and attach to function.
   const Bytecode& bytecode = Bytecode::Handle(Z, ReadBytecode(pool));
   function.AttachBytecode(bytecode);
-  ASSERT(bytecode.GetBinary(Z) == helper_->reader_.typed_data()->raw());
+  ASSERT(bytecode.GetBinary(Z) == reader_.typed_data()->raw());
 
   ReadExceptionsTable(bytecode, has_exceptions_table);
 
@@ -312,7 +222,7 @@
   // Record the corresponding stores if field guards are enabled.
   if (has_nullable_fields) {
     ASSERT(function.IsGenerativeConstructor());
-    const intptr_t num_fields = helper_->ReadListLength();
+    const intptr_t num_fields = reader_.ReadListLength();
     if (I->use_field_guards()) {
       Field& field = Field::Handle(Z);
       for (intptr_t i = 0; i < num_fields; i++) {
@@ -333,7 +243,7 @@
     for (intptr_t i = 0; i < num_closures; i++) {
       closure ^= closures_->At(i);
 
-      const intptr_t flags = helper_->reader_.ReadUInt();
+      const intptr_t flags = reader_.ReadUInt();
       const bool has_exceptions_table =
           (flags & ClosureCode::kHasExceptionsTableFlag) != 0;
       const bool has_source_positions =
@@ -344,7 +254,7 @@
       // Read closure bytecode and attach to closure function.
       closure_bytecode = ReadBytecode(pool);
       closure.AttachBytecode(closure_bytecode);
-      ASSERT(bytecode.GetBinary(Z) == helper_->reader_.typed_data()->raw());
+      ASSERT(bytecode.GetBinary(Z) == reader_.typed_data()->raw());
 
       ReadExceptionsTable(closure_bytecode, has_exceptions_table);
 
@@ -368,7 +278,7 @@
   const int kHasTypeParamsFlag = 1 << 2;
   const int kHasSourcePositionsFlag = 1 << 3;
 
-  const intptr_t flags = helper_->reader_.ReadUInt();
+  const intptr_t flags = reader_.ReadUInt();
 
   Object& parent = Object::Handle(Z, ReadObject());
   if (!parent.IsFunction()) {
@@ -384,8 +294,8 @@
   TokenPosition position = TokenPosition::kNoSource;
   TokenPosition end_position = TokenPosition::kNoSource;
   if ((flags & kHasSourcePositionsFlag) != 0) {
-    position = helper_->ReadPosition();
-    end_position = helper_->ReadPosition();
+    position = reader_.ReadPosition();
+    end_position = reader_.ReadPosition();
   }
 
   const Function& closure = Function::Handle(
@@ -419,12 +329,11 @@
   }
 
   const intptr_t kImplicitClosureParam = 1;
-  const intptr_t num_params =
-      kImplicitClosureParam + helper_->reader_.ReadUInt();
+  const intptr_t num_params = kImplicitClosureParam + reader_.ReadUInt();
 
   intptr_t num_required_params = num_params;
   if (has_optional_positional_params || has_optional_named_params) {
-    num_required_params = kImplicitClosureParam + helper_->reader_.ReadUInt();
+    num_required_params = kImplicitClosureParam + reader_.ReadUInt();
   }
 
   func.set_num_fixed_parameters(num_required_params);
@@ -470,7 +379,7 @@
     const Function& parameterized_function) {
   ASSERT(parameterized_class.IsNull() != parameterized_function.IsNull());
 
-  const intptr_t num_type_params = helper_->reader_.ReadUInt();
+  const intptr_t num_type_params = reader_.ReadUInt();
   ASSERT(num_type_params > 0);
 
   // First setup the type parameters, so if any of the following code uses it
@@ -566,18 +475,18 @@
   const String* simpleInstanceOf = nullptr;
   const intptr_t obj_count = pool.Length();
   for (intptr_t i = 0; i < obj_count; ++i) {
-    const intptr_t tag = helper_->ReadTag();
+    const intptr_t tag = reader_.ReadTag();
     switch (tag) {
       case ConstantPoolTag::kInvalid:
         UNREACHABLE();
       case ConstantPoolTag::kICData: {
-        intptr_t flags = helper_->ReadByte();
+        intptr_t flags = reader_.ReadByte();
         InvocationKind kind =
             static_cast<InvocationKind>(flags & kInvocationKindMask);
         bool isDynamic = (flags & kFlagDynamic) != 0;
         name ^= ReadObject();
         ASSERT(name.IsSymbol());
-        intptr_t arg_desc_index = helper_->ReadUInt();
+        intptr_t arg_desc_index = reader_.ReadUInt();
         ASSERT(arg_desc_index < i);
         array ^= pool.ObjectAt(arg_desc_index);
         if (simpleInstanceOf == nullptr) {
@@ -607,7 +516,7 @@
         obj =
             ICData::New(function, name,
                         array,  // Arguments descriptor.
-                        H.thread()->compiler_state().GetNextDeoptId(),
+                        thread_->compiler_state().GetNextDeoptId(),
                         checked_argument_count, ICData::RebindRule::kInstance);
       } break;
       case ConstantPoolTag::kStaticField:
@@ -640,7 +549,7 @@
         ASSERT(obj.IsAbstractType());
         break;
       case ConstantPoolTag::kClosureFunction: {
-        intptr_t closure_index = helper_->ReadUInt();
+        intptr_t closure_index = reader_.ReadUInt();
         obj = closures_->At(closure_index);
         ASSERT(obj.IsFunction());
       } break;
@@ -705,8 +614,8 @@
   TIMELINE_DURATION(Thread::Current(), CompilerVerbose,
                     "BytecodeReaderHelper::ReadBytecode");
 #endif  // defined(SUPPORT_TIMELINE)
-  intptr_t size = helper_->ReadUInt();
-  intptr_t offset = helper_->reader_.offset();
+  intptr_t size = reader_.ReadUInt();
+  intptr_t offset = reader_.offset();
 
   static_assert(KernelBytecode::kMinSupportedBytecodeFormatVersion < 7,
                 "Cleanup support for old bytecode format versions");
@@ -715,8 +624,8 @@
     offset = Utils::RoundUp(offset, kAlignment);
   }
 
-  const uint8_t* data = helper_->reader_.BufferAt(offset);
-  helper_->reader_.set_offset(offset + size);
+  const uint8_t* data = reader_.BufferAt(offset);
+  reader_.set_offset(offset + size);
 
   // Create and return bytecode object.
   return Bytecode::New(reinterpret_cast<uword>(data), size, offset, pool);
@@ -730,7 +639,7 @@
 #endif
 
   const intptr_t try_block_count =
-      has_exceptions_table ? helper_->reader_.ReadListLength() : 0;
+      has_exceptions_table ? reader_.ReadListLength() : 0;
   if (try_block_count > 0) {
     const ObjectPool& pool = ObjectPool::Handle(Z, bytecode.object_pool());
     AbstractType& handler_type = AbstractType::Handle(Z);
@@ -746,28 +655,28 @@
     // Encoding of ExceptionsTable is described in
     // pkg/vm/lib/bytecode/exceptions.dart.
     for (intptr_t try_index = 0; try_index < try_block_count; try_index++) {
-      intptr_t outer_try_index_plus1 = helper_->reader_.ReadUInt();
+      intptr_t outer_try_index_plus1 = reader_.ReadUInt();
       intptr_t outer_try_index = outer_try_index_plus1 - 1;
       // PcDescriptors are expressed in terms of return addresses.
-      intptr_t start_pc = KernelBytecode::BytecodePcToOffset(
-          helper_->reader_.ReadUInt() << kPCShifter,
-          /* is_return_address = */ true);
-      intptr_t end_pc = KernelBytecode::BytecodePcToOffset(
-          helper_->reader_.ReadUInt() << kPCShifter,
-          /* is_return_address = */ true);
-      intptr_t handler_pc = KernelBytecode::BytecodePcToOffset(
-          helper_->reader_.ReadUInt() << kPCShifter,
-          /* is_return_address = */ false);
-      uint8_t flags = helper_->reader_.ReadByte();
+      intptr_t start_pc =
+          KernelBytecode::BytecodePcToOffset(reader_.ReadUInt() << kPCShifter,
+                                             /* is_return_address = */ true);
+      intptr_t end_pc =
+          KernelBytecode::BytecodePcToOffset(reader_.ReadUInt() << kPCShifter,
+                                             /* is_return_address = */ true);
+      intptr_t handler_pc =
+          KernelBytecode::BytecodePcToOffset(reader_.ReadUInt() << kPCShifter,
+                                             /* is_return_address = */ false);
+      uint8_t flags = reader_.ReadByte();
       const uint8_t kFlagNeedsStackTrace = 1 << 0;
       const uint8_t kFlagIsSynthetic = 1 << 1;
       const bool needs_stacktrace = (flags & kFlagNeedsStackTrace) != 0;
       const bool is_generated = (flags & kFlagIsSynthetic) != 0;
-      intptr_t type_count = helper_->reader_.ReadListLength();
+      intptr_t type_count = reader_.ReadListLength();
       ASSERT(type_count > 0);
       handler_types = Array::New(type_count, Heap::kOld);
       for (intptr_t i = 0; i < type_count; i++) {
-        intptr_t type_index = helper_->reader_.ReadUInt();
+        intptr_t type_index = reader_.ReadUInt();
         ASSERT(type_index < pool.Length());
         handler_type ^= pool.ObjectAt(type_index);
         handler_types.SetAt(i, handler_type);
@@ -802,7 +711,7 @@
     return;
   }
 
-  intptr_t offset = helper_->reader_.ReadUInt();
+  intptr_t offset = reader_.ReadUInt();
   bytecode.set_source_positions_binary_offset(
       bytecode_component_->GetSourcePositionsOffset() + offset);
 }
@@ -813,7 +722,7 @@
     return;
   }
 
-  intptr_t offset = helper_->reader_.ReadUInt();
+  intptr_t offset = reader_.ReadUInt();
   USE(offset);
 
 #if !defined(PRODUCT)
@@ -892,17 +801,16 @@
 RawArray* BytecodeReaderHelper::ReadBytecodeComponent(intptr_t md_offset) {
   ASSERT(Thread::Current()->IsMutatorThread());
 
-  AlternativeReadingScope alt(&helper_->reader_, &H.metadata_payloads(),
-                              md_offset);
+  AlternativeReadingScope alt(&reader_, md_offset);
 
-  const intptr_t start_offset = helper_->reader_.offset();
+  const intptr_t start_offset = reader_.offset();
 
-  intptr_t magic = helper_->reader_.ReadUInt32();
+  intptr_t magic = reader_.ReadUInt32();
   if (magic != KernelBytecode::kMagicValue) {
     FATAL1("Unexpected Dart bytecode magic %" Px, magic);
   }
 
-  const intptr_t version = helper_->reader_.ReadUInt32();
+  const intptr_t version = reader_.ReadUInt32();
   if ((version < KernelBytecode::kMinSupportedBytecodeFormatVersion) ||
       (version > KernelBytecode::kMaxSupportedBytecodeFormatVersion)) {
     FATAL3("Unsupported Dart bytecode format version %" Pd
@@ -914,55 +822,50 @@
   }
   BytecodeReader::UseBytecodeVersion(version);
 
-  helper_->reader_.ReadUInt32();  // Skip stringTable.numItems
-  const intptr_t string_table_offset =
-      start_offset + helper_->reader_.ReadUInt32();
+  reader_.ReadUInt32();  // Skip stringTable.numItems
+  const intptr_t string_table_offset = start_offset + reader_.ReadUInt32();
 
-  helper_->reader_.ReadUInt32();  // Skip objectTable.numItems
-  const intptr_t object_table_offset =
-      start_offset + helper_->reader_.ReadUInt32();
+  reader_.ReadUInt32();  // Skip objectTable.numItems
+  const intptr_t object_table_offset = start_offset + reader_.ReadUInt32();
 
-  helper_->reader_.ReadUInt32();  // Skip main.numItems
-  const intptr_t main_offset = start_offset + helper_->reader_.ReadUInt32();
+  reader_.ReadUInt32();  // Skip main.numItems
+  const intptr_t main_offset = start_offset + reader_.ReadUInt32();
 
-  helper_->reader_.ReadUInt32();  // Skip members.numItems
-  const intptr_t members_offset = start_offset + helper_->reader_.ReadUInt32();
+  reader_.ReadUInt32();  // Skip members.numItems
+  const intptr_t members_offset = start_offset + reader_.ReadUInt32();
 
-  helper_->reader_.ReadUInt32();  // Skip codes.numItems
-  const intptr_t codes_offset = start_offset + helper_->reader_.ReadUInt32();
+  reader_.ReadUInt32();  // Skip codes.numItems
+  const intptr_t codes_offset = start_offset + reader_.ReadUInt32();
 
-  helper_->reader_.ReadUInt32();  // Skip sourcePositions.numItems
-  const intptr_t sources_positions_offset =
-      start_offset + helper_->reader_.ReadUInt32();
+  reader_.ReadUInt32();  // Skip sourcePositions.numItems
+  const intptr_t sources_positions_offset = start_offset + reader_.ReadUInt32();
 
   intptr_t local_variables_offset = 0;
   static_assert(KernelBytecode::kMinSupportedBytecodeFormatVersion < 9,
                 "Cleanup condition");
   if (version >= 9) {
-    helper_->reader_.ReadUInt32();  // Skip localVariables.numItems
-    local_variables_offset = start_offset + helper_->reader_.ReadUInt32();
+    reader_.ReadUInt32();  // Skip localVariables.numItems
+    local_variables_offset = start_offset + reader_.ReadUInt32();
   }
 
-  helper_->reader_.ReadUInt32();  // Skip annotations.numItems
-  const intptr_t annotations_offset =
-      start_offset + helper_->reader_.ReadUInt32();
+  reader_.ReadUInt32();  // Skip annotations.numItems
+  const intptr_t annotations_offset = start_offset + reader_.ReadUInt32();
 
   // Read header of string table.
-  helper_->reader_.set_offset(string_table_offset);
-  const intptr_t num_one_byte_strings = helper_->reader_.ReadUInt32();
-  const intptr_t num_two_byte_strings = helper_->reader_.ReadUInt32();
+  reader_.set_offset(string_table_offset);
+  const intptr_t num_one_byte_strings = reader_.ReadUInt32();
+  const intptr_t num_two_byte_strings = reader_.ReadUInt32();
   const intptr_t strings_contents_offset =
-      helper_->reader_.offset() +
-      (num_one_byte_strings + num_two_byte_strings) * 4;
+      reader_.offset() + (num_one_byte_strings + num_two_byte_strings) * 4;
 
   // Read header of object table.
-  helper_->reader_.set_offset(object_table_offset);
-  const intptr_t num_objects = helper_->reader_.ReadUInt();
-  const intptr_t objects_size = helper_->reader_.ReadUInt();
+  reader_.set_offset(object_table_offset);
+  const intptr_t num_objects = reader_.ReadUInt();
+  const intptr_t objects_size = reader_.ReadUInt();
 
   // Skip over contents of objects.
-  const intptr_t objects_contents_offset = helper_->reader_.offset();
-  helper_->reader_.set_offset(objects_contents_offset + objects_size);
+  const intptr_t objects_contents_offset = reader_.offset();
+  reader_.set_offset(objects_contents_offset + objects_size);
 
   const Array& bytecode_component_array = Array::Handle(
       Z, BytecodeComponentData::New(
@@ -976,7 +879,7 @@
   // Read object offsets.
   Smi& offs = Smi::Handle(Z);
   for (intptr_t i = 0; i < num_objects; ++i) {
-    offs = Smi::New(helper_->reader_.ReadUInt());
+    offs = Smi::New(reader_.ReadUInt());
     bytecode_component.SetObject(i, offs);
   }
 
@@ -986,7 +889,7 @@
 }
 
 RawObject* BytecodeReaderHelper::ReadObject() {
-  uint32_t header = helper_->reader_.ReadUInt();
+  uint32_t header = reader_.ReadUInt();
   if ((header & kReferenceBit) != 0) {
     intptr_t index = header >> kIndexShift;
     if (index == 0) {
@@ -999,16 +902,14 @@
     // Object is not loaded yet.
     intptr_t offset = bytecode_component_->GetObjectsContentsOffset() +
                       Smi::Value(Smi::RawCast(obj));
-    AlternativeReadingScope alt(&helper_->reader_, &H.metadata_payloads(),
-                                offset);
-    header = helper_->reader_.ReadUInt();
+    AlternativeReadingScope alt(&reader_, offset);
+    header = reader_.ReadUInt();
 
     obj = ReadObjectContents(header);
     ASSERT(obj->IsHeapObject());
     {
-      Thread* thread = H.thread();
-      REUSABLE_OBJECT_HANDLESCOPE(thread);
-      Object& obj_handle = thread->ObjectHandle();
+      REUSABLE_OBJECT_HANDLESCOPE(thread_);
+      Object& obj_handle = thread_->ObjectHandle();
       obj_handle = obj;
       bytecode_component_->SetObject(index, obj_handle);
     }
@@ -1024,7 +925,7 @@
   pieces.Add(String::Handle(Z, cls.Name()));
   pieces.Add(Symbols::Dot());
   pieces.Add(name);
-  return Symbols::FromConcatAll(H.thread(), pieces);
+  return Symbols::FromConcatAll(thread_, pieces);
 }
 
 RawObject* BytecodeReaderHelper::ReadObjectContents(uint32_t header) {
@@ -1079,7 +980,7 @@
       break;
     case kLibrary: {
       const String& uri = String::Handle(Z, ReadString());
-      RawLibrary* library = Library::LookupLibrary(H.thread(), uri);
+      RawLibrary* library = Library::LookupLibrary(thread_, uri);
       if (library == Library::null()) {
         FATAL1("Unable to find library %s", uri.ToCString());
       }
@@ -1139,7 +1040,7 @@
     }
     case kClosure: {
       ReadObject();  // Skip enclosing member.
-      const intptr_t closure_index = helper_->reader_.ReadUInt();
+      const intptr_t closure_index = reader_.ReadUInt();
       return closures_->At(closure_index);
     }
     case kSimpleType: {
@@ -1156,7 +1057,7 @@
     }
     case kTypeParameter: {
       Object& parent = Object::Handle(Z, ReadObject());
-      const intptr_t index_in_parent = helper_->reader_.ReadUInt();
+      const intptr_t index_in_parent = reader_.ReadUInt();
       TypeArguments& type_parameters = TypeArguments::Handle(Z);
       if (parent.IsClass()) {
         type_parameters = Class::Cast(parent).type_parameters();
@@ -1230,13 +1131,13 @@
       return ReadConstObject(tag);
     }
     case kArgDesc: {
-      const intptr_t num_arguments = helper_->ReadUInt();
+      const intptr_t num_arguments = reader_.ReadUInt();
       const intptr_t num_type_args =
-          ((flags & kFlagHasTypeArgs) != 0) ? helper_->ReadUInt() : 0;
+          ((flags & kFlagHasTypeArgs) != 0) ? reader_.ReadUInt() : 0;
       if ((flags & kFlagHasNamedArgs) == 0) {
         return ArgumentsDescriptor::New(num_type_args, num_arguments);
       } else {
-        const intptr_t num_arg_names = helper_->ReadListLength();
+        const intptr_t num_arg_names = reader_.ReadListLength();
         const Array& array = Array::Handle(Z, Array::New(num_arg_names));
         String& name = String::Handle(Z);
         for (intptr_t i = 0; i < num_arg_names; ++i) {
@@ -1281,7 +1182,7 @@
             TypeArguments::Handle(Z, type.arguments());
         obj.SetTypeArguments(type_args);
       }
-      const intptr_t num_fields = helper_->ReadUInt();
+      const intptr_t num_fields = reader_.ReadUInt();
       Field& field = Field::Handle(Z);
       Object& value = Object::Handle(Z);
       for (intptr_t i = 0; i < num_fields; ++i) {
@@ -1292,7 +1193,7 @@
       return H.Canonicalize(obj);
     }
     case kInt: {
-      const int64_t value = helper_->reader_.ReadSLEB128AsInt64();
+      const int64_t value = reader_.ReadSLEB128AsInt64();
       if (Smi::IsValid(value)) {
         return Smi::New(static_cast<intptr_t>(value));
       }
@@ -1300,7 +1201,7 @@
       return H.Canonicalize(obj);
     }
     case kDouble: {
-      const int64_t bits = helper_->reader_.ReadSLEB128AsInt64();
+      const int64_t bits = reader_.ReadSLEB128AsInt64();
       double value = bit_cast<double, int64_t>(bits);
       const Double& obj = Double::Handle(Z, Double::New(value, Heap::kOld));
       return H.Canonicalize(obj);
@@ -1308,7 +1209,7 @@
     case kList: {
       const AbstractType& elem_type =
           AbstractType::CheckedHandle(Z, ReadObject());
-      const intptr_t length = helper_->ReadUInt();
+      const intptr_t length = reader_.ReadUInt();
       const Array& array = Array::Handle(Z, Array::New(length, elem_type));
       Object& value = Object::Handle(Z);
       for (intptr_t i = 0; i < length; ++i) {
@@ -1328,7 +1229,7 @@
       return H.Canonicalize(Instance::Cast(obj));
     }
     case kBool: {
-      bool is_true = helper_->ReadByte() != 0;
+      bool is_true = reader_.ReadByte() != 0;
       return is_true ? Bool::True().raw() : Bool::False().raw();
     }
     case kSymbol: {
@@ -1368,21 +1269,21 @@
   const int kHeaderFields = 2;
   const int kUInt32Size = 4;
 
-  uint32_t ref = helper_->reader_.ReadUInt();
+  uint32_t ref = reader_.ReadUInt();
   const bool isOneByteString = (ref & kFlagTwoByteString) == 0;
   intptr_t index = ref >> 1;
 
   if (!isOneByteString) {
-    const uint32_t num_one_byte_strings = helper_->reader_.ReadUInt32At(
-        bytecode_component_->GetStringsHeaderOffset());
+    const uint32_t num_one_byte_strings =
+        reader_.ReadUInt32At(bytecode_component_->GetStringsHeaderOffset());
     index += num_one_byte_strings;
   }
 
-  AlternativeReadingScope alt(&helper_->reader_, &H.metadata_payloads(),
+  AlternativeReadingScope alt(&reader_,
                               bytecode_component_->GetStringsHeaderOffset() +
                                   (kHeaderFields + index - 1) * kUInt32Size);
-  intptr_t start_offs = helper_->ReadUInt32();
-  intptr_t end_offs = helper_->ReadUInt32();
+  intptr_t start_offs = reader_.ReadUInt32();
+  intptr_t end_offs = reader_.ReadUInt32();
   if (index == 0) {
     // For the 0-th string we read a header field instead of end offset of
     // the previous string.
@@ -1392,14 +1293,14 @@
   // Bytecode strings reside in ExternalTypedData which is not movable by GC,
   // so it is OK to take a direct pointer to string characters even if
   // symbol allocation triggers GC.
-  const uint8_t* data = helper_->reader_.BufferAt(
+  const uint8_t* data = reader_.BufferAt(
       bytecode_component_->GetStringsContentsOffset() + start_offs);
 
   if (is_canonical) {
     if (isOneByteString) {
-      return Symbols::FromLatin1(H.thread(), data, end_offs - start_offs);
+      return Symbols::FromLatin1(thread_, data, end_offs - start_offs);
     } else {
-      return Symbols::FromUTF16(H.thread(),
+      return Symbols::FromUTF16(thread_,
                                 reinterpret_cast<const uint16_t*>(data),
                                 (end_offs - start_offs) >> 1);
     }
@@ -1415,7 +1316,7 @@
 
 RawTypeArguments* BytecodeReaderHelper::ReadTypeArguments(
     const Class& instantiator) {
-  const intptr_t length = helper_->reader_.ReadUInt();
+  const intptr_t length = reader_.ReadUInt();
   TypeArguments& type_arguments =
       TypeArguments::ZoneHandle(Z, TypeArguments::New(length));
   AbstractType& type = AbstractType::Handle(Z);
@@ -1451,10 +1352,9 @@
 
   const intptr_t offset =
       bytecode_component_->GetMembersOffset() + members_offset;
-  AlternativeReadingScope alt_md(&helper_->reader_, &H.metadata_payloads(),
-                                 offset);
+  AlternativeReadingScope alt_md(&reader_, offset);
 
-  const intptr_t num_functions = helper_->reader_.ReadUInt();
+  const intptr_t num_functions = reader_.ReadUInt();
   functions_ = &Array::Handle(Z, Array::New(num_functions, Heap::kOld));
   function_index_ = 0;
 
@@ -1482,7 +1382,7 @@
   const int kHasPragmaFlag = 1 << 11;
   const int kHasCustomScriptFlag = 1 << 12;
 
-  const int num_fields = helper_->ReadListLength();
+  const int num_fields = reader_.ReadListLength();
   if ((num_fields == 0) && !cls.is_enum_class()) {
     return;
   }
@@ -1496,7 +1396,7 @@
   Function& function = Function::Handle(Z);
 
   for (intptr_t i = 0; i < num_fields; ++i) {
-    intptr_t flags = helper_->reader_.ReadUInt();
+    intptr_t flags = reader_.ReadUInt();
 
     const bool is_static = (flags & kIsStaticFlag) != 0;
     const bool is_final = (flags & kIsFinalFlag) != 0;
@@ -1517,8 +1417,8 @@
     TokenPosition position = TokenPosition::kNoSource;
     TokenPosition end_position = TokenPosition::kNoSource;
     if ((flags & kHasSourcePositionsFlag) != 0) {
-      position = helper_->ReadPosition();
-      end_position = helper_->ReadPosition();
+      position = reader_.ReadPosition();
+      end_position = reader_.ReadPosition();
     }
 
     field = Field::New(name, is_static, is_final, is_const,
@@ -1552,7 +1452,7 @@
     }
 
     if (has_initializer && is_static) {
-      const intptr_t code_offset = helper_->reader_.ReadUInt();
+      const intptr_t code_offset = reader_.ReadUInt();
       field.set_bytecode_offset(code_offset +
                                 bytecode_component_->GetCodesOffset());
       field.SetStaticValue(Object::sentinel(), true);
@@ -1600,8 +1500,8 @@
     }
 
     if ((flags & kHasAnnotationsFlag) != 0) {
-      intptr_t annotations_offset = helper_->reader_.ReadUInt() +
-                                    bytecode_component_->GetAnnotationsOffset();
+      intptr_t annotations_offset =
+          reader_.ReadUInt() + bytecode_component_->GetAnnotationsOffset();
       ASSERT(annotations_offset > 0);
 
       if (FLAG_enable_mirrors || has_pragma) {
@@ -1611,9 +1511,8 @@
         if (has_pragma) {
           // TODO(alexmarkov): read annotations right away using
           //  annotations_offset.
-          Thread* thread = H.thread();
-          NoOOBMessageScope no_msg_scope(thread);
-          NoReloadScope no_reload_scope(thread->isolate(), thread);
+          NoOOBMessageScope no_msg_scope(thread_);
+          NoReloadScope no_reload_scope(thread_->isolate(), thread_);
           library.GetMetadata(field);
         }
       }
@@ -1689,7 +1588,7 @@
   const int kHasPragmaFlag = 1 << 21;
   const int kHasCustomScriptFlag = 1 << 22;
 
-  const intptr_t num_functions = helper_->ReadListLength();
+  const intptr_t num_functions = reader_.ReadListLength();
   ASSERT(function_index_ + num_functions == functions_->Length());
 
   if (function_index_ + num_functions == 0) {
@@ -1704,7 +1603,7 @@
   AbstractType& type = AbstractType::Handle(Z);
 
   for (intptr_t i = 0; i < num_functions; ++i) {
-    intptr_t flags = helper_->reader_.ReadUInt();
+    intptr_t flags = reader_.ReadUInt();
 
     const bool is_static = (flags & kIsStaticFlag) != 0;
     const bool is_factory = (flags & kIsFactoryFlag) != 0;
@@ -1723,8 +1622,8 @@
     TokenPosition position = TokenPosition::kNoSource;
     TokenPosition end_position = TokenPosition::kNoSource;
     if ((flags & kHasSourcePositionsFlag) != 0) {
-      position = helper_->ReadPosition();
-      end_position = helper_->ReadPosition();
+      position = reader_.ReadPosition();
+      end_position = reader_.ReadPosition();
     }
 
     RawFunction::Kind kind = RawFunction::kRegularFunction;
@@ -1774,13 +1673,12 @@
     }
 
     const intptr_t num_implicit_params = (!is_static || is_factory) ? 1 : 0;
-    const intptr_t num_params =
-        num_implicit_params + helper_->reader_.ReadUInt();
+    const intptr_t num_params = num_implicit_params + reader_.ReadUInt();
 
     intptr_t num_required_params = num_params;
     if ((flags & (kHasOptionalPositionalParamsFlag |
                   kHasOptionalNamedParamsFlag)) != 0) {
-      num_required_params = num_implicit_params + helper_->reader_.ReadUInt();
+      num_required_params = num_implicit_params + reader_.ReadUInt();
     }
 
     function.set_num_fixed_parameters(num_required_params);
@@ -1822,15 +1720,14 @@
     }
 
     if ((flags & kIsAbstractFlag) == 0) {
-      const intptr_t code_offset = helper_->reader_.ReadUInt();
+      const intptr_t code_offset = reader_.ReadUInt();
       function.set_bytecode_offset(code_offset +
                                    bytecode_component_->GetCodesOffset());
     }
 
     if ((flags & kHasAnnotationsFlag) != 0) {
       const intptr_t annotations_offset =
-          helper_->reader_.ReadUInt() +
-          bytecode_component_->GetAnnotationsOffset();
+          reader_.ReadUInt() + bytecode_component_->GetAnnotationsOffset();
       ASSERT(annotations_offset > 0);
 
       if (FLAG_enable_mirrors || has_pragma) {
@@ -1885,17 +1782,16 @@
   ASSERT(is_covariant->length() == num_params);
   ASSERT(is_generic_covariant_impl->length() == num_params);
 
-  AlternativeReadingScope alt(&helper_->reader_, &H.metadata_payloads(),
-                              function.bytecode_offset());
+  AlternativeReadingScope alt(&reader_, function.bytecode_offset());
 
-  const intptr_t code_flags = helper_->reader_.ReadUInt();
+  const intptr_t code_flags = reader_.ReadUInt();
   if ((code_flags & Code::kHasParameterFlagsFlag) != 0) {
-    const intptr_t num_explicit_params = helper_->reader_.ReadUInt();
+    const intptr_t num_explicit_params = reader_.ReadUInt();
     ASSERT(num_params ==
            function.NumImplicitParameters() + num_explicit_params);
 
     for (intptr_t i = function.NumImplicitParameters(); i < num_params; ++i) {
-      const intptr_t flags = helper_->reader_.ReadUInt();
+      const intptr_t flags = reader_.ReadUInt();
 
       if ((flags & Parameter::kIsCovariantFlag) != 0) {
         is_covariant->Add(i);
@@ -1980,10 +1876,9 @@
   const auto& target_bytecode = Bytecode::Handle(Z, target.bytecode());
   const auto& obj_pool = ObjectPool::Handle(Z, target_bytecode.object_pool());
 
-  AlternativeReadingScope alt(&helper_->reader_, &H.metadata_payloads(),
-                              target.bytecode_offset());
+  AlternativeReadingScope alt(&reader_, target.bytecode_offset());
 
-  const intptr_t flags = helper_->reader_.ReadUInt();
+  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;
@@ -1991,10 +1886,10 @@
       (flags & Code::kHasDefaultFunctionTypeArgsFlag) != 0;
 
   if (has_parameters_flags) {
-    const intptr_t num_params = helper_->reader_.ReadUInt();
+    const intptr_t num_params = reader_.ReadUInt();
     const intptr_t num_implicit_params = function.NumImplicitParameters();
     for (intptr_t i = 0; i < num_params; ++i) {
-      const intptr_t flags = helper_->reader_.ReadUInt();
+      const intptr_t flags = reader_.ReadUInt();
 
       bool is_covariant = (flags & Parameter::kIsCovariantFlag) != 0;
       bool is_generic_covariant_impl =
@@ -2019,7 +1914,7 @@
   }
 
   if (has_forwarding_stub_target) {
-    const intptr_t cp_index = helper_->reader_.ReadUInt();
+    const intptr_t cp_index = reader_.ReadUInt();
     const auto& forwarding_stub_target =
         Function::CheckedZoneHandle(Z, obj_pool.ObjectAt(cp_index));
     parsed_function->MarkForwardingStub(&forwarding_stub_target);
@@ -2027,7 +1922,7 @@
 
   if (has_default_function_type_args) {
     ASSERT(function.IsGeneric());
-    const intptr_t cp_index = helper_->reader_.ReadUInt();
+    const intptr_t cp_index = reader_.ReadUInt();
     const auto& type_args =
         TypeArguments::CheckedHandle(Z, obj_pool.ObjectAt(cp_index));
     parsed_function->SetDefaultFunctionTypeArguments(type_args);
@@ -2200,40 +2095,92 @@
 
   VMTagScope tagScope(thread, VMTag::kLoadBytecodeTagId);
 
+#if defined(SUPPORT_TIMELINE)
+  TimelineDurationScope tds(Thread::Current(), Timeline::GetCompilerStream(),
+                            "BytecodeReader::ReadFunctionBytecode");
+  // This increases bytecode reading time by ~7%, so only keep it around for
+  // debugging.
+#if defined(DEBUG)
+  tds.SetNumArguments(1);
+  tds.CopyArgument(0, "Function", function.ToQualifiedCString());
+#endif  // defined(DEBUG)
+#endif  // !defined(SUPPORT_TIMELINE)
+
   LongJumpScope jump;
   if (setjmp(*jump.Set()) == 0) {
     StackZone stack_zone(thread);
     Zone* const zone = stack_zone.GetZone();
     HANDLESCOPE(thread);
-    CompilerState compiler_state(thread);
 
-    const Script& script = Script::Handle(zone, function.script());
-    TranslationHelper translation_helper(thread);
-    translation_helper.InitFromScript(script);
+    auto& bytecode = Bytecode::Handle(zone);
 
-    KernelReaderHelper reader_helper(
-        zone, &translation_helper, script,
-        ExternalTypedData::Handle(zone, function.KernelData()),
-        function.KernelDataProgramOffset());
-    ActiveClass active_class;
+    switch (function.kind()) {
+      case RawFunction::kImplicitGetter:
+        bytecode = Object::implicit_getter_bytecode().raw();
+        break;
+      case RawFunction::kImplicitSetter:
+        bytecode = Object::implicit_setter_bytecode().raw();
+        break;
+      case RawFunction::kImplicitStaticGetter:
+        if (!IsStaticFieldGetterGeneratedAsInitializer(function, zone)) {
+          bytecode = Object::implicit_static_getter_bytecode().raw();
+        }
+        break;
+      case RawFunction::kMethodExtractor:
+        bytecode = Object::method_extractor_bytecode().raw();
+        break;
+      case RawFunction::kInvokeFieldDispatcher:
+        if (Class::Handle(function.Owner()).id() == kClosureCid) {
+          bytecode = Object::invoke_closure_bytecode().raw();
+        } else {
+          bytecode = Object::invoke_field_bytecode().raw();
+        }
+        break;
+      case RawFunction::kNoSuchMethodDispatcher:
+        bytecode = Object::nsm_dispatcher_bytecode().raw();
+        break;
+      default:
+        break;
+    }
 
-    BytecodeMetadataHelper bytecode_metadata_helper(&reader_helper,
-                                                    &active_class);
+    if (!bytecode.IsNull()) {
+      function.AttachBytecode(bytecode);
+    } else if (function.is_declared_in_bytecode()) {
+      const intptr_t code_offset = function.bytecode_offset();
+      if (code_offset != 0) {
+        CompilerState compiler_state(thread);
 
-    // Setup a [ActiveClassScope] and a [ActiveMemberScope] which will be used
-    // e.g. for type translation.
-    const Class& klass = Class::Handle(zone, function.Owner());
-    Function& outermost_function =
-        Function::Handle(zone, function.GetOutermostFunction());
+        const Script& script = Script::Handle(zone, function.script());
+        TranslationHelper translation_helper(thread);
+        translation_helper.InitFromScript(script);
 
-    ActiveClassScope active_class_scope(&active_class, &klass);
-    ActiveMemberScope active_member(&active_class, &outermost_function);
-    ActiveTypeParametersScope active_type_params(&active_class, function, zone);
+        ActiveClass active_class;
 
-    bytecode_metadata_helper.ReadMetadata(function);
+        // Setup a [ActiveClassScope] and a [ActiveMemberScope] which will be
+        // used e.g. for type translation.
+        const Class& klass = Class::Handle(zone, function.Owner());
+        Function& outermost_function =
+            Function::Handle(zone, function.GetOutermostFunction());
+
+        ActiveClassScope active_class_scope(&active_class, &klass);
+        ActiveMemberScope active_member(&active_class, &outermost_function);
+        ActiveTypeParametersScope active_type_params(&active_class, function,
+                                                     zone);
+
+        BytecodeComponentData bytecode_component(
+            Array::Handle(zone, translation_helper.GetBytecodeComponent()));
+        ASSERT(!bytecode_component.IsNull());
+        BytecodeReaderHelper bytecode_reader(&translation_helper, &active_class,
+                                             &bytecode_component);
+
+        bytecode_reader.ReadCode(function, code_offset);
+      }
+    }
 
 #if !defined(PRODUCT)
-    thread->isolate()->debugger()->NotifyBytecodeLoaded(function);
+    if (function.HasBytecode()) {
+      thread->isolate()->debugger()->NotifyBytecodeLoaded(function);
+    }
 #endif
 
     return Error::null();
@@ -2253,17 +2200,18 @@
   TranslationHelper translation_helper(thread);
   translation_helper.InitFromScript(script);
 
-  KernelReaderHelper reader_helper(
-      zone, &translation_helper, script,
-      ExternalTypedData::Handle(zone, annotation_field.KernelData()),
-      annotation_field.KernelDataProgramOffset());
   ActiveClass active_class;
 
-  BytecodeMetadataHelper bytecode_metadata_helper(&reader_helper,
-                                                  &active_class);
+  BytecodeComponentData bytecode_component(
+      Array::Handle(zone, translation_helper.GetBytecodeComponent()));
+  ASSERT(!bytecode_component.IsNull());
+  BytecodeReaderHelper bytecode_reader(&translation_helper, &active_class,
+                                       &bytecode_component);
 
-  return bytecode_metadata_helper.ReadAnnotation(
-      annotation_field.bytecode_offset());
+  AlternativeReadingScope alt(&bytecode_reader.reader(),
+                              annotation_field.bytecode_offset());
+
+  return bytecode_reader.ReadObject();
 }
 
 #if !defined(PRODUCT)
diff --git a/runtime/vm/compiler/frontend/bytecode_reader.h b/runtime/vm/compiler/frontend/bytecode_reader.h
index 9353029..753bff9 100644
--- a/runtime/vm/compiler/frontend/bytecode_reader.h
+++ b/runtime/vm/compiler/frontend/bytecode_reader.h
@@ -24,10 +24,6 @@
   explicit BytecodeMetadataHelper(KernelReaderHelper* helper,
                                   ActiveClass* active_class);
 
-  bool HasBytecode(intptr_t node_offset);
-
-  void ReadMetadata(const Function& function);
-
   void ParseBytecodeFunction(ParsedFunction* parsed_function);
   void ParseBytecodeImplicitClosureFunction(ParsedFunction* parsed_function);
 
@@ -36,9 +32,6 @@
   // Returns true if class members are loaded.
   bool ReadMembers(intptr_t node_offset, const Class& cls, bool discard_fields);
 
-  // Read annotation at given offset.
-  RawObject* ReadAnnotation(intptr_t annotation_offset);
-
   RawLibrary* GetMainLibrary();
 
   RawArray* GetBytecodeComponent();
@@ -53,10 +46,12 @@
 // Helper class for reading bytecode.
 class BytecodeReaderHelper : public ValueObject {
  public:
-  explicit BytecodeReaderHelper(KernelReaderHelper* helper,
+  explicit BytecodeReaderHelper(TranslationHelper* translation_helper,
                                 ActiveClass* active_class,
                                 BytecodeComponentData* bytecode_component);
 
+  Reader& reader() { return reader_; }
+
   void ReadCode(const Function& function, intptr_t code_offset);
 
   void ReadMembers(const Class& cls,
@@ -196,9 +191,10 @@
                               const Function& function,
                               const Function& target);
 
-  KernelReaderHelper* const helper_;
+  Reader reader_;
   TranslationHelper& translation_helper_;
   ActiveClass* const active_class_;
+  Thread* const thread_;
   Zone* const zone_;
   BytecodeComponentData* const bytecode_component_;
   Array* closures_ = nullptr;
diff --git a/runtime/vm/kernel.cc b/runtime/vm/kernel.cc
index 703a495..4f54e5d 100644
--- a/runtime/vm/kernel.cc
+++ b/runtime/vm/kernel.cc
@@ -672,19 +672,19 @@
   TranslationHelper translation_helper(thread);
   translation_helper.InitFromScript(script);
 
-  KernelReaderHelper reader_helper(
-      zone, &translation_helper, script,
-      ExternalTypedData::Handle(zone, function.KernelData()),
-      function.KernelDataProgramOffset());
-
   if (function.is_declared_in_bytecode()) {
-    BytecodeReaderHelper bytecode_reader_helper(&reader_helper, nullptr,
+    BytecodeReaderHelper bytecode_reader_helper(&translation_helper, nullptr,
                                                 nullptr);
     bytecode_reader_helper.ReadParameterCovariance(function, is_covariant,
                                                    is_generic_covariant_impl);
     return;
   }
 
+  KernelReaderHelper reader_helper(
+      zone, &translation_helper, script,
+      ExternalTypedData::Handle(zone, function.KernelData()),
+      function.KernelDataProgramOffset());
+
   reader_helper.SetOffset(function.kernel_offset());
   reader_helper.ReadUntilFunctionNode();
 
diff --git a/runtime/vm/kernel_loader.cc b/runtime/vm/kernel_loader.cc
index c7e57fce..b5001d1 100644
--- a/runtime/vm/kernel_loader.cc
+++ b/runtime/vm/kernel_loader.cc
@@ -965,13 +965,6 @@
       return;
     }
   }
-  if (FLAG_enable_interpreter || FLAG_use_bytecode_compiler) {
-    if (bytecode_metadata_helper_.HasBytecode(field.kernel_offset() +
-                                              library_kernel_offset_)) {
-      field.set_has_initializer(true);
-      return;
-    }
-  }
   field.set_has_initializer(false);
 }
 
@@ -2072,12 +2065,6 @@
   if (field_helper->IsStatic()) {
     bool has_initializer = (tag == kSomething);
 
-    if (FLAG_enable_interpreter || FLAG_use_bytecode_compiler) {
-      has_initializer = has_initializer ||
-                        bytecode_metadata_helper_.HasBytecode(
-                            field.kernel_offset() + library_kernel_offset_);
-    }
-
     if (!has_initializer) {
       // Static fields without an initializer are implicitly initialized to
       // null. We do not need a getter.