| OLD | NEW |
| 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/become.h" | 10 #include "vm/become.h" |
| (...skipping 22245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 22256 return reinterpret_cast<RawClosure*>(raw); | 22256 return reinterpret_cast<RawClosure*>(raw); |
| 22257 } | 22257 } |
| 22258 | 22258 |
| 22259 | 22259 |
| 22260 intptr_t StackTrace::Length() const { | 22260 intptr_t StackTrace::Length() const { |
| 22261 const Array& code_array = Array::Handle(raw_ptr()->code_array_); | 22261 const Array& code_array = Array::Handle(raw_ptr()->code_array_); |
| 22262 return code_array.Length(); | 22262 return code_array.Length(); |
| 22263 } | 22263 } |
| 22264 | 22264 |
| 22265 | 22265 |
| 22266 RawFunction* StackTrace::FunctionAtFrame(intptr_t frame_index) const { | |
| 22267 const Code& code = Code::Handle(CodeAtFrame(frame_index)); | |
| 22268 return code.IsNull() ? Function::null() : code.function(); | |
| 22269 } | |
| 22270 | |
| 22271 | |
| 22272 RawCode* StackTrace::CodeAtFrame(intptr_t frame_index) const { | 22266 RawCode* StackTrace::CodeAtFrame(intptr_t frame_index) const { |
| 22273 const Array& code_array = Array::Handle(raw_ptr()->code_array_); | 22267 const Array& code_array = Array::Handle(raw_ptr()->code_array_); |
| 22274 return reinterpret_cast<RawCode*>(code_array.At(frame_index)); | 22268 return reinterpret_cast<RawCode*>(code_array.At(frame_index)); |
| 22275 } | 22269 } |
| 22276 | 22270 |
| 22277 | 22271 |
| 22278 void StackTrace::SetCodeAtFrame(intptr_t frame_index, const Code& code) const { | 22272 void StackTrace::SetCodeAtFrame(intptr_t frame_index, const Code& code) const { |
| 22279 const Array& code_array = Array::Handle(raw_ptr()->code_array_); | 22273 const Array& code_array = Array::Handle(raw_ptr()->code_array_); |
| 22280 code_array.SetAt(frame_index, code); | 22274 code_array.SetAt(frame_index, code); |
| 22281 } | 22275 } |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 22330 return result.raw(); | 22324 return result.raw(); |
| 22331 } | 22325 } |
| 22332 | 22326 |
| 22333 | 22327 |
| 22334 const char* StackTrace::ToCString() const { | 22328 const char* StackTrace::ToCString() const { |
| 22335 intptr_t idx = 0; | 22329 intptr_t idx = 0; |
| 22336 return ToCStringInternal(&idx); | 22330 return ToCStringInternal(&idx); |
| 22337 } | 22331 } |
| 22338 | 22332 |
| 22339 | 22333 |
| 22340 static intptr_t PrintOneStackTrace(Zone* zone, | 22334 static void PrintStackTraceFrame(Zone* zone, |
| 22341 GrowableArray<char*>* frame_strings, | 22335 TextBuffer* buffer, |
| 22342 uword pc, | 22336 const Function& function, |
| 22343 const Function& function, | 22337 TokenPosition token_pos, |
| 22344 const Code& code, | 22338 intptr_t frame_index) { |
| 22345 intptr_t frame_index) { | |
| 22346 const TokenPosition token_pos = code.GetTokenIndexOfPC(pc); | |
| 22347 const Script& script = Script::Handle(zone, function.script()); | 22339 const Script& script = Script::Handle(zone, function.script()); |
| 22348 const String& function_name = | 22340 const String& function_name = |
| 22349 String::Handle(zone, function.QualifiedUserVisibleName()); | 22341 String::Handle(zone, function.QualifiedUserVisibleName()); |
| 22350 const String& url = String::Handle( | 22342 const String& url = String::Handle( |
| 22351 zone, script.IsNull() ? String::New("Kernel") : script.url()); | 22343 zone, script.IsNull() ? String::New("Kernel") : script.url()); |
| 22352 intptr_t line = -1; | 22344 intptr_t line = -1; |
| 22353 intptr_t column = -1; | 22345 intptr_t column = -1; |
| 22354 if (!script.IsNull() && token_pos.IsReal()) { | 22346 if (!script.IsNull() && token_pos.IsReal()) { |
| 22355 if (script.HasSource() || script.kind() == RawScript::kKernelTag) { | 22347 if (script.HasSource() || script.kind() == RawScript::kKernelTag) { |
| 22356 script.GetTokenLocation(token_pos, &line, &column); | 22348 script.GetTokenLocation(token_pos, &line, &column); |
| 22357 } else { | 22349 } else { |
| 22358 script.GetTokenLocation(token_pos, &line, NULL); | 22350 script.GetTokenLocation(token_pos, &line, NULL); |
| 22359 } | 22351 } |
| 22360 } | 22352 } |
| 22361 char* chars = NULL; | |
| 22362 if (column >= 0) { | 22353 if (column >= 0) { |
| 22363 chars = | 22354 buffer->Printf("#%-6" Pd " %s (%s:%" Pd ":%" Pd ")\n", frame_index, |
| 22364 OS::SCreate(zone, "#%-6" Pd " %s (%s:%" Pd ":%" Pd ")\n", frame_index, | 22355 function_name.ToCString(), url.ToCString(), line, column); |
| 22365 function_name.ToCString(), url.ToCString(), line, column); | |
| 22366 } else if (line >= 0) { | 22356 } else if (line >= 0) { |
| 22367 chars = OS::SCreate(zone, "#%-6" Pd " %s (%s:%" Pd ")\n", frame_index, | 22357 buffer->Printf("#%-6" Pd " %s (%s:%" Pd ")\n", frame_index, |
| 22368 function_name.ToCString(), url.ToCString(), line); | 22358 function_name.ToCString(), url.ToCString(), line); |
| 22369 } else { | 22359 } else { |
| 22370 chars = OS::SCreate(zone, "#%-6" Pd " %s (%s)\n", frame_index, | 22360 buffer->Printf("#%-6" Pd " %s (%s)\n", frame_index, |
| 22371 function_name.ToCString(), url.ToCString()); | 22361 function_name.ToCString(), url.ToCString()); |
| 22372 } | 22362 } |
| 22373 frame_strings->Add(chars); | |
| 22374 return strlen(chars); | |
| 22375 } | 22363 } |
| 22376 | 22364 |
| 22377 | 22365 |
| 22378 const char* StackTrace::ToCStringInternal(intptr_t* frame_index, | 22366 const char* StackTrace::ToCStringInternal(intptr_t* frame_index, |
| 22379 intptr_t max_frames) const { | 22367 intptr_t max_frames) const { |
| 22380 Zone* zone = Thread::Current()->zone(); | 22368 Zone* zone = Thread::Current()->zone(); |
| 22381 Function& function = Function::Handle(); | 22369 Function& function = Function::Handle(zone); |
| 22382 Code& code = Code::Handle(); | 22370 Code& code = Code::Handle(zone); |
| 22371 GrowableArray<const Function*> inlined_functions; |
| 22372 GrowableArray<TokenPosition> inlined_token_positions; |
| 22373 TextBuffer buffer(1024); |
| 22374 |
| 22383 // Iterate through the stack frames and create C string description | 22375 // Iterate through the stack frames and create C string description |
| 22384 // for each frame. | 22376 // for each frame. |
| 22385 intptr_t total_len = 0; | |
| 22386 GrowableArray<char*> frame_strings; | |
| 22387 for (intptr_t i = 0; (i < Length()) && (*frame_index < max_frames); i++) { | 22377 for (intptr_t i = 0; (i < Length()) && (*frame_index < max_frames); i++) { |
| 22388 function = FunctionAtFrame(i); | 22378 code = CodeAtFrame(i); |
| 22389 if (function.IsNull()) { | 22379 if (code.IsNull()) { |
| 22390 // Check for a null function, which indicates a gap in a StackOverflow or | 22380 // Check for a null function, which indicates a gap in a StackOverflow or |
| 22391 // OutOfMemory trace. | 22381 // OutOfMemory trace. |
| 22392 if ((i < (Length() - 1)) && | 22382 if ((i < (Length() - 1)) && (CodeAtFrame(i + 1) != Code::null())) { |
| 22393 (FunctionAtFrame(i + 1) != Function::null())) { | 22383 buffer.AddString("...\n...\n"); |
| 22394 const char* kTruncated = "...\n...\n"; | |
| 22395 intptr_t truncated_len = strlen(kTruncated) + 1; | |
| 22396 char* chars = zone->Alloc<char>(truncated_len); | |
| 22397 OS::SNPrint(chars, truncated_len, "%s", kTruncated); | |
| 22398 frame_strings.Add(chars); | |
| 22399 total_len += truncated_len; | |
| 22400 ASSERT(PcOffsetAtFrame(i) != Smi::null()); | 22384 ASSERT(PcOffsetAtFrame(i) != Smi::null()); |
| 22401 // To account for gap frames. | 22385 // To account for gap frames. |
| 22402 (*frame_index) += Smi::Value(PcOffsetAtFrame(i)); | 22386 (*frame_index) += Smi::Value(PcOffsetAtFrame(i)); |
| 22403 } | 22387 } |
| 22404 } else { | 22388 } else { |
| 22405 code = CodeAtFrame(i); | 22389 // Stub code is not included in the stack trace. |
| 22406 ASSERT(function.raw() == code.function()); | 22390 ASSERT(code.IsFunctionCode()); |
| 22407 uword pc = code.PayloadStart() + Smi::Value(PcOffsetAtFrame(i)); | 22391 |
| 22392 intptr_t pc_offset = Smi::Value(PcOffsetAtFrame(i)); |
| 22408 if (code.is_optimized() && expand_inlined() && | 22393 if (code.is_optimized() && expand_inlined() && |
| 22409 !FLAG_precompiled_runtime) { | 22394 !FLAG_precompiled_runtime) { |
| 22410 // Traverse inlined frames. | 22395 // Convert return address to call address. Compare the profiler's |
| 22411 for (InlinedFunctionsIterator it(code, pc); | 22396 // OffsetForPC. |
| 22412 !it.Done() && (*frame_index < max_frames); it.Advance()) { | 22397 intptr_t effective_pc_offset = pc_offset - 1; |
| 22413 function = it.function(); | 22398 code.GetInlinedFunctionsAt(effective_pc_offset, &inlined_functions, |
| 22414 if (function.is_visible() || FLAG_show_invisible_frames) { | 22399 &inlined_token_positions); |
| 22415 code = it.code(); | 22400 ASSERT(inlined_functions.length() >= 1); |
| 22416 ASSERT(function.raw() == code.function()); | 22401 for (intptr_t j = inlined_functions.length() - 1; j >= 0; j--) { |
| 22417 uword pc = it.pc(); | 22402 if (inlined_functions[j]->is_visible() || |
| 22418 ASSERT(pc != 0); | 22403 FLAG_show_invisible_frames) { |
| 22419 ASSERT(code.PayloadStart() <= pc); | 22404 PrintStackTraceFrame(zone, &buffer, *inlined_functions[j], |
| 22420 ASSERT(pc < (code.PayloadStart() + code.Size())); | 22405 inlined_token_positions[j], *frame_index); |
| 22421 total_len += PrintOneStackTrace(zone, &frame_strings, pc, function, | 22406 (*frame_index)++; |
| 22422 code, *frame_index); | |
| 22423 (*frame_index)++; // To account for inlined frames. | |
| 22424 } | 22407 } |
| 22425 } | 22408 } |
| 22426 } else { | 22409 } else { |
| 22410 function = code.function(); |
| 22427 if (function.is_visible() || FLAG_show_invisible_frames) { | 22411 if (function.is_visible() || FLAG_show_invisible_frames) { |
| 22428 total_len += PrintOneStackTrace(zone, &frame_strings, pc, function, | 22412 uword pc = code.PayloadStart() + pc_offset; |
| 22429 code, *frame_index); | 22413 const TokenPosition token_pos = code.GetTokenIndexOfPC(pc); |
| 22414 PrintStackTraceFrame(zone, &buffer, function, token_pos, |
| 22415 *frame_index); |
| 22430 (*frame_index)++; | 22416 (*frame_index)++; |
| 22431 } | 22417 } |
| 22432 } | 22418 } |
| 22433 } | 22419 } |
| 22434 } | 22420 } |
| 22435 | 22421 |
| 22436 // Now concatenate the frame descriptions into a single C string. | 22422 return buffer.Steal(); |
| 22437 char* chars = zone->Alloc<char>(total_len + 1); | |
| 22438 intptr_t index = 0; | |
| 22439 for (intptr_t i = 0; i < frame_strings.length(); i++) { | |
| 22440 index += OS::SNPrint((chars + index), (total_len + 1 - index), "%s", | |
| 22441 frame_strings[i]); | |
| 22442 } | |
| 22443 chars[total_len] = '\0'; | |
| 22444 return chars; | |
| 22445 } | 22423 } |
| 22446 | 22424 |
| 22447 | 22425 |
| 22448 void RegExp::set_pattern(const String& pattern) const { | 22426 void RegExp::set_pattern(const String& pattern) const { |
| 22449 StorePointer(&raw_ptr()->pattern_, pattern.raw()); | 22427 StorePointer(&raw_ptr()->pattern_, pattern.raw()); |
| 22450 } | 22428 } |
| 22451 | 22429 |
| 22452 | 22430 |
| 22453 void RegExp::set_function(intptr_t cid, | 22431 void RegExp::set_function(intptr_t cid, |
| 22454 bool sticky, | 22432 bool sticky, |
| (...skipping 304 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 22759 return UserTag::null(); | 22737 return UserTag::null(); |
| 22760 } | 22738 } |
| 22761 | 22739 |
| 22762 | 22740 |
| 22763 const char* UserTag::ToCString() const { | 22741 const char* UserTag::ToCString() const { |
| 22764 const String& tag_label = String::Handle(label()); | 22742 const String& tag_label = String::Handle(label()); |
| 22765 return tag_label.ToCString(); | 22743 return tag_label.ToCString(); |
| 22766 } | 22744 } |
| 22767 | 22745 |
| 22768 } // namespace dart | 22746 } // namespace dart |
| OLD | NEW |