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

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

Issue 18422003: Correctly report callstack when current function is FunctionCall builtin (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: 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 593 matching lines...) Expand 10 before | Expand all | Expand 10 after
841 static_cast<unsigned>(kWallTimeQueryIntervalMs * ticks_per_ms_); 847 static_cast<unsigned>(kWallTimeQueryIntervalMs * ticks_per_ms_);
842 } 848 }
843 849
844 850
845 const char* const ProfileGenerator::kAnonymousFunctionName = 851 const char* const ProfileGenerator::kAnonymousFunctionName =
846 "(anonymous function)"; 852 "(anonymous function)";
847 const char* const ProfileGenerator::kProgramEntryName = 853 const char* const ProfileGenerator::kProgramEntryName =
848 "(program)"; 854 "(program)";
849 const char* const ProfileGenerator::kGarbageCollectorEntryName = 855 const char* const ProfileGenerator::kGarbageCollectorEntryName =
850 "(garbage collector)"; 856 "(garbage collector)";
857 const char* const ProfileGenerator::kUnresolvedFunctionName =
858 "(unresolved function)";
851 859
852 860
853 ProfileGenerator::ProfileGenerator(CpuProfilesCollection* profiles) 861 ProfileGenerator::ProfileGenerator(CpuProfilesCollection* profiles)
854 : profiles_(profiles), 862 : profiles_(profiles),
855 program_entry_( 863 program_entry_(
856 profiles->NewCodeEntry(Logger::FUNCTION_TAG, kProgramEntryName)), 864 profiles->NewCodeEntry(Logger::FUNCTION_TAG, kProgramEntryName)),
857 gc_entry_( 865 gc_entry_(
858 profiles->NewCodeEntry(Logger::BUILTIN_TAG, 866 profiles->NewCodeEntry(Logger::BUILTIN_TAG,
859 kGarbageCollectorEntryName)) { 867 kGarbageCollectorEntryName)),
868 unresolved_entry_(
869 profiles->NewCodeEntry(Logger::FUNCTION_TAG,
870 kUnresolvedFunctionName)) {
860 } 871 }
861 872
862 873
863 void ProfileGenerator::RecordTickSample(const TickSample& sample) { 874 void ProfileGenerator::RecordTickSample(const TickSample& sample) {
864 // Allocate space for stack frames + pc + function + vm-state. 875 // Allocate space for stack frames + pc + function + vm-state.
865 ScopedVector<CodeEntry*> entries(sample.frames_count + 3); 876 ScopedVector<CodeEntry*> entries(sample.frames_count + 3);
866 // As actual number of decoded code entries may vary, initialize 877 // As actual number of decoded code entries may vary, initialize
867 // entries vector with NULL values. 878 // entries vector with NULL values.
868 CodeEntry** entry = entries.start(); 879 CodeEntry** entry = entries.start();
869 memset(entry, 0, entries.length() * sizeof(*entry)); 880 memset(entry, 0, entries.length() * sizeof(*entry));
870 if (sample.pc != NULL) { 881 if (sample.pc != NULL) {
871 Address start;
872 CodeEntry* pc_entry = code_map_.FindEntry(sample.pc, &start);
873 // If pc is in the function code before it set up stack frame or after the
874 // frame was destroyed SafeStackFrameIterator incorrectly thinks that
875 // ebp contains return address of the current function and skips caller's
876 // frame. Check for this case and just skip such samples.
877 if (pc_entry) {
878 List<OffsetRange>* ranges = pc_entry->no_frame_ranges();
879 if (ranges) {
880 Code* code = Code::cast(HeapObject::FromAddress(start));
881 int pc_offset = static_cast<int>(sample.pc - code->instruction_start());
882 for (int i = 0; i < ranges->length(); i++) {
883 OffsetRange& range = ranges->at(i);
884 if (range.from <= pc_offset && pc_offset < range.to) {
885 return;
886 }
887 }
888 }
889 }
890 *entry++ = pc_entry;
891
892 if (sample.has_external_callback) { 882 if (sample.has_external_callback) {
893 // Don't use PC when in external callback code, as it can point 883 // Don't use PC when in external callback code, as it can point
894 // inside callback's code, and we will erroneously report 884 // inside callback's code, and we will erroneously report
895 // that a callback calls itself. 885 // that a callback calls itself.
896 *(entries.start()) = NULL;
897 *entry++ = code_map_.FindEntry(sample.external_callback); 886 *entry++ = code_map_.FindEntry(sample.external_callback);
887 } else {
888 Address start;
889 CodeEntry* pc_entry = code_map_.FindEntry(sample.pc, &start);
890 // If pc is in the function code before it set up stack frame or after the
891 // frame was destroyed SafeStackFrameIterator incorrectly thinks that
892 // ebp contains return address of the current function and skips caller's
893 // frame. Check for this case and just skip such samples.
894 if (pc_entry) {
895 List<OffsetRange>* ranges = pc_entry->no_frame_ranges();
896 if (ranges) {
897 Code* code = Code::cast(HeapObject::FromAddress(start));
898 int pc_offset = static_cast<int>(
899 sample.pc - code->instruction_start());
900 for (int i = 0; i < ranges->length(); i++) {
901 OffsetRange& range = ranges->at(i);
902 if (range.from <= pc_offset && pc_offset < range.to) {
903 return;
904 }
905 }
906 }
907 *entry++ = pc_entry;
908
909 if (pc_entry->builtin_id() == Builtins::kFunctionCall) {
910 // When current function is FunctionCall builtin tos is sometimes
911 // address of the function that invoked it but sometimes it's one
912 // of the arguments. We simply replace the frame with 'unknown' entry.
913 *entry++ = unresolved_entry_;
914 }
915 }
898 } 916 }
899 917
900 for (const Address* stack_pos = sample.stack, 918 for (const Address* stack_pos = sample.stack,
901 *stack_end = stack_pos + sample.frames_count; 919 *stack_end = stack_pos + sample.frames_count;
902 stack_pos != stack_end; 920 stack_pos != stack_end;
903 ++stack_pos) { 921 ++stack_pos) {
904 *entry++ = code_map_.FindEntry(*stack_pos); 922 *entry++ = code_map_.FindEntry(*stack_pos);
905 } 923 }
906 } 924 }
907 925
908 if (FLAG_prof_browser_mode) { 926 if (FLAG_prof_browser_mode) {
909 bool no_symbolized_entries = true; 927 bool no_symbolized_entries = true;
910 for (CodeEntry** e = entries.start(); e != entry; ++e) { 928 for (CodeEntry** e = entries.start(); e != entry; ++e) {
911 if (*e != NULL) { 929 if (*e != NULL) {
912 no_symbolized_entries = false; 930 no_symbolized_entries = false;
913 break; 931 break;
914 } 932 }
915 } 933 }
916 // If no frames were symbolized, put the VM state entry in. 934 // If no frames were symbolized, put the VM state entry in.
917 if (no_symbolized_entries) { 935 if (no_symbolized_entries) {
918 *entry++ = EntryForVMState(sample.state); 936 *entry++ = EntryForVMState(sample.state);
919 } 937 }
920 } 938 }
921 939
922 profiles_->AddPathToCurrentProfiles(entries); 940 profiles_->AddPathToCurrentProfiles(entries);
923 } 941 }
924 942
925 943
926 } } // namespace v8::internal 944 } } // 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