Index: runtime/vm/object.cc |
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc |
index b28e24f98366a43da798f1aa26a00356152f1a80..43c8b2e581afd4a37c8409892a4db0b2c3870ca9 100644 |
--- a/runtime/vm/object.cc |
+++ b/runtime/vm/object.cc |
@@ -15373,7 +15373,7 @@ const char* Stacktrace::ToCStringInternal(intptr_t* frame_index) const { |
for (intptr_t i = 0; i < Length(); i++) { |
function = FunctionAtFrame(i); |
if (function.IsNull()) { |
- // Check if null function object indicates a stack trace overflow. |
+ // Check for null function object, which indicates a stack trace overflow. |
siva
2013/10/31 17:13:26
A null function object doesn't necessarily mean a
rmacnak
2013/11/07 21:31:12
Reverted.
|
if ((i < (Length() - 1)) && |
(FunctionAtFrame(i + 1) != Function::null())) { |
const char* kTruncated = "...\n...\n"; |
@@ -15421,6 +15421,124 @@ const char* Stacktrace::ToCStringInternal(intptr_t* frame_index) const { |
return chars; |
} |
+intptr_t Stacktrace::VisibleLength() const { |
+ // Isolate* isolate = Isolate::Current(); |
+ Function& function = Function::Handle(); |
+ Code& code = Code::Handle(); |
+ intptr_t frame_count = 0; |
+ for (intptr_t i = 0; i < Length(); i++) { |
+ function = FunctionAtFrame(i); |
+ if (function.IsNull()) { |
+ // Check for null function object, which indicates a stack trace overflow. |
+ if ((i < (Length() - 1)) && |
+ (FunctionAtFrame(i + 1) != Function::null())) { |
+ // How to inform API users? |
rmacnak
2013/10/30 16:52:45
frame_count++ if we indicate the gap. See comment
siva
2013/10/31 17:13:26
Since you are handing out actual frames maybe the
rmacnak
2013/11/07 21:31:12
The truncation for StackOverflow happens before th
|
+ } |
+ } else if (function.is_visible() || FLAG_verbose_stacktrace) { |
siva
2013/10/31 17:13:26
We probably don't want the verbose_stacktrace flag
rmacnak
2013/11/07 21:31:12
Removed.
|
+ code = CodeAtFrame(i); |
+ ASSERT(function.raw() == code.function()); |
+ uword pc = code.EntryPoint() + Smi::Value(PcOffsetAtFrame(i)); |
+ if (code.is_optimized() && expand_inlined()) { |
+ // Traverse inlined frames. |
+ for (InlinedFunctionsIterator it(code, pc); !it.Done(); it.Advance()) { |
+ function = it.function(); |
+ code = it.code(); |
+ ASSERT(function.raw() == code.function()); |
+ uword pc = it.pc(); |
+ ASSERT(pc != 0); |
+ ASSERT(code.EntryPoint() <= pc); |
+ ASSERT(pc < (code.EntryPoint() + code.Size())); |
+ frame_count++; |
+ } |
+ } else { |
+ frame_count++; |
+ } |
+ } |
+ } |
+ return frame_count; |
+} |
+ |
+bool Stacktrace::VisibleFrameInfoAt(intptr_t frame_index, |
+ String* function_name, |
+ String* script_url, |
+ intptr_t* line_number, |
+ intptr_t* col_num) const { |
+ ASSERT(function_name); |
+ ASSERT(script_url); |
+ ASSERT(line_number); |
+ ASSERT(col_num); |
+ |
+ if (frame_index < 0) { |
+ return false; |
+ } |
+ |
+ Isolate* isolate = Isolate::Current(); |
+ Function& function = Function::Handle(); |
+ Code& code = Code::Handle(); |
+ intptr_t frame_count = 0; |
+ for (intptr_t i = 0; i < Length(); i++) { |
+ function = FunctionAtFrame(i); |
+ if (function.IsNull()) { |
+ // Check for null function object, which indicates a stack trace overflow. |
+ if ((i < (Length() - 1)) && |
+ (FunctionAtFrame(i + 1) != Function::null())) { |
+ // How to inform API users? |
rmacnak
2013/10/30 16:52:45
Function named '...' at -1, -1?
siva
2013/10/31 17:13:26
Ditto comment as above, the API implementation sho
|
+ } |
+ } else if (function.is_visible() || FLAG_verbose_stacktrace) { |
+ code = CodeAtFrame(i); |
+ ASSERT(function.raw() == code.function()); |
+ uword pc = code.EntryPoint() + Smi::Value(PcOffsetAtFrame(i)); |
+ if (code.is_optimized() && expand_inlined()) { |
+ // Traverse inlined frames. |
+ for (InlinedFunctionsIterator it(code, pc); !it.Done(); it.Advance()) { |
+ function = it.function(); |
+ code = it.code(); |
+ ASSERT(function.raw() == code.function()); |
+ uword pc = it.pc(); |
+ ASSERT(pc != 0); |
+ ASSERT(code.EntryPoint() <= pc); |
+ ASSERT(pc < (code.EntryPoint() + code.Size())); |
+ |
+ if (frame_count == frame_index) { |
+ *function_name = function.QualifiedUserVisibleName(); |
rmacnak
2013/10/30 16:52:45
Might allocate.
|
+ const Script& script = Script::Handle(isolate, function.script()); |
+ *script_url = script.url(); |
+ const intptr_t token_pos = code.GetTokenIndexOfPC(pc); |
+ if (token_pos >= 0) { |
+ if (script.HasSource()) { |
+ script.GetTokenLocation(token_pos, line_number, col_num); |
+ } else { |
+ script.GetTokenLocation(token_pos, line_number, NULL); |
+ *col_num = -1; |
+ } |
+ } |
+ return true; |
+ } |
+ frame_count++; |
+ } |
+ } else { |
+ if (frame_count == frame_index) { |
+ *function_name = function.QualifiedUserVisibleName(); |
rmacnak
2013/10/30 16:52:45
Might allocate.
|
+ const Script& script = Script::Handle(isolate, function.script()); |
+ *script_url = script.url(); |
+ const intptr_t token_pos = code.GetTokenIndexOfPC(pc); |
+ if (token_pos >= 0) { |
+ if (script.HasSource()) { |
+ script.GetTokenLocation(token_pos, line_number, col_num); |
+ } else { |
+ script.GetTokenLocation(token_pos, line_number, NULL); |
+ *col_num = -1; |
+ } |
+ } |
+ return true; |
+ } |
+ frame_count++; |
+ } |
+ } |
+ } |
+ return false; |
+} |
+ |
void JSRegExp::set_pattern(const String& pattern) const { |
StorePointer(&raw_ptr()->pattern_, pattern.raw()); |