Version 1.0.0.6

svn merge -c 30233 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 30234 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 30250 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 30308 https://dart.googlecode.com/svn/branches/bleeding_edge trunk

Cherry picked multivm blink revision 1608 to the blink stable branch in revision 1609  and updated dartium blink deps to point to that.

R=iposva@google.com

Review URL: https://codereview.chromium.org//75123002

git-svn-id: http://dart.googlecode.com/svn/trunk@30334 260f80e4-7a28-3924-810f-c04153c831b5
diff --git a/runtime/lib/mirrors.cc b/runtime/lib/mirrors.cc
index 22b2d47..483f5c6 100644
--- a/runtime/lib/mirrors.cc
+++ b/runtime/lib/mirrors.cc
@@ -51,7 +51,7 @@
   if (FLAG_use_mirrored_compilation_error && error.IsLanguageError()) {
     // A compilation error that was delayed by lazy compilation.
     const LanguageError& compilation_error = LanguageError::Cast(error);
-    String& message = String::Handle(compilation_error.message());
+    String& message = String::Handle(compilation_error.FormatMessage());
     ThrowMirroredCompilationError(message);
     UNREACHABLE();
   }
diff --git a/runtime/vm/class_finalizer.cc b/runtime/vm/class_finalizer.cc
index 1113f5e..170f508 100644
--- a/runtime/vm/class_finalizer.cc
+++ b/runtime/vm/class_finalizer.cc
@@ -4,12 +4,12 @@
 
 #include "vm/class_finalizer.h"
 
+#include "vm/code_generator.h"
 #include "vm/flags.h"
 #include "vm/heap.h"
 #include "vm/isolate.h"
 #include "vm/longjump.h"
 #include "vm/object_store.h"
-#include "vm/parser.h"
 #include "vm/symbols.h"
 
 namespace dart {
@@ -2623,14 +2623,11 @@
                                          const Type& type,
                                          const char* format,
                                          va_list args) {
-  LanguageError& error = LanguageError::Handle();
-  if (prev_error.IsNull()) {
-    error ^= Parser::FormatError(
-        script, type.token_pos(), "Error", format, args);
-  } else {
-    error ^= Parser::FormatErrorWithAppend(
-        prev_error, script, type.token_pos(), "Error", format, args);
-  }
+  LanguageError& error = LanguageError::Handle(
+      LanguageError::NewFormattedV(
+          prev_error, script, type.token_pos(),
+          LanguageError::kMalformedType, Heap::kOld,
+          format, args));
   if (FLAG_error_on_bad_type) {
     ReportError(error);
   }
@@ -2693,13 +2690,11 @@
                                  const char* format, ...) {
   va_list args;
   va_start(args, format);
-  Error& error = Error::Handle();
-  if (prev_error.IsNull()) {
-    error ^= Parser::FormatError(script, token_pos, "Error", format, args);
-  } else {
-    error ^= Parser::FormatErrorWithAppend(
-        prev_error, script, token_pos, "Error", format, args);
-  }
+  Error& error = Error::Handle(
+      LanguageError::NewFormattedV(
+          prev_error, script, token_pos,
+          LanguageError::kError, Heap::kNew,
+          format, args));
   va_end(args);
   ReportError(error);
 }
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index f22df2c..5e9a5f3 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -2955,6 +2955,21 @@
   }
   const Class& cls = Class::Handle(isolate, type_obj.type_class());
 
+  // Mark all fields as nullable.
+  Class& iterate_cls = Class::Handle(isolate, cls.raw());
+  Field& field = Field::Handle(isolate);
+  Array& fields = Array::Handle(isolate);
+  while (!iterate_cls.IsNull()) {
+    fields = iterate_cls.fields();
+    iterate_cls = iterate_cls.SuperClass();
+    for (int field_num = 0; field_num < fields.Length(); field_num++) {
+      field ^= fields.At(field_num);
+      if (field.is_static()) {
+        continue;
+      }
+      field.UpdateGuardedCidAndLength(Object::null_object());
+    }
+  }
   // Allocate an object for the given class.
   return Api::NewHandle(isolate, Instance::New(cls));
 }
diff --git a/runtime/vm/flow_graph.cc b/runtime/vm/flow_graph.cc
index d942747..ff6be53 100644
--- a/runtime/vm/flow_graph.cc
+++ b/runtime/vm/flow_graph.cc
@@ -1067,13 +1067,16 @@
 
 
 void FlowGraph::Bailout(const char* reason) const {
-  const char* kFormat = "FlowGraph Bailout: %s %s";
-  const char* function_name = parsed_function_.function().ToCString();
-  intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1;
-  char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
-  OS::SNPrint(chars, len, kFormat, function_name, reason);
+  const Function& function = parsed_function_.function();
   const Error& error = Error::Handle(
-      LanguageError::New(String::Handle(String::New(chars))));
+      LanguageError::NewFormatted(Error::Handle(),  // No previous error.
+                                  Script::Handle(function.script()),
+                                  function.token_pos(),
+                                  LanguageError::kError,
+                                  Heap::kNew,
+                                  "FlowGraph Bailout: %s %s",
+                                  String::Handle(function.name()).ToCString(),
+                                  reason));
   Isolate::Current()->long_jump_base()->Jump(1, error);
 }
 
diff --git a/runtime/vm/flow_graph_builder.cc b/runtime/vm/flow_graph_builder.cc
index b231788..d4469cd 100644
--- a/runtime/vm/flow_graph_builder.cc
+++ b/runtime/vm/flow_graph_builder.cc
@@ -3853,13 +3853,16 @@
 
 
 void FlowGraphBuilder::Bailout(const char* reason) {
-  const char* kFormat = "FlowGraphBuilder Bailout: %s %s";
-  const char* function_name = parsed_function_->function().ToCString();
-  intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1;
-  char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
-  OS::SNPrint(chars, len, kFormat, function_name, reason);
+  const Function& function = parsed_function_->function();
   const Error& error = Error::Handle(
-      LanguageError::New(String::Handle(String::New(chars))));
+      LanguageError::NewFormatted(Error::Handle(),  // No previous error.
+                                  Script::Handle(function.script()),
+                                  function.token_pos(),
+                                  LanguageError::kError,
+                                  Heap::kNew,
+                                  "FlowGraphBuilder Bailout: %s %s",
+                                  String::Handle(function.name()).ToCString(),
+                                  reason));
   Isolate::Current()->long_jump_base()->Jump(1, error);
 }
 
diff --git a/runtime/vm/flow_graph_compiler.cc b/runtime/vm/flow_graph_compiler.cc
index a7affc9..6eeba1a 100644
--- a/runtime/vm/flow_graph_compiler.cc
+++ b/runtime/vm/flow_graph_compiler.cc
@@ -285,13 +285,16 @@
 
 
 void FlowGraphCompiler::Bailout(const char* reason) {
-  const char* kFormat = "FlowGraphCompiler Bailout: %s %s.";
-  const char* function_name = parsed_function().function().ToCString();
-  intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1;
-  char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
-  OS::SNPrint(chars, len, kFormat, function_name, reason);
+  const Function& function = parsed_function_.function();
   const Error& error = Error::Handle(
-      LanguageError::New(String::Handle(String::New(chars))));
+      LanguageError::NewFormatted(Error::Handle(),  // No previous error.
+                                  Script::Handle(function.script()),
+                                  function.token_pos(),
+                                  LanguageError::kError,
+                                  Heap::kNew,
+                                  "FlowGraphCompiler Bailout: %s %s",
+                                  String::Handle(function.name()).ToCString(),
+                                  reason));
   Isolate::Current()->long_jump_base()->Jump(1, error);
 }
 
diff --git a/runtime/vm/intermediate_language.h b/runtime/vm/intermediate_language.h
index ea91a10..0ebdeab 100644
--- a/runtime/vm/intermediate_language.h
+++ b/runtime/vm/intermediate_language.h
@@ -4520,6 +4520,10 @@
 
   virtual bool CanDeoptimize() const { return false; }
 
+  virtual intptr_t DeoptimizationTarget() const {
+    return Isolate::kNoDeoptId;
+  }
+
   virtual Representation RequiredInputRepresentation(intptr_t idx) const {
     ASSERT(idx == 0);
     return kUnboxedDouble;
@@ -4549,6 +4553,10 @@
 
   virtual bool CanDeoptimize() const { return false; }
 
+  virtual intptr_t DeoptimizationTarget() const {
+    return Isolate::kNoDeoptId;
+  }
+
   virtual Representation RequiredInputRepresentation(intptr_t idx) const {
     ASSERT(idx == 0);
     return kUnboxedFloat32x4;
@@ -4581,6 +4589,10 @@
 
   virtual bool CanDeoptimize() const { return false; }
 
+  virtual intptr_t DeoptimizationTarget() const {
+    return Isolate::kNoDeoptId;
+  }
+
   virtual Representation RequiredInputRepresentation(intptr_t idx) const {
     ASSERT(idx == 0);
     return kUnboxedInt32x4;
@@ -4613,6 +4625,10 @@
 
   virtual bool CanDeoptimize() const { return false; }
 
+  virtual intptr_t DeoptimizationTarget() const {
+    return Isolate::kNoDeoptId;
+  }
+
   virtual Representation RequiredInputRepresentation(intptr_t idx) const {
     ASSERT(idx == 0);
     return kUnboxedMint;
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 8ba182a..139e0ca 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -1680,28 +1680,18 @@
 }
 
 
-static RawError* FormatError(const Error& prev_error,
-                             const Script& script,
-                             intptr_t token_pos,
-                             const char* format, ...) {
-  va_list args;
-  va_start(args, format);
-  if (prev_error.IsNull()) {
-    return Parser::FormatError(script, token_pos, "Error", format, args);
-  } else {
-    return Parser::FormatErrorWithAppend(prev_error, script, token_pos,
-                                         "Error", format, args);
-  }
-}
-
 
 static void ReportTooManyTypeArguments(const Class& cls) {
   const Error& error = Error::Handle(
-      FormatError(Error::Handle(),  // No previous error.
-                  Script::Handle(cls.script()), cls.token_pos(),
-                  "too many type parameters declared in class '%s' or in its "
-                  "super classes",
-                  String::Handle(cls.Name()).ToCString()));
+      LanguageError::NewFormatted(
+          Error::Handle(),  // No previous error.
+          Script::Handle(cls.script()),
+          cls.token_pos(),
+          LanguageError::kError,
+          Heap::kNew,
+          "too many type parameters declared in class '%s' or in its "
+          "super classes",
+          String::Handle(cls.Name()).ToCString()));
   Isolate::Current()->long_jump_base()->Jump(1, error);
   UNREACHABLE();
 }
@@ -2238,9 +2228,13 @@
                orig_func.UserVisibleSignature()) {
       // Compare user visible signatures to ignore different implicit parameters
       // when patching a constructor with a factory.
-      *error = FormatError(*error,  // No previous error.
-                           Script::Handle(patch.script()), func.token_pos(),
-                           "signature mismatch: '%s'", member_name.ToCString());
+      *error = LanguageError::NewFormatted(
+          *error,  // No previous error.
+          Script::Handle(patch.script()),
+          func.token_pos(),
+          LanguageError::kError,
+          Heap::kNew,
+          "signature mismatch: '%s'", member_name.ToCString());
       return false;
     }
   }
@@ -2279,9 +2273,13 @@
     // Verify no duplicate additions.
     orig_field ^= LookupField(member_name);
     if (!orig_field.IsNull()) {
-      *error = FormatError(*error,  // No previous error.
-                           Script::Handle(patch.script()), field.token_pos(),
-                           "duplicate field: %s", member_name.ToCString());
+      *error = LanguageError::NewFormatted(
+          *error,  // No previous error.
+          Script::Handle(patch.script()),
+          field.token_pos(),
+          LanguageError::kError,
+          Heap::kNew,
+          "duplicate field: %s", member_name.ToCString());
       return false;
     }
     new_list.SetAt(i, field);
@@ -2843,9 +2841,11 @@
     for (intptr_t i = 0; i < interfaces.Length(); i++) {
       interface ^= interfaces.At(i);
       if (!interface.IsFinalized()) {
-        // We may be checking bounds at finalization time. Skipping this
-        // unfinalized interface will postpone bound checking to run time.
-        continue;
+        // We may be checking bounds at finalization time and can encounter
+        // a still unfinalized interface.
+        ClassFinalizer::FinalizeType(
+            thsi, interface, ClassFinalizer::kCanonicalize);
+        interfaces.SetAt(i, interface);
       }
       error = Error::null();
       if (interface.IsMalboundedWithError(&error)) {
@@ -4846,10 +4846,12 @@
                 other, Object::null_abstract_type_arguments(), bound_error)) {
     // For more informative error reporting, use the location of the other
     // function here, since the caller will use the location of this function.
-    *bound_error = FormatError(
+    *bound_error = LanguageError::NewFormatted(
         *bound_error,  // A bound error if non null.
         Script::Handle(other.script()),
         other.token_pos(),
+        LanguageError::kError,
+        Heap::kNew,
         "signature type '%s' of function '%s' is not a subtype of signature "
         "type '%s' of function '%s'",
         String::Handle(UserVisibleSignature()).ToCString(),
@@ -10662,7 +10664,13 @@
 }
 
 
-RawLanguageError* LanguageError::New(const String& message, Heap::Space space) {
+RawLanguageError* LanguageError::NewFormattedV(const Error& prev_error,
+                                               const Script& script,
+                                               intptr_t token_pos,
+                                               Kind kind,
+                                               Heap::Space space,
+                                               const char* format,
+                                               va_list args) {
   ASSERT(Object::language_error_class() != Class::null());
   LanguageError& result = LanguageError::Handle();
   {
@@ -10672,18 +10680,151 @@
     NoGCScope no_gc;
     result ^= raw;
   }
-  result.set_message(message);
+  result.set_previous_error(prev_error);
+  result.set_script(script);
+  result.set_token_pos(token_pos);
+  result.set_kind(kind);
+  result.set_message(String::Handle(String::NewFormattedV(format, args)));
   return result.raw();
 }
 
 
-void LanguageError::set_message(const String& message) const {
-  StorePointer(&raw_ptr()->message_, message.raw());
+RawLanguageError* LanguageError::NewFormatted(const Error& prev_error,
+                                              const Script& script,
+                                              intptr_t token_pos,
+                                              Kind kind,
+                                              Heap::Space space,
+                                              const char* format, ...) {
+  va_list args;
+  va_start(args, format);
+  RawLanguageError* result = LanguageError::NewFormattedV(
+      prev_error, script, token_pos, kind, space, format, args);
+  NoGCScope no_gc;
+  va_end(args);
+  return result;
+}
+
+
+RawLanguageError* LanguageError::New(const String& formatted_message,
+                                     Heap::Space space) {
+  ASSERT(Object::language_error_class() != Class::null());
+  LanguageError& result = LanguageError::Handle();
+  {
+    RawObject* raw = Object::Allocate(LanguageError::kClassId,
+                                      LanguageError::InstanceSize(),
+                                      space);
+    NoGCScope no_gc;
+    result ^= raw;
+  }
+  result.set_formatted_message(formatted_message);
+  return result.raw();
+}
+
+
+void LanguageError::set_previous_error(const Error& value) const {
+  StorePointer(&raw_ptr()->previous_error_, value.raw());
+}
+
+
+void LanguageError::set_script(const Script& value) const {
+  StorePointer(&raw_ptr()->script_, value.raw());
+}
+
+
+void LanguageError::set_token_pos(intptr_t value) const {
+  ASSERT(value >= 0);
+  raw_ptr()->token_pos_ = value;
+}
+
+
+void LanguageError::set_kind(uint8_t value) const {
+  raw_ptr()->kind_ = value;
+}
+
+
+void LanguageError::set_message(const String& value) const {
+  StorePointer(&raw_ptr()->message_, value.raw());
+}
+
+
+void LanguageError::set_formatted_message(const String& value) const {
+  StorePointer(&raw_ptr()->formatted_message_, value.raw());
+}
+
+
+RawString* LanguageError::FormatMessage() const {
+  if (formatted_message() != String::null()) {
+    return formatted_message();
+  }
+  const char* message_header;
+  switch (kind()) {
+    case kWarning: message_header = "warning"; break;
+    case kError: message_header = "error"; break;
+    case kMalformedType: message_header = "malformed type"; break;
+    case kMalboundedType: message_header = "malbounded type"; break;
+    default: message_header = ""; UNREACHABLE();
+  }
+  String& result = String::Handle();
+  String& msg = String::Handle(message());
+  const Script& scr = Script::Handle(script());
+  if (!scr.IsNull()) {
+    const String& script_url = String::Handle(scr.url());
+    if (token_pos() >= 0) {
+      intptr_t line, column;
+      scr.GetTokenLocation(token_pos(), &line, &column);
+      // Only report the line position if we have the original source. We still
+      // need to get a valid column so that we can report the ^ mark below the
+      // snippet.
+      if (scr.HasSource()) {
+        result = String::NewFormatted("'%s': %s: line %" Pd " pos %" Pd ": ",
+                                      script_url.ToCString(),
+                                      message_header,
+                                      line,
+                                      column);
+      } else {
+        result = String::NewFormatted("'%s': %s: line %" Pd ": ",
+                                      script_url.ToCString(),
+                                      message_header,
+                                      line);
+      }
+      // Append the formatted error or warning message.
+      result = String::Concat(result, msg);
+      // Append the source line.
+      const String& script_line = String::Handle(scr.GetLine(line));
+      ASSERT(!script_line.IsNull());
+      result = String::Concat(result, Symbols::NewLine());
+      result = String::Concat(result, script_line);
+      result = String::Concat(result, Symbols::NewLine());
+      // Append the column marker.
+      const String& column_line = String::Handle(
+          String::NewFormatted("%*s\n", static_cast<int>(column), "^"));
+      result = String::Concat(result, column_line);
+    } else {
+      // Token position is unknown.
+      result = String::NewFormatted("'%s': %s: ",
+                                    script_url.ToCString(),
+                                    message_header);
+      result = String::Concat(result, msg);
+    }
+  } else {
+    // Script is unknown.
+    // Append the formatted error or warning message.
+    result = String::NewFormatted("%s: ", message_header);
+    result = String::Concat(result, msg);
+  }
+  // Prepend previous error message.
+  const Error& prev_error = Error::Handle(previous_error());
+  if (!prev_error.IsNull()) {
+    msg = String::New(prev_error.ToErrorCString());
+    result = String::Concat(msg, result);
+  }
+  set_formatted_message(result);
+  return result.raw();
 }
 
 
 const char* LanguageError::ToErrorCString() const {
-  const String& msg_str = String::Handle(message());
+  const String& msg_str = String::Handle(FormatMessage());
   return msg_str.ToCString();
 }
 
@@ -12112,10 +12253,12 @@
     const Script& script = Script::Handle(cls.script());
     // Since the bound may have been canonicalized, its token index is
     // meaningless, therefore use the token index of this type parameter.
-    *bound_error = FormatError(
+    *bound_error = LanguageError::NewFormatted(
         *bound_error,
         script,
         token_pos(),
+        LanguageError::kMalboundedType,
+        Heap::kNew,
         "type parameter '%s' of class '%s' must extend bound '%s', "
         "but type argument '%s' is not a subtype of '%s'\n",
         type_param_name.ToCString(),
@@ -12370,19 +12513,28 @@
 
 
 const char* BoundedType::ToCString() const {
-  const char* format = "BoundedType: type %s; bound: %s; class: %s";
+  const char* format = "BoundedType: type %s; bound: %s; type param: %s%s%s";
   const char* type_cstr = String::Handle(AbstractType::Handle(
       type()).Name()).ToCString();
   const char* bound_cstr = String::Handle(AbstractType::Handle(
       bound()).Name()).ToCString();
-  const Class& cls = Class::Handle(TypeParameter::Handle(
-      type_parameter()).parameterized_class());
-  const char* cls_cstr =
-      cls.IsNull() ? " null" : String::Handle(cls.Name()).ToCString();
-  intptr_t len = OS::SNPrint(
-      NULL, 0, format, type_cstr, bound_cstr, cls_cstr) + 1;
+  const TypeParameter& type_param = TypeParameter::Handle(type_parameter());
+  const char* type_param_cstr = "null";
+  const char* of_cstr = "";
+  const char* cls_cstr = "";
+  if (!type_param.IsNull()) {
+    type_param_cstr = String::Handle(type_param.name()).ToCString();
+    const Class& cls = Class::Handle(type_param.parameterized_class());
+    if (!cls.IsNull()) {
+      of_cstr = " of ";
+      cls_cstr = String::Handle(cls.Name()).ToCString();
+    }
+  }
+  intptr_t len = OS::SNPrint(NULL, 0, format, type_cstr, bound_cstr,
+                             type_param_cstr, of_cstr, cls_cstr) + 1;
   char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
-  OS::SNPrint(chars, len, format, type_cstr, bound_cstr, cls_cstr);
+  OS::SNPrint(chars, len, format, type_cstr, bound_cstr, type_param_cstr,
+              of_cstr, cls_cstr);
   return chars;
 }
 
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 2b48af2..d6ac20b 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -3757,9 +3757,6 @@
 class ApiError : public Error {
  public:
   RawString* message() const { return raw_ptr()->message_; }
-  static intptr_t message_offset() {
-    return OFFSET_OF(RawApiError, message_);
-  }
 
   static intptr_t InstanceSize() {
     return RoundedAllocationSize(sizeof(RawApiError));
@@ -3782,22 +3779,61 @@
 
 class LanguageError : public Error {
  public:
-  RawString* message() const { return raw_ptr()->message_; }
-  static intptr_t message_offset() {
-    return OFFSET_OF(RawLanguageError, message_);
-  }
+  enum Kind {
+    kWarning,
+    kError,
+    kMalformedType,
+    kMalboundedType,
+  };
+
+  // Build, cache, and return formatted message.
+  RawString* FormatMessage() const;
 
   static intptr_t InstanceSize() {
     return RoundedAllocationSize(sizeof(RawLanguageError));
   }
 
-  static RawLanguageError* New(const String& message,
+  // A null script means no source and a negative token_pos means no position.
+  static RawLanguageError* NewFormatted(const Error& prev_error,
+                                        const Script& script,
+                                        intptr_t token_pos,
+                                        Kind kind,
+                                        Heap::Space space,
+                                        const char* format, ...)
+    PRINTF_ATTRIBUTE(6, 7);
+
+  static RawLanguageError* NewFormattedV(const Error& prev_error,
+                                         const Script& script,
+                                         intptr_t token_pos,
+                                         Kind kind,
+                                         Heap::Space space,
+                                         const char* format, va_list args);
+
+  static RawLanguageError* New(const String& formatted_message,
                                Heap::Space space = Heap::kNew);
 
   virtual const char* ToErrorCString() const;
 
  private:
-  void set_message(const String& message) const;
+  RawError* previous_error() const {
+    return raw_ptr()->previous_error_;
+  }
+  void set_previous_error(const Error& value) const;
+
+  RawScript* script() const { return raw_ptr()->script_; }
+  void set_script(const Script& value) const;
+
+  intptr_t token_pos() const { return raw_ptr()->token_pos_; }
+  void set_token_pos(intptr_t value) const;
+
+  Kind kind() const { return static_cast<Kind>(raw_ptr()->kind_); }
+  void set_kind(uint8_t value) const;
+
+  RawString* message() const { return raw_ptr()->message_; }
+  void set_message(const String& value) const;
+
+  RawString* formatted_message() const { return raw_ptr()->formatted_message_; }
+  void set_formatted_message(const String& value) const;
 
   static RawLanguageError* New();
 
@@ -3840,9 +3876,6 @@
 class UnwindError : public Error {
  public:
   RawString* message() const { return raw_ptr()->message_; }
-  static intptr_t message_offset() {
-    return OFFSET_OF(RawUnwindError, message_);
-  }
 
   static intptr_t InstanceSize() {
     return RoundedAllocationSize(sizeof(RawUnwindError));
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc
index 0fff78e..4fc43e0 100644
--- a/runtime/vm/parser.cc
+++ b/runtime/vm/parser.cc
@@ -5251,8 +5251,10 @@
   if (!Utils::IsInt(16, params->num_fixed_parameters) ||
       !Utils::IsInt(16, params->num_optional_parameters)) {
     const Script& script = Script::Handle(Class::Handle(func.Owner()).script());
-    const Error& error = Error::Handle(FormatErrorMsg(
-        script, func.token_pos(), "Error", "too many formal parameters"));
+    const Error& error = Error::Handle(LanguageError::NewFormatted(
+        Error::Handle(), script, func.token_pos(),
+        LanguageError::kError, Heap::kNew,
+        "too many formal parameters"));
     ErrorMsg(error);
   }
   func.set_num_fixed_parameters(params->num_fixed_parameters);
@@ -7226,116 +7228,12 @@
 }
 
 
-RawError* Parser::FormatErrorWithAppend(const Error& prev_error,
-                                        const Script& script,
-                                        intptr_t token_pos,
-                                        const char* message_header,
-                                        const char* format,
-                                        va_list args) {
-  const String& msg1 = String::Handle(String::New(prev_error.ToErrorCString()));
-  const String& msg2 = String::Handle(
-      FormatMessage(script, token_pos, message_header, format, args));
-  return LanguageError::New(String::Handle(String::Concat(msg1, msg2)));
-}
-
-
-RawError* Parser::FormatError(const Script& script,
-                              intptr_t token_pos,
-                              const char* message_header,
-                              const char* format,
-                              va_list args) {
-  const String& msg = String::Handle(
-      FormatMessage(script, token_pos, message_header, format, args));
-  return LanguageError::New(msg);
-}
-
-
-RawError* Parser::FormatErrorMsg(const Script& script,
-                                 intptr_t token_pos,
-                                 const char* message_header,
-                                 const char* format, ...) {
-  va_list args;
-  va_start(args, format);
-  const Error& error = Error::Handle(
-      FormatError(script, token_pos, message_header, format, args));
-  va_end(args);
-  return error.raw();
-}
-
-
-RawString* Parser::FormatMessage(const Script& script,
-                                 intptr_t token_pos,
-                                 const char* message_header,
-                                 const char* format, va_list args) {
-  String& result = String::Handle();
-  const String& msg = String::Handle(String::NewFormattedV(format, args));
-  if (!script.IsNull()) {
-    const String& script_url = String::Handle(script.url());
-    if (token_pos >= 0) {
-      intptr_t line, column;
-      script.GetTokenLocation(token_pos, &line, &column);
-      // Only report the line position if we have the original source. We still
-      // need to get a valid column so that we can report the ^ mark below the
-      // snippet.
-      if (script.HasSource()) {
-        result = String::NewFormatted("'%s': %s: line %" Pd " pos %" Pd ": ",
-                                      script_url.ToCString(),
-                                      message_header,
-                                      line,
-                                      column);
-      } else {
-        result = String::NewFormatted("'%s': %s: line %" Pd ": ",
-                                      script_url.ToCString(),
-                                      message_header,
-                                      line);
-      }
-      // Append the formatted error or warning message.
-      result = String::Concat(result, msg);
-      const String& new_line = String::Handle(String::New("\n"));
-      // Append the source line.
-      const String& script_line = String::Handle(script.GetLine(line));
-      ASSERT(!script_line.IsNull());
-      result = String::Concat(result, new_line);
-      result = String::Concat(result, script_line);
-      result = String::Concat(result, new_line);
-      // Append the column marker.
-      const String& column_line = String::Handle(
-          String::NewFormatted("%*s\n", static_cast<int>(column), "^"));
-      result = String::Concat(result, column_line);
-    } else {
-      // Token position is unknown.
-      result = String::NewFormatted("'%s': %s: ",
-                                    script_url.ToCString(),
-                                    message_header);
-      result = String::Concat(result, msg);
-    }
-  } else {
-    // Script is unknown.
-    // Append the formatted error or warning message.
-    result = msg.raw();
-  }
-  return result.raw();
-}
-
-
-void Parser::PrintMessage(const Script& script,
-                          intptr_t token_pos,
-                          const char* message_header,
-                          const char* format, ...) {
-  va_list args;
-  va_start(args, format);
-  const String& buf = String::Handle(
-      FormatMessage(script, token_pos, message_header, format, args));
-  va_end(args);
-  OS::Print("%s", buf.ToCString());
-}
-
-
 void Parser::ErrorMsg(intptr_t token_pos, const char* format, ...) const {
   va_list args;
   va_start(args, format);
-  const Error& error = Error::Handle(
-      FormatError(script_, token_pos, "Error", format, args));
+  const Error& error = Error::Handle(LanguageError::NewFormattedV(
+      Error::Handle(), script_, token_pos,
+      LanguageError::kError, Heap::kNew, format, args));
   va_end(args);
   isolate()->long_jump_base()->Jump(1, error);
   UNREACHABLE();
@@ -7345,8 +7243,9 @@
 void Parser::ErrorMsg(const char* format, ...) {
   va_list args;
   va_start(args, format);
-  const Error& error = Error::Handle(
-      FormatError(script_, TokenPos(), "Error", format, args));
+  const Error& error = Error::Handle(LanguageError::NewFormattedV(
+      Error::Handle(), script_, TokenPos(),
+      LanguageError::kError, Heap::kNew, format, args));
   va_end(args);
   isolate()->long_jump_base()->Jump(1, error);
   UNREACHABLE();
@@ -7363,8 +7262,11 @@
       const Error& prev_error, intptr_t token_pos, const char* format, ...) {
   va_list args;
   va_start(args, format);
-  const Error& error = Error::Handle(FormatErrorWithAppend(
-      prev_error, script_, token_pos, "Error", format, args));
+  const Error& error = Error::Handle(
+      LanguageError::NewFormattedV(
+          prev_error, script_, token_pos,
+          LanguageError::kError, Heap::kNew,
+          format, args));
   va_end(args);
   isolate()->long_jump_base()->Jump(1, error);
   UNREACHABLE();
@@ -7376,7 +7278,10 @@
   va_list args;
   va_start(args, format);
   const Error& error = Error::Handle(
-      FormatError(script_, token_pos, "Warning", format, args));
+      LanguageError::NewFormattedV(
+          Error::Handle(), script_, token_pos,
+          LanguageError::kWarning, Heap::kNew,
+          format, args));
   va_end(args);
   if (FLAG_warning_as_error) {
     isolate()->long_jump_base()->Jump(1, error);
@@ -7392,7 +7297,10 @@
   va_list args;
   va_start(args, format);
   const Error& error = Error::Handle(
-      FormatError(script_, TokenPos(), "Warning", format, args));
+      LanguageError::NewFormattedV(
+          Error::Handle(), script_, TokenPos(),
+          LanguageError::kWarning, Heap::kNew,
+          format, args));
   va_end(args);
   if (FLAG_warning_as_error) {
     isolate()->long_jump_base()->Jump(1, error);
diff --git a/runtime/vm/parser.h b/runtime/vm/parser.h
index 41798e3..7b82f6b 100644
--- a/runtime/vm/parser.h
+++ b/runtime/vm/parser.h
@@ -159,34 +159,6 @@
   };
   static RawObject* ParseFunctionParameters(const Function& func);
 
-  // Format and print a message with source location.
-  // A null script means no source and a negative token_pos means no position.
-  static void PrintMessage(const Script& script,
-                           intptr_t token_pos,
-                           const char* message_header,
-                           const char* format, ...) PRINTF_ATTRIBUTE(4, 5);
-
-  // Build an error object containing a formatted error or warning message.
-  // A null script means no source and a negative token_pos means no position.
-  static RawError* FormatError(const Script& script,
-                               intptr_t token_pos,
-                               const char* message_header,
-                               const char* format,
-                               va_list args);
-  static RawError* FormatErrorMsg(const Script& script,
-                                  intptr_t token_pos,
-                                  const char* message_header,
-                                  const char* format, ...)
-      PRINTF_ATTRIBUTE(4, 5);
-
-  // Same as FormatError, but appends the new error to the 'prev_error'.
-  static RawError* FormatErrorWithAppend(const Error& prev_error,
-                                         const Script& script,
-                                         intptr_t token_pos,
-                                         const char* message_header,
-                                         const char* format,
-                                         va_list args);
-
  private:
   friend class EffectGraphVisitor;  // For BuildNoSuchMethodArguments.
 
@@ -312,7 +284,7 @@
   // A null script means no source and a negative token_pos means no position.
   static RawString* FormatMessage(const Script& script,
                                   intptr_t token_pos,
-                                  const char* message_header,
+                                  LanguageError::Kind kind,
                                   const char* format,
                                   va_list args);
 
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index 0d17902..31cd343 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -1092,12 +1092,17 @@
   RAW_HEAP_OBJECT_IMPLEMENTATION(LanguageError);
 
   RawObject** from() {
-    return reinterpret_cast<RawObject**>(&ptr()->message_);
+    return reinterpret_cast<RawObject**>(&ptr()->previous_error_);
   }
+  RawError* previous_error_;  // May be null.
+  RawScript* script_;
   RawString* message_;
+  RawString* formatted_message_;  // Incl. previous error's formatted message.
   RawObject** to() {
-    return reinterpret_cast<RawObject**>(&ptr()->message_);
+    return reinterpret_cast<RawObject**>(&ptr()->formatted_message_);
   }
+  intptr_t token_pos_;  // Source position in script_.
+  int8_t kind_;  // Of type LanguageError::Kind.
 };
 
 
diff --git a/runtime/vm/raw_object_snapshot.cc b/runtime/vm/raw_object_snapshot.cc
index db525ec..e8874af 100644
--- a/runtime/vm/raw_object_snapshot.cc
+++ b/runtime/vm/raw_object_snapshot.cc
@@ -1563,6 +1563,10 @@
   // Set the object tags.
   language_error.set_tags(tags);
 
+  // Set all non object fields.
+  language_error.set_token_pos(reader->ReadIntptrValue());
+  language_error.set_kind(reader->Read<uint8_t>());
+
   // Set all the object fields.
   // TODO(5411462): Need to assert No GC can happen here, even though
   // allocations may happen.
@@ -1590,6 +1594,10 @@
   writer->WriteVMIsolateObject(kLanguageErrorCid);
   writer->WriteIntptrValue(writer->GetObjectTags(this));
 
+  // Write out all the non object fields.
+  writer->WriteIntptrValue(ptr()->token_pos_);
+  writer->Write<uint8_t>(ptr()->kind_);
+
   // Write out all the object pointer fields.
   SnapshotWriterVisitor visitor(writer);
   visitor.VisitPointers(from(), to());
diff --git a/tools/VERSION b/tools/VERSION
index eb9f7be..ef4495b 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -1,4 +1,4 @@
 MAJOR 1
 MINOR 0
 BUILD 0
-PATCH 5
+PATCH 6