[vm] Refactoring: move out classes independent of StreamingFlowGraphBuilder

This change continues refactoring to split kernel_binary_flowgraph and
kernel_to_il and move out parts which have no dependencies on flow graph
construction.

Bytecode reading is moved to a separate file bytecode_reader{.h, .cc}.

Metadata helpers, TypeTranslator, ActiveClass and other Active* are moved
to kernel_translation_helper.

Removed dependency of ICData tags on IL Instruction tags, so ICData objects
can be created by bytecode reader without depending on IL.

Unused AlternativeScriptScope is removed.

Change-Id: Ic9f98af82697b48013fb89802076b56833acf55d
Reviewed-on: https://dart-review.googlesource.com/63262
Reviewed-by: Vyacheslav Egorov <vegorov@google.com>
Reviewed-by: RĂ©gis Crelier <regis@google.com>
Commit-Queue: Alexander Markov <alexmarkov@google.com>
diff --git a/runtime/vm/clustered_snapshot.cc b/runtime/vm/clustered_snapshot.cc
index de660dd..c688a31 100644
--- a/runtime/vm/clustered_snapshot.cc
+++ b/runtime/vm/clustered_snapshot.cc
@@ -2444,7 +2444,7 @@
       }
       s->Write<uint32_t>(ic->ptr()->state_bits_);
 #if defined(TAG_IC_DATA)
-      s->Write<int32_t>(ic->ptr()->tag_);
+      s->Write<int32_t>(static_cast<int32_t>(ic->ptr()->tag_));
 #endif
     }
   }
@@ -2489,7 +2489,7 @@
       NOT_IN_PRECOMPILED(ic->ptr()->deopt_id_ = d->Read<int32_t>());
       ic->ptr()->state_bits_ = d->Read<int32_t>();
 #if defined(TAG_IC_DATA)
-      ic->ptr()->tag_ = d->Read<int32_t>();
+      ic->ptr()->tag_ = static_cast<ICData::Tag>(d->Read<int32_t>());
 #endif
     }
   }
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler.cc b/runtime/vm/compiler/backend/flow_graph_compiler.cc
index 5b941df..d180a24 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler.cc
@@ -1649,7 +1649,7 @@
                           arguments_descriptor, deopt_id, num_args_tested,
                           ICData::kInstance));
 #if defined(TAG_IC_DATA)
-  ic_data.set_tag(Instruction::kInstanceCall);
+  ic_data.set_tag(ICData::Tag::kInstanceCall);
 #endif
   if (deopt_id_to_ic_data_ != NULL) {
     (*deopt_id_to_ic_data_)[deopt_id] = &ic_data;
@@ -1683,7 +1683,7 @@
                   deopt_id, num_args_tested, rebind_rule));
   ic_data.AddTarget(target);
 #if defined(TAG_IC_DATA)
-  ic_data.set_tag(Instruction::kStaticCall);
+  ic_data.set_tag(ICData::Tag::kStaticCall);
 #endif
   if (deopt_id_to_ic_data_ != NULL) {
     (*deopt_id_to_ic_data_)[deopt_id] = &ic_data;
diff --git a/runtime/vm/compiler/backend/il.cc b/runtime/vm/compiler/backend/il.cc
index b1ed153..0dd7ed5 100644
--- a/runtime/vm/compiler/backend/il.cc
+++ b/runtime/vm/compiler/backend/il.cc
@@ -320,9 +320,20 @@
     const ICData* result = ic_data_array[deopt_id_];
 #if defined(TAG_IC_DATA)
     if (result != NULL) {
-      if (result->tag() == -1) {
-        result->set_tag(tag());
-      } else if (result->tag() != tag()) {
+      ICData::Tag ic_data_tag = ICData::Tag::kUnknown;
+      switch (tag()) {
+        case kInstanceCall:
+          ic_data_tag = ICData::Tag::kInstanceCall;
+          break;
+        case kStaticCall:
+          ic_data_tag = ICData::Tag::kStaticCall;
+          break;
+        default:
+          UNREACHABLE();
+      }
+      if (result->tag() == ICData::Tag::kUnknown) {
+        result->set_tag(ic_data_tag);
+      } else if (result->tag() != ic_data_tag) {
         FATAL("ICData tag mismatch");
       }
     }
diff --git a/runtime/vm/compiler/compiler_sources.gni b/runtime/vm/compiler/compiler_sources.gni
index 09118db..5f6b3f9 100644
--- a/runtime/vm/compiler/compiler_sources.gni
+++ b/runtime/vm/compiler/compiler_sources.gni
@@ -75,6 +75,8 @@
   "cha.h",
   "compiler_pass.cc",
   "compiler_pass.h",
+  "frontend/bytecode_reader.cc",
+  "frontend/bytecode_reader.h",
   "frontend/flow_graph_builder.cc",
   "frontend/flow_graph_builder.h",
   "frontend/kernel_binary_flowgraph.cc",
diff --git a/runtime/vm/compiler/frontend/bytecode_reader.cc b/runtime/vm/compiler/frontend/bytecode_reader.cc
new file mode 100644
index 0000000..b3ed8a3
--- /dev/null
+++ b/runtime/vm/compiler/frontend/bytecode_reader.cc
@@ -0,0 +1,612 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#include "vm/compiler/frontend/bytecode_reader.h"
+
+#include "vm/bootstrap.h"
+#include "vm/code_descriptors.h"
+#include "vm/compiler/assembler/disassembler_kbc.h"
+#include "vm/dart_entry.h"
+
+#if !defined(DART_PRECOMPILED_RUNTIME)
+#if defined(DART_USE_INTERPRETER)
+
+#define Z (zone_)
+#define H (translation_helper_)
+#define T (type_translator_)
+#define I Isolate::Current()
+
+namespace dart {
+
+DEFINE_FLAG(bool, dump_kernel_bytecode, false, "Dump kernel bytecode");
+
+namespace kernel {
+
+BytecodeMetadataHelper::BytecodeMetadataHelper(KernelReaderHelper* helper,
+                                               TypeTranslator* type_translator,
+                                               ActiveClass* active_class)
+    : MetadataHelper(helper, tag(), /* precompiler_only = */ false),
+      type_translator_(*type_translator),
+      active_class_(active_class) {}
+
+void BytecodeMetadataHelper::ReadMetadata(const Function& function) {
+  const intptr_t node_offset = function.kernel_offset();
+  const intptr_t md_offset = GetNextMetadataPayloadOffset(node_offset);
+  if (md_offset < 0) {
+    return;
+  }
+
+  AlternativeReadingScope alt(&helper_->reader_, &H.metadata_payloads(),
+                              md_offset);
+
+  // Create object pool and read pool entries.
+  const intptr_t obj_count = helper_->reader_.ReadListLength();
+  const ObjectPool& pool =
+      ObjectPool::Handle(helper_->zone_, ObjectPool::New(obj_count));
+  ReadPoolEntries(function, function, pool, 0);
+
+  // Read bytecode and attach to function.
+  const Code& bytecode = Code::Handle(helper_->zone_, ReadBytecode(pool));
+  function.AttachBytecode(bytecode);
+
+  // Read exceptions table.
+  ReadExceptionsTable(bytecode);
+
+  if (FLAG_dump_kernel_bytecode) {
+    KernelBytecodeDisassembler::Disassemble(function);
+  }
+
+  // Read closures.
+  Function& closure = Function::Handle(helper_->zone_);
+  Code& closure_bytecode = Code::Handle(helper_->zone_);
+  intptr_t num_closures = helper_->ReadListLength();
+  for (intptr_t i = 0; i < num_closures; i++) {
+    intptr_t closure_index = helper_->ReadUInt();
+    ASSERT(closure_index < obj_count);
+    closure ^= pool.ObjectAt(closure_index);
+
+    // Read closure bytecode and attach to closure function.
+    closure_bytecode = ReadBytecode(pool);
+    closure.AttachBytecode(closure_bytecode);
+
+    // Read closure exceptions table.
+    ReadExceptionsTable(closure_bytecode);
+
+    if (FLAG_dump_kernel_bytecode) {
+      KernelBytecodeDisassembler::Disassemble(closure);
+    }
+  }
+}
+
+intptr_t BytecodeMetadataHelper::ReadPoolEntries(const Function& function,
+                                                 const Function& inner_function,
+                                                 const ObjectPool& pool,
+                                                 intptr_t from_index) {
+  // These enums and the code below reading the constant pool from kernel must
+  // be kept in sync with pkg/vm/lib/bytecode/constant_pool.dart.
+  enum ConstantPoolTag {
+    kInvalid,
+    kNull,
+    kString,
+    kInt,
+    kDouble,
+    kBool,
+    kArgDesc,
+    kICData,
+    kStaticICData,
+    kField,
+    kFieldOffset,
+    kClass,
+    kTypeArgumentsFieldOffset,
+    kTearOff,
+    kType,
+    kTypeArguments,
+    kList,
+    kInstance,
+    kSymbol,
+    kTypeArgumentsForInstanceAllocation,
+    kContextOffset,
+    kClosureFunction,
+    kEndClosureFunctionScope,
+    kNativeEntry,
+    kSubtypeTestCache,
+  };
+
+  enum InvocationKind {
+    method,  // x.foo(...) or foo(...)
+    getter,  // x.foo
+    setter   // x.foo = ...
+  };
+
+  Object& obj = Object::Handle(helper_->zone_);
+  Object& elem = Object::Handle(helper_->zone_);
+  Array& array = Array::Handle(helper_->zone_);
+  Field& field = Field::Handle(helper_->zone_);
+  Class& cls = Class::Handle(helper_->zone_);
+  String& name = String::Handle(helper_->zone_);
+  TypeArguments& type_args = TypeArguments::Handle(helper_->zone_);
+  const intptr_t obj_count = pool.Length();
+  for (intptr_t i = from_index; i < obj_count; ++i) {
+    const intptr_t tag = helper_->ReadTag();
+    switch (tag) {
+      case ConstantPoolTag::kInvalid:
+        UNREACHABLE();
+      case ConstantPoolTag::kNull:
+        obj = Object::null();
+        break;
+      case ConstantPoolTag::kString:
+        obj = H.DartString(helper_->ReadStringReference()).raw();
+        ASSERT(obj.IsString());
+        obj = H.Canonicalize(String::Cast(obj));
+        break;
+      case ConstantPoolTag::kInt: {
+        uint32_t low_bits = helper_->ReadUInt32();
+        int64_t value = helper_->ReadUInt32();
+        value = (value << 32) | low_bits;
+        obj = Integer::New(value);
+      } break;
+      case ConstantPoolTag::kDouble: {
+        uint32_t low_bits = helper_->ReadUInt32();
+        uint64_t bits = helper_->ReadUInt32();
+        bits = (bits << 32) | low_bits;
+        double value = bit_cast<double, uint64_t>(bits);
+        obj = Double::New(value);
+      } break;
+      case ConstantPoolTag::kBool:
+        if (helper_->ReadUInt() == 1) {
+          obj = Bool::True().raw();
+        } else {
+          obj = Bool::False().raw();
+        }
+        break;
+      case ConstantPoolTag::kArgDesc: {
+        intptr_t num_arguments = helper_->ReadUInt();
+        intptr_t num_type_args = helper_->ReadUInt();
+        intptr_t num_arg_names = helper_->ReadListLength();
+        if (num_arg_names == 0) {
+          obj = ArgumentsDescriptor::New(num_type_args, num_arguments);
+        } else {
+          array = Array::New(num_arg_names);
+          for (intptr_t j = 0; j < num_arg_names; j++) {
+            array.SetAt(j, H.DartSymbolPlain(helper_->ReadStringReference()));
+          }
+          obj = ArgumentsDescriptor::New(num_type_args, num_arguments, array);
+        }
+      } break;
+      case ConstantPoolTag::kICData: {
+        InvocationKind kind = static_cast<InvocationKind>(helper_->ReadByte());
+        if (kind == InvocationKind::getter) {
+          name = helper_->ReadNameAsGetterName().raw();
+        } else if (kind == InvocationKind::setter) {
+          name = helper_->ReadNameAsSetterName().raw();
+        } else {
+          ASSERT(kind == InvocationKind::method);
+          name = helper_->ReadNameAsMethodName().raw();
+        }
+        intptr_t arg_desc_index = helper_->ReadUInt();
+        ASSERT(arg_desc_index < i);
+        array ^= pool.ObjectAt(arg_desc_index);
+        // TODO(regis): Should num_args_tested be explicitly provided?
+        obj = ICData::New(function, name,
+                          array,  // Arguments descriptor.
+                          Thread::kNoDeoptId, 1 /* num_args_tested */,
+                          ICData::RebindRule::kInstance);
+#if defined(TAG_IC_DATA)
+        ICData::Cast(obj).set_tag(ICData::Tag::kInstanceCall);
+#endif
+      } break;
+      case ConstantPoolTag::kStaticICData: {
+        InvocationKind kind = static_cast<InvocationKind>(helper_->ReadByte());
+        NameIndex target = helper_->ReadCanonicalNameReference();
+        if (H.IsConstructor(target)) {
+          name = H.DartConstructorName(target).raw();
+          elem = H.LookupConstructorByKernelConstructor(target);
+        } else if (H.IsField(target)) {
+          if (kind == InvocationKind::getter) {
+            name = H.DartGetterName(target).raw();
+          } else if (kind == InvocationKind::setter) {
+            name = H.DartSetterName(target).raw();
+          } else {
+            ASSERT(kind == InvocationKind::method);
+            UNIMPLEMENTED();  // TODO(regis): Revisit.
+          }
+          field = H.LookupFieldByKernelField(target);
+          cls = field.Owner();
+          elem = cls.LookupFunctionAllowPrivate(name);
+        } else {
+          if ((kind == InvocationKind::method) && H.IsGetter(target)) {
+            UNIMPLEMENTED();  // TODO(regis): Revisit.
+          }
+          name = H.DartProcedureName(target).raw();
+          elem = H.LookupStaticMethodByKernelProcedure(target);
+        }
+        ASSERT(elem.IsFunction());
+        intptr_t arg_desc_index = helper_->ReadUInt();
+        ASSERT(arg_desc_index < i);
+        array ^= pool.ObjectAt(arg_desc_index);
+        obj = ICData::New(function, name,
+                          array,  // Arguments descriptor.
+                          Thread::kNoDeoptId, 0 /* num_args_tested */,
+                          ICData::RebindRule::kStatic);
+        ICData::Cast(obj).AddTarget(Function::Cast(elem));
+#if defined(TAG_IC_DATA)
+        ICData::Cast(obj).set_tag(ICData::Tag::kStaticCall);
+#endif
+      } break;
+      case ConstantPoolTag::kField:
+        obj = H.LookupFieldByKernelField(helper_->ReadCanonicalNameReference());
+        ASSERT(obj.IsField());
+        break;
+      case ConstantPoolTag::kFieldOffset:
+        obj = H.LookupFieldByKernelField(helper_->ReadCanonicalNameReference());
+        ASSERT(obj.IsField());
+        obj = Smi::New(Field::Cast(obj).Offset() / kWordSize);
+        break;
+      case ConstantPoolTag::kClass:
+        obj = H.LookupClassByKernelClass(helper_->ReadCanonicalNameReference());
+        ASSERT(obj.IsClass());
+        break;
+      case ConstantPoolTag::kTypeArgumentsFieldOffset:
+        cls = H.LookupClassByKernelClass(helper_->ReadCanonicalNameReference());
+        obj = Smi::New(cls.type_arguments_field_offset() / kWordSize);
+        break;
+      case ConstantPoolTag::kTearOff:
+        obj = H.LookupStaticMethodByKernelProcedure(
+            helper_->ReadCanonicalNameReference());
+        ASSERT(obj.IsFunction());
+        obj = Function::Cast(obj).ImplicitClosureFunction();
+        ASSERT(obj.IsFunction());
+        obj = Function::Cast(obj).ImplicitStaticClosure();
+        ASSERT(obj.IsInstance());
+        obj = H.Canonicalize(Instance::Cast(obj));
+        break;
+      case ConstantPoolTag::kType:
+        obj = type_translator_.BuildType().raw();
+        ASSERT(obj.IsAbstractType());
+        break;
+      case ConstantPoolTag::kTypeArguments:
+        obj = type_translator_.BuildTypeArguments(helper_->ReadListLength())
+                  .raw();
+        ASSERT(obj.IsNull() || obj.IsTypeArguments());
+        break;
+      case ConstantPoolTag::kList: {
+        obj = type_translator_.BuildType().raw();
+        ASSERT(obj.IsAbstractType());
+        const intptr_t length = helper_->ReadListLength();
+        array = Array::New(length, AbstractType::Cast(obj));
+        for (intptr_t j = 0; j < length; j++) {
+          intptr_t elem_index = helper_->ReadUInt();
+          ASSERT(elem_index < i);
+          elem = pool.ObjectAt(elem_index);
+          array.SetAt(j, elem);
+        }
+        obj = H.Canonicalize(Array::Cast(array));
+        ASSERT(!obj.IsNull());
+      } break;
+      case ConstantPoolTag::kInstance: {
+        cls = H.LookupClassByKernelClass(helper_->ReadCanonicalNameReference());
+        obj = Instance::New(cls, Heap::kOld);
+        intptr_t type_args_index = helper_->ReadUInt();
+        ASSERT(type_args_index < i);
+        type_args ^= pool.ObjectAt(type_args_index);
+        if (!type_args.IsNull()) {
+          Instance::Cast(obj).SetTypeArguments(type_args);
+        }
+        intptr_t num_fields = helper_->ReadUInt();
+        for (intptr_t j = 0; j < num_fields; j++) {
+          NameIndex field_name = helper_->ReadCanonicalNameReference();
+          ASSERT(H.IsField(field_name));
+          field = H.LookupFieldByKernelField(field_name);
+          intptr_t elem_index = helper_->ReadUInt();
+          ASSERT(elem_index < i);
+          elem = pool.ObjectAt(elem_index);
+          Instance::Cast(obj).SetField(field, elem);
+        }
+        obj = H.Canonicalize(Instance::Cast(obj));
+      } break;
+      case ConstantPoolTag::kSymbol:
+        obj = H.DartSymbolPlain(helper_->ReadStringReference()).raw();
+        ASSERT(String::Cast(obj).IsSymbol());
+        break;
+      case ConstantPoolTag::kTypeArgumentsForInstanceAllocation: {
+        cls = H.LookupClassByKernelClass(helper_->ReadCanonicalNameReference());
+        obj =
+            type_translator_
+                .BuildInstantiatedTypeArguments(cls, helper_->ReadListLength())
+                .raw();
+        ASSERT(obj.IsNull() || obj.IsTypeArguments());
+      } break;
+      case ConstantPoolTag::kContextOffset: {
+        intptr_t index = helper_->ReadUInt();
+        if (index == 0) {
+          obj = Smi::New(Context::parent_offset() / kWordSize);
+        } else {
+          obj = Smi::New(Context::variable_offset(index - 1) / kWordSize);
+        }
+      } break;
+      case ConstantPoolTag::kClosureFunction: {
+        name = H.DartSymbolPlain(helper_->ReadStringReference()).raw();
+        const Function& closure = Function::Handle(
+            helper_->zone_,
+            Function::NewClosureFunction(name, inner_function,
+                                         TokenPosition::kNoSource));
+
+        FunctionNodeHelper function_node_helper(helper_);
+        function_node_helper.ReadUntilExcluding(
+            FunctionNodeHelper::kTypeParameters);
+        type_translator_.LoadAndSetupTypeParameters(
+            active_class_, closure, helper_->ReadListLength(), closure);
+        function_node_helper.SetJustRead(FunctionNodeHelper::kTypeParameters);
+
+        // Scope remains opened until ConstantPoolTag::kEndClosureFunctionScope.
+        ActiveTypeParametersScope scope(
+            active_class_, &closure,
+            TypeArguments::Handle(helper_->zone_, closure.type_parameters()),
+            helper_->zone_);
+
+        function_node_helper.ReadUntilExcluding(
+            FunctionNodeHelper::kPositionalParameters);
+
+        intptr_t required_parameter_count =
+            function_node_helper.required_parameter_count_;
+        intptr_t total_parameter_count =
+            function_node_helper.total_parameter_count_;
+
+        intptr_t positional_parameter_count = helper_->ReadListLength();
+
+        intptr_t named_parameter_count =
+            total_parameter_count - positional_parameter_count;
+
+        const intptr_t extra_parameters = 1;
+        closure.set_num_fixed_parameters(extra_parameters +
+                                         required_parameter_count);
+        if (named_parameter_count > 0) {
+          closure.SetNumOptionalParameters(named_parameter_count, false);
+        } else {
+          closure.SetNumOptionalParameters(
+              positional_parameter_count - required_parameter_count, true);
+        }
+        intptr_t parameter_count = extra_parameters + total_parameter_count;
+        closure.set_parameter_types(Array::Handle(
+            helper_->zone_, Array::New(parameter_count, Heap::kOld)));
+        closure.set_parameter_names(Array::Handle(
+            helper_->zone_, Array::New(parameter_count, Heap::kOld)));
+
+        intptr_t pos = 0;
+        closure.SetParameterTypeAt(pos, AbstractType::dynamic_type());
+        closure.SetParameterNameAt(pos, Symbols::ClosureParameter());
+        pos++;
+
+        const Library& lib =
+            Library::Handle(helper_->zone_, active_class_->klass->library());
+        for (intptr_t j = 0; j < positional_parameter_count; ++j, ++pos) {
+          VariableDeclarationHelper helper(helper_);
+          helper.ReadUntilExcluding(VariableDeclarationHelper::kType);
+          const AbstractType& type = type_translator_.BuildVariableType();
+          Tag tag = helper_->ReadTag();  // read (first part of) initializer.
+          if (tag == kSomething) {
+            helper_->SkipExpression();  // read (actual) initializer.
+          }
+
+          closure.SetParameterTypeAt(pos, type);
+          closure.SetParameterNameAt(pos,
+                                     H.DartIdentifier(lib, helper.name_index_));
+        }
+
+        intptr_t named_parameter_count_check = helper_->ReadListLength();
+        ASSERT(named_parameter_count_check == named_parameter_count);
+        for (intptr_t j = 0; j < named_parameter_count; ++j, ++pos) {
+          VariableDeclarationHelper helper(helper_);
+          helper.ReadUntilExcluding(VariableDeclarationHelper::kType);
+          const AbstractType& type = type_translator_.BuildVariableType();
+          Tag tag = helper_->ReadTag();  // read (first part of) initializer.
+          if (tag == kSomething) {
+            helper_->SkipExpression();  // read (actual) initializer.
+          }
+
+          closure.SetParameterTypeAt(pos, type);
+          closure.SetParameterNameAt(pos,
+                                     H.DartIdentifier(lib, helper.name_index_));
+        }
+
+        function_node_helper.SetJustRead(FunctionNodeHelper::kNamedParameters);
+
+        const AbstractType& return_type = type_translator_.BuildVariableType();
+        closure.set_result_type(return_type);
+        function_node_helper.SetJustRead(FunctionNodeHelper::kReturnType);
+        // The closure has no body.
+        function_node_helper.ReadUntilExcluding(FunctionNodeHelper::kEnd);
+
+        pool.SetTypeAt(i, ObjectPool::kTaggedObject);
+        pool.SetObjectAt(i, closure);
+
+        // Continue reading the constant pool entries inside the opened
+        // ActiveTypeParametersScope until the scope gets closed by a
+        // kEndClosureFunctionScope tag, in which case control returns here.
+        i = ReadPoolEntries(function, closure, pool, i + 1);
+        // Pool entry at index i has been set to null, because it was a
+        // kEndClosureFunctionScope.
+        ASSERT(pool.ObjectAt(i) == Object::null());
+        continue;
+      }
+      case ConstantPoolTag::kEndClosureFunctionScope: {
+        // Entry is not used and set to null.
+        obj = Object::null();
+        pool.SetTypeAt(i, ObjectPool::kTaggedObject);
+        pool.SetObjectAt(i, obj);
+        return i;  // The caller will close the scope.
+      } break;
+      case ConstantPoolTag::kNativeEntry: {
+        name = H.DartString(helper_->ReadStringReference()).raw();
+        obj = NativeEntry(function, name);
+      } break;
+      case ConstantPoolTag::kSubtypeTestCache: {
+        obj = SubtypeTestCache::New();
+      } break;
+      default:
+        UNREACHABLE();
+    }
+    pool.SetTypeAt(i, ObjectPool::kTaggedObject);
+    pool.SetObjectAt(i, obj);
+  }
+  // Return the index of the last read pool entry.
+  return obj_count - 1;
+}
+
+RawCode* BytecodeMetadataHelper::ReadBytecode(const ObjectPool& pool) {
+  intptr_t size = helper_->reader_.ReadUInt();
+  intptr_t offset = helper_->reader_.offset();
+  const uint8_t* data = helper_->reader_.BufferAt(offset);
+  helper_->reader_.set_offset(offset + size);
+
+  // Create and return code object.
+  return Code::FinalizeBytecode(reinterpret_cast<const void*>(data), size,
+                                pool);
+}
+
+void BytecodeMetadataHelper::ReadExceptionsTable(const Code& bytecode) {
+  const intptr_t try_block_count = helper_->reader_.ReadListLength();
+  if (try_block_count > 0) {
+    const ObjectPool& pool =
+        ObjectPool::Handle(helper_->zone_, bytecode.object_pool());
+    AbstractType& handler_type = AbstractType::Handle(helper_->zone_);
+    Array& handler_types = Array::ZoneHandle(helper_->zone_);
+    DescriptorList* pc_descriptors_list =
+        new (helper_->zone_) DescriptorList(64);
+    ExceptionHandlerList* exception_handlers_list =
+        new (helper_->zone_) ExceptionHandlerList();
+
+    // 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 = outer_try_index_plus1 - 1;
+      intptr_t start_pc = helper_->reader_.ReadUInt();
+      intptr_t end_pc = helper_->reader_.ReadUInt();
+      intptr_t handler_pc = helper_->reader_.ReadUInt();
+      uint8_t flags = helper_->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();
+      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();
+        ASSERT(type_index < pool.Length());
+        handler_type ^= pool.ObjectAt(type_index);
+        handler_types.SetAt(i, handler_type);
+      }
+      pc_descriptors_list->AddDescriptor(RawPcDescriptors::kOther, start_pc,
+                                         Thread::kNoDeoptId,
+                                         TokenPosition::kNoSource, try_index);
+      pc_descriptors_list->AddDescriptor(RawPcDescriptors::kOther, end_pc,
+                                         Thread::kNoDeoptId,
+                                         TokenPosition::kNoSource, -1);
+
+      exception_handlers_list->AddHandler(
+          try_index, outer_try_index, handler_pc, TokenPosition::kNoSource,
+          is_generated, handler_types, needs_stacktrace);
+    }
+    const PcDescriptors& descriptors = PcDescriptors::Handle(
+        helper_->zone_,
+        pc_descriptors_list->FinalizePcDescriptors(bytecode.PayloadStart()));
+    bytecode.set_pc_descriptors(descriptors);
+    const ExceptionHandlers& handlers = ExceptionHandlers::Handle(
+        helper_->zone_, exception_handlers_list->FinalizeExceptionHandlers(
+                            bytecode.PayloadStart()));
+    bytecode.set_exception_handlers(handlers);
+  } else {
+    bytecode.set_pc_descriptors(Object::empty_descriptors());
+    bytecode.set_exception_handlers(Object::empty_exception_handlers());
+  }
+}
+
+RawTypedData* BytecodeMetadataHelper::NativeEntry(const Function& function,
+                                                  const String& external_name) {
+  Zone* zone = helper_->zone_;
+  MethodRecognizer::Kind kind = MethodRecognizer::RecognizeKind(function);
+  // This list of recognized methods must be kept in sync with the list of
+  // methods handled specially by the NativeCall bytecode in the interpreter.
+  switch (kind) {
+    case MethodRecognizer::kObjectEquals:
+    case MethodRecognizer::kStringBaseLength:
+    case MethodRecognizer::kStringBaseIsEmpty:
+    case MethodRecognizer::kGrowableArrayLength:
+    case MethodRecognizer::kObjectArrayLength:
+    case MethodRecognizer::kImmutableArrayLength:
+    case MethodRecognizer::kTypedDataLength:
+    case MethodRecognizer::kClassIDgetID:
+    case MethodRecognizer::kGrowableArrayCapacity:
+    case MethodRecognizer::kListFactory:
+    case MethodRecognizer::kObjectArrayAllocate:
+    case MethodRecognizer::kLinkedHashMap_getIndex:
+    case MethodRecognizer::kLinkedHashMap_setIndex:
+    case MethodRecognizer::kLinkedHashMap_getData:
+    case MethodRecognizer::kLinkedHashMap_setData:
+    case MethodRecognizer::kLinkedHashMap_getHashMask:
+    case MethodRecognizer::kLinkedHashMap_setHashMask:
+    case MethodRecognizer::kLinkedHashMap_getUsedData:
+    case MethodRecognizer::kLinkedHashMap_setUsedData:
+    case MethodRecognizer::kLinkedHashMap_getDeletedKeys:
+    case MethodRecognizer::kLinkedHashMap_setDeletedKeys:
+      break;
+    default:
+      kind = MethodRecognizer::kUnknown;
+  }
+  NativeFunctionWrapper trampoline = NULL;
+  NativeFunction native_function = NULL;
+  intptr_t argc_tag = 0;
+  if (kind == MethodRecognizer::kUnknown) {
+    if (FLAG_link_natives_lazily) {
+      trampoline = &NativeEntry::BootstrapNativeCallWrapper;
+      native_function =
+          reinterpret_cast<NativeFunction>(&NativeEntry::LinkNativeCall);
+    } else {
+      const Class& cls = Class::Handle(zone, function.Owner());
+      const Library& library = Library::Handle(zone, cls.library());
+      Dart_NativeEntryResolver resolver = library.native_entry_resolver();
+      const bool is_bootstrap_native = Bootstrap::IsBootstrapResolver(resolver);
+      const int num_params =
+          NativeArguments::ParameterCountForResolution(function);
+      bool is_auto_scope = true;
+      native_function = NativeEntry::ResolveNative(library, external_name,
+                                                   num_params, &is_auto_scope);
+      ASSERT(native_function != NULL);  // TODO(regis): Should we throw instead?
+      if (is_bootstrap_native) {
+        trampoline = &NativeEntry::BootstrapNativeCallWrapper;
+      } else if (is_auto_scope) {
+        trampoline = &NativeEntry::AutoScopeNativeCallWrapper;
+      } else {
+        trampoline = &NativeEntry::NoScopeNativeCallWrapper;
+      }
+    }
+    argc_tag = NativeArguments::ComputeArgcTag(function);
+  }
+  // TODO(regis): Introduce a new VM class subclassing Object and containing
+  // these four untagged values.
+#ifdef ARCH_IS_32_BIT
+  const TypedData& native_entry = TypedData::Handle(
+      zone, TypedData::New(kTypedDataUint32ArrayCid, 4, Heap::kOld));
+  native_entry.SetUint32(0 << 2, static_cast<uint32_t>(kind));
+  native_entry.SetUint32(1 << 2, reinterpret_cast<uint32_t>(trampoline));
+  native_entry.SetUint32(2 << 2, reinterpret_cast<uint32_t>(native_function));
+  native_entry.SetUint32(3 << 2, static_cast<uint32_t>(argc_tag));
+#else
+  const TypedData& native_entry = TypedData::Handle(
+      zone, TypedData::New(kTypedDataUint64ArrayCid, 4, Heap::kOld));
+  native_entry.SetUint64(0 << 3, static_cast<uint64_t>(kind));
+  native_entry.SetUint64(1 << 3, reinterpret_cast<uint64_t>(trampoline));
+  native_entry.SetUint64(2 << 3, reinterpret_cast<uint64_t>(native_function));
+  native_entry.SetUint64(3 << 3, static_cast<uint64_t>(argc_tag));
+#endif
+  return native_entry.raw();
+}
+
+}  // namespace kernel
+}  // namespace dart
+
+#endif  // defined(DART_USE_INTERPRETER)
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
diff --git a/runtime/vm/compiler/frontend/bytecode_reader.h b/runtime/vm/compiler/frontend/bytecode_reader.h
new file mode 100644
index 0000000..e32cf14
--- /dev/null
+++ b/runtime/vm/compiler/frontend/bytecode_reader.h
@@ -0,0 +1,48 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#ifndef RUNTIME_VM_COMPILER_FRONTEND_BYTECODE_READER_H_
+#define RUNTIME_VM_COMPILER_FRONTEND_BYTECODE_READER_H_
+
+#include "vm/compiler/frontend/kernel_translation_helper.h"
+#include "vm/object.h"
+
+#if !defined(DART_PRECOMPILED_RUNTIME)
+#if defined(DART_USE_INTERPRETER)
+
+namespace dart {
+namespace kernel {
+
+// Helper class which provides access to bytecode metadata.
+class BytecodeMetadataHelper : public MetadataHelper {
+ public:
+  static const char* tag() { return "vm.bytecode"; }
+
+  explicit BytecodeMetadataHelper(KernelReaderHelper* helper,
+                                  TypeTranslator* type_translator,
+                                  ActiveClass* active_class);
+
+  void ReadMetadata(const Function& function);
+
+ private:
+  // Returns the index of the last read pool entry.
+  intptr_t ReadPoolEntries(const Function& function,
+                           const Function& inner_function,
+                           const ObjectPool& pool,
+                           intptr_t from_index);
+  RawCode* ReadBytecode(const ObjectPool& pool);
+  void ReadExceptionsTable(const Code& bytecode);
+  RawTypedData* NativeEntry(const Function& function,
+                            const String& external_name);
+
+  TypeTranslator& type_translator_;
+  ActiveClass* const active_class_;
+};
+
+}  // namespace kernel
+}  // namespace dart
+
+#endif  // defined(DART_USE_INTERPRETER)
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
+#endif  // RUNTIME_VM_COMPILER_FRONTEND_BYTECODE_READER_H_
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
index 3a8f5cb..037f497 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
@@ -4,10 +4,8 @@
 
 #include "vm/compiler/frontend/kernel_binary_flowgraph.h"
 
-#include "vm/bootstrap.h"
-#include "vm/code_descriptors.h"
 #include "vm/compiler/aot/precompiler.h"
-#include "vm/compiler/assembler/disassembler_kbc.h"
+#include "vm/compiler/frontend/bytecode_reader.h"
 #include "vm/compiler/frontend/prologue_builder.h"
 #include "vm/compiler/jit/compiler.h"
 #include "vm/dart_entry.h"
@@ -19,11 +17,6 @@
 #if !defined(DART_PRECOMPILED_RUNTIME)
 
 namespace dart {
-
-#if defined(DART_USE_INTERPRETER)
-DEFINE_FLAG(bool, dump_kernel_bytecode, false, "Dump kernel bytecode");
-#endif  // defined(DART_USE_INTERPRETER)
-
 namespace kernel {
 
 #define Z (zone_)
@@ -63,738 +56,6 @@
   return !FLAG_precompiled_mode || !attrs.has_dynamic_invocations;
 }
 
-DirectCallMetadataHelper::DirectCallMetadataHelper(KernelReaderHelper* helper)
-    : MetadataHelper(helper, tag(), /* precompiler_only = */ true) {}
-
-bool DirectCallMetadataHelper::ReadMetadata(intptr_t node_offset,
-                                            NameIndex* target_name,
-                                            bool* check_receiver_for_null) {
-  intptr_t md_offset = GetNextMetadataPayloadOffset(node_offset);
-  if (md_offset < 0) {
-    return false;
-  }
-
-  AlternativeReadingScope alt(&helper_->reader_, &H.metadata_payloads(),
-                              md_offset);
-
-  *target_name = helper_->ReadCanonicalNameReference();
-  *check_receiver_for_null = helper_->ReadBool();
-  return true;
-}
-
-DirectCallMetadata DirectCallMetadataHelper::GetDirectTargetForPropertyGet(
-    intptr_t node_offset) {
-  NameIndex kernel_name;
-  bool check_receiver_for_null = false;
-  if (!ReadMetadata(node_offset, &kernel_name, &check_receiver_for_null)) {
-    return DirectCallMetadata(Function::null_function(), false);
-  }
-
-  if (H.IsProcedure(kernel_name) && !H.IsGetter(kernel_name)) {
-    // Tear-off. Use method extractor as direct call target.
-    const String& method_name = H.DartMethodName(kernel_name);
-    const Function& target_method = Function::ZoneHandle(
-        helper_->zone_, H.LookupMethodByMember(kernel_name, method_name));
-    const String& getter_name = H.DartGetterName(kernel_name);
-    return DirectCallMetadata(
-        Function::ZoneHandle(helper_->zone_,
-                             target_method.GetMethodExtractor(getter_name)),
-        check_receiver_for_null);
-  } else {
-    const String& getter_name = H.DartGetterName(kernel_name);
-    const Function& target = Function::ZoneHandle(
-        helper_->zone_, H.LookupMethodByMember(kernel_name, getter_name));
-    ASSERT(target.IsGetterFunction() || target.IsImplicitGetterFunction());
-    return DirectCallMetadata(target, check_receiver_for_null);
-  }
-}
-
-DirectCallMetadata DirectCallMetadataHelper::GetDirectTargetForPropertySet(
-    intptr_t node_offset) {
-  NameIndex kernel_name;
-  bool check_receiver_for_null = false;
-  if (!ReadMetadata(node_offset, &kernel_name, &check_receiver_for_null)) {
-    return DirectCallMetadata(Function::null_function(), false);
-  }
-
-  const String& method_name = H.DartSetterName(kernel_name);
-  const Function& target = Function::ZoneHandle(
-      helper_->zone_, H.LookupMethodByMember(kernel_name, method_name));
-  ASSERT(target.IsSetterFunction() || target.IsImplicitSetterFunction());
-
-  return DirectCallMetadata(target, check_receiver_for_null);
-}
-
-DirectCallMetadata DirectCallMetadataHelper::GetDirectTargetForMethodInvocation(
-    intptr_t node_offset) {
-  NameIndex kernel_name;
-  bool check_receiver_for_null = false;
-  if (!ReadMetadata(node_offset, &kernel_name, &check_receiver_for_null)) {
-    return DirectCallMetadata(Function::null_function(), false);
-  }
-
-  const String& method_name = H.DartProcedureName(kernel_name);
-  const Function& target = Function::ZoneHandle(
-      helper_->zone_, H.LookupMethodByMember(kernel_name, method_name));
-
-  return DirectCallMetadata(target, check_receiver_for_null);
-}
-
-bool ProcedureAttributesMetadataHelper::ReadMetadata(
-    intptr_t node_offset,
-    ProcedureAttributesMetadata* metadata) {
-  intptr_t md_offset = GetNextMetadataPayloadOffset(node_offset);
-  if (md_offset < 0) {
-    return false;
-  }
-
-  AlternativeReadingScope alt(&helper_->reader_, &H.metadata_payloads(),
-                              md_offset);
-
-  const int kDynamicUsesBit = 1 << 0;
-  const int kNonThisUsesBit = 1 << 1;
-  const int kTearOffUsesBit = 1 << 2;
-
-  const uint8_t flags = helper_->ReadByte();
-  metadata->has_dynamic_invocations =
-      (flags & kDynamicUsesBit) == kDynamicUsesBit;
-  metadata->has_non_this_uses = (flags & kNonThisUsesBit) == kNonThisUsesBit;
-  metadata->has_tearoff_uses = (flags & kTearOffUsesBit) == kTearOffUsesBit;
-  return true;
-}
-
-ProcedureAttributesMetadataHelper::ProcedureAttributesMetadataHelper(
-    KernelReaderHelper* helper)
-    : MetadataHelper(helper, tag(), /* precompiler_only = */ true) {}
-
-ProcedureAttributesMetadata
-ProcedureAttributesMetadataHelper::GetProcedureAttributes(
-    intptr_t node_offset) {
-  ProcedureAttributesMetadata metadata;
-  ReadMetadata(node_offset, &metadata);
-  return metadata;
-}
-
-InferredTypeMetadataHelper::InferredTypeMetadataHelper(
-    KernelReaderHelper* helper)
-    : MetadataHelper(helper, tag(), /* precompiler_only = */ true) {}
-
-InferredTypeMetadata InferredTypeMetadataHelper::GetInferredType(
-    intptr_t node_offset) {
-  const intptr_t md_offset = GetNextMetadataPayloadOffset(node_offset);
-  if (md_offset < 0) {
-    return InferredTypeMetadata(kDynamicCid, true);
-  }
-
-  AlternativeReadingScope alt(&helper_->reader_, &H.metadata_payloads(),
-                              md_offset);
-
-  const NameIndex kernel_name = helper_->ReadCanonicalNameReference();
-  const bool nullable = helper_->ReadBool();
-
-  if (H.IsRoot(kernel_name)) {
-    return InferredTypeMetadata(kDynamicCid, nullable);
-  }
-
-  const Class& klass =
-      Class::Handle(helper_->zone_, H.LookupClassByKernelClass(kernel_name));
-  ASSERT(!klass.IsNull());
-
-  intptr_t cid = klass.id();
-  if (cid == kClosureCid) {
-    // VM uses more specific function types and doesn't expect instances of
-    // _Closure class, so inferred _Closure class doesn't make sense for the VM.
-    cid = kDynamicCid;
-  }
-
-  return InferredTypeMetadata(cid, nullable);
-}
-
-#if defined(DART_USE_INTERPRETER)
-
-BytecodeMetadataHelper::BytecodeMetadataHelper(KernelReaderHelper* helper,
-                                               TypeTranslator* type_translator,
-                                               ActiveClass* active_class)
-    : MetadataHelper(helper, tag(), /* precompiler_only = */ false),
-      type_translator_(*type_translator),
-      active_class_(active_class) {}
-
-void BytecodeMetadataHelper::ReadMetadata(const Function& function) {
-  const intptr_t node_offset = function.kernel_offset();
-  const intptr_t md_offset = GetNextMetadataPayloadOffset(node_offset);
-  if (md_offset < 0) {
-    return;
-  }
-
-  AlternativeReadingScope alt(&helper_->reader_, &H.metadata_payloads(),
-                              md_offset);
-
-  // Create object pool and read pool entries.
-  const intptr_t obj_count = helper_->reader_.ReadListLength();
-  const ObjectPool& pool =
-      ObjectPool::Handle(helper_->zone_, ObjectPool::New(obj_count));
-  ReadPoolEntries(function, function, pool, 0);
-
-  // Read bytecode and attach to function.
-  const Code& bytecode = Code::Handle(helper_->zone_, ReadBytecode(pool));
-  function.AttachBytecode(bytecode);
-
-  // Read exceptions table.
-  ReadExceptionsTable(bytecode);
-
-  if (FLAG_dump_kernel_bytecode) {
-    KernelBytecodeDisassembler::Disassemble(function);
-  }
-
-  // Read closures.
-  Function& closure = Function::Handle(helper_->zone_);
-  Code& closure_bytecode = Code::Handle(helper_->zone_);
-  intptr_t num_closures = helper_->ReadListLength();
-  for (intptr_t i = 0; i < num_closures; i++) {
-    intptr_t closure_index = helper_->ReadUInt();
-    ASSERT(closure_index < obj_count);
-    closure ^= pool.ObjectAt(closure_index);
-
-    // Read closure bytecode and attach to closure function.
-    closure_bytecode = ReadBytecode(pool);
-    closure.AttachBytecode(closure_bytecode);
-
-    // Read closure exceptions table.
-    ReadExceptionsTable(closure_bytecode);
-
-    if (FLAG_dump_kernel_bytecode) {
-      KernelBytecodeDisassembler::Disassemble(closure);
-    }
-  }
-}
-
-intptr_t BytecodeMetadataHelper::ReadPoolEntries(const Function& function,
-                                                 const Function& inner_function,
-                                                 const ObjectPool& pool,
-                                                 intptr_t from_index) {
-  // These enums and the code below reading the constant pool from kernel must
-  // be kept in sync with pkg/vm/lib/bytecode/constant_pool.dart.
-  enum ConstantPoolTag {
-    kInvalid,
-    kNull,
-    kString,
-    kInt,
-    kDouble,
-    kBool,
-    kArgDesc,
-    kICData,
-    kStaticICData,
-    kField,
-    kFieldOffset,
-    kClass,
-    kTypeArgumentsFieldOffset,
-    kTearOff,
-    kType,
-    kTypeArguments,
-    kList,
-    kInstance,
-    kSymbol,
-    kTypeArgumentsForInstanceAllocation,
-    kContextOffset,
-    kClosureFunction,
-    kEndClosureFunctionScope,
-    kNativeEntry,
-    kSubtypeTestCache,
-  };
-
-  enum InvocationKind {
-    method,  // x.foo(...) or foo(...)
-    getter,  // x.foo
-    setter   // x.foo = ...
-  };
-
-  Object& obj = Object::Handle(helper_->zone_);
-  Object& elem = Object::Handle(helper_->zone_);
-  Array& array = Array::Handle(helper_->zone_);
-  Field& field = Field::Handle(helper_->zone_);
-  Class& cls = Class::Handle(helper_->zone_);
-  String& name = String::Handle(helper_->zone_);
-  TypeArguments& type_args = TypeArguments::Handle(helper_->zone_);
-  const intptr_t obj_count = pool.Length();
-  for (intptr_t i = from_index; i < obj_count; ++i) {
-    const intptr_t tag = helper_->ReadTag();
-    switch (tag) {
-      case ConstantPoolTag::kInvalid:
-        UNREACHABLE();
-      case ConstantPoolTag::kNull:
-        obj = Object::null();
-        break;
-      case ConstantPoolTag::kString:
-        obj = H.DartString(helper_->ReadStringReference()).raw();
-        ASSERT(obj.IsString());
-        obj = H.Canonicalize(String::Cast(obj));
-        break;
-      case ConstantPoolTag::kInt: {
-        uint32_t low_bits = helper_->ReadUInt32();
-        int64_t value = helper_->ReadUInt32();
-        value = (value << 32) | low_bits;
-        obj = Integer::New(value);
-      } break;
-      case ConstantPoolTag::kDouble: {
-        uint32_t low_bits = helper_->ReadUInt32();
-        uint64_t bits = helper_->ReadUInt32();
-        bits = (bits << 32) | low_bits;
-        double value = bit_cast<double, uint64_t>(bits);
-        obj = Double::New(value);
-      } break;
-      case ConstantPoolTag::kBool:
-        if (helper_->ReadUInt() == 1) {
-          obj = Bool::True().raw();
-        } else {
-          obj = Bool::False().raw();
-        }
-        break;
-      case ConstantPoolTag::kArgDesc: {
-        intptr_t num_arguments = helper_->ReadUInt();
-        intptr_t num_type_args = helper_->ReadUInt();
-        intptr_t num_arg_names = helper_->ReadListLength();
-        if (num_arg_names == 0) {
-          obj = ArgumentsDescriptor::New(num_type_args, num_arguments);
-        } else {
-          array = Array::New(num_arg_names);
-          for (intptr_t j = 0; j < num_arg_names; j++) {
-            array.SetAt(j, H.DartSymbolPlain(helper_->ReadStringReference()));
-          }
-          obj = ArgumentsDescriptor::New(num_type_args, num_arguments, array);
-        }
-      } break;
-      case ConstantPoolTag::kICData: {
-        InvocationKind kind = static_cast<InvocationKind>(helper_->ReadByte());
-        if (kind == InvocationKind::getter) {
-          name = helper_->ReadNameAsGetterName().raw();
-        } else if (kind == InvocationKind::setter) {
-          name = helper_->ReadNameAsSetterName().raw();
-        } else {
-          ASSERT(kind == InvocationKind::method);
-          name = helper_->ReadNameAsMethodName().raw();
-        }
-        intptr_t arg_desc_index = helper_->ReadUInt();
-        ASSERT(arg_desc_index < i);
-        array ^= pool.ObjectAt(arg_desc_index);
-        // TODO(regis): Should num_args_tested be explicitly provided?
-        obj = ICData::New(function, name,
-                          array,  // Arguments descriptor.
-                          Thread::kNoDeoptId, 1 /* num_args_tested */,
-                          ICData::RebindRule::kInstance);
-#if defined(TAG_IC_DATA)
-        ICData::Cast(obj).set_tag(Instruction::kInstanceCall);
-#endif
-      } break;
-      case ConstantPoolTag::kStaticICData: {
-        InvocationKind kind = static_cast<InvocationKind>(helper_->ReadByte());
-        NameIndex target = helper_->ReadCanonicalNameReference();
-        if (H.IsConstructor(target)) {
-          name = H.DartConstructorName(target).raw();
-          elem = H.LookupConstructorByKernelConstructor(target);
-        } else if (H.IsField(target)) {
-          if (kind == InvocationKind::getter) {
-            name = H.DartGetterName(target).raw();
-          } else if (kind == InvocationKind::setter) {
-            name = H.DartSetterName(target).raw();
-          } else {
-            ASSERT(kind == InvocationKind::method);
-            UNIMPLEMENTED();  // TODO(regis): Revisit.
-          }
-          field = H.LookupFieldByKernelField(target);
-          cls = field.Owner();
-          elem = cls.LookupFunctionAllowPrivate(name);
-        } else {
-          if ((kind == InvocationKind::method) && H.IsGetter(target)) {
-            UNIMPLEMENTED();  // TODO(regis): Revisit.
-          }
-          name = H.DartProcedureName(target).raw();
-          elem = H.LookupStaticMethodByKernelProcedure(target);
-        }
-        ASSERT(elem.IsFunction());
-        intptr_t arg_desc_index = helper_->ReadUInt();
-        ASSERT(arg_desc_index < i);
-        array ^= pool.ObjectAt(arg_desc_index);
-        obj = ICData::New(function, name,
-                          array,  // Arguments descriptor.
-                          Thread::kNoDeoptId, 0 /* num_args_tested */,
-                          ICData::RebindRule::kStatic);
-        ICData::Cast(obj).AddTarget(Function::Cast(elem));
-#if defined(TAG_IC_DATA)
-        ICData::Cast(obj).set_tag(Instruction::kStaticCall);
-#endif
-      } break;
-      case ConstantPoolTag::kField:
-        obj = H.LookupFieldByKernelField(helper_->ReadCanonicalNameReference());
-        ASSERT(obj.IsField());
-        break;
-      case ConstantPoolTag::kFieldOffset:
-        obj = H.LookupFieldByKernelField(helper_->ReadCanonicalNameReference());
-        ASSERT(obj.IsField());
-        obj = Smi::New(Field::Cast(obj).Offset() / kWordSize);
-        break;
-      case ConstantPoolTag::kClass:
-        obj = H.LookupClassByKernelClass(helper_->ReadCanonicalNameReference());
-        ASSERT(obj.IsClass());
-        break;
-      case ConstantPoolTag::kTypeArgumentsFieldOffset:
-        cls = H.LookupClassByKernelClass(helper_->ReadCanonicalNameReference());
-        obj = Smi::New(cls.type_arguments_field_offset() / kWordSize);
-        break;
-      case ConstantPoolTag::kTearOff:
-        obj = H.LookupStaticMethodByKernelProcedure(
-            helper_->ReadCanonicalNameReference());
-        ASSERT(obj.IsFunction());
-        obj = Function::Cast(obj).ImplicitClosureFunction();
-        ASSERT(obj.IsFunction());
-        obj = Function::Cast(obj).ImplicitStaticClosure();
-        ASSERT(obj.IsInstance());
-        obj = H.Canonicalize(Instance::Cast(obj));
-        break;
-      case ConstantPoolTag::kType:
-        obj = type_translator_.BuildType().raw();
-        ASSERT(obj.IsAbstractType());
-        break;
-      case ConstantPoolTag::kTypeArguments:
-        obj = type_translator_.BuildTypeArguments(helper_->ReadListLength())
-                  .raw();
-        ASSERT(obj.IsNull() || obj.IsTypeArguments());
-        break;
-      case ConstantPoolTag::kList: {
-        obj = type_translator_.BuildType().raw();
-        ASSERT(obj.IsAbstractType());
-        const intptr_t length = helper_->ReadListLength();
-        array = Array::New(length, AbstractType::Cast(obj));
-        for (intptr_t j = 0; j < length; j++) {
-          intptr_t elem_index = helper_->ReadUInt();
-          ASSERT(elem_index < i);
-          elem = pool.ObjectAt(elem_index);
-          array.SetAt(j, elem);
-        }
-        obj = H.Canonicalize(Array::Cast(array));
-        ASSERT(!obj.IsNull());
-      } break;
-      case ConstantPoolTag::kInstance: {
-        cls = H.LookupClassByKernelClass(helper_->ReadCanonicalNameReference());
-        obj = Instance::New(cls, Heap::kOld);
-        intptr_t type_args_index = helper_->ReadUInt();
-        ASSERT(type_args_index < i);
-        type_args ^= pool.ObjectAt(type_args_index);
-        if (!type_args.IsNull()) {
-          Instance::Cast(obj).SetTypeArguments(type_args);
-        }
-        intptr_t num_fields = helper_->ReadUInt();
-        for (intptr_t j = 0; j < num_fields; j++) {
-          NameIndex field_name = helper_->ReadCanonicalNameReference();
-          ASSERT(H.IsField(field_name));
-          field = H.LookupFieldByKernelField(field_name);
-          intptr_t elem_index = helper_->ReadUInt();
-          ASSERT(elem_index < i);
-          elem = pool.ObjectAt(elem_index);
-          Instance::Cast(obj).SetField(field, elem);
-        }
-        obj = H.Canonicalize(Instance::Cast(obj));
-      } break;
-      case ConstantPoolTag::kSymbol:
-        obj = H.DartSymbolPlain(helper_->ReadStringReference()).raw();
-        ASSERT(String::Cast(obj).IsSymbol());
-        break;
-      case ConstantPoolTag::kTypeArgumentsForInstanceAllocation: {
-        cls = H.LookupClassByKernelClass(helper_->ReadCanonicalNameReference());
-        obj =
-            type_translator_
-                .BuildInstantiatedTypeArguments(cls, helper_->ReadListLength())
-                .raw();
-        ASSERT(obj.IsNull() || obj.IsTypeArguments());
-      } break;
-      case ConstantPoolTag::kContextOffset: {
-        intptr_t index = helper_->ReadUInt();
-        if (index == 0) {
-          obj = Smi::New(Context::parent_offset() / kWordSize);
-        } else {
-          obj = Smi::New(Context::variable_offset(index - 1) / kWordSize);
-        }
-      } break;
-      case ConstantPoolTag::kClosureFunction: {
-        name = H.DartSymbolPlain(helper_->ReadStringReference()).raw();
-        const Function& closure = Function::Handle(
-            helper_->zone_,
-            Function::NewClosureFunction(name, inner_function,
-                                         TokenPosition::kNoSource));
-
-        FunctionNodeHelper function_node_helper(helper_);
-        function_node_helper.ReadUntilExcluding(
-            FunctionNodeHelper::kTypeParameters);
-        type_translator_.LoadAndSetupTypeParameters(
-            active_class_, closure, helper_->ReadListLength(), closure);
-        function_node_helper.SetJustRead(FunctionNodeHelper::kTypeParameters);
-
-        // Scope remains opened until ConstantPoolTag::kEndClosureFunctionScope.
-        ActiveTypeParametersScope scope(
-            active_class_, &closure,
-            TypeArguments::Handle(helper_->zone_, closure.type_parameters()),
-            helper_->zone_);
-
-        function_node_helper.ReadUntilExcluding(
-            FunctionNodeHelper::kPositionalParameters);
-
-        intptr_t required_parameter_count =
-            function_node_helper.required_parameter_count_;
-        intptr_t total_parameter_count =
-            function_node_helper.total_parameter_count_;
-
-        intptr_t positional_parameter_count = helper_->ReadListLength();
-
-        intptr_t named_parameter_count =
-            total_parameter_count - positional_parameter_count;
-
-        const intptr_t extra_parameters = 1;
-        closure.set_num_fixed_parameters(extra_parameters +
-                                         required_parameter_count);
-        if (named_parameter_count > 0) {
-          closure.SetNumOptionalParameters(named_parameter_count, false);
-        } else {
-          closure.SetNumOptionalParameters(
-              positional_parameter_count - required_parameter_count, true);
-        }
-        intptr_t parameter_count = extra_parameters + total_parameter_count;
-        closure.set_parameter_types(Array::Handle(
-            helper_->zone_, Array::New(parameter_count, Heap::kOld)));
-        closure.set_parameter_names(Array::Handle(
-            helper_->zone_, Array::New(parameter_count, Heap::kOld)));
-
-        intptr_t pos = 0;
-        closure.SetParameterTypeAt(pos, AbstractType::dynamic_type());
-        closure.SetParameterNameAt(pos, Symbols::ClosureParameter());
-        pos++;
-
-        const Library& lib =
-            Library::Handle(helper_->zone_, active_class_->klass->library());
-        for (intptr_t j = 0; j < positional_parameter_count; ++j, ++pos) {
-          VariableDeclarationHelper helper(helper_);
-          helper.ReadUntilExcluding(VariableDeclarationHelper::kType);
-          const AbstractType& type = type_translator_.BuildVariableType();
-          Tag tag = helper_->ReadTag();  // read (first part of) initializer.
-          if (tag == kSomething) {
-            helper_->SkipExpression();  // read (actual) initializer.
-          }
-
-          closure.SetParameterTypeAt(pos, type);
-          closure.SetParameterNameAt(pos,
-                                     H.DartIdentifier(lib, helper.name_index_));
-        }
-
-        intptr_t named_parameter_count_check = helper_->ReadListLength();
-        ASSERT(named_parameter_count_check == named_parameter_count);
-        for (intptr_t j = 0; j < named_parameter_count; ++j, ++pos) {
-          VariableDeclarationHelper helper(helper_);
-          helper.ReadUntilExcluding(VariableDeclarationHelper::kType);
-          const AbstractType& type = type_translator_.BuildVariableType();
-          Tag tag = helper_->ReadTag();  // read (first part of) initializer.
-          if (tag == kSomething) {
-            helper_->SkipExpression();  // read (actual) initializer.
-          }
-
-          closure.SetParameterTypeAt(pos, type);
-          closure.SetParameterNameAt(pos,
-                                     H.DartIdentifier(lib, helper.name_index_));
-        }
-
-        function_node_helper.SetJustRead(FunctionNodeHelper::kNamedParameters);
-
-        const AbstractType& return_type = type_translator_.BuildVariableType();
-        closure.set_result_type(return_type);
-        function_node_helper.SetJustRead(FunctionNodeHelper::kReturnType);
-        // The closure has no body.
-        function_node_helper.ReadUntilExcluding(FunctionNodeHelper::kEnd);
-
-        pool.SetTypeAt(i, ObjectPool::kTaggedObject);
-        pool.SetObjectAt(i, closure);
-
-        // Continue reading the constant pool entries inside the opened
-        // ActiveTypeParametersScope until the scope gets closed by a
-        // kEndClosureFunctionScope tag, in which case control returns here.
-        i = ReadPoolEntries(function, closure, pool, i + 1);
-        // Pool entry at index i has been set to null, because it was a
-        // kEndClosureFunctionScope.
-        ASSERT(pool.ObjectAt(i) == Object::null());
-        continue;
-      }
-      case ConstantPoolTag::kEndClosureFunctionScope: {
-        // Entry is not used and set to null.
-        obj = Object::null();
-        pool.SetTypeAt(i, ObjectPool::kTaggedObject);
-        pool.SetObjectAt(i, obj);
-        return i;  // The caller will close the scope.
-      } break;
-      case ConstantPoolTag::kNativeEntry: {
-        name = H.DartString(helper_->ReadStringReference()).raw();
-        obj = NativeEntry(function, name);
-      } break;
-      case ConstantPoolTag::kSubtypeTestCache: {
-        obj = SubtypeTestCache::New();
-      } break;
-      default:
-        UNREACHABLE();
-    }
-    pool.SetTypeAt(i, ObjectPool::kTaggedObject);
-    pool.SetObjectAt(i, obj);
-  }
-  // Return the index of the last read pool entry.
-  return obj_count - 1;
-}
-
-RawCode* BytecodeMetadataHelper::ReadBytecode(const ObjectPool& pool) {
-  intptr_t size = helper_->reader_.ReadUInt();
-  intptr_t offset = helper_->reader_.offset();
-  const uint8_t* data = helper_->reader_.BufferAt(offset);
-  helper_->reader_.set_offset(offset + size);
-
-  // Create and return code object.
-  return Code::FinalizeBytecode(reinterpret_cast<const void*>(data), size,
-                                pool);
-}
-
-void BytecodeMetadataHelper::ReadExceptionsTable(const Code& bytecode) {
-  const intptr_t try_block_count = helper_->reader_.ReadListLength();
-  if (try_block_count > 0) {
-    const ObjectPool& pool =
-        ObjectPool::Handle(helper_->zone_, bytecode.object_pool());
-    AbstractType& handler_type = AbstractType::Handle(helper_->zone_);
-    Array& handler_types = Array::ZoneHandle(helper_->zone_);
-    DescriptorList* pc_descriptors_list =
-        new (helper_->zone_) DescriptorList(64);
-    ExceptionHandlerList* exception_handlers_list =
-        new (helper_->zone_) ExceptionHandlerList();
-
-    // 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 = outer_try_index_plus1 - 1;
-      intptr_t start_pc = helper_->reader_.ReadUInt();
-      intptr_t end_pc = helper_->reader_.ReadUInt();
-      intptr_t handler_pc = helper_->reader_.ReadUInt();
-      uint8_t flags = helper_->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();
-      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();
-        ASSERT(type_index < pool.Length());
-        handler_type ^= pool.ObjectAt(type_index);
-        handler_types.SetAt(i, handler_type);
-      }
-      pc_descriptors_list->AddDescriptor(RawPcDescriptors::kOther, start_pc,
-                                         Thread::kNoDeoptId,
-                                         TokenPosition::kNoSource, try_index);
-      pc_descriptors_list->AddDescriptor(RawPcDescriptors::kOther, end_pc,
-                                         Thread::kNoDeoptId,
-                                         TokenPosition::kNoSource, -1);
-
-      exception_handlers_list->AddHandler(
-          try_index, outer_try_index, handler_pc, TokenPosition::kNoSource,
-          is_generated, handler_types, needs_stacktrace);
-    }
-    const PcDescriptors& descriptors = PcDescriptors::Handle(
-        helper_->zone_,
-        pc_descriptors_list->FinalizePcDescriptors(bytecode.PayloadStart()));
-    bytecode.set_pc_descriptors(descriptors);
-    const ExceptionHandlers& handlers = ExceptionHandlers::Handle(
-        helper_->zone_, exception_handlers_list->FinalizeExceptionHandlers(
-                            bytecode.PayloadStart()));
-    bytecode.set_exception_handlers(handlers);
-  } else {
-    bytecode.set_pc_descriptors(Object::empty_descriptors());
-    bytecode.set_exception_handlers(Object::empty_exception_handlers());
-  }
-}
-
-RawTypedData* BytecodeMetadataHelper::NativeEntry(const Function& function,
-                                                  const String& external_name) {
-  Zone* zone = helper_->zone_;
-  MethodRecognizer::Kind kind = MethodRecognizer::RecognizeKind(function);
-  // This list of recognized methods must be kept in sync with the list of
-  // methods handled specially by the NativeCall bytecode in the interpreter.
-  switch (kind) {
-    case MethodRecognizer::kObjectEquals:
-    case MethodRecognizer::kStringBaseLength:
-    case MethodRecognizer::kStringBaseIsEmpty:
-    case MethodRecognizer::kGrowableArrayLength:
-    case MethodRecognizer::kObjectArrayLength:
-    case MethodRecognizer::kImmutableArrayLength:
-    case MethodRecognizer::kTypedDataLength:
-    case MethodRecognizer::kClassIDgetID:
-    case MethodRecognizer::kGrowableArrayCapacity:
-    case MethodRecognizer::kListFactory:
-    case MethodRecognizer::kObjectArrayAllocate:
-    case MethodRecognizer::kLinkedHashMap_getIndex:
-    case MethodRecognizer::kLinkedHashMap_setIndex:
-    case MethodRecognizer::kLinkedHashMap_getData:
-    case MethodRecognizer::kLinkedHashMap_setData:
-    case MethodRecognizer::kLinkedHashMap_getHashMask:
-    case MethodRecognizer::kLinkedHashMap_setHashMask:
-    case MethodRecognizer::kLinkedHashMap_getUsedData:
-    case MethodRecognizer::kLinkedHashMap_setUsedData:
-    case MethodRecognizer::kLinkedHashMap_getDeletedKeys:
-    case MethodRecognizer::kLinkedHashMap_setDeletedKeys:
-      break;
-    default:
-      kind = MethodRecognizer::kUnknown;
-  }
-  NativeFunctionWrapper trampoline = NULL;
-  NativeFunction native_function = NULL;
-  intptr_t argc_tag = 0;
-  if (kind == MethodRecognizer::kUnknown) {
-    if (FLAG_link_natives_lazily) {
-      trampoline = &NativeEntry::BootstrapNativeCallWrapper;
-      native_function =
-          reinterpret_cast<NativeFunction>(&NativeEntry::LinkNativeCall);
-    } else {
-      const Class& cls = Class::Handle(zone, function.Owner());
-      const Library& library = Library::Handle(zone, cls.library());
-      Dart_NativeEntryResolver resolver = library.native_entry_resolver();
-      const bool is_bootstrap_native = Bootstrap::IsBootstrapResolver(resolver);
-      const int num_params =
-          NativeArguments::ParameterCountForResolution(function);
-      bool is_auto_scope = true;
-      native_function = NativeEntry::ResolveNative(library, external_name,
-                                                   num_params, &is_auto_scope);
-      ASSERT(native_function != NULL);  // TODO(regis): Should we throw instead?
-      if (is_bootstrap_native) {
-        trampoline = &NativeEntry::BootstrapNativeCallWrapper;
-      } else if (is_auto_scope) {
-        trampoline = &NativeEntry::AutoScopeNativeCallWrapper;
-      } else {
-        trampoline = &NativeEntry::NoScopeNativeCallWrapper;
-      }
-    }
-    argc_tag = NativeArguments::ComputeArgcTag(function);
-  }
-  // TODO(regis): Introduce a new VM class subclassing Object and containing
-  // these four untagged values.
-#ifdef ARCH_IS_32_BIT
-  const TypedData& native_entry = TypedData::Handle(
-      zone, TypedData::New(kTypedDataUint32ArrayCid, 4, Heap::kOld));
-  native_entry.SetUint32(0 << 2, static_cast<uint32_t>(kind));
-  native_entry.SetUint32(1 << 2, reinterpret_cast<uint32_t>(trampoline));
-  native_entry.SetUint32(2 << 2, reinterpret_cast<uint32_t>(native_function));
-  native_entry.SetUint32(3 << 2, static_cast<uint32_t>(argc_tag));
-#else
-  const TypedData& native_entry = TypedData::Handle(
-      zone, TypedData::New(kTypedDataUint64ArrayCid, 4, Heap::kOld));
-  native_entry.SetUint64(0 << 3, static_cast<uint64_t>(kind));
-  native_entry.SetUint64(1 << 3, reinterpret_cast<uint64_t>(trampoline));
-  native_entry.SetUint64(2 << 3, reinterpret_cast<uint64_t>(native_function));
-  native_entry.SetUint64(3 << 3, static_cast<uint64_t>(argc_tag));
-#endif
-  return native_entry.raw();
-}
-#endif  // defined(DART_USE_INTERPRETER)
-
 StreamingScopeBuilder::StreamingScopeBuilder(ParsedFunction* parsed_function)
     : result_(NULL),
       parsed_function_(parsed_function),
@@ -2428,456 +1689,6 @@
   }
 }
 
-TypeTranslator::TypeTranslator(KernelReaderHelper* helper,
-                               ActiveClass* active_class,
-                               bool finalize)
-    : helper_(helper),
-      translation_helper_(helper->translation_helper_),
-      active_class_(active_class),
-      type_parameter_scope_(NULL),
-      zone_(translation_helper_.zone()),
-      result_(AbstractType::Handle(translation_helper_.zone())),
-      finalize_(finalize) {}
-
-AbstractType& TypeTranslator::BuildType() {
-  BuildTypeInternal();
-
-  // We return a new `ZoneHandle` here on purpose: The intermediate language
-  // instructions do not make a copy of the handle, so we do it.
-  return AbstractType::ZoneHandle(Z, result_.raw());
-}
-
-AbstractType& TypeTranslator::BuildTypeWithoutFinalization() {
-  bool saved_finalize = finalize_;
-  finalize_ = false;
-  BuildTypeInternal();
-  finalize_ = saved_finalize;
-
-  // We return a new `ZoneHandle` here on purpose: The intermediate language
-  // instructions do not make a copy of the handle, so we do it.
-  return AbstractType::ZoneHandle(Z, result_.raw());
-}
-
-AbstractType& TypeTranslator::BuildVariableType() {
-  AbstractType& abstract_type = BuildType();
-
-  // We return a new `ZoneHandle` here on purpose: The intermediate language
-  // instructions do not make a copy of the handle, so we do it.
-  AbstractType& type = Type::ZoneHandle(Z);
-
-  if (abstract_type.IsMalformed()) {
-    type = AbstractType::dynamic_type().raw();
-  } else {
-    type = result_.raw();
-  }
-
-  return type;
-}
-
-void TypeTranslator::BuildTypeInternal(bool invalid_as_dynamic) {
-  Tag tag = helper_->ReadTag();
-  switch (tag) {
-    case kInvalidType:
-      if (invalid_as_dynamic) {
-        result_ = Object::dynamic_type().raw();
-      } else {
-        result_ = ClassFinalizer::NewFinalizedMalformedType(
-            Error::Handle(Z),  // No previous error.
-            Script::Handle(Z, Script::null()), TokenPosition::kNoSource,
-            "[InvalidType] in Kernel IR.");
-      }
-      break;
-    case kDynamicType:
-      result_ = Object::dynamic_type().raw();
-      break;
-    case kVoidType:
-      result_ = Object::void_type().raw();
-      break;
-    case kBottomType:
-      result_ =
-          Class::Handle(Z, I->object_store()->null_class()).CanonicalType();
-      break;
-    case kInterfaceType:
-      BuildInterfaceType(false);
-      break;
-    case kSimpleInterfaceType:
-      BuildInterfaceType(true);
-      break;
-    case kFunctionType:
-      BuildFunctionType(false);
-      break;
-    case kSimpleFunctionType:
-      BuildFunctionType(true);
-      break;
-    case kTypeParameterType:
-      BuildTypeParameterType();
-      break;
-    default:
-      helper_->ReportUnexpectedTag("type", tag);
-      UNREACHABLE();
-  }
-}
-
-void TypeTranslator::BuildInterfaceType(bool simple) {
-  // NOTE: That an interface type like `T<A, B>` is considered to be
-  // malformed iff `T` is malformed.
-  //   => We therefore ignore errors in `A` or `B`.
-
-  NameIndex klass_name =
-      helper_->ReadCanonicalNameReference();  // read klass_name.
-
-  intptr_t length;
-  if (simple) {
-    length = 0;
-  } else {
-    length = helper_->ReadListLength();  // read type_arguments list length.
-  }
-  const TypeArguments& type_arguments =
-      BuildTypeArguments(length);  // read type arguments.
-
-  Object& klass = Object::Handle(Z, H.LookupClassByKernelClass(klass_name));
-  result_ = Type::New(klass, type_arguments, TokenPosition::kNoSource);
-  if (finalize_) {
-    ASSERT(active_class_->klass != NULL);
-    result_ = ClassFinalizer::FinalizeType(*active_class_->klass, result_);
-  }
-}
-
-void TypeTranslator::BuildFunctionType(bool simple) {
-  Function& signature_function = Function::ZoneHandle(
-      Z, Function::NewSignatureFunction(*active_class_->klass,
-                                        active_class_->enclosing != NULL
-                                            ? *active_class_->enclosing
-                                            : Function::Handle(Z),
-                                        TokenPosition::kNoSource));
-
-  // Suspend finalization of types inside this one. They will be finalized after
-  // the whole function type is constructed.
-  //
-  // TODO(31213): Test further when nested generic function types
-  // are supported by fasta.
-  bool finalize = finalize_;
-  finalize_ = false;
-
-  if (!simple) {
-    LoadAndSetupTypeParameters(active_class_, signature_function,
-                               helper_->ReadListLength(), signature_function);
-  }
-
-  ActiveTypeParametersScope scope(
-      active_class_, &signature_function,
-      TypeArguments::Handle(Z, signature_function.type_parameters()), Z);
-
-  intptr_t required_count;
-  intptr_t all_count;
-  intptr_t positional_count;
-  if (!simple) {
-    required_count = helper_->ReadUInt();  // read required parameter count.
-    all_count = helper_->ReadUInt();       // read total parameter count.
-    positional_count =
-        helper_->ReadListLength();  // read positional_parameters list length.
-  } else {
-    positional_count =
-        helper_->ReadListLength();  // read positional_parameters list length.
-    required_count = positional_count;
-    all_count = positional_count;
-  }
-
-  const Array& parameter_types =
-      Array::Handle(Z, Array::New(1 + all_count, Heap::kOld));
-  signature_function.set_parameter_types(parameter_types);
-  const Array& parameter_names =
-      Array::Handle(Z, Array::New(1 + all_count, Heap::kOld));
-  signature_function.set_parameter_names(parameter_names);
-
-  intptr_t pos = 0;
-  parameter_types.SetAt(pos, AbstractType::dynamic_type());
-  parameter_names.SetAt(pos, H.DartSymbolPlain("_receiver_"));
-  ++pos;
-  for (intptr_t i = 0; i < positional_count; ++i, ++pos) {
-    BuildTypeInternal();  // read ith positional parameter.
-    if (result_.IsMalformed()) {
-      result_ = AbstractType::dynamic_type().raw();
-    }
-    parameter_types.SetAt(pos, result_);
-    parameter_names.SetAt(pos, H.DartSymbolPlain("noname"));
-  }
-
-  // The additional first parameter is the receiver type (set to dynamic).
-  signature_function.set_num_fixed_parameters(1 + required_count);
-  signature_function.SetNumOptionalParameters(
-      all_count - required_count, positional_count > required_count);
-
-  if (!simple) {
-    const intptr_t named_count =
-        helper_->ReadListLength();  // read named_parameters list length.
-    for (intptr_t i = 0; i < named_count; ++i, ++pos) {
-      // read string reference (i.e. named_parameters[i].name).
-      String& name = H.DartSymbolObfuscate(helper_->ReadStringReference());
-      BuildTypeInternal();  // read named_parameters[i].type.
-      if (result_.IsMalformed()) {
-        result_ = AbstractType::dynamic_type().raw();
-      }
-      parameter_types.SetAt(pos, result_);
-      parameter_names.SetAt(pos, name);
-    }
-  }
-
-  helper_->SkipListOfStrings();  // read positional parameter names.
-
-  if (!simple) {
-    helper_->SkipCanonicalNameReference();  // read typedef reference.
-  }
-
-  BuildTypeInternal();  // read return type.
-  if (result_.IsMalformed()) {
-    result_ = AbstractType::dynamic_type().raw();
-  }
-  signature_function.set_result_type(result_);
-
-  finalize_ = finalize;
-
-  Type& signature_type =
-      Type::ZoneHandle(Z, signature_function.SignatureType());
-
-  if (finalize_) {
-    signature_type ^=
-        ClassFinalizer::FinalizeType(*active_class_->klass, signature_type);
-    // Do not refer to signature_function anymore, since it may have been
-    // replaced during canonicalization.
-    signature_function = Function::null();
-  }
-
-  result_ = signature_type.raw();
-}
-
-void TypeTranslator::BuildTypeParameterType() {
-  intptr_t parameter_index = helper_->ReadUInt();  // read parameter index.
-  helper_->SkipOptionalDartType();                 // read bound.
-
-  const TypeArguments& class_types =
-      TypeArguments::Handle(Z, active_class_->klass->type_parameters());
-  if (parameter_index < class_types.Length()) {
-    // The index of the type parameter in [parameters] is
-    // the same index into the `klass->type_parameters()` array.
-    result_ ^= class_types.TypeAt(parameter_index);
-    return;
-  }
-  parameter_index -= class_types.Length();
-
-  if (active_class_->HasMember()) {
-    if (active_class_->MemberIsFactoryProcedure()) {
-      //
-      // WARNING: This is a little hackish:
-      //
-      // We have a static factory constructor. The kernel IR gives the factory
-      // constructor function its own type parameters (which are equal in name
-      // and number to the ones of the enclosing class). I.e.,
-      //
-      //   class A<T> {
-      //     factory A.x() { return new B<T>(); }
-      //   }
-      //
-      //  is basically translated to this:
-      //
-      //   class A<T> {
-      //     static A.x<T'>() { return new B<T'>(); }
-      //   }
-      //
-      if (class_types.Length() > parameter_index) {
-        result_ ^= class_types.TypeAt(parameter_index);
-        return;
-      }
-      parameter_index -= class_types.Length();
-    }
-
-    intptr_t procedure_type_parameter_count =
-        active_class_->MemberIsProcedure()
-            ? active_class_->MemberTypeParameterCount(Z)
-            : 0;
-    if (procedure_type_parameter_count > 0) {
-      if (procedure_type_parameter_count > parameter_index) {
-        if (I->reify_generic_functions()) {
-          result_ ^=
-              TypeArguments::Handle(Z, active_class_->member->type_parameters())
-                  .TypeAt(parameter_index);
-        } else {
-          result_ ^= Type::DynamicType();
-        }
-        return;
-      }
-      parameter_index -= procedure_type_parameter_count;
-    }
-  }
-
-  if (active_class_->local_type_parameters != NULL) {
-    if (parameter_index < active_class_->local_type_parameters->Length()) {
-      if (I->reify_generic_functions()) {
-        result_ ^=
-            active_class_->local_type_parameters->TypeAt(parameter_index);
-      } else {
-        result_ ^= Type::DynamicType();
-      }
-      return;
-    }
-    parameter_index -= active_class_->local_type_parameters->Length();
-  }
-
-  if (type_parameter_scope_ != NULL &&
-      parameter_index < type_parameter_scope_->outer_parameter_count() +
-                            type_parameter_scope_->parameter_count()) {
-    result_ ^= Type::DynamicType();
-    return;
-  }
-
-  H.ReportError(
-      helper_->script(), TokenPosition::kNoSource,
-      "Unbound type parameter found in %s.  Please report this at dartbug.com.",
-      active_class_->ToCString());
-}
-
-const TypeArguments& TypeTranslator::BuildTypeArguments(intptr_t length) {
-  bool only_dynamic = true;
-  intptr_t offset = helper_->ReaderOffset();
-  for (intptr_t i = 0; i < length; ++i) {
-    if (helper_->ReadTag() != kDynamicType) {  // Read the ith types tag.
-      only_dynamic = false;
-      helper_->SetOffset(offset);
-      break;
-    }
-  }
-  TypeArguments& type_arguments = TypeArguments::ZoneHandle(Z);
-  if (!only_dynamic) {
-    type_arguments = TypeArguments::New(length);
-    for (intptr_t i = 0; i < length; ++i) {
-      BuildTypeInternal(true);  // read ith type.
-      type_arguments.SetTypeAt(i, result_);
-    }
-
-    if (finalize_) {
-      type_arguments = type_arguments.Canonicalize();
-    }
-  }
-  return type_arguments;
-}
-
-const TypeArguments& TypeTranslator::BuildInstantiatedTypeArguments(
-    const Class& receiver_class,
-    intptr_t length) {
-  const TypeArguments& type_arguments = BuildTypeArguments(length);
-
-  // If type_arguments is null all arguments are dynamic.
-  // If, however, this class doesn't specify all the type arguments directly we
-  // still need to finalize the type below in order to get any non-dynamic types
-  // from any super. See http://www.dartbug.com/29537.
-  if (type_arguments.IsNull() && receiver_class.NumTypeArguments() == length) {
-    return type_arguments;
-  }
-
-  // We make a temporary [Type] object and use `ClassFinalizer::FinalizeType` to
-  // finalize the argument types.
-  // (This can for example make the [type_arguments] vector larger)
-  Type& type = Type::Handle(
-      Z, Type::New(receiver_class, type_arguments, TokenPosition::kNoSource));
-  if (finalize_) {
-    type ^= ClassFinalizer::FinalizeType(*active_class_->klass, type);
-  }
-
-  const TypeArguments& instantiated_type_arguments =
-      TypeArguments::ZoneHandle(Z, type.arguments());
-  return instantiated_type_arguments;
-}
-
-void TypeTranslator::LoadAndSetupTypeParameters(
-    ActiveClass* active_class,
-    const Object& set_on,
-    intptr_t type_parameter_count,
-    const Function& parameterized_function) {
-  ASSERT(type_parameter_count >= 0);
-  if (type_parameter_count == 0) {
-    return;
-  }
-  ASSERT(set_on.IsClass() || set_on.IsFunction());
-  bool set_on_class = set_on.IsClass();
-  ASSERT(set_on_class == parameterized_function.IsNull());
-
-  // First setup the type parameters, so if any of the following code uses it
-  // (in a recursive way) we're fine.
-  TypeArguments& type_parameters = TypeArguments::Handle(Z);
-  TypeParameter& parameter = TypeParameter::Handle(Z);
-  const Type& null_bound = Type::Handle(Z);
-
-  // Step a) Create array of [TypeParameter] objects (without bound).
-  type_parameters = TypeArguments::New(type_parameter_count);
-  const Library& lib = Library::Handle(Z, active_class->klass->library());
-  {
-    AlternativeReadingScope alt(&helper_->reader_);
-    for (intptr_t i = 0; i < type_parameter_count; i++) {
-      TypeParameterHelper helper(helper_);
-      helper.Finish();
-      parameter = TypeParameter::New(
-          set_on_class ? *active_class->klass : Class::Handle(Z),
-          parameterized_function, i,
-          H.DartIdentifier(lib, helper.name_index_),  // read ith name index.
-          null_bound, TokenPosition::kNoSource);
-      type_parameters.SetTypeAt(i, parameter);
-    }
-  }
-
-  if (set_on.IsClass()) {
-    Class::Cast(set_on).set_type_parameters(type_parameters);
-  } else {
-    Function::Cast(set_on).set_type_parameters(type_parameters);
-  }
-
-  const Function* enclosing = NULL;
-  if (!parameterized_function.IsNull()) {
-    enclosing = &parameterized_function;
-  }
-  ActiveTypeParametersScope scope(active_class, enclosing, type_parameters, Z);
-
-  // Step b) Fill in the bounds of all [TypeParameter]s.
-  for (intptr_t i = 0; i < type_parameter_count; i++) {
-    TypeParameterHelper helper(helper_);
-    helper.ReadUntilExcludingAndSetJustRead(TypeParameterHelper::kBound);
-
-    // TODO(github.com/dart-lang/kernel/issues/42): This should be handled
-    // by the frontend.
-    parameter ^= type_parameters.TypeAt(i);
-    const Tag tag = helper_->PeekTag();  // peek ith bound type.
-    if (tag == kDynamicType) {
-      helper_->SkipDartType();  // read ith bound.
-      parameter.set_bound(Type::Handle(Z, I->object_store()->object_type()));
-    } else {
-      AbstractType& bound = BuildTypeWithoutFinalization();  // read ith bound.
-      if (bound.IsMalformedOrMalbounded()) {
-        bound = I->object_store()->object_type();
-      }
-      parameter.set_bound(bound);
-    }
-
-    helper.Finish();
-  }
-}
-
-const Type& TypeTranslator::ReceiverType(const Class& klass) {
-  ASSERT(!klass.IsNull());
-  ASSERT(!klass.IsTypedefClass());
-  // Note that if klass is _Closure, the returned type will be _Closure,
-  // and not the signature type.
-  Type& type = Type::ZoneHandle(Z, klass.CanonicalType());
-  if (!type.IsNull()) {
-    return type;
-  }
-  type = Type::New(klass, TypeArguments::Handle(Z, klass.type_parameters()),
-                   klass.token_pos());
-  if (klass.is_type_finalized()) {
-    type ^= ClassFinalizer::FinalizeType(klass, type);
-    klass.SetCanonicalType(type);
-  }
-  return type;
-}
-
 StreamingConstantEvaluator::StreamingConstantEvaluator(
     StreamingFlowGraphBuilder* builder)
     : builder_(builder),
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
index 35f905c..82600d0 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
@@ -7,6 +7,7 @@
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
 
+#include "vm/compiler/frontend/bytecode_reader.h"
 #include "vm/compiler/frontend/kernel_to_il.h"
 #include "vm/compiler/frontend/kernel_translation_helper.h"
 #include "vm/kernel.h"
@@ -16,184 +17,6 @@
 namespace dart {
 namespace kernel {
 
-class TypeTranslator;
-
-struct DirectCallMetadata {
-  DirectCallMetadata(const Function& target, bool check_receiver_for_null)
-      : target_(target), check_receiver_for_null_(check_receiver_for_null) {}
-
-  const Function& target_;
-  const bool check_receiver_for_null_;
-};
-
-// Helper class which provides access to direct call metadata.
-class DirectCallMetadataHelper : public MetadataHelper {
- public:
-  static const char* tag() { return "vm.direct-call.metadata"; }
-
-  explicit DirectCallMetadataHelper(KernelReaderHelper* helper);
-
-  DirectCallMetadata GetDirectTargetForPropertyGet(intptr_t node_offset);
-  DirectCallMetadata GetDirectTargetForPropertySet(intptr_t node_offset);
-  DirectCallMetadata GetDirectTargetForMethodInvocation(intptr_t node_offset);
-
- private:
-  bool ReadMetadata(intptr_t node_offset,
-                    NameIndex* target_name,
-                    bool* check_receiver_for_null);
-};
-
-struct InferredTypeMetadata {
-  InferredTypeMetadata(intptr_t cid_, bool nullable_)
-      : cid(cid_), nullable(nullable_) {}
-
-  const intptr_t cid;
-  const bool nullable;
-
-  bool IsTrivial() const { return (cid == kDynamicCid) && nullable; }
-};
-
-// Helper class which provides access to inferred type metadata.
-class InferredTypeMetadataHelper : public MetadataHelper {
- public:
-  static const char* tag() { return "vm.inferred-type.metadata"; }
-
-  explicit InferredTypeMetadataHelper(KernelReaderHelper* helper);
-
-  InferredTypeMetadata GetInferredType(intptr_t node_offset);
-};
-
-struct ProcedureAttributesMetadata {
-  ProcedureAttributesMetadata(bool has_dynamic_invocations = true,
-                              bool has_non_this_uses = true,
-                              bool has_tearoff_uses = true)
-      : has_dynamic_invocations(has_dynamic_invocations),
-        has_non_this_uses(has_non_this_uses),
-        has_tearoff_uses(has_tearoff_uses) {}
-  bool has_dynamic_invocations;
-  bool has_non_this_uses;
-  bool has_tearoff_uses;
-};
-
-// Helper class which provides access to direct call metadata.
-class ProcedureAttributesMetadataHelper : public MetadataHelper {
- public:
-  static const char* tag() { return "vm.procedure-attributes.metadata"; }
-
-  explicit ProcedureAttributesMetadataHelper(KernelReaderHelper* helper);
-
-  ProcedureAttributesMetadata GetProcedureAttributes(intptr_t node_offset);
-
- private:
-  bool ReadMetadata(intptr_t node_offset,
-                    ProcedureAttributesMetadata* metadata);
-};
-
-#if defined(DART_USE_INTERPRETER)
-
-// Helper class which provides access to bytecode metadata.
-class BytecodeMetadataHelper : public MetadataHelper {
- public:
-  static const char* tag() { return "vm.bytecode"; }
-
-  explicit BytecodeMetadataHelper(KernelReaderHelper* helper,
-                                  TypeTranslator* type_translator,
-                                  ActiveClass* active_class);
-
-  void ReadMetadata(const Function& function);
-
- private:
-  // Returns the index of the last read pool entry.
-  intptr_t ReadPoolEntries(const Function& function,
-                           const Function& inner_function,
-                           const ObjectPool& pool,
-                           intptr_t from_index);
-  RawCode* ReadBytecode(const ObjectPool& pool);
-  void ReadExceptionsTable(const Code& bytecode);
-  RawTypedData* NativeEntry(const Function& function,
-                            const String& external_name);
-
-  TypeTranslator& type_translator_;
-  ActiveClass* const active_class_;
-};
-
-#endif  // defined(DART_USE_INTERPRETER)
-
-class TypeTranslator {
- public:
-  TypeTranslator(KernelReaderHelper* helper,
-                 ActiveClass* active_class,
-                 bool finalize = false);
-
-  // Can return a malformed type.
-  AbstractType& BuildType();
-  // Can return a malformed type.
-  AbstractType& BuildTypeWithoutFinalization();
-  // Is guaranteed to be not malformed.
-  AbstractType& BuildVariableType();
-
-  // Will return `TypeArguments::null()` in case any of the arguments are
-  // malformed.
-  const TypeArguments& BuildTypeArguments(intptr_t length);
-
-  // Will return `TypeArguments::null()` in case any of the arguments are
-  // malformed.
-  const TypeArguments& BuildInstantiatedTypeArguments(
-      const Class& receiver_class,
-      intptr_t length);
-
-  void LoadAndSetupTypeParameters(ActiveClass* active_class,
-                                  const Object& set_on,
-                                  intptr_t type_parameter_count,
-                                  const Function& parameterized_function);
-
-  const Type& ReceiverType(const Class& klass);
-
- private:
-  // Can build a malformed type.
-  void BuildTypeInternal(bool invalid_as_dynamic = false);
-  void BuildInterfaceType(bool simple);
-  void BuildFunctionType(bool simple);
-  void BuildTypeParameterType();
-
-  class TypeParameterScope {
-   public:
-    TypeParameterScope(TypeTranslator* translator, intptr_t parameter_count)
-        : parameter_count_(parameter_count),
-          outer_(translator->type_parameter_scope_),
-          translator_(translator) {
-      outer_parameter_count_ = 0;
-      if (outer_ != NULL) {
-        outer_parameter_count_ =
-            outer_->outer_parameter_count_ + outer_->parameter_count_;
-      }
-      translator_->type_parameter_scope_ = this;
-    }
-    ~TypeParameterScope() { translator_->type_parameter_scope_ = outer_; }
-
-    TypeParameterScope* outer() const { return outer_; }
-    intptr_t parameter_count() const { return parameter_count_; }
-    intptr_t outer_parameter_count() const { return outer_parameter_count_; }
-
-   private:
-    intptr_t parameter_count_;
-    intptr_t outer_parameter_count_;
-    TypeParameterScope* outer_;
-    TypeTranslator* translator_;
-  };
-
-  KernelReaderHelper* helper_;
-  TranslationHelper& translation_helper_;
-  ActiveClass* const active_class_;
-  TypeParameterScope* type_parameter_scope_;
-  Zone* zone_;
-  AbstractType& result_;
-  bool finalize_;
-
-  friend class StreamingScopeBuilder;
-  friend class KernelLoader;
-};
-
 class StreamingScopeBuilder {
  public:
   explicit StreamingScopeBuilder(ParsedFunction* parsed_function);
@@ -919,24 +742,6 @@
   friend class StreamingScopeBuilder;
 };
 
-class AlternativeScriptScope {
- public:
-  AlternativeScriptScope(TranslationHelper* helper,
-                         const Script& new_script,
-                         const Script& old_script)
-      : helper_(helper), old_script_(old_script) {
-    helper_->Reset();
-    helper_->InitFromScript(new_script);
-  }
-  ~AlternativeScriptScope() {
-    helper_->Reset();
-    helper_->InitFromScript(old_script_);
-  }
-
-  TranslationHelper* helper_;
-  const Script& old_script_;
-};
-
 // Helper class that reads a kernel Constant from binary.
 class ConstantHelper {
  public:
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.cc b/runtime/vm/compiler/frontend/kernel_to_il.cc
index 38bfda8..83d8666 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.cc
+++ b/runtime/vm/compiler/frontend/kernel_to_il.cc
@@ -28,67 +28,6 @@
 #define T (type_translator_)
 #define I Isolate::Current()
 
-ActiveTypeParametersScope::ActiveTypeParametersScope(ActiveClass* active_class,
-                                                     const Function& innermost,
-                                                     Zone* Z)
-    : active_class_(active_class), saved_(*active_class) {
-  active_class_->enclosing = &innermost;
-
-  intptr_t num_params = 0;
-
-  Function& f = Function::Handle(Z);
-  TypeArguments& f_params = TypeArguments::Handle(Z);
-  for (f = innermost.raw(); f.parent_function() != Object::null();
-       f = f.parent_function()) {
-    f_params = f.type_parameters();
-    num_params += f_params.Length();
-  }
-  if (num_params == 0) return;
-
-  TypeArguments& params =
-      TypeArguments::Handle(Z, TypeArguments::New(num_params));
-
-  intptr_t index = num_params;
-  for (f = innermost.raw(); f.parent_function() != Object::null();
-       f = f.parent_function()) {
-    f_params = f.type_parameters();
-    for (intptr_t j = f_params.Length() - 1; j >= 0; --j) {
-      params.SetTypeAt(--index, AbstractType::Handle(Z, f_params.TypeAt(j)));
-    }
-  }
-
-  active_class_->local_type_parameters = &params;
-}
-
-ActiveTypeParametersScope::ActiveTypeParametersScope(
-    ActiveClass* active_class,
-    const Function* function,
-    const TypeArguments& new_params,
-    Zone* Z)
-    : active_class_(active_class), saved_(*active_class) {
-  active_class_->enclosing = function;
-
-  if (new_params.IsNull()) return;
-
-  const TypeArguments* old_params = active_class->local_type_parameters;
-  const intptr_t old_param_count =
-      old_params == NULL ? 0 : old_params->Length();
-  const TypeArguments& extended_params = TypeArguments::Handle(
-      Z, TypeArguments::New(old_param_count + new_params.Length()));
-
-  intptr_t index = 0;
-  for (intptr_t i = 0; i < old_param_count; ++i) {
-    extended_params.SetTypeAt(
-        index++, AbstractType::ZoneHandle(Z, old_params->TypeAt(i)));
-  }
-  for (intptr_t i = 0; i < new_params.Length(); ++i) {
-    extended_params.SetTypeAt(
-        index++, AbstractType::ZoneHandle(Z, new_params.TypeAt(i)));
-  }
-
-  active_class_->local_type_parameters = &extended_params;
-}
-
 Fragment& Fragment::operator+=(const Fragment& other) {
   if (entry == NULL) {
     entry = other.entry;
@@ -136,25 +75,6 @@
   return result;
 }
 
-intptr_t ActiveClass::MemberTypeParameterCount(Zone* zone) {
-  ASSERT(member != NULL);
-  if (member->IsFactory()) {
-    TypeArguments& class_types =
-        TypeArguments::Handle(zone, klass->type_parameters());
-    return class_types.Length();
-  } else if (member->IsMethodExtractor()) {
-    Function& extracted =
-        Function::Handle(zone, member->extracted_method_closure());
-    TypeArguments& function_types =
-        TypeArguments::Handle(zone, extracted.type_parameters());
-    return function_types.Length();
-  } else {
-    TypeArguments& function_types =
-        TypeArguments::Handle(zone, member->type_parameters());
-    return function_types.Length();
-  }
-}
-
 FlowGraphBuilder::FlowGraphBuilder(
     intptr_t kernel_offset,
     ParsedFunction* parsed_function,
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.h b/runtime/vm/compiler/frontend/kernel_to_il.h
index a305b30..26defcf 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.h
+++ b/runtime/vm/compiler/frontend/kernel_to_il.h
@@ -201,110 +201,6 @@
 
 typedef ZoneGrowableArray<PushArgumentInstr*>* ArgumentArray;
 
-class ActiveClass {
- public:
-  ActiveClass()
-      : klass(NULL),
-        member(NULL),
-        enclosing(NULL),
-        local_type_parameters(NULL) {}
-
-  bool HasMember() { return member != NULL; }
-
-  bool MemberIsProcedure() {
-    ASSERT(member != NULL);
-    RawFunction::Kind function_kind = member->kind();
-    return function_kind == RawFunction::kRegularFunction ||
-           function_kind == RawFunction::kGetterFunction ||
-           function_kind == RawFunction::kSetterFunction ||
-           function_kind == RawFunction::kMethodExtractor ||
-           function_kind == RawFunction::kDynamicInvocationForwarder ||
-           member->IsFactory();
-  }
-
-  bool MemberIsFactoryProcedure() {
-    ASSERT(member != NULL);
-    return member->IsFactory();
-  }
-
-  intptr_t MemberTypeParameterCount(Zone* zone);
-
-  intptr_t ClassNumTypeArguments() {
-    ASSERT(klass != NULL);
-    return klass->NumTypeArguments();
-  }
-
-  const char* ToCString() {
-    return member != NULL ? member->ToCString() : klass->ToCString();
-  }
-
-  // The current enclosing class (or the library top-level class).
-  const Class* klass;
-
-  const Function* member;
-
-  // The innermost enclosing function. This is used for building types, as a
-  // parent for function types.
-  const Function* enclosing;
-
-  const TypeArguments* local_type_parameters;
-};
-
-class ActiveClassScope {
- public:
-  ActiveClassScope(ActiveClass* active_class, const Class* klass)
-      : active_class_(active_class), saved_(*active_class) {
-    active_class_->klass = klass;
-  }
-
-  ~ActiveClassScope() { *active_class_ = saved_; }
-
- private:
-  ActiveClass* active_class_;
-  ActiveClass saved_;
-};
-
-class ActiveMemberScope {
- public:
-  ActiveMemberScope(ActiveClass* active_class, const Function* member)
-      : active_class_(active_class), saved_(*active_class) {
-    // The class is inherited.
-    active_class_->member = member;
-  }
-
-  ~ActiveMemberScope() { *active_class_ = saved_; }
-
- private:
-  ActiveClass* active_class_;
-  ActiveClass saved_;
-};
-
-class ActiveTypeParametersScope {
- public:
-  // Set the local type parameters of the ActiveClass to be exactly all type
-  // parameters defined by 'innermost' and any enclosing *closures* (but not
-  // enclosing methods/top-level functions/classes).
-  //
-  // Also, the enclosing function is set to 'innermost'.
-  ActiveTypeParametersScope(ActiveClass* active_class,
-                            const Function& innermost,
-                            Zone* Z);
-
-  // Append the list of the local type parameters to the list in ActiveClass.
-  //
-  // Also, the enclosing function is set to 'function'.
-  ActiveTypeParametersScope(ActiveClass* active_class,
-                            const Function* function,
-                            const TypeArguments& new_params,
-                            Zone* Z);
-
-  ~ActiveTypeParametersScope() { *active_class_ = saved_; }
-
- private:
-  ActiveClass* active_class_;
-  ActiveClass saved_;
-};
-
 struct FunctionScope {
   intptr_t kernel_offset;
   LocalScope* scope;
diff --git a/runtime/vm/compiler/frontend/kernel_translation_helper.cc b/runtime/vm/compiler/frontend/kernel_translation_helper.cc
index 2c963ac..59b1acc 100644
--- a/runtime/vm/compiler/frontend/kernel_translation_helper.cc
+++ b/runtime/vm/compiler/frontend/kernel_translation_helper.cc
@@ -7,6 +7,7 @@
 #include "vm/class_finalizer.h"
 #include "vm/compiler/aot/precompiler.h"
 #include "vm/log.h"
+#include "vm/object_store.h"
 #include "vm/symbols.h"
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
@@ -1499,6 +1500,153 @@
   }
 }
 
+DirectCallMetadataHelper::DirectCallMetadataHelper(KernelReaderHelper* helper)
+    : MetadataHelper(helper, tag(), /* precompiler_only = */ true) {}
+
+bool DirectCallMetadataHelper::ReadMetadata(intptr_t node_offset,
+                                            NameIndex* target_name,
+                                            bool* check_receiver_for_null) {
+  intptr_t md_offset = GetNextMetadataPayloadOffset(node_offset);
+  if (md_offset < 0) {
+    return false;
+  }
+
+  AlternativeReadingScope alt(&helper_->reader_, &H.metadata_payloads(),
+                              md_offset);
+
+  *target_name = helper_->ReadCanonicalNameReference();
+  *check_receiver_for_null = helper_->ReadBool();
+  return true;
+}
+
+DirectCallMetadata DirectCallMetadataHelper::GetDirectTargetForPropertyGet(
+    intptr_t node_offset) {
+  NameIndex kernel_name;
+  bool check_receiver_for_null = false;
+  if (!ReadMetadata(node_offset, &kernel_name, &check_receiver_for_null)) {
+    return DirectCallMetadata(Function::null_function(), false);
+  }
+
+  if (H.IsProcedure(kernel_name) && !H.IsGetter(kernel_name)) {
+    // Tear-off. Use method extractor as direct call target.
+    const String& method_name = H.DartMethodName(kernel_name);
+    const Function& target_method = Function::ZoneHandle(
+        helper_->zone_, H.LookupMethodByMember(kernel_name, method_name));
+    const String& getter_name = H.DartGetterName(kernel_name);
+    return DirectCallMetadata(
+        Function::ZoneHandle(helper_->zone_,
+                             target_method.GetMethodExtractor(getter_name)),
+        check_receiver_for_null);
+  } else {
+    const String& getter_name = H.DartGetterName(kernel_name);
+    const Function& target = Function::ZoneHandle(
+        helper_->zone_, H.LookupMethodByMember(kernel_name, getter_name));
+    ASSERT(target.IsGetterFunction() || target.IsImplicitGetterFunction());
+    return DirectCallMetadata(target, check_receiver_for_null);
+  }
+}
+
+DirectCallMetadata DirectCallMetadataHelper::GetDirectTargetForPropertySet(
+    intptr_t node_offset) {
+  NameIndex kernel_name;
+  bool check_receiver_for_null = false;
+  if (!ReadMetadata(node_offset, &kernel_name, &check_receiver_for_null)) {
+    return DirectCallMetadata(Function::null_function(), false);
+  }
+
+  const String& method_name = H.DartSetterName(kernel_name);
+  const Function& target = Function::ZoneHandle(
+      helper_->zone_, H.LookupMethodByMember(kernel_name, method_name));
+  ASSERT(target.IsSetterFunction() || target.IsImplicitSetterFunction());
+
+  return DirectCallMetadata(target, check_receiver_for_null);
+}
+
+DirectCallMetadata DirectCallMetadataHelper::GetDirectTargetForMethodInvocation(
+    intptr_t node_offset) {
+  NameIndex kernel_name;
+  bool check_receiver_for_null = false;
+  if (!ReadMetadata(node_offset, &kernel_name, &check_receiver_for_null)) {
+    return DirectCallMetadata(Function::null_function(), false);
+  }
+
+  const String& method_name = H.DartProcedureName(kernel_name);
+  const Function& target = Function::ZoneHandle(
+      helper_->zone_, H.LookupMethodByMember(kernel_name, method_name));
+
+  return DirectCallMetadata(target, check_receiver_for_null);
+}
+
+InferredTypeMetadataHelper::InferredTypeMetadataHelper(
+    KernelReaderHelper* helper)
+    : MetadataHelper(helper, tag(), /* precompiler_only = */ true) {}
+
+InferredTypeMetadata InferredTypeMetadataHelper::GetInferredType(
+    intptr_t node_offset) {
+  const intptr_t md_offset = GetNextMetadataPayloadOffset(node_offset);
+  if (md_offset < 0) {
+    return InferredTypeMetadata(kDynamicCid, true);
+  }
+
+  AlternativeReadingScope alt(&helper_->reader_, &H.metadata_payloads(),
+                              md_offset);
+
+  const NameIndex kernel_name = helper_->ReadCanonicalNameReference();
+  const bool nullable = helper_->ReadBool();
+
+  if (H.IsRoot(kernel_name)) {
+    return InferredTypeMetadata(kDynamicCid, nullable);
+  }
+
+  const Class& klass =
+      Class::Handle(helper_->zone_, H.LookupClassByKernelClass(kernel_name));
+  ASSERT(!klass.IsNull());
+
+  intptr_t cid = klass.id();
+  if (cid == kClosureCid) {
+    // VM uses more specific function types and doesn't expect instances of
+    // _Closure class, so inferred _Closure class doesn't make sense for the VM.
+    cid = kDynamicCid;
+  }
+
+  return InferredTypeMetadata(cid, nullable);
+}
+
+ProcedureAttributesMetadataHelper::ProcedureAttributesMetadataHelper(
+    KernelReaderHelper* helper)
+    : MetadataHelper(helper, tag(), /* precompiler_only = */ true) {}
+
+bool ProcedureAttributesMetadataHelper::ReadMetadata(
+    intptr_t node_offset,
+    ProcedureAttributesMetadata* metadata) {
+  intptr_t md_offset = GetNextMetadataPayloadOffset(node_offset);
+  if (md_offset < 0) {
+    return false;
+  }
+
+  AlternativeReadingScope alt(&helper_->reader_, &H.metadata_payloads(),
+                              md_offset);
+
+  const int kDynamicUsesBit = 1 << 0;
+  const int kNonThisUsesBit = 1 << 1;
+  const int kTearOffUsesBit = 1 << 2;
+
+  const uint8_t flags = helper_->ReadByte();
+  metadata->has_dynamic_invocations =
+      (flags & kDynamicUsesBit) == kDynamicUsesBit;
+  metadata->has_non_this_uses = (flags & kNonThisUsesBit) == kNonThisUsesBit;
+  metadata->has_tearoff_uses = (flags & kTearOffUsesBit) == kTearOffUsesBit;
+  return true;
+}
+
+ProcedureAttributesMetadata
+ProcedureAttributesMetadataHelper::GetProcedureAttributes(
+    intptr_t node_offset) {
+  ProcedureAttributesMetadata metadata;
+  ReadMetadata(node_offset, &metadata);
+  return metadata;
+}
+
 intptr_t KernelReaderHelper::ReaderOffset() const {
   return reader_.offset();
 }
@@ -2199,6 +2347,536 @@
   return position;
 }
 
+intptr_t ActiveClass::MemberTypeParameterCount(Zone* zone) {
+  ASSERT(member != NULL);
+  if (member->IsFactory()) {
+    TypeArguments& class_types =
+        TypeArguments::Handle(zone, klass->type_parameters());
+    return class_types.Length();
+  } else if (member->IsMethodExtractor()) {
+    Function& extracted =
+        Function::Handle(zone, member->extracted_method_closure());
+    TypeArguments& function_types =
+        TypeArguments::Handle(zone, extracted.type_parameters());
+    return function_types.Length();
+  } else {
+    TypeArguments& function_types =
+        TypeArguments::Handle(zone, member->type_parameters());
+    return function_types.Length();
+  }
+}
+
+ActiveTypeParametersScope::ActiveTypeParametersScope(ActiveClass* active_class,
+                                                     const Function& innermost,
+                                                     Zone* Z)
+    : active_class_(active_class), saved_(*active_class) {
+  active_class_->enclosing = &innermost;
+
+  intptr_t num_params = 0;
+
+  Function& f = Function::Handle(Z);
+  TypeArguments& f_params = TypeArguments::Handle(Z);
+  for (f = innermost.raw(); f.parent_function() != Object::null();
+       f = f.parent_function()) {
+    f_params = f.type_parameters();
+    num_params += f_params.Length();
+  }
+  if (num_params == 0) return;
+
+  TypeArguments& params =
+      TypeArguments::Handle(Z, TypeArguments::New(num_params));
+
+  intptr_t index = num_params;
+  for (f = innermost.raw(); f.parent_function() != Object::null();
+       f = f.parent_function()) {
+    f_params = f.type_parameters();
+    for (intptr_t j = f_params.Length() - 1; j >= 0; --j) {
+      params.SetTypeAt(--index, AbstractType::Handle(Z, f_params.TypeAt(j)));
+    }
+  }
+
+  active_class_->local_type_parameters = &params;
+}
+
+ActiveTypeParametersScope::ActiveTypeParametersScope(
+    ActiveClass* active_class,
+    const Function* function,
+    const TypeArguments& new_params,
+    Zone* Z)
+    : active_class_(active_class), saved_(*active_class) {
+  active_class_->enclosing = function;
+
+  if (new_params.IsNull()) return;
+
+  const TypeArguments* old_params = active_class->local_type_parameters;
+  const intptr_t old_param_count =
+      old_params == NULL ? 0 : old_params->Length();
+  const TypeArguments& extended_params = TypeArguments::Handle(
+      Z, TypeArguments::New(old_param_count + new_params.Length()));
+
+  intptr_t index = 0;
+  for (intptr_t i = 0; i < old_param_count; ++i) {
+    extended_params.SetTypeAt(
+        index++, AbstractType::ZoneHandle(Z, old_params->TypeAt(i)));
+  }
+  for (intptr_t i = 0; i < new_params.Length(); ++i) {
+    extended_params.SetTypeAt(
+        index++, AbstractType::ZoneHandle(Z, new_params.TypeAt(i)));
+  }
+
+  active_class_->local_type_parameters = &extended_params;
+}
+
+TypeTranslator::TypeTranslator(KernelReaderHelper* helper,
+                               ActiveClass* active_class,
+                               bool finalize)
+    : helper_(helper),
+      translation_helper_(helper->translation_helper_),
+      active_class_(active_class),
+      type_parameter_scope_(NULL),
+      zone_(translation_helper_.zone()),
+      result_(AbstractType::Handle(translation_helper_.zone())),
+      finalize_(finalize) {}
+
+AbstractType& TypeTranslator::BuildType() {
+  BuildTypeInternal();
+
+  // We return a new `ZoneHandle` here on purpose: The intermediate language
+  // instructions do not make a copy of the handle, so we do it.
+  return AbstractType::ZoneHandle(Z, result_.raw());
+}
+
+AbstractType& TypeTranslator::BuildTypeWithoutFinalization() {
+  bool saved_finalize = finalize_;
+  finalize_ = false;
+  BuildTypeInternal();
+  finalize_ = saved_finalize;
+
+  // We return a new `ZoneHandle` here on purpose: The intermediate language
+  // instructions do not make a copy of the handle, so we do it.
+  return AbstractType::ZoneHandle(Z, result_.raw());
+}
+
+AbstractType& TypeTranslator::BuildVariableType() {
+  AbstractType& abstract_type = BuildType();
+
+  // We return a new `ZoneHandle` here on purpose: The intermediate language
+  // instructions do not make a copy of the handle, so we do it.
+  AbstractType& type = Type::ZoneHandle(Z);
+
+  if (abstract_type.IsMalformed()) {
+    type = AbstractType::dynamic_type().raw();
+  } else {
+    type = result_.raw();
+  }
+
+  return type;
+}
+
+void TypeTranslator::BuildTypeInternal(bool invalid_as_dynamic) {
+  Tag tag = helper_->ReadTag();
+  switch (tag) {
+    case kInvalidType:
+      if (invalid_as_dynamic) {
+        result_ = Object::dynamic_type().raw();
+      } else {
+        result_ = ClassFinalizer::NewFinalizedMalformedType(
+            Error::Handle(Z),  // No previous error.
+            Script::Handle(Z, Script::null()), TokenPosition::kNoSource,
+            "[InvalidType] in Kernel IR.");
+      }
+      break;
+    case kDynamicType:
+      result_ = Object::dynamic_type().raw();
+      break;
+    case kVoidType:
+      result_ = Object::void_type().raw();
+      break;
+    case kBottomType:
+      result_ =
+          Class::Handle(Z, I->object_store()->null_class()).CanonicalType();
+      break;
+    case kInterfaceType:
+      BuildInterfaceType(false);
+      break;
+    case kSimpleInterfaceType:
+      BuildInterfaceType(true);
+      break;
+    case kFunctionType:
+      BuildFunctionType(false);
+      break;
+    case kSimpleFunctionType:
+      BuildFunctionType(true);
+      break;
+    case kTypeParameterType:
+      BuildTypeParameterType();
+      break;
+    default:
+      helper_->ReportUnexpectedTag("type", tag);
+      UNREACHABLE();
+  }
+}
+
+void TypeTranslator::BuildInterfaceType(bool simple) {
+  // NOTE: That an interface type like `T<A, B>` is considered to be
+  // malformed iff `T` is malformed.
+  //   => We therefore ignore errors in `A` or `B`.
+
+  NameIndex klass_name =
+      helper_->ReadCanonicalNameReference();  // read klass_name.
+
+  intptr_t length;
+  if (simple) {
+    length = 0;
+  } else {
+    length = helper_->ReadListLength();  // read type_arguments list length.
+  }
+  const TypeArguments& type_arguments =
+      BuildTypeArguments(length);  // read type arguments.
+
+  Object& klass = Object::Handle(Z, H.LookupClassByKernelClass(klass_name));
+  result_ = Type::New(klass, type_arguments, TokenPosition::kNoSource);
+  if (finalize_) {
+    ASSERT(active_class_->klass != NULL);
+    result_ = ClassFinalizer::FinalizeType(*active_class_->klass, result_);
+  }
+}
+
+void TypeTranslator::BuildFunctionType(bool simple) {
+  Function& signature_function = Function::ZoneHandle(
+      Z, Function::NewSignatureFunction(*active_class_->klass,
+                                        active_class_->enclosing != NULL
+                                            ? *active_class_->enclosing
+                                            : Function::Handle(Z),
+                                        TokenPosition::kNoSource));
+
+  // Suspend finalization of types inside this one. They will be finalized after
+  // the whole function type is constructed.
+  //
+  // TODO(31213): Test further when nested generic function types
+  // are supported by fasta.
+  bool finalize = finalize_;
+  finalize_ = false;
+
+  if (!simple) {
+    LoadAndSetupTypeParameters(active_class_, signature_function,
+                               helper_->ReadListLength(), signature_function);
+  }
+
+  ActiveTypeParametersScope scope(
+      active_class_, &signature_function,
+      TypeArguments::Handle(Z, signature_function.type_parameters()), Z);
+
+  intptr_t required_count;
+  intptr_t all_count;
+  intptr_t positional_count;
+  if (!simple) {
+    required_count = helper_->ReadUInt();  // read required parameter count.
+    all_count = helper_->ReadUInt();       // read total parameter count.
+    positional_count =
+        helper_->ReadListLength();  // read positional_parameters list length.
+  } else {
+    positional_count =
+        helper_->ReadListLength();  // read positional_parameters list length.
+    required_count = positional_count;
+    all_count = positional_count;
+  }
+
+  const Array& parameter_types =
+      Array::Handle(Z, Array::New(1 + all_count, Heap::kOld));
+  signature_function.set_parameter_types(parameter_types);
+  const Array& parameter_names =
+      Array::Handle(Z, Array::New(1 + all_count, Heap::kOld));
+  signature_function.set_parameter_names(parameter_names);
+
+  intptr_t pos = 0;
+  parameter_types.SetAt(pos, AbstractType::dynamic_type());
+  parameter_names.SetAt(pos, H.DartSymbolPlain("_receiver_"));
+  ++pos;
+  for (intptr_t i = 0; i < positional_count; ++i, ++pos) {
+    BuildTypeInternal();  // read ith positional parameter.
+    if (result_.IsMalformed()) {
+      result_ = AbstractType::dynamic_type().raw();
+    }
+    parameter_types.SetAt(pos, result_);
+    parameter_names.SetAt(pos, H.DartSymbolPlain("noname"));
+  }
+
+  // The additional first parameter is the receiver type (set to dynamic).
+  signature_function.set_num_fixed_parameters(1 + required_count);
+  signature_function.SetNumOptionalParameters(
+      all_count - required_count, positional_count > required_count);
+
+  if (!simple) {
+    const intptr_t named_count =
+        helper_->ReadListLength();  // read named_parameters list length.
+    for (intptr_t i = 0; i < named_count; ++i, ++pos) {
+      // read string reference (i.e. named_parameters[i].name).
+      String& name = H.DartSymbolObfuscate(helper_->ReadStringReference());
+      BuildTypeInternal();  // read named_parameters[i].type.
+      if (result_.IsMalformed()) {
+        result_ = AbstractType::dynamic_type().raw();
+      }
+      parameter_types.SetAt(pos, result_);
+      parameter_names.SetAt(pos, name);
+    }
+  }
+
+  helper_->SkipListOfStrings();  // read positional parameter names.
+
+  if (!simple) {
+    helper_->SkipCanonicalNameReference();  // read typedef reference.
+  }
+
+  BuildTypeInternal();  // read return type.
+  if (result_.IsMalformed()) {
+    result_ = AbstractType::dynamic_type().raw();
+  }
+  signature_function.set_result_type(result_);
+
+  finalize_ = finalize;
+
+  Type& signature_type =
+      Type::ZoneHandle(Z, signature_function.SignatureType());
+
+  if (finalize_) {
+    signature_type ^=
+        ClassFinalizer::FinalizeType(*active_class_->klass, signature_type);
+    // Do not refer to signature_function anymore, since it may have been
+    // replaced during canonicalization.
+    signature_function = Function::null();
+  }
+
+  result_ = signature_type.raw();
+}
+
+void TypeTranslator::BuildTypeParameterType() {
+  intptr_t parameter_index = helper_->ReadUInt();  // read parameter index.
+  helper_->SkipOptionalDartType();                 // read bound.
+
+  const TypeArguments& class_types =
+      TypeArguments::Handle(Z, active_class_->klass->type_parameters());
+  if (parameter_index < class_types.Length()) {
+    // The index of the type parameter in [parameters] is
+    // the same index into the `klass->type_parameters()` array.
+    result_ ^= class_types.TypeAt(parameter_index);
+    return;
+  }
+  parameter_index -= class_types.Length();
+
+  if (active_class_->HasMember()) {
+    if (active_class_->MemberIsFactoryProcedure()) {
+      //
+      // WARNING: This is a little hackish:
+      //
+      // We have a static factory constructor. The kernel IR gives the factory
+      // constructor function its own type parameters (which are equal in name
+      // and number to the ones of the enclosing class). I.e.,
+      //
+      //   class A<T> {
+      //     factory A.x() { return new B<T>(); }
+      //   }
+      //
+      //  is basically translated to this:
+      //
+      //   class A<T> {
+      //     static A.x<T'>() { return new B<T'>(); }
+      //   }
+      //
+      if (class_types.Length() > parameter_index) {
+        result_ ^= class_types.TypeAt(parameter_index);
+        return;
+      }
+      parameter_index -= class_types.Length();
+    }
+
+    intptr_t procedure_type_parameter_count =
+        active_class_->MemberIsProcedure()
+            ? active_class_->MemberTypeParameterCount(Z)
+            : 0;
+    if (procedure_type_parameter_count > 0) {
+      if (procedure_type_parameter_count > parameter_index) {
+        if (I->reify_generic_functions()) {
+          result_ ^=
+              TypeArguments::Handle(Z, active_class_->member->type_parameters())
+                  .TypeAt(parameter_index);
+        } else {
+          result_ ^= Type::DynamicType();
+        }
+        return;
+      }
+      parameter_index -= procedure_type_parameter_count;
+    }
+  }
+
+  if (active_class_->local_type_parameters != NULL) {
+    if (parameter_index < active_class_->local_type_parameters->Length()) {
+      if (I->reify_generic_functions()) {
+        result_ ^=
+            active_class_->local_type_parameters->TypeAt(parameter_index);
+      } else {
+        result_ ^= Type::DynamicType();
+      }
+      return;
+    }
+    parameter_index -= active_class_->local_type_parameters->Length();
+  }
+
+  if (type_parameter_scope_ != NULL &&
+      parameter_index < type_parameter_scope_->outer_parameter_count() +
+                            type_parameter_scope_->parameter_count()) {
+    result_ ^= Type::DynamicType();
+    return;
+  }
+
+  H.ReportError(
+      helper_->script(), TokenPosition::kNoSource,
+      "Unbound type parameter found in %s.  Please report this at dartbug.com.",
+      active_class_->ToCString());
+}
+
+const TypeArguments& TypeTranslator::BuildTypeArguments(intptr_t length) {
+  bool only_dynamic = true;
+  intptr_t offset = helper_->ReaderOffset();
+  for (intptr_t i = 0; i < length; ++i) {
+    if (helper_->ReadTag() != kDynamicType) {  // Read the ith types tag.
+      only_dynamic = false;
+      helper_->SetOffset(offset);
+      break;
+    }
+  }
+  TypeArguments& type_arguments = TypeArguments::ZoneHandle(Z);
+  if (!only_dynamic) {
+    type_arguments = TypeArguments::New(length);
+    for (intptr_t i = 0; i < length; ++i) {
+      BuildTypeInternal(true);  // read ith type.
+      type_arguments.SetTypeAt(i, result_);
+    }
+
+    if (finalize_) {
+      type_arguments = type_arguments.Canonicalize();
+    }
+  }
+  return type_arguments;
+}
+
+const TypeArguments& TypeTranslator::BuildInstantiatedTypeArguments(
+    const Class& receiver_class,
+    intptr_t length) {
+  const TypeArguments& type_arguments = BuildTypeArguments(length);
+
+  // If type_arguments is null all arguments are dynamic.
+  // If, however, this class doesn't specify all the type arguments directly we
+  // still need to finalize the type below in order to get any non-dynamic types
+  // from any super. See http://www.dartbug.com/29537.
+  if (type_arguments.IsNull() && receiver_class.NumTypeArguments() == length) {
+    return type_arguments;
+  }
+
+  // We make a temporary [Type] object and use `ClassFinalizer::FinalizeType` to
+  // finalize the argument types.
+  // (This can for example make the [type_arguments] vector larger)
+  Type& type = Type::Handle(
+      Z, Type::New(receiver_class, type_arguments, TokenPosition::kNoSource));
+  if (finalize_) {
+    type ^= ClassFinalizer::FinalizeType(*active_class_->klass, type);
+  }
+
+  const TypeArguments& instantiated_type_arguments =
+      TypeArguments::ZoneHandle(Z, type.arguments());
+  return instantiated_type_arguments;
+}
+
+void TypeTranslator::LoadAndSetupTypeParameters(
+    ActiveClass* active_class,
+    const Object& set_on,
+    intptr_t type_parameter_count,
+    const Function& parameterized_function) {
+  ASSERT(type_parameter_count >= 0);
+  if (type_parameter_count == 0) {
+    return;
+  }
+  ASSERT(set_on.IsClass() || set_on.IsFunction());
+  bool set_on_class = set_on.IsClass();
+  ASSERT(set_on_class == parameterized_function.IsNull());
+
+  // First setup the type parameters, so if any of the following code uses it
+  // (in a recursive way) we're fine.
+  TypeArguments& type_parameters = TypeArguments::Handle(Z);
+  TypeParameter& parameter = TypeParameter::Handle(Z);
+  const Type& null_bound = Type::Handle(Z);
+
+  // Step a) Create array of [TypeParameter] objects (without bound).
+  type_parameters = TypeArguments::New(type_parameter_count);
+  const Library& lib = Library::Handle(Z, active_class->klass->library());
+  {
+    AlternativeReadingScope alt(&helper_->reader_);
+    for (intptr_t i = 0; i < type_parameter_count; i++) {
+      TypeParameterHelper helper(helper_);
+      helper.Finish();
+      parameter = TypeParameter::New(
+          set_on_class ? *active_class->klass : Class::Handle(Z),
+          parameterized_function, i,
+          H.DartIdentifier(lib, helper.name_index_),  // read ith name index.
+          null_bound, TokenPosition::kNoSource);
+      type_parameters.SetTypeAt(i, parameter);
+    }
+  }
+
+  if (set_on.IsClass()) {
+    Class::Cast(set_on).set_type_parameters(type_parameters);
+  } else {
+    Function::Cast(set_on).set_type_parameters(type_parameters);
+  }
+
+  const Function* enclosing = NULL;
+  if (!parameterized_function.IsNull()) {
+    enclosing = &parameterized_function;
+  }
+  ActiveTypeParametersScope scope(active_class, enclosing, type_parameters, Z);
+
+  // Step b) Fill in the bounds of all [TypeParameter]s.
+  for (intptr_t i = 0; i < type_parameter_count; i++) {
+    TypeParameterHelper helper(helper_);
+    helper.ReadUntilExcludingAndSetJustRead(TypeParameterHelper::kBound);
+
+    // TODO(github.com/dart-lang/kernel/issues/42): This should be handled
+    // by the frontend.
+    parameter ^= type_parameters.TypeAt(i);
+    const Tag tag = helper_->PeekTag();  // peek ith bound type.
+    if (tag == kDynamicType) {
+      helper_->SkipDartType();  // read ith bound.
+      parameter.set_bound(Type::Handle(Z, I->object_store()->object_type()));
+    } else {
+      AbstractType& bound = BuildTypeWithoutFinalization();  // read ith bound.
+      if (bound.IsMalformedOrMalbounded()) {
+        bound = I->object_store()->object_type();
+      }
+      parameter.set_bound(bound);
+    }
+
+    helper.Finish();
+  }
+}
+
+const Type& TypeTranslator::ReceiverType(const Class& klass) {
+  ASSERT(!klass.IsNull());
+  ASSERT(!klass.IsTypedefClass());
+  // Note that if klass is _Closure, the returned type will be _Closure,
+  // and not the signature type.
+  Type& type = Type::ZoneHandle(Z, klass.CanonicalType());
+  if (!type.IsNull()) {
+    return type;
+  }
+  type = Type::New(klass, TypeArguments::Handle(Z, klass.type_parameters()),
+                   klass.token_pos());
+  if (klass.is_type_finalized()) {
+    type ^= ClassFinalizer::FinalizeType(klass, type);
+    klass.SetCanonicalType(type);
+  }
+  return type;
+}
+
 }  // namespace kernel
 }  // namespace dart
 
diff --git a/runtime/vm/compiler/frontend/kernel_translation_helper.h b/runtime/vm/compiler/frontend/kernel_translation_helper.h
index 75d4566..6964154 100644
--- a/runtime/vm/compiler/frontend/kernel_translation_helper.h
+++ b/runtime/vm/compiler/frontend/kernel_translation_helper.h
@@ -778,6 +778,77 @@
   intptr_t last_mapping_index_;
 };
 
+struct DirectCallMetadata {
+  DirectCallMetadata(const Function& target, bool check_receiver_for_null)
+      : target_(target), check_receiver_for_null_(check_receiver_for_null) {}
+
+  const Function& target_;
+  const bool check_receiver_for_null_;
+};
+
+// Helper class which provides access to direct call metadata.
+class DirectCallMetadataHelper : public MetadataHelper {
+ public:
+  static const char* tag() { return "vm.direct-call.metadata"; }
+
+  explicit DirectCallMetadataHelper(KernelReaderHelper* helper);
+
+  DirectCallMetadata GetDirectTargetForPropertyGet(intptr_t node_offset);
+  DirectCallMetadata GetDirectTargetForPropertySet(intptr_t node_offset);
+  DirectCallMetadata GetDirectTargetForMethodInvocation(intptr_t node_offset);
+
+ private:
+  bool ReadMetadata(intptr_t node_offset,
+                    NameIndex* target_name,
+                    bool* check_receiver_for_null);
+};
+
+struct InferredTypeMetadata {
+  InferredTypeMetadata(intptr_t cid_, bool nullable_)
+      : cid(cid_), nullable(nullable_) {}
+
+  const intptr_t cid;
+  const bool nullable;
+
+  bool IsTrivial() const { return (cid == kDynamicCid) && nullable; }
+};
+
+// Helper class which provides access to inferred type metadata.
+class InferredTypeMetadataHelper : public MetadataHelper {
+ public:
+  static const char* tag() { return "vm.inferred-type.metadata"; }
+
+  explicit InferredTypeMetadataHelper(KernelReaderHelper* helper);
+
+  InferredTypeMetadata GetInferredType(intptr_t node_offset);
+};
+
+struct ProcedureAttributesMetadata {
+  ProcedureAttributesMetadata(bool has_dynamic_invocations = true,
+                              bool has_non_this_uses = true,
+                              bool has_tearoff_uses = true)
+      : has_dynamic_invocations(has_dynamic_invocations),
+        has_non_this_uses(has_non_this_uses),
+        has_tearoff_uses(has_tearoff_uses) {}
+  bool has_dynamic_invocations;
+  bool has_non_this_uses;
+  bool has_tearoff_uses;
+};
+
+// Helper class which provides access to direct call metadata.
+class ProcedureAttributesMetadataHelper : public MetadataHelper {
+ public:
+  static const char* tag() { return "vm.procedure-attributes.metadata"; }
+
+  explicit ProcedureAttributesMetadataHelper(KernelReaderHelper* helper);
+
+  ProcedureAttributesMetadata GetProcedureAttributes(intptr_t node_offset);
+
+ private:
+  bool ReadMetadata(intptr_t node_offset,
+                    ProcedureAttributesMetadata* metadata);
+};
+
 class KernelReaderHelper {
  public:
   KernelReaderHelper(Zone* zone,
@@ -910,6 +981,185 @@
 #endif  // defined(DART_USE_INTERPRETER)
 };
 
+class ActiveClass {
+ public:
+  ActiveClass()
+      : klass(NULL),
+        member(NULL),
+        enclosing(NULL),
+        local_type_parameters(NULL) {}
+
+  bool HasMember() { return member != NULL; }
+
+  bool MemberIsProcedure() {
+    ASSERT(member != NULL);
+    RawFunction::Kind function_kind = member->kind();
+    return function_kind == RawFunction::kRegularFunction ||
+           function_kind == RawFunction::kGetterFunction ||
+           function_kind == RawFunction::kSetterFunction ||
+           function_kind == RawFunction::kMethodExtractor ||
+           function_kind == RawFunction::kDynamicInvocationForwarder ||
+           member->IsFactory();
+  }
+
+  bool MemberIsFactoryProcedure() {
+    ASSERT(member != NULL);
+    return member->IsFactory();
+  }
+
+  intptr_t MemberTypeParameterCount(Zone* zone);
+
+  intptr_t ClassNumTypeArguments() {
+    ASSERT(klass != NULL);
+    return klass->NumTypeArguments();
+  }
+
+  const char* ToCString() {
+    return member != NULL ? member->ToCString() : klass->ToCString();
+  }
+
+  // The current enclosing class (or the library top-level class).
+  const Class* klass;
+
+  const Function* member;
+
+  // The innermost enclosing function. This is used for building types, as a
+  // parent for function types.
+  const Function* enclosing;
+
+  const TypeArguments* local_type_parameters;
+};
+
+class ActiveClassScope {
+ public:
+  ActiveClassScope(ActiveClass* active_class, const Class* klass)
+      : active_class_(active_class), saved_(*active_class) {
+    active_class_->klass = klass;
+  }
+
+  ~ActiveClassScope() { *active_class_ = saved_; }
+
+ private:
+  ActiveClass* active_class_;
+  ActiveClass saved_;
+};
+
+class ActiveMemberScope {
+ public:
+  ActiveMemberScope(ActiveClass* active_class, const Function* member)
+      : active_class_(active_class), saved_(*active_class) {
+    // The class is inherited.
+    active_class_->member = member;
+  }
+
+  ~ActiveMemberScope() { *active_class_ = saved_; }
+
+ private:
+  ActiveClass* active_class_;
+  ActiveClass saved_;
+};
+
+class ActiveTypeParametersScope {
+ public:
+  // Set the local type parameters of the ActiveClass to be exactly all type
+  // parameters defined by 'innermost' and any enclosing *closures* (but not
+  // enclosing methods/top-level functions/classes).
+  //
+  // Also, the enclosing function is set to 'innermost'.
+  ActiveTypeParametersScope(ActiveClass* active_class,
+                            const Function& innermost,
+                            Zone* Z);
+
+  // Append the list of the local type parameters to the list in ActiveClass.
+  //
+  // Also, the enclosing function is set to 'function'.
+  ActiveTypeParametersScope(ActiveClass* active_class,
+                            const Function* function,
+                            const TypeArguments& new_params,
+                            Zone* Z);
+
+  ~ActiveTypeParametersScope() { *active_class_ = saved_; }
+
+ private:
+  ActiveClass* active_class_;
+  ActiveClass saved_;
+};
+
+class TypeTranslator {
+ public:
+  TypeTranslator(KernelReaderHelper* helper,
+                 ActiveClass* active_class,
+                 bool finalize = false);
+
+  // Can return a malformed type.
+  AbstractType& BuildType();
+  // Can return a malformed type.
+  AbstractType& BuildTypeWithoutFinalization();
+  // Is guaranteed to be not malformed.
+  AbstractType& BuildVariableType();
+
+  // Will return `TypeArguments::null()` in case any of the arguments are
+  // malformed.
+  const TypeArguments& BuildTypeArguments(intptr_t length);
+
+  // Will return `TypeArguments::null()` in case any of the arguments are
+  // malformed.
+  const TypeArguments& BuildInstantiatedTypeArguments(
+      const Class& receiver_class,
+      intptr_t length);
+
+  void LoadAndSetupTypeParameters(ActiveClass* active_class,
+                                  const Object& set_on,
+                                  intptr_t type_parameter_count,
+                                  const Function& parameterized_function);
+
+  const Type& ReceiverType(const Class& klass);
+
+ private:
+  // Can build a malformed type.
+  void BuildTypeInternal(bool invalid_as_dynamic = false);
+  void BuildInterfaceType(bool simple);
+  void BuildFunctionType(bool simple);
+  void BuildTypeParameterType();
+
+  class TypeParameterScope {
+   public:
+    TypeParameterScope(TypeTranslator* translator, intptr_t parameter_count)
+        : parameter_count_(parameter_count),
+          outer_(translator->type_parameter_scope_),
+          translator_(translator) {
+      outer_parameter_count_ = 0;
+      if (outer_ != NULL) {
+        outer_parameter_count_ =
+            outer_->outer_parameter_count_ + outer_->parameter_count_;
+      }
+      translator_->type_parameter_scope_ = this;
+    }
+    ~TypeParameterScope() { translator_->type_parameter_scope_ = outer_; }
+
+    TypeParameterScope* outer() const { return outer_; }
+    intptr_t parameter_count() const { return parameter_count_; }
+    intptr_t outer_parameter_count() const { return outer_parameter_count_; }
+
+   private:
+    intptr_t parameter_count_;
+    intptr_t outer_parameter_count_;
+    TypeParameterScope* outer_;
+    TypeTranslator* translator_;
+  };
+
+  KernelReaderHelper* helper_;
+  TranslationHelper& translation_helper_;
+  ActiveClass* const active_class_;
+  TypeParameterScope* type_parameter_scope_;
+  Zone* zone_;
+  AbstractType& result_;
+  bool finalize_;
+
+  friend class StreamingScopeBuilder;
+  friend class KernelLoader;
+};
+
 }  // namespace kernel
 }  // namespace dart
 
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 2440091..65fd953 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -13540,7 +13540,7 @@
 }
 
 #if defined(TAG_IC_DATA)
-void ICData::set_tag(intptr_t value) const {
+void ICData::set_tag(Tag value) const {
   StoreNonPointer(&raw_ptr()->tag_, value);
 }
 #endif
@@ -14427,7 +14427,7 @@
   NOT_IN_PRECOMPILED(result.set_deopt_id(deopt_id));
   result.set_state_bits(0);
 #if defined(TAG_IC_DATA)
-  result.set_tag(-1);
+  result.set_tag(ICData::Tag::kUnknown);
 #endif
   result.set_rebind_rule(rebind_rule);
   result.SetNumArgsTested(num_args_tested);
@@ -14451,7 +14451,7 @@
   result.set_deopt_id(Thread::kNoDeoptId);
   result.set_state_bits(0);
 #if defined(TAG_IC_DATA)
-  result.set_tag(-1);
+  result.set_tag(ICData::Tag::kUnknown);
 #endif
   return result.raw();
 }
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index ba4f605..17cc0f4 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -2004,8 +2004,9 @@
   enum { kCachedICDataArrayCount = 4 };
 
 #if defined(TAG_IC_DATA)
-  void set_tag(intptr_t value) const;
-  intptr_t tag() const { return raw_ptr()->tag_; }
+  using Tag = RawICData::Tag;
+  void set_tag(Tag value) const;
+  Tag tag() const { return raw_ptr()->tag_; }
 #endif
 
   bool is_static_call() const;
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index 5d7a7f0..88bd409 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -1663,8 +1663,10 @@
   NOT_IN_PRECOMPILED(int32_t deopt_id_);
   uint32_t state_bits_;  // Number of arguments tested in IC, deopt reasons.
 #if defined(TAG_IC_DATA)
-  intptr_t tag_;  // Debugging, verifying that the icdata is assigned to the
-                  // same instruction again. Store -1 or Instruction::Tag.
+  enum class Tag : intptr_t{kUnknown, kInstanceCall, kStaticCall};
+
+  Tag tag_;  // Debugging, verifying that the icdata is assigned to the
+             // same instruction again.
 #endif
 };
 
diff --git a/runtime/vm/raw_object_snapshot.cc b/runtime/vm/raw_object_snapshot.cc
index 435e697..2609707 100644
--- a/runtime/vm/raw_object_snapshot.cc
+++ b/runtime/vm/raw_object_snapshot.cc
@@ -1639,7 +1639,7 @@
   NOT_IN_PRECOMPILED(result.set_deopt_id(reader->Read<int32_t>()));
   result.set_state_bits(reader->Read<uint32_t>());
 #if defined(TAG_IC_DATA)
-  result.set_tag(reader->Read<int16_t>());
+  result.set_tag(static_cast<ICData::Tag>(reader->Read<int16_t>()));
 #endif
 
   // Set all the object fields.
@@ -1666,7 +1666,7 @@
   NOT_IN_PRECOMPILED(writer->Write<int32_t>(ptr()->deopt_id_));
   writer->Write<uint32_t>(ptr()->state_bits_);
 #if defined(TAG_IC_DATA)
-  writer->Write<int16_t>(ptr()->tag_);
+  writer->Write<int16_t>(static_cast<int64_t>(ptr()->tag_));
 #endif
 
   // Write out all the object pointer fields.