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

Side by Side Diff: src/profile-generator.cc

Issue 18316004: Correctly report callstack when current function is FunctionCall builtin (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Use unresolved function Created 7 years, 5 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 | « src/profile-generator.h ('k') | src/profile-generator-inl.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after
228 || (tag_ == entry->tag_ 228 || (tag_ == entry->tag_
229 && shared_id_ == entry->shared_id_ 229 && shared_id_ == entry->shared_id_
230 && (shared_id_ != 0 230 && (shared_id_ != 0
231 || (name_prefix_ == entry->name_prefix_ 231 || (name_prefix_ == entry->name_prefix_
232 && name_ == entry->name_ 232 && name_ == entry->name_
233 && resource_name_ == entry->resource_name_ 233 && resource_name_ == entry->resource_name_
234 && line_number_ == entry->line_number_))); 234 && line_number_ == entry->line_number_)));
235 } 235 }
236 236
237 237
238 void CodeEntry::SetBuiltinId(Builtins::Name id) {
239 tag_ = Logger::BUILTIN_TAG;
240 builtin_id_ = id;
241 }
242
243
238 ProfileNode* ProfileNode::FindChild(CodeEntry* entry) { 244 ProfileNode* ProfileNode::FindChild(CodeEntry* entry) {
239 HashMap::Entry* map_entry = 245 HashMap::Entry* map_entry =
240 children_.Lookup(entry, CodeEntryHash(entry), false); 246 children_.Lookup(entry, CodeEntryHash(entry), false);
241 return map_entry != NULL ? 247 return map_entry != NULL ?
242 reinterpret_cast<ProfileNode*>(map_entry->value) : NULL; 248 reinterpret_cast<ProfileNode*>(map_entry->value) : NULL;
243 } 249 }
244 250
245 251
246 ProfileNode* ProfileNode::FindOrAddChild(CodeEntry* entry) { 252 ProfileNode* ProfileNode::FindOrAddChild(CodeEntry* entry) {
247 HashMap::Entry* map_entry = 253 HashMap::Entry* map_entry =
(...skipping 592 matching lines...) Expand 10 before | Expand all | Expand 10 after
840 static_cast<unsigned>(kWallTimeQueryIntervalMs * ticks_per_ms_); 846 static_cast<unsigned>(kWallTimeQueryIntervalMs * ticks_per_ms_);
841 } 847 }
842 848
843 849
844 const char* const ProfileGenerator::kAnonymousFunctionName = 850 const char* const ProfileGenerator::kAnonymousFunctionName =
845 "(anonymous function)"; 851 "(anonymous function)";
846 const char* const ProfileGenerator::kProgramEntryName = 852 const char* const ProfileGenerator::kProgramEntryName =
847 "(program)"; 853 "(program)";
848 const char* const ProfileGenerator::kGarbageCollectorEntryName = 854 const char* const ProfileGenerator::kGarbageCollectorEntryName =
849 "(garbage collector)"; 855 "(garbage collector)";
856 const char* const ProfileGenerator::kUnresolvedFunctionName =
857 "(unresolved function)";
850 858
851 859
852 ProfileGenerator::ProfileGenerator(CpuProfilesCollection* profiles) 860 ProfileGenerator::ProfileGenerator(CpuProfilesCollection* profiles)
853 : profiles_(profiles), 861 : profiles_(profiles),
854 program_entry_( 862 program_entry_(
855 profiles->NewCodeEntry(Logger::FUNCTION_TAG, kProgramEntryName)), 863 profiles->NewCodeEntry(Logger::FUNCTION_TAG, kProgramEntryName)),
856 gc_entry_( 864 gc_entry_(
857 profiles->NewCodeEntry(Logger::BUILTIN_TAG, 865 profiles->NewCodeEntry(Logger::BUILTIN_TAG,
858 kGarbageCollectorEntryName)) { 866 kGarbageCollectorEntryName)),
867 unresolved_entry_(
868 profiles->NewCodeEntry(Logger::FUNCTION_TAG,
869 kUnresolvedFunctionName)) {
859 } 870 }
860 871
861 872
862 void ProfileGenerator::RecordTickSample(const TickSample& sample) { 873 void ProfileGenerator::RecordTickSample(const TickSample& sample) {
863 // Allocate space for stack frames + pc + function + vm-state. 874 // Allocate space for stack frames + pc + function + vm-state.
864 ScopedVector<CodeEntry*> entries(sample.frames_count + 3); 875 ScopedVector<CodeEntry*> entries(sample.frames_count + 3);
865 // As actual number of decoded code entries may vary, initialize 876 // As actual number of decoded code entries may vary, initialize
866 // entries vector with NULL values. 877 // entries vector with NULL values.
867 CodeEntry** entry = entries.start(); 878 CodeEntry** entry = entries.start();
868 memset(entry, 0, entries.length() * sizeof(*entry)); 879 memset(entry, 0, entries.length() * sizeof(*entry));
869 if (sample.pc != NULL) { 880 if (sample.pc != NULL) {
870 Address start;
871 CodeEntry* pc_entry = code_map_.FindEntry(sample.pc, &start);
872 // If pc is in the function code before it set up stack frame or after the
873 // frame was destroyed SafeStackFrameIterator incorrectly thinks that
874 // ebp contains return address of the current function and skips caller's
875 // frame. Check for this case and just skip such samples.
876 if (pc_entry) {
877 List<OffsetRange>* ranges = pc_entry->no_frame_ranges();
878 if (ranges) {
879 Code* code = Code::cast(HeapObject::FromAddress(start));
880 int pc_offset = static_cast<int>(sample.pc - code->instruction_start());
881 for (int i = 0; i < ranges->length(); i++) {
882 OffsetRange& range = ranges->at(i);
883 if (range.from <= pc_offset && pc_offset < range.to) {
884 return;
885 }
886 }
887 }
888 }
889 *entry++ = pc_entry;
890
891 if (sample.has_external_callback) { 881 if (sample.has_external_callback) {
892 // Don't use PC when in external callback code, as it can point 882 // Don't use PC when in external callback code, as it can point
893 // inside callback's code, and we will erroneously report 883 // inside callback's code, and we will erroneously report
894 // that a callback calls itself. 884 // that a callback calls itself.
895 *(entries.start()) = NULL;
896 *entry++ = code_map_.FindEntry(sample.external_callback); 885 *entry++ = code_map_.FindEntry(sample.external_callback);
886 } else {
887 Address start;
888 CodeEntry* pc_entry = code_map_.FindEntry(sample.pc, &start);
889 // If pc is in the function code before it set up stack frame or after the
890 // frame was destroyed SafeStackFrameIterator incorrectly thinks that
891 // ebp contains return address of the current function and skips caller's
892 // frame. Check for this case and just skip such samples.
893 if (pc_entry) {
894 List<OffsetRange>* ranges = pc_entry->no_frame_ranges();
895 if (ranges) {
896 Code* code = Code::cast(HeapObject::FromAddress(start));
897 int pc_offset = static_cast<int>(
898 sample.pc - code->instruction_start());
899 for (int i = 0; i < ranges->length(); i++) {
900 OffsetRange& range = ranges->at(i);
901 if (range.from <= pc_offset && pc_offset < range.to) {
902 return;
903 }
904 }
905 }
906 *entry++ = pc_entry;
907
908 if (pc_entry->builtin_id() == Builtins::kFunctionCall) {
909 // When current function is FunctionCall builtin tos is sometimes
910 // address of the function that invoked it but sometimes it's one
911 // of the arguments. We simply replace the frame with 'unknown' entry.
912 *entry++ = unresolved_entry_;
913 }
914 }
897 } 915 }
898 916
899 for (const Address* stack_pos = sample.stack, 917 for (const Address* stack_pos = sample.stack,
900 *stack_end = stack_pos + sample.frames_count; 918 *stack_end = stack_pos + sample.frames_count;
901 stack_pos != stack_end; 919 stack_pos != stack_end;
902 ++stack_pos) { 920 ++stack_pos) {
903 *entry++ = code_map_.FindEntry(*stack_pos); 921 *entry++ = code_map_.FindEntry(*stack_pos);
904 } 922 }
905 } 923 }
906 924
907 if (FLAG_prof_browser_mode) { 925 if (FLAG_prof_browser_mode) {
908 bool no_symbolized_entries = true; 926 bool no_symbolized_entries = true;
909 for (CodeEntry** e = entries.start(); e != entry; ++e) { 927 for (CodeEntry** e = entries.start(); e != entry; ++e) {
910 if (*e != NULL) { 928 if (*e != NULL) {
911 no_symbolized_entries = false; 929 no_symbolized_entries = false;
912 break; 930 break;
913 } 931 }
914 } 932 }
915 // If no frames were symbolized, put the VM state entry in. 933 // If no frames were symbolized, put the VM state entry in.
916 if (no_symbolized_entries) { 934 if (no_symbolized_entries) {
917 *entry++ = EntryForVMState(sample.state); 935 *entry++ = EntryForVMState(sample.state);
918 } 936 }
919 } 937 }
920 938
921 profiles_->AddPathToCurrentProfiles(entries); 939 profiles_->AddPathToCurrentProfiles(entries);
922 } 940 }
923 941
924 942
925 } } // namespace v8::internal 943 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/profile-generator.h ('k') | src/profile-generator-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698