Index: src/profile-generator.cc |
diff --git a/src/profile-generator.cc b/src/profile-generator.cc |
index b1b163b50ecdf2d59173eef568c84878fb50becf..15066158abc8af80f1e64f150c80765263a7851d 100644 |
--- a/src/profile-generator.cc |
+++ b/src/profile-generator.cc |
@@ -29,6 +29,7 @@ |
#include "profile-generator-inl.h" |
+#include "compiler.h" |
#include "global-handles.h" |
#include "scopeinfo.h" |
#include "unicode.h" |
@@ -186,6 +187,11 @@ size_t StringsStorage::GetUsedMemorySize() const { |
const char* const CodeEntry::kEmptyNamePrefix = ""; |
+CodeEntry::~CodeEntry() { |
+ delete no_frame_ranges_; |
+} |
+ |
+ |
void CodeEntry::CopyData(const CodeEntry& source) { |
tag_ = source.tag_; |
name_prefix_ = source.name_prefix_; |
@@ -531,13 +537,17 @@ void CodeMap::DeleteAllCoveredCode(Address start, Address end) { |
} |
-CodeEntry* CodeMap::FindEntry(Address addr) { |
+CodeEntry* CodeMap::FindEntry(Address addr, Address* start) { |
CodeTree::Locator locator; |
if (tree_.FindGreatestLessThan(addr, &locator)) { |
// locator.key() <= addr. Need to check that addr is within entry. |
const CodeEntryInfo& entry = locator.value(); |
- if (addr < (locator.key() + entry.size)) |
+ if (addr < (locator.key() + entry.size)) { |
+ if (start) { |
+ *start = locator.key(); |
+ } |
return entry.entry; |
+ } |
} |
return NULL; |
} |
@@ -898,7 +908,26 @@ void ProfileGenerator::RecordTickSample(const TickSample& sample) { |
CodeEntry** entry = entries.start(); |
memset(entry, 0, entries.length() * sizeof(*entry)); |
if (sample.pc != NULL) { |
- *entry++ = code_map_.FindEntry(sample.pc); |
+ Address start; |
+ CodeEntry* pc_entry = code_map_.FindEntry(sample.pc, &start); |
+ // If pc is in the function code before it set up stack frame or after the |
+ // frame was destroyed SafeStackTraceFrameIterator incorrectly thinks that |
+ // ebp contains return address of the current function and skips caller's |
+ // frame. Check for this case and just skip such samples. |
+ if (pc_entry) { |
+ List<OffsetRange>* ranges = pc_entry->no_frame_ranges(); |
+ if (ranges) { |
+ Code* code = Code::cast(HeapObject::FromAddress(start)); |
+ int pc_offset = sample.pc - code->instruction_start(); |
+ for (int i = 0; i < ranges->length(); i++) { |
+ OffsetRange& range = ranges->at(i); |
+ if (range.from <= pc_offset && pc_offset < range.to) { |
+ return; |
+ } |
+ } |
+ } |
+ } |
+ *entry++ = pc_entry; |
if (sample.has_external_callback) { |
// Don't use PC when in external callback code, as it can point |