Revision: 14670
Author: [email protected]
Date: Tue May 14 15:51:33 2013
Log: Skip samples where top function's stack frame is not setup properly
Stack iterator takes return address based on the frame pointer (ebp) and
detects JS frames based on value at fp +
StandardFrameConstants::kMarkerOffset. So in order the iterator to work
correctly this values should be already setup for the current function.
Stack frame is constructed at the very beginning of JS function code and
destroyed before return. If sample is taken before before the frame
construction is completed or after it was destroyed the stack iterator will
wrongly think that FP points at the current functions frame base and will
skip callers frame. To avoid this we mark code ranges where stack frame
doesn't exist and completely ignore such samples.
This fixes cctest/test-cpu-profiler/CollectCpuProfile flakiness.
BUG=v8:2628
[email protected]
Review URL: https://codereview.chromium.org/14253015
http://code.google.com/p/v8/source/detail?r=14670
Modified:
/branches/bleeding_edge/src/arm/full-codegen-arm.cc
/branches/bleeding_edge/src/arm/lithium-codegen-arm.cc
/branches/bleeding_edge/src/compiler.cc
/branches/bleeding_edge/src/compiler.h
/branches/bleeding_edge/src/cpu-profiler.cc
/branches/bleeding_edge/src/cpu-profiler.h
/branches/bleeding_edge/src/ia32/full-codegen-ia32.cc
/branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc
/branches/bleeding_edge/src/log.cc
/branches/bleeding_edge/src/log.h
/branches/bleeding_edge/src/mips/full-codegen-mips.cc
/branches/bleeding_edge/src/mips/lithium-codegen-mips.cc
/branches/bleeding_edge/src/profile-generator-inl.h
/branches/bleeding_edge/src/profile-generator.cc
/branches/bleeding_edge/src/profile-generator.h
/branches/bleeding_edge/src/x64/full-codegen-x64.cc
/branches/bleeding_edge/src/x64/lithium-codegen-x64.cc
/branches/bleeding_edge/test/cctest/cctest.status
/branches/bleeding_edge/test/cctest/test-cpu-profiler.cc
=======================================
--- /branches/bleeding_edge/src/arm/full-codegen-arm.cc Tue May 14 09:26:56
2013
+++ /branches/bleeding_edge/src/arm/full-codegen-arm.cc Tue May 14 15:51:33
2013
@@ -175,6 +175,7 @@
// Adjust FP to point to saved FP.
__ add(fp, sp, Operand(2 * kPointerSize));
}
+ info->AddNoFrameRange(0, masm_->pc_offset());
{ Comment cmnt(masm_, "[ Allocate locals");
int locals_count = info->scope()->num_stack_slots();
@@ -438,9 +439,11 @@
PredictableCodeSizeScope predictable(masm_, -1);
__ RecordJSReturn();
masm_->mov(sp, fp);
+ int no_frame_start = masm_->pc_offset();
masm_->ldm(ia_w, sp, fp.bit() | lr.bit());
masm_->add(sp, sp, Operand(sp_delta));
masm_->Jump(lr);
+ info_->AddNoFrameRange(no_frame_start, masm_->pc_offset());
}
#ifdef DEBUG
=======================================
--- /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc Tue May 14
05:56:53 2013
+++ /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc Tue May 14
15:51:33 2013
@@ -2898,9 +2898,11 @@
count++;
}
}
+ int no_frame_start = -1;
if (NeedsEagerFrame()) {
__ mov(sp, fp);
__ ldm(ia_w, sp, fp.bit() | lr.bit());
+ no_frame_start = masm_->pc_offset();
}
if (instr->has_constant_parameter_count()) {
int parameter_count = ToInteger32(instr->constant_parameter_count());
@@ -2916,6 +2918,10 @@
}
__ Jump(lr);
+
+ if (no_frame_start != -1) {
+ info_->AddNoFrameRange(no_frame_start, masm_->pc_offset());
+ }
}
=======================================
--- /branches/bleeding_edge/src/compiler.cc Mon May 13 04:10:31 2013
+++ /branches/bleeding_edge/src/compiler.cc Tue May 14 15:51:33 2013
@@ -103,6 +103,8 @@
code_stub_ = NULL;
prologue_offset_ = kPrologueOffsetNotSet;
opt_count_ = shared_info().is_null() ? 0 : shared_info()->opt_count();
+ no_frame_ranges_ = isolate->cpu_profiler()->is_profiling()
+ ? new List<OffsetRange>(2) : NULL;
if (mode == STUB) {
mode_ = STUB;
return;
@@ -121,6 +123,7 @@
CompilationInfo::~CompilationInfo() {
delete deferred_handles_;
+ delete no_frame_ranges_;
}
@@ -568,6 +571,7 @@
: Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script),
*info->code(),
*result,
+ info,
String::cast(script->name())));
GDBJIT(AddCode(Handle<String>(String::cast(script->name())),
script,
@@ -580,6 +584,7 @@
: Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script),
*info->code(),
*result,
+ info,
isolate->heap()->empty_string()));
GDBJIT(AddCode(Handle<String>(), script, info->code(), info));
}
@@ -807,6 +812,10 @@
// reset this bit when lazy compiling the code again.
if (shared->optimization_disabled()) code->set_optimizable(false);
+ if (shared->code() == *code) {
+ // Do not send compilation event for the same code twice.
+ return;
+ }
Compiler::RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, info,
shared);
}
@@ -1151,6 +1160,7 @@
CodeCreateEvent(Logger::ToNativeByScript(tag, *script),
*code,
*shared,
+ info,
String::cast(script->name()),
line_num));
} else {
@@ -1158,6 +1168,7 @@
CodeCreateEvent(Logger::ToNativeByScript(tag, *script),
*code,
*shared,
+ info,
shared->DebugName()));
}
}
=======================================
--- /branches/bleeding_edge/src/compiler.h Thu Apr 18 08:44:38 2013
+++ /branches/bleeding_edge/src/compiler.h Tue May 14 15:51:33 2013
@@ -47,6 +47,12 @@
ONLY_SINGLE_FUNCTION_LITERAL // Only a single FunctionLiteral expression.
};
+struct OffsetRange {
+ OffsetRange(int from, int to) : from(from), to(to) {}
+ int from;
+ int to;
+};
+
// CompilationInfo encapsulates some information known at compile time. It
// is constructed based on the resources available at compile-time.
class CompilationInfo {
@@ -256,6 +262,20 @@
ASSERT_EQ(kPrologueOffsetNotSet, prologue_offset_);
prologue_offset_ = prologue_offset;
}
+
+ // Adds offset range [from, to) where fp register does not point
+ // to the current frame base. Used in CPU profiler to detect stack
+ // samples where top frame is not set up.
+ inline void AddNoFrameRange(int from, int to) {
+ if (no_frame_ranges_) no_frame_ranges_->Add(OffsetRange(from, to));
+ }
+
+ List<OffsetRange>* ReleaseNoFrameRanges() {
+ List<OffsetRange>* result = no_frame_ranges_;
+ no_frame_ranges_ = NULL;
+ return result;
+ }
+
private:
Isolate* isolate_;
@@ -361,6 +381,8 @@
int prologue_offset_;
+ List<OffsetRange>* no_frame_ranges_;
+
// A copy of shared_info()->opt_count() to avoid handle deref
// during graph optimization.
int opt_count_;
=======================================
--- /branches/bleeding_edge/src/cpu-profiler.cc Fri Apr 26 00:50:35 2013
+++ /branches/bleeding_edge/src/cpu-profiler.cc Tue May 14 15:51:33 2013
@@ -29,6 +29,7 @@
#include "cpu-profiler-inl.h"
+#include "compiler.h"
#include "frames-inl.h"
#include "hashmap.h"
#include "log-inl.h"
@@ -80,7 +81,8 @@
int line_number,
Address start,
unsigned size,
- Address shared) {
+ Address shared,
+ CompilationInfo* info) {
if (FilterOutCodeCreateEvent(tag)) return;
CodeEventsContainer evt_rec;
CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
@@ -88,6 +90,9 @@
rec->order = ++enqueue_order_;
rec->start = start;
rec->entry = profiles_->NewCodeEntry(tag, name, resource_name,
line_number);
+ if (info) {
+ rec->entry->set_no_frame_ranges(info->ReleaseNoFrameRanges());
+ }
rec->size = size;
rec->shared = shared;
events_buffer_.Enqueue(evt_rec);
@@ -323,6 +328,7 @@
v8::CpuProfileNode::kNoLineNumberInfo,
code->address(),
code->ExecutableSize(),
+ NULL,
NULL);
}
@@ -330,6 +336,7 @@
void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
Code* code,
SharedFunctionInfo* shared,
+ CompilationInfo* info,
Name* name) {
processor_->CodeCreateEvent(
tag,
@@ -338,13 +345,15 @@
v8::CpuProfileNode::kNoLineNumberInfo,
code->address(),
code->ExecutableSize(),
- shared->address());
+ shared->address(),
+ info);
}
void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
Code* code,
SharedFunctionInfo* shared,
+ CompilationInfo* info,
String* source, int line) {
processor_->CodeCreateEvent(
tag,
@@ -353,7 +362,8 @@
line,
code->address(),
code->ExecutableSize(),
- shared->address());
+ shared->address(),
+ info);
}
=======================================
--- /branches/bleeding_edge/src/cpu-profiler.h Fri Apr 26 00:50:35 2013
+++ /branches/bleeding_edge/src/cpu-profiler.h Tue May 14 15:51:33 2013
@@ -40,6 +40,7 @@
// Forward declarations.
class CodeEntry;
class CodeMap;
+class CompilationInfo;
class CpuProfile;
class CpuProfilesCollection;
class ProfileGenerator;
@@ -142,7 +143,8 @@
Name* name,
String* resource_name, int line_number,
Address start, unsigned size,
- Address shared);
+ Address shared,
+ CompilationInfo* info);
void CodeCreateEvent(Logger::LogEventsAndTags tag,
const char* name,
Address start, unsigned size);
@@ -227,11 +229,13 @@
Code* code, Name* name);
void CodeCreateEvent(Logger::LogEventsAndTags tag,
Code* code,
- SharedFunctionInfo* shared,
- Name* name);
+ SharedFunctionInfo* shared,
+ CompilationInfo* info,
+ Name* name);
void CodeCreateEvent(Logger::LogEventsAndTags tag,
Code* code,
SharedFunctionInfo* shared,
+ CompilationInfo* info,
String* source, int line);
void CodeCreateEvent(Logger::LogEventsAndTags tag,
Code* code, int args_count);
=======================================
--- /branches/bleeding_edge/src/ia32/full-codegen-ia32.cc Tue May 14
09:26:56 2013
+++ /branches/bleeding_edge/src/ia32/full-codegen-ia32.cc Tue May 14
15:51:33 2013
@@ -161,6 +161,7 @@
__ mov(ebp, esp);
__ push(esi); // Callee's context.
__ push(edi); // Callee's JS Function.
+ info->AddNoFrameRange(0, masm_->pc_offset());
{ Comment cmnt(masm_, "[ Allocate locals");
int locals_count = info->scope()->num_stack_slots();
@@ -410,6 +411,7 @@
// Do not use the leave instruction here because it is too short to
// patch with the code required by the debugger.
__ mov(esp, ebp);
+ int no_frame_start = masm_->pc_offset();
__ pop(ebp);
int arguments_bytes = (info_->scope()->num_parameters() + 1) *
kPointerSize;
@@ -420,6 +422,7 @@
ASSERT(Assembler::kJSReturnSequenceLength <=
masm_->SizeOfCodeGeneratedSince(&check_exit_codesize));
#endif
+ info_->AddNoFrameRange(no_frame_start, masm_->pc_offset());
}
}
=======================================
--- /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc Tue May 14
05:56:53 2013
+++ /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc Tue May 14
15:51:33 2013
@@ -210,6 +210,7 @@
frame_is_built_ = true;
__ push(ebp); // Caller's frame pointer.
__ mov(ebp, esp);
+ info()->AddNoFrameRange(0, masm_->pc_offset());
__ push(esi); // Callee's context.
if (info()->IsStub()) {
__ push(Immediate(Smi::FromInt(StackFrame::STUB)));
@@ -2806,9 +2807,11 @@
__ mov(edx, Operand(ebp,
JavaScriptFrameConstants::kDynamicAlignmentStateOffset));
}
+ int no_frame_start = -1;
if (NeedsEagerFrame()) {
__ mov(esp, ebp);
__ pop(ebp);
+ no_frame_start = masm_->pc_offset();
}
if (dynamic_frame_alignment_) {
Label no_padding;
@@ -2820,6 +2823,9 @@
}
EmitReturn(instr, false);
+ if (no_frame_start != -1) {
+ info()->AddNoFrameRange(no_frame_start, masm_->pc_offset());
+ }
}
=======================================
--- /branches/bleeding_edge/src/log.cc Fri Apr 26 04:34:44 2013
+++ /branches/bleeding_edge/src/log.cc Tue May 14 15:51:33 2013
@@ -1016,6 +1016,7 @@
void Logger::CodeCreateEvent(LogEventsAndTags tag,
Code* code,
SharedFunctionInfo* shared,
+ CompilationInfo* info,
Name* name) {
if (!is_logging_code_events()) return;
if (FLAG_ll_prof || Serializer::enabled() || code_event_handler_ != NULL) {
@@ -1093,6 +1094,7 @@
void Logger::CodeCreateEvent(LogEventsAndTags tag,
Code* code,
SharedFunctionInfo* shared,
+ CompilationInfo* info,
Name* source, int line) {
if (!is_logging_code_events()) return;
if (FLAG_ll_prof || Serializer::enabled() || code_event_handler_ != NULL) {
@@ -1735,20 +1737,20 @@
PROFILE(isolate_,
CodeCreateEvent(
Logger::ToNativeByScript(Logger::LAZY_COMPILE_TAG, *script),
- *code, *shared,
+ *code, *shared, NULL,
*script_name, line_num + 1));
} else {
// Can't distinguish eval and script here, so always use Script.
PROFILE(isolate_,
CodeCreateEvent(
Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script),
- *code, *shared, *script_name));
+ *code, *shared, NULL, *script_name));
}
} else {
PROFILE(isolate_,
CodeCreateEvent(
Logger::ToNativeByScript(Logger::LAZY_COMPILE_TAG, *script),
- *code, *shared, *func_name));
+ *code, *shared, NULL, *func_name));
}
} else if (shared->IsApiFunction()) {
// API function.
@@ -1763,7 +1765,7 @@
} else {
PROFILE(isolate_,
CodeCreateEvent(
- Logger::LAZY_COMPILE_TAG, *code, *shared, *func_name));
+ Logger::LAZY_COMPILE_TAG, *code, *shared, NULL, *func_name));
}
}
=======================================
--- /branches/bleeding_edge/src/log.h Wed Apr 24 07:44:08 2013
+++ /branches/bleeding_edge/src/log.h Tue May 14 15:51:33 2013
@@ -79,6 +79,7 @@
class Isolate;
class PositionsRecorder;
class CpuProfiler;
+class CompilationInfo;
#undef LOG
#define LOG(isolate, Call) \
@@ -235,10 +236,12 @@
void CodeCreateEvent(LogEventsAndTags tag,
Code* code,
SharedFunctionInfo* shared,
+ CompilationInfo* info,
Name* name);
void CodeCreateEvent(LogEventsAndTags tag,
Code* code,
SharedFunctionInfo* shared,
+ CompilationInfo* info,
Name* source, int line);
void CodeCreateEvent(LogEventsAndTags tag, Code* code, int args_count);
void CodeMovingGCEvent();
=======================================
--- /branches/bleeding_edge/src/mips/full-codegen-mips.cc Wed May 8
15:15:27 2013
+++ /branches/bleeding_edge/src/mips/full-codegen-mips.cc Tue May 14
15:51:33 2013
@@ -179,6 +179,7 @@
__ LoadRoot(at, Heap::kUndefinedValueRootIndex);
// Adjust fp to point to caller's fp.
__ Addu(fp, sp, Operand(2 * kPointerSize));
+ info->AddNoFrameRange(0, masm_->pc_offset());
{ Comment cmnt(masm_, "[ Allocate locals");
int locals_count = info->scope()->num_stack_slots();
@@ -438,9 +439,11 @@
CodeGenerator::RecordPositions(masm_, function()->end_position() - 1);
__ RecordJSReturn();
masm_->mov(sp, fp);
+ int no_frame_start = masm_->pc_offset();
masm_->MultiPop(static_cast<RegList>(fp.bit() | ra.bit()));
masm_->Addu(sp, sp, Operand(sp_delta));
masm_->Jump(ra);
+ info_->AddNoFrameRange(no_frame_start, masm_->pc_offset());
}
#ifdef DEBUG
=======================================
--- /branches/bleeding_edge/src/mips/lithium-codegen-mips.cc Tue May 14
05:56:53 2013
+++ /branches/bleeding_edge/src/mips/lithium-codegen-mips.cc Tue May 14
15:51:33 2013
@@ -179,6 +179,7 @@
__ Addu(fp, sp, Operand(2 * kPointerSize));
}
frame_is_built_ = true;
+ info_->AddNoFrameRange(0, masm_->pc_offset());
}
// Reserve space for the stack slots needed by the code.
@@ -2511,9 +2512,11 @@
count++;
}
}
+ int no_frame_start = -1;
if (NeedsEagerFrame()) {
__ mov(sp, fp);
__ Pop(ra, fp);
+ no_frame_start = masm_->pc_offset();
}
if (instr->has_constant_parameter_count()) {
int parameter_count = ToInteger32(instr->constant_parameter_count());
@@ -2530,6 +2533,10 @@
}
__ Jump(ra);
+
+ if (no_frame_start != -1) {
+ info_->AddNoFrameRange(no_frame_start, masm_->pc_offset());
+ }
}
=======================================
--- /branches/bleeding_edge/src/profile-generator-inl.h Wed Apr 24 07:44:08
2013
+++ /branches/bleeding_edge/src/profile-generator-inl.h Tue May 14 15:51:33
2013
@@ -55,7 +55,8 @@
resource_name_(resource_name),
line_number_(line_number),
shared_id_(0),
- security_token_id_(security_token_id) {
+ security_token_id_(security_token_id),
+ no_frame_ranges_(NULL) {
}
=======================================
--- /branches/bleeding_edge/src/profile-generator.cc Wed Apr 24 05:09:04
2013
+++ /branches/bleeding_edge/src/profile-generator.cc Tue May 14 15:51:33
2013
@@ -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 @@
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 @@
}
-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 @@
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
=======================================
--- /branches/bleeding_edge/src/profile-generator.h Fri Apr 26 00:50:35 2013
+++ /branches/bleeding_edge/src/profile-generator.h Tue May 14 15:51:33 2013
@@ -35,6 +35,8 @@
namespace v8 {
namespace internal {
+struct OffsetRange;
+
class TokenEnumerator {
public:
TokenEnumerator();
@@ -100,6 +102,7 @@
const char* resource_name,
int line_number,
int security_token_id));
+ ~CodeEntry();
INLINE(bool is_js_function() const) { return is_js_function_tag(tag_); }
INLINE(const char* name_prefix() const) { return name_prefix_; }
@@ -111,6 +114,11 @@
INLINE(int security_token_id() const) { return security_token_id_; }
INLINE(static bool is_js_function_tag(Logger::LogEventsAndTags tag));
+
+ List<OffsetRange>* no_frame_ranges() const { return no_frame_ranges_; }
+ void set_no_frame_ranges(List<OffsetRange>* ranges) {
+ no_frame_ranges_ = ranges;
+ }
void CopyData(const CodeEntry& source);
uint32_t GetCallUid() const;
@@ -126,6 +134,7 @@
int line_number_;
int shared_id_;
int security_token_id_;
+ List<OffsetRange>* no_frame_ranges_;
DISALLOW_COPY_AND_ASSIGN(CodeEntry);
};
@@ -251,7 +260,7 @@
CodeMap() : next_shared_id_(1) { }
void AddCode(Address addr, CodeEntry* entry, unsigned size);
void MoveCode(Address from, Address to);
- CodeEntry* FindEntry(Address addr);
+ CodeEntry* FindEntry(Address addr, Address* start = NULL);
int GetSharedId(Address addr);
void Print();
=======================================
--- /branches/bleeding_edge/src/x64/full-codegen-x64.cc Tue May 14 09:26:56
2013
+++ /branches/bleeding_edge/src/x64/full-codegen-x64.cc Tue May 14 15:51:33
2013
@@ -157,6 +157,7 @@
__ movq(rbp, rsp);
__ push(rsi); // Callee's context.
__ push(rdi); // Callee's JS Function.
+ info->AddNoFrameRange(0, masm_->pc_offset());
{ Comment cmnt(masm_, "[ Allocate locals");
int locals_count = info->scope()->num_stack_slots();
@@ -406,6 +407,7 @@
// patch with the code required by the debugger.
__ movq(rsp, rbp);
__ pop(rbp);
+ int no_frame_start = masm_->pc_offset();
int arguments_bytes = (info_->scope()->num_parameters() + 1) *
kPointerSize;
__ Ret(arguments_bytes, rcx);
@@ -423,6 +425,7 @@
ASSERT(Assembler::kJSReturnSequenceLength <=
masm_->SizeOfCodeGeneratedSince(&check_exit_codesize));
#endif
+ info_->AddNoFrameRange(no_frame_start, masm_->pc_offset());
}
}
=======================================
--- /branches/bleeding_edge/src/x64/lithium-codegen-x64.cc Tue May 14
05:56:53 2013
+++ /branches/bleeding_edge/src/x64/lithium-codegen-x64.cc Tue May 14
15:51:33 2013
@@ -174,6 +174,7 @@
} else {
__ push(rdi); // Callee's JS function.
}
+ info()->AddNoFrameRange(0, masm_->pc_offset());
}
// Reserve space for the stack slots needed by the code.
@@ -2521,9 +2522,11 @@
count++;
}
}
+ int no_frame_start = -1;
if (NeedsEagerFrame()) {
__ movq(rsp, rbp);
__ pop(rbp);
+ no_frame_start = masm_->pc_offset();
}
if (instr->has_constant_parameter_count()) {
__ Ret((ToInteger32(instr->constant_parameter_count()) + 1) * kPointerSize,
@@ -2538,6 +2541,9 @@
__ addq(rsp, reg);
__ jmp(return_addr_reg);
}
+ if (no_frame_start != -1) {
+ info_->AddNoFrameRange(no_frame_start, masm_->pc_offset());
+ }
}
=======================================
--- /branches/bleeding_edge/test/cctest/cctest.status Tue May 7 07:02:31
2013
+++ /branches/bleeding_edge/test/cctest/cctest.status Tue May 14 15:51:33
2013
@@ -80,6 +80,14 @@
test-serialize/DeserializeAndRunScript2: SKIP
test-serialize/DeserializeFromSecondSerialization: SKIP
+##############################################################################
+[ $arch == arm || $arch == mipsel ]
+
+# BUG(2628): Signal may come when pc is close to frame enter/exit code and
on
+# simulator the stack frame is not set up when it is expected to be for
the pc
+# value.
+test-cpu-profiler/SampleWhenFrameIsNotSetup: SKIP
+
##############################################################################
[ $arch == android_arm || $arch == android_ia32 ]
=======================================
--- /branches/bleeding_edge/test/cctest/test-cpu-profiler.cc Thu May 2
13:18:42 2013
+++ /branches/bleeding_edge/test/cctest/test-cpu-profiler.cc Tue May 14
15:51:33 2013
@@ -122,7 +122,8 @@
0,
ToAddress(0x1000),
0x100,
- ToAddress(0x10000));
+ ToAddress(0x10000),
+ NULL);
processor.CodeCreateEvent(i::Logger::BUILTIN_TAG,
"bbb",
ToAddress(0x1200),
@@ -549,3 +550,72 @@
cpu_profiler->DeleteAllCpuProfiles();
}
+
+
+
+static const char* cpu_profiler_test_source2 = "function loop() {}\n"
+"function delay() { loop(); }\n"
+"function start(count) {\n"
+" var k = 0;\n"
+" do {\n"
+" delay();\n"
+" } while (++k < count*100*1000);\n"
+"}\n";
+
+// Check that the profile tree doesn't contain unexpecte traces:
+// - 'loop' can be called only by 'delay'
+// - 'delay' may be called only by 'start'
+// The profile will look like the following:
+//
+// [Top down]:
+// 135 0 (root) [-1] #1
+// 121 72 start [-1] #3
+// 49 33 delay [-1] #4
+// 16 16 loop [-1] #5
+// 14 14 (program) [-1] #2
+TEST(SampleWhenFrameIsNotSetup) {
+ LocalContext env;
+ v8::HandleScope scope(env->GetIsolate());
+
+ v8::Script::Compile(v8::String::New(cpu_profiler_test_source2))->Run();
+ v8::Local<v8::Function> function = v8::Local<v8::Function>::Cast(
+ env->Global()->Get(v8::String::New("start")));
+
+ v8::CpuProfiler* cpu_profiler = env->GetIsolate()->GetCpuProfiler();
+ v8::Local<v8::String> profile_name = v8::String::New("my_profile");
+
+ cpu_profiler->StartCpuProfiling(profile_name);
+ int32_t repeat_count = 100;
+#if defined(USE_SIMULATOR)
+ // Simulators are much slower.
+ repeat_count = 1;
+#endif
+ v8::Handle<v8::Value> args[] = { v8::Integer::New(repeat_count) };
+ function->Call(env->Global(), ARRAY_SIZE(args), args);
+ const v8::CpuProfile* profile =
cpu_profiler->StopCpuProfiling(profile_name);
+
+ CHECK_NE(NULL, profile);
+ // Dump collected profile to have a better diagnostic in case of failure.
+ reinterpret_cast<i::CpuProfile*>(
+ const_cast<v8::CpuProfile*>(profile))->Print();
+
+ const v8::CpuProfileNode* root = profile->GetTopDownRoot();
+
+ ScopedVector<v8::Handle<v8::String> > names(3);
+ names[0] = v8::String::New(ProfileGenerator::kGarbageCollectorEntryName);
+ names[1] = v8::String::New(ProfileGenerator::kProgramEntryName);
+ names[2] = v8::String::New("start");
+ CheckChildrenNames(root, names);
+
+ const v8::CpuProfileNode* startNode = FindChild(root, "start");
+ if (startNode->GetChildrenCount() > 0) {
+ CHECK_EQ(1, startNode->GetChildrenCount());
+ const v8::CpuProfileNode* delayNode = FindChild(startNode, "delay");
+ if (delayNode->GetChildrenCount() > 0) {
+ CHECK_EQ(1, delayNode->GetChildrenCount());
+ FindChild(delayNode, "loop");
+ }
+ }
+
+ cpu_profiler->DeleteAllCpuProfiles();
+}
--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.