Index: vm/object.cc |
=================================================================== |
--- vm/object.cc (revision 10396) |
+++ vm/object.cc (working copy) |
@@ -101,6 +101,90 @@ |
RawClass* Object::unwind_error_class_ = reinterpret_cast<RawClass*>(RAW_NULL); |
#undef RAW_NULL |
+ |
+// Takes a vm internal name and makes it suitable for external user. |
+// |
+// Examples: |
+// |
+// Internal getter and setter prefixes are changed: |
+// |
+// get:foo -> foo |
+// set:foo -> foo= |
+// |
+// Private name mangling is removed, possibly twice: |
+// |
+// _ReceivePortImpl@6be832b -> _ReceivePortImpl |
+// _ReceivePortImpl@6be832b._internal@6be832b -> +ReceivePortImpl._internal |
+// |
+// The trailing . on the default constructor name is dropped: |
+// |
+// List. -> List |
+// |
+// And so forth: |
+// |
+// get:foo@6be832b -> foo |
+// _MyClass@6b3832b. -> _MyClass |
+// _MyClass@6b3832b.named -> _MyClass.named |
+// |
+static RawString* IdentifierPrettyName(const String& name) { |
+ intptr_t len = name.Length(); |
+ intptr_t start = 0; |
+ intptr_t at_pos = len; // Position of '@' in the name. |
+ intptr_t dot_pos = len; // Position of '.' in the name. |
+ bool is_setter = false; |
+ |
+ for (int i = 0; i < name.Length(); i++) { |
+ if (name.CharAt(i) == ':') { |
+ ASSERT(start == 0); |
+ if (name.CharAt(0) == 's') { |
+ is_setter = true; |
+ } |
+ start = i + 1; |
+ } else if (name.CharAt(i) == '@') { |
+ ASSERT(at_pos == len); |
+ at_pos = i; |
+ } else if (name.CharAt(i) == '.') { |
+ dot_pos = i; |
+ break; |
+ } |
+ } |
+ intptr_t limit = (at_pos < dot_pos ? at_pos : dot_pos); |
+ if (start == 0 && limit == len) { |
+ // This name is fine as it is. |
+ return name.raw(); |
+ } |
+ |
+ const String& result = |
+ String::Handle(String::SubString(name, start, (limit - start))); |
+ |
+ // Look for a second '@' now to correctly handle names like |
+ // "_ReceivePortImpl@6be832b._internal@6be832b". |
+ at_pos = len; |
+ for (int i = dot_pos; i < name.Length(); i++) { |
+ if (name.CharAt(i) == '@') { |
+ ASSERT(at_pos == len); |
+ at_pos = i; |
+ } |
+ } |
+ |
+ intptr_t suffix_len = at_pos - dot_pos; |
+ if (suffix_len > 1) { |
+ // This is a named constructor. Add the name back to the string. |
+ const String& suffix = |
+ String::Handle(String::SubString(name, dot_pos, suffix_len)); |
+ return String::Concat(result, suffix); |
+ } |
+ |
+ if (is_setter) { |
+ // Setters need to end with '='. |
+ const String& suffix = String::Handle(Symbols::Equals()); |
+ return String::Concat(result, suffix); |
+ } |
+ |
+ return result.raw(); |
+} |
+ |
+ |
int Object::GetSingletonClassIndex(const RawClass* raw_class) { |
ASSERT(raw_class->IsHeapObject()); |
if (raw_class == class_class()) { |
@@ -1131,7 +1215,8 @@ |
case kExternalFloat64Array: |
return Symbols::New("Float64List"); |
default: |
- return Name(); |
+ const String& name = String::Handle(Name()); |
+ return IdentifierPrettyName(name); |
} |
UNREACHABLE(); |
} |
@@ -4372,6 +4457,38 @@ |
} |
+RawString* Function::UserVisibleName() const { |
+ const String& str = String::Handle(name()); |
+ return IdentifierPrettyName(str); |
+} |
+ |
+ |
+RawString* Function::QualifiedUserVisibleName() const { |
+ String& tmp = String::Handle(); |
+ String& suffix = String::Handle(); |
+ const Class& cls = Class::Handle(owner()); |
+ |
+ if (IsClosureFunction()) { |
+ if (IsLocalFunction()) { |
+ const Function& parent = Function::Handle(parent_function()); |
+ tmp = parent.QualifiedUserVisibleName(); |
+ } else { |
+ return UserVisibleName(); |
+ } |
+ } else { |
+ if (cls.IsTopLevel()) { |
+ return UserVisibleName(); |
+ } else { |
+ tmp = cls.UserVisibleName(); |
+ } |
+ } |
+ suffix = Symbols::Dot(); |
+ tmp = String::Concat(tmp, suffix); |
+ suffix = UserVisibleName(); |
+ return String::Concat(tmp, suffix); |
+} |
+ |
+ |
const char* Function::ToCString() const { |
const char* static_str = is_static() ? " static" : ""; |
const char* abstract_str = is_abstract() ? " abstract" : ""; |
@@ -4525,6 +4642,12 @@ |
} |
+RawString* Field::UserVisibleName() const { |
+ const String& str = String::Handle(name()); |
+ return IdentifierPrettyName(str); |
+} |
+ |
+ |
const char* Field::ToCString() const { |
const char* kF0 = is_static() ? " static" : ""; |
const char* kF1 = is_final() ? " final" : ""; |
@@ -10894,31 +11017,27 @@ |
} |
-const char* Stacktrace::ToCStringInternal(bool verbose) const { |
+const char* Stacktrace::ToCString() const { |
Function& function = Function::Handle(); |
Code& code = Code::Handle(); |
- Class& function_class = Class::Handle(); |
+ Class& owner = Class::Handle(); |
Script& script = Script::Handle(); |
String& function_name = String::Handle(); |
- String& class_name = String::Handle(); |
String& url = String::Handle(); |
// Iterate through the stack frames and create C string description |
// for each frame. |
intptr_t total_len = 0; |
- const char* kFormat = verbose ? |
- " %d. Function: '%s%s%s' url: '%s' line:%d col:%d code-entry: 0x%x\n" : |
- " %d. Function: '%s%s%s' url: '%s' line:%d col:%d\n"; |
+ const char* kFormat = "#%-6d %s (%s:%d:%d)\n"; |
GrowableArray<char*> frame_strings; |
for (intptr_t i = 0; i < Length(); i++) { |
function = FunctionAtFrame(i); |
code = CodeAtFrame(i); |
uword pc = code.EntryPoint() + Smi::Value(PcOffsetAtFrame(i)); |
intptr_t token_pos = code.GetTokenIndexOfPC(pc); |
- function_class = function.owner(); |
- script = function_class.script(); |
- function_name = function.name(); |
- class_name = function_class.Name(); |
+ owner = function.owner(); |
+ script = owner.script(); |
+ function_name = function.QualifiedUserVisibleName(); |
url = script.url(); |
intptr_t line = -1; |
intptr_t column = -1; |
@@ -10927,22 +11046,16 @@ |
} |
intptr_t len = OS::SNPrint(NULL, 0, kFormat, |
i, |
- class_name.ToCString(), |
- function_class.IsTopLevel() ? "" : ".", |
function_name.ToCString(), |
url.ToCString(), |
- line, column, |
- code.EntryPoint()); |
+ line, column); |
total_len += len; |
char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1); |
OS::SNPrint(chars, (len + 1), kFormat, |
i, |
- class_name.ToCString(), |
- function_class.IsTopLevel() ? "" : ".", |
function_name.ToCString(), |
url.ToCString(), |
- line, column, |
- code.EntryPoint()); |
+ line, column); |
frame_strings.Add(chars); |
} |
@@ -10959,11 +11072,6 @@ |
} |
-const char* Stacktrace::ToCString() const { |
- return ToCStringInternal(false); |
-} |
- |
- |
void JSRegExp::set_pattern(const String& pattern) const { |
StorePointer(&raw_ptr()->pattern_, pattern.raw()); |
} |