[kernel] Stream everything. Replace .kernel_function with .kernel_offset

- Put pointer to kernel data into Script.
- Replace function.kernel_function pointer to AstNode with
  kernel_offset():
- Replace field.kernel_field pointer to AstNode with kernel_offest().
- Stream the previously unstreamed AstNodes: FunctionDeclaration and
  FunctionExpression.
- Move special handling for _buildin.getMainClosure into the streaming
  flowgraph builder.
- Delete big parts of kernel_to_il.

R=kmillikin@google.com

Committed: https://github.com/dart-lang/sdk/commit/948e2f5d7916032ed6f0bfdc316ba4f577a5ea61
Review-Url: https://codereview.chromium.org/2901533002 .
diff --git a/pkg/kernel/binary.md b/pkg/kernel/binary.md
index b07e9a2..09fc3e6 100644
--- a/pkg/kernel/binary.md
+++ b/pkg/kernel/binary.md
@@ -329,6 +329,7 @@
   Byte asyncMarker; // Index into AsyncMarker above.
   Byte dartAsyncMarker; // Index into AsyncMarker above.
   List<TypeParameter> typeParameters;
+  UInt parameterCount; // positionalParameters.length + namedParameters.length.
   UInt requiredParameterCount;
   List<VariableDeclaration> positionalParameters;
   List<VariableDeclaration> namedParameters;
diff --git a/pkg/kernel/lib/binary/ast_from_binary.dart b/pkg/kernel/lib/binary/ast_from_binary.dart
index 95a4ea3..b730dde 100644
--- a/pkg/kernel/lib/binary/ast_from_binary.dart
+++ b/pkg/kernel/lib/binary/ast_from_binary.dart
@@ -617,6 +617,7 @@
     AsyncMarker dartAsyncMarker = AsyncMarker.values[readByte()];
     int typeParameterStackHeight = typeParameterStack.length;
     var typeParameters = readAndPushTypeParameterList();
+    readUInt(); // total parameter count.
     var requiredParameterCount = readUInt();
     int variableStackHeight = variableStack.length;
     var positional = readAndPushVariableDeclarationList();
diff --git a/pkg/kernel/lib/binary/ast_to_binary.dart b/pkg/kernel/lib/binary/ast_to_binary.dart
index bc29337..80a31bc 100644
--- a/pkg/kernel/lib/binary/ast_to_binary.dart
+++ b/pkg/kernel/lib/binary/ast_to_binary.dart
@@ -482,6 +482,7 @@
     writeByte(node.asyncMarker.index);
     writeByte(node.dartAsyncMarker.index);
     writeNodeList(node.typeParameters);
+    writeUInt30(node.positionalParameters.length + node.namedParameters.length);
     writeUInt30(node.requiredParameterCount);
     writeVariableDeclarationList(node.positionalParameters);
     writeVariableDeclarationList(node.namedParameters);
diff --git a/runtime/lib/mirrors.cc b/runtime/lib/mirrors.cc
index 54b22a6..9e2a1dd 100644
--- a/runtime/lib/mirrors.cc
+++ b/runtime/lib/mirrors.cc
@@ -145,7 +145,7 @@
     // * Whether a parameters has been declared as final.
     // * Any metadata associated with the parameter.
     Object& result = Object::Handle();
-    if (func.kernel_function() != NULL) {
+    if (func.kernel_offset() > 0) {
       result = kernel::BuildParameterDescriptor(func);
     } else {
       result = Parser::ParseFunctionParameters(func);
diff --git a/runtime/vm/class_finalizer.cc b/runtime/vm/class_finalizer.cc
index 288e056..13ac675 100644
--- a/runtime/vm/class_finalizer.cc
+++ b/runtime/vm/class_finalizer.cc
@@ -1631,7 +1631,7 @@
                         /* is_native = */ false, cls, field.token_pos()));
           getter.set_result_type(type);
           getter.set_is_debuggable(false);
-          getter.set_kernel_function(field.kernel_field());
+          getter.set_kernel_offset(field.kernel_offset());
           cls.AddFunction(getter);
           field.SetStaticValue(Object::sentinel(), true);
         }
@@ -2389,7 +2389,7 @@
   } else {
     for (intptr_t i = 0; i < functions.Length(); i++) {
       func ^= functions.At(i);
-      ASSERT(func.kernel_function() != 0);
+      ASSERT(func.kernel_offset() > 0);
       cloned_funcs.Add(func);
     }
   }
diff --git a/runtime/vm/compiler.cc b/runtime/vm/compiler.cc
index a99d4ba..f5a702a 100644
--- a/runtime/vm/compiler.cc
+++ b/runtime/vm/compiler.cc
@@ -115,7 +115,7 @@
 
 bool UseKernelFrontEndFor(ParsedFunction* parsed_function) {
   const Function& function = parsed_function->function();
-  return (function.kernel_function() != NULL) ||
+  return (function.kernel_offset() > 0) ||
          (function.kind() == RawFunction::kNoSuchMethodDispatcher) ||
          (function.kind() == RawFunction::kInvokeFieldDispatcher);
 }
@@ -135,11 +135,11 @@
     const ZoneGrowableArray<const ICData*>& ic_data_array,
     intptr_t osr_id) {
   if (UseKernelFrontEndFor(parsed_function)) {
-    kernel::TreeNode* node = static_cast<kernel::TreeNode*>(
-        parsed_function->function().kernel_function());
-    kernel::FlowGraphBuilder builder(node, parsed_function, ic_data_array,
-                                     /* not building var desc */ NULL,
-                                     /* not inlining */ NULL, osr_id);
+    kernel::FlowGraphBuilder builder(
+        parsed_function->function().kernel_offset(), parsed_function,
+        ic_data_array,
+        /* not building var desc */ NULL,
+        /* not inlining */ NULL, osr_id);
     FlowGraph* graph = builder.BuildGraph();
     ASSERT(graph != NULL);
     return graph;
@@ -1606,10 +1606,9 @@
       builder.BuildGraph();
     } else {
       parsed_function->EnsureKernelScopes();
-      kernel::TreeNode* node = static_cast<kernel::TreeNode*>(
-          parsed_function->function().kernel_function());
       kernel::FlowGraphBuilder builder(
-          node, parsed_function, *ic_data_array, context_level_array,
+          parsed_function->function().kernel_offset(), parsed_function,
+          *ic_data_array, context_level_array,
           /* not inlining */ NULL, Compiler::kNoOSRDeoptId);
       builder.BuildGraph();
     }
@@ -1732,7 +1731,7 @@
 
       // Create a one-time-use function to evaluate the initializer and invoke
       // it immediately.
-      if (field.kernel_field() != NULL) {
+      if (field.kernel_offset() > 0) {
         parsed_function = kernel::ParseStaticFieldInitializer(zone, field);
       } else {
         parsed_function = Parser::ParseStaticFieldInitializer(field);
diff --git a/runtime/vm/flow_graph_inliner.cc b/runtime/vm/flow_graph_inliner.cc
index b5063f8..65c3741 100644
--- a/runtime/vm/flow_graph_inliner.cc
+++ b/runtime/vm/flow_graph_inliner.cc
@@ -796,12 +796,9 @@
             new (Z) InlineExitCollector(caller_graph_, call);
         FlowGraph* callee_graph;
         if (UseKernelFrontEndFor(parsed_function)) {
-          kernel::TreeNode* node = static_cast<kernel::TreeNode*>(
-              parsed_function->function().kernel_function());
-
           kernel::FlowGraphBuilder builder(
-              node, parsed_function, *ic_data_array,
-              /* not building var desc */ NULL, exit_collector,
+              parsed_function->function().kernel_offset(), parsed_function,
+              *ic_data_array, /* not building var desc */ NULL, exit_collector,
               Compiler::kNoOSRDeoptId, caller_graph_->max_block_id() + 1);
           {
             CSTAT_TIMER_SCOPE(thread(), graphinliner_build_timer);
diff --git a/runtime/vm/kernel.h b/runtime/vm/kernel.h
index e2970b1..70f5f36 100644
--- a/runtime/vm/kernel.h
+++ b/runtime/vm/kernel.h
@@ -429,7 +429,10 @@
 
   virtual void AcceptVisitor(Visitor* visitor);
   virtual void AcceptTreeVisitor(TreeVisitor* visitor) = 0;
-  intptr_t kernel_offset() const { return kernel_offset_; }
+  intptr_t kernel_offset() const {
+    ASSERT(kernel_offset_ > 0);
+    return kernel_offset_;
+  }
   bool can_stream() { return can_stream_; }
 
  protected:
diff --git a/runtime/vm/kernel_binary.cc b/runtime/vm/kernel_binary.cc
index dd791b1..6902242 100644
--- a/runtime/vm/kernel_binary.cc
+++ b/runtime/vm/kernel_binary.cc
@@ -257,6 +257,7 @@
 Class* Class::ReadFrom(Reader* reader) {
   TRACE_READ_OFFSET();
 
+  kernel_offset_ = reader->offset() - 1;  // -1 to include tag byte.
   canonical_name_ = reader->ReadCanonicalNameReference();
   position_ = reader->ReadPosition(false);
   is_abstract_ = reader->ReadBool();
@@ -1843,6 +1844,7 @@
   function->dart_async_marker_ =
       static_cast<FunctionNode::AsyncMarker>(reader->ReadByte());
   function->type_parameters().ReadFrom(reader);
+  reader->ReadUInt();  // total parameter count.
   function->required_parameter_count_ = reader->ReadUInt();
   function->positional_parameters().ReadFromStatic<VariableDeclarationImpl>(
       reader);
diff --git a/runtime/vm/kernel_binary_flowgraph.cc b/runtime/vm/kernel_binary_flowgraph.cc
index c88ddce..adcfcec 100644
--- a/runtime/vm/kernel_binary_flowgraph.cc
+++ b/runtime/vm/kernel_binary_flowgraph.cc
@@ -4,6 +4,7 @@
 
 #include "vm/kernel_binary_flowgraph.h"
 
+#include "vm/compiler.h"
 #include "vm/longjump.h"
 #include "vm/object_store.h"
 
@@ -54,27 +55,6 @@
   delete builder_;
 }
 
-void StreamingScopeBuilder::DiscoverEnclosingElements(
-    Zone* zone,
-    const Function& function,
-    Function* outermost_function,
-    intptr_t* outermost_kernel_offset,
-    intptr_t* parent_class_offset) {
-  // Find out if there is an enclosing kernel class (which will be used to
-  // resolve type parameters).
-  *outermost_function = function.raw();
-  while (outermost_function->parent_function() != Object::null()) {
-    *outermost_function = outermost_function->parent_function();
-  }
-
-  if (outermost_function->kernel_function() != NULL) {
-    *outermost_kernel_offset =
-        static_cast<TreeNode*>(outermost_function->kernel_function())
-            ->kernel_offset();
-    *parent_class_offset = GetParentOffset(*outermost_kernel_offset);
-  }
-}
-
 ScopeBuildingResult* StreamingScopeBuilder::BuildScopes() {
   if (result_ != NULL) return result_;
 
@@ -91,16 +71,18 @@
   Function& outermost_function = Function::Handle(Z);
   intptr_t outermost_kernel_offset = -1;
   intptr_t parent_class_offset = -1;
-  DiscoverEnclosingElements(Z, function, &outermost_function,
-                            &outermost_kernel_offset, &parent_class_offset);
+  builder_->DiscoverEnclosingElements(Z, function, &outermost_function,
+                                      &outermost_kernel_offset,
+                                      &parent_class_offset);
   // Use [klass]/[kernel_class] as active class.  Type parameters will get
   // resolved via [kernel_class] unless we are nested inside a static factory
   // in which case we will use [member].
   intptr_t class_type_parameters = 0;
   intptr_t class_type_parameters_offset_start = -1;
   if (parent_class_offset > 0) {
-    GetTypeParameterInfoForClass(parent_class_offset, &class_type_parameters,
-                                 &class_type_parameters_offset_start);
+    builder_->GetTypeParameterInfoForClass(parent_class_offset,
+                                           &class_type_parameters,
+                                           &class_type_parameters_offset_start);
   }
   ActiveClassScope active_class_scope(&active_class_, class_type_parameters,
                                       class_type_parameters_offset_start,
@@ -110,7 +92,7 @@
   bool is_factory_procedure = false;
   intptr_t member_type_parameters = 0;
   intptr_t member_type_parameters_offset_start = -1;
-  GetTypeParameterInfoForPossibleProcedure(
+  builder_->GetTypeParameterInfoForPossibleProcedure(
       outermost_kernel_offset, &member_is_procedure, &is_factory_procedure,
       &member_type_parameters, &member_type_parameters_offset_start);
 
@@ -144,27 +126,10 @@
     case RawFunction::kSetterFunction:
     case RawFunction::kConstructor: {
       const Tag tag = builder_->PeekTag();
-      if (tag == kProcedure) {
-        Tag has_function_node = ReadProcedureUntilFunctionNode(
-            &unused_word, &unused_intptr);  // read first part of procedure.
-        if (has_function_node == kNothing) {
-          // Running a procedure without a function node doesn't make sense.
-          UNREACHABLE();
-        }
-        // Now at start of FunctionNode.
-      } else if (tag == kConstructor) {
-        // read first part of constructor.
-        parent_offset = ReadConstructorUntilFunctionNode();
-        // Now at start of FunctionNode.
-        // Notice that we also have a list of initializers after that!
-      } else if (tag == kFunctionNode) {
-        // Already at start of FunctionNode.
-      } else {
-        UNREACHABLE();
-      }
+      parent_offset = builder_->ReadUntilFunctionNode();
       word async_marker_word;
-      ReadFunctionNodeUntilTypeParameters(
-          &async_marker_word,
+      builder_->ReadFunctionNodeUntilTypeParameters(
+          &unused_tokenposition, &unused_tokenposition, &async_marker_word,
           &unused_word);  // read first part of function node.
       current_function_async_marker_ =
           static_cast<FunctionNode::AsyncMarker>(async_marker_word);
@@ -193,7 +158,7 @@
         if (tag == kConstructor) {
           ASSERT(parent_offset >= 0);
           AlternativeReadingScope alt(builder_->reader_, parent_offset);
-          ReadClassUntilFields();  // read first part of class.
+          builder_->ReadClassUntilFields();  // read first part of class.
           intptr_t list_length =
               builder_->ReadListLength();  // read fields list length.
           for (intptr_t i = 0; i < list_length; i++) {
@@ -201,12 +166,14 @@
             TokenPosition position;
             TokenPosition end_position;
             word flags;
-            ReadFieldUntilAnnotation(&position, &end_position, &flags,
-                                     &unused_intptr);
+            builder_->ReadFieldUntilAnnotation(&unused_nameindex, &position,
+                                               &end_position, &flags,
+                                               &unused_intptr);
             bool is_static = (flags & Field::kFlagStatic) == Field::kFlagStatic;
             builder_->SkipListOfExpressions();  // read annotations.
             builder_->SkipDartType();           // read type.
-            Tag initializer_tag = builder_->ReadTag();
+            Tag initializer_tag =
+                builder_->ReadTag();  // read first part of initializer.
             if (!is_static && initializer_tag == kSomething) {
               EnterScope(field_offset);
               VisitExpression();  // read initializer.
@@ -226,6 +193,7 @@
 
       // Continue reading FunctionNode.
       builder_->SkipTypeParametersList();  // read type_parameters.
+      builder_->ReadUInt();                // read total parameter count.
       builder_->ReadUInt();                // read required_parameter_count.
       AddPositionalAndNamedParameters(
           pos);  // read positional_parameters and named_parameters.
@@ -319,40 +287,6 @@
   return result_;
 }
 
-intptr_t StreamingScopeBuilder::GetParentOffset(intptr_t offset) {
-  AlternativeReadingScope alt(builder_->reader_, offset);
-
-  Tag tag = builder_->PeekTag();
-  intptr_t parent_offset = -1;
-  switch (tag) {
-    case kConstructor:
-      return ReadConstructorUntilFunctionNode();
-    case kProcedure:
-      ReadProcedureUntilFunctionNode(
-          &unused_word, &parent_offset);  // read first part of procedure.
-      return parent_offset;
-    case kField:
-      ReadFieldUntilAnnotation(&unused_tokenposition, &unused_tokenposition,
-                               &unused_word, &parent_offset);
-      return parent_offset;
-    default:
-      UNIMPLEMENTED();
-      return -1;
-  }
-}
-
-void StreamingScopeBuilder::GetTypeParameterInfoForClass(
-    intptr_t class_offset,
-    intptr_t* type_paremeter_counts,
-    intptr_t* type_paremeter_offset) {
-  AlternativeReadingScope alt(builder_->reader_, class_offset);
-
-  ReadClassUntilTypeParameters();
-  *type_paremeter_counts =
-      builder_->ReadListLength();  // read type_parameters list length.
-  *type_paremeter_offset = builder_->ReaderOffset();
-}
-
 void StreamingScopeBuilder::VisitNode() {
   Tag tag = builder_->PeekTag();
   switch (tag) {
@@ -374,37 +308,25 @@
   }
 }
 
-intptr_t StreamingScopeBuilder::ReadConstructorUntilFunctionNode() {
-  Tag tag = builder_->ReadTag();
-  ASSERT(tag == kConstructor);
-  builder_->SkipCanonicalNameReference();  // read canonical name reference.
-  builder_->ReadPosition();                // read position.
-  builder_->ReadPosition();                // read end position.
-  builder_->ReadFlags();                   // read flags.
-  intptr_t parent_offset = builder_->ReadUInt();  // parent class binary offset.
-  builder_->SkipName();                           // read name.
-  builder_->SkipListOfExpressions();              // read annotations.
-  return parent_offset;
-}
-
 void StreamingScopeBuilder::VisitConstructor() {
   // Field initializers that come from non-static field declarations are
   // compiled as if they appear in the constructor initializer list.  This is
   // important for closure-valued field initializers because the VM expects the
   // corresponding closure functions to appear as if they were nested inside the
   // constructor.
-  intptr_t parent_offset = ReadConstructorUntilFunctionNode();
+  intptr_t parent_offset = builder_->ReadConstructorUntilFunctionNode();
   ASSERT(parent_offset >= 0);
   {
     AlternativeReadingScope alt(builder_->reader_, parent_offset);
-    ReadClassUntilFields();  // read first part of class.
+    builder_->ReadClassUntilFields();  // read first part of class.
 
     intptr_t list_length =
         builder_->ReadListLength();  // read fields list length.
     for (intptr_t i = 0; i < list_length; i++) {
       word flags;
-      ReadFieldUntilAnnotation(&unused_tokenposition, &unused_tokenposition,
-                               &flags, &unused_intptr);
+      builder_->ReadFieldUntilAnnotation(
+          &unused_nameindex, &unused_tokenposition, &unused_tokenposition,
+          &flags, &unused_intptr);
       bool is_static = (flags & Field::kFlagStatic) == Field::kFlagStatic;
       builder_->SkipListOfExpressions();  // read annotations.
       builder_->SkipDartType();           // read type.
@@ -427,34 +349,17 @@
 }
 
 void StreamingScopeBuilder::VisitProcedure() {
-  Tag function_node = ReadProcedureUntilFunctionNode(
+  Tag function_node = builder_->ReadProcedureUntilFunctionNode(
       &unused_word, &unused_intptr);  // read first part of procedure.
   if (function_node == kSomething) {
     VisitFunctionNode();
   }
 }
 
-void StreamingScopeBuilder::ReadFieldUntilAnnotation(
-    TokenPosition* position,
-    TokenPosition* end_position,
-    word* flags,
-    intptr_t* parent_offset) {
-  Tag tag = builder_->ReadTag();
-  ASSERT(tag == kField);
-
-  builder_->SkipCanonicalNameReference();    // read canonical_name.
-  *position = builder_->ReadPosition();      // read position.
-  *end_position = builder_->ReadPosition();  // read end position.
-  *flags = builder_->ReadFlags();            // read flags.
-  *parent_offset = builder_->ReadUInt();     // read parent class binary offset.
-  builder_->SkipName();                      // read name.
-  builder_->ReadUInt();                      // source_uri_index.
-}
-
 void StreamingScopeBuilder::VisitField() {
-  ReadFieldUntilAnnotation(&unused_tokenposition, &unused_tokenposition,
-                           &unused_intptr,
-                           &unused_word);  // read first part of field.
+  builder_->ReadFieldUntilAnnotation(
+      &unused_nameindex, &unused_tokenposition, &unused_tokenposition,
+      &unused_intptr, &unused_word);       // read first part of field.
   builder_->SkipListOfExpressions();       // read annotations.
   VisitDartType();                         // read type.
   Tag tag = builder_->ReadTag();           // read initializer (part 1).
@@ -463,98 +368,12 @@
   }
 }
 
-Tag StreamingScopeBuilder::ReadProcedureUntilFunctionNode(
-    word* kind,
-    intptr_t* parent_offset) {
-  Tag tag = builder_->ReadTag();  // read tag.
-  ASSERT(tag == kProcedure);
-  builder_->SkipCanonicalNameReference();  // read canonical name reference.
-  builder_->ReadPosition();                // read position.
-  builder_->ReadPosition();                // read end position.
-  *kind = builder_->ReadByte();            // read kind.
-  builder_->ReadFlags();                   // read flags.
-  *parent_offset = builder_->ReadUInt();   // read parent class binary offset.
-  builder_->SkipName();                    // read name,
-  builder_->ReadUInt();                    // read source_uri_index.
-  builder_->SkipListOfExpressions();       // read annotations.
-  return builder_->ReadTag();  // read tag for optional function node.
-}
-
-void StreamingScopeBuilder::GetTypeParameterInfoForPossibleProcedure(
-    intptr_t outermost_kernel_offset,
-    bool* member_is_procedure,
-    bool* is_factory_procedure,
-    intptr_t* member_type_parameters,
-    intptr_t* member_type_parameters_offset_start) {
-  if (outermost_kernel_offset >= 0) {
-    AlternativeReadingScope alt(builder_->reader_, outermost_kernel_offset);
-    Tag tag = builder_->PeekTag();
-    if (tag == kProcedure) {
-      *member_is_procedure = true;
-
-      word kind;
-      tag = ReadProcedureUntilFunctionNode(
-          &kind, &unused_intptr);  // read first part of procedure.
-      *is_factory_procedure =
-          static_cast<Procedure::ProcedureKind>(kind) == Procedure::kFactory;
-
-      if (tag == kSomething) {
-        ReadFunctionNodeUntilTypeParameters(
-            &unused_word, &unused_word);  // read first part of function node.
-
-        intptr_t list_length =
-            builder_->ReadListLength();  // read type_parameters list length.
-        if (list_length > 0) {
-          *member_type_parameters = list_length;
-          *member_type_parameters_offset_start = builder_->ReaderOffset();
-        }
-      }
-    }
-  }
-}
-
-void StreamingScopeBuilder::ReadClassUntilTypeParameters() {
-  Tag class_tag = builder_->ReadTag();
-  ASSERT(class_tag == kClass);
-  builder_->SkipCanonicalNameReference();  // read canonical_name.
-  builder_->ReadPosition();                // read position.
-  builder_->ReadBool();                    // read is_abstract.
-  builder_->SkipStringReference();         // read name index.
-  builder_->ReadUInt();                    // read source_uri_index.
-  builder_->SkipListOfExpressions();       // read annotations.
-}
-
-void StreamingScopeBuilder::ReadClassUntilFields() {
-  ReadClassUntilTypeParameters();
-  builder_->SkipTypeParametersList();  // read type_parameters.
-  Tag type_tag = builder_->ReadTag();  // read type (part 1).
-  if (type_tag == kSomething) {
-    builder_->SkipDartType();  // read type (part 2).
-  }
-  type_tag = builder_->ReadTag();  // read Mixed-in type (part 1).
-  if (type_tag == kSomething) {
-    builder_->SkipDartType();  // read Mixed-in type (part 2).
-  }
-  builder_->SkipListOfDartTypes();  // read implemented_classes.
-}
-
-void StreamingScopeBuilder::ReadFunctionNodeUntilTypeParameters(
-    word* async_marker,
-    word* dart_async_marker) {
-  Tag tag = builder_->ReadTag();  // read tag.
-  ASSERT(tag == kFunctionNode);
-
-  builder_->ReadPosition();                   // read position.
-  builder_->ReadPosition();                   // read end position.
-  *async_marker = builder_->ReadByte();       // read async marker.
-  *dart_async_marker = builder_->ReadByte();  // read dart async marker.
-}
-
 void StreamingScopeBuilder::VisitFunctionNode() {
   word async_marker_word;
   word dart_async_marker_word;
-  ReadFunctionNodeUntilTypeParameters(&async_marker_word,
-                                      &dart_async_marker_word);
+  builder_->ReadFunctionNodeUntilTypeParameters(
+      &unused_tokenposition, &unused_tokenposition, &async_marker_word,
+      &dart_async_marker_word);
   FunctionNode::AsyncMarker async_marker =
       static_cast<FunctionNode::AsyncMarker>(async_marker_word);
   FunctionNode::AsyncMarker dart_async_marker =
@@ -589,6 +408,7 @@
   // Read (but don't visit) the positional and named parameters, because they've
   // already been added to the scope.
 
+  builder_->ReadUInt();  // read total parameter count.
   builder_->ReadUInt();  // read required_parameter_count.
 
   builder_->SkipListOfVariableDeclarations();  // read list of positionals.
@@ -643,11 +463,11 @@
       VisitExpression();                       // read value.
       return;
     case kSuperInitializer:
-      builder_->SkipCanonicalNameReference();  // read field_reference.
+      builder_->SkipCanonicalNameReference();  // read target_reference.
       VisitArguments();                        // read arguments.
       return;
     case kRedirectingInitializer:
-      builder_->SkipCanonicalNameReference();  // read field_reference.
+      builder_->SkipCanonicalNameReference();  // read target_reference.
       VisitArguments();                        // read arguments.
       return;
     case kLocalInitializer:
@@ -1320,6 +1140,7 @@
     result_->function_scopes.Add(function_scope);
   }
 
+  builder_->ReadUInt();  // read total parameter count.
   builder_->ReadUInt();  // read required_parameter_count.
   // read positional_parameters and named_parameters.
   AddPositionalAndNamedParameters();
@@ -1481,16 +1302,6 @@
   }
 }
 
-StringIndex StreamingScopeBuilder::GetNameFromVariableDeclaration(
-    intptr_t kernel_offset) {
-  // Temporarily go to the variable declaration, read the name.
-  AlternativeReadingScope alt(builder_->reader_, kernel_offset);
-  builder_->ReadPosition();                // read position.
-  builder_->ReadPosition();                // read equals position.
-  builder_->ReadFlags();                   // read flags.
-  return builder_->ReadStringReference();  // read name index.
-}
-
 void StreamingScopeBuilder::LookupVariable(intptr_t declaration_binary_offest) {
   LocalVariable* variable = result_->locals.Lookup(declaration_binary_offest);
   if (variable == NULL) {
@@ -1501,7 +1312,7 @@
     ASSERT(current_function_scope_->parent() != NULL);
 
     StringIndex var_name =
-        GetNameFromVariableDeclaration(declaration_binary_offest);
+        builder_->GetNameFromVariableDeclaration(declaration_binary_offest);
 
     const dart::String& name = H.DartSymbol(var_name);
     variable = current_function_scope_->parent()->LookupVariable(name, true);
@@ -1586,6 +1397,17 @@
   return dart::AbstractType::ZoneHandle(Z, result_.raw());
 }
 
+AbstractType& StreamingDartTypeTranslator::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 dart::AbstractType::ZoneHandle(Z, result_.raw());
+}
+
 AbstractType& StreamingDartTypeTranslator::BuildVariableType() {
   AbstractType& abstract_type = BuildType();
 
@@ -2189,7 +2011,6 @@
     if (H.IsMethod(target)) {
       Function& closure_function =
           Function::ZoneHandle(Z, function.ImplicitClosureFunction());
-      closure_function.set_kernel_function(function.kernel_function());
       result_ = closure_function.ImplicitStaticClosure();
       result_ = H.Canonicalize(result_);
     } else if (H.IsGetter(target)) {
@@ -2639,7 +2460,7 @@
 
 bool StreamingConstantEvaluator::GetCachedConstant(intptr_t kernel_offset,
                                                    Instance* value) {
-  if (builder_ == NULL) return false;
+  if (builder_ == NULL || builder_->flow_graph_builder_ == NULL) return false;
 
   const Function& function = builder_->parsed_function()->function();
   if (function.kind() == RawFunction::kImplicitStaticFinalGetter) {
@@ -2670,7 +2491,7 @@
                                                     const Instance& value) {
   ASSERT(Thread::Current()->IsMutatorThread());
 
-  if (builder_ == NULL) return;
+  if (builder_ == NULL || builder_->flow_graph_builder_ == NULL) return;
 
   const Function& function = builder_->parsed_function()->function();
   if (function.kind() == RawFunction::kImplicitStaticFinalGetter) {
@@ -2690,12 +2511,1095 @@
   script_.set_compile_time_constants(constants.Release());
 }
 
+void StreamingFlowGraphBuilder::DiscoverEnclosingElements(
+    Zone* zone,
+    const Function& function,
+    Function* outermost_function,
+    intptr_t* outermost_kernel_offset,
+    intptr_t* parent_class_offset) {
+  // Find out if there is an enclosing kernel class (which will be used to
+  // resolve type parameters).
+  *outermost_function = function.raw();
+  while (outermost_function->parent_function() != Object::null()) {
+    *outermost_function = outermost_function->parent_function();
+  }
 
-Fragment StreamingFlowGraphBuilder::BuildExpressionAt(intptr_t kernel_offset) {
-  SetOffset(kernel_offset);
-  return BuildExpression();  // read expression.
+  if (outermost_function->kernel_offset() > 0) {
+    *outermost_kernel_offset = outermost_function->kernel_offset();
+    *parent_class_offset = GetParentOffset(*outermost_kernel_offset);
+  }
 }
 
+intptr_t StreamingFlowGraphBuilder::GetParentOffset(intptr_t offset) {
+  AlternativeReadingScope alt(reader_, offset);
+
+  Tag tag = PeekTag();
+  intptr_t parent_offset = -1;
+  switch (tag) {
+    case kConstructor:
+      return ReadConstructorUntilFunctionNode();
+    case kProcedure:
+      ReadProcedureUntilFunctionNode(
+          &unused_word, &parent_offset);  // read first part of procedure.
+      return parent_offset;
+    case kField:
+      ReadFieldUntilAnnotation(&unused_nameindex, &unused_tokenposition,
+                               &unused_tokenposition, &unused_word,
+                               &parent_offset);
+      return parent_offset;
+    default:
+      UNIMPLEMENTED();
+      return -1;
+  }
+}
+
+void StreamingFlowGraphBuilder::GetTypeParameterInfoForClass(
+    intptr_t class_offset,
+    intptr_t* type_paremeter_counts,
+    intptr_t* type_paremeter_offset) {
+  AlternativeReadingScope alt(reader_, class_offset);
+
+  ReadClassUntilTypeParameters();
+  *type_paremeter_counts =
+      ReadListLength();  // read type_parameters list length.
+  *type_paremeter_offset = ReaderOffset();
+}
+
+void StreamingFlowGraphBuilder::ReadClassUntilFields() {
+  ReadClassUntilTypeParameters();
+  SkipTypeParametersList();  // read type_parameters.
+  Tag type_tag = ReadTag();  // read type (part 1).
+  if (type_tag == kSomething) {
+    SkipDartType();  // read type (part 2).
+  }
+  type_tag = ReadTag();  // read Mixed-in type (part 1).
+  if (type_tag == kSomething) {
+    SkipDartType();  // read Mixed-in type (part 2).
+  }
+  SkipListOfDartTypes();  // read implemented_classes.
+}
+
+void StreamingFlowGraphBuilder::ReadClassUntilTypeParameters() {
+  Tag class_tag = ReadTag();
+  ASSERT(class_tag == kClass);
+  SkipCanonicalNameReference();  // read canonical_name.
+  ReadPosition();                // read position.
+  ReadBool();                    // read is_abstract.
+  SkipStringReference();         // read name index.
+  ReadUInt();                    // read source_uri_index.
+  SkipListOfExpressions();       // read annotations.
+}
+
+intptr_t StreamingFlowGraphBuilder::ReadConstructorUntilFunctionNode() {
+  Tag tag = ReadTag();
+  ASSERT(tag == kConstructor);
+  SkipCanonicalNameReference();         // read canonical name reference.
+  ReadPosition();                       // read position.
+  ReadPosition();                       // read end position.
+  ReadFlags();                          // read flags.
+  intptr_t parent_offset = ReadUInt();  // parent class binary offset.
+  SkipName();                           // read name.
+  SkipListOfExpressions();              // read annotations.
+  return parent_offset;
+}
+
+Tag StreamingFlowGraphBuilder::ReadProcedureUntilFunctionNode(
+    word* kind,
+    intptr_t* parent_offset) {
+  Tag tag = ReadTag();  // read tag.
+  ASSERT(tag == kProcedure);
+  SkipCanonicalNameReference();  // read canonical name reference.
+  ReadPosition();                // read position.
+  ReadPosition();                // read end position.
+  *kind = ReadByte();            // read kind.
+  ReadFlags();                   // read flags.
+  *parent_offset = ReadUInt();   // read parent class binary offset.
+  SkipName();                    // read name,
+  ReadUInt();                    // read source_uri_index.
+  SkipListOfExpressions();       // read annotations.
+  return ReadTag();              // read tag for optional function node.
+}
+
+void StreamingFlowGraphBuilder::ReadFieldUntilAnnotation(
+    NameIndex* canonical_name,
+    TokenPosition* position,
+    TokenPosition* end_position,
+    word* flags,
+    intptr_t* parent_offset) {
+  Tag tag = ReadTag();
+  ASSERT(tag == kField);
+
+  *canonical_name = ReadCanonicalNameReference();  // read canonical_name.
+  *position = ReadPosition();                      // read position.
+  *end_position = ReadPosition();                  // read end position.
+  *flags = ReadFlags();                            // read flags.
+  *parent_offset = ReadUInt();  // read parent class binary offset.
+  SkipName();                   // read name.
+  ReadUInt();                   // source_uri_index.
+}
+
+void StreamingFlowGraphBuilder::GetTypeParameterInfoForPossibleProcedure(
+    intptr_t outermost_kernel_offset,
+    bool* member_is_procedure,
+    bool* is_factory_procedure,
+    intptr_t* member_type_parameters,
+    intptr_t* member_type_parameters_offset_start) {
+  if (outermost_kernel_offset >= 0) {
+    AlternativeReadingScope alt(reader_, outermost_kernel_offset);
+    Tag tag = PeekTag();
+    if (tag == kProcedure) {
+      *member_is_procedure = true;
+
+      word kind;
+      tag = ReadProcedureUntilFunctionNode(
+          &kind, &unused_intptr);  // read first part of procedure.
+      *is_factory_procedure =
+          static_cast<Procedure::ProcedureKind>(kind) == Procedure::kFactory;
+
+      if (tag == kSomething) {
+        ReadFunctionNodeUntilTypeParameters(
+            &unused_tokenposition, &unused_tokenposition, &unused_word,
+            &unused_word);  // read first part of function node.
+
+        intptr_t list_length =
+            ReadListLength();  // read type_parameters list length.
+        if (list_length > 0) {
+          *member_type_parameters = list_length;
+          *member_type_parameters_offset_start = ReaderOffset();
+        }
+      }
+    }
+  }
+}
+
+void StreamingFlowGraphBuilder::ReadFunctionNodeUntilTypeParameters(
+    TokenPosition* position,
+    TokenPosition* end_position,
+    word* async_marker,
+    word* dart_async_marker) {
+  Tag tag = ReadTag();  // read tag.
+  ASSERT(tag == kFunctionNode);
+
+  *position = ReadPosition();       // read position.
+  *end_position = ReadPosition();   // read end position.
+  *async_marker = ReadByte();       // read async marker.
+  *dart_async_marker = ReadByte();  // read dart async marker.
+}
+
+intptr_t StreamingFlowGraphBuilder::ReadUntilFunctionNode() {
+  const Tag tag = PeekTag();
+  if (tag == kProcedure) {
+    Tag has_function_node = ReadProcedureUntilFunctionNode(
+        &unused_word, &unused_intptr);  // read first part of procedure.
+    if (has_function_node == kNothing) {
+      // Running a procedure without a function node doesn't make sense.
+      UNREACHABLE();
+    }
+    return -1;
+    // Now at start of FunctionNode.
+  } else if (tag == kConstructor) {
+    // read first part of constructor.
+    return ReadConstructorUntilFunctionNode();
+    // Now at start of FunctionNode.
+    // Notice that we also have a list of initializers after that!
+  } else if (tag == kFunctionNode) {
+    // Already at start of FunctionNode.
+  } else {
+    UNREACHABLE();
+  }
+  return -1;
+}
+
+StringIndex StreamingFlowGraphBuilder::GetNameFromVariableDeclaration(
+    intptr_t kernel_offset) {
+  // Temporarily go to the variable declaration, read the name.
+  AlternativeReadingScope alt(reader_, kernel_offset);
+  ReadPosition();                // read position.
+  ReadPosition();                // read equals position.
+  ReadFlags();                   // read flags.
+  return ReadStringReference();  // read name index.
+}
+
+FlowGraph* StreamingFlowGraphBuilder::BuildGraphOfStaticFieldInitializer() {
+  TokenPosition position;
+  TokenPosition end_position;
+  word flags;
+  ReadFieldUntilAnnotation(&unused_nameindex, &position, &end_position, &flags,
+                           &unused_intptr);
+  bool is_static = (flags & Field::kFlagStatic) == Field::kFlagStatic;
+  bool is_const = (flags & Field::kFlagConst) == Field::kFlagConst;
+  ASSERT(is_static);
+
+  SkipListOfExpressions();          // read annotations.
+  SkipDartType();                   // read type.
+  Tag initializer_tag = ReadTag();  // read first part of initializer.
+  if (initializer_tag != kSomething) {
+    UNREACHABLE();
+  }
+
+  TargetEntryInstr* normal_entry = flow_graph_builder_->BuildTargetEntry();
+  flow_graph_builder_->graph_entry_ = new (Z) GraphEntryInstr(
+      *parsed_function(), normal_entry, Compiler::kNoOSRDeoptId);
+
+  Fragment body(normal_entry);
+  body += flow_graph_builder_->CheckStackOverflowInPrologue();
+  if (is_const) {
+    // this will (potentially) read the initializer, but reset the position.
+    body += Constant(constant_evaluator_.EvaluateExpression(ReaderOffset()));
+    SkipExpression();  // read the initializer.
+  } else {
+    body += BuildExpression();  // read initializer.
+  }
+  body += Return(TokenPosition::kNoSource);
+
+  return new (Z)
+      FlowGraph(*parsed_function(), flow_graph_builder_->graph_entry_,
+                flow_graph_builder_->next_block_id_ - 1);
+}
+
+FlowGraph* StreamingFlowGraphBuilder::BuildGraphOfFieldAccessor(
+    LocalVariable* setter_value) {
+  NameIndex canonical_name;
+  ReadFieldUntilAnnotation(&canonical_name, &unused_tokenposition,
+                           &unused_tokenposition, &unused_word, &unused_intptr);
+  SkipListOfExpressions();          // read annotations.
+  SkipDartType();                   // read type.
+  Tag initializer_tag = ReadTag();  // read first part of initializer.
+
+  const Function& function = parsed_function()->function();
+
+  bool is_setter = function.IsImplicitSetterFunction();
+  bool is_method = !function.IsStaticFunction();
+  dart::Field& field =
+      dart::Field::ZoneHandle(Z, H.LookupFieldByKernelField(canonical_name));
+
+  TargetEntryInstr* normal_entry = flow_graph_builder_->BuildTargetEntry();
+  flow_graph_builder_->graph_entry_ = new (Z) GraphEntryInstr(
+      *parsed_function(), normal_entry, Compiler::kNoOSRDeoptId);
+
+  Fragment body(normal_entry);
+  if (is_setter) {
+    if (is_method) {
+      body += LoadLocal(scopes()->this_variable);
+      body += LoadLocal(setter_value);
+      body += flow_graph_builder_->StoreInstanceFieldGuarded(field, false);
+    } else {
+      body += LoadLocal(setter_value);
+      body += StoreStaticField(TokenPosition::kNoSource, field);
+    }
+    body += NullConstant();
+  } else if (is_method) {
+    body += LoadLocal(scopes()->this_variable);
+    body += flow_graph_builder_->LoadField(field);
+  } else if (field.is_const()) {
+    // If the parser needs to know the value of an uninitialized constant field
+    // it will set the value to the transition sentinel (used to detect circular
+    // initialization) and then call the implicit getter.  Thus, the getter
+    // cannot contain the InitStaticField instruction that normal static getters
+    // contain because it would detect spurious circular initialization when it
+    // checks for the transition sentinel.
+    ASSERT(initializer_tag == kSomething);
+    // this will (potentially) read the initializer, but reset the position.
+    body += Constant(constant_evaluator_.EvaluateExpression(ReaderOffset()));
+    SkipExpression();  // read the initializer.
+  } else {
+    // The field always has an initializer because static fields without
+    // initializers are initialized eagerly and do not have implicit getters.
+    ASSERT(field.has_initializer());
+    body += Constant(field);
+    body += flow_graph_builder_->InitStaticField(field);
+    body += Constant(field);
+    body += LoadStaticField();
+  }
+  body += Return(TokenPosition::kNoSource);
+
+  return new (Z)
+      FlowGraph(*parsed_function(), flow_graph_builder_->graph_entry_,
+                flow_graph_builder_->next_block_id_ - 1);
+}
+
+void StreamingFlowGraphBuilder::SetupDefaultParameterValues() {
+  intptr_t num_optional_parameters =
+      parsed_function()->function().NumOptionalParameters();
+  if (num_optional_parameters > 0) {
+    ZoneGrowableArray<const Instance*>* default_values =
+        new ZoneGrowableArray<const Instance*>(Z, num_optional_parameters);
+
+    AlternativeReadingScope alt(reader_);
+    ReadFunctionNodeUntilTypeParameters(
+        &unused_tokenposition, &unused_tokenposition, &unused_word,
+        &unused_word);               // read first part of function node.
+    SkipTypeParametersList();        // read type_parameters.
+    ReadUInt();                      // read total parameter count.
+    intptr_t required = ReadUInt();  // read required_parameter_count.
+
+    if (parsed_function()->function().HasOptionalNamedParameters()) {
+      // List of positional.
+      intptr_t list_length = ReadListLength();  // read list length.
+      for (intptr_t i = 0; i < list_length; ++i) {
+        SkipVariableDeclaration();  // read ith variable declaration.
+      }
+
+      // List of named.
+      list_length = ReadListLength();  // read list length.
+      ASSERT(num_optional_parameters == list_length);
+      ASSERT(!parsed_function()->function().HasOptionalPositionalParameters());
+      for (intptr_t i = 0; i < list_length; ++i) {
+        Instance* default_value;
+
+        // Read ith variable declaration
+        ReadPosition();         // read position.
+        ReadPosition();         // read equals position.
+        ReadFlags();            // read flags.
+        SkipStringReference();  // read name index.
+        SkipDartType();         // read type.
+        Tag tag = ReadTag();    // read (first part of) initializer.
+        if (tag == kSomething) {
+          // this will (potentially) read the initializer,
+          // but reset the position.
+          default_value =
+              &constant_evaluator_.EvaluateExpression(ReaderOffset());
+          SkipExpression();  // read (actual) initializer.
+        } else {
+          default_value = &Instance::ZoneHandle(Z, Instance::null());
+        }
+        default_values->Add(default_value);
+      }
+    } else {
+      // List of positional.
+      intptr_t list_length = ReadListLength();  // read list length.
+      ASSERT(list_length == required + num_optional_parameters);
+      ASSERT(parsed_function()->function().HasOptionalPositionalParameters());
+      for (intptr_t i = 0; i < required; ++i) {
+        SkipVariableDeclaration();  // read ith variable declaration.
+      }
+      for (intptr_t i = 0; i < num_optional_parameters; ++i) {
+        Instance* default_value;
+
+        // Read ith variable declaration
+        ReadPosition();         // read position.
+        ReadPosition();         // read equals position.
+        ReadFlags();            // read flags.
+        SkipStringReference();  // read name index.
+        SkipDartType();         // read type.
+        Tag tag = ReadTag();    // read (first part of) initializer.
+        if (tag == kSomething) {
+          // this will (potentially) read the initializer,
+          // but reset the position.
+          default_value =
+              &constant_evaluator_.EvaluateExpression(ReaderOffset());
+          SkipExpression();  // read (actual) initializer.
+        } else {
+          default_value = &Instance::ZoneHandle(Z, Instance::null());
+        }
+        default_values->Add(default_value);
+      }
+
+      // List of named.
+      list_length = ReadListLength();  // read list length.
+      ASSERT(list_length == 0);
+    }
+    parsed_function()->set_default_parameter_values(default_values);
+  }
+}
+
+Fragment StreamingFlowGraphBuilder::BuildFieldInitializer(
+    NameIndex canonical_name) {
+  dart::Field& field =
+      dart::Field::ZoneHandle(Z, H.LookupFieldByKernelField(canonical_name));
+  if (PeekTag() == kNullLiteral) {
+    SkipExpression();  // read past the null literal.
+    field.RecordStore(Object::null_object());
+    return Fragment();
+  }
+
+  Fragment instructions;
+  instructions += LoadLocal(scopes()->this_variable);
+  instructions += BuildExpression();
+  instructions += flow_graph_builder_->StoreInstanceFieldGuarded(field, true);
+  return instructions;
+}
+
+Fragment StreamingFlowGraphBuilder::BuildInitializers(
+    intptr_t constructor_class_parent_offset) {
+  Fragment instructions;
+
+  // These come from:
+  //   class A {
+  //     var x = (expr);
+  //   }
+  {
+    AlternativeReadingScope alt(reader_, constructor_class_parent_offset);
+    ReadClassUntilFields();                   // read first part of class.
+    intptr_t list_length = ReadListLength();  // read fields list length.
+
+    for (intptr_t i = 0; i < list_length; ++i) {
+      intptr_t field_offset = ReaderOffset();
+      NameIndex canonical_name;
+      TokenPosition position;
+      TokenPosition end_position;
+      word flags;
+      ReadFieldUntilAnnotation(&canonical_name, &position, &end_position,
+                               &flags, &unused_intptr);
+      bool is_static = (flags & Field::kFlagStatic) == Field::kFlagStatic;
+      SkipListOfExpressions();          // read annotations.
+      SkipDartType();                   // read type.
+      Tag initializer_tag = ReadTag();  // read first part of initializer.
+      if (!is_static && initializer_tag == kSomething) {
+        EnterScope(field_offset);
+        instructions +=
+            BuildFieldInitializer(canonical_name);  // read initializer.
+        ExitScope(field_offset);
+      } else if (initializer_tag == kSomething) {
+        SkipExpression();  // read initializer.
+      }
+    }
+  }
+
+  // These to come from:
+  //   class A {
+  //     var x;
+  //     var y;
+  //     A(this.x) : super(expr), y = (expr);
+  //   }
+  {
+    AlternativeReadingScope alt(reader_);
+    SkipFunctionNode();  // read constructors function node.
+
+    intptr_t list_length = ReadListLength();  // read initializers list length.
+    for (intptr_t i = 0; i < list_length; ++i) {
+      Tag tag = ReadTag();
+      switch (tag) {
+        case kInvalidInitializer:
+          UNIMPLEMENTED();
+          return Fragment();
+        case kFieldInitializer: {
+          NameIndex canonical_name =
+              ReadCanonicalNameReference();  // read field_reference.
+          instructions += BuildFieldInitializer(canonical_name);  // read value.
+          break;
+        }
+        case kSuperInitializer: {
+          NameIndex canonical_target =
+              ReadCanonicalNameReference();  // read target_reference.
+
+          instructions += LoadLocal(scopes()->this_variable);
+          instructions += PushArgument();
+
+          // TODO(jensj): ASSERT(init->arguments()->types().length() == 0);
+          Array& argument_names = Array::ZoneHandle(Z);
+          intptr_t argument_count;
+          instructions += BuildArguments(&argument_names,
+                                         &argument_count);  // read arguments.
+          argument_count += 1;
+
+          const Function& target = Function::ZoneHandle(
+              Z, H.LookupConstructorByKernelConstructor(canonical_target));
+          instructions += StaticCall(TokenPosition::kNoSource, target,
+                                     argument_count, argument_names);
+          instructions += Drop();
+          break;
+        }
+        case kRedirectingInitializer: {
+          NameIndex canonical_target =
+              ReadCanonicalNameReference();  // read target_reference.
+
+          instructions += LoadLocal(scopes()->this_variable);
+          instructions += PushArgument();
+
+          // TODO(jensj): ASSERT(init->arguments()->types().length() == 0);
+          Array& argument_names = Array::ZoneHandle(Z);
+          intptr_t argument_count;
+          instructions += BuildArguments(&argument_names,
+                                         &argument_count);  // read arguments.
+          argument_count += 1;
+
+          const Function& target = Function::ZoneHandle(
+              Z, H.LookupConstructorByKernelConstructor(canonical_target));
+          instructions += StaticCall(TokenPosition::kNoSource, target,
+                                     argument_count, argument_names);
+          instructions += Drop();
+          break;
+        }
+        case kLocalInitializer: {
+          // The other initializers following this one might read the variable.
+          // This is used e.g. for evaluating the arguments to a super call
+          // first, run normal field initializers next and then make the actual
+          // super call:
+          //
+          //   The frontend converts
+          //
+          //      class A {
+          //        var x;
+          //        A(a, b) : super(a + b), x = 2*b {}
+          //      }
+          //
+          //   to
+          //
+          //      class A {
+          //        var x;
+          //        A(a, b) : tmp = a + b, x = 2*b, super(tmp) {}
+          //      }
+          //
+          // (This is strictly speaking not what one should do in terms of the
+          //  specification but that is how it is currently implemented.)
+          LocalVariable* variable = LookupVariable(ReaderOffset());
+
+          // Variable declaration
+          ReadPosition();            // read position.
+          ReadPosition();            // read equals position.
+          word flags = ReadFlags();  // read flags.
+          ASSERT((flags & VariableDeclaration::kFlagConst) !=
+                 VariableDeclaration::kFlagConst);
+          SkipStringReference();  // read name index.
+          SkipDartType();         // read type.
+          Tag tag = ReadTag();    // read (first part of) initializer.
+          if (tag != kSomething) {
+            UNREACHABLE();
+          }
+
+          instructions += BuildExpression();  // read initializer.
+          instructions += StoreLocal(TokenPosition::kNoSource, variable);
+          instructions += Drop();
+          break;
+        }
+        default:
+          UNREACHABLE();
+      }
+    }
+  }
+  return instructions;
+}
+
+FlowGraph* StreamingFlowGraphBuilder::BuildGraphOfImplicitClosureFunction(
+    const Function& function) {
+  const Function& target = Function::ZoneHandle(Z, function.parent_function());
+
+  TargetEntryInstr* normal_entry = flow_graph_builder_->BuildTargetEntry();
+  flow_graph_builder_->graph_entry_ = new (Z) GraphEntryInstr(
+      *parsed_function(), normal_entry, Compiler::kNoOSRDeoptId);
+  SetupDefaultParameterValues();
+
+  Fragment body(normal_entry);
+  body += flow_graph_builder_->CheckStackOverflowInPrologue();
+
+  // Load all the arguments.
+  if (!target.is_static()) {
+    // The context has a fixed shape: a single variable which is the
+    // closed-over receiver.
+    body += LoadLocal(parsed_function()->current_context_var());
+    body += flow_graph_builder_->LoadField(Context::variable_offset(0));
+    body += PushArgument();
+  }
+
+  TokenPosition end_position;
+  ReadFunctionNodeUntilTypeParameters(
+      &unused_tokenposition, &end_position, &unused_word,
+      &unused_word);         // read first part of function node.
+  SkipTypeParametersList();  // read type parameter list.
+  ReadUInt();                // read total parameter count.
+  ReadUInt();                // read required_parameter_count.
+
+  // Positional.
+  intptr_t positional_argument_count = ReadListLength();
+  for (intptr_t i = 0; i < positional_argument_count; ++i) {
+    body += LoadLocal(LookupVariable(ReaderOffset()));  // ith variable offset.
+    body += PushArgument();
+    SkipVariableDeclaration();  // read ith variable.
+  }
+
+  // Named.
+  intptr_t named_argument_count = ReadListLength();
+  Array& argument_names = Array::ZoneHandle(Z);
+  if (named_argument_count > 0) {
+    argument_names = Array::New(named_argument_count);
+    for (intptr_t i = 0; i < named_argument_count; ++i) {
+      body +=
+          LoadLocal(LookupVariable(ReaderOffset()));  // ith variable offset.
+      body += PushArgument();
+      argument_names.SetAt(
+          i, H.DartSymbol(GetNameFromVariableDeclaration(ReaderOffset())));
+      SkipVariableDeclaration();  // read ith variable.
+    }
+  }
+
+  // Forward them to the target.
+  intptr_t argument_count = positional_argument_count + named_argument_count;
+  if (!target.is_static()) ++argument_count;
+  body += StaticCall(TokenPosition::kNoSource, target, argument_count,
+                     argument_names);
+
+  // Return the result.
+  body += Return(end_position);
+
+  return new (Z)
+      FlowGraph(*parsed_function(), flow_graph_builder_->graph_entry_,
+                flow_graph_builder_->next_block_id_ - 1);
+}
+
+static bool IsGetMainClosure(const String& name) {
+  if (name.Length() < 16) return false;
+  const char* cstr = "_getMainClosure@";
+  for (intptr_t i = 0; i < 16; ++i) {
+    if (name.CharAt(i) != cstr[i]) return false;
+  }
+  return true;
+}
+
+FlowGraph* StreamingFlowGraphBuilder::BuildGraphOfFunction(
+    bool is_in_builtin_library_toplevel,
+    intptr_t constructor_class_parent_offset) {
+  const Function& dart_function = parsed_function()->function();
+  TargetEntryInstr* normal_entry = flow_graph_builder_->BuildTargetEntry();
+  flow_graph_builder_->graph_entry_ = new (Z) GraphEntryInstr(
+      *parsed_function(), normal_entry, flow_graph_builder_->osr_id_);
+
+  SetupDefaultParameterValues();
+
+  Fragment body;
+  if (!dart_function.is_native())
+    body += flow_graph_builder_->CheckStackOverflowInPrologue();
+  intptr_t context_size =
+      parsed_function()->node_sequence()->scope()->num_context_variables();
+  if (context_size > 0) {
+    body += flow_graph_builder_->PushContext(context_size);
+    LocalVariable* context = MakeTemporary();
+
+    // Copy captured parameters from the stack into the context.
+    LocalScope* scope = parsed_function()->node_sequence()->scope();
+    intptr_t parameter_count = dart_function.NumParameters();
+    intptr_t parameter_index = parsed_function()->first_parameter_index();
+    for (intptr_t i = 0; i < parameter_count; ++i, --parameter_index) {
+      LocalVariable* variable = scope->VariableAt(i);
+      if (variable->is_captured()) {
+        // There is no LocalVariable describing the on-stack parameter so
+        // create one directly and use the same type.
+        LocalVariable* parameter = new (Z)
+            LocalVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
+                          Symbols::TempParam(), variable->type());
+        parameter->set_index(parameter_index);
+        // Mark the stack variable so it will be ignored by the code for
+        // try/catch.
+        parameter->set_is_captured_parameter(true);
+
+        // Copy the parameter from the stack to the context.  Overwrite it
+        // with a null constant on the stack so the original value is
+        // eligible for garbage collection.
+        body += LoadLocal(context);
+        body += LoadLocal(parameter);
+        body += flow_graph_builder_->StoreInstanceField(
+            TokenPosition::kNoSource,
+            Context::variable_offset(variable->index()));
+        body += NullConstant();
+        body += StoreLocal(TokenPosition::kNoSource, parameter);
+        body += Drop();
+      }
+    }
+    body += Drop();  // The context.
+  }
+  if (constructor_class_parent_offset > 0) {
+    // TODO(27590): Currently the [VariableDeclaration]s from the
+    // initializers will be visible inside the entire body of the constructor.
+    // We should make a separate scope for them.
+    body += BuildInitializers(constructor_class_parent_offset);
+  }
+
+  TokenPosition position;
+  ReadFunctionNodeUntilTypeParameters(
+      &position, &unused_tokenposition, &unused_word,
+      &unused_word);         // read first part of function node.
+  SkipTypeParametersList();  // read type parameter list.
+  ReadUInt();                // read total parameter count
+  ReadUInt();                // read required_parameter_count.
+  intptr_t first_parameter_offset = -1;
+  {
+    AlternativeReadingScope alt(reader_);
+    intptr_t list_length = ReadListLength();  // read number of positionals.
+    if (list_length > 0) {
+      first_parameter_offset = ReaderOffset();
+    }
+  }
+  // Current position: About to read list of positionals.
+
+  // The specification defines the result of `a == b` to be:
+  //
+  //   a) if either side is `null` then the result is `identical(a, b)`.
+  //   b) else the result is `a.operator==(b)`
+  //
+  // For user-defined implementations of `operator==` we need therefore
+  // implement the handling of a).
+  //
+  // The default `operator==` implementation in `Object` is implemented in terms
+  // of identical (which we assume here!) which means that case a) is actually
+  // included in b).  So we just use the normal implementation in the body.
+  if ((dart_function.NumParameters() == 2) &&
+      (dart_function.name() == Symbols::EqualOperator().raw()) &&
+      (dart_function.Owner() != I->object_store()->object_class())) {
+    LocalVariable* parameter = LookupVariable(first_parameter_offset);
+
+    TargetEntryInstr* null_entry;
+    TargetEntryInstr* non_null_entry;
+
+    body += LoadLocal(parameter);
+    body += BranchIfNull(&null_entry, &non_null_entry);
+
+    // The argument was `null` and the receiver is not the null class (we only
+    // go into this branch for user-defined == operators) so we can return
+    // false.
+    Fragment null_fragment(null_entry);
+    null_fragment += Constant(Bool::False());
+    null_fragment += Return(dart_function.end_token_pos());
+
+    body = Fragment(body.entry, non_null_entry);
+  }
+
+  // If we run in checked mode, we have to check the type of the passed
+  // arguments.
+  if (I->type_checks()) {
+    // Positional.
+    intptr_t list_length = ReadListLength();
+    for (intptr_t i = 0; i < list_length; ++i) {
+      body +=
+          LoadLocal(LookupVariable(ReaderOffset()));  // ith variable offset.
+      body += CheckVariableTypeInCheckedMode(ReaderOffset());
+      body += Drop();
+      SkipVariableDeclaration();  // read ith variable.
+    }
+
+    // Named.
+    list_length = ReadListLength();
+    for (intptr_t i = 0; i < list_length; ++i) {
+      body +=
+          LoadLocal(LookupVariable(ReaderOffset()));  // ith variable offset.
+      body += CheckVariableTypeInCheckedMode(ReaderOffset());
+      body += Drop();
+      SkipVariableDeclaration();  // read ith variable.
+    }
+  } else {
+    // Still skip past the parameters.
+    SkipListOfVariableDeclarations();  // read list of positionals.
+    SkipListOfVariableDeclarations();  // read list of named.
+  }
+
+  SkipDartType();  // read return type.
+
+  if (FLAG_causal_async_stacks &&
+      (dart_function.IsAsyncFunction() || dart_function.IsAsyncGenerator())) {
+    LocalScope* scope = parsed_function()->node_sequence()->scope();
+    // :async_stack_trace = _asyncStackTraceHelper(:async_op);
+    const dart::Library& async_lib =
+        dart::Library::Handle(dart::Library::AsyncLibrary());
+    const Function& target = Function::ZoneHandle(
+        Z,
+        async_lib.LookupFunctionAllowPrivate(Symbols::AsyncStackTraceHelper()));
+    ASSERT(!target.IsNull());
+
+    // TODO(johnmccutchan): Why does this have the null value?
+    LocalVariable* async_op =
+        scope->child()->LookupVariable(Symbols::AsyncOperation(), false);
+    ASSERT(async_op != NULL);
+    ASSERT(async_op->is_captured());
+    body += LoadLocal(async_op);
+    body += PushArgument();
+    body += StaticCall(TokenPosition::kNoSource, target, 1);
+    LocalVariable* async_stack_trace_var =
+        scope->LookupVariable(Symbols::AsyncStackTraceVar(), false);
+    ASSERT(async_stack_trace_var != NULL);
+    body += StoreLocal(TokenPosition::kNoSource, async_stack_trace_var);
+    body += Drop();
+  }
+
+  bool has_body = ReadTag() == kSomething;  // read first part of body.
+
+  if (dart_function.is_native()) {
+    body += flow_graph_builder_->NativeFunctionBody(first_parameter_offset,
+                                                    dart_function);
+  } else if (has_body) {
+    if (is_in_builtin_library_toplevel &&
+        IsGetMainClosure(dart::String::Handle(Z, dart_function.name()))) {
+      body += BuildGetMainClosure();
+    } else {
+      body += BuildStatement();  // read body.
+    }
+  }
+  if (body.is_open()) {
+    body += NullConstant();
+    body += Return(dart_function.end_token_pos());
+  }
+
+  // If functions body contains any yield points build switch statement that
+  // selects a continuation point based on the value of :await_jump_var.
+  if (!yield_continuations().is_empty()) {
+    // The code we are building will be executed right after we enter
+    // the function and before any nested contexts are allocated.
+    // Reset current context_depth_ to match this.
+    const intptr_t current_context_depth = flow_graph_builder_->context_depth_;
+    flow_graph_builder_->context_depth_ =
+        scopes()->yield_jump_variable->owner()->context_level();
+
+    // Prepend an entry corresponding to normal entry to the function.
+    yield_continuations().InsertAt(
+        0, YieldContinuation(new (Z) DropTempsInstr(0, NULL),
+                             CatchClauseNode::kInvalidTryIndex));
+    yield_continuations()[0].entry->LinkTo(body.entry);
+
+    // Build a switch statement.
+    Fragment dispatch;
+
+    // Load :await_jump_var into a temporary.
+    dispatch += LoadLocal(scopes()->yield_jump_variable);
+    dispatch += StoreLocal(TokenPosition::kNoSource, scopes()->switch_variable);
+    dispatch += Drop();
+
+    BlockEntryInstr* block = NULL;
+    for (intptr_t i = 0; i < yield_continuations().length(); i++) {
+      if (i == 1) {
+        // This is not a normal entry but a resumption.  Restore
+        // :current_context_var from :await_ctx_var.
+        // Note: after this point context_depth_ does not match current context
+        // depth so we should not access any local variables anymore.
+        dispatch += LoadLocal(scopes()->yield_context_variable);
+        dispatch += StoreLocal(TokenPosition::kNoSource,
+                               parsed_function()->current_context_var());
+        dispatch += Drop();
+      }
+      if (i == (yield_continuations().length() - 1)) {
+        // We reached the last possility, no need to build more ifs.
+        // Continue to the last continuation.
+        // Note: continuations start with nop DropTemps instruction
+        // which acts like an anchor, so we need to skip it.
+        block->set_try_index(yield_continuations()[i].try_index);
+        dispatch <<= yield_continuations()[i].entry->next();
+        break;
+      }
+
+      // Build comparison:
+      //
+      //   if (:await_ctx_var == i) {
+      //     -> yield_continuations()[i]
+      //   } else ...
+      //
+      TargetEntryInstr* then;
+      TargetEntryInstr* otherwise;
+      dispatch += LoadLocal(scopes()->switch_variable);
+      dispatch += IntConstant(i);
+      dispatch += flow_graph_builder_->BranchIfStrictEqual(&then, &otherwise);
+
+      // True branch is linked to appropriate continuation point.
+      // Note: continuations start with nop DropTemps instruction
+      // which acts like an anchor, so we need to skip it.
+      then->LinkTo(yield_continuations()[i].entry->next());
+      then->set_try_index(yield_continuations()[i].try_index);
+      // False branch will contain the next comparison.
+      dispatch = Fragment(dispatch.entry, otherwise);
+      block = otherwise;
+    }
+    body = dispatch;
+
+    flow_graph_builder_->context_depth_ = current_context_depth;
+  }
+
+  if (FLAG_causal_async_stacks &&
+      (dart_function.IsAsyncClosure() || dart_function.IsAsyncGenClosure())) {
+    // The code we are building will be executed right after we enter
+    // the function and before any nested contexts are allocated.
+    // Reset current context_depth_ to match this.
+    const intptr_t current_context_depth = flow_graph_builder_->context_depth_;
+    flow_graph_builder_->context_depth_ =
+        scopes()->yield_jump_variable->owner()->context_level();
+
+    Fragment instructions;
+    LocalScope* scope = parsed_function()->node_sequence()->scope();
+
+    const Function& target = Function::ZoneHandle(
+        Z, I->object_store()->async_set_thread_stack_trace());
+    ASSERT(!target.IsNull());
+
+    // Fetch and load :async_stack_trace
+    LocalVariable* async_stack_trace_var =
+        scope->LookupVariable(Symbols::AsyncStackTraceVar(), false);
+    ASSERT((async_stack_trace_var != NULL) &&
+           async_stack_trace_var->is_captured());
+    instructions += LoadLocal(async_stack_trace_var);
+    instructions += PushArgument();
+
+    // Call _asyncSetThreadStackTrace
+    instructions += StaticCall(TokenPosition::kNoSource, target, 1);
+    instructions += Drop();
+
+    // TODO(29737): This sequence should be generated in order.
+    body = instructions + body;
+    flow_graph_builder_->context_depth_ = current_context_depth;
+  }
+
+  if (NeedsDebugStepCheck(dart_function, position)) {
+    const intptr_t current_context_depth = flow_graph_builder_->context_depth_;
+    flow_graph_builder_->context_depth_ = 0;
+
+    // If a switch was added above: Start the switch by injecting a debuggable
+    // safepoint so stepping over an await works.
+    // If not, still start the body with a debuggable safepoint to ensure
+    // breaking on a method always happens, even if there are no
+    // assignments/calls/runtimecalls in the first basic block.
+    // Place this check at the last parameter to ensure parameters
+    // are in scope in the debugger at method entry.
+    const int num_params = dart_function.NumParameters();
+    TokenPosition check_pos = TokenPosition::kNoSource;
+    if (num_params > 0) {
+      LocalScope* scope = parsed_function()->node_sequence()->scope();
+      const LocalVariable& parameter = *scope->VariableAt(num_params - 1);
+      check_pos = parameter.token_pos();
+    }
+    if (!check_pos.IsDebugPause()) {
+      // No parameters or synthetic parameters.
+      check_pos = position;
+      ASSERT(check_pos.IsDebugPause());
+    }
+
+    // TODO(29737): This sequence should be generated in order.
+    body = DebugStepCheck(check_pos) + body;
+    flow_graph_builder_->context_depth_ = current_context_depth;
+  }
+
+  normal_entry->LinkTo(body.entry);
+
+  // When compiling for OSR, use a depth first search to prune instructions
+  // unreachable from the OSR entry. Catch entries are always considered
+  // reachable, even if they become unreachable after OSR.
+  if (flow_graph_builder_->osr_id_ != Compiler::kNoOSRDeoptId) {
+    BitVector* block_marks =
+        new (Z) BitVector(Z, flow_graph_builder_->next_block_id_);
+    bool found = flow_graph_builder_->graph_entry_->PruneUnreachable(
+        flow_graph_builder_->graph_entry_, NULL, flow_graph_builder_->osr_id_,
+        block_marks);
+    ASSERT(found);
+  }
+  return new (Z)
+      FlowGraph(*parsed_function(), flow_graph_builder_->graph_entry_,
+                flow_graph_builder_->next_block_id_ - 1);
+}
+
+Fragment StreamingFlowGraphBuilder::BuildGetMainClosure() {
+  // _getMainClosure in dart:_builtin. Compile that one specially here.
+  const dart::Library& builtin =
+      dart::Library::Handle(Z, I->object_store()->builtin_library());
+  const Object& main =
+      Object::Handle(Z, builtin.LookupObjectAllowPrivate(dart::String::Handle(
+                            Z, dart::String::New("main"))));
+  if (main.IsField()) {
+    UNIMPLEMENTED();
+  } else if (main.IsFunction()) {
+    const Function& function = Function::Cast(main);
+    if (function.kind() == RawFunction::kRegularFunction) {
+      const Function& closure_function =
+          Function::Handle(Z, function.ImplicitClosureFunction());
+      const Instance& closure =
+          Instance::ZoneHandle(Z, closure_function.ImplicitStaticClosure());
+      return Constant(closure) + Return(TokenPosition::kNoSource);
+    } else {
+      UNIMPLEMENTED();
+    }
+  } else {
+    UNIMPLEMENTED();
+  }
+  return Fragment();
+}
+
+FlowGraph* StreamingFlowGraphBuilder::BuildGraph(intptr_t kernel_offset) {
+  const Function& function = parsed_function()->function();
+
+  // Setup a [ActiveClassScope] and a [ActiveMemberScope] which will be used
+  // e.g. for type translation.
+  const dart::Class& klass =
+      dart::Class::Handle(zone_, parsed_function()->function().Owner());
+  bool is_in_builtin_library_toplevel =
+      klass.library() == I->object_store()->builtin_library() &&
+      klass.IsTopLevel();
+
+  Function& outermost_function = Function::Handle(Z);
+  intptr_t outermost_kernel_offset = -1;
+  intptr_t parent_class_offset = -1;
+  DiscoverEnclosingElements(Z, function, &outermost_function,
+                            &outermost_kernel_offset, &parent_class_offset);
+  // Use [klass]/[kernel_class] as active class.  Type parameters will get
+  // resolved via [kernel_class] unless we are nested inside a static factory
+  // in which case we will use [member].
+  intptr_t class_type_parameters = 0;
+  intptr_t class_type_parameters_offset_start = -1;
+  if (parent_class_offset > 0) {
+    GetTypeParameterInfoForClass(parent_class_offset, &class_type_parameters,
+                                 &class_type_parameters_offset_start);
+  }
+
+  ActiveClassScope active_class_scope(active_class(), class_type_parameters,
+                                      class_type_parameters_offset_start,
+                                      &klass);
+
+  bool member_is_procedure = false;
+  bool is_factory_procedure = false;
+  intptr_t member_type_parameters = 0;
+  intptr_t member_type_parameters_offset_start = -1;
+  GetTypeParameterInfoForPossibleProcedure(
+      outermost_kernel_offset, &member_is_procedure, &is_factory_procedure,
+      &member_type_parameters, &member_type_parameters_offset_start);
+
+  ActiveMemberScope active_member(active_class(), member_is_procedure,
+                                  is_factory_procedure, member_type_parameters,
+                                  member_type_parameters_offset_start);
+
+  // The IR builder will create its own local variables and scopes, and it
+  // will not need an AST.  The code generator will assume that there is a
+  // local variable stack slot allocated for the current context and (I
+  // think) that the runtime will expect it to be at a fixed offset which
+  // requires allocating an unused expression temporary variable.
+  set_scopes(parsed_function()->EnsureKernelScopes());
+
+  SetOffset(kernel_offset);
+
+  switch (function.kind()) {
+    case RawFunction::kClosureFunction:
+    case RawFunction::kRegularFunction:
+    case RawFunction::kGetterFunction:
+    case RawFunction::kSetterFunction: {
+      ReadUntilFunctionNode();  // read until function node.
+      return function.IsImplicitClosureFunction()
+                 ? BuildGraphOfImplicitClosureFunction(function)
+                 : BuildGraphOfFunction(is_in_builtin_library_toplevel);
+    }
+    case RawFunction::kConstructor: {
+      bool is_factory = function.IsFactory();
+      if (is_factory) {
+        ReadUntilFunctionNode();  // read until function node.
+        return BuildGraphOfFunction(is_in_builtin_library_toplevel);
+      } else {
+        // Constructor: Pass offset to parent class.
+        return BuildGraphOfFunction(
+            is_in_builtin_library_toplevel,
+            ReadUntilFunctionNode());  // read until function node.
+      }
+    }
+    case RawFunction::kImplicitGetter:
+    case RawFunction::kImplicitStaticFinalGetter:
+    case RawFunction::kImplicitSetter: {
+      return IsStaticInitializer(function, Z)
+                 ? BuildGraphOfStaticFieldInitializer()
+                 : BuildGraphOfFieldAccessor(scopes()->setter_value);
+    }
+    case RawFunction::kMethodExtractor:
+      return flow_graph_builder_->BuildGraphOfMethodExtractor(function);
+    case RawFunction::kNoSuchMethodDispatcher:
+      return flow_graph_builder_->BuildGraphOfNoSuchMethodDispatcher(function);
+    case RawFunction::kInvokeFieldDispatcher:
+      return flow_graph_builder_->BuildGraphOfInvokeFieldDispatcher(function);
+    case RawFunction::kSignatureFunction:
+    case RawFunction::kIrregexpFunction:
+      break;
+  }
+  UNREACHABLE();
+  return NULL;
+}
+
+
 Fragment StreamingFlowGraphBuilder::BuildStatementAt(intptr_t kernel_offset) {
   SetOffset(kernel_offset);
   return BuildStatement();  // read statement.
@@ -2770,9 +3674,7 @@
     case kConstMapLiteral:
       return BuildMapLiteral(true, position);
     case kFunctionExpression:
-      // TODO(jensj)
-      UNIMPLEMENTED();
-      return Fragment();
+      return BuildFunctionExpression();
     case kLet:
       return BuildLet(position);
     case kBigIntLiteral:
@@ -2844,9 +3746,7 @@
     case kVariableDeclaration:
       return BuildVariableDeclaration();
     case kFunctionDeclaration:
-      // TODO(jensj)
-      UNIMPLEMENTED();
-      return Fragment();
+      return BuildFunctionDeclaration();
     default:
       UNREACHABLE();
   }
@@ -3361,6 +4261,7 @@
   ReadByte();                // read async marker.
   ReadByte();                // read dart async marker.
   SkipTypeParametersList();  // read type_parameters.
+  ReadUInt();                // read total parameter count.
   ReadUInt();                // read required_parameter_count.
 
   SkipListOfVariableDeclarations();  // read list of positionals.
@@ -3485,6 +4386,10 @@
   return flow_graph_builder_->scopes_;
 }
 
+void StreamingFlowGraphBuilder::set_scopes(ScopeBuildingResult* scope) {
+  flow_graph_builder_->scopes_ = scope;
+}
+
 ParsedFunction* StreamingFlowGraphBuilder::parsed_function() {
   return flow_graph_builder_->parsed_function_;
 }
@@ -4868,6 +5773,11 @@
   return instructions + StaticCall(position, factory_method, 2);
 }
 
+Fragment StreamingFlowGraphBuilder::BuildFunctionExpression() {
+  intptr_t offset = ReaderOffset() - 1;  // -1 to include tag byte.
+  return BuildFunctionNode(offset, TokenPosition::kNoSource, false, -1);
+}
+
 Fragment StreamingFlowGraphBuilder::BuildLet(TokenPosition* position) {
   if (position != NULL) *position = TokenPosition::kNoSource;
 
@@ -5875,6 +6785,372 @@
   return instructions;
 }
 
+Fragment StreamingFlowGraphBuilder::BuildFunctionDeclaration() {
+  intptr_t offset = ReaderOffset() - 1;     // -1 to include tag byte.
+  TokenPosition position = ReadPosition();  // read position.
+  intptr_t variable_offeset = ReaderOffset();
+  SkipVariableDeclaration();  // read variable declaration.
+
+  Fragment instructions = DebugStepCheck(position);
+  instructions += BuildFunctionNode(offset, position, true, variable_offeset);
+  instructions += StoreLocal(position, LookupVariable(variable_offeset));
+  instructions += Drop();
+  return instructions;
+}
+
+Fragment StreamingFlowGraphBuilder::BuildFunctionNode(
+    intptr_t parent_kernel_offset,
+    TokenPosition parent_position,
+    bool declaration,
+    intptr_t variable_offeset) {
+  intptr_t offset = ReaderOffset();
+
+  TokenPosition position;
+  TokenPosition end_position;
+  word async_marker_word;
+  word dart_async_marker_word;
+  ReadFunctionNodeUntilTypeParameters(
+      &position, &end_position, &async_marker_word,
+      &dart_async_marker_word);  // read first part of function node.
+  FunctionNode::AsyncMarker async_marker =
+      static_cast<FunctionNode::AsyncMarker>(async_marker_word);
+  FunctionNode::AsyncMarker dart_async_marker =
+      static_cast<FunctionNode::AsyncMarker>(dart_async_marker_word);
+
+  if (declaration) {
+    position = parent_position;
+  }
+  if (!position.IsReal()) {
+    // Positions has to be unique in regards to the parent.
+    // A non-real at this point is probably -1, we cannot blindly use that
+    // as others might use it too. Create a new dummy non-real TokenPosition.
+    position = TokenPosition(offset).ToSynthetic();
+  }
+
+  SkipTypeParametersList();  // read type parameters.
+
+  // The VM has a per-isolate table of functions indexed by the enclosing
+  // function and token position.
+  Function& function = Function::ZoneHandle(Z);
+  bool read_rest_of_function_node = false;
+
+  // NOTE: This is not TokenPosition in the general sense!
+  function = I->LookupClosureFunction(parsed_function()->function(), position);
+  if (function.IsNull()) {
+    for (intptr_t i = 0; i < scopes()->function_scopes.length(); ++i) {
+      if (scopes()->function_scopes[i].kernel_offset != offset) {
+        continue;
+      }
+
+      const dart::String* name;
+      if (!declaration) {
+        name = &Symbols::AnonymousClosure();
+      } else {
+        name = &H.DartSymbol(GetNameFromVariableDeclaration(variable_offeset));
+      }
+      // NOTE: This is not TokenPosition in the general sense!
+      function = Function::NewClosureFunction(
+          *name, parsed_function()->function(), position);
+
+      function.set_is_debuggable(dart_async_marker == FunctionNode::kSync);
+      switch (dart_async_marker) {
+        case FunctionNode::kSyncStar:
+          function.set_modifier(RawFunction::kSyncGen);
+          break;
+        case FunctionNode::kAsync:
+          function.set_modifier(RawFunction::kAsync);
+          function.set_is_inlinable(!FLAG_causal_async_stacks);
+          break;
+        case FunctionNode::kAsyncStar:
+          function.set_modifier(RawFunction::kAsyncGen);
+          function.set_is_inlinable(!FLAG_causal_async_stacks);
+          break;
+        default:
+          // no special modifier
+          break;
+      }
+      function.set_is_generated_body(async_marker ==
+                                     FunctionNode::kSyncYielding);
+      if (function.IsAsyncClosure() || function.IsAsyncGenClosure()) {
+        function.set_is_inlinable(!FLAG_causal_async_stacks);
+      }
+
+      function.set_end_token_pos(end_position);
+      LocalScope* scope = scopes()->function_scopes[i].scope;
+      const ContextScope& context_scope = ContextScope::Handle(
+          Z, scope->PreserveOuterScope(flow_graph_builder_->context_depth_));
+      function.set_context_scope(context_scope);
+      function.set_kernel_offset(offset);
+      // Read rest of function node.
+      SetupFunctionParameters(dart::Class::Handle(Z), function,
+                              false,  // is_method
+                              true);  // is_closure
+      read_rest_of_function_node = true;
+      // Finalize function type.
+      Type& signature_type = Type::Handle(Z, function.SignatureType());
+      signature_type ^=
+          ClassFinalizer::FinalizeType(*active_class()->klass, signature_type);
+      function.SetSignatureType(signature_type);
+
+      I->AddClosureFunction(function);
+      break;
+    }
+  }
+
+  if (!read_rest_of_function_node) {
+    ReadUInt();                        // read total parameter count.
+    ReadUInt();                        // read required_parameter_count.
+    SkipListOfVariableDeclarations();  // read list of positionals.
+    SkipListOfVariableDeclarations();  // read list of named.
+    SkipDartType();                    // read return type.
+    if (ReadTag() == kSomething) {     // read first part of body.
+      SkipStatement();                 // read body.
+    }
+  }
+
+  const dart::Class& closure_class =
+      dart::Class::ZoneHandle(Z, I->object_store()->closure_class());
+  ASSERT(!closure_class.IsNull());
+  Fragment instructions =
+      flow_graph_builder_->AllocateObject(closure_class, function);
+  LocalVariable* closure = MakeTemporary();
+
+  // The function signature can have uninstantiated class type parameters.
+  //
+  // TODO(regis): Also handle the case of a function signature that has
+  // uninstantiated function type parameters.
+  if (!function.HasInstantiatedSignature(kCurrentClass)) {
+    instructions += LoadLocal(closure);
+    instructions += LoadInstantiatorTypeArguments();
+    instructions += flow_graph_builder_->StoreInstanceField(
+        TokenPosition::kNoSource,
+        Closure::instantiator_type_arguments_offset());
+  }
+
+  // Store the function and the context in the closure.
+  instructions += LoadLocal(closure);
+  instructions += Constant(function);
+  instructions += flow_graph_builder_->StoreInstanceField(
+      TokenPosition::kNoSource, Closure::function_offset());
+
+  instructions += LoadLocal(closure);
+  instructions += LoadLocal(parsed_function()->current_context_var());
+  instructions += flow_graph_builder_->StoreInstanceField(
+      TokenPosition::kNoSource, Closure::context_offset());
+
+  return instructions;
+}
+
+
+void StreamingFlowGraphBuilder::SetupFunctionParameters(
+    const dart::Class& klass,
+    const dart::Function& function,
+    bool is_method,
+    bool is_closure) {
+  ASSERT(!(is_method && is_closure));
+  bool is_factory = function.IsFactory();
+  intptr_t extra_parameters = (is_method || is_closure || is_factory) ? 1 : 0;
+
+  intptr_t total_parameter_count = ReadUInt();  // read total parameter count.
+  intptr_t required_parameter_count =
+      ReadUInt();  // read required_parameter_count.
+  intptr_t positional_parameters_count = ReadListLength();  // read list length.
+  intptr_t named_parameters_count =
+      total_parameter_count - positional_parameters_count;
+
+  function.set_num_fixed_parameters(extra_parameters +
+                                    required_parameter_count);
+  if (named_parameters_count > 0) {
+    function.SetNumOptionalParameters(named_parameters_count, false);
+  } else {
+    function.SetNumOptionalParameters(
+        positional_parameters_count - required_parameter_count, true);
+  }
+  intptr_t num_parameters = extra_parameters + total_parameter_count;
+  function.set_parameter_types(
+      Array::Handle(Z, Array::New(num_parameters, Heap::kOld)));
+  function.set_parameter_names(
+      Array::Handle(Z, Array::New(num_parameters, Heap::kOld)));
+  intptr_t pos = 0;
+  if (is_method) {
+    ASSERT(!klass.IsNull());
+    function.SetParameterTypeAt(pos, H.GetCanonicalType(klass));
+    function.SetParameterNameAt(pos, Symbols::This());
+    pos++;
+  } else if (is_closure) {
+    function.SetParameterTypeAt(pos, AbstractType::dynamic_type());
+    function.SetParameterNameAt(pos, Symbols::ClosureParameter());
+    pos++;
+  } else if (is_factory) {
+    function.SetParameterTypeAt(pos, AbstractType::dynamic_type());
+    function.SetParameterNameAt(pos, Symbols::TypeArgumentsParameter());
+    pos++;
+  }
+
+  for (intptr_t i = 0; i < positional_parameters_count; ++i, ++pos) {
+    // Read ith variable declaration.
+    ReadPosition();                            // read position.
+    ReadPosition();                            // read equals position.
+    ReadFlags();                               // read flags.
+    StringIndex name = ReadStringReference();  // read name index.
+    const AbstractType& type = T.BuildTypeWithoutFinalization();  // read type.
+    Tag tag = ReadTag();  // read (first part of) initializer.
+    if (tag == kSomething) {
+      SkipExpression();  // read (actual) initializer.
+    }
+
+    function.SetParameterTypeAt(
+        pos, type.IsMalformed() ? Type::dynamic_type() : type);
+    function.SetParameterNameAt(pos, H.DartSymbol(name));
+  }
+
+  intptr_t named_parameters_count_check =
+      ReadListLength();  // read list length.
+  ASSERT(named_parameters_count_check == named_parameters_count);
+  for (intptr_t i = 0; i < named_parameters_count; ++i, ++pos) {
+    // Read ith variable declaration.
+    ReadPosition();                            // read position.
+    ReadPosition();                            // read equals position.
+    ReadFlags();                               // read flags.
+    StringIndex name = ReadStringReference();  // read name index.
+    const AbstractType& type = T.BuildTypeWithoutFinalization();  // read type.
+    Tag tag = ReadTag();  // read (first part of) initializer.
+    if (tag == kSomething) {
+      SkipExpression();  // read (actual) initializer.
+    }
+
+    function.SetParameterTypeAt(
+        pos, type.IsMalformed() ? Type::dynamic_type() : type);
+    function.SetParameterNameAt(pos, H.DartSymbol(name));
+  }
+
+  // The result type for generative constructors has already been set.
+  if (!function.IsGenerativeConstructor()) {
+    const AbstractType& return_type =
+        T.BuildTypeWithoutFinalization();  // read return type.
+    function.set_result_type(return_type.IsMalformed() ? Type::dynamic_type()
+                                                       : return_type);
+  } else {
+    SkipDartType();  // read return type.
+  }
+
+  if (ReadTag() == kSomething) {  // read first part of body.
+    SkipStatement();              // read body.
+  }
+}
+
+RawObject* StreamingFlowGraphBuilder::BuildParameterDescriptor(
+    intptr_t kernel_offset) {
+  SetOffset(kernel_offset);
+  ReadUntilFunctionNode();  // read until function node.
+  ReadFunctionNodeUntilTypeParameters(
+      &unused_tokenposition, &unused_tokenposition, &unused_word,
+      &unused_word);         // read first part of function node.
+  SkipTypeParametersList();  // read type_parameters.
+
+  intptr_t param_count = ReadUInt();  // read total parameter count.
+  ReadUInt();                         // read required_parameter_count.
+  intptr_t positional_count = ReadListLength();  // read list length.
+  intptr_t named_parameters_count = param_count - positional_count;
+
+  const Array& param_descriptor = Array::Handle(
+      Array::New(param_count * Parser::kParameterEntrySize, Heap::kOld));
+  for (intptr_t i = 0; i < param_count; ++i) {
+    const intptr_t entry_start = i * Parser::kParameterEntrySize;
+
+    if (i == positional_count) {
+      intptr_t named_parameters_count_check =
+          ReadListLength();  // read list length.
+      ASSERT(named_parameters_count_check == named_parameters_count);
+    }
+
+    // Read ith variable declaration.
+    ReadPosition();            // read position.
+    ReadPosition();            // read equals position.
+    word flags = ReadFlags();  // read flags.
+    bool is_final = (flags & VariableDeclaration::kFlagFinal) ==
+                    VariableDeclaration::kFlagFinal;
+    param_descriptor.SetAt(entry_start + Parser::kParameterIsFinalOffset,
+                           is_final ? Bool::True() : Bool::False());
+
+    SkipStringReference();  // read name index.
+    SkipDartType();         // read type.
+    Tag tag = ReadTag();    // read (first part of) initializer.
+    if (tag == kSomething) {
+      // this will (potentially) read the initializer, but reset the position.
+      Instance& constant =
+          constant_evaluator_.EvaluateExpression(ReaderOffset());
+      SkipExpression();  // read (actual) initializer.
+      param_descriptor.SetAt(entry_start + Parser::kParameterDefaultValueOffset,
+                             constant);
+    } else {
+      param_descriptor.SetAt(entry_start + Parser::kParameterDefaultValueOffset,
+                             Object::null_instance());
+    }
+
+    param_descriptor.SetAt(entry_start + Parser::kParameterMetadataOffset,
+                           /* Issue(28434): Missing parameter metadata. */
+                           Object::null_instance());
+  }
+  return param_descriptor.raw();
+}
+
+RawObject* StreamingFlowGraphBuilder::EvaluateMetadata(intptr_t kernel_offset) {
+  SetOffset(kernel_offset);
+  const Tag tag = PeekTag();
+
+  if (tag == kClass) {
+    Tag tag = ReadTag();  // read tag.
+    ASSERT(tag == kClass);
+    SkipCanonicalNameReference();  // read canonical name reference.
+    ReadPosition();                // read position.
+    ReadByte();                    // read is_abstract
+    SkipStringReference();         // read name_index.
+    ReadUInt();                    // read source_uri_index.
+    // SkipListOfExpressions();       // read annotations.
+  } else if (tag == kProcedure) {
+    Tag tag = ReadTag();  // read tag.
+    ASSERT(tag == kProcedure);
+    SkipCanonicalNameReference();  // read canonical name reference.
+    ReadPosition();                // read position.
+    ReadPosition();                // read end position.
+    ReadByte();                    // read kind.
+    ReadFlags();                   // read flags.
+    ReadUInt();                    // read parent class binary offset.
+    SkipName();                    // read name,
+    ReadUInt();                    // read source_uri_index.
+    // SkipListOfExpressions();       // read annotations.
+  } else if (tag == kField) {
+    ReadFieldUntilAnnotation(&unused_nameindex, &unused_tokenposition,
+                             &unused_tokenposition, &unused_word,
+                             &unused_intptr);
+    // SkipListOfExpressions();  // read annotations.
+  } else if (tag == kConstructor) {
+    Tag tag = ReadTag();
+    ASSERT(tag == kConstructor);
+    SkipCanonicalNameReference();  // read canonical name reference.
+    ReadPosition();                // read position.
+    ReadPosition();                // read end position.
+    ReadFlags();                   // read flags.
+    ReadUInt();                    // parent class binary offset.
+    SkipName();                    // read name.
+    // SkipListOfExpressions();              // read annotations.
+  } else {
+    FATAL("No support for metadata on this type of kernel node\n");
+  }
+
+  intptr_t list_length = ReadListLength();  // read list length.
+  const Array& metadata_values = Array::Handle(Z, Array::New(list_length));
+  for (intptr_t i = 0; i < list_length; ++i) {
+    // this will (potentially) read the expression, but reset the position.
+    Instance& value = constant_evaluator_.EvaluateExpression(ReaderOffset());
+    SkipExpression();  // read (actual) initializer.
+    metadata_values.SetAt(i, value);
+  }
+
+  return metadata_values.raw();
+}
+
 }  // namespace kernel
 }  // namespace dart
 
diff --git a/runtime/vm/kernel_binary_flowgraph.h b/runtime/vm/kernel_binary_flowgraph.h
index 300787d..4667e51 100644
--- a/runtime/vm/kernel_binary_flowgraph.h
+++ b/runtime/vm/kernel_binary_flowgraph.h
@@ -24,6 +24,8 @@
 
   // Can return a malformed type.
   AbstractType& BuildType();
+  // Can return a malformed type.
+  AbstractType& BuildTypeWithoutFinalization();
   // Is guaranteed to be not malformed.
   AbstractType& BuildVariableType();
 
@@ -101,46 +103,12 @@
 
  private:
   void VisitField();
-  void ReadFieldUntilAnnotation(TokenPosition* position,
-                                TokenPosition* end_position,
-                                word* flags,
-                                intptr_t* parent_offset);
 
-  /**
-   * Will read until the function node; as this is optional, will return the tag
-   * (i.e. either kSomething or kNothing).
-   */
-  Tag ReadProcedureUntilFunctionNode(word* kind, intptr_t* parent_offset);
-  void GetTypeParameterInfoForPossibleProcedure(
-      intptr_t outermost_kernel_offset,
-      bool* member_is_procedure,
-      bool* is_factory_procedure,
-      intptr_t* member_type_parameters,
-      intptr_t* member_type_parameters_offset_start);
   void VisitProcedure();
 
-  /**
-   * Will return binary offset of parent class.
-   */
-  intptr_t ReadConstructorUntilFunctionNode();
   void VisitConstructor();
 
-  void ReadClassUntilTypeParameters();
-  void ReadClassUntilFields();
-
-  void ReadFunctionNodeUntilTypeParameters(word* async_marker,
-                                           word* dart_async_marker);
   void VisitFunctionNode();
-
-  void DiscoverEnclosingElements(Zone* zone,
-                                 const Function& function,
-                                 Function* outermost_function,
-                                 intptr_t* outermost_kernel_offset,
-                                 intptr_t* parent_class_offset);
-  intptr_t GetParentOffset(intptr_t offset);
-  void GetTypeParameterInfoForClass(intptr_t class_offset,
-                                    intptr_t* type_paremeter_counts,
-                                    intptr_t* type_paremeter_offset);
   void VisitNode();
   void VisitInitializer();
   void VisitExpression();
@@ -181,8 +149,6 @@
   void AddIteratorVariable();
   void AddSwitchVariable();
 
-  StringIndex GetNameFromVariableDeclaration(intptr_t kernel_offset);
-
   // Record an assignment or reference to a variable.  If the occurrence is
   // in a nested function, ensure that the variable is handled properly as a
   // captured variable.
@@ -236,9 +202,29 @@
   word unused_word;
   intptr_t unused_intptr;
   TokenPosition unused_tokenposition;
+  NameIndex unused_nameindex;
 };
 
 
+// There are several cases when we are compiling constant expressions:
+//
+//   * constant field initializers:
+//      const FieldName = <expr>;
+//
+//   * constant expressions:
+//      const [<expr>, ...]
+//      const {<expr> : <expr>, ...}
+//      const Constructor(<expr>, ...)
+//
+//   * constant default parameters:
+//      f(a, [b = <expr>])
+//      f(a, {b: <expr>})
+//
+//   * constant values to compare in a [SwitchCase]
+//      case <expr>:
+//
+// In all cases `<expr>` must be recursively evaluated and canonicalized at
+// compile-time.
 class StreamingConstantEvaluator {
  public:
   explicit StreamingConstantEvaluator(StreamingFlowGraphBuilder* builder);
@@ -328,12 +314,6 @@
         constant_evaluator_(this),
         type_translator_(this, /* finalize= */ true) {}
 
-  ~StreamingFlowGraphBuilder() { delete reader_; }
-
-  Fragment BuildExpressionAt(intptr_t kernel_offset);
-  Fragment BuildStatementAt(intptr_t kernel_offset);
-
- private:
   StreamingFlowGraphBuilder(TranslationHelper* translation_helper,
                             Zone* zone,
                             const uint8_t* buffer,
@@ -345,6 +325,69 @@
         constant_evaluator_(this),
         type_translator_(this, /* finalize= */ true) {}
 
+  ~StreamingFlowGraphBuilder() { delete reader_; }
+
+  FlowGraph* BuildGraph(intptr_t kernel_offset);
+
+  Fragment BuildStatementAt(intptr_t kernel_offset);
+  RawObject* BuildParameterDescriptor(intptr_t kernel_offset);
+  RawObject* EvaluateMetadata(intptr_t kernel_offset);
+
+ private:
+  void DiscoverEnclosingElements(Zone* zone,
+                                 const Function& function,
+                                 Function* outermost_function,
+                                 intptr_t* outermost_kernel_offset,
+                                 intptr_t* parent_class_offset);
+  intptr_t GetParentOffset(intptr_t offset);
+  void GetTypeParameterInfoForClass(intptr_t class_offset,
+                                    intptr_t* type_paremeter_counts,
+                                    intptr_t* type_paremeter_offset);
+  void ReadClassUntilFields();
+  void ReadClassUntilTypeParameters();
+  /**
+   * Will return binary offset of parent class.
+   */
+  intptr_t ReadConstructorUntilFunctionNode();
+  /**
+   * Will read until the function node; as this is optional, will return the tag
+   * (i.e. either kSomething or kNothing).
+   */
+  Tag ReadProcedureUntilFunctionNode(word* kind, intptr_t* parent_offset);
+
+  void ReadFieldUntilAnnotation(NameIndex* canonical_name,
+                                TokenPosition* position,
+                                TokenPosition* end_position,
+                                word* flags,
+                                intptr_t* parent_offset);
+  void GetTypeParameterInfoForPossibleProcedure(
+      intptr_t outermost_kernel_offset,
+      bool* member_is_procedure,
+      bool* is_factory_procedure,
+      intptr_t* member_type_parameters,
+      intptr_t* member_type_parameters_offset_start);
+  void ReadFunctionNodeUntilTypeParameters(TokenPosition* position,
+                                           TokenPosition* end_position,
+                                           word* async_marker,
+                                           word* dart_async_marker);
+  /**
+   * Will return kernel offset for parent class if reading a constructor.
+   * Will otherwise return -1.
+   */
+  intptr_t ReadUntilFunctionNode();
+  StringIndex GetNameFromVariableDeclaration(intptr_t kernel_offset);
+
+  FlowGraph* BuildGraphOfStaticFieldInitializer();
+  FlowGraph* BuildGraphOfFieldAccessor(LocalVariable* setter_value);
+  void SetupDefaultParameterValues();
+  Fragment BuildFieldInitializer(NameIndex canonical_name);
+  Fragment BuildInitializers(intptr_t constructor_class_parent_offset);
+  FlowGraph* BuildGraphOfImplicitClosureFunction(const Function& function);
+  FlowGraph* BuildGraphOfFunction(
+      bool is_in_builtin_library_toplevel,
+      intptr_t constructor_class_parent_offset = -1);
+  Fragment BuildGetMainClosure();
+
   Fragment BuildExpression(TokenPosition* position = NULL);
   Fragment BuildStatement();
 
@@ -399,6 +442,7 @@
   CatchBlock* catch_block();
   ActiveClass* active_class();
   ScopeBuildingResult* scopes();
+  void set_scopes(ScopeBuildingResult* scope);
   ParsedFunction* parsed_function();
   TryFinallyBlock* try_finally_block();
   SwitchBlock* switch_block();
@@ -537,6 +581,7 @@
   Fragment BuildThrow(TokenPosition* position);
   Fragment BuildListLiteral(bool is_const, TokenPosition* position);
   Fragment BuildMapLiteral(bool is_const, TokenPosition* position);
+  Fragment BuildFunctionExpression();
   Fragment BuildLet(TokenPosition* position);
   Fragment BuildBigIntLiteral(TokenPosition* position);
   Fragment BuildStringLiteral(TokenPosition* position);
@@ -565,6 +610,15 @@
   Fragment BuildTryFinally();
   Fragment BuildYieldStatement();
   Fragment BuildVariableDeclaration();
+  Fragment BuildFunctionDeclaration();
+  Fragment BuildFunctionNode(intptr_t parent_kernel_offset,
+                             TokenPosition parent_position,
+                             bool declaration,
+                             intptr_t variable_offeset);
+  void SetupFunctionParameters(const dart::Class& klass,
+                               const dart::Function& function,
+                               bool is_method,
+                               bool is_closure);
 
   FlowGraphBuilder* flow_graph_builder_;
   TranslationHelper& translation_helper_;
@@ -573,6 +627,11 @@
   StreamingConstantEvaluator constant_evaluator_;
   StreamingDartTypeTranslator type_translator_;
 
+  word unused_word;
+  intptr_t unused_intptr;
+  TokenPosition unused_tokenposition;
+  NameIndex unused_nameindex;
+
   friend class StreamingConstantEvaluator;
   friend class StreamingDartTypeTranslator;
   friend class StreamingScopeBuilder;
diff --git a/runtime/vm/kernel_reader.cc b/runtime/vm/kernel_reader.cc
index 5f4dd9c..bbc8e1a 100644
--- a/runtime/vm/kernel_reader.cc
+++ b/runtime/vm/kernel_reader.cc
@@ -202,24 +202,6 @@
           Z, library.LookupObjectAllowPrivate(H.DartSymbol("main")));
       ASSERT(!main_obj.IsNull());
 
-      Function& to_patch = Function::Handle(
-          Z, builtin_library.LookupFunctionAllowPrivate(
-                 dart::String::Handle(dart::String::New("_getMainClosure"))));
-
-      Procedure* procedure =
-          reinterpret_cast<Procedure*>(to_patch.kernel_function());
-      // If dart:_builtin was not compiled from Kernel at all it does not need
-      // to be patched.
-      if (procedure != NULL) {
-        // We will handle the StaticGet specially and will not use the name.
-        // Note that we pass "true" in cannot_stream to avoid trying to stream
-        // a non-existing part of the binary.
-        //
-        // TODO(kmillikin): we are leaking the new function body.  Find a way to
-        // deallocate it.
-        procedure->function()->ReplaceBody(
-            new ReturnStatement(new StaticGet(NameIndex(), false), false));
-      }
       return library;
     }
   }
@@ -271,7 +253,7 @@
         Z, dart::Field::NewTopLevel(name, kernel_field->IsFinal(),
                                     kernel_field->IsConst(), script_class,
                                     kernel_field->position()));
-    field.set_kernel_field(kernel_field);
+    field.set_kernel_offset(kernel_field->kernel_offset());
     const AbstractType& type = T.TranslateType(kernel_field->type());
     field.SetFieldType(type);
     field.set_has_initializer(kernel_field->initializer() != NULL);
@@ -423,7 +405,7 @@
                            kernel_field->IsConst(),
                            false,  // is_reflectable
                            script_class, type, kernel_field->position()));
-      field.set_kernel_field(kernel_field);
+      field.set_kernel_offset(kernel_field->kernel_offset());
       field.set_has_initializer(kernel_field->initializer() != NULL);
       GenerateFieldAccessors(klass, field, kernel_field);
       fields_.Add(&field);
@@ -447,7 +429,7 @@
                                klass, kernel_constructor->position()));
     function.set_end_token_pos(kernel_constructor->end_position());
     functions_.Add(&function);
-    function.set_kernel_function(kernel_constructor);
+    function.set_kernel_offset(kernel_constructor->kernel_offset());
     function.set_result_type(T.ReceiverType(klass));
     SetupFunctionParameters(H, T, klass, function,
                             kernel_constructor->function(),
@@ -456,7 +438,7 @@
 
     if (FLAG_enable_mirrors) {
       library.AddFunctionMetadata(function, TokenPosition::kNoSource,
-                                  kernel_constructor);
+                                  kernel_constructor->kernel_offset());
     }
   }
 
@@ -474,7 +456,7 @@
 
   if (FLAG_enable_mirrors) {
     library.AddClassMetadata(klass, toplevel_class, TokenPosition::kNoSource,
-                             kernel_klass);
+                             kernel_klass->kernel_offset());
   }
 
   return klass;
@@ -533,7 +515,7 @@
                        script_class, kernel_procedure->position()));
   function.set_end_token_pos(kernel_procedure->end_position());
   functions_.Add(&function);
-  function.set_kernel_function(kernel_procedure);
+  function.set_kernel_offset(kernel_procedure->kernel_offset());
 
   function.set_is_debuggable(
       kernel_procedure->function()->dart_async_marker() == FunctionNode::kSync);
@@ -572,7 +554,7 @@
   }
   if (FLAG_enable_mirrors) {
     library.AddFunctionMetadata(function, TokenPosition::kNoSource,
-                                kernel_procedure);
+                                kernel_procedure->kernel_offset());
   }
 }
 
@@ -642,6 +624,8 @@
         H.DartString(source_buffer, source_size, Heap::kOld);
     script = Script::New(import_uri_string, uri_string, source_code,
                          RawScript::kKernelTag);
+    script.set_kernel_data(program_->libraries()[0]->kernel_data());
+    script.set_kernel_data_size(program_->libraries()[0]->kernel_data_size());
     script.set_kernel_string_offsets(H.string_offsets());
     script.set_kernel_string_data(H.string_data());
     script.set_kernel_canonical_names(H.canonical_names());
@@ -729,7 +713,7 @@
           script_class, kernel_field->position()));
   functions_.Add(&getter);
   getter.set_end_token_pos(kernel_field->end_position());
-  getter.set_kernel_function(kernel_field);
+  getter.set_kernel_offset(kernel_field->kernel_offset());
   getter.set_result_type(AbstractType::Handle(Z, field.type()));
   getter.set_is_debuggable(false);
   SetupFieldAccessorFunction(klass, getter);
@@ -749,7 +733,7 @@
                          script_class, kernel_field->position()));
     functions_.Add(&setter);
     setter.set_end_token_pos(kernel_field->end_position());
-    setter.set_kernel_function(kernel_field);
+    setter.set_kernel_offset(kernel_field->kernel_offset());
     setter.set_result_type(Object::void_type());
     setter.set_is_debuggable(false);
     SetupFieldAccessorFunction(klass, setter);
@@ -916,8 +900,6 @@
 ParsedFunction* ParseStaticFieldInitializer(Zone* zone,
                                             const dart::Field& field) {
   Thread* thread = Thread::Current();
-  kernel::Field* kernel_field = kernel::Field::Cast(
-      reinterpret_cast<kernel::Node*>(field.kernel_field()));
 
   dart::String& init_name = dart::String::Handle(zone, field.name());
   init_name = Symbols::FromConcat(thread, Symbols::InitPrefix(), init_name);
@@ -933,7 +915,7 @@
                           false,  // is_external
                           false,  // is_native
                           owner, TokenPosition::kNoSource));
-  initializer_fun.set_kernel_function(kernel_field);
+  initializer_fun.set_kernel_offset(field.kernel_offset());
   initializer_fun.set_result_type(AbstractType::Handle(zone, field.type()));
   initializer_fun.set_is_debuggable(false);
   initializer_fun.set_is_reflectable(false);
diff --git a/runtime/vm/kernel_to_il.cc b/runtime/vm/kernel_to_il.cc
index 5b10f05..f9f4e35 100644
--- a/runtime/vm/kernel_to_il.cc
+++ b/runtime/vm/kernel_to_il.cc
@@ -30,40 +30,6 @@
 #define I Isolate::Current()
 
 
-static void DiscoverEnclosingElements(Zone* zone,
-                                      const Function& function,
-                                      Function* outermost_function,
-                                      TreeNode** outermost_node,
-                                      Class** klass) {
-  // Find out if there is an enclosing kernel class (which will be used to
-  // resolve type parameters).
-  *outermost_function = function.raw();
-  while (outermost_function->parent_function() != Object::null()) {
-    *outermost_function = outermost_function->parent_function();
-  }
-  *outermost_node =
-      static_cast<TreeNode*>(outermost_function->kernel_function());
-  if (*outermost_node != NULL) {
-    TreeNode* parent = NULL;
-    if ((*outermost_node)->IsProcedure()) {
-      parent = Procedure::Cast(*outermost_node)->parent();
-    } else if ((*outermost_node)->IsConstructor()) {
-      parent = Constructor::Cast(*outermost_node)->parent();
-    } else if ((*outermost_node)->IsField()) {
-      parent = Field::Cast(*outermost_node)->parent();
-    }
-    if (parent != NULL && parent->IsClass()) *klass = Class::Cast(parent);
-  }
-}
-
-
-static bool IsStaticInitializer(const Function& function, Zone* zone) {
-  return (function.kind() == RawFunction::kImplicitStaticFinalGetter) &&
-         dart::String::Handle(zone, function.name())
-             .StartsWith(Symbols::InitPrefix());
-}
-
-
 Fragment& Fragment::operator+=(const Fragment& other) {
   if (entry == NULL) {
     entry = other.entry;
@@ -684,581 +650,9 @@
   return names;
 }
 
-ConstantEvaluator::ConstantEvaluator(FlowGraphBuilder* builder,
-                                     Zone* zone,
-                                     TranslationHelper* h,
-                                     DartTypeTranslator* type_translator)
-    : builder_(builder),
-      isolate_(Isolate::Current()),
-      zone_(zone),
-      translation_helper_(*h),
-      type_translator_(*type_translator),
-      script_(Script::Handle(
-          zone,
-          builder == NULL ? Script::null()
-                          : builder_->parsed_function_->function().script())),
-      result_(Instance::Handle(zone)) {}
-
-
-Instance& ConstantEvaluator::EvaluateExpression(Expression* expression) {
-  if (!GetCachedConstant(expression, &result_)) {
-    expression->AcceptExpressionVisitor(this);
-    CacheConstantValue(expression, result_);
-  }
-  // 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 Instance::ZoneHandle(Z, result_.raw());
-}
-
-
-Object& ConstantEvaluator::EvaluateExpressionSafe(Expression* expression) {
-  LongJumpScope jump;
-  if (setjmp(*jump.Set()) == 0) {
-    return EvaluateExpression(expression);
-  } else {
-    Thread* thread = H.thread();
-    Error& error = Error::Handle(Z);
-    error = thread->sticky_error();
-    thread->clear_sticky_error();
-    return error;
-  }
-}
-
-
-Instance& ConstantEvaluator::EvaluateConstructorInvocation(
-    ConstructorInvocation* node) {
-  if (!GetCachedConstant(node, &result_)) {
-    VisitConstructorInvocation(node);
-    CacheConstantValue(node, result_);
-  }
-  // 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 Instance::ZoneHandle(Z, result_.raw());
-}
-
-
-Instance& ConstantEvaluator::EvaluateListLiteral(ListLiteral* node) {
-  if (!GetCachedConstant(node, &result_)) {
-    VisitListLiteral(node);
-    CacheConstantValue(node, result_);
-  }
-  // 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 Instance::ZoneHandle(Z, result_.raw());
-}
-
-
-Instance& ConstantEvaluator::EvaluateMapLiteral(MapLiteral* node) {
-  if (!GetCachedConstant(node, &result_)) {
-    VisitMapLiteral(node);
-    CacheConstantValue(node, result_);
-  }
-  // 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 Instance::ZoneHandle(Z, result_.raw());
-}
-
-
-void ConstantEvaluator::VisitBigintLiteral(BigintLiteral* node) {
-  const dart::String& value = H.DartString(node->value());
-  result_ = Integer::New(value, Heap::kOld);
-  result_ = H.Canonicalize(result_);
-}
-
-
-void ConstantEvaluator::VisitBoolLiteral(BoolLiteral* node) {
-  result_ = Bool::Get(node->value()).raw();
-}
-
-
-void ConstantEvaluator::VisitDoubleLiteral(DoubleLiteral* node) {
-  result_ = Double::New(H.DartString(node->value()), Heap::kOld);
-  result_ = H.Canonicalize(result_);
-}
-
-
-void ConstantEvaluator::VisitIntLiteral(IntLiteral* node) {
-  result_ = Integer::New(node->value(), Heap::kOld);
-  result_ = H.Canonicalize(result_);
-}
-
-
-void ConstantEvaluator::VisitNullLiteral(NullLiteral* node) {
-  result_ = Instance::null();
-}
-
-
-void ConstantEvaluator::VisitStringLiteral(StringLiteral* node) {
-  result_ = H.DartSymbol(node->value()).raw();
-}
-
-
-void ConstantEvaluator::VisitTypeLiteral(TypeLiteral* node) {
-  const AbstractType& type = T.TranslateType(node->type());
-  if (type.IsMalformed()) {
-    H.ReportError("Malformed type literal in constant expression.");
-  }
-  result_ = type.raw();
-}
-
-
-RawObject* ConstantEvaluator::EvaluateConstConstructorCall(
-    const dart::Class& type_class,
-    const TypeArguments& type_arguments,
-    const Function& constructor,
-    const Object& argument) {
-  // Factories have one extra argument: the type arguments.
-  // Constructors have 1 extra arguments: receiver.
-  const int kTypeArgsLen = 0;
-  const int kNumArgs = 1;
-  const int kNumExtraArgs = 1;
-  const int num_arguments = kNumArgs + kNumExtraArgs;
-  const Array& arg_values =
-      Array::Handle(Z, Array::New(num_arguments, Heap::kOld));
-  Instance& instance = Instance::Handle(Z);
-  if (!constructor.IsFactory()) {
-    instance = Instance::New(type_class, Heap::kOld);
-    if (!type_arguments.IsNull()) {
-      ASSERT(type_arguments.IsInstantiated());
-      instance.SetTypeArguments(
-          TypeArguments::Handle(Z, type_arguments.Canonicalize()));
-    }
-    arg_values.SetAt(0, instance);
-  } else {
-    // Prepend type_arguments to list of arguments to factory.
-    ASSERT(type_arguments.IsZoneHandle());
-    arg_values.SetAt(0, type_arguments);
-  }
-  arg_values.SetAt((0 + kNumExtraArgs), argument);
-  const Array& args_descriptor =
-      Array::Handle(Z, ArgumentsDescriptor::New(kTypeArgsLen, num_arguments,
-                                                Object::empty_array()));
-  const Object& result = Object::Handle(
-      Z, DartEntry::InvokeFunction(constructor, arg_values, args_descriptor));
-  ASSERT(!result.IsError());
-  if (constructor.IsFactory()) {
-    // The factory method returns the allocated object.
-    instance ^= result.raw();
-  }
-  return H.Canonicalize(instance);
-}
-
-
-bool ConstantEvaluator::GetCachedConstant(TreeNode* node, Instance* value) {
-  if (builder_ == NULL) return false;
-
-  const Function& function = builder_->parsed_function_->function();
-  if (function.kind() == RawFunction::kImplicitStaticFinalGetter) {
-    // Don't cache constants in initializer expressions. They get
-    // evaluated only once.
-    return false;
-  }
-
-  bool is_present = false;
-  ASSERT(!script_.InVMHeap());
-  if (script_.compile_time_constants() == Array::null()) {
-    return false;
-  }
-  KernelConstantsMap constants(script_.compile_time_constants());
-  *value ^= constants.GetOrNull(node->kernel_offset(), &is_present);
-  // Mutator compiler thread may add constants while background compiler
-  // is running, and thus change the value of 'compile_time_constants';
-  // do not assert that 'compile_time_constants' has not changed.
-  constants.Release();
-  if (FLAG_compiler_stats && is_present) {
-    H.thread()->compiler_stats()->num_const_cache_hits++;
-  }
-  return is_present;
-}
-
-
-void ConstantEvaluator::CacheConstantValue(TreeNode* node,
-                                           const Instance& value) {
-  ASSERT(Thread::Current()->IsMutatorThread());
-
-  if (builder_ == NULL) return;
-
-  const Function& function = builder_->parsed_function_->function();
-  if (function.kind() == RawFunction::kImplicitStaticFinalGetter) {
-    // Don't cache constants in initializer expressions. They get
-    // evaluated only once.
-    return;
-  }
-  const intptr_t kInitialConstMapSize = 16;
-  ASSERT(!script_.InVMHeap());
-  if (script_.compile_time_constants() == Array::null()) {
-    const Array& array = Array::Handle(
-        HashTables::New<KernelConstantsMap>(kInitialConstMapSize, Heap::kNew));
-    script_.set_compile_time_constants(array);
-  }
-  KernelConstantsMap constants(script_.compile_time_constants());
-  constants.InsertNewOrGetValue(node->kernel_offset(), value);
-  script_.set_compile_time_constants(constants.Release());
-}
-
-
-void ConstantEvaluator::VisitSymbolLiteral(SymbolLiteral* node) {
-  const dart::String& symbol_value = H.DartSymbol(node->value());
-
-  const dart::Class& symbol_class =
-      dart::Class::ZoneHandle(Z, I->object_store()->symbol_class());
-  ASSERT(!symbol_class.IsNull());
-  const Function& symbol_constructor = Function::ZoneHandle(
-      Z, symbol_class.LookupConstructor(Symbols::SymbolCtor()));
-  ASSERT(!symbol_constructor.IsNull());
-  result_ ^= EvaluateConstConstructorCall(
-      symbol_class, TypeArguments::Handle(Z), symbol_constructor, symbol_value);
-}
-
-
-void ConstantEvaluator::VisitListLiteral(ListLiteral* node) {
-  DartType* types[] = {node->type()};
-  const TypeArguments& type_arguments = T.TranslateTypeArguments(types, 1);
-
-  intptr_t length = node->expressions().length();
-  const Array& const_list =
-      Array::ZoneHandle(Z, Array::New(length, Heap::kOld));
-  const_list.SetTypeArguments(type_arguments);
-  for (intptr_t i = 0; i < length; i++) {
-    const Instance& expression = EvaluateExpression(node->expressions()[i]);
-    const_list.SetAt(i, expression);
-  }
-  const_list.MakeImmutable();
-  result_ = H.Canonicalize(const_list);
-}
-
-
-void ConstantEvaluator::VisitMapLiteral(MapLiteral* node) {
-  DartType* types[] = {node->key_type(), node->value_type()};
-  const TypeArguments& type_arguments = T.TranslateTypeArguments(types, 2);
-
-  intptr_t length = node->entries().length();
-
-  Array& const_kv_array =
-      Array::ZoneHandle(Z, Array::New(2 * length, Heap::kOld));
-  for (intptr_t i = 0; i < length; i++) {
-    const_kv_array.SetAt(2 * i + 0,
-                         EvaluateExpression(node->entries()[i]->key()));
-    const_kv_array.SetAt(2 * i + 1,
-                         EvaluateExpression(node->entries()[i]->value()));
-  }
-
-  const_kv_array.MakeImmutable();
-  const_kv_array ^= H.Canonicalize(const_kv_array);
-
-  const dart::Class& map_class = dart::Class::Handle(
-      Z, dart::Library::LookupCoreClass(Symbols::ImmutableMap()));
-  ASSERT(!map_class.IsNull());
-  ASSERT(map_class.NumTypeArguments() == 2);
-
-  const dart::Field& field = dart::Field::Handle(
-      Z, map_class.LookupInstanceFieldAllowPrivate(H.DartSymbol("_kvPairs")));
-  ASSERT(!field.IsNull());
-
-  // NOTE: This needs to be kept in sync with `runtime/lib/immutable_map.dart`!
-  result_ = Instance::New(map_class, Heap::kOld);
-  ASSERT(!result_.IsNull());
-  result_.SetTypeArguments(type_arguments);
-  result_.SetField(field, const_kv_array);
-  result_ = H.Canonicalize(result_);
-}
-
-
-void ConstantEvaluator::VisitConstructorInvocation(
-    ConstructorInvocation* node) {
-  Arguments* kernel_arguments = node->arguments();
-
-  const Function& constructor = Function::Handle(
-      Z, H.LookupConstructorByKernelConstructor(node->target()));
-  dart::Class& klass = dart::Class::Handle(Z, constructor.Owner());
-
-  // Build the type arguments vector (if necessary).
-  const TypeArguments* type_arguments =
-      TranslateTypeArguments(constructor, &klass, kernel_arguments);
-
-  // Prepare either the instance or the type argument vector for the constructor
-  // call.
-  Instance* receiver = NULL;
-  const TypeArguments* type_arguments_argument = NULL;
-  if (!constructor.IsFactory()) {
-    receiver = &Instance::ZoneHandle(Z, Instance::New(klass, Heap::kOld));
-    if (type_arguments != NULL) {
-      receiver->SetTypeArguments(*type_arguments);
-    }
-  } else {
-    type_arguments_argument = type_arguments;
-  }
-
-  const Object& result = RunFunction(constructor, kernel_arguments, receiver,
-                                     type_arguments_argument);
-  if (constructor.IsFactory()) {
-    // Factories return the new object.
-    result_ ^= result.raw();
-    result_ = H.Canonicalize(result_);
-  } else {
-    ASSERT(!receiver->IsNull());
-    result_ = H.Canonicalize(*receiver);
-  }
-}
-
-
-void ConstantEvaluator::VisitMethodInvocation(MethodInvocation* node) {
-  Arguments* kernel_arguments = node->arguments();
-
-  // Dart does not support generic methods yet.
-  ASSERT(kernel_arguments->types().length() == 0);
-
-  const Instance& receiver = EvaluateExpression(node->receiver());
-  dart::Class& klass = dart::Class::Handle(
-      Z, isolate_->class_table()->At(receiver.GetClassId()));
-  ASSERT(!klass.IsNull());
-
-  // Search the superclass chain for the selector.
-  Function& function = Function::Handle(Z);
-  const dart::String& method_name = H.DartMethodName(node->name());
-  while (!klass.IsNull()) {
-    function = klass.LookupDynamicFunctionAllowPrivate(method_name);
-    if (!function.IsNull()) break;
-    klass = klass.SuperClass();
-  }
-
-  // The frontend should guarantee that [MethodInvocation]s inside constant
-  // expressions are always valid.
-  ASSERT(!function.IsNull());
-
-  // Run the method and canonicalize the result.
-  const Object& result = RunFunction(function, kernel_arguments, &receiver);
-  result_ ^= result.raw();
-  result_ = H.Canonicalize(result_);
-}
-
-
-void ConstantEvaluator::VisitStaticGet(StaticGet* node) {
-  NameIndex target = node->target();
-  if (H.IsField(target)) {
-    const dart::Field& field =
-        dart::Field::Handle(Z, H.LookupFieldByKernelField(target));
-    if (field.StaticValue() == Object::sentinel().raw() ||
-        field.StaticValue() == Object::transition_sentinel().raw()) {
-      field.EvaluateInitializer();
-      result_ = field.StaticValue();
-      result_ = H.Canonicalize(result_);
-      field.SetStaticValue(result_, true);
-    } else {
-      result_ = field.StaticValue();
-    }
-  } else if (H.IsProcedure(target)) {
-    const Function& function =
-        Function::ZoneHandle(Z, H.LookupStaticMethodByKernelProcedure(target));
-
-    if (H.IsMethod(target)) {
-      Function& closure_function =
-          Function::ZoneHandle(Z, function.ImplicitClosureFunction());
-      closure_function.set_kernel_function(function.kernel_function());
-      result_ = closure_function.ImplicitStaticClosure();
-      result_ = H.Canonicalize(result_);
-    } else if (H.IsGetter(target)) {
-      UNIMPLEMENTED();
-    } else {
-      UNIMPLEMENTED();
-    }
-  }
-}
-
-
-void ConstantEvaluator::VisitVariableGet(VariableGet* node) {
-  // When we see a [VariableGet] the corresponding [VariableDeclaration] must've
-  // been executed already. It therefore must have a constant object associated
-  // with it.
-  LocalVariable* variable = builder_->LookupVariable(node->variable());
-  ASSERT(variable->IsConst());
-  result_ = variable->ConstValue()->raw();
-}
-
-
-void ConstantEvaluator::VisitLet(Let* node) {
-  VariableDeclaration* variable = node->variable();
-  LocalVariable* local = builder_->LookupVariable(variable);
-  local->SetConstValue(EvaluateExpression(variable->initializer()));
-  node->body()->AcceptExpressionVisitor(this);
-}
-
-
-void ConstantEvaluator::VisitStaticInvocation(StaticInvocation* node) {
-  const Function& function = Function::ZoneHandle(
-      Z, H.LookupStaticMethodByKernelProcedure(node->procedure()));
-  dart::Class& klass = dart::Class::Handle(Z, function.Owner());
-
-  // Build the type arguments vector (if necessary).
-  const TypeArguments* type_arguments =
-      TranslateTypeArguments(function, &klass, node->arguments());
-
-  const Object& result =
-      RunFunction(function, node->arguments(), NULL, type_arguments);
-  result_ ^= result.raw();
-  result_ = H.Canonicalize(result_);
-}
-
-
-void ConstantEvaluator::VisitStringConcatenation(StringConcatenation* node) {
-  intptr_t length = node->expressions().length();
-
-  bool all_string = true;
-  const Array& strings = Array::Handle(Z, Array::New(length));
-  for (intptr_t i = 0; i < length; i++) {
-    EvaluateExpression(node->expressions()[i]);
-    strings.SetAt(i, result_);
-    all_string = all_string && result_.IsString();
-  }
-  if (all_string) {
-    result_ = dart::String::ConcatAll(strings, Heap::kOld);
-    result_ = H.Canonicalize(result_);
-  } else {
-    // Get string interpolation function.
-    const dart::Class& cls = dart::Class::Handle(
-        Z, dart::Library::LookupCoreClass(Symbols::StringBase()));
-    ASSERT(!cls.IsNull());
-    const Function& func = Function::Handle(
-        Z, cls.LookupStaticFunction(
-               dart::Library::PrivateCoreLibName(Symbols::Interpolate())));
-    ASSERT(!func.IsNull());
-
-    // Build argument array to pass to the interpolation function.
-    const Array& interpolate_arg = Array::Handle(Z, Array::New(1, Heap::kOld));
-    interpolate_arg.SetAt(0, strings);
-
-    // Run and canonicalize.
-    const Object& result =
-        RunFunction(func, interpolate_arg, Array::null_array());
-    result_ = H.Canonicalize(dart::String::Cast(result));
-  }
-}
-
-
-void ConstantEvaluator::VisitConditionalExpression(
-    ConditionalExpression* node) {
-  if (EvaluateBooleanExpression(node->condition())) {
-    EvaluateExpression(node->then());
-  } else {
-    EvaluateExpression(node->otherwise());
-  }
-}
-
-
-void ConstantEvaluator::VisitLogicalExpression(LogicalExpression* node) {
-  if (node->op() == LogicalExpression::kAnd) {
-    if (EvaluateBooleanExpression(node->left())) {
-      EvaluateBooleanExpression(node->right());
-    }
-  } else {
-    ASSERT(node->op() == LogicalExpression::kOr);
-    if (!EvaluateBooleanExpression(node->left())) {
-      EvaluateBooleanExpression(node->right());
-    }
-  }
-}
-
-
-void ConstantEvaluator::VisitNot(Not* node) {
-  result_ ^= Bool::Get(!EvaluateBooleanExpression(node->expression())).raw();
-}
-
-
-void ConstantEvaluator::VisitPropertyGet(PropertyGet* node) {
-  StringIndex string_index = node->name()->string_index();
-  if (H.StringEquals(string_index, "length")) {
-    node->receiver()->AcceptExpressionVisitor(this);
-    if (result_.IsString()) {
-      const dart::String& str =
-          dart::String::Handle(Z, dart::String::RawCast(result_.raw()));
-      result_ = Integer::New(str.Length());
-    } else {
-      H.ReportError(
-          "Constant expressions can only call "
-          "'length' on string constants.");
-    }
-  } else {
-    VisitDefaultExpression(node);
-  }
-}
-
-
-const TypeArguments* ConstantEvaluator::TranslateTypeArguments(
-    const Function& target,
-    dart::Class* target_klass,
-    Arguments* kernel_arguments) {
-  List<DartType>& kernel_type_arguments = kernel_arguments->types();
-
-  const TypeArguments* type_arguments = NULL;
-  if (kernel_type_arguments.length() > 0) {
-    type_arguments = &T.TranslateInstantiatedTypeArguments(
-        *target_klass, kernel_type_arguments.raw_array(),
-        kernel_type_arguments.length());
-
-    if (!(type_arguments->IsNull() || type_arguments->IsInstantiated())) {
-      H.ReportError("Type must be constant in const constructor.");
-    }
-  } else if (target.IsFactory() && type_arguments == NULL) {
-    // All factories take a type arguments vector as first argument (independent
-    // of whether the class is generic or not).
-    type_arguments = &TypeArguments::ZoneHandle(Z, TypeArguments::null());
-  }
-  return type_arguments;
-}
-
-
-const Object& ConstantEvaluator::RunFunction(const Function& function,
-                                             Arguments* kernel_arguments,
-                                             const Instance* receiver,
-                                             const TypeArguments* type_args) {
-  // We do not support generic methods yet.
-  ASSERT((receiver == NULL) || (type_args == NULL));
-  intptr_t extra_arguments =
-      (receiver != NULL ? 1 : 0) + (type_args != NULL ? 1 : 0);
-
-  // Build up arguments.
-  const Array& arguments = Array::ZoneHandle(
-      Z, Array::New(extra_arguments + kernel_arguments->count()));
-  const Array& names =
-      Array::ZoneHandle(Z, Array::New(kernel_arguments->named().length()));
-  intptr_t pos = 0;
-  if (receiver != NULL) {
-    arguments.SetAt(pos++, *receiver);
-  }
-  if (type_args != NULL) {
-    arguments.SetAt(pos++, *type_args);
-  }
-  for (intptr_t i = 0; i < kernel_arguments->positional().length(); i++) {
-    EvaluateExpression(kernel_arguments->positional()[i]);
-    arguments.SetAt(pos++, result_);
-  }
-  for (intptr_t i = 0; i < kernel_arguments->named().length(); i++) {
-    NamedExpression* named_expression = kernel_arguments->named()[i];
-    EvaluateExpression(named_expression->expression());
-    arguments.SetAt(pos++, result_);
-    names.SetAt(i, H.DartSymbol(named_expression->name()));
-  }
-  return RunFunction(function, arguments, names);
-}
-
-
-const Object& ConstantEvaluator::RunFunction(const Function& function,
-                                             const Array& arguments,
-                                             const Array& names) {
-  const int kTypeArgsLen = 0;  // Generic functions not yet supported.
-  const Array& args_descriptor = Array::Handle(
-      Z, ArgumentsDescriptor::New(kTypeArgsLen, arguments.Length(), names));
-  const Object& result = Object::Handle(
-      Z, DartEntry::InvokeFunction(function, arguments, args_descriptor));
-  if (result.IsError()) {
-    H.ReportError(Error::Cast(result), "error evaluating constant constructor");
-  }
-  return result;
-}
-
 
 FlowGraphBuilder::FlowGraphBuilder(
-    TreeNode* node,
+    intptr_t kernel_offset,
     ParsedFunction* parsed_function,
     const ZoneGrowableArray<const ICData*>& ic_data_array,
     ZoneGrowableArray<intptr_t>* context_level_array,
@@ -1268,7 +662,7 @@
     : translation_helper_(Thread::Current()),
       thread_(translation_helper_.thread()),
       zone_(translation_helper_.zone()),
-      node_(node),
+      kernel_offset_(kernel_offset),
       parsed_function_(parsed_function),
       osr_id_(osr_id),
       ic_data_array_(ic_data_array),
@@ -1294,7 +688,6 @@
       type_translator_(&translation_helper_,
                        &active_class_,
                        /* finalize= */ true),
-      constant_evaluator_(this, zone_, &translation_helper_, &type_translator_),
       streaming_flow_graph_builder_(NULL) {
   Script& script = Script::Handle(Z, parsed_function->function().script());
   H.SetStringOffsets(TypedData::Handle(Z, script.kernel_string_offsets()));
@@ -1349,9 +742,7 @@
         try_finally_block_->finalizer_kernel_offset();
     try_finally_block_ = try_finally_block_->outer();
     if (finalizer != NULL) {
-      // This will potentially have exceptional cases as described in
-      // [VisitTryFinally] and will handle them.
-      instructions += TranslateStatement(finalizer);
+      UNREACHABLE();
     } else {
       instructions += streaming_flow_graph_builder_->BuildStatementAt(
           finalizer_kernel_offset);
@@ -1378,11 +769,6 @@
 }
 
 
-Fragment FlowGraphBuilder::EnterScope(TreeNode* node, bool* new_context) {
-  return EnterScope(node->kernel_offset(), new_context);
-}
-
-
 Fragment FlowGraphBuilder::EnterScope(intptr_t kernel_offset,
                                       bool* new_context) {
   Fragment instructions;
@@ -1399,11 +785,6 @@
 }
 
 
-Fragment FlowGraphBuilder::ExitScope(TreeNode* node) {
-  return ExitScope(node->kernel_offset());
-}
-
-
 Fragment FlowGraphBuilder::ExitScope(intptr_t kernel_offset) {
   Fragment instructions;
   const intptr_t context_size =
@@ -1474,8 +855,7 @@
 #endif
     instructions += LoadLocal(scopes_->type_arguments_variable);
   } else if (scopes_->this_variable != NULL &&
-             active_class_.kernel_class != NULL &&
-             active_class_.kernel_class->type_parameters().length() > 0) {
+             active_class_.class_type_parameters > 0) {
     ASSERT(!parsed_function_->function().IsFactory());
     intptr_t type_arguments_field_offset =
         active_class_.klass->type_arguments_field_offset();
@@ -2410,402 +1790,20 @@
 
   if (function.IsConstructorClosureFunction()) return NULL;
 
-  TreeNode* library_node = node_;
-  if (node_ != NULL) {
-    const Function* parent = &function;
-    while (true) {
-      library_node = static_cast<kernel::TreeNode*>(parent->kernel_function());
-      while (library_node != NULL && !library_node->IsLibrary()) {
-        if (library_node->IsMember()) {
-          library_node = Member::Cast(library_node)->parent();
-        } else if (library_node->IsClass()) {
-          library_node = Class::Cast(library_node)->parent();
-          break;
-        } else {
-          library_node = NULL;
-          break;
-        }
-      }
-      if (library_node != NULL) break;
-      parent = &Function::Handle(parent->parent_function());
-    }
-  }
   if (streaming_flow_graph_builder_ != NULL) {
     delete streaming_flow_graph_builder_;
     streaming_flow_graph_builder_ = NULL;
   }
-  if (library_node != NULL && library_node->IsLibrary()) {
-    Library* library = Library::Cast(library_node);
-    streaming_flow_graph_builder_ = new StreamingFlowGraphBuilder(
-        this, library->kernel_data(), library->kernel_data_size());
-  }
 
-  dart::Class& klass =
-      dart::Class::Handle(zone_, parsed_function_->function().Owner());
+  Script& script = Script::Handle(Z, function.script());
+  streaming_flow_graph_builder_ = new StreamingFlowGraphBuilder(
+      this, script.kernel_data(), script.kernel_data_size());
 
-  Function& outermost_function = Function::Handle(Z);
-  TreeNode* outermost_node = NULL;
-  Class* kernel_class = NULL;
-  DiscoverEnclosingElements(Z, function, &outermost_function, &outermost_node,
-                            &kernel_class);
-
-  // Mark that we are using [klass]/[kernell_klass] as active class.  Resolving
-  // of type parameters will get resolved via [kernell_klass] unless we are
-  // nested inside a static factory in which case we will use [member].
-  ActiveClassScope active_class_scope(&active_class_, kernel_class, &klass);
-  Member* member = ((outermost_node != NULL) && outermost_node->IsMember())
-                       ? Member::Cast(outermost_node)
-                       : NULL;
-  ActiveMemberScope active_member(&active_class_, member);
-
-  // The IR builder will create its own local variables and scopes, and it
-  // will not need an AST.  The code generator will assume that there is a
-  // local variable stack slot allocated for the current context and (I
-  // think) that the runtime will expect it to be at a fixed offset which
-  // requires allocating an unused expression temporary variable.
-  scopes_ = parsed_function_->EnsureKernelScopes();
-
-  switch (function.kind()) {
-    case RawFunction::kClosureFunction:
-    case RawFunction::kRegularFunction:
-    case RawFunction::kGetterFunction:
-    case RawFunction::kSetterFunction: {
-      FunctionNode* kernel_function = node_->IsProcedure()
-                                          ? Procedure::Cast(node_)->function()
-                                          : FunctionNode::Cast(node_);
-      return function.IsImplicitClosureFunction()
-                 ? BuildGraphOfImplicitClosureFunction(kernel_function,
-                                                       function)
-                 : BuildGraphOfFunction(kernel_function);
-    }
-    case RawFunction::kConstructor: {
-      bool is_factory = function.IsFactory();
-      if (is_factory) {
-        Procedure* procedure = Procedure::Cast(node_);
-        FunctionNode* function = procedure->function();
-        return BuildGraphOfFunction(function, NULL);
-      } else {
-        Constructor* constructor = Constructor::Cast(node_);
-        FunctionNode* function = constructor->function();
-        return BuildGraphOfFunction(function, constructor);
-      }
-    }
-    case RawFunction::kImplicitGetter:
-    case RawFunction::kImplicitStaticFinalGetter:
-    case RawFunction::kImplicitSetter: {
-      Field* field = Field::Cast(node_);
-      return IsStaticInitializer(function, Z)
-                 ? BuildGraphOfStaticFieldInitializer(field)
-                 : BuildGraphOfFieldAccessor(field, scopes_->setter_value);
-    }
-    case RawFunction::kMethodExtractor:
-      return BuildGraphOfMethodExtractor(function);
-    case RawFunction::kNoSuchMethodDispatcher:
-      return BuildGraphOfNoSuchMethodDispatcher(function);
-    case RawFunction::kInvokeFieldDispatcher:
-      return BuildGraphOfInvokeFieldDispatcher(function);
-    case RawFunction::kSignatureFunction:
-    case RawFunction::kIrregexpFunction:
-      break;
-  }
-  UNREACHABLE();
-  return NULL;
+  return streaming_flow_graph_builder_->BuildGraph(kernel_offset_);
 }
 
 
-FlowGraph* FlowGraphBuilder::BuildGraphOfFunction(FunctionNode* function,
-                                                  Constructor* constructor) {
-  const Function& dart_function = parsed_function_->function();
-  TargetEntryInstr* normal_entry = BuildTargetEntry();
-  graph_entry_ =
-      new (Z) GraphEntryInstr(*parsed_function_, normal_entry, osr_id_);
-
-  SetupDefaultParameterValues(function);
-
-  Fragment body;
-  if (!dart_function.is_native()) body += CheckStackOverflowInPrologue();
-  intptr_t context_size =
-      parsed_function_->node_sequence()->scope()->num_context_variables();
-  if (context_size > 0) {
-    body += PushContext(context_size);
-    LocalVariable* context = MakeTemporary();
-
-    // Copy captured parameters from the stack into the context.
-    LocalScope* scope = parsed_function_->node_sequence()->scope();
-    intptr_t parameter_count = dart_function.NumParameters();
-    intptr_t parameter_index = parsed_function_->first_parameter_index();
-    for (intptr_t i = 0; i < parameter_count; ++i, --parameter_index) {
-      LocalVariable* variable = scope->VariableAt(i);
-      if (variable->is_captured()) {
-        // There is no LocalVariable describing the on-stack parameter so
-        // create one directly and use the same type.
-        LocalVariable* parameter = new (Z)
-            LocalVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
-                          Symbols::TempParam(), variable->type());
-        parameter->set_index(parameter_index);
-        // Mark the stack variable so it will be ignored by the code for
-        // try/catch.
-        parameter->set_is_captured_parameter(true);
-
-        // Copy the parameter from the stack to the context.  Overwrite it
-        // with a null constant on the stack so the original value is
-        // eligible for garbage collection.
-        body += LoadLocal(context);
-        body += LoadLocal(parameter);
-        body += StoreInstanceField(TokenPosition::kNoSource,
-                                   Context::variable_offset(variable->index()));
-        body += NullConstant();
-        body += StoreLocal(TokenPosition::kNoSource, parameter);
-        body += Drop();
-      }
-    }
-    body += Drop();  // The context.
-  }
-  if (constructor != NULL) {
-    // TODO(27590): Currently the [VariableDeclaration]s from the
-    // initializers will be visible inside the entire body of the constructor.
-    // We should make a separate scope for them.
-    Class* kernel_class = Class::Cast(constructor->parent());
-    body += TranslateInitializers(kernel_class, &constructor->initializers());
-  }
-
-  // The specification defines the result of `a == b` to be:
-  //
-  //   a) if either side is `null` then the result is `identical(a, b)`.
-  //   b) else the result is `a.operator==(b)`
-  //
-  // For user-defined implementations of `operator==` we need therefore
-  // implement the handling of a).
-  //
-  // The default `operator==` implementation in `Object` is implemented in terms
-  // of identical (which we assume here!) which means that case a) is actually
-  // included in b).  So we just use the normal implementation in the body.
-  if ((dart_function.NumParameters() == 2) &&
-      (dart_function.name() == Symbols::EqualOperator().raw()) &&
-      (dart_function.Owner() != I->object_store()->object_class())) {
-    LocalVariable* parameter =
-        LookupVariable(function->positional_parameters()[0]);
-
-    TargetEntryInstr* null_entry;
-    TargetEntryInstr* non_null_entry;
-
-    body += LoadLocal(parameter);
-    body += BranchIfNull(&null_entry, &non_null_entry);
-
-    // The argument was `null` and the receiver is not the null class (we only
-    // go into this branch for user-defined == operators) so we can return
-    // false.
-    Fragment null_fragment(null_entry);
-    null_fragment += Constant(Bool::False());
-    null_fragment += Return(dart_function.end_token_pos());
-
-    body = Fragment(body.entry, non_null_entry);
-  }
-
-  // If we run in checked mode, we have to check the type of the passed
-  // arguments.
-  if (I->type_checks()) {
-    List<VariableDeclaration>& positional = function->positional_parameters();
-    List<VariableDeclaration>& named = function->named_parameters();
-
-    for (intptr_t i = 0; i < positional.length(); i++) {
-      VariableDeclaration* variable = positional[i];
-      body += LoadLocal(LookupVariable(variable));
-      body += CheckVariableTypeInCheckedMode(variable);
-      body += Drop();
-    }
-    for (intptr_t i = 0; i < named.length(); i++) {
-      VariableDeclaration* variable = named[i];
-      body += LoadLocal(LookupVariable(variable));
-      body += CheckVariableTypeInCheckedMode(variable);
-      body += Drop();
-    }
-  }
-
-  if (FLAG_causal_async_stacks &&
-      (dart_function.IsAsyncFunction() || dart_function.IsAsyncGenerator())) {
-    LocalScope* scope = parsed_function_->node_sequence()->scope();
-    // :async_stack_trace = _asyncStackTraceHelper(:async_op);
-    const dart::Library& async_lib =
-        dart::Library::Handle(dart::Library::AsyncLibrary());
-    const Function& target = Function::ZoneHandle(
-        Z,
-        async_lib.LookupFunctionAllowPrivate(Symbols::AsyncStackTraceHelper()));
-    ASSERT(!target.IsNull());
-
-    // TODO(johnmccutchan): Why does this have the null value?
-    LocalVariable* async_op =
-        scope->child()->LookupVariable(Symbols::AsyncOperation(), false);
-    ASSERT(async_op != NULL);
-    ASSERT(async_op->is_captured());
-    body += LoadLocal(async_op);
-    body += PushArgument();
-    body += StaticCall(TokenPosition::kNoSource, target, 1);
-    LocalVariable* async_stack_trace_var =
-        scope->LookupVariable(Symbols::AsyncStackTraceVar(), false);
-    ASSERT(async_stack_trace_var != NULL);
-    body += StoreLocal(TokenPosition::kNoSource, async_stack_trace_var);
-    body += Drop();
-  }
-
-  if (dart_function.is_native()) {
-    body += NativeFunctionBody(function, dart_function);
-  } else if (function->body() != NULL) {
-    body += TranslateStatement(function->body());
-  }
-  if (body.is_open()) {
-    body += NullConstant();
-    body += Return(dart_function.end_token_pos());
-  }
-
-  // If functions body contains any yield points build switch statement that
-  // selects a continuation point based on the value of :await_jump_var.
-  if (!yield_continuations_.is_empty()) {
-    // The code we are building will be executed right after we enter
-    // the function and before any nested contexts are allocated.
-    // Reset current context_depth_ to match this.
-    const intptr_t current_context_depth = context_depth_;
-    context_depth_ = scopes_->yield_jump_variable->owner()->context_level();
-
-    // Prepend an entry corresponding to normal entry to the function.
-    yield_continuations_.InsertAt(
-        0, YieldContinuation(new (Z) DropTempsInstr(0, NULL),
-                             CatchClauseNode::kInvalidTryIndex));
-    yield_continuations_[0].entry->LinkTo(body.entry);
-
-    // Build a switch statement.
-    Fragment dispatch;
-
-    // Load :await_jump_var into a temporary.
-    dispatch += LoadLocal(scopes_->yield_jump_variable);
-    dispatch += StoreLocal(TokenPosition::kNoSource, scopes_->switch_variable);
-    dispatch += Drop();
-
-    BlockEntryInstr* block = NULL;
-    for (intptr_t i = 0; i < yield_continuations_.length(); i++) {
-      if (i == 1) {
-        // This is not a normal entry but a resumption.  Restore
-        // :current_context_var from :await_ctx_var.
-        // Note: after this point context_depth_ does not match current context
-        // depth so we should not access any local variables anymore.
-        dispatch += LoadLocal(scopes_->yield_context_variable);
-        dispatch += StoreLocal(TokenPosition::kNoSource,
-                               parsed_function_->current_context_var());
-        dispatch += Drop();
-      }
-      if (i == (yield_continuations_.length() - 1)) {
-        // We reached the last possility, no need to build more ifs.
-        // Continue to the last continuation.
-        // Note: continuations start with nop DropTemps instruction
-        // which acts like an anchor, so we need to skip it.
-        block->set_try_index(yield_continuations_[i].try_index);
-        dispatch <<= yield_continuations_[i].entry->next();
-        break;
-      }
-
-      // Build comparison:
-      //
-      //   if (:await_ctx_var == i) {
-      //     -> yield_continuations_[i]
-      //   } else ...
-      //
-      TargetEntryInstr* then;
-      TargetEntryInstr* otherwise;
-      dispatch += LoadLocal(scopes_->switch_variable);
-      dispatch += IntConstant(i);
-      dispatch += BranchIfStrictEqual(&then, &otherwise);
-
-      // True branch is linked to appropriate continuation point.
-      // Note: continuations start with nop DropTemps instruction
-      // which acts like an anchor, so we need to skip it.
-      then->LinkTo(yield_continuations_[i].entry->next());
-      then->set_try_index(yield_continuations_[i].try_index);
-      // False branch will contain the next comparison.
-      dispatch = Fragment(dispatch.entry, otherwise);
-      block = otherwise;
-    }
-    body = dispatch;
-
-    context_depth_ = current_context_depth;
-  }
-
-  if (FLAG_causal_async_stacks &&
-      (dart_function.IsAsyncClosure() || dart_function.IsAsyncGenClosure())) {
-    // The code we are building will be executed right after we enter
-    // the function and before any nested contexts are allocated.
-    // Reset current context_depth_ to match this.
-    const intptr_t current_context_depth = context_depth_;
-    context_depth_ = scopes_->yield_jump_variable->owner()->context_level();
-
-    Fragment instructions;
-    LocalScope* scope = parsed_function_->node_sequence()->scope();
-
-    const Function& target = Function::ZoneHandle(
-        Z, I->object_store()->async_set_thread_stack_trace());
-    ASSERT(!target.IsNull());
-
-    // Fetch and load :async_stack_trace
-    LocalVariable* async_stack_trace_var =
-        scope->LookupVariable(Symbols::AsyncStackTraceVar(), false);
-    ASSERT((async_stack_trace_var != NULL) &&
-           async_stack_trace_var->is_captured());
-    instructions += LoadLocal(async_stack_trace_var);
-    instructions += PushArgument();
-
-    // Call _asyncSetThreadStackTrace
-    instructions += StaticCall(TokenPosition::kNoSource, target, 1);
-    instructions += Drop();
-
-    // TODO(29737): This sequence should be generated in order.
-    body = instructions + body;
-    context_depth_ = current_context_depth;
-  }
-
-  if (NeedsDebugStepCheck(dart_function, function->position())) {
-    const intptr_t current_context_depth = context_depth_;
-    context_depth_ = 0;
-
-    // If a switch was added above: Start the switch by injecting a debuggable
-    // safepoint so stepping over an await works.
-    // If not, still start the body with a debuggable safepoint to ensure
-    // breaking on a method always happens, even if there are no
-    // assignments/calls/runtimecalls in the first basic block.
-    // Place this check at the last parameter to ensure parameters
-    // are in scope in the debugger at method entry.
-    const int num_params = dart_function.NumParameters();
-    TokenPosition check_pos = TokenPosition::kNoSource;
-    if (num_params > 0) {
-      LocalScope* scope = parsed_function_->node_sequence()->scope();
-      const LocalVariable& parameter = *scope->VariableAt(num_params - 1);
-      check_pos = parameter.token_pos();
-    }
-    if (!check_pos.IsDebugPause()) {
-      // No parameters or synthetic parameters.
-      check_pos = function->position();
-      ASSERT(check_pos.IsDebugPause());
-    }
-
-    // TODO(29737): This sequence should be generated in order.
-    body = DebugStepCheck(check_pos) + body;
-    context_depth_ = current_context_depth;
-  }
-
-  normal_entry->LinkTo(body.entry);
-
-  // When compiling for OSR, use a depth first search to prune instructions
-  // unreachable from the OSR entry. Catch entries are always considered
-  // reachable, even if they become unreachable after OSR.
-  if (osr_id_ != Compiler::kNoOSRDeoptId) {
-    BitVector* block_marks = new (Z) BitVector(Z, next_block_id_);
-    bool found = graph_entry_->PruneUnreachable(graph_entry_, NULL, osr_id_,
-                                                block_marks);
-    ASSERT(found);
-  }
-  return new (Z) FlowGraph(*parsed_function_, graph_entry_, next_block_id_ - 1);
-}
-
-
-Fragment FlowGraphBuilder::NativeFunctionBody(FunctionNode* kernel_function,
+Fragment FlowGraphBuilder::NativeFunctionBody(intptr_t first_positional_offset,
                                               const Function& function) {
   ASSERT(function.is_native());
   // We explicitly build the graph for native functions in the same way that the
@@ -2817,8 +1815,7 @@
   switch (kind) {
     case MethodRecognizer::kObjectEquals:
       body += LoadLocal(scopes_->this_variable);
-      body += LoadLocal(
-          LookupVariable(kernel_function->positional_parameters()[0]));
+      body += LoadLocal(LookupVariable(first_positional_offset));
       body += StrictCompare(Token::kEQ_STRICT);
       break;
     case MethodRecognizer::kStringBaseLength:
@@ -2856,8 +1853,7 @@
                           Type::ZoneHandle(Z, Type::SmiType()), kSmiCid, true);
       break;
     case MethodRecognizer::kClassIDgetID:
-      body += LoadLocal(
-          LookupVariable(kernel_function->positional_parameters()[0]));
+      body += LoadLocal(LookupVariable(first_positional_offset));
       body += LoadClassId();
       break;
     case MethodRecognizer::kGrowableArrayCapacity:
@@ -2869,8 +1865,7 @@
       break;
     case MethodRecognizer::kObjectArrayAllocate:
       body += LoadLocal(scopes_->type_arguments_variable);
-      body += LoadLocal(
-          LookupVariable(kernel_function->positional_parameters()[0]));
+      body += LoadLocal(LookupVariable(first_positional_offset));
       body += CreateArray();
       break;
     case MethodRecognizer::kBigint_getDigits:
@@ -2890,8 +1885,7 @@
       break;
     case MethodRecognizer::kLinkedHashMap_setIndex:
       body += LoadLocal(scopes_->this_variable);
-      body += LoadLocal(
-          LookupVariable(kernel_function->positional_parameters()[0]));
+      body += LoadLocal(LookupVariable(first_positional_offset));
       body += StoreInstanceField(TokenPosition::kNoSource,
                                  LinkedHashMap::index_offset());
       body += NullConstant();
@@ -2903,8 +1897,7 @@
       break;
     case MethodRecognizer::kLinkedHashMap_setData:
       body += LoadLocal(scopes_->this_variable);
-      body += LoadLocal(
-          LookupVariable(kernel_function->positional_parameters()[0]));
+      body += LoadLocal(LookupVariable(first_positional_offset));
       body += StoreInstanceField(TokenPosition::kNoSource,
                                  LinkedHashMap::data_offset());
       body += NullConstant();
@@ -2916,8 +1909,7 @@
       break;
     case MethodRecognizer::kLinkedHashMap_setHashMask:
       body += LoadLocal(scopes_->this_variable);
-      body += LoadLocal(
-          LookupVariable(kernel_function->positional_parameters()[0]));
+      body += LoadLocal(LookupVariable(first_positional_offset));
       body += StoreInstanceField(TokenPosition::kNoSource,
                                  LinkedHashMap::hash_mask_offset(),
                                  kNoStoreBarrier);
@@ -2930,8 +1922,7 @@
       break;
     case MethodRecognizer::kLinkedHashMap_setUsedData:
       body += LoadLocal(scopes_->this_variable);
-      body += LoadLocal(
-          LookupVariable(kernel_function->positional_parameters()[0]));
+      body += LoadLocal(LookupVariable(first_positional_offset));
       body += StoreInstanceField(TokenPosition::kNoSource,
                                  LinkedHashMap::used_data_offset(),
                                  kNoStoreBarrier);
@@ -2944,8 +1935,7 @@
       break;
     case MethodRecognizer::kLinkedHashMap_setDeletedKeys:
       body += LoadLocal(scopes_->this_variable);
-      body += LoadLocal(
-          LookupVariable(kernel_function->positional_parameters()[0]));
+      body += LoadLocal(LookupVariable(first_positional_offset));
       body += StoreInstanceField(TokenPosition::kNoSource,
                                  LinkedHashMap::deleted_keys_offset(),
                                  kNoStoreBarrier);
@@ -2966,82 +1956,6 @@
 }
 
 
-FlowGraph* FlowGraphBuilder::BuildGraphOfFieldAccessor(
-    Field* kernel_field,
-    LocalVariable* setter_value) {
-  const Function& function = parsed_function_->function();
-
-  bool is_setter = function.IsImplicitSetterFunction();
-  bool is_method = !function.IsStaticFunction();
-  dart::Field& field = dart::Field::ZoneHandle(
-      Z, H.LookupFieldByKernelField(kernel_field->canonical_name()));
-
-  TargetEntryInstr* normal_entry = BuildTargetEntry();
-  graph_entry_ = new (Z)
-      GraphEntryInstr(*parsed_function_, normal_entry, Compiler::kNoOSRDeoptId);
-
-  Fragment body(normal_entry);
-  if (is_setter) {
-    if (is_method) {
-      body += LoadLocal(scopes_->this_variable);
-      body += LoadLocal(setter_value);
-      body += StoreInstanceFieldGuarded(field, false);
-    } else {
-      body += LoadLocal(setter_value);
-      body += StoreStaticField(TokenPosition::kNoSource, field);
-    }
-    body += NullConstant();
-  } else if (is_method) {
-    body += LoadLocal(scopes_->this_variable);
-    body += LoadField(field);
-  } else if (field.is_const()) {
-    // If the parser needs to know the value of an uninitialized constant field
-    // it will set the value to the transition sentinel (used to detect circular
-    // initialization) and then call the implicit getter.  Thus, the getter
-    // cannot contain the InitStaticField instruction that normal static getters
-    // contain because it would detect spurious circular initialization when it
-    // checks for the transition sentinel.
-    Expression* initializer = kernel_field->initializer();
-    ASSERT(initializer != NULL);
-    body += Constant(constant_evaluator_.EvaluateExpression(initializer));
-  } else {
-    // The field always has an initializer because static fields without
-    // initializers are initialized eagerly and do not have implicit getters.
-    ASSERT(field.has_initializer());
-    body += Constant(field);
-    body += InitStaticField(field);
-    body += Constant(field);
-    body += LoadStaticField();
-  }
-  body += Return(TokenPosition::kNoSource);
-
-  return new (Z) FlowGraph(*parsed_function_, graph_entry_, next_block_id_ - 1);
-}
-
-
-FlowGraph* FlowGraphBuilder::BuildGraphOfStaticFieldInitializer(
-    Field* kernel_field) {
-  ASSERT(kernel_field->IsStatic());
-
-  Expression* initializer = kernel_field->initializer();
-
-  TargetEntryInstr* normal_entry = BuildTargetEntry();
-  graph_entry_ = new (Z)
-      GraphEntryInstr(*parsed_function_, normal_entry, Compiler::kNoOSRDeoptId);
-
-  Fragment body(normal_entry);
-  body += CheckStackOverflowInPrologue();
-  if (kernel_field->IsConst()) {
-    body += Constant(constant_evaluator_.EvaluateExpression(initializer));
-  } else {
-    body += TranslateExpression(initializer);
-  }
-  body += Return(TokenPosition::kNoSource);
-
-  return new (Z) FlowGraph(*parsed_function_, graph_entry_, next_block_id_ - 1);
-}
-
-
 Fragment FlowGraphBuilder::BuildImplicitClosureCreation(
     const Function& target) {
   Fragment fragment;
@@ -3101,19 +2015,6 @@
 
 
 Fragment FlowGraphBuilder::CheckVariableTypeInCheckedMode(
-    VariableDeclaration* variable) {
-  if (I->type_checks()) {
-    const AbstractType& dst_type = T.TranslateType(variable->type());
-    if (dst_type.IsMalformed()) {
-      return ThrowTypeError();
-    }
-    return CheckAssignableInCheckedMode(dst_type,
-                                        H.DartSymbol(variable->name()));
-  }
-  return Fragment();
-}
-
-Fragment FlowGraphBuilder::CheckVariableTypeInCheckedMode(
     const AbstractType& dst_type,
     const dart::String& name_symbol) {
   if (I->type_checks()) {
@@ -3257,58 +2158,6 @@
 }
 
 
-FlowGraph* FlowGraphBuilder::BuildGraphOfImplicitClosureFunction(
-    FunctionNode* kernel_function,
-    const Function& function) {
-  const Function& target = Function::ZoneHandle(Z, function.parent_function());
-
-  TargetEntryInstr* normal_entry = BuildTargetEntry();
-  graph_entry_ = new (Z)
-      GraphEntryInstr(*parsed_function_, normal_entry, Compiler::kNoOSRDeoptId);
-  SetupDefaultParameterValues(kernel_function);
-
-  Fragment body(normal_entry);
-  body += CheckStackOverflowInPrologue();
-
-  // Load all the arguments.
-  if (!target.is_static()) {
-    // The context has a fixed shape: a single variable which is the
-    // closed-over receiver.
-    body += LoadLocal(parsed_function_->current_context_var());
-    body += LoadField(Context::variable_offset(0));
-    body += PushArgument();
-  }
-  intptr_t positional_argument_count =
-      kernel_function->positional_parameters().length();
-  for (intptr_t i = 0; i < positional_argument_count; i++) {
-    body +=
-        LoadLocal(LookupVariable(kernel_function->positional_parameters()[i]));
-    body += PushArgument();
-  }
-  intptr_t named_argument_count = kernel_function->named_parameters().length();
-  Array& argument_names = Array::ZoneHandle(Z);
-  if (named_argument_count > 0) {
-    argument_names = Array::New(named_argument_count);
-    for (intptr_t i = 0; i < named_argument_count; i++) {
-      VariableDeclaration* variable = kernel_function->named_parameters()[i];
-      body += LoadLocal(LookupVariable(variable));
-      body += PushArgument();
-      argument_names.SetAt(i, H.DartSymbol(variable->name()));
-    }
-  }
-  // Forward them to the target.
-  intptr_t argument_count = positional_argument_count + named_argument_count;
-  if (!target.is_static()) ++argument_count;
-  body += StaticCall(TokenPosition::kNoSource, target, argument_count,
-                     argument_names);
-
-  // Return the result.
-  body += Return(kernel_function->end_position());
-
-  return new (Z) FlowGraph(*parsed_function_, graph_entry_, next_block_id_ - 1);
-}
-
-
 FlowGraph* FlowGraphBuilder::BuildGraphOfNoSuchMethodDispatcher(
     const Function& function) {
   // This function is specialized for a receiver class, a method name, and
@@ -3500,47 +2349,6 @@
 }
 
 
-void FlowGraphBuilder::SetupDefaultParameterValues(FunctionNode* function) {
-  intptr_t num_optional_parameters =
-      parsed_function_->function().NumOptionalParameters();
-  if (num_optional_parameters > 0) {
-    ZoneGrowableArray<const Instance*>* default_values =
-        new ZoneGrowableArray<const Instance*>(Z, num_optional_parameters);
-
-    if (parsed_function_->function().HasOptionalNamedParameters()) {
-      ASSERT(!parsed_function_->function().HasOptionalPositionalParameters());
-      for (intptr_t i = 0; i < num_optional_parameters; i++) {
-        VariableDeclaration* variable = function->named_parameters()[i];
-        Instance* default_value;
-        if (variable->initializer() != NULL) {
-          default_value =
-              &constant_evaluator_.EvaluateExpression(variable->initializer());
-        } else {
-          default_value = &Instance::ZoneHandle(Z, Instance::null());
-        }
-        default_values->Add(default_value);
-      }
-    } else {
-      ASSERT(parsed_function_->function().HasOptionalPositionalParameters());
-      intptr_t required = function->required_parameter_count();
-      for (intptr_t i = 0; i < num_optional_parameters; i++) {
-        VariableDeclaration* variable =
-            function->positional_parameters()[required + i];
-        Instance* default_value;
-        if (variable->initializer() != NULL) {
-          default_value =
-              &constant_evaluator_.EvaluateExpression(variable->initializer());
-        } else {
-          default_value = &Instance::ZoneHandle(Z, Instance::null());
-        }
-        default_values->Add(default_value);
-      }
-    }
-    parsed_function_->set_default_parameter_values(default_values);
-  }
-}
-
-
 TargetEntryInstr* FlowGraphBuilder::BuildTargetEntry() {
   return new (Z)
       TargetEntryInstr(AllocateBlockId(), CurrentTryIndex(), GetNextDeoptId());
@@ -3557,171 +2365,6 @@
       JoinEntryInstr(AllocateBlockId(), CurrentTryIndex(), GetNextDeoptId());
 }
 
-
-Fragment FlowGraphBuilder::TranslateFieldInitializer(NameIndex canonical_name,
-                                                     Expression* init) {
-  dart::Field& field =
-      dart::Field::ZoneHandle(Z, H.LookupFieldByKernelField(canonical_name));
-  if (init->IsNullLiteral()) {
-    field.RecordStore(Object::null_object());
-    return Fragment();
-  }
-  Fragment instructions;
-  instructions += LoadLocal(scopes_->this_variable);
-  instructions += TranslateExpression(init);
-  instructions += StoreInstanceFieldGuarded(field, true);
-  return instructions;
-}
-
-
-Fragment FlowGraphBuilder::TranslateInitializers(
-    Class* kernel_class,
-    List<Initializer>* initializers) {
-  Fragment instructions;
-
-  // These come from:
-  //   class A {
-  //     var x = (expr);
-  //   }
-  for (intptr_t i = 0; i < kernel_class->fields().length(); i++) {
-    Field* kernel_field = kernel_class->fields()[i];
-    Expression* init = kernel_field->initializer();
-    if (!kernel_field->IsStatic() && init != NULL) {
-      EnterScope(kernel_field);
-      instructions +=
-          TranslateFieldInitializer(kernel_field->canonical_name(), init);
-      ExitScope(kernel_field);
-    }
-  }
-
-  // These to come from:
-  //   class A {
-  //     var x;
-  //     var y;
-  //     A(this.x) : super(expr), y = (expr);
-  //   }
-  for (intptr_t i = 0; i < initializers->length(); i++) {
-    Initializer* initializer = (*initializers)[i];
-    if (initializer->IsFieldInitializer()) {
-      FieldInitializer* init = FieldInitializer::Cast(initializer);
-      instructions += TranslateFieldInitializer(init->field(), init->value());
-    } else if (initializer->IsSuperInitializer()) {
-      SuperInitializer* init = SuperInitializer::Cast(initializer);
-
-      instructions += LoadLocal(scopes_->this_variable);
-      instructions += PushArgument();
-
-      ASSERT(init->arguments()->types().length() == 0);
-      Array& argument_names = Array::ZoneHandle(Z);
-      instructions += TranslateArguments(init->arguments(), &argument_names);
-
-      const Function& target = Function::ZoneHandle(
-          Z, H.LookupConstructorByKernelConstructor(init->target()));
-      intptr_t argument_count = init->arguments()->count() + 1;
-      instructions += StaticCall(TokenPosition::kNoSource, target,
-                                 argument_count, argument_names);
-      instructions += Drop();
-    } else if (initializer->IsRedirectingInitializer()) {
-      RedirectingInitializer* init = RedirectingInitializer::Cast(initializer);
-
-      instructions += LoadLocal(scopes_->this_variable);
-      instructions += PushArgument();
-
-      ASSERT(init->arguments()->types().length() == 0);
-      Array& argument_names = Array::ZoneHandle(Z);
-      instructions += TranslateArguments(init->arguments(), &argument_names);
-
-      const Function& target = Function::ZoneHandle(
-          Z, H.LookupConstructorByKernelConstructor(init->target()));
-      intptr_t argument_count = init->arguments()->count() + 1;
-      instructions += StaticCall(TokenPosition::kNoSource, target,
-                                 argument_count, argument_names);
-      instructions += Drop();
-    } else if (initializer->IsLocalInitializer()) {
-      // The other initializers following this one might read the variable. This
-      // is used e.g. for evaluating the arguments to a super call first, run
-      // normal field initializers next and then make the actual super call:
-      //
-      //   The frontend converts
-      //
-      //      class A {
-      //        var x;
-      //        A(a, b) : super(a + b), x = 2*b {}
-      //      }
-      //
-      //   to
-      //
-      //      class A {
-      //        var x;
-      //        A(a, b) : tmp = a + b, x = 2*b, super(tmp) {}
-      //      }
-      //
-      // (This is strictly speaking not what one should do in terms of the
-      //  specification but that is how it is currently implemented.)
-      LocalInitializer* init = LocalInitializer::Cast(initializer);
-
-      VariableDeclaration* declaration = init->variable();
-      LocalVariable* variable = LookupVariable(declaration);
-      Expression* initializer = init->variable()->initializer();
-      ASSERT(initializer != NULL);
-      ASSERT(!declaration->IsConst());
-
-      instructions += TranslateExpression(initializer);
-      instructions += StoreLocal(TokenPosition::kNoSource, variable);
-      instructions += Drop();
-
-      fragment_ = instructions;
-    } else {
-      UNIMPLEMENTED();
-    }
-  }
-  return instructions;
-}
-
-
-Fragment FlowGraphBuilder::TranslateStatement(Statement* statement) {
-#ifdef DEBUG
-  intptr_t original_context_depth = context_depth_;
-#endif
-
-  // TODO(jensj): VariableDeclaration doesn't necessarily have a tag.
-  if (statement->can_stream() &&
-      statement->Type() != Node::kTypeVariableDeclaration) {
-    fragment_ = streaming_flow_graph_builder_->BuildStatementAt(
-        statement->kernel_offset());
-  } else {
-    statement->AcceptStatementVisitor(this);
-  }
-  DEBUG_ASSERT(context_depth_ == original_context_depth);
-  return fragment_;
-}
-
-
-Fragment FlowGraphBuilder::TranslateCondition(Expression* expression,
-                                              bool* negate) {
-  *negate = expression->IsNot();
-  Fragment instructions;
-  if (*negate) {
-    instructions += TranslateExpression(Not::Cast(expression)->expression());
-  } else {
-    instructions += TranslateExpression(expression);
-  }
-  instructions += CheckBooleanInCheckedMode();
-  return instructions;
-}
-
-
-Fragment FlowGraphBuilder::TranslateExpression(Expression* expression) {
-  if (expression->can_stream()) {
-    fragment_ = streaming_flow_graph_builder_->BuildExpressionAt(
-        expression->kernel_offset());
-  } else {
-    expression->AcceptExpressionVisitor(this);
-  }
-  return fragment_;
-}
-
-
 ArgumentArray FlowGraphBuilder::GetArguments(int count) {
   ArgumentArray arguments =
       new (Z) ZoneGrowableArray<PushArgumentInstr*>(Z, count);
@@ -3746,54 +2389,6 @@
   }
 
 
-void FlowGraphBuilder::VisitInvalidExpression(InvalidExpression* node) {
-  fragment_ =
-      streaming_flow_graph_builder_->BuildExpressionAt(node->kernel_offset());
-}
-
-
-void FlowGraphBuilder::VisitNullLiteral(NullLiteral* node) {
-  fragment_ =
-      streaming_flow_graph_builder_->BuildExpressionAt(node->kernel_offset());
-}
-
-
-void FlowGraphBuilder::VisitBoolLiteral(BoolLiteral* node) {
-  fragment_ =
-      streaming_flow_graph_builder_->BuildExpressionAt(node->kernel_offset());
-}
-
-
-void FlowGraphBuilder::VisitIntLiteral(IntLiteral* node) {
-  fragment_ =
-      streaming_flow_graph_builder_->BuildExpressionAt(node->kernel_offset());
-}
-
-
-void FlowGraphBuilder::VisitBigintLiteral(BigintLiteral* node) {
-  fragment_ =
-      streaming_flow_graph_builder_->BuildExpressionAt(node->kernel_offset());
-}
-
-
-void FlowGraphBuilder::VisitDoubleLiteral(DoubleLiteral* node) {
-  fragment_ =
-      streaming_flow_graph_builder_->BuildExpressionAt(node->kernel_offset());
-}
-
-
-void FlowGraphBuilder::VisitStringLiteral(StringLiteral* node) {
-  fragment_ =
-      streaming_flow_graph_builder_->BuildExpressionAt(node->kernel_offset());
-}
-
-
-void FlowGraphBuilder::VisitSymbolLiteral(SymbolLiteral* node) {
-  fragment_ =
-      streaming_flow_graph_builder_->BuildExpressionAt(node->kernel_offset());
-}
-
-
 AbstractType& DartTypeTranslator::TranslateType(DartType* node) {
   node->AcceptDartTypeVisitor(this);
 
@@ -4093,1923 +2688,11 @@
   return type;
 }
 
-void FlowGraphBuilder::VisitTypeLiteral(TypeLiteral* node) {
-  STREAM_EXPRESSION_IF_POSSIBLE(node);
-
-  const AbstractType& type = T.TranslateType(node->type());
-  if (type.IsMalformed()) H.ReportError("Malformed type literal");
-
-  Fragment instructions;
-  if (type.IsInstantiated()) {
-    instructions += Constant(type);
-  } else {
-    if (!type.IsInstantiated(kCurrentClass)) {
-      instructions += LoadInstantiatorTypeArguments();
-    } else {
-      instructions += NullConstant();
-    }
-    if (!type.IsInstantiated(kFunctions)) {
-      instructions += LoadFunctionTypeArguments();
-    } else {
-      instructions += NullConstant();
-    }
-    instructions += InstantiateType(type);
-  }
-  fragment_ = instructions;
-}
-
-
-void FlowGraphBuilder::VisitVariableGet(VariableGet* node) {
-  fragment_ =
-      streaming_flow_graph_builder_->BuildExpressionAt(node->kernel_offset());
-}
-
-
-void FlowGraphBuilder::VisitVariableSet(VariableSet* node) {
-  STREAM_EXPRESSION_IF_POSSIBLE(node);
-
-  Fragment instructions = TranslateExpression(node->expression());
-  if (NeedsDebugStepCheck(stack_, node->position())) {
-    instructions = DebugStepCheck(node->position()) + instructions;
-  }
-  instructions += CheckVariableTypeInCheckedMode(node->variable());
-  instructions +=
-      StoreLocal(node->position(), LookupVariable(node->variable()));
-  fragment_ = instructions;
-}
-
-
-void FlowGraphBuilder::VisitStaticGet(StaticGet* node) {
-  STREAM_EXPRESSION_IF_POSSIBLE(node);
-
-  // A StaticGet will always have a kernel_offset, except for the StaticGet that
-  // was manually created for _getMainClosure in dart:_builtin.  Compile that
-  // one specially here.
-  const dart::Library& builtin =
-      dart::Library::Handle(Z, I->object_store()->builtin_library());
-  const Object& main =
-      Object::Handle(Z, builtin.LookupObjectAllowPrivate(dart::String::Handle(
-                            Z, dart::String::New("main"))));
-  if (main.IsField()) {
-    UNIMPLEMENTED();
-  } else if (main.IsFunction()) {
-    const Function& function = Function::Cast(main);
-    if (function.kind() == RawFunction::kRegularFunction) {
-      const Function& closure_function =
-          Function::Handle(Z, function.ImplicitClosureFunction());
-      closure_function.set_kernel_function(function.kernel_function());
-      const Instance& closure =
-          Instance::ZoneHandle(Z, closure_function.ImplicitStaticClosure());
-      fragment_ = Constant(closure);
-    } else {
-      UNIMPLEMENTED();
-    }
-  } else {
-    UNIMPLEMENTED();
-  }
-}
-
-
-void FlowGraphBuilder::VisitStaticSet(StaticSet* node) {
-  STREAM_EXPRESSION_IF_POSSIBLE(node);
-
-  NameIndex target = node->target();
-  if (H.IsField(target)) {
-    const dart::Field& field =
-        dart::Field::ZoneHandle(Z, H.LookupFieldByKernelField(target));
-    const AbstractType& dst_type = AbstractType::ZoneHandle(Z, field.type());
-    Fragment instructions = TranslateExpression(node->expression());
-    if (NeedsDebugStepCheck(stack_, node->position())) {
-      instructions = DebugStepCheck(node->position()) + instructions;
-    }
-    instructions += CheckAssignableInCheckedMode(
-        dst_type, dart::String::ZoneHandle(Z, field.name()));
-    LocalVariable* variable = MakeTemporary();
-    instructions += LoadLocal(variable);
-    fragment_ = instructions + StoreStaticField(node->position(), field);
-  } else {
-    ASSERT(H.IsProcedure(target));
-
-    // Evaluate the expression on the right hand side.
-    Fragment instructions = TranslateExpression(node->expression());
-    LocalVariable* variable = MakeTemporary();
-
-    // Prepare argument.
-    instructions += LoadLocal(variable);
-    instructions += PushArgument();
-
-    // Invoke the setter function.
-    const Function& function =
-        Function::ZoneHandle(Z, H.LookupStaticMethodByKernelProcedure(target));
-    instructions += StaticCall(node->position(), function, 1);
-
-    // Drop the unused result & leave the stored value on the stack.
-    fragment_ = instructions + Drop();
-  }
-}
-
-
-void FlowGraphBuilder::VisitPropertyGet(PropertyGet* node) {
-  STREAM_EXPRESSION_IF_POSSIBLE(node);
-
-  Fragment instructions = TranslateExpression(node->receiver());
-  instructions += PushArgument();
-  const dart::String& getter_name = H.DartGetterName(node->name());
-  fragment_ = instructions +
-              InstanceCall(node->position(), getter_name, Token::kGET, 1);
-}
-
-
-void FlowGraphBuilder::VisitPropertySet(PropertySet* node) {
-  STREAM_EXPRESSION_IF_POSSIBLE(node);
-
-  Fragment instructions(NullConstant());
-  LocalVariable* variable = MakeTemporary();
-  instructions += TranslateExpression(node->receiver());
-  instructions += PushArgument();
-  instructions += TranslateExpression(node->value());
-  instructions += StoreLocal(TokenPosition::kNoSource, variable);
-  instructions += PushArgument();
-
-  const dart::String& setter_name = H.DartSetterName(node->name());
-  instructions += InstanceCall(node->position(), setter_name, Token::kSET, 2);
-  fragment_ = instructions + Drop();
-}
-
-
-void FlowGraphBuilder::VisitDirectPropertyGet(DirectPropertyGet* node) {
-  STREAM_EXPRESSION_IF_POSSIBLE(node);
-
-  Function& target = Function::ZoneHandle(Z);
-  NameIndex kernel_name = node->target();
-  if (H.IsProcedure(kernel_name)) {
-    if (H.IsGetter(kernel_name)) {
-      target = LookupMethodByMember(kernel_name, H.DartGetterName(kernel_name));
-    } else {
-      target = LookupMethodByMember(kernel_name, H.DartMethodName(kernel_name));
-      target = target.ImplicitClosureFunction();
-      ASSERT(!target.IsNull());
-      fragment_ = BuildImplicitClosureCreation(target);
-      return;
-    }
-  } else {
-    ASSERT(H.IsField(kernel_name));
-    const dart::String& getter_name = H.DartGetterName(kernel_name);
-    target = LookupMethodByMember(kernel_name, getter_name);
-    ASSERT(target.IsGetterFunction() || target.IsImplicitGetterFunction());
-  }
-
-  Fragment instructions = TranslateExpression(node->receiver());
-  instructions += PushArgument();
-  fragment_ = instructions + StaticCall(node->position(), target, 1);
-}
-
-
-void FlowGraphBuilder::VisitDirectPropertySet(DirectPropertySet* node) {
-  STREAM_EXPRESSION_IF_POSSIBLE(node);
-
-  const dart::String& method_name = H.DartSetterName(node->target());
-  const Function& target = Function::ZoneHandle(
-      Z, LookupMethodByMember(node->target(), method_name));
-  ASSERT(target.IsSetterFunction() || target.IsImplicitSetterFunction());
-
-  Fragment instructions(NullConstant());
-  LocalVariable* value = MakeTemporary();
-  instructions += TranslateExpression(node->receiver());
-  instructions += PushArgument();
-  instructions += TranslateExpression(node->value());
-  instructions += StoreLocal(TokenPosition::kNoSource, value);
-  instructions += PushArgument();
-  instructions += StaticCall(node->position(), target, 2);
-
-  fragment_ = instructions + Drop();
-}
-
-
-void FlowGraphBuilder::VisitStaticInvocation(StaticInvocation* node) {
-  STREAM_EXPRESSION_IF_POSSIBLE(node);
-
-  const Function& target = Function::ZoneHandle(
-      Z, H.LookupStaticMethodByKernelProcedure(node->procedure()));
-  const dart::Class& klass = dart::Class::ZoneHandle(Z, target.Owner());
-  intptr_t argument_count = node->arguments()->count();
-  if (target.IsGenerativeConstructor() || target.IsFactory()) {
-    // The VM requires a TypeArguments object as first parameter for
-    // every factory constructor.
-    ++argument_count;
-  }
-
-  List<NamedExpression>& named = node->arguments()->named();
-  const Array& argument_names = H.ArgumentNames(&named);
-
-  // The frontend ensures we the [StaticInvocation] has matching arguments.
-  const intptr_t kTypeArgsLen = 0;  // Generic functions not yet supported.
-  ASSERT(target.AreValidArguments(kTypeArgsLen, argument_count, argument_names,
-                                  NULL));
-
-  Fragment instructions;
-  LocalVariable* instance_variable = NULL;
-
-  // If we cross the Kernel -> VM core library boundary, a [StaticInvocation]
-  // can appear, but the thing we're calling is not a static method, but a
-  // factory constructor.
-  // The `H.LookupStaticmethodByKernelProcedure` will potentially resolve to the
-  // forwarded constructor.
-  // In that case we'll make an instance and pass it as first argument.
-  //
-  // TODO(27590): Get rid of this after we're using core libraries compiled
-  // into Kernel.
-  if (target.IsGenerativeConstructor()) {
-    if (klass.NumTypeArguments() > 0) {
-      List<DartType>& kernel_type_arguments = node->arguments()->types();
-      const TypeArguments& type_arguments =
-          T.TranslateInstantiatedTypeArguments(
-              klass, kernel_type_arguments.raw_array(),
-              kernel_type_arguments.length());
-      instructions += TranslateInstantiatedTypeArguments(type_arguments);
-      instructions += PushArgument();
-      instructions += AllocateObject(klass, 1);
-    } else {
-      instructions += AllocateObject(klass, 0);
-    }
-
-    instance_variable = MakeTemporary();
-
-    instructions += LoadLocal(instance_variable);
-    instructions += PushArgument();
-  } else if (target.IsFactory()) {
-    // The VM requires currently a TypeArguments object as first parameter for
-    // every factory constructor :-/ !
-    //
-    // TODO(27590): Get rid of this after we're using core libraries compiled
-    // into Kernel.
-    List<DartType>& kernel_type_arguments = node->arguments()->types();
-
-    const TypeArguments& type_arguments = T.TranslateInstantiatedTypeArguments(
-        klass, kernel_type_arguments.raw_array(),
-        kernel_type_arguments.length());
-
-    instructions += TranslateInstantiatedTypeArguments(type_arguments);
-    instructions += PushArgument();
-  } else {
-    // TODO(28109) Support generic methods in the VM or reify them away.
-  }
-
-  // Special case identical(x, y) call.
-  // TODO(27590) consider moving this into the inliner and force inline it
-  // there.
-  if (klass.IsTopLevel() && (klass.library() == dart::Library::CoreLibrary()) &&
-      (target.name() == Symbols::Identical().raw())) {
-    ASSERT(argument_count == 2);
-
-    List<Expression>& positional = node->arguments()->positional();
-    for (intptr_t i = 0; i < positional.length(); ++i) {
-      instructions += TranslateExpression(positional[i]);
-    }
-    instructions += StrictCompare(Token::kEQ_STRICT, /*number_check=*/true);
-  } else {
-    instructions += TranslateArguments(node->arguments(), NULL);
-    instructions +=
-        StaticCall(node->position(), target, argument_count, argument_names);
-
-    if (target.IsGenerativeConstructor()) {
-      // Drop the result of the constructor call and leave [instance_variable]
-      // on top-of-stack.
-      instructions += Drop();
-    }
-  }
-
-  fragment_ = instructions;
-}
-
-
-static bool IsNumberLiteral(Node* node) {
-  return node->IsIntLiteral() || node->IsDoubleLiteral();
-}
-
-template <class Invocation>
-bool FlowGraphBuilder::RecognizeComparisonWithNull(Token::Kind token_kind,
-                                                   Invocation* node) {
-  if (token_kind == Token::kEQ || token_kind == Token::kNE) {
-    if (node->arguments()->positional().length() != 1) return false;
-    Fragment instructions;
-    Expression* left = node->receiver();
-    Expression* right = node->arguments()->positional()[0];
-    if (left->IsNullLiteral() || right->IsNullLiteral()) {
-      instructions += TranslateExpression(left);
-      instructions += TranslateExpression(right);
-      Token::Kind strict_cmp_kind =
-          token_kind == Token::kEQ ? Token::kEQ_STRICT : Token::kNE_STRICT;
-      fragment_ = instructions + StrictCompare(strict_cmp_kind,
-                                               /*number_check = */ true);
-      return true;
-    }
-  }
-  return false;
-}
-
-
-void FlowGraphBuilder::VisitMethodInvocation(MethodInvocation* node) {
-  STREAM_EXPRESSION_IF_POSSIBLE(node);
-
-  const dart::String& name = H.DartMethodName(node->name());
-  const intptr_t argument_count = node->arguments()->count() + 1;
-  const Token::Kind token_kind = MethodKind(name);
-  if (IsNumberLiteral(node->receiver())) {
-    if ((argument_count == 1) && (token_kind == Token::kNEGATE)) {
-      const Object& result = constant_evaluator_.EvaluateExpressionSafe(node);
-      if (!result.IsError()) {
-        fragment_ = Constant(result);
-        return;
-      }
-    } else if ((argument_count == 2) &&
-               Token::IsBinaryArithmeticOperator(token_kind) &&
-               IsNumberLiteral(node->arguments()->positional()[0])) {
-      const Object& result = constant_evaluator_.EvaluateExpressionSafe(node);
-      if (!result.IsError()) {
-        fragment_ = Constant(result);
-        return;
-      }
-    }
-  }
-
-  if (RecognizeComparisonWithNull(token_kind, node)) return;
-
-  Fragment instructions = TranslateExpression(node->receiver());
-  instructions += PushArgument();
-
-  // TODO(28109) Support generic methods in the VM or reify them away.
-  Array& argument_names = Array::ZoneHandle(Z);
-  instructions += TranslateArguments(node->arguments(), &argument_names);
-
-  intptr_t num_args_checked = 1;
-  // If we have a special operation (e.g. +/-/==) we mark both arguments as
-  // to be checked.
-  if (token_kind != Token::kILLEGAL) {
-    ASSERT(argument_count <= 2);
-    num_args_checked = argument_count;
-  }
-
-  fragment_ = instructions + InstanceCall(node->position(), name, token_kind,
-                                          argument_count, argument_names,
-                                          num_args_checked);
-  // Later optimization passes assume that result of a x.[]=(...) call is not
-  // used. We must guarantee this invariant because violation will lead to an
-  // illegal IL once we replace x.[]=(...) with a sequence that does not
-  // actually produce any value. See http://dartbug.com/29135 for more details.
-  if (name.raw() == Symbols::AssignIndexToken().raw()) {
-    fragment_ += Drop();
-    fragment_ += NullConstant();
-  }
-}
-
-
-void FlowGraphBuilder::VisitDirectMethodInvocation(
-    DirectMethodInvocation* node) {
-  STREAM_EXPRESSION_IF_POSSIBLE(node);
-
-  const dart::String& method_name = H.DartProcedureName(node->target());
-  const Token::Kind token_kind = MethodKind(method_name);
-
-  if (RecognizeComparisonWithNull(token_kind, node)) return;
-
-  const Function& target = Function::ZoneHandle(
-      Z, LookupMethodByMember(node->target(), method_name));
-
-  intptr_t argument_count = node->arguments()->count() + 1;
-  Array& argument_names = Array::ZoneHandle(Z);
-
-  // TODO(28109) Support generic methods in the VM or reify them away.
-  Fragment instructions = TranslateExpression(node->receiver());
-  instructions += PushArgument();
-  instructions += TranslateArguments(node->arguments(), &argument_names);
-  fragment_ = instructions + StaticCall(node->position(), target,
-                                        argument_count, argument_names);
-}
-
-
-void FlowGraphBuilder::VisitConstructorInvocation(ConstructorInvocation* node) {
-  STREAM_EXPRESSION_IF_POSSIBLE(node);
-
-  if (node->is_const()) {
-    fragment_ =
-        Constant(constant_evaluator_.EvaluateConstructorInvocation(node));
-    return;
-  }
-
-  dart::Class& klass = dart::Class::ZoneHandle(
-      Z, H.LookupClassByKernelClass(H.EnclosingName(node->target())));
-
-  Fragment instructions;
-
-  // Check for malbounded-ness of type.
-  if (I->type_checks()) {
-    List<DartType>& kernel_type_arguments = node->arguments()->types();
-    const TypeArguments& type_arguments = T.TranslateTypeArguments(
-        kernel_type_arguments.raw_array(), kernel_type_arguments.length());
-
-    AbstractType& type = AbstractType::Handle(
-        Z, Type::New(klass, type_arguments, TokenPosition::kNoSource));
-    type = ClassFinalizer::FinalizeType(klass, type);
-
-    if (type.IsMalbounded()) {
-      // Evaluate expressions for correctness.
-      List<Expression>& positional = node->arguments()->positional();
-      List<NamedExpression>& named = node->arguments()->named();
-      for (intptr_t i = 0; i < positional.length(); ++i) {
-        instructions += TranslateExpression(positional[i]);
-        instructions += Drop();
-      }
-      for (intptr_t i = 0; i < named.length(); ++i) {
-        instructions += TranslateExpression(named[i]->expression());
-        instructions += Drop();
-      }
-
-      // Throw an error & keep the [Value] on the stack.
-      instructions += ThrowTypeError();
-
-      // Bail out early.
-      fragment_ = instructions;
-      return;
-    }
-  }
-
-  if (klass.NumTypeArguments() > 0) {
-    List<DartType>& kernel_type_arguments = node->arguments()->types();
-    const TypeArguments& type_arguments = T.TranslateInstantiatedTypeArguments(
-        klass, kernel_type_arguments.raw_array(),
-        kernel_type_arguments.length());
-    if (!klass.IsGeneric()) {
-      Type& type = Type::ZoneHandle(Z, T.ReceiverType(klass).raw());
-
-      // TODO(27590): Can we move this code into [ReceiverType]?
-      type ^= ClassFinalizer::FinalizeType(*active_class_.klass, type,
-                                           ClassFinalizer::kFinalize);
-      ASSERT(!type.IsMalformedOrMalbounded());
-
-      TypeArguments& canonicalized_type_arguments =
-          TypeArguments::ZoneHandle(Z, type.arguments());
-      canonicalized_type_arguments =
-          canonicalized_type_arguments.Canonicalize();
-      instructions += Constant(canonicalized_type_arguments);
-    } else {
-      instructions += TranslateInstantiatedTypeArguments(type_arguments);
-    }
-
-    instructions += PushArgument();
-    instructions += AllocateObject(klass, 1);
-  } else {
-    instructions += AllocateObject(klass, 0);
-  }
-  LocalVariable* variable = MakeTemporary();
-
-  instructions += LoadLocal(variable);
-  instructions += PushArgument();
-
-  Array& argument_names = Array::ZoneHandle(Z);
-  instructions += TranslateArguments(node->arguments(), &argument_names);
-
-  const Function& target = Function::ZoneHandle(
-      Z, H.LookupConstructorByKernelConstructor(klass, node->target()));
-  intptr_t argument_count = node->arguments()->count() + 1;
-  instructions +=
-      StaticCall(node->position(), target, argument_count, argument_names);
-  fragment_ = instructions + Drop();
-}
-
-
-void FlowGraphBuilder::VisitIsExpression(IsExpression* node) {
-  STREAM_EXPRESSION_IF_POSSIBLE(node);
-
-  Fragment instructions = TranslateExpression(node->operand());
-
-  // The VM does not like an instanceOf call with a dynamic type. We need to
-  // special case this situation.
-  const Type& object_type = Type::Handle(Z, Type::ObjectType());
-  const AbstractType& type = T.TranslateType(node->type());
-  if (type.IsMalformed()) {
-    instructions += Drop();
-    instructions += ThrowTypeError();
-    fragment_ = instructions;
-    return;
-  }
-
-  if (type.IsInstantiated() &&
-      object_type.IsSubtypeOf(type, NULL, NULL, Heap::kOld)) {
-    // Evaluate the expression on the left but ignore it's result.
-    instructions += Drop();
-
-    // Let condition be always true.
-    instructions += Constant(Bool::True());
-  } else {
-    instructions += PushArgument();
-
-    // See if simple instanceOf is applicable.
-    if (dart::FlowGraphBuilder::SimpleInstanceOfType(type)) {
-      instructions += Constant(type);
-      instructions += PushArgument();  // Type.
-      instructions += InstanceCall(
-          node->position(),
-          dart::Library::PrivateCoreLibName(Symbols::_simpleInstanceOf()),
-          Token::kIS, 2, 2);  // 2 checked arguments.
-      fragment_ = instructions;
-      return;
-    }
-
-    if (!type.IsInstantiated(kCurrentClass)) {
-      instructions += LoadInstantiatorTypeArguments();
-    } else {
-      instructions += NullConstant();
-    }
-    instructions += PushArgument();  // Instantiator type arguments.
-
-    if (!type.IsInstantiated(kFunctions)) {
-      instructions += LoadFunctionTypeArguments();
-    } else {
-      instructions += NullConstant();
-    }
-    instructions += PushArgument();  // Function type arguments.
-
-    instructions += Constant(type);
-    instructions += PushArgument();  // Type.
-
-    instructions +=
-        InstanceCall(node->position(),
-                     dart::Library::PrivateCoreLibName(Symbols::_instanceOf()),
-                     Token::kIS, 4);
-  }
-
-  fragment_ = instructions;
-}
-
-
-void FlowGraphBuilder::VisitAsExpression(AsExpression* node) {
-  STREAM_EXPRESSION_IF_POSSIBLE(node);
-
-  Fragment instructions = TranslateExpression(node->operand());
-
-  // The VM does not like an Object_as call with a dynamic type. We need to
-  // special case this situation.
-  const Type& object_type = Type::Handle(Z, Type::ObjectType());
-  const AbstractType& type = T.TranslateType(node->type());
-  if (type.IsMalformed()) {
-    instructions += Drop();
-    instructions += ThrowTypeError();
-    fragment_ = instructions;
-    return;
-  }
-
-  if (type.IsInstantiated() &&
-      object_type.IsSubtypeOf(type, NULL, NULL, Heap::kOld)) {
-    // We already evaluated the operand on the left and just leave it there as
-    // the result of the `obj as dynamic` expression.
-  } else {
-    instructions += PushArgument();
-
-    if (!type.IsInstantiated(kCurrentClass)) {
-      instructions += LoadInstantiatorTypeArguments();
-    } else {
-      instructions += NullConstant();
-    }
-    instructions += PushArgument();  // Instantiator type arguments.
-
-    if (!type.IsInstantiated(kFunctions)) {
-      instructions += LoadFunctionTypeArguments();
-    } else {
-      instructions += NullConstant();
-    }
-    instructions += PushArgument();  // Function type arguments.
-
-    instructions += Constant(type);
-    instructions += PushArgument();  // Type.
-
-    instructions += InstanceCall(
-        node->position(), dart::Library::PrivateCoreLibName(Symbols::_as()),
-        Token::kAS, 4);
-  }
-
-  fragment_ = instructions;
-}
-
-
-void FlowGraphBuilder::VisitConditionalExpression(ConditionalExpression* node) {
-  STREAM_EXPRESSION_IF_POSSIBLE(node);
-
-  bool negate;
-  Fragment instructions = TranslateCondition(node->condition(), &negate);
-
-  TargetEntryInstr* then_entry;
-  TargetEntryInstr* otherwise_entry;
-  instructions += BranchIfTrue(&then_entry, &otherwise_entry, negate);
-
-  Value* top = stack_;
-  Fragment then_fragment(then_entry);
-  then_fragment += TranslateExpression(node->then());
-  then_fragment += StoreLocal(TokenPosition::kNoSource,
-                              parsed_function_->expression_temp_var());
-  then_fragment += Drop();
-  ASSERT(stack_ == top);
-
-  Fragment otherwise_fragment(otherwise_entry);
-  otherwise_fragment += TranslateExpression(node->otherwise());
-  otherwise_fragment += StoreLocal(TokenPosition::kNoSource,
-                                   parsed_function_->expression_temp_var());
-  otherwise_fragment += Drop();
-  ASSERT(stack_ == top);
-
-  JoinEntryInstr* join = BuildJoinEntry();
-  then_fragment += Goto(join);
-  otherwise_fragment += Goto(join);
-
-  fragment_ = Fragment(instructions.entry, join) +
-              LoadLocal(parsed_function_->expression_temp_var());
-}
-
-
-void FlowGraphBuilder::VisitLogicalExpression(LogicalExpression* node) {
-  STREAM_EXPRESSION_IF_POSSIBLE(node);
-
-  bool negate;
-  Fragment instructions = TranslateCondition(node->left(), &negate);
-  TargetEntryInstr* right_entry;
-  TargetEntryInstr* constant_entry;
-
-  if (node->op() == LogicalExpression::kAnd) {
-    instructions += BranchIfTrue(&right_entry, &constant_entry, negate);
-  } else {
-    instructions += BranchIfTrue(&constant_entry, &right_entry, negate);
-  }
-
-  Value* top = stack_;
-  Fragment right_fragment(right_entry);
-  right_fragment += TranslateCondition(node->right(), &negate);
-  right_fragment += Constant(Bool::True());
-  right_fragment +=
-      StrictCompare(negate ? Token::kNE_STRICT : Token::kEQ_STRICT);
-  right_fragment += StoreLocal(TokenPosition::kNoSource,
-                               parsed_function_->expression_temp_var());
-  right_fragment += Drop();
-
-  ASSERT(top == stack_);
-  Fragment constant_fragment(constant_entry);
-  constant_fragment +=
-      Constant(Bool::Get(node->op() == LogicalExpression::kOr));
-  constant_fragment += StoreLocal(TokenPosition::kNoSource,
-                                  parsed_function_->expression_temp_var());
-  constant_fragment += Drop();
-
-  JoinEntryInstr* join = BuildJoinEntry();
-  right_fragment += Goto(join);
-  constant_fragment += Goto(join);
-
-  fragment_ = Fragment(instructions.entry, join) +
-              LoadLocal(parsed_function_->expression_temp_var());
-}
-
-
-void FlowGraphBuilder::VisitNot(Not* node) {
-  STREAM_EXPRESSION_IF_POSSIBLE(node);
-
-  Fragment instructions = TranslateExpression(node->expression());
-  instructions += CheckBooleanInCheckedMode();
-  instructions += BooleanNegate();
-  fragment_ = instructions;
-}
-
-
-void FlowGraphBuilder::VisitThisExpression(ThisExpression* node) {
-  fragment_ =
-      streaming_flow_graph_builder_->BuildExpressionAt(node->kernel_offset());
-}
-
-
-void FlowGraphBuilder::VisitStringConcatenation(StringConcatenation* node) {
-  STREAM_EXPRESSION_IF_POSSIBLE(node);
-
-  List<Expression>& expressions = node->expressions();
-
-  Fragment instructions;
-
-  if (node->expressions().length() == 1) {
-    instructions += TranslateExpression(node->expressions()[0]);
-    instructions += StringInterpolateSingle(node->position());
-  } else {
-    // The type arguments for CreateArray.
-    instructions += Constant(TypeArguments::ZoneHandle(Z));
-    instructions += IntConstant(expressions.length());
-    instructions += CreateArray();
-    LocalVariable* array = MakeTemporary();
-
-    for (intptr_t i = 0; i < node->expressions().length(); i++) {
-      instructions += LoadLocal(array);
-      instructions += IntConstant(i);
-      instructions += TranslateExpression(node->expressions()[i]);
-      instructions += StoreIndexed(kArrayCid);
-      instructions += Drop();
-    }
-
-    instructions += StringInterpolate(node->position());
-  }
-  fragment_ = instructions;
-}
-
-
-void FlowGraphBuilder::VisitListLiteral(ListLiteral* node) {
-  STREAM_EXPRESSION_IF_POSSIBLE(node);
-
-  if (node->is_const()) {
-    fragment_ = Constant(constant_evaluator_.EvaluateListLiteral(node));
-    return;
-  }
-
-  DartType* types[] = {node->type()};
-  const TypeArguments& type_arguments = T.TranslateTypeArguments(types, 1);
-
-  // The type argument for the factory call.
-  Fragment instructions = TranslateInstantiatedTypeArguments(type_arguments);
-  instructions += PushArgument();
-  List<Expression>& expressions = node->expressions();
-  if (expressions.length() == 0) {
-    instructions += Constant(Object::empty_array());
-  } else {
-    // The type arguments for CreateArray.
-    instructions += Constant(TypeArguments::ZoneHandle(Z));
-    instructions += IntConstant(expressions.length());
-    instructions += CreateArray();
-
-    LocalVariable* array = MakeTemporary();
-    for (intptr_t i = 0; i < expressions.length(); ++i) {
-      instructions += LoadLocal(array);
-      instructions += IntConstant(i);
-      instructions += TranslateExpression(expressions[i]);
-      instructions += StoreIndexed(kArrayCid);
-      instructions += Drop();
-    }
-  }
-  instructions += PushArgument();  // The array.
-
-  const dart::Class& factory_class =
-      dart::Class::Handle(Z, dart::Library::LookupCoreClass(Symbols::List()));
-  const Function& factory_method = Function::ZoneHandle(
-      Z, factory_class.LookupFactory(
-             dart::Library::PrivateCoreLibName(Symbols::ListLiteralFactory())));
-  fragment_ = instructions + StaticCall(node->position(), factory_method, 2);
-}
-
-
-void FlowGraphBuilder::VisitMapLiteral(MapLiteral* node) {
-  STREAM_EXPRESSION_IF_POSSIBLE(node);
-
-  if (node->is_const()) {
-    fragment_ = Constant(constant_evaluator_.EvaluateMapLiteral(node));
-    return;
-  }
-
-  const dart::Class& map_class =
-      dart::Class::Handle(Z, dart::Library::LookupCoreClass(Symbols::Map()));
-  const Function& factory_method = Function::ZoneHandle(
-      Z, map_class.LookupFactory(
-             dart::Library::PrivateCoreLibName(Symbols::MapLiteralFactory())));
-
-  DartType* types[] = {node->key_type(), node->value_type()};
-  const TypeArguments& type_arguments = T.TranslateTypeArguments(types, 2);
-
-  // The type argument for the factory call `new Map<K, V>._fromLiteral(List)`.
-  Fragment instructions = TranslateInstantiatedTypeArguments(type_arguments);
-  instructions += PushArgument();
-
-  List<MapEntry>& entries = node->entries();
-  if (entries.length() == 0) {
-    instructions += Constant(Object::empty_array());
-  } else {
-    // The type arguments for `new List<X>(int len)`.
-    instructions += Constant(TypeArguments::ZoneHandle(Z));
-
-    // We generate a list of tuples, i.e. [key1, value1, ..., keyN, valueN].
-    instructions += IntConstant(2 * entries.length());
-    instructions += CreateArray();
-
-    LocalVariable* array = MakeTemporary();
-    for (intptr_t i = 0; i < entries.length(); ++i) {
-      instructions += LoadLocal(array);
-      instructions += IntConstant(2 * i);
-      instructions += TranslateExpression(entries[i]->key());
-      instructions += StoreIndexed(kArrayCid);
-      instructions += Drop();
-
-      instructions += LoadLocal(array);
-      instructions += IntConstant(2 * i + 1);
-      instructions += TranslateExpression(entries[i]->value());
-      instructions += StoreIndexed(kArrayCid);
-      instructions += Drop();
-    }
-  }
-  instructions += PushArgument();  // The array.
-
-  fragment_ = instructions + StaticCall(node->position(), factory_method, 2);
-}
-
-
-void FlowGraphBuilder::VisitFunctionExpression(FunctionExpression* node) {
-  fragment_ = TranslateFunctionNode(node->function(), node);
-}
-
-
-void FlowGraphBuilder::VisitLet(Let* node) {
-  STREAM_EXPRESSION_IF_POSSIBLE(node);
-
-  Fragment instructions = TranslateStatement(node->variable());
-  instructions += TranslateExpression(node->body());
-  fragment_ = instructions;
-}
-
-
-void FlowGraphBuilder::VisitThrow(Throw* node) {
-  STREAM_EXPRESSION_IF_POSSIBLE(node);
-
-  Fragment instructions;
-
-  instructions += TranslateExpression(node->expression());
-  if (NeedsDebugStepCheck(stack_, node->position())) {
-    instructions = DebugStepCheck(node->position()) + instructions;
-  }
-  instructions += PushArgument();
-  instructions += ThrowException(node->position());
-  ASSERT(instructions.is_closed());
-
-  fragment_ = instructions;
-}
-
-
-void FlowGraphBuilder::VisitRethrow(Rethrow* node) {
-  fragment_ =
-      streaming_flow_graph_builder_->BuildExpressionAt(node->kernel_offset());
-}
-
-
-Fragment FlowGraphBuilder::TranslateArguments(Arguments* node,
-                                              Array* argument_names) {
-  Fragment instructions;
-
-  List<Expression>& positional = node->positional();
-  for (intptr_t i = 0; i < positional.length(); ++i) {
-    instructions += TranslateExpression(positional[i]);
-    instructions += PushArgument();
-  }
-
-  List<NamedExpression>& named = node->named();
-  if (argument_names != NULL) {
-    *argument_names = H.ArgumentNames(&named).raw();
-  }
-  for (intptr_t i = 0; i < named.length(); ++i) {
-    NamedExpression* named_expression = named[i];
-    instructions += TranslateExpression(named_expression->expression());
-    instructions += PushArgument();
-  }
-  return instructions;
-}
-
-#define STREAM_STATEMENT_IF_POSSIBLE(node)                                     \
-  if (node->can_stream()) {                                                    \
-    fragment_ = streaming_flow_graph_builder_->BuildStatementAt(               \
-        node->kernel_offset());                                                \
-    return;                                                                    \
-  }
-
-
-void FlowGraphBuilder::VisitInvalidStatement(InvalidStatement* node) {
-  fragment_ =
-      streaming_flow_graph_builder_->BuildStatementAt(node->kernel_offset());
-}
-
-
-void FlowGraphBuilder::VisitEmptyStatement(EmptyStatement* node) {
-  fragment_ =
-      streaming_flow_graph_builder_->BuildStatementAt(node->kernel_offset());
-}
-
-
-void FlowGraphBuilder::VisitBlock(Block* node) {
-  STREAM_STATEMENT_IF_POSSIBLE(node);
-
-  Fragment instructions;
-
-  instructions += EnterScope(node);
-  List<Statement>& statements = node->statements();
-  for (intptr_t i = 0; (i < statements.length()) && instructions.is_open();
-       ++i) {
-    instructions += TranslateStatement(statements[i]);
-  }
-  instructions += ExitScope(node);
-
-  fragment_ = instructions;
-}
-
-
-void FlowGraphBuilder::VisitReturnStatement(ReturnStatement* node) {
-  STREAM_STATEMENT_IF_POSSIBLE(node);
-
-  bool inside_try_finally = try_finally_block_ != NULL;
-
-  Fragment instructions = node->expression() == NULL
-                              ? NullConstant()
-                              : TranslateExpression(node->expression());
-  if (instructions.is_open()) {
-    if (inside_try_finally) {
-      ASSERT(scopes_->finally_return_variable != NULL);
-      const Function& function = parsed_function_->function();
-      if (NeedsDebugStepCheck(function, node->position())) {
-        instructions += DebugStepCheck(node->position());
-      }
-      instructions +=
-          StoreLocal(node->position(), scopes_->finally_return_variable);
-      instructions += Drop();
-      instructions += TranslateFinallyFinalizers(NULL, -1);
-      if (instructions.is_open()) {
-        instructions += LoadLocal(scopes_->finally_return_variable);
-        instructions += Return(TokenPosition::kNoSource);
-      }
-    } else {
-      instructions += Return(node->position());
-    }
-  } else {
-    Pop();
-  }
-  fragment_ = instructions;
-}
-
-
-void FlowGraphBuilder::VisitExpressionStatement(ExpressionStatement* node) {
-  STREAM_STATEMENT_IF_POSSIBLE(node);
-
-  Fragment instructions = TranslateExpression(node->expression());
-  instructions += Drop();
-  fragment_ = instructions;
-}
-
-
-void FlowGraphBuilder::VisitVariableDeclaration(VariableDeclaration* node) {
-  LocalVariable* variable = LookupVariable(node);
-  Expression* initializer = node->initializer();
-
-  Fragment instructions;
-  if (initializer == NULL) {
-    instructions += NullConstant();
-  } else {
-    if (node->IsConst()) {
-      const Instance& constant_value =
-          constant_evaluator_.EvaluateExpression(initializer);
-      variable->SetConstValue(constant_value);
-      instructions += Constant(constant_value);
-    } else {
-      instructions += TranslateExpression(initializer);
-      instructions += CheckVariableTypeInCheckedMode(node);
-    }
-  }
-  // Use position of equal sign if it exists. If the equal sign does not exist
-  // use the position of the identifier.
-  TokenPosition debug_position =
-      Utils::Maximum(node->position(), node->equals_position());
-  if (NeedsDebugStepCheck(stack_, debug_position)) {
-    instructions = DebugStepCheck(debug_position) + instructions;
-  }
-  instructions += StoreLocal(node->position(), variable);
-  instructions += Drop();
-  fragment_ = instructions;
-}
-
-
-void FlowGraphBuilder::VisitFunctionDeclaration(FunctionDeclaration* node) {
-  Fragment instructions = DebugStepCheck(node->position());
-  instructions += TranslateFunctionNode(node->function(), node);
-  instructions +=
-      StoreLocal(node->position(), LookupVariable(node->variable()));
-  instructions += Drop();
-  fragment_ = instructions;
-}
-
-
-void FlowGraphBuilder::VisitIfStatement(IfStatement* node) {
-  STREAM_STATEMENT_IF_POSSIBLE(node);
-
-  bool negate;
-  Fragment instructions = TranslateCondition(node->condition(), &negate);
-  TargetEntryInstr* then_entry;
-  TargetEntryInstr* otherwise_entry;
-  instructions += BranchIfTrue(&then_entry, &otherwise_entry, negate);
-
-  Fragment then_fragment(then_entry);
-  then_fragment += TranslateStatement(node->then());
-
-  Fragment otherwise_fragment(otherwise_entry);
-  otherwise_fragment += TranslateStatement(node->otherwise());
-
-  if (then_fragment.is_open()) {
-    if (otherwise_fragment.is_open()) {
-      JoinEntryInstr* join = BuildJoinEntry();
-      then_fragment += Goto(join);
-      otherwise_fragment += Goto(join);
-      fragment_ = Fragment(instructions.entry, join);
-    } else {
-      fragment_ = Fragment(instructions.entry, then_fragment.current);
-    }
-  } else if (otherwise_fragment.is_open()) {
-    fragment_ = Fragment(instructions.entry, otherwise_fragment.current);
-  } else {
-    fragment_ = instructions.closed();
-  }
-}
-
-
-void FlowGraphBuilder::VisitWhileStatement(WhileStatement* node) {
-  STREAM_STATEMENT_IF_POSSIBLE(node);
-
-  ++loop_depth_;
-  bool negate;
-  Fragment condition = TranslateCondition(node->condition(), &negate);
-  TargetEntryInstr* body_entry;
-  TargetEntryInstr* loop_exit;
-  condition += BranchIfTrue(&body_entry, &loop_exit, negate);
-
-  Fragment body(body_entry);
-  body += TranslateStatement(node->body());
-
-  Instruction* entry;
-  if (body.is_open()) {
-    JoinEntryInstr* join = BuildJoinEntry();
-    body += Goto(join);
-
-    Fragment loop(join);
-    loop += CheckStackOverflow();
-    loop += condition;
-    entry = new (Z) GotoInstr(join, GetNextDeoptId());
-  } else {
-    entry = condition.entry;
-  }
-
-
-  fragment_ = Fragment(entry, loop_exit);
-  --loop_depth_;
-}
-
-
-void FlowGraphBuilder::VisitDoStatement(DoStatement* node) {
-  STREAM_STATEMENT_IF_POSSIBLE(node);
-
-  ++loop_depth_;
-  Fragment body = TranslateStatement(node->body());
-
-  if (body.is_closed()) {
-    fragment_ = body;
-    --loop_depth_;
-    return;
-  }
-
-  bool negate;
-  JoinEntryInstr* join = BuildJoinEntry();
-  Fragment loop(join);
-  loop += CheckStackOverflow();
-  loop += body;
-  loop += TranslateCondition(node->condition(), &negate);
-  TargetEntryInstr* loop_repeat;
-  TargetEntryInstr* loop_exit;
-  loop += BranchIfTrue(&loop_repeat, &loop_exit, negate);
-
-  Fragment repeat(loop_repeat);
-  repeat += Goto(join);
-
-  fragment_ = Fragment(new (Z) GotoInstr(join, GetNextDeoptId()), loop_exit);
-  --loop_depth_;
-}
-
-
-void FlowGraphBuilder::VisitForStatement(ForStatement* node) {
-  STREAM_STATEMENT_IF_POSSIBLE(node);
-
-  Fragment declarations;
-
-  bool new_context = false;
-  declarations += EnterScope(node, &new_context);
-
-  List<VariableDeclaration>& variables = node->variables();
-  for (intptr_t i = 0; i < variables.length(); ++i) {
-    declarations += TranslateStatement(variables[i]);
-  }
-
-  ++loop_depth_;
-  bool negate = false;
-  Fragment condition = node->condition() == NULL
-                           ? Constant(Bool::True())
-                           : TranslateCondition(node->condition(), &negate);
-  TargetEntryInstr* body_entry;
-  TargetEntryInstr* loop_exit;
-  condition += BranchIfTrue(&body_entry, &loop_exit, negate);
-
-  Fragment body(body_entry);
-  body += TranslateStatement(node->body());
-
-  if (body.is_open()) {
-    // We allocated a fresh context before the loop which contains captured
-    // [ForStatement] variables.  Before jumping back to the loop entry we clone
-    // the context object (at same depth) which ensures the next iteration of
-    // the body gets a fresh set of [ForStatement] variables (with the old
-    // (possibly updated) values).
-    if (new_context) body += CloneContext();
-
-    List<Expression>& updates = node->updates();
-    for (intptr_t i = 0; i < updates.length(); ++i) {
-      body += TranslateExpression(updates[i]);
-      body += Drop();
-    }
-    JoinEntryInstr* join = BuildJoinEntry();
-    declarations += Goto(join);
-    body += Goto(join);
-
-    Fragment loop(join);
-    loop += CheckStackOverflow();
-    loop += condition;
-  } else {
-    declarations += condition;
-  }
-
-  Fragment loop(declarations.entry, loop_exit);
-  --loop_depth_;
-
-  loop += ExitScope(node);
-
-  fragment_ = loop;
-}
-
-
-void FlowGraphBuilder::VisitForInStatement(ForInStatement* node) {
-  STREAM_STATEMENT_IF_POSSIBLE(node);
-
-  Fragment instructions = TranslateExpression(node->iterable());
-  instructions += PushArgument();
-
-  const dart::String& iterator_getter = dart::String::ZoneHandle(
-      Z, dart::Field::GetterSymbol(Symbols::Iterator()));
-  instructions += InstanceCall(node->iterable()->position(), iterator_getter,
-                               Token::kGET, 1);
-  LocalVariable* iterator = scopes_->iterator_variables[for_in_depth_];
-  instructions += StoreLocal(TokenPosition::kNoSource, iterator);
-  instructions += Drop();
-
-  ++for_in_depth_;
-  ++loop_depth_;
-  Fragment condition = LoadLocal(iterator);
-  condition += PushArgument();
-  condition += InstanceCall(node->iterable()->position(), Symbols::MoveNext(),
-                            Token::kILLEGAL, 1);
-  TargetEntryInstr* body_entry;
-  TargetEntryInstr* loop_exit;
-  condition += BranchIfTrue(&body_entry, &loop_exit);
-
-  Fragment body(body_entry);
-  body += EnterScope(node);
-  body += LoadLocal(iterator);
-  body += PushArgument();
-  const dart::String& current_getter = dart::String::ZoneHandle(
-      Z, dart::Field::GetterSymbol(Symbols::Current()));
-  body += InstanceCall(node->position(), current_getter, Token::kGET, 1);
-  body +=
-      StoreLocal(TokenPosition::kNoSource, LookupVariable(node->variable()));
-  body += Drop();
-  body += TranslateStatement(node->body());
-  body += ExitScope(node);
-
-  if (body.is_open()) {
-    JoinEntryInstr* join = BuildJoinEntry();
-    instructions += Goto(join);
-    body += Goto(join);
-
-    Fragment loop(join);
-    loop += CheckStackOverflow();
-    loop += condition;
-  } else {
-    instructions += condition;
-  }
-
-  fragment_ = Fragment(instructions.entry, loop_exit);
-  --loop_depth_;
-  --for_in_depth_;
-}
-
-
-void FlowGraphBuilder::VisitLabeledStatement(LabeledStatement* node) {
-  STREAM_STATEMENT_IF_POSSIBLE(node);
-
-  // There can be serveral cases:
-  //
-  //   * the body contains a break
-  //   * the body doesn't contain a break
-  //
-  //   * translating the body results in a closed fragment
-  //   * translating the body results in a open fragment
-  //
-  // => We will only know which case we are in after the body has been
-  //    traversed.
-
-  BreakableBlock block(this);
-  Fragment instructions = TranslateStatement(node->body());
-  if (block.HadJumper()) {
-    if (instructions.is_open()) {
-      instructions += Goto(block.destination());
-    }
-    fragment_ = Fragment(instructions.entry, block.destination());
-  } else {
-    fragment_ = instructions;
-  }
-}
-
-
-void FlowGraphBuilder::VisitBreakStatement(BreakStatement* node) {
-  fragment_ =
-      streaming_flow_graph_builder_->BuildStatementAt(node->kernel_offset());
-}
-
-
-void FlowGraphBuilder::VisitSwitchStatement(SwitchStatement* node) {
-  STREAM_STATEMENT_IF_POSSIBLE(node);
-
-  SwitchBlock block(this, node->cases().length());
-
-  // Instead of using a variable we should reuse the expression on the stack,
-  // since it won't be assigned again, we don't need phi nodes.
-  Fragment head_instructions = TranslateExpression(node->condition());
-  head_instructions +=
-      StoreLocal(TokenPosition::kNoSource, scopes_->switch_variable);
-  head_instructions += Drop();
-
-  // Phase 1: Generate bodies and try to find out whether a body will be target
-  // of a jump due to:
-  //   * `continue case_label`
-  //   * `case e1: case e2: body`
-  Fragment* body_fragments = new Fragment[node->cases().length()];
-
-  intptr_t num_cases = node->cases().length();
-  for (intptr_t i = 0; i < num_cases; i++) {
-    SwitchCase* switch_case = node->cases()[i];
-    Fragment& body_fragment = body_fragments[i] =
-        TranslateStatement(switch_case->body());
-
-    if (body_fragment.entry == NULL) {
-      // Make a NOP in order to ensure linking works properly.
-      body_fragment = NullConstant();
-      body_fragment += Drop();
-    }
-
-    // The Dart language specification mandates fall-throughs in [SwitchCase]es
-    // to be runtime errors.
-    if (!switch_case->is_default() && body_fragment.is_open() &&
-        (i < (node->cases().length() - 1))) {
-      const dart::Class& klass = dart::Class::ZoneHandle(
-          Z, dart::Library::LookupCoreClass(Symbols::FallThroughError()));
-      ASSERT(!klass.IsNull());
-      const Function& constructor = Function::ZoneHandle(
-          Z, klass.LookupConstructorAllowPrivate(
-                 H.DartSymbol("FallThroughError._create")));
-      ASSERT(!constructor.IsNull());
-      const dart::String& url = H.DartString(
-          parsed_function_->function().ToLibNamePrefixedQualifiedCString(),
-          Heap::kOld);
-
-      // Create instance of _FallThroughError
-      body_fragment += AllocateObject(klass, 0);
-      LocalVariable* instance = MakeTemporary();
-
-      // Call _FallThroughError._create constructor.
-      body_fragment += LoadLocal(instance);
-      body_fragment += PushArgument();  // this
-
-      body_fragment += Constant(url);
-      body_fragment += PushArgument();  // url
-
-      body_fragment += NullConstant();
-      body_fragment += PushArgument();  // line
-
-      body_fragment += StaticCall(TokenPosition::kNoSource, constructor, 3);
-      body_fragment += Drop();
-
-      // Throw the exception
-      body_fragment += PushArgument();
-      body_fragment += ThrowException(TokenPosition::kNoSource);
-      body_fragment += Drop();
-    }
-
-    // If there is an implicit fall-through we have one [SwitchCase] and
-    // multiple expressions, e.g.
-    //
-    //    switch(expr) {
-    //      case a:
-    //      case b:
-    //        <stmt-body>
-    //    }
-    //
-    // This means that the <stmt-body> will have more than 1 incoming edge (one
-    // from `a == expr` and one from `a != expr && b == expr`). The
-    // `block.Destination()` records the additional jump.
-    if (switch_case->expressions().length() > 1) {
-      block.DestinationDirect(i);
-    }
-  }
-
-  // Phase 2: Generate everything except the real bodies:
-  //   * jump directly to a body (if there is no jumper)
-  //   * jump to a wrapper block which jumps to the body (if there is a jumper)
-  Fragment current_instructions = head_instructions;
-  for (intptr_t i = 0; i < num_cases; i++) {
-    SwitchCase* switch_case = node->cases()[i];
-
-    if (switch_case->is_default()) {
-      ASSERT(i == (node->cases().length() - 1));
-
-      // Evaluate the conditions for the default [SwitchCase] just for the
-      // purpose of potentially triggering a compile-time error.
-      for (intptr_t k = 0; k < switch_case->expressions().length(); k++) {
-        constant_evaluator_.EvaluateExpression(switch_case->expressions()[k]);
-      }
-
-      if (block.HadJumper(i)) {
-        // There are several branches to the body, so we will make a goto to
-        // the join block (and prepend a join instruction to the real body).
-        JoinEntryInstr* join = block.DestinationDirect(i);
-        current_instructions += Goto(join);
-
-        current_instructions = Fragment(current_instructions.entry, join);
-        current_instructions += body_fragments[i];
-      } else {
-        current_instructions += body_fragments[i];
-      }
-    } else {
-      JoinEntryInstr* body_join = NULL;
-      if (block.HadJumper(i)) {
-        body_join = block.DestinationDirect(i);
-        body_fragments[i] = Fragment(body_join) + body_fragments[i];
-      }
-
-      for (intptr_t j = 0; j < switch_case->expressions().length(); j++) {
-        TargetEntryInstr* then;
-        TargetEntryInstr* otherwise;
-
-        Expression* expression = switch_case->expressions()[j];
-        current_instructions +=
-            Constant(constant_evaluator_.EvaluateExpression(expression));
-        current_instructions += PushArgument();
-        current_instructions += LoadLocal(scopes_->switch_variable);
-        current_instructions += PushArgument();
-        current_instructions += InstanceCall(
-            expression->position(), Symbols::EqualOperator(), Token::kEQ,
-            /*argument_count=*/2,
-            /*num_args_checked=*/2);
-        current_instructions += BranchIfTrue(&then, &otherwise);
-
-        Fragment then_fragment(then);
-
-        if (body_join != NULL) {
-          // There are several branches to the body, so we will make a goto to
-          // the join block (the real body has already been prepended with a
-          // join instruction).
-          then_fragment += Goto(body_join);
-        } else {
-          // There is only a signle branch to the body, so we will just append
-          // the body fragment.
-          then_fragment += body_fragments[i];
-        }
-
-        current_instructions = Fragment(otherwise);
-      }
-    }
-  }
-
-  bool has_no_default =
-      num_cases > 0 && !node->cases()[num_cases - 1]->is_default();
-  if (has_no_default) {
-    // There is no default, which means we have an open [current_instructions]
-    // (which is a [TargetEntryInstruction] for the last "otherwise" branch).
-    //
-    // Furthermore the last [SwitchCase] can be open as well.  If so, we need
-    // to join these two.
-    Fragment& last_body = body_fragments[node->cases().length() - 1];
-    if (last_body.is_open()) {
-      ASSERT(current_instructions.is_open());
-      ASSERT(current_instructions.current->IsTargetEntry());
-
-      // Join the last "otherwise" branch and the last [SwitchCase] fragment.
-      JoinEntryInstr* join = BuildJoinEntry();
-      current_instructions += Goto(join);
-      last_body += Goto(join);
-
-      current_instructions = Fragment(join);
-    }
-  } else {
-    // All non-default cases will be closed (i.e. break/continue/throw/return)
-    // So it is fine to just let more statements after the switch append to the
-    // default case.
-  }
-
-  delete[] body_fragments;
-
-  fragment_ = Fragment(head_instructions.entry, current_instructions.current);
-}
-
-
-void FlowGraphBuilder::VisitContinueSwitchStatement(
-    ContinueSwitchStatement* node) {
-  fragment_ =
-      streaming_flow_graph_builder_->BuildStatementAt(node->kernel_offset());
-}
-
-
-void FlowGraphBuilder::VisitAssertStatement(AssertStatement* node) {
-  STREAM_STATEMENT_IF_POSSIBLE(node);
-
-  if (!I->asserts()) {
-    fragment_ = Fragment();
-    return;
-  }
-
-  TargetEntryInstr* then;
-  TargetEntryInstr* otherwise;
-
-  Fragment instructions;
-  // Asserts can be of the following two kinds:
-  //
-  //    * `assert(expr)`
-  //    * `assert(() { ... })`
-  //
-  // The call to `_AssertionError._evaluateAssertion()` will take care of both
-  // and returns a boolean.
-  instructions += TranslateExpression(node->condition());
-  instructions += PushArgument();
-  instructions += EvaluateAssertion();
-  instructions += CheckBooleanInCheckedMode();
-  instructions += Constant(Bool::True());
-  instructions += BranchIfEqual(&then, &otherwise, false);
-
-  const dart::Class& klass = dart::Class::ZoneHandle(
-      Z, dart::Library::LookupCoreClass(Symbols::AssertionError()));
-  ASSERT(!klass.IsNull());
-  const Function& constructor =
-      Function::ZoneHandle(Z, klass.LookupConstructorAllowPrivate(
-                                  H.DartSymbol("_AssertionError._create")));
-  ASSERT(!constructor.IsNull());
-
-  const dart::String& url = H.DartString(
-      parsed_function_->function().ToLibNamePrefixedQualifiedCString(),
-      Heap::kOld);
-
-  // Create instance of _AssertionError
-  Fragment otherwise_fragment(otherwise);
-  otherwise_fragment += AllocateObject(klass, 0);
-  LocalVariable* instance = MakeTemporary();
-
-  // Call _AssertionError._create constructor.
-  otherwise_fragment += LoadLocal(instance);
-  otherwise_fragment += PushArgument();  // this
-
-  otherwise_fragment += Constant(H.DartString("<no message>", Heap::kOld));
-  otherwise_fragment += PushArgument();  // failedAssertion
-
-  otherwise_fragment += Constant(url);
-  otherwise_fragment += PushArgument();  // url
-
-  otherwise_fragment += IntConstant(0);
-  otherwise_fragment += PushArgument();  // line
-
-  otherwise_fragment += IntConstant(0);
-  otherwise_fragment += PushArgument();  // column
-
-  otherwise_fragment +=
-      node->message() != NULL
-          ? TranslateExpression(node->message())
-          : Constant(H.DartString("<no message>", Heap::kOld));
-  otherwise_fragment += PushArgument();  // message
-
-  otherwise_fragment += StaticCall(TokenPosition::kNoSource, constructor, 6);
-  otherwise_fragment += Drop();
-
-  // Throw _AssertionError exception.
-  otherwise_fragment += PushArgument();
-  otherwise_fragment += ThrowException(TokenPosition::kNoSource);
-  otherwise_fragment += Drop();
-
-  fragment_ = Fragment(instructions.entry, then);
-}
-
-
-void FlowGraphBuilder::VisitTryFinally(TryFinally* node) {
-  STREAM_STATEMENT_IF_POSSIBLE(node);
-
-  InlineBailout("kernel::FlowgraphBuilder::VisitTryFinally");
-
-  // There are 5 different cases where we need to execute the finally block:
-  //
-  //  a) 1/2/3th case: Special control flow going out of `node->body()`:
-  //
-  //   * [BreakStatement] transfers control to a [LabledStatement]
-  //   * [ContinueSwitchStatement] transfers control to a [SwitchCase]
-  //   * [ReturnStatement] returns a value
-  //
-  //   => All three cases will automatically append all finally blocks
-  //      between the branching point and the destination (so we don't need to
-  //      do anything here).
-  //
-  //  b) 4th case: Translating the body resulted in an open fragment (i.e. body
-  //               executes without any control flow out of it)
-  //
-  //   => We are responsible for jumping out of the body to a new block (with
-  //      different try index) and execute the finalizer.
-  //
-  //  c) 5th case: An exception occured inside the body.
-  //
-  //   => We are responsible for catching it, executing the finally block and
-  //      rethrowing the exception.
-  intptr_t try_handler_index = AllocateTryIndex();
-  Fragment try_body = TryCatch(try_handler_index);
-  JoinEntryInstr* after_try = BuildJoinEntry();
-
-  // Fill in the body of the try.
-  ++try_depth_;
-  {
-    TryFinallyBlock tfb(this, node->finalizer(), -1);
-    TryCatchBlock tcb(this, try_handler_index);
-    try_body += TranslateStatement(node->body());
-  }
-  --try_depth_;
-
-  if (try_body.is_open()) {
-    // Please note: The try index will be on level out of this block,
-    // thereby ensuring if there's an exception in the finally block we
-    // won't run it twice.
-    JoinEntryInstr* finally_entry = BuildJoinEntry();
-
-    try_body += Goto(finally_entry);
-
-    Fragment finally_body(finally_entry);
-    finally_body += TranslateStatement(node->finalizer());
-    finally_body += Goto(after_try);
-  }
-
-  // Fill in the body of the catch.
-  ++catch_depth_;
-  const Array& handler_types = Array::ZoneHandle(Z, Array::New(1, Heap::kOld));
-  handler_types.SetAt(0, Object::dynamic_type());
-  // Note: rethrow will actually force mark the handler as needing a stacktrace.
-  Fragment finally_body = CatchBlockEntry(handler_types, try_handler_index,
-                                          /* needs_stacktrace = */ false);
-  finally_body += TranslateStatement(node->finalizer());
-  if (finally_body.is_open()) {
-    finally_body += LoadLocal(CurrentException());
-    finally_body += PushArgument();
-    finally_body += LoadLocal(CurrentStackTrace());
-    finally_body += PushArgument();
-    finally_body +=
-        RethrowException(TokenPosition::kNoSource, try_handler_index);
-    Drop();
-  }
-  --catch_depth_;
-
-  fragment_ = Fragment(try_body.entry, after_try);
-}
-
-
-void FlowGraphBuilder::VisitTryCatch(class TryCatch* node) {
-  STREAM_STATEMENT_IF_POSSIBLE(node);
-
-  InlineBailout("kernel::FlowgraphBuilder::VisitTryCatch");
-
-  intptr_t try_handler_index = AllocateTryIndex();
-  Fragment try_body = TryCatch(try_handler_index);
-  JoinEntryInstr* after_try = BuildJoinEntry();
-
-  // Fill in the body of the try.
-  ++try_depth_;
-  {
-    TryCatchBlock block(this, try_handler_index);
-    try_body += TranslateStatement(node->body());
-    try_body += Goto(after_try);
-  }
-  --try_depth_;
-
-  ++catch_depth_;
-  const Array& handler_types =
-      Array::ZoneHandle(Z, Array::New(node->catches().length(), Heap::kOld));
-  bool needs_stacktrace = false;
-  for (intptr_t i = 0; i < node->catches().length(); i++) {
-    if (node->catches()[i]->stack_trace() != NULL) {
-      needs_stacktrace = true;
-      break;
-    }
-  }
-  Fragment catch_body =
-      CatchBlockEntry(handler_types, try_handler_index, needs_stacktrace);
-  // Fill in the body of the catch.
-  for (intptr_t i = 0; i < node->catches().length(); i++) {
-    Catch* catch_clause = node->catches()[i];
-
-    Fragment catch_handler_body;
-
-    catch_handler_body += EnterScope(catch_clause);
-
-    if (catch_clause->exception() != NULL) {
-      catch_handler_body += LoadLocal(CurrentException());
-      catch_handler_body += StoreLocal(
-          TokenPosition::kNoSource, LookupVariable(catch_clause->exception()));
-      catch_handler_body += Drop();
-    }
-    if (catch_clause->stack_trace() != NULL) {
-      catch_handler_body += LoadLocal(CurrentStackTrace());
-      catch_handler_body +=
-          StoreLocal(TokenPosition::kNoSource,
-                     LookupVariable(catch_clause->stack_trace()));
-      catch_handler_body += Drop();
-    }
-    AbstractType* type_guard = NULL;
-    if (catch_clause->guard() != NULL &&
-        !catch_clause->guard()->IsDynamicType()) {
-      type_guard = &T.TranslateType(catch_clause->guard());
-      handler_types.SetAt(i, *type_guard);
-    } else {
-      handler_types.SetAt(i, Object::dynamic_type());
-    }
-
-    {
-      CatchBlock block(this, CurrentException(), CurrentStackTrace(),
-                       try_handler_index);
-
-      catch_handler_body += TranslateStatement(catch_clause->body());
-
-      // Note: ExitScope adjusts context_depth_ so even if catch_handler_body
-      // is closed we still need to execute ExitScope for its side effect.
-      catch_handler_body += ExitScope(catch_clause);
-      if (catch_handler_body.is_open()) {
-        catch_handler_body += Goto(after_try);
-      }
-    }
-
-    if (type_guard != NULL) {
-      if (type_guard->IsMalformed()) {
-        catch_body += ThrowTypeError();
-        catch_body += Drop();
-      } else {
-        catch_body += LoadLocal(CurrentException());
-        catch_body += PushArgument();  // exception
-        catch_body += NullConstant();
-        catch_body += PushArgument();  // instantiator type arguments
-        catch_body += NullConstant();
-        catch_body += PushArgument();  // function type arguments
-        catch_body += Constant(*type_guard);
-        catch_body += PushArgument();  // guard type
-        catch_body += InstanceCall(
-            TokenPosition::kNoSource,
-            dart::Library::PrivateCoreLibName(Symbols::_instanceOf()),
-            Token::kIS, 4);
-
-        TargetEntryInstr* catch_entry;
-        TargetEntryInstr* next_catch_entry;
-        catch_body += BranchIfTrue(&catch_entry, &next_catch_entry);
-
-        Fragment(catch_entry) + catch_handler_body;
-        catch_body = Fragment(next_catch_entry);
-      }
-    } else {
-      catch_body += catch_handler_body;
-    }
-  }
-
-  // In case the last catch body was not handling the exception and branching to
-  // after the try block, we will rethrow the exception (i.e. no default catch
-  // handler).
-  if (catch_body.is_open()) {
-    catch_body += LoadLocal(CurrentException());
-    catch_body += PushArgument();
-    catch_body += LoadLocal(CurrentStackTrace());
-    catch_body += PushArgument();
-    catch_body += RethrowException(TokenPosition::kNoSource, try_handler_index);
-    Drop();
-  }
-  --catch_depth_;
-
-  fragment_ = Fragment(try_body.entry, after_try);
-}
-
-
-void FlowGraphBuilder::VisitYieldStatement(YieldStatement* node) {
-  STREAM_STATEMENT_IF_POSSIBLE(node);
-
-  ASSERT(node->is_native());  // Must have been desugared.
-  // Setup yield/continue point:
-  //
-  //   ...
-  //   :await_jump_var = index;
-  //   :await_ctx_var = :current_context_var
-  //   return <expr>
-  //
-  // Continuation<index>:
-  //   Drop(1)
-  //   ...
-  //
-  // BuildGraphOfFunction will create a dispatch that jumps to
-  // Continuation<:await_jump_var> upon entry to the function.
-  //
-  Fragment instructions = IntConstant(yield_continuations_.length() + 1);
-  instructions +=
-      StoreLocal(TokenPosition::kNoSource, scopes_->yield_jump_variable);
-  instructions += Drop();
-  instructions += LoadLocal(parsed_function_->current_context_var());
-  instructions +=
-      StoreLocal(TokenPosition::kNoSource, scopes_->yield_context_variable);
-  instructions += Drop();
-  instructions += TranslateExpression(node->expression());
-  instructions += Return(TokenPosition::kNoSource);
-
-  // Note: DropTempsInstr serves as an anchor instruction. It will not
-  // be linked into the resulting graph.
-  DropTempsInstr* anchor = new (Z) DropTempsInstr(0, NULL);
-  yield_continuations_.Add(YieldContinuation(anchor, CurrentTryIndex()));
-
-  Fragment continuation(instructions.entry, anchor);
-
-  if (parsed_function_->function().IsAsyncClosure() ||
-      parsed_function_->function().IsAsyncGenClosure()) {
-    // If function is async closure or async gen closure it takes three
-    // parameters where the second and the third are exception and stack_trace.
-    // Check if exception is non-null and rethrow it.
-    //
-    //   :async_op([:result, :exception, :stack_trace]) {
-    //     ...
-    //     Continuation<index>:
-    //       if (:exception != null) rethrow(:exception, :stack_trace);
-    //     ...
-    //   }
-    //
-    LocalScope* scope = parsed_function_->node_sequence()->scope();
-    LocalVariable* exception_var = scope->VariableAt(2);
-    LocalVariable* stack_trace_var = scope->VariableAt(3);
-    ASSERT(exception_var->name().raw() == Symbols::ExceptionParameter().raw());
-    ASSERT(stack_trace_var->name().raw() ==
-           Symbols::StackTraceParameter().raw());
-
-    TargetEntryInstr* no_error;
-    TargetEntryInstr* error;
-
-    continuation += LoadLocal(exception_var);
-    continuation += BranchIfNull(&no_error, &error);
-
-    Fragment rethrow(error);
-    rethrow += LoadLocal(exception_var);
-    rethrow += PushArgument();
-    rethrow += LoadLocal(stack_trace_var);
-    rethrow += PushArgument();
-    rethrow +=
-        RethrowException(node->position(), CatchClauseNode::kInvalidTryIndex);
-    Drop();
-
-
-    continuation = Fragment(continuation.entry, no_error);
-  }
-
-  fragment_ = continuation;
-}
-
-
-Fragment FlowGraphBuilder::TranslateFunctionNode(FunctionNode* node,
-                                                 TreeNode* parent) {
-  // The VM has a per-isolate table of functions indexed by the enclosing
-  // function and token position.
-  Function& function = Function::ZoneHandle(Z);
-  for (intptr_t i = 0; i < scopes_->function_scopes.length(); ++i) {
-    if (scopes_->function_scopes[i].kernel_offset != node->kernel_offset()) {
-      continue;
-    }
-
-    TokenPosition position = node->position();
-    if (parent->IsFunctionDeclaration()) {
-      position = FunctionDeclaration::Cast(parent)->position();
-    }
-    if (!position.IsReal()) {
-      // Positions has to be unique in regards to the parent.
-      // A non-real at this point is probably -1, we cannot blindly use that
-      // as others might use it too. Create a new dummy non-real TokenPosition.
-      position = TokenPosition(i).ToSynthetic();
-    }
-
-    // NOTE: This is not TokenPosition in the general sense!
-    function = I->LookupClosureFunction(parsed_function_->function(), position);
-    if (function.IsNull()) {
-      const dart::String* name;
-      if (parent->IsFunctionExpression()) {
-        name = &Symbols::AnonymousClosure();
-      } else {
-        ASSERT(parent->IsFunctionDeclaration());
-        name = &H.DartSymbol(
-            FunctionDeclaration::Cast(parent)->variable()->name());
-      }
-      // NOTE: This is not TokenPosition in the general sense!
-      function = Function::NewClosureFunction(
-          *name, parsed_function_->function(), position);
-
-      function.set_is_debuggable(node->dart_async_marker() ==
-                                 FunctionNode::kSync);
-      switch (node->dart_async_marker()) {
-        case FunctionNode::kSyncStar:
-          function.set_modifier(RawFunction::kSyncGen);
-          break;
-        case FunctionNode::kAsync:
-          function.set_modifier(RawFunction::kAsync);
-          function.set_is_inlinable(!FLAG_causal_async_stacks);
-          break;
-        case FunctionNode::kAsyncStar:
-          function.set_modifier(RawFunction::kAsyncGen);
-          function.set_is_inlinable(!FLAG_causal_async_stacks);
-          break;
-        default:
-          // no special modifier
-          break;
-      }
-      function.set_is_generated_body(node->async_marker() ==
-                                     FunctionNode::kSyncYielding);
-      if (function.IsAsyncClosure() || function.IsAsyncGenClosure()) {
-        function.set_is_inlinable(!FLAG_causal_async_stacks);
-      }
-
-      function.set_end_token_pos(node->end_position());
-      LocalScope* scope = scopes_->function_scopes[i].scope;
-      const ContextScope& context_scope =
-          ContextScope::Handle(Z, scope->PreserveOuterScope(context_depth_));
-      function.set_context_scope(context_scope);
-      function.set_kernel_function(node);
-      KernelReader::SetupFunctionParameters(H, T, dart::Class::Handle(Z),
-                                            function, node,
-                                            false,  // is_method
-                                            true);  // is_closure
-      // Finalize function type.
-      Type& signature_type = Type::Handle(Z, function.SignatureType());
-      signature_type ^=
-          ClassFinalizer::FinalizeType(*active_class_.klass, signature_type);
-      function.SetSignatureType(signature_type);
-
-      I->AddClosureFunction(function);
-    }
-    break;
-  }
-
-  const dart::Class& closure_class =
-      dart::Class::ZoneHandle(Z, I->object_store()->closure_class());
-  ASSERT(!closure_class.IsNull());
-  Fragment instructions = AllocateObject(closure_class, function);
-  LocalVariable* closure = MakeTemporary();
-
-  // The function signature can have uninstantiated class type parameters.
-  //
-  // TODO(regis): Also handle the case of a function signature that has
-  // uninstantiated function type parameters.
-  if (!function.HasInstantiatedSignature(kCurrentClass)) {
-    instructions += LoadLocal(closure);
-    instructions += LoadInstantiatorTypeArguments();
-    instructions +=
-        StoreInstanceField(TokenPosition::kNoSource,
-                           Closure::instantiator_type_arguments_offset());
-  }
-
-  // Store the function and the context in the closure.
-  instructions += LoadLocal(closure);
-  instructions += Constant(function);
-  instructions +=
-      StoreInstanceField(TokenPosition::kNoSource, Closure::function_offset());
-
-  instructions += LoadLocal(closure);
-  instructions += LoadLocal(parsed_function_->current_context_var());
-  instructions +=
-      StoreInstanceField(TokenPosition::kNoSource, Closure::context_offset());
-
-  return instructions;
-}
-
-
 RawObject* EvaluateMetadata(const dart::Field& metadata_field) {
   LongJumpScope jump;
   if (setjmp(*jump.Set()) == 0) {
     Thread* thread = Thread::Current();
     Zone* zone_ = thread->zone();
-
-    TreeNode* kernel_node =
-        reinterpret_cast<TreeNode*>(metadata_field.kernel_field());
-    List<Expression>* metadata_expressions = NULL;
-    if (kernel_node->IsClass()) {
-      metadata_expressions = &Class::Cast(kernel_node)->annotations();
-    } else if (kernel_node->IsProcedure()) {
-      metadata_expressions = &Procedure::Cast(kernel_node)->annotations();
-    } else if (kernel_node->IsField()) {
-      metadata_expressions = &Field::Cast(kernel_node)->annotations();
-    } else if (kernel_node->IsConstructor()) {
-      metadata_expressions = &Constructor::Cast(kernel_node)->annotations();
-    } else {
-      FATAL1("No support for metadata on this type of kernel node %p\n",
-             kernel_node);
-    }
-
     TranslationHelper helper(thread);
     Script& script = Script::Handle(Z, metadata_field.Script());
     helper.SetStringOffsets(
@@ -6017,20 +2700,11 @@
     helper.SetStringData(TypedData::Handle(Z, script.kernel_string_data()));
     helper.SetCanonicalNames(
         TypedData::Handle(Z, script.kernel_canonical_names()));
-    DartTypeTranslator type_translator(&helper, NULL, true);
-    ConstantEvaluator constant_evaluator(/* flow_graph_builder = */ NULL, Z,
-                                         &helper, &type_translator);
 
-    const Array& metadata_values =
-        Array::Handle(Z, Array::New(metadata_expressions->length()));
-
-    for (intptr_t i = 0; i < metadata_expressions->length(); i++) {
-      const Instance& value =
-          constant_evaluator.EvaluateExpression((*metadata_expressions)[i]);
-      metadata_values.SetAt(i, value);
-    }
-
-    return metadata_values.raw();
+    StreamingFlowGraphBuilder streaming_flow_graph_builder(
+        &helper, zone_, script.kernel_data(), script.kernel_data_size());
+    return streaming_flow_graph_builder.EvaluateMetadata(
+        metadata_field.kernel_offset());
   } else {
     Thread* thread = Thread::Current();
     Error& error = Error::Handle();
@@ -6044,20 +2718,6 @@
 RawObject* BuildParameterDescriptor(const Function& function) {
   LongJumpScope jump;
   if (setjmp(*jump.Set()) == 0) {
-    TreeNode* kernel_node =
-        reinterpret_cast<TreeNode*>(function.kernel_function());
-    FunctionNode* function_node = NULL;
-    if (kernel_node->IsProcedure()) {
-      function_node = Procedure::Cast(kernel_node)->function();
-    } else if (kernel_node->IsConstructor()) {
-      function_node = Constructor::Cast(kernel_node)->function();
-    } else if (kernel_node->IsFunctionNode()) {
-      function_node = FunctionNode::Cast(kernel_node);
-    } else {
-      UNIMPLEMENTED();
-      return NULL;
-    }
-
     Thread* thread = Thread::Current();
     Zone* zone_ = thread->zone();
     TranslationHelper helper(thread);
@@ -6067,45 +2727,11 @@
     helper.SetStringData(TypedData::Handle(Z, script.kernel_string_data()));
     helper.SetCanonicalNames(
         TypedData::Handle(Z, script.kernel_canonical_names()));
-    DartTypeTranslator type_translator(&helper, NULL, true);
-    ConstantEvaluator constant_evaluator(/* flow_graph_builder = */ NULL, Z,
-                                         &helper, &type_translator);
 
-    const intptr_t positional_count =
-        function_node->positional_parameters().length();
-    const intptr_t param_count =
-        positional_count + function_node->named_parameters().length();
-    const Array& param_descriptor = Array::Handle(
-        Array::New(param_count * Parser::kParameterEntrySize, Heap::kOld));
-    for (intptr_t i = 0; i < param_count; ++i) {
-      const intptr_t entry_start = i * Parser::kParameterEntrySize;
-
-      VariableDeclaration* variable;
-      if (i < positional_count) {
-        variable = function_node->positional_parameters()[i];
-      } else {
-        variable = function_node->named_parameters()[i - positional_count];
-      }
-
-      param_descriptor.SetAt(
-          entry_start + Parser::kParameterIsFinalOffset,
-          variable->IsFinal() ? Bool::True() : Bool::False());
-
-      if (variable->initializer() != NULL) {
-        param_descriptor.SetAt(
-            entry_start + Parser::kParameterDefaultValueOffset,
-            constant_evaluator.EvaluateExpression(variable->initializer()));
-      } else {
-        param_descriptor.SetAt(
-            entry_start + Parser::kParameterDefaultValueOffset,
-            Object::null_instance());
-      }
-
-      param_descriptor.SetAt(entry_start + Parser::kParameterMetadataOffset,
-                             /* Issue(28434): Missing parameter metadata. */
-                             Object::null_instance());
-    }
-    return param_descriptor.raw();
+    StreamingFlowGraphBuilder streaming_flow_graph_builder(
+        &helper, zone_, script.kernel_data(), script.kernel_data_size());
+    return streaming_flow_graph_builder.BuildParameterDescriptor(
+        function.kernel_offset());
   } else {
     Thread* thread = Thread::Current();
     Error& error = Error::Handle();
diff --git a/runtime/vm/kernel_to_il.h b/runtime/vm/kernel_to_il.h
index 038e0e1..9591977 100644
--- a/runtime/vm/kernel_to_il.h
+++ b/runtime/vm/kernel_to_il.h
@@ -13,7 +13,6 @@
 #include "vm/flow_graph.h"
 #include "vm/flow_graph_builder.h"
 #include "vm/intermediate_language.h"
-#include "vm/kernel.h"
 
 namespace dart {
 namespace kernel {
@@ -551,115 +550,6 @@
 };
 
 
-// There are several cases when we are compiling constant expressions:
-//
-//   * constant field initializers:
-//      const FieldName = <expr>;
-//
-//   * constant expressions:
-//      const [<expr>, ...]
-//      const {<expr> : <expr>, ...}
-//      const Constructor(<expr>, ...)
-//
-//   * constant default parameters:
-//      f(a, [b = <expr>])
-//      f(a, {b: <expr>})
-//
-//   * constant values to compare in a [SwitchCase]
-//      case <expr>:
-//
-// In all cases `<expr>` must be recursively evaluated and canonicalized at
-// compile-time.
-class ConstantEvaluator : public ExpressionVisitor {
- public:
-  ConstantEvaluator(FlowGraphBuilder* builder,
-                    Zone* zone,
-                    TranslationHelper* h,
-                    DartTypeTranslator* type_translator);
-  virtual ~ConstantEvaluator() {}
-
-  Instance& EvaluateExpression(Expression* node);
-  Object& EvaluateExpressionSafe(Expression* node);
-  Instance& EvaluateConstructorInvocation(ConstructorInvocation* node);
-  Instance& EvaluateListLiteral(ListLiteral* node);
-  Instance& EvaluateMapLiteral(MapLiteral* node);
-
-  virtual void VisitDefaultExpression(Expression* node) { UNREACHABLE(); }
-
-  virtual void VisitBigintLiteral(BigintLiteral* node);
-  virtual void VisitBoolLiteral(BoolLiteral* node);
-  virtual void VisitDoubleLiteral(DoubleLiteral* node);
-  virtual void VisitIntLiteral(IntLiteral* node);
-  virtual void VisitNullLiteral(NullLiteral* node);
-  virtual void VisitStringLiteral(StringLiteral* node);
-  virtual void VisitSymbolLiteral(SymbolLiteral* node);
-  virtual void VisitTypeLiteral(TypeLiteral* node);
-
-  virtual void VisitListLiteral(ListLiteral* node);
-  virtual void VisitMapLiteral(MapLiteral* node);
-
-  virtual void VisitConstructorInvocation(ConstructorInvocation* node);
-  virtual void VisitMethodInvocation(MethodInvocation* node);
-  virtual void VisitStaticGet(StaticGet* node);
-  virtual void VisitVariableGet(VariableGet* node);
-  virtual void VisitLet(Let* node);
-  virtual void VisitStaticInvocation(StaticInvocation* node);
-  virtual void VisitStringConcatenation(StringConcatenation* node);
-  virtual void VisitConditionalExpression(ConditionalExpression* node);
-  virtual void VisitLogicalExpression(LogicalExpression* node);
-  virtual void VisitNot(Not* node);
-  virtual void VisitPropertyGet(PropertyGet* node);
-
- private:
-  // This will translate type arguments form [kernel_arguments].  If no type
-  // arguments are passed and the [target] is a factory then the null type
-  // argument array will be returned.
-  //
-  // If none of these cases apply, NULL will be returned.
-  const TypeArguments* TranslateTypeArguments(const Function& target,
-                                              dart::Class* target_klass,
-                                              Arguments* kernel_arguments);
-
-  const Object& RunFunction(const Function& function,
-                            Arguments* arguments,
-                            const Instance* receiver = NULL,
-                            const TypeArguments* type_args = NULL);
-
-  const Object& RunFunction(const Function& function,
-                            const Array& arguments,
-                            const Array& names);
-
-  RawObject* EvaluateConstConstructorCall(const dart::Class& type_class,
-                                          const TypeArguments& type_arguments,
-                                          const Function& constructor,
-                                          const Object& argument);
-
-  void AssertBoolInCheckedMode() {
-    if (isolate_->type_checks() && !result_.IsBool()) {
-      translation_helper_.ReportError("Expected boolean expression.");
-    }
-  }
-
-  bool EvaluateBooleanExpression(Expression* expression) {
-    EvaluateExpression(expression);
-    AssertBoolInCheckedMode();
-    return result_.raw() == Bool::True().raw();
-  }
-
-  bool GetCachedConstant(TreeNode* node, Instance* value);
-  void CacheConstantValue(TreeNode* node, const Instance& value);
-
-  FlowGraphBuilder* builder_;
-  Isolate* isolate_;
-  Zone* zone_;
-  TranslationHelper& translation_helper_;
-  DartTypeTranslator& type_translator_;
-
-  Script& script_;
-  Instance& result_;
-};
-
-
 struct FunctionScope {
   intptr_t kernel_offset;
   LocalScope* scope;
@@ -728,9 +618,9 @@
       : entry(NULL), try_index(CatchClauseNode::kInvalidTryIndex) {}
 };
 
-class FlowGraphBuilder : public ExpressionVisitor, public StatementVisitor {
+class FlowGraphBuilder {
  public:
-  FlowGraphBuilder(TreeNode* node,
+  FlowGraphBuilder(intptr_t kernel_offset,
                    ParsedFunction* parsed_function,
                    const ZoneGrowableArray<const ICData*>& ic_data_array,
                    ZoneGrowableArray<intptr_t>* context_level_array,
@@ -741,106 +631,24 @@
 
   FlowGraph* BuildGraph();
 
-  virtual void VisitDefaultExpression(Expression* node) { UNREACHABLE(); }
-  virtual void VisitDefaultStatement(Statement* node) { UNREACHABLE(); }
-
-  virtual void VisitInvalidExpression(InvalidExpression* node);
-  virtual void VisitNullLiteral(NullLiteral* node);
-  virtual void VisitBoolLiteral(BoolLiteral* node);
-  virtual void VisitIntLiteral(IntLiteral* node);
-  virtual void VisitBigintLiteral(BigintLiteral* node);
-  virtual void VisitDoubleLiteral(DoubleLiteral* node);
-  virtual void VisitStringLiteral(StringLiteral* node);
-  virtual void VisitSymbolLiteral(SymbolLiteral* node);
-  virtual void VisitTypeLiteral(TypeLiteral* node);
-  virtual void VisitVariableGet(VariableGet* node);
-  virtual void VisitVariableSet(VariableSet* node);
-  virtual void VisitStaticGet(StaticGet* node);
-  virtual void VisitStaticSet(StaticSet* node);
-  virtual void VisitPropertyGet(PropertyGet* node);
-  virtual void VisitPropertySet(PropertySet* node);
-  virtual void VisitDirectPropertyGet(DirectPropertyGet* node);
-  virtual void VisitDirectPropertySet(DirectPropertySet* node);
-  virtual void VisitStaticInvocation(StaticInvocation* node);
-  virtual void VisitMethodInvocation(MethodInvocation* node);
-  virtual void VisitDirectMethodInvocation(DirectMethodInvocation* node);
-  virtual void VisitConstructorInvocation(ConstructorInvocation* node);
-  virtual void VisitIsExpression(IsExpression* node);
-  virtual void VisitAsExpression(AsExpression* node);
-  virtual void VisitConditionalExpression(ConditionalExpression* node);
-  virtual void VisitLogicalExpression(LogicalExpression* node);
-  virtual void VisitNot(Not* node);
-  virtual void VisitThisExpression(ThisExpression* node);
-  virtual void VisitStringConcatenation(StringConcatenation* node);
-  virtual void VisitListLiteral(ListLiteral* node);
-  virtual void VisitMapLiteral(MapLiteral* node);
-  virtual void VisitFunctionExpression(FunctionExpression* node);
-  virtual void VisitLet(Let* node);
-  virtual void VisitThrow(Throw* node);
-  virtual void VisitRethrow(Rethrow* node);
-
-  virtual void VisitInvalidStatement(InvalidStatement* node);
-  virtual void VisitEmptyStatement(EmptyStatement* node);
-  virtual void VisitBlock(Block* node);
-  virtual void VisitReturnStatement(ReturnStatement* node);
-  virtual void VisitExpressionStatement(ExpressionStatement* node);
-  virtual void VisitVariableDeclaration(VariableDeclaration* node);
-  virtual void VisitFunctionDeclaration(FunctionDeclaration* node);
-  virtual void VisitIfStatement(IfStatement* node);
-  virtual void VisitWhileStatement(WhileStatement* node);
-  virtual void VisitDoStatement(DoStatement* node);
-  virtual void VisitForStatement(ForStatement* node);
-  virtual void VisitForInStatement(ForInStatement* node);
-  virtual void VisitLabeledStatement(LabeledStatement* node);
-  virtual void VisitBreakStatement(BreakStatement* node);
-  virtual void VisitSwitchStatement(SwitchStatement* node);
-  virtual void VisitContinueSwitchStatement(ContinueSwitchStatement* node);
-  virtual void VisitAssertStatement(AssertStatement* node);
-  virtual void VisitTryFinally(TryFinally* node);
-  virtual void VisitTryCatch(TryCatch* node);
-  virtual void VisitYieldStatement(YieldStatement* node);
-
  private:
-  FlowGraph* BuildGraphOfFunction(FunctionNode* node,
-                                  Constructor* constructor = NULL);
-  FlowGraph* BuildGraphOfFieldAccessor(Field* node,
-                                       LocalVariable* setter_value);
-  FlowGraph* BuildGraphOfStaticFieldInitializer(Field* node);
   FlowGraph* BuildGraphOfMethodExtractor(const Function& method);
-  FlowGraph* BuildGraphOfImplicitClosureFunction(FunctionNode* kernel_function,
-                                                 const Function& function);
   FlowGraph* BuildGraphOfNoSuchMethodDispatcher(const Function& function);
   FlowGraph* BuildGraphOfInvokeFieldDispatcher(const Function& function);
 
-  Fragment NativeFunctionBody(FunctionNode* kernel_function,
+  Fragment NativeFunctionBody(intptr_t first_positional_offset,
                               const Function& function);
 
-  void SetupDefaultParameterValues(FunctionNode* function);
-
   TargetEntryInstr* BuildTargetEntry();
   JoinEntryInstr* BuildJoinEntry();
   JoinEntryInstr* BuildJoinEntry(intptr_t try_index);
 
-  Fragment TranslateArguments(Arguments* node, Array* argument_names);
   ArgumentArray GetArguments(int count);
 
-  Fragment TranslateInitializers(Class* kernel_class,
-                                 List<Initializer>* initialiers);
-  Fragment TranslateFieldInitializer(NameIndex canonical_name,
-                                     Expression* init);
-
-  Fragment TranslateStatement(Statement* statement);
-  Fragment TranslateCondition(Expression* expression, bool* negate);
-  Fragment TranslateExpression(Expression* expression);
-
   Fragment TranslateFinallyFinalizers(TryFinallyBlock* outer_finally,
                                       intptr_t target_context_depth);
 
-  Fragment TranslateFunctionNode(FunctionNode* node, TreeNode* parent);
-
-  Fragment EnterScope(TreeNode* node, bool* new_context = NULL);
   Fragment EnterScope(intptr_t kernel_offset, bool* new_context = NULL);
-  Fragment ExitScope(TreeNode* node);
   Fragment ExitScope(intptr_t kernel_offset);
 
   Fragment LoadContextAt(int depth);
@@ -943,7 +751,6 @@
 
   Fragment EvaluateAssertion();
   Fragment CheckReturnTypeInCheckedMode();
-  Fragment CheckVariableTypeInCheckedMode(VariableDeclaration* variable);
   Fragment CheckVariableTypeInCheckedMode(const AbstractType& dst_type,
                                           const dart::String& name_symbol);
   Fragment CheckBooleanInCheckedMode();
@@ -954,9 +761,6 @@
   Fragment AssertAssignable(const dart::AbstractType& dst_type,
                             const dart::String& dst_name);
 
-  template <class Invocation>
-  bool RecognizeComparisonWithNull(Token::Kind token_kind, Invocation* node);
-
   bool NeedsDebugStepCheck(const Function& function, TokenPosition position);
   bool NeedsDebugStepCheck(Value* value, TokenPosition position);
   Fragment DebugStepCheck(TokenPosition position);
@@ -970,10 +774,6 @@
   intptr_t CurrentTryIndex();
   intptr_t AllocateTryIndex() { return next_used_try_index_++; }
 
-  void AddVariable(VariableDeclaration* declaration, LocalVariable* variable);
-  void AddParameter(VariableDeclaration* declaration,
-                    LocalVariable* variable,
-                    intptr_t pos);
   dart::LocalVariable* LookupVariable(VariableDeclaration* var);
   dart::LocalVariable* LookupVariable(intptr_t kernel_offset);
 
@@ -993,9 +793,7 @@
   Thread* thread_;
   Zone* zone_;
 
-  // The node we are currently compiling (e.g. FunctionNode, Constructor,
-  // Field)
-  TreeNode* node_;
+  intptr_t kernel_offset_;
 
   ParsedFunction* parsed_function_;
   intptr_t osr_id_;
@@ -1025,7 +823,6 @@
   intptr_t try_depth_;
   intptr_t catch_depth_;
   intptr_t for_in_depth_;
-  Fragment fragment_;
   Value* stack_;
   intptr_t pending_argument_count_;
 
@@ -1069,7 +866,6 @@
 
   ActiveClass active_class_;
   DartTypeTranslator type_translator_;
-  ConstantEvaluator constant_evaluator_;
 
   StreamingFlowGraphBuilder* streaming_flow_graph_builder_;
 
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 62844ac..a1f636e 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -2740,7 +2740,7 @@
   extractor.set_parameter_types(Object::extractor_parameter_types());
   extractor.set_parameter_names(Object::extractor_parameter_names());
   extractor.set_result_type(Object::dynamic_type());
-  extractor.set_kernel_function(kernel_function());
+  extractor.set_kernel_offset(kernel_offset());
 
   extractor.set_extracted_method_closure(closure_function);
   extractor.set_is_debuggable(false);
@@ -6814,7 +6814,7 @@
   NOT_IN_PRECOMPILED(result.set_deoptimization_counter(0));
   NOT_IN_PRECOMPILED(result.set_optimized_instruction_count(0));
   NOT_IN_PRECOMPILED(result.set_optimized_call_site_count(0));
-  result.set_kernel_function(NULL);
+  result.set_kernel_offset(0);
   result.set_is_optimizable(is_native ? false : true);
   result.set_is_inlinable(true);
   result.set_allows_hoisting_check_class(true);
@@ -6854,7 +6854,7 @@
   clone.set_deoptimization_counter(0);
   clone.set_optimized_instruction_count(0);
   clone.set_optimized_call_site_count(0);
-  clone.set_kernel_function(kernel_function());
+  clone.set_kernel_offset(kernel_offset());
   if (new_owner.NumTypeParameters() > 0) {
     // Adjust uninstantiated types to refer to type parameters of the new owner.
     const TypeArguments& type_params =
@@ -7010,7 +7010,7 @@
     param_name = ParameterNameAt(has_receiver - kClosure + i);
     closure_function.SetParameterNameAt(i, param_name);
   }
-  closure_function.set_kernel_function(kernel_function());
+  closure_function.set_kernel_offset(kernel_offset());
 
   const Type& signature_type =
       Type::Handle(zone, closure_function.SignatureType());
@@ -7480,7 +7480,7 @@
 
 
 bool Function::CheckSourceFingerprint(const char* prefix, int32_t fp) const {
-  if ((kernel_function() == NULL) && (SourceFingerprint() != fp)) {
+  if ((kernel_offset() <= 0) && (SourceFingerprint() != fp)) {
     const bool recalculatingFingerprints = false;
     if (recalculatingFingerprints) {
       // This output can be copied into a file, then used with sed
@@ -7864,7 +7864,7 @@
   result.set_token_pos(token_pos);
   result.set_has_initializer(false);
   result.set_is_unboxing_candidate(true);
-  result.set_kernel_field(NULL);
+  result.set_kernel_offset(0);
   Isolate* isolate = Isolate::Current();
 
   // Use field guards if they are enabled and the isolate has never reloaded.
@@ -7944,7 +7944,7 @@
   Field& clone = Field::Handle();
   clone ^= Object::Clone(*this, Heap::kOld);
   clone.SetOriginal(original);
-  clone.set_kernel_field(original.kernel_field());
+  clone.set_kernel_offset(original.kernel_offset());
   return clone.raw();
 }
 
@@ -9121,6 +9121,16 @@
 }
 
 
+void Script::set_kernel_data(const uint8_t* kernel_data) const {
+  StoreNonPointer(&raw_ptr()->kernel_data_, kernel_data);
+}
+
+
+void Script::set_kernel_data_size(const intptr_t kernel_data_size) const {
+  StoreNonPointer(&raw_ptr()->kernel_data_size_, kernel_data_size);
+}
+
+
 void Script::set_kernel_string_offsets(const TypedData& offsets) const {
   StorePointer(&raw_ptr()->kernel_string_offsets_, offsets.raw());
 }
@@ -10085,7 +10095,7 @@
 void Library::AddMetadata(const Object& owner,
                           const String& name,
                           TokenPosition token_pos,
-                          kernel::TreeNode* kernel_node) const {
+                          intptr_t kernel_offset) const {
   Thread* thread = Thread::Current();
   ASSERT(thread->IsMutatorThread());
   Zone* zone = thread->zone();
@@ -10098,7 +10108,7 @@
   field.SetFieldType(Object::dynamic_type());
   field.set_is_reflectable(false);
   field.SetStaticValue(Array::empty_array(), true);
-  field.set_kernel_field(kernel_node);
+  field.set_kernel_offset(kernel_offset);
   GrowableObjectArray& metadata =
       GrowableObjectArray::Handle(zone, this->metadata());
   metadata.Add(field, Heap::kOld);
@@ -10108,36 +10118,36 @@
 void Library::AddClassMetadata(const Class& cls,
                                const Object& tl_owner,
                                TokenPosition token_pos,
-                               kernel::TreeNode* kernel_node) const {
+                               intptr_t kernel_offset) const {
   Thread* thread = Thread::Current();
   Zone* zone = thread->zone();
   // We use the toplevel class as the owner of a class's metadata field because
   // a class's metadata is in scope of the library, not the class.
   AddMetadata(tl_owner,
               String::Handle(zone, MakeClassMetaName(thread, zone, cls)),
-              token_pos, kernel_node);
+              token_pos, kernel_offset);
 }
 
 
 void Library::AddFieldMetadata(const Field& field,
                                TokenPosition token_pos,
-                               kernel::TreeNode* kernel_node) const {
+                               intptr_t kernel_offset) const {
   Thread* thread = Thread::Current();
   Zone* zone = thread->zone();
   AddMetadata(Object::Handle(zone, field.RawOwner()),
               String::Handle(zone, MakeFieldMetaName(thread, zone, field)),
-              token_pos, kernel_node);
+              token_pos, kernel_offset);
 }
 
 
 void Library::AddFunctionMetadata(const Function& func,
                                   TokenPosition token_pos,
-                                  kernel::TreeNode* kernel_node) const {
+                                  intptr_t kernel_offset) const {
   Thread* thread = Thread::Current();
   Zone* zone = thread->zone();
   AddMetadata(Object::Handle(zone, func.RawOwner()),
               String::Handle(zone, MakeFunctionMetaName(thread, zone, func)),
-              token_pos, kernel_node);
+              token_pos, kernel_offset);
 }
 
 
@@ -10213,7 +10223,7 @@
   Object& metadata = Object::Handle();
   metadata = field.StaticValue();
   if (field.StaticValue() == Object::empty_array().raw()) {
-    if (field.kernel_field() != NULL) {
+    if (field.kernel_offset() > 0) {
       metadata = kernel::EvaluateMetadata(field);
     } else {
       metadata = Parser::ParseMetadata(field);
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 7419287..c6715d6 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -2627,17 +2627,17 @@
 #endif
   }
 
-  void* kernel_function() const {
+  intptr_t kernel_offset() const {
 #if defined(DART_PRECOMPILED_RUNTIME)
-    return NULL;
+    return 0;
 #else
-    return raw_ptr()->kernel_function_;
+    return raw_ptr()->kernel_offset_;
 #endif
   }
 
-  void set_kernel_function(void* kernel_function) const {
+  void set_kernel_offset(intptr_t kernel_offset) const {
 #if !defined(DART_PRECOMPILED_RUNTIME)
-    StoreNonPointer(&raw_ptr()->kernel_function_, kernel_function);
+    StoreNonPointer(&raw_ptr()->kernel_offset_, kernel_offset);
 #endif
   }
 
@@ -3181,17 +3181,17 @@
     set_kind_bits(DoubleInitializedBit::update(value, raw_ptr()->kind_bits_));
   }
 
-  void* kernel_field() const {
+  intptr_t kernel_offset() const {
 #if defined(DART_PRECOMPILED_RUNTIME)
     return NULL;
 #else
-    return raw_ptr()->kernel_field_;
+    return raw_ptr()->kernel_offset_;
 #endif
   }
 
-  void set_kernel_field(void* kernel_field) const {
+  void set_kernel_offset(intptr_t kernel_offset) const {
 #if !defined(DART_PRECOMPILED_RUNTIME)
-    StoreNonPointer(&raw_ptr()->kernel_field_, kernel_field);
+    StoreNonPointer(&raw_ptr()->kernel_offset_, kernel_offset);
 #endif
   }
 
@@ -3605,6 +3605,12 @@
   }
   void set_compile_time_constants(const Array& value) const;
 
+  const uint8_t* kernel_data() { return raw_ptr()->kernel_data_; }
+  void set_kernel_data(const uint8_t* kernel_data) const;
+
+  intptr_t kernel_data_size() { return raw_ptr()->kernel_data_size_; }
+  void set_kernel_data_size(const intptr_t kernel_data_size) const;
+
   RawTypedData* kernel_string_offsets() const {
     return raw_ptr()->kernel_string_offsets_;
   }
@@ -3843,13 +3849,13 @@
   void AddClassMetadata(const Class& cls,
                         const Object& tl_owner,
                         TokenPosition token_pos,
-                        kernel::TreeNode* kernel_node = NULL) const;
+                        intptr_t kernel_offset = 0) const;
   void AddFieldMetadata(const Field& field,
                         TokenPosition token_pos,
-                        kernel::TreeNode* kernel_node = NULL) const;
+                        intptr_t kernel_offset = 0) const;
   void AddFunctionMetadata(const Function& func,
                            TokenPosition token_pos,
-                           kernel::TreeNode* kernel_node = NULL) const;
+                           intptr_t kernel_offset = 0) const;
   void AddLibraryMetadata(const Object& tl_owner,
                           TokenPosition token_pos) const;
   void AddTypeParameterMetadata(const TypeParameter& param,
@@ -4018,7 +4024,7 @@
   void AddMetadata(const Object& owner,
                    const String& name,
                    TokenPosition token_pos,
-                   kernel::TreeNode* kernel_node = NULL) const;
+                   intptr_t kernel_offset = 0) const;
 
   FINAL_HEAP_OBJECT_IMPLEMENTATION(Library, Object);
 
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc
index c3f39cc..6f63938 100644
--- a/runtime/vm/parser.cc
+++ b/runtime/vm/parser.cc
@@ -235,47 +235,11 @@
 
 kernel::ScopeBuildingResult* ParsedFunction::EnsureKernelScopes() {
   if (kernel_scopes_ == NULL) {
-    kernel::TreeNode* node = NULL;
-    if (function().kernel_function() != NULL) {
-      node = static_cast<kernel::TreeNode*>(function().kernel_function());
-    }
-
-    intptr_t kernel_offset = -1;
-    const uint8_t* kernel_data = NULL;
-    intptr_t kernel_data_size = 0;
-    if (node != NULL) {
-      kernel::TreeNode* library_node = node;
-      if (node != NULL) {
-        const Function* parent = &function();
-        while (true) {
-          library_node =
-              static_cast<kernel::TreeNode*>(parent->kernel_function());
-          while (library_node != NULL && !library_node->IsLibrary()) {
-            if (library_node->IsMember()) {
-              library_node = kernel::Member::Cast(library_node)->parent();
-            } else if (library_node->IsClass()) {
-              library_node = kernel::Class::Cast(library_node)->parent();
-              break;
-            } else {
-              library_node = NULL;
-              break;
-            }
-          }
-          if (library_node != NULL) break;
-          parent = &Function::Handle(parent->parent_function());
-        }
-      }
-      if (library_node != NULL && library_node->IsLibrary()) {
-        kernel::Library* library = kernel::Library::Cast(library_node);
-        kernel_offset = node->kernel_offset();
-        kernel_data = library->kernel_data();
-        kernel_data_size = library->kernel_data_size();
-      }
-    }
-
-    kernel::StreamingScopeBuilder builder2(this, kernel_offset, kernel_data,
-                                           kernel_data_size);
-    kernel_scopes_ = builder2.BuildScopes();
+    intptr_t kernel_offset = function().kernel_offset();
+    Script& script = Script::Handle(Z, function().script());
+    kernel::StreamingScopeBuilder builder(
+        this, kernel_offset, script.kernel_data(), script.kernel_data_size());
+    kernel_scopes_ = builder.BuildScopes();
   }
   return kernel_scopes_;
 }
@@ -1664,7 +1628,7 @@
     ASSERT(func.num_fixed_parameters() == 2);  // closure, value.
   } else if (!parent.IsGetterFunction() && !parent.IsImplicitGetterFunction()) {
     // NOTE: For the `kernel -> flowgraph` we don't use the parser.
-    if (parent.kernel_function() == NULL) {
+    if (parent.kernel_offset() <= 0) {
       SkipFunctionPreamble();
       const bool use_function_type_syntax = false;
       const bool allow_explicit_default_values = true;
diff --git a/runtime/vm/precompiler.cc b/runtime/vm/precompiler.cc
index 8b2ab13..a4297ba 100644
--- a/runtime/vm/precompiler.cc
+++ b/runtime/vm/precompiler.cc
@@ -1221,7 +1221,7 @@
 
   ParsedFunction* parsed_function;
   // Check if this field is coming from the Kernel binary.
-  if (field.kernel_field() != NULL) {
+  if (field.kernel_offset() > 0) {
     parsed_function = kernel::ParseStaticFieldInitializer(zone, field);
   } else {
     parsed_function = Parser::ParseStaticFieldInitializer(field);
diff --git a/runtime/vm/precompiler.h b/runtime/vm/precompiler.h
index dec16dc..07dfed2 100644
--- a/runtime/vm/precompiler.h
+++ b/runtime/vm/precompiler.h
@@ -108,8 +108,8 @@
   static inline intptr_t Hashcode(Key key) {
     // We are using pointer hash for objects originating from Kernel because
     // Fasta currently does not assign any position information to them.
-    if (key->kernel_function() != NULL) {
-      return SimplePointerHash(key->kernel_function());
+    if (key->kernel_offset() > 0) {
+      return key->kernel_offset();
     } else {
       return key->token_pos().value();
     }
@@ -137,8 +137,8 @@
   static inline intptr_t Hashcode(Key key) {
     // We are using pointer hash for objects originating from Kernel because
     // Fasta currently does not assign any position information to them.
-    if (key->kernel_field() != NULL) {
-      return SimplePointerHash(key->kernel_field());
+    if (key->kernel_offset() > 0) {
+      return key->kernel_offset();
     } else {
       return key->token_pos().value();
     }
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index d9b73be..89e9999 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -893,7 +893,7 @@
   uint32_t kind_tag_;                          // See Function::KindTagBits.
   int16_t num_fixed_parameters_;
   int16_t num_optional_parameters_;  // > 0: positional; < 0: named.
-  NOT_IN_PRECOMPILED(void* kernel_function_);
+  NOT_IN_PRECOMPILED(intptr_t kernel_offset_);
   NOT_IN_PRECOMPILED(uint16_t optimized_instruction_count_);
   NOT_IN_PRECOMPILED(uint16_t optimized_call_site_count_);
   NOT_IN_PRECOMPILED(int8_t deoptimization_counter_);
@@ -1005,7 +1005,7 @@
   int8_t guarded_list_length_in_object_offset_;
 
   uint8_t kind_bits_;  // static, final, const, has initializer....
-  NOT_IN_PRECOMPILED(void* kernel_field_);
+  NOT_IN_PRECOMPILED(intptr_t kernel_offset_);
 
   friend class CidRewriteVisitor;
 };
@@ -1087,6 +1087,8 @@
   int32_t col_offset_;
   int8_t kind_;  // Of type Kind.
   int64_t load_timestamp_;
+  const uint8_t* kernel_data_;
+  intptr_t kernel_data_size_;
 };
 
 
diff --git a/runtime/vm/raw_object_snapshot.cc b/runtime/vm/raw_object_snapshot.cc
index c610431..6317a72 100644
--- a/runtime/vm/raw_object_snapshot.cc
+++ b/runtime/vm/raw_object_snapshot.cc
@@ -757,7 +757,7 @@
     func.set_deoptimization_counter(reader->Read<int8_t>());
     func.set_optimized_instruction_count(reader->Read<uint16_t>());
     func.set_optimized_call_site_count(reader->Read<uint16_t>());
-    func.set_kernel_function(NULL);
+    func.set_kernel_offset(0);
     func.set_was_compiled(false);
 
     // Set all the object fields.
@@ -863,7 +863,7 @@
   field.set_guarded_cid(reader->Read<int32_t>());
   field.set_is_nullable(reader->Read<int32_t>());
   field.set_kind_bits(reader->Read<uint8_t>());
-  field.set_kernel_field(NULL);
+  field.set_kernel_offset(0);
 
   // Set all the object fields.
   READ_OBJECT_FIELDS(field, field.raw()->from(), field.raw()->to_snapshot(kind),