Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(43)

Side by Side Diff: runtime/vm/object.cc

Issue 68113028: Lazily format LanguageError messages (fix issue 15069). (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/object.h" 5 #include "vm/object.h"
6 6
7 #include "include/dart_api.h" 7 #include "include/dart_api.h"
8 #include "platform/assert.h" 8 #include "platform/assert.h"
9 #include "vm/assembler.h" 9 #include "vm/assembler.h"
10 #include "vm/cpu.h" 10 #include "vm/cpu.h"
(...skipping 1664 matching lines...) Expand 10 before | Expand all | Expand 10 after
1675 result.set_num_type_arguments(0); 1675 result.set_num_type_arguments(0);
1676 result.set_num_own_type_arguments(0); 1676 result.set_num_own_type_arguments(0);
1677 result.set_num_native_fields(0); 1677 result.set_num_native_fields(0);
1678 result.set_token_pos(Scanner::kDummyTokenIndex); 1678 result.set_token_pos(Scanner::kDummyTokenIndex);
1679 result.InitEmptyFields(); 1679 result.InitEmptyFields();
1680 Isolate::Current()->RegisterClass(result); 1680 Isolate::Current()->RegisterClass(result);
1681 return result.raw(); 1681 return result.raw();
1682 } 1682 }
1683 1683
1684 1684
1685 static RawError* FormatError(const Error& prev_error,
1686 const Script& script,
1687 intptr_t token_pos,
1688 const char* format, ...) {
1689 va_list args;
1690 va_start(args, format);
1691 if (prev_error.IsNull()) {
1692 return Parser::FormatError(script, token_pos, "Error", format, args);
1693 } else {
1694 return Parser::FormatErrorWithAppend(prev_error, script, token_pos,
1695 "Error", format, args);
1696 }
1697 }
1698
1699 1685
1700 static void ReportTooManyTypeArguments(const Class& cls) { 1686 static void ReportTooManyTypeArguments(const Class& cls) {
1701 const Error& error = Error::Handle( 1687 const Error& error = Error::Handle(
1702 FormatError(Error::Handle(), // No previous error. 1688 LanguageError::NewFormatted(
1703 Script::Handle(cls.script()), cls.token_pos(), 1689 Error::Handle(), // No previous error.
1704 "too many type parameters declared in class '%s' or in its " 1690 Script::Handle(cls.script()),
1705 "super classes", 1691 cls.token_pos(),
1706 String::Handle(cls.Name()).ToCString())); 1692 LanguageError::kError,
1693 Heap::kNew,
1694 "too many type parameters declared in class '%s' or in its "
1695 "super classes",
1696 String::Handle(cls.Name()).ToCString()));
1707 Isolate::Current()->long_jump_base()->Jump(1, error); 1697 Isolate::Current()->long_jump_base()->Jump(1, error);
1708 UNREACHABLE(); 1698 UNREACHABLE();
1709 } 1699 }
1710 1700
1711 1701
1712 void Class::set_num_type_arguments(intptr_t value) const { 1702 void Class::set_num_type_arguments(intptr_t value) const {
1713 if (!Utils::IsInt(16, value)) { 1703 if (!Utils::IsInt(16, value)) {
1714 ReportTooManyTypeArguments(*this); 1704 ReportTooManyTypeArguments(*this);
1715 } 1705 }
1716 raw_ptr()->num_type_arguments_ = value; 1706 raw_ptr()->num_type_arguments_ = value;
(...skipping 516 matching lines...) Expand 10 before | Expand all | Expand 10 after
2233 // the loop below. 2223 // the loop below.
2234 // However, an implicitly created constructor should not be preserved if 2224 // However, an implicitly created constructor should not be preserved if
2235 // the patch provides a constructor or a factory. Wait for now. 2225 // the patch provides a constructor or a factory. Wait for now.
2236 if (orig_func.raw() != orig_implicit_ctor.raw()) { 2226 if (orig_func.raw() != orig_implicit_ctor.raw()) {
2237 new_functions.Add(orig_func); 2227 new_functions.Add(orig_func);
2238 } 2228 }
2239 } else if (func.UserVisibleSignature() != 2229 } else if (func.UserVisibleSignature() !=
2240 orig_func.UserVisibleSignature()) { 2230 orig_func.UserVisibleSignature()) {
2241 // Compare user visible signatures to ignore different implicit parameters 2231 // Compare user visible signatures to ignore different implicit parameters
2242 // when patching a constructor with a factory. 2232 // when patching a constructor with a factory.
2243 *error = FormatError(*error, // No previous error. 2233 *error = LanguageError::NewFormatted(
2244 Script::Handle(patch.script()), func.token_pos(), 2234 *error, // No previous error.
2245 "signature mismatch: '%s'", member_name.ToCString()); 2235 Script::Handle(patch.script()),
2236 func.token_pos(),
2237 LanguageError::kError,
2238 Heap::kNew,
2239 "signature mismatch: '%s'", member_name.ToCString());
2246 return false; 2240 return false;
2247 } 2241 }
2248 } 2242 }
2249 for (intptr_t i = 0; i < patch_len; i++) { 2243 for (intptr_t i = 0; i < patch_len; i++) {
2250 func ^= patch_list.At(i); 2244 func ^= patch_list.At(i);
2251 if (func.IsConstructor() || func.IsFactory()) { 2245 if (func.IsConstructor() || func.IsFactory()) {
2252 // Do not preserve the original implicit constructor, if any. 2246 // Do not preserve the original implicit constructor, if any.
2253 orig_implicit_ctor = Function::null(); 2247 orig_implicit_ctor = Function::null();
2254 } 2248 }
2255 func.set_owner(patch_class); 2249 func.set_owner(patch_class);
(...skipping 18 matching lines...) Expand all
2274 new_list = Array::New(patch_len + orig_len); 2268 new_list = Array::New(patch_len + orig_len);
2275 for (intptr_t i = 0; i < patch_len; i++) { 2269 for (intptr_t i = 0; i < patch_len; i++) {
2276 field ^= patch_list.At(i); 2270 field ^= patch_list.At(i);
2277 field.set_owner(*this); 2271 field.set_owner(*this);
2278 member_name = field.name(); 2272 member_name = field.name();
2279 // TODO(iposva): Verify non-public fields only. 2273 // TODO(iposva): Verify non-public fields only.
2280 2274
2281 // Verify no duplicate additions. 2275 // Verify no duplicate additions.
2282 orig_field ^= LookupField(member_name); 2276 orig_field ^= LookupField(member_name);
2283 if (!orig_field.IsNull()) { 2277 if (!orig_field.IsNull()) {
2284 *error = FormatError(*error, // No previous error. 2278 *error = LanguageError::NewFormatted(
2285 Script::Handle(patch.script()), field.token_pos(), 2279 *error, // No previous error.
2286 "duplicate field: %s", member_name.ToCString()); 2280 Script::Handle(patch.script()),
2281 field.token_pos(),
2282 LanguageError::kError,
2283 Heap::kNew,
2284 "duplicate field: %s", member_name.ToCString());
2287 return false; 2285 return false;
2288 } 2286 }
2289 new_list.SetAt(i, field); 2287 new_list.SetAt(i, field);
2290 } 2288 }
2291 for (intptr_t i = 0; i < orig_len; i++) { 2289 for (intptr_t i = 0; i < orig_len; i++) {
2292 field ^= orig_list.At(i); 2290 field ^= orig_list.At(i);
2293 new_list.SetAt(patch_len + i, field); 2291 new_list.SetAt(patch_len + i, field);
2294 } 2292 }
2295 SetFields(new_list); 2293 SetFields(new_list);
2296 2294
(...skipping 2548 matching lines...) Expand 10 before | Expand all | Expand 10 after
4845 bool Function::HasCompatibleParametersWith(const Function& other, 4843 bool Function::HasCompatibleParametersWith(const Function& other,
4846 Error* bound_error) const { 4844 Error* bound_error) const {
4847 ASSERT(FLAG_error_on_bad_override); 4845 ASSERT(FLAG_error_on_bad_override);
4848 ASSERT((bound_error != NULL) && bound_error->IsNull()); 4846 ASSERT((bound_error != NULL) && bound_error->IsNull());
4849 // Check that this function's signature type is a subtype of the other 4847 // Check that this function's signature type is a subtype of the other
4850 // function's signature type. 4848 // function's signature type.
4851 if (!TypeTest(kIsSubtypeOf, Object::null_abstract_type_arguments(), 4849 if (!TypeTest(kIsSubtypeOf, Object::null_abstract_type_arguments(),
4852 other, Object::null_abstract_type_arguments(), bound_error)) { 4850 other, Object::null_abstract_type_arguments(), bound_error)) {
4853 // For more informative error reporting, use the location of the other 4851 // For more informative error reporting, use the location of the other
4854 // function here, since the caller will use the location of this function. 4852 // function here, since the caller will use the location of this function.
4855 *bound_error = FormatError( 4853 *bound_error = LanguageError::NewFormatted(
4856 *bound_error, // A bound error if non null. 4854 *bound_error, // A bound error if non null.
4857 Script::Handle(other.script()), 4855 Script::Handle(other.script()),
4858 other.token_pos(), 4856 other.token_pos(),
4857 LanguageError::kError,
4858 Heap::kNew,
4859 "signature type '%s' of function '%s' is not a subtype of signature " 4859 "signature type '%s' of function '%s' is not a subtype of signature "
4860 "type '%s' of function '%s'", 4860 "type '%s' of function '%s'",
4861 String::Handle(UserVisibleSignature()).ToCString(), 4861 String::Handle(UserVisibleSignature()).ToCString(),
4862 String::Handle(UserVisibleName()).ToCString(), 4862 String::Handle(UserVisibleName()).ToCString(),
4863 String::Handle(other.UserVisibleSignature()).ToCString(), 4863 String::Handle(other.UserVisibleSignature()).ToCString(),
4864 String::Handle(other.UserVisibleName()).ToCString()); 4864 String::Handle(other.UserVisibleName()).ToCString());
4865 return false; 4865 return false;
4866 } 4866 }
4867 // We should also check that if the other function explicitly specifies a 4867 // We should also check that if the other function explicitly specifies a
4868 // default value for a formal parameter, this function does not specify a 4868 // default value for a formal parameter, this function does not specify a
(...skipping 5803 matching lines...) Expand 10 before | Expand all | Expand 10 after
10672 10672
10673 RawLanguageError* LanguageError::New() { 10673 RawLanguageError* LanguageError::New() {
10674 ASSERT(Object::language_error_class() != Class::null()); 10674 ASSERT(Object::language_error_class() != Class::null());
10675 RawObject* raw = Object::Allocate(LanguageError::kClassId, 10675 RawObject* raw = Object::Allocate(LanguageError::kClassId,
10676 LanguageError::InstanceSize(), 10676 LanguageError::InstanceSize(),
10677 Heap::kOld); 10677 Heap::kOld);
10678 return reinterpret_cast<RawLanguageError*>(raw); 10678 return reinterpret_cast<RawLanguageError*>(raw);
10679 } 10679 }
10680 10680
10681 10681
10682 RawLanguageError* LanguageError::New(const String& message, Heap::Space space) { 10682 RawLanguageError* LanguageError::New(const Error& prev_error,
10683 const Script& script,
10684 intptr_t token_pos,
10685 Kind kind,
10686 const String& message,
10687 Heap::Space space) {
10683 ASSERT(Object::language_error_class() != Class::null()); 10688 ASSERT(Object::language_error_class() != Class::null());
10684 LanguageError& result = LanguageError::Handle(); 10689 LanguageError& result = LanguageError::Handle();
10685 { 10690 {
10686 RawObject* raw = Object::Allocate(LanguageError::kClassId, 10691 RawObject* raw = Object::Allocate(LanguageError::kClassId,
10687 LanguageError::InstanceSize(), 10692 LanguageError::InstanceSize(),
10688 space); 10693 space);
10689 NoGCScope no_gc; 10694 NoGCScope no_gc;
10690 result ^= raw; 10695 result ^= raw;
10691 } 10696 }
10697 result.set_previous_error(prev_error);
10698 result.set_script(script);
10699 result.set_token_pos(token_pos);
10700 result.set_kind(kind);
10692 result.set_message(message); 10701 result.set_message(message);
10693 return result.raw(); 10702 return result.raw();
10694 } 10703 }
10695 10704
10696 10705
10697 void LanguageError::set_message(const String& message) const { 10706 RawLanguageError* LanguageError::NewFormattedV(const Error& prev_error,
10698 StorePointer(&raw_ptr()->message_, message.raw()); 10707 const Script& script,
10708 intptr_t token_pos,
10709 Kind kind,
10710 Heap::Space space,
10711 const char* format,
10712 va_list args) {
10713 const String& msg = String::Handle(String::NewFormattedV(format, args));
10714 return LanguageError::New(prev_error, script, token_pos, kind, msg, space);
10715 }
10716
10717
10718 RawLanguageError* LanguageError::NewFormatted(const Error& prev_error,
10719 const Script& script,
10720 intptr_t token_pos,
10721 Kind kind,
10722 Heap::Space space,
10723 const char* format, ...) {
10724 va_list args;
10725 va_start(args, format);
10726 RawLanguageError* result = LanguageError::NewFormattedV(
10727 prev_error, script, token_pos, kind, space, format, args);
10728 NoGCScope no_gc;
Ivan Posva 2013/11/15 04:42:13 What is this NoGCScope for?
regis 2013/11/15 18:27:38 To save a handle. Same as in String::NewFormatted.
10729 va_end(args);
10730 return result;
10731 }
10732
10733
10734 RawLanguageError* LanguageError::New(const String& formatted_message,
10735 Heap::Space space) {
10736 ASSERT(Object::language_error_class() != Class::null());
10737 LanguageError& result = LanguageError::Handle();
10738 {
10739 RawObject* raw = Object::Allocate(LanguageError::kClassId,
10740 LanguageError::InstanceSize(),
10741 space);
10742 NoGCScope no_gc;
10743 result ^= raw;
10744 }
10745 result.set_formatted_message(formatted_message);
10746 return result.raw();
10747 }
10748
10749
10750 void LanguageError::set_previous_error(const Error& value) const {
10751 StorePointer(&raw_ptr()->previous_error_, value.raw());
10752 }
10753
10754
10755 void LanguageError::set_script(const Script& value) const {
10756 StorePointer(&raw_ptr()->script_, value.raw());
10757 }
10758
10759
10760 void LanguageError::set_token_pos(intptr_t value) const {
10761 ASSERT(value >= 0);
10762 raw_ptr()->token_pos_ = value;
10763 }
10764
10765
10766 void LanguageError::set_kind(uint8_t value) const {
10767 raw_ptr()->kind_ = value;
10768 }
10769
10770
10771 void LanguageError::set_message(const String& value) const {
10772 StorePointer(&raw_ptr()->message_, value.raw());
10773 }
10774
10775
10776 void LanguageError::set_formatted_message(const String& value) const {
10777 StorePointer(&raw_ptr()->formatted_message_, value.raw());
10778 }
10779
10780
10781 RawString* LanguageError::FormatMessage() const {
10782 if (formatted_message() != String::null()) {
10783 return formatted_message();
10784 }
10785 const char* message_header;
10786 switch (kind()) {
10787 case kWarning: message_header = "warning"; break;
10788 case kError: message_header = "error"; break;
10789 case kMalformedType: message_header = "malformed type"; break;
10790 case kMalboundedType: message_header = "malbounded type"; break;
10791 default: message_header = ""; UNREACHABLE();
10792 }
10793 String& result = String::Handle();
10794 String& msg = String::Handle(message());
10795 const Script& scr = Script::Handle(script());
10796 if (!scr.IsNull()) {
10797 const String& script_url = String::Handle(scr.url());
10798 if (token_pos() >= 0) {
10799 intptr_t line, column;
10800 scr.GetTokenLocation(token_pos(), &line, &column);
10801 // Only report the line position if we have the original source. We still
10802 // need to get a valid column so that we can report the ^ mark below the
10803 // snippet.
10804 if (scr.HasSource()) {
10805 result = String::NewFormatted("'%s': %s: line %" Pd " pos %" Pd ": ",
10806 script_url.ToCString(),
10807 message_header,
10808 line,
10809 column);
10810 } else {
10811 result = String::NewFormatted("'%s': %s: line %" Pd ": ",
10812 script_url.ToCString(),
10813 message_header,
10814 line);
10815 }
10816 // Append the formatted error or warning message.
10817 result = String::Concat(result, msg);
10818 const String& new_line = String::Handle(String::New("\n"));
Ivan Posva 2013/11/15 04:42:13 Please just use Symbols::NewLine() where we use th
regis 2013/11/15 18:27:38 Done.
10819 // Append the source line.
10820 const String& script_line = String::Handle(scr.GetLine(line));
10821 ASSERT(!script_line.IsNull());
10822 result = String::Concat(result, new_line);
10823 result = String::Concat(result, script_line);
10824 result = String::Concat(result, new_line);
10825 // Append the column marker.
10826 const String& column_line = String::Handle(
10827 String::NewFormatted("%*s\n", static_cast<int>(column), "^"));
10828 result = String::Concat(result, column_line);
10829 } else {
10830 // Token position is unknown.
10831 result = String::NewFormatted("'%s': %s: ",
10832 script_url.ToCString(),
10833 message_header);
10834 result = String::Concat(result, msg);
10835 }
10836 } else {
10837 // Script is unknown.
10838 // Append the formatted error or warning message.
10839 result = String::NewFormatted("%s: ", message_header);
10840 result = String::Concat(result, msg);
10841 }
10842 // Prepend previous error message.
10843 const Error& prev_error = Error::Handle(previous_error());
10844 if (!prev_error.IsNull()) {
10845 msg = String::New(prev_error.ToErrorCString());
10846 result = String::Concat(msg, result);
10847 }
10848 set_formatted_message(result);
10849 return result.raw();
10699 } 10850 }
10700 10851
10701 10852
10702 const char* LanguageError::ToErrorCString() const { 10853 const char* LanguageError::ToErrorCString() const {
10703 const String& msg_str = String::Handle(message()); 10854 const String& msg_str = String::Handle(FormatMessage());
10704 return msg_str.ToCString(); 10855 return msg_str.ToCString();
10705 } 10856 }
10706 10857
10707 10858
10708 const char* LanguageError::ToCString() const { 10859 const char* LanguageError::ToCString() const {
10709 return "LanguageError"; 10860 return "LanguageError";
10710 } 10861 }
10711 10862
10712 10863
10713 void LanguageError::PrintToJSONStream(JSONStream* stream, bool ref) const { 10864 void LanguageError::PrintToJSONStream(JSONStream* stream, bool ref) const {
(...skipping 1413 matching lines...) Expand 10 before | Expand all | Expand 10 after
12127 upper_bound.UserVisibleName()); 12278 upper_bound.UserVisibleName());
12128 const AbstractType& declared_bound = AbstractType::Handle(bound()); 12279 const AbstractType& declared_bound = AbstractType::Handle(bound());
12129 const String& declared_bound_name = String::Handle( 12280 const String& declared_bound_name = String::Handle(
12130 declared_bound.UserVisibleName()); 12281 declared_bound.UserVisibleName());
12131 const String& type_param_name = String::Handle(UserVisibleName()); 12282 const String& type_param_name = String::Handle(UserVisibleName());
12132 const Class& cls = Class::Handle(parameterized_class()); 12283 const Class& cls = Class::Handle(parameterized_class());
12133 const String& class_name = String::Handle(cls.Name()); 12284 const String& class_name = String::Handle(cls.Name());
12134 const Script& script = Script::Handle(cls.script()); 12285 const Script& script = Script::Handle(cls.script());
12135 // Since the bound may have been canonicalized, its token index is 12286 // Since the bound may have been canonicalized, its token index is
12136 // meaningless, therefore use the token index of this type parameter. 12287 // meaningless, therefore use the token index of this type parameter.
12137 *bound_error = FormatError( 12288 *bound_error = LanguageError::NewFormatted(
12138 *bound_error, 12289 *bound_error,
12139 script, 12290 script,
12140 token_pos(), 12291 token_pos(),
12292 LanguageError::kMalboundedType,
12293 Heap::kNew,
12141 "type parameter '%s' of class '%s' must extend bound '%s', " 12294 "type parameter '%s' of class '%s' must extend bound '%s', "
12142 "but type argument '%s' is not a subtype of '%s'\n", 12295 "but type argument '%s' is not a subtype of '%s'\n",
12143 type_param_name.ToCString(), 12296 type_param_name.ToCString(),
12144 class_name.ToCString(), 12297 class_name.ToCString(),
12145 declared_bound_name.ToCString(), 12298 declared_bound_name.ToCString(),
12146 bounded_type_name.ToCString(), 12299 bounded_type_name.ToCString(),
12147 upper_bound_name.ToCString()); 12300 upper_bound_name.ToCString());
12148 } 12301 }
12149 } 12302 }
12150 return false; 12303 return false;
(...skipping 3632 matching lines...) Expand 10 before | Expand all | Expand 10 after
15783 return "_MirrorReference"; 15936 return "_MirrorReference";
15784 } 15937 }
15785 15938
15786 15939
15787 void MirrorReference::PrintToJSONStream(JSONStream* stream, bool ref) const { 15940 void MirrorReference::PrintToJSONStream(JSONStream* stream, bool ref) const {
15788 JSONObject jsobj(stream); 15941 JSONObject jsobj(stream);
15789 } 15942 }
15790 15943
15791 15944
15792 } // namespace dart 15945 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698