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

Side by Side Diff: vm/object.cc

Issue 10826191: Improve the stack trace output to be more readable. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/runtime/
Patch Set: Created 8 years, 4 months 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
« no previous file with comments | « vm/object.h ('k') | vm/object_test.cc » ('j') | vm/object_test.cc » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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/bigint_operations.h" 10 #include "vm/bigint_operations.h"
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
94 RawClass* Object::icdata_class_ = reinterpret_cast<RawClass*>(RAW_NULL); 94 RawClass* Object::icdata_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
95 RawClass* Object::subtypetestcache_class_ = 95 RawClass* Object::subtypetestcache_class_ =
96 reinterpret_cast<RawClass*>(RAW_NULL); 96 reinterpret_cast<RawClass*>(RAW_NULL);
97 RawClass* Object::api_error_class_ = reinterpret_cast<RawClass*>(RAW_NULL); 97 RawClass* Object::api_error_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
98 RawClass* Object::language_error_class_ = reinterpret_cast<RawClass*>(RAW_NULL); 98 RawClass* Object::language_error_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
99 RawClass* Object::unhandled_exception_class_ = 99 RawClass* Object::unhandled_exception_class_ =
100 reinterpret_cast<RawClass*>(RAW_NULL); 100 reinterpret_cast<RawClass*>(RAW_NULL);
101 RawClass* Object::unwind_error_class_ = reinterpret_cast<RawClass*>(RAW_NULL); 101 RawClass* Object::unwind_error_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
102 #undef RAW_NULL 102 #undef RAW_NULL
103 103
104
105 // Takes a vm internal name and makes it suitable for external user.
106 //
107 // Examples:
108 //
109 // Internal getter and setter prefices are removed:
siva 2012/08/07 21:41:37 prefixes
turnidge 2012/08/07 23:32:09 Done.
110 //
111 // get:foo -> foo
112 // set:foo -> foo
siva 2012/08/07 21:41:37 I am wondering get:foo should become 'get foo' and
turnidge 2012/08/07 23:32:09 Discussed offline. For now this lets me share the
113 //
114 // Private name mangling is removed, possibly twice:
115 //
116 // _ReceivePortImpl@6be832b -> _ReceivePortImpl
117 // _ReceivePortImpl@6be832b._internal@6be832b -> +ReceivePortImpl._internal
118 //
119 // The trailing . on the default constructor name is dropped:
120 //
121 // List. -> List
122 //
123 // And so forth:
124 //
125 // get:foo@6be832b -> foo
126 // _MyClass@6b3832b. -> _MyClass
127 // _MyClass@6b3832b.named -> _MyClass.named
128 //
129 static RawString* IdentifierPrettyName(const String& name) {
130 intptr_t len = name.Length();
131 intptr_t start = 0;
132 intptr_t at_pos = len; // Position of '@' in the name.
133 intptr_t dot_pos = len; // Position of '.' in the name.
134
135 for (int i = 0; i < name.Length(); i++) {
136 if (name.CharAt(i) == ':') {
137 ASSERT(start == 0);
138 start = i + 1;
139 } else if (name.CharAt(i) == '@') {
140 ASSERT(at_pos == len);
141 at_pos = i;
142 } else if (name.CharAt(i) == '.') {
143 dot_pos = i;
144 break;
145 }
146 }
147 intptr_t limit = (at_pos < dot_pos ? at_pos : dot_pos);
148 if (start == 0 && limit == len) {
149 // This name is fine as it is.
150 return name.raw();
151 }
152
153 String& result = String::Handle();
154 result = String::SubString(name, start, (limit - start));
siva 2012/08/07 21:41:37 const String& result = String::Handle(String::Sub.
turnidge 2012/08/07 23:32:09 Done.
155
156 // Look for a second '@' now to correctly handle names like
157 // "_ReceivePortImpl@6be832b._internal@6be832b".
158 at_pos = len;
159 for (int i = dot_pos; i < name.Length(); i++) {
160 if (name.CharAt(i) == '@') {
161 ASSERT(at_pos == len);
162 at_pos = i;
163 }
164 }
165
166 intptr_t suffix_len = at_pos - dot_pos;
167 if (suffix_len <= 1) {
168 // The constructor name is of length 0 or 1. That means that
169 // either this isn't a constructor or that this is an unnamed
170 // constructor. In either case, we're done.
171 return result.raw();
172 }
173
174 const String& suffix =
175 String::Handle(String::SubString(name, dot_pos, suffix_len));
176 return String::Concat(result, suffix);
177 }
178
179
104 int Object::GetSingletonClassIndex(const RawClass* raw_class) { 180 int Object::GetSingletonClassIndex(const RawClass* raw_class) {
105 ASSERT(raw_class->IsHeapObject()); 181 ASSERT(raw_class->IsHeapObject());
106 if (raw_class == class_class()) { 182 if (raw_class == class_class()) {
107 return kClassClass; 183 return kClassClass;
108 } else if (raw_class == null_class()) { 184 } else if (raw_class == null_class()) {
109 return kNullClass; 185 return kNullClass;
110 } else if (raw_class == dynamic_class()) { 186 } else if (raw_class == dynamic_class()) {
111 return kDynamicClass; 187 return kDynamicClass;
112 } else if (raw_class == void_class()) { 188 } else if (raw_class == void_class()) {
113 return kVoidClass; 189 return kVoidClass;
(...skipping 1010 matching lines...) Expand 10 before | Expand all | Expand 10 after
1124 case kUint64Array: 1200 case kUint64Array:
1125 case kExternalUint64Array: 1201 case kExternalUint64Array:
1126 return Symbols::New("Uint64List"); 1202 return Symbols::New("Uint64List");
1127 case kFloat32Array: 1203 case kFloat32Array:
1128 case kExternalFloat32Array: 1204 case kExternalFloat32Array:
1129 return Symbols::New("Float32List"); 1205 return Symbols::New("Float32List");
1130 case kFloat64Array: 1206 case kFloat64Array:
1131 case kExternalFloat64Array: 1207 case kExternalFloat64Array:
1132 return Symbols::New("Float64List"); 1208 return Symbols::New("Float64List");
1133 default: 1209 default:
1134 return Name(); 1210 const String& name = String::Handle(Name());
1211 return IdentifierPrettyName(name);
1135 } 1212 }
1136 UNREACHABLE(); 1213 UNREACHABLE();
1137 } 1214 }
1138 1215
1139 1216
1140 RawType* Class::SignatureType() const { 1217 RawType* Class::SignatureType() const {
1141 ASSERT(IsSignatureClass()); 1218 ASSERT(IsSignatureClass());
1142 const Function& function = Function::Handle(signature_function()); 1219 const Function& function = Function::Handle(signature_function());
1143 ASSERT(!function.IsNull()); 1220 ASSERT(!function.IsNull());
1144 if (function.signature_class() != raw()) { 1221 if (function.signature_class() != raw()) {
(...skipping 3214 matching lines...) Expand 10 before | Expand all | Expand 10 after
4359 } 4436 }
4360 return true; 4437 return true;
4361 } 4438 }
4362 4439
4363 4440
4364 bool Function::HasOptimizedCode() const { 4441 bool Function::HasOptimizedCode() const {
4365 return HasCode() && Code::Handle(raw_ptr()->code_).is_optimized(); 4442 return HasCode() && Code::Handle(raw_ptr()->code_).is_optimized();
4366 } 4443 }
4367 4444
4368 4445
4446 RawString* Function::UserVisibleName() const {
4447 String& tmp = String::Handle();
4448 tmp = name();
4449 tmp = IdentifierPrettyName(tmp);
4450 if (kind() == RawFunction::kSetterFunction) {
4451 const String& suffix = String::Handle(Symbols::Equals());
4452 tmp = String::Concat(tmp, suffix);
siva 2012/08/07 21:41:37 See comment above regarding setter/gettter, does i
turnidge 2012/08/07 23:32:09 See above.
4453 }
4454 return tmp.raw();
4455 }
4456
4457
4458 RawString* Function::QualifiedUserVisibleName() const {
4459 String& tmp = String::Handle();
4460 String& suffix = String::Handle();
4461 const Class& cls = Class::Handle(owner());
4462
4463 if (IsClosureFunction()) {
4464 if (IsLocalFunction()) {
4465 const Function& parent = Function::Handle(parent_function());
4466 tmp = parent.QualifiedUserVisibleName();
4467 } else {
4468 return UserVisibleName();
4469 }
4470 } else {
4471 if (cls.IsTopLevel()) {
4472 return UserVisibleName();
4473 } else {
4474 tmp = cls.UserVisibleName();
4475 }
4476 }
4477 suffix = Symbols::Dot();
4478 tmp = String::Concat(tmp, suffix);
4479 suffix = UserVisibleName();
4480 return String::Concat(tmp, suffix);
4481 }
4482
4483
4369 const char* Function::ToCString() const { 4484 const char* Function::ToCString() const {
4370 const char* static_str = is_static() ? " static" : ""; 4485 const char* static_str = is_static() ? " static" : "";
4371 const char* abstract_str = is_abstract() ? " abstract" : ""; 4486 const char* abstract_str = is_abstract() ? " abstract" : "";
4372 const char* kind_str = NULL; 4487 const char* kind_str = NULL;
4373 const char* const_str = is_const() ? " const" : ""; 4488 const char* const_str = is_const() ? " const" : "";
4374 switch (kind()) { 4489 switch (kind()) {
4375 case RawFunction::kRegularFunction: 4490 case RawFunction::kRegularFunction:
4376 case RawFunction::kClosureFunction: 4491 case RawFunction::kClosureFunction:
4377 case RawFunction::kGetterFunction: 4492 case RawFunction::kGetterFunction:
4378 case RawFunction::kSetterFunction: 4493 case RawFunction::kSetterFunction:
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
4512 } 4627 }
4513 result.set_is_final(is_final); 4628 result.set_is_final(is_final);
4514 result.set_is_const(is_const); 4629 result.set_is_const(is_const);
4515 result.set_owner(owner); 4630 result.set_owner(owner);
4516 result.set_token_pos(token_pos); 4631 result.set_token_pos(token_pos);
4517 result.set_has_initializer(false); 4632 result.set_has_initializer(false);
4518 return result.raw(); 4633 return result.raw();
4519 } 4634 }
4520 4635
4521 4636
4637 RawString* Field::UserVisibleName() const {
4638 const String& str = String::Handle(name());
4639 return IdentifierPrettyName(str);
4640 }
4641
4642
4522 const char* Field::ToCString() const { 4643 const char* Field::ToCString() const {
4523 const char* kF0 = is_static() ? " static" : ""; 4644 const char* kF0 = is_static() ? " static" : "";
4524 const char* kF1 = is_final() ? " final" : ""; 4645 const char* kF1 = is_final() ? " final" : "";
4525 const char* kF2 = is_const() ? " const" : ""; 4646 const char* kF2 = is_const() ? " const" : "";
4526 const char* kFormat = "Field <%s.%s>:%s%s%s"; 4647 const char* kFormat = "Field <%s.%s>:%s%s%s";
4527 const char* field_name = String::Handle(name()).ToCString(); 4648 const char* field_name = String::Handle(name()).ToCString();
4528 const Class& cls = Class::Handle(owner()); 4649 const Class& cls = Class::Handle(owner());
4529 const char* cls_name = String::Handle(cls.Name()).ToCString(); 4650 const char* cls_name = String::Handle(cls.Name()).ToCString();
4530 intptr_t len = 4651 intptr_t len =
4531 OS::SNPrint(NULL, 0, kFormat, cls_name, field_name, kF0, kF1, kF2) + 1; 4652 OS::SNPrint(NULL, 0, kFormat, cls_name, field_name, kF0, kF1, kF2) + 1;
(...skipping 6349 matching lines...) Expand 10 before | Expand all | Expand 10 after
10881 obj = func_list.At(j); 11002 obj = func_list.At(j);
10882 function_array.SetAt(i, obj); 11003 function_array.SetAt(i, obj);
10883 obj = code_list.At(j); 11004 obj = code_list.At(j);
10884 code_array.SetAt(i, obj); 11005 code_array.SetAt(i, obj);
10885 obj = pc_offset_list.At(j); 11006 obj = pc_offset_list.At(j);
10886 pc_offset_array.SetAt(i, obj); 11007 pc_offset_array.SetAt(i, obj);
10887 } 11008 }
10888 } 11009 }
10889 11010
10890 11011
10891 const char* Stacktrace::ToCStringInternal(bool verbose) const { 11012 const char* Stacktrace::ToCString() const {
10892 Function& function = Function::Handle(); 11013 Function& function = Function::Handle();
10893 Code& code = Code::Handle(); 11014 Code& code = Code::Handle();
10894 Class& function_class = Class::Handle(); 11015 Class& owner = Class::Handle();
10895 Script& script = Script::Handle(); 11016 Script& script = Script::Handle();
10896 String& function_name = String::Handle(); 11017 String& function_name = String::Handle();
10897 String& class_name = String::Handle();
10898 String& url = String::Handle(); 11018 String& url = String::Handle();
10899 11019
10900 // Iterate through the stack frames and create C string description 11020 // Iterate through the stack frames and create C string description
10901 // for each frame. 11021 // for each frame.
10902 intptr_t total_len = 0; 11022 intptr_t total_len = 0;
10903 const char* kFormat = verbose ? 11023 const char* kFormat = " at %s (%s:%d:%d)\n";
siva 2012/08/07 21:41:37 Looking at the sample output you have attached I a
turnidge 2012/08/07 23:32:09 Replaced "at" with a frame number. On 2012/08/07
10904 " %d. Function: '%s%s%s' url: '%s' line:%d col:%d code-entry: 0x%x\n" :
10905 " %d. Function: '%s%s%s' url: '%s' line:%d col:%d\n";
10906 GrowableArray<char*> frame_strings; 11024 GrowableArray<char*> frame_strings;
10907 for (intptr_t i = 0; i < Length(); i++) { 11025 for (intptr_t i = 0; i < Length(); i++) {
10908 function = FunctionAtFrame(i); 11026 function = FunctionAtFrame(i);
10909 code = CodeAtFrame(i); 11027 code = CodeAtFrame(i);
10910 uword pc = code.EntryPoint() + Smi::Value(PcOffsetAtFrame(i)); 11028 uword pc = code.EntryPoint() + Smi::Value(PcOffsetAtFrame(i));
10911 intptr_t token_pos = code.GetTokenIndexOfPC(pc); 11029 intptr_t token_pos = code.GetTokenIndexOfPC(pc);
10912 function_class = function.owner(); 11030 owner = function.owner();
10913 script = function_class.script(); 11031 script = owner.script();
10914 function_name = function.name(); 11032 function_name = function.QualifiedUserVisibleName();
10915 class_name = function_class.Name();
10916 url = script.url(); 11033 url = script.url();
10917 intptr_t line = -1; 11034 intptr_t line = -1;
10918 intptr_t column = -1; 11035 intptr_t column = -1;
10919 if (token_pos >= 0) { 11036 if (token_pos >= 0) {
10920 script.GetTokenLocation(token_pos, &line, &column); 11037 script.GetTokenLocation(token_pos, &line, &column);
10921 } 11038 }
10922 intptr_t len = OS::SNPrint(NULL, 0, kFormat, 11039 intptr_t len = OS::SNPrint(NULL, 0, kFormat,
10923 i,
10924 class_name.ToCString(),
10925 function_class.IsTopLevel() ? "" : ".",
10926 function_name.ToCString(), 11040 function_name.ToCString(),
10927 url.ToCString(), 11041 url.ToCString(),
10928 line, column, 11042 line, column);
10929 code.EntryPoint());
10930 total_len += len; 11043 total_len += len;
10931 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1); 11044 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1);
10932 OS::SNPrint(chars, (len + 1), kFormat, 11045 OS::SNPrint(chars, (len + 1), kFormat,
10933 i,
10934 class_name.ToCString(),
10935 function_class.IsTopLevel() ? "" : ".",
10936 function_name.ToCString(), 11046 function_name.ToCString(),
10937 url.ToCString(), 11047 url.ToCString(),
10938 line, column, 11048 line, column);
10939 code.EntryPoint());
10940 frame_strings.Add(chars); 11049 frame_strings.Add(chars);
10941 } 11050 }
10942 11051
10943 // Now concatentate the frame descriptions into a single C string. 11052 // Now concatentate the frame descriptions into a single C string.
10944 char* chars = Isolate::Current()->current_zone()->Alloc<char>(total_len + 1); 11053 char* chars = Isolate::Current()->current_zone()->Alloc<char>(total_len + 1);
10945 intptr_t index = 0; 11054 intptr_t index = 0;
10946 for (intptr_t i = 0; i < frame_strings.length(); i++) { 11055 for (intptr_t i = 0; i < frame_strings.length(); i++) {
10947 index += OS::SNPrint((chars + index), 11056 index += OS::SNPrint((chars + index),
10948 (total_len + 1 - index), 11057 (total_len + 1 - index),
10949 "%s", 11058 "%s",
10950 frame_strings[i]); 11059 frame_strings[i]);
10951 } 11060 }
10952 return chars; 11061 return chars;
10953 } 11062 }
10954 11063
10955 11064
10956 const char* Stacktrace::ToCString() const {
10957 return ToCStringInternal(false);
10958 }
10959
10960
10961 void JSRegExp::set_pattern(const String& pattern) const { 11065 void JSRegExp::set_pattern(const String& pattern) const {
10962 StorePointer(&raw_ptr()->pattern_, pattern.raw()); 11066 StorePointer(&raw_ptr()->pattern_, pattern.raw());
10963 } 11067 }
10964 11068
10965 11069
10966 void JSRegExp::set_num_bracket_expressions(intptr_t value) const { 11070 void JSRegExp::set_num_bracket_expressions(intptr_t value) const {
10967 raw_ptr()->num_bracket_expressions_ = Smi::New(value); 11071 raw_ptr()->num_bracket_expressions_ = Smi::New(value);
10968 } 11072 }
10969 11073
10970 11074
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
11049 const char* JSRegExp::ToCString() const { 11153 const char* JSRegExp::ToCString() const {
11050 const String& str = String::Handle(pattern()); 11154 const String& str = String::Handle(pattern());
11051 const char* format = "JSRegExp: pattern=%s flags=%s"; 11155 const char* format = "JSRegExp: pattern=%s flags=%s";
11052 intptr_t len = OS::SNPrint(NULL, 0, format, str.ToCString(), Flags()); 11156 intptr_t len = OS::SNPrint(NULL, 0, format, str.ToCString(), Flags());
11053 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1); 11157 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1);
11054 OS::SNPrint(chars, (len + 1), format, str.ToCString(), Flags()); 11158 OS::SNPrint(chars, (len + 1), format, str.ToCString(), Flags());
11055 return chars; 11159 return chars;
11056 } 11160 }
11057 11161
11058 } // namespace dart 11162 } // namespace dart
OLDNEW
« no previous file with comments | « vm/object.h ('k') | vm/object_test.cc » ('j') | vm/object_test.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698