| 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 29 matching lines...) Expand all Loading... |
| 40 #include "vm/scopes.h" | 40 #include "vm/scopes.h" |
| 41 #include "vm/stack_frame.h" | 41 #include "vm/stack_frame.h" |
| 42 #include "vm/symbols.h" | 42 #include "vm/symbols.h" |
| 43 #include "vm/tags.h" | 43 #include "vm/tags.h" |
| 44 #include "vm/thread_registry.h" | 44 #include "vm/thread_registry.h" |
| 45 #include "vm/timeline.h" | 45 #include "vm/timeline.h" |
| 46 #include "vm/timer.h" | 46 #include "vm/timer.h" |
| 47 #include "vm/type_table.h" | 47 #include "vm/type_table.h" |
| 48 #include "vm/unicode.h" | 48 #include "vm/unicode.h" |
| 49 #include "vm/weak_code.h" | 49 #include "vm/weak_code.h" |
| 50 #include "vm/zone_text_buffer.h" |
| 50 | 51 |
| 51 namespace dart { | 52 namespace dart { |
| 52 | 53 |
| 53 DEFINE_FLAG(int, | 54 DEFINE_FLAG(int, |
| 54 huge_method_cutoff_in_code_size, | 55 huge_method_cutoff_in_code_size, |
| 55 200000, | 56 200000, |
| 56 "Huge method cutoff in unoptimized code size (in bytes)."); | 57 "Huge method cutoff in unoptimized code size (in bytes)."); |
| 57 DEFINE_FLAG( | 58 DEFINE_FLAG( |
| 58 bool, | 59 bool, |
| 59 overlap_type_arguments, | 60 overlap_type_arguments, |
| (...skipping 14393 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 14453 // If we are missing a stack map, this must either be unoptimized code, or | 14454 // If we are missing a stack map, this must either be unoptimized code, or |
| 14454 // the entry to an osr function. (In which case all stack slots are | 14455 // the entry to an osr function. (In which case all stack slots are |
| 14455 // considered to have tagged pointers.) | 14456 // considered to have tagged pointers.) |
| 14456 // Running with --verify-on-transition should hit this. | 14457 // Running with --verify-on-transition should hit this. |
| 14457 ASSERT(!is_optimized() || | 14458 ASSERT(!is_optimized() || |
| 14458 (pc_offset == UncheckedEntryPoint() - PayloadStart())); | 14459 (pc_offset == UncheckedEntryPoint() - PayloadStart())); |
| 14459 return StackMap::null(); | 14460 return StackMap::null(); |
| 14460 } | 14461 } |
| 14461 | 14462 |
| 14462 | 14463 |
| 14463 void Code::GetInlinedFunctionsAt( | 14464 void Code::GetInlinedFunctionsAtInstruction( |
| 14464 intptr_t pc_offset, | 14465 intptr_t pc_offset, |
| 14465 GrowableArray<const Function*>* functions, | 14466 GrowableArray<const Function*>* functions, |
| 14466 GrowableArray<TokenPosition>* token_positions) const { | 14467 GrowableArray<TokenPosition>* token_positions) const { |
| 14467 const CodeSourceMap& map = CodeSourceMap::Handle(code_source_map()); | 14468 const CodeSourceMap& map = CodeSourceMap::Handle(code_source_map()); |
| 14468 if (map.IsNull()) { | 14469 if (map.IsNull()) { |
| 14469 // Stub code. | 14470 // Stub code. |
| 14470 return; | 14471 return; |
| 14471 } | 14472 } |
| 14472 const Array& id_map = Array::Handle(inlined_id_to_function()); | 14473 const Array& id_map = Array::Handle(inlined_id_to_function()); |
| 14473 const Function& root = Function::Handle(function()); | 14474 const Function& root = Function::Handle(function()); |
| (...skipping 7782 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 22256 return reinterpret_cast<RawClosure*>(raw); | 22257 return reinterpret_cast<RawClosure*>(raw); |
| 22257 } | 22258 } |
| 22258 | 22259 |
| 22259 | 22260 |
| 22260 intptr_t StackTrace::Length() const { | 22261 intptr_t StackTrace::Length() const { |
| 22261 const Array& code_array = Array::Handle(raw_ptr()->code_array_); | 22262 const Array& code_array = Array::Handle(raw_ptr()->code_array_); |
| 22262 return code_array.Length(); | 22263 return code_array.Length(); |
| 22263 } | 22264 } |
| 22264 | 22265 |
| 22265 | 22266 |
| 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 { | 22267 RawCode* StackTrace::CodeAtFrame(intptr_t frame_index) const { |
| 22273 const Array& code_array = Array::Handle(raw_ptr()->code_array_); | 22268 const Array& code_array = Array::Handle(raw_ptr()->code_array_); |
| 22274 return reinterpret_cast<RawCode*>(code_array.At(frame_index)); | 22269 return reinterpret_cast<RawCode*>(code_array.At(frame_index)); |
| 22275 } | 22270 } |
| 22276 | 22271 |
| 22277 | 22272 |
| 22278 void StackTrace::SetCodeAtFrame(intptr_t frame_index, const Code& code) const { | 22273 void StackTrace::SetCodeAtFrame(intptr_t frame_index, const Code& code) const { |
| 22279 const Array& code_array = Array::Handle(raw_ptr()->code_array_); | 22274 const Array& code_array = Array::Handle(raw_ptr()->code_array_); |
| 22280 code_array.SetAt(frame_index, code); | 22275 code_array.SetAt(frame_index, code); |
| 22281 } | 22276 } |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 22354 return result.raw(); | 22349 return result.raw(); |
| 22355 } | 22350 } |
| 22356 | 22351 |
| 22357 | 22352 |
| 22358 const char* StackTrace::ToCString() const { | 22353 const char* StackTrace::ToCString() const { |
| 22359 intptr_t idx = 0; | 22354 intptr_t idx = 0; |
| 22360 return ToCStringInternal(*this, &idx); | 22355 return ToCStringInternal(*this, &idx); |
| 22361 } | 22356 } |
| 22362 | 22357 |
| 22363 | 22358 |
| 22364 static intptr_t PrintOneStackTrace(Zone* zone, | 22359 static void PrintStackTraceFrame(Zone* zone, |
| 22365 GrowableArray<char*>* frame_strings, | 22360 ZoneTextBuffer* buffer, |
| 22366 uword pc, | 22361 const Function& function, |
| 22367 const Function& function, | 22362 TokenPosition token_pos, |
| 22368 const Code& code, | 22363 intptr_t frame_index) { |
| 22369 intptr_t frame_index) { | |
| 22370 const TokenPosition token_pos = code.GetTokenIndexOfPC(pc); | |
| 22371 const Script& script = Script::Handle(zone, function.script()); | 22364 const Script& script = Script::Handle(zone, function.script()); |
| 22372 const String& function_name = | 22365 const String& function_name = |
| 22373 String::Handle(zone, function.QualifiedUserVisibleName()); | 22366 String::Handle(zone, function.QualifiedUserVisibleName()); |
| 22374 const String& url = String::Handle( | 22367 const String& url = String::Handle( |
| 22375 zone, script.IsNull() ? String::New("Kernel") : script.url()); | 22368 zone, script.IsNull() ? String::New("Kernel") : script.url()); |
| 22376 intptr_t line = -1; | 22369 intptr_t line = -1; |
| 22377 intptr_t column = -1; | 22370 intptr_t column = -1; |
| 22378 if (!script.IsNull() && token_pos.IsReal()) { | 22371 if (!script.IsNull() && token_pos.IsReal()) { |
| 22379 if (script.HasSource() || script.kind() == RawScript::kKernelTag) { | 22372 if (script.HasSource() || script.kind() == RawScript::kKernelTag) { |
| 22380 script.GetTokenLocation(token_pos, &line, &column); | 22373 script.GetTokenLocation(token_pos, &line, &column); |
| 22381 } else { | 22374 } else { |
| 22382 script.GetTokenLocation(token_pos, &line, NULL); | 22375 script.GetTokenLocation(token_pos, &line, NULL); |
| 22383 } | 22376 } |
| 22384 } | 22377 } |
| 22385 char* chars = NULL; | |
| 22386 if (column >= 0) { | 22378 if (column >= 0) { |
| 22387 chars = | 22379 buffer->Printf("#%-6" Pd " %s (%s:%" Pd ":%" Pd ")\n", frame_index, |
| 22388 OS::SCreate(zone, "#%-6" Pd " %s (%s:%" Pd ":%" Pd ")\n", frame_index, | 22380 function_name.ToCString(), url.ToCString(), line, column); |
| 22389 function_name.ToCString(), url.ToCString(), line, column); | |
| 22390 } else if (line >= 0) { | 22381 } else if (line >= 0) { |
| 22391 chars = OS::SCreate(zone, "#%-6" Pd " %s (%s:%" Pd ")\n", frame_index, | 22382 buffer->Printf("#%-6" Pd " %s (%s:%" Pd ")\n", frame_index, |
| 22392 function_name.ToCString(), url.ToCString(), line); | 22383 function_name.ToCString(), url.ToCString(), line); |
| 22393 } else { | 22384 } else { |
| 22394 chars = OS::SCreate(zone, "#%-6" Pd " %s (%s)\n", frame_index, | 22385 buffer->Printf("#%-6" Pd " %s (%s)\n", frame_index, |
| 22395 function_name.ToCString(), url.ToCString()); | 22386 function_name.ToCString(), url.ToCString()); |
| 22396 } | 22387 } |
| 22397 frame_strings->Add(chars); | |
| 22398 return strlen(chars); | |
| 22399 } | 22388 } |
| 22400 | 22389 |
| 22401 | 22390 |
| 22402 const char* StackTrace::ToCStringInternal(const StackTrace& stack_trace_in, | 22391 const char* StackTrace::ToCStringInternal(const StackTrace& stack_trace_in, |
| 22403 intptr_t* frame_index, | 22392 intptr_t* frame_index, |
| 22404 intptr_t max_frames) { | 22393 intptr_t max_frames) { |
| 22405 Zone* zone = Thread::Current()->zone(); | 22394 Zone* zone = Thread::Current()->zone(); |
| 22395 StackTrace& stack_trace = StackTrace::Handle(zone, stack_trace_in.raw()); |
| 22406 Function& function = Function::Handle(zone); | 22396 Function& function = Function::Handle(zone); |
| 22407 Code& code = Code::Handle(zone); | 22397 Code& code = Code::Handle(zone); |
| 22398 GrowableArray<const Function*> inlined_functions; |
| 22399 GrowableArray<TokenPosition> inlined_token_positions; |
| 22400 ZoneTextBuffer buffer(zone, 1024); |
| 22401 |
| 22408 // Iterate through the stack frames and create C string description | 22402 // Iterate through the stack frames and create C string description |
| 22409 // for each frame. | 22403 // for each frame. |
| 22410 intptr_t total_len = 0; | 22404 do { |
| 22411 GrowableArray<char*> frame_strings; | |
| 22412 StackTrace& stack_trace = StackTrace::Handle(zone); | |
| 22413 stack_trace ^= stack_trace_in.raw(); | |
| 22414 while (!stack_trace.IsNull()) { | |
| 22415 for (intptr_t i = 0; | 22405 for (intptr_t i = 0; |
| 22416 (i < stack_trace.Length()) && (*frame_index < max_frames); i++) { | 22406 (i < stack_trace.Length()) && (*frame_index < max_frames); i++) { |
| 22417 code = stack_trace.CodeAtFrame(i); | 22407 code = stack_trace.CodeAtFrame(i); |
| 22418 function = stack_trace.FunctionAtFrame(i); | 22408 if (code.IsNull()) { |
| 22419 if (code.raw() == StubCode::AsynchronousGapMarker_entry()->code()) { | |
| 22420 const char* kAsyncSuspension = "<asynchronous suspension>\n"; | |
| 22421 intptr_t async_suspension_len = strlen(kAsyncSuspension) + 1; | |
| 22422 char* chars = zone->Alloc<char>(async_suspension_len); | |
| 22423 OS::SNPrint(chars, async_suspension_len, "%s", kAsyncSuspension); | |
| 22424 frame_strings.Add(chars); | |
| 22425 total_len += async_suspension_len; | |
| 22426 } else if (function.IsNull()) { | |
| 22427 // Check for a null function, which indicates a gap in a StackOverflow | 22409 // Check for a null function, which indicates a gap in a StackOverflow |
| 22428 // or OutOfMemory trace. | 22410 // or OutOfMemory trace. |
| 22429 if ((i < (stack_trace.Length() - 1)) && | 22411 if ((i < (stack_trace.Length() - 1)) && |
| 22430 (stack_trace.FunctionAtFrame(i + 1) != Function::null())) { | 22412 (stack_trace.CodeAtFrame(i + 1) != Code::null())) { |
| 22431 const char* kTruncated = "...\n...\n"; | 22413 buffer.AddString("...\n...\n"); |
| 22432 intptr_t truncated_len = strlen(kTruncated) + 1; | |
| 22433 char* chars = zone->Alloc<char>(truncated_len); | |
| 22434 OS::SNPrint(chars, truncated_len, "%s", kTruncated); | |
| 22435 frame_strings.Add(chars); | |
| 22436 total_len += truncated_len; | |
| 22437 ASSERT(stack_trace.PcOffsetAtFrame(i) != Smi::null()); | 22414 ASSERT(stack_trace.PcOffsetAtFrame(i) != Smi::null()); |
| 22438 // To account for gap frames. | 22415 // To account for gap frames. |
| 22439 (*frame_index) += Smi::Value(stack_trace.PcOffsetAtFrame(i)); | 22416 (*frame_index) += Smi::Value(stack_trace.PcOffsetAtFrame(i)); |
| 22440 } | 22417 } |
| 22418 } else if (code.raw() == |
| 22419 StubCode::AsynchronousGapMarker_entry()->code()) { |
| 22420 buffer.AddString("<asynchronous suspension>\n"); |
| 22441 } else { | 22421 } else { |
| 22442 code = stack_trace.CodeAtFrame(i); | 22422 ASSERT(code.IsFunctionCode()); |
| 22443 ASSERT(function.raw() == code.function()); | 22423 intptr_t pc_offset = Smi::Value(stack_trace.PcOffsetAtFrame(i)); |
| 22444 uword pc = | |
| 22445 code.PayloadStart() + Smi::Value(stack_trace.PcOffsetAtFrame(i)); | |
| 22446 if (code.is_optimized() && stack_trace.expand_inlined() && | 22424 if (code.is_optimized() && stack_trace.expand_inlined() && |
| 22447 !FLAG_precompiled_runtime) { | 22425 !FLAG_precompiled_runtime) { |
| 22448 // Traverse inlined frames. | 22426 code.GetInlinedFunctionsAtReturnAddress(pc_offset, &inlined_functions, |
| 22449 for (InlinedFunctionsIterator it(code, pc); | 22427 &inlined_token_positions); |
| 22450 !it.Done() && (*frame_index < max_frames); it.Advance()) { | 22428 ASSERT(inlined_functions.length() >= 1); |
| 22451 function = it.function(); | 22429 for (intptr_t j = inlined_functions.length() - 1; j >= 0; j--) { |
| 22452 if (function.is_visible() || FLAG_show_invisible_frames) { | 22430 if (inlined_functions[j]->is_visible() || |
| 22453 code = it.code(); | 22431 FLAG_show_invisible_frames) { |
| 22454 ASSERT(function.raw() == code.function()); | 22432 PrintStackTraceFrame(zone, &buffer, *inlined_functions[j], |
| 22455 uword pc = it.pc(); | 22433 inlined_token_positions[j], *frame_index); |
| 22456 ASSERT(pc != 0); | 22434 (*frame_index)++; |
| 22457 ASSERT(code.PayloadStart() <= pc); | |
| 22458 ASSERT(pc < (code.PayloadStart() + code.Size())); | |
| 22459 total_len += PrintOneStackTrace(zone, &frame_strings, pc, | |
| 22460 function, code, *frame_index); | |
| 22461 (*frame_index)++; // To account for inlined frames. | |
| 22462 } | 22435 } |
| 22463 } | 22436 } |
| 22464 } else { | 22437 } else { |
| 22438 function = code.function(); |
| 22465 if (function.is_visible() || FLAG_show_invisible_frames) { | 22439 if (function.is_visible() || FLAG_show_invisible_frames) { |
| 22466 total_len += PrintOneStackTrace(zone, &frame_strings, pc, function, | 22440 uword pc = code.PayloadStart() + pc_offset; |
| 22467 code, *frame_index); | 22441 const TokenPosition token_pos = code.GetTokenIndexOfPC(pc); |
| 22442 PrintStackTraceFrame(zone, &buffer, function, token_pos, |
| 22443 *frame_index); |
| 22468 (*frame_index)++; | 22444 (*frame_index)++; |
| 22469 } | 22445 } |
| 22470 } | 22446 } |
| 22471 } | 22447 } |
| 22472 } | 22448 } |
| 22473 // Follow the link. | 22449 // Follow the link. |
| 22474 stack_trace ^= stack_trace.async_link(); | 22450 stack_trace ^= stack_trace.async_link(); |
| 22475 } | 22451 } while (!stack_trace.IsNull()); |
| 22476 | 22452 |
| 22477 // Now concatenate the frame descriptions into a single C string. | 22453 return buffer.buffer(); |
| 22478 char* chars = zone->Alloc<char>(total_len + 1); | |
| 22479 intptr_t index = 0; | |
| 22480 for (intptr_t i = 0; i < frame_strings.length(); i++) { | |
| 22481 index += OS::SNPrint((chars + index), (total_len + 1 - index), "%s", | |
| 22482 frame_strings[i]); | |
| 22483 } | |
| 22484 chars[total_len] = '\0'; | |
| 22485 return chars; | |
| 22486 } | 22454 } |
| 22487 | 22455 |
| 22488 | 22456 |
| 22489 void RegExp::set_pattern(const String& pattern) const { | 22457 void RegExp::set_pattern(const String& pattern) const { |
| 22490 StorePointer(&raw_ptr()->pattern_, pattern.raw()); | 22458 StorePointer(&raw_ptr()->pattern_, pattern.raw()); |
| 22491 } | 22459 } |
| 22492 | 22460 |
| 22493 | 22461 |
| 22494 void RegExp::set_function(intptr_t cid, | 22462 void RegExp::set_function(intptr_t cid, |
| 22495 bool sticky, | 22463 bool sticky, |
| (...skipping 304 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 22800 return UserTag::null(); | 22768 return UserTag::null(); |
| 22801 } | 22769 } |
| 22802 | 22770 |
| 22803 | 22771 |
| 22804 const char* UserTag::ToCString() const { | 22772 const char* UserTag::ToCString() const { |
| 22805 const String& tag_label = String::Handle(label()); | 22773 const String& tag_label = String::Handle(label()); |
| 22806 return tag_label.ToCString(); | 22774 return tag_label.ToCString(); |
| 22807 } | 22775 } |
| 22808 | 22776 |
| 22809 } // namespace dart | 22777 } // namespace dart |
| OLD | NEW |