Retry landing cl for issue with TSAN.

BUG=
R=rmacnak@google.com

Review URL: https://codereview.chromium.org/2525103003 .
This commit is contained in:
Siva Annamalai 2016-11-23 15:40:26 -08:00
parent 12de13d1ae
commit 501720c644
11 changed files with 205 additions and 159 deletions

View file

@ -67,8 +67,8 @@ var tests = [
cpuProfile.buildFunctionCallerAndCallees();
var tree = cpuProfile.loadCodeTree(M.ProfileTreeDirection.exclusive);
var node = tree.root;
var expected =
['Root', 'DRT_AllocateObject', 'test', 'test', '_Closure.call'];
var expected = ['Root', 'DRT_AllocateObject', '[Stub] Allocate Foo',
'test', 'test', '_Closure.call'];
for (var i = 0; i < expected.length; i++) {
expect(node.profileCode.code.name, equals(expected[i]));
// Depth first traversal.

View file

@ -38,7 +38,7 @@ void DynamicAssertionHelper::Fail(const char* format, ...) {
// until the program is exiting before producing a non-zero exit
// code through abort.
if (kind_ == ASSERT) {
NOT_IN_PRODUCT(Profiler::DumpStackTrace(true /* native_stack_trace */));
NOT_IN_PRODUCT(Profiler::DumpStackTrace());
OS::Abort();
}
failed_ = true;

View file

@ -46,8 +46,36 @@ cc/Service_Profile: Skip
cc/Dart2JSCompilerStats: Skip
cc/CorelibCompilerStats: Skip
# Profiler is completely disabled in SIMDBC builds.
# On the simluator stack traces produced by the Profiler do not match
# up with the real Dart stack trace and hence we don't get correct
# symbol names.
[ $arch == simarm || $arch == simarmv6 || $arch == simarmv5te || $arch == simarm64 || $arch == simmips || $arch == simdbc || $arch == simdbc64 ]
cc/Service_Profile: Skip
cc/Profiler_AllocationSampleTest: Skip
cc/Profiler_ArrayAllocation: Skip
cc/Profiler_BasicSourcePosition: Skip
cc/Profiler_BasicSourcePositionOptimized: Skip
cc/Profiler_BinaryOperatorSourcePosition: Skip
cc/Profiler_BinaryOperatorSourcePositionOptimized: Skip
cc/Profiler_ChainedSamples: Skip
cc/Profiler_ClosureAllocation: Skip
cc/Profiler_CodeTicks: Skip
cc/Profiler_ContextAllocation: Skip
cc/Profiler_FunctionInline: Skip
cc/Profiler_FunctionTicks: Skip
cc/Profiler_InliningIntervalBoundry: Skip
cc/Profiler_IntrinsicAllocation: Skip
cc/Profiler_SampleBufferIterateTest: Skip
cc/Profiler_SampleBufferWrapTest: Skip
cc/Profiler_SourcePosition: Skip
cc/Profiler_SourcePositionOptimized: Skip
cc/Profiler_StringAllocation: Skip
cc/Profiler_StringInterpolation: Skip
cc/Profiler_ToggleRecordAllocation: Skip
cc/Profiler_TrivialRecordAllocation: Skip
cc/Profiler_TypedArrayAllocation: Skip
cc/Profiler_GetSourceReport: Skip
[ $compiler == dart2js ]
dart/redirection_type_shuffling_test: Skip # Depends on lazy enforcement of type bounds
@ -116,33 +144,6 @@ cc/StackTraceFormat: Fail,OK # Expects exact type name.
cc/String_ScrubName: Fail,OK # Expects exact type name.
cc/GetFunctionNames: Fail,OK # Expects exact type name.
[ $arch == simdbc || $arch == simdbc64 ]
# TODO(vegorov) Profiler is completely disabled in SIMDBC builds.
cc/Profiler_AllocationSampleTest: Skip
cc/Profiler_ArrayAllocation: Skip
cc/Profiler_BasicSourcePosition: Skip
cc/Profiler_BasicSourcePositionOptimized: Skip
cc/Profiler_BinaryOperatorSourcePosition: Skip
cc/Profiler_BinaryOperatorSourcePositionOptimized: Skip
cc/Profiler_ChainedSamples: Skip
cc/Profiler_ClosureAllocation: Skip
cc/Profiler_CodeTicks: Skip
cc/Profiler_ContextAllocation: Skip
cc/Profiler_FunctionInline: Skip
cc/Profiler_FunctionTicks: Skip
cc/Profiler_InliningIntervalBoundry: Skip
cc/Profiler_IntrinsicAllocation: Skip
cc/Profiler_SampleBufferIterateTest: Skip
cc/Profiler_SampleBufferWrapTest: Skip
cc/Profiler_SourcePosition: Skip
cc/Profiler_SourcePositionOptimized: Skip
cc/Profiler_StringAllocation: Skip
cc/Profiler_StringInterpolation: Skip
cc/Profiler_ToggleRecordAllocation: Skip
cc/Profiler_TrivialRecordAllocation: Skip
cc/Profiler_TypedArrayAllocation: Skip
cc/Profiler_GetSourceReport: Skip
# TODO(vegorov) These tests don't seem to work if FLAG_interpret_irregexp
# is switched on by default because they attempt to call regexp functions
# directly instead of going through JSSyntaxRegExp_ExecuteMatch.

View file

@ -107,7 +107,9 @@ static const uword kZapUninitializedWord = 0xabababababababab;
; // NOLINT
// clang-format on
#elif defined(HOST_ARCH_X64)
#define COPY_FP_REGISTER(fp) UNIMPLEMENTED();
// We don't have the asm equivalent to get at the frame pointer on
// windows x64, return the stack pointer instead.
#define COPY_FP_REGISTER(fp) fp = Thread::GetCurrentStackPointer();
#else
#error Unknown host architecture.
#endif

View file

@ -24,7 +24,7 @@ namespace dart {
if (result != 0) { \
const int kBufferSize = 1024; \
char error_message[kBufferSize]; \
NOT_IN_PRODUCT(Profiler::DumpStackTrace(true /* native_stack_trace */)); \
NOT_IN_PRODUCT(Profiler::DumpStackTrace()); \
Utils::StrError(result, error_message, kBufferSize); \
FATAL2("pthread error: %d (%s)", result, error_message); \
}

View file

@ -25,7 +25,7 @@ namespace dart {
if (result != 0) { \
const int kBufferSize = 1024; \
char error_buf[kBufferSize]; \
NOT_IN_PRODUCT(Profiler::DumpStackTrace(true /* native_stack_trace */)); \
NOT_IN_PRODUCT(Profiler::DumpStackTrace()); \
FATAL2("pthread error: %d (%s)", result, \
Utils::StrError(result, error_buf, kBufferSize)); \
}

View file

@ -29,7 +29,7 @@ namespace dart {
if (result != 0) { \
const int kBufferSize = 1024; \
char error_message[kBufferSize]; \
NOT_IN_PRODUCT(Profiler::DumpStackTrace(true /* native_stack_trace */)); \
NOT_IN_PRODUCT(Profiler::DumpStackTrace()); \
Utils::StrError(result, error_message, kBufferSize); \
FATAL2("pthread error: %d (%s)", result, error_message); \
}

View file

@ -418,67 +418,54 @@ class ProfilerStackWalker : public ValueObject {
};
// Given an exit frame, walk the Dart stack.
class ProfilerDartExitStackWalker : public ProfilerStackWalker {
public:
ProfilerDartExitStackWalker(Thread* thread,
Isolate* isolate,
Sample* sample,
SampleBuffer* sample_buffer)
: ProfilerStackWalker(isolate, sample, sample_buffer),
frame_iterator_(thread) {}
void walk() {
// Mark that this sample was collected from an exit frame.
sample_->set_exit_frame_sample(true);
StackFrame* frame = frame_iterator_.NextFrame();
if (sample_ == NULL) {
// Only when we are dumping the stack trace for debug purposes.
Code& code = Code::Handle();
while (frame != NULL) {
code ^= frame->LookupDartCode();
if (!Append(frame->pc(), code)) {
return;
}
frame = frame_iterator_.NextFrame();
}
} else {
while (frame != NULL) {
if (!Append(frame->pc())) {
return;
}
frame = frame_iterator_.NextFrame();
}
}
}
private:
DartFrameIterator frame_iterator_;
};
// Executing Dart code, walk the stack.
class ProfilerDartStackWalker : public ProfilerStackWalker {
public:
ProfilerDartStackWalker(Isolate* isolate,
ProfilerDartStackWalker(Thread* thread,
Sample* sample,
SampleBuffer* sample_buffer,
uword stack_lower,
uword stack_upper,
uword pc,
uword fp,
uword sp)
: ProfilerStackWalker(isolate, sample, sample_buffer),
uword sp,
bool exited_dart_code,
bool allocation_sample)
: ProfilerStackWalker(thread->isolate(), sample, sample_buffer),
pc_(reinterpret_cast<uword*>(pc)),
fp_(reinterpret_cast<uword*>(fp)),
sp_(reinterpret_cast<uword*>(sp)),
stack_upper_(stack_upper),
stack_lower_(stack_lower) {
pc_ = reinterpret_cast<uword*>(pc);
fp_ = reinterpret_cast<uword*>(fp);
sp_ = reinterpret_cast<uword*>(sp);
stack_lower_(stack_lower),
has_exit_frame_(exited_dart_code) {
if (exited_dart_code) {
StackFrameIterator iterator(StackFrameIterator::kDontValidateFrames,
thread);
pc_ = NULL;
fp_ = NULL;
sp_ = NULL;
if (!iterator.HasNextFrame()) {
return;
}
// Ensure we are able to get to the exit frame.
StackFrame* frame = iterator.NextFrame();
if (!frame->IsExitFrame()) {
return;
}
// Skip the exit frame.
if (!iterator.HasNextFrame()) {
return;
}
frame = iterator.NextFrame();
// Record frame details of the first frame from which we start walking.
pc_ = reinterpret_cast<uword*>(frame->pc());
fp_ = reinterpret_cast<uword*>(frame->fp());
sp_ = reinterpret_cast<uword*>(frame->sp());
}
}
void walk() {
sample_->set_exit_frame_sample(false);
sample_->set_exit_frame_sample(has_exit_frame_);
if (!ValidFramePointer()) {
sample_->set_ignore_sample(true);
return;
@ -605,7 +592,8 @@ class ProfilerDartStackWalker : public ProfilerStackWalker {
uword* fp_;
uword* sp_;
const uword stack_upper_;
uword stack_lower_;
const uword stack_lower_;
bool has_exit_frame_;
};
@ -758,7 +746,6 @@ static void CollectSample(Isolate* isolate,
bool in_dart_code,
Sample* sample,
ProfilerNativeStackWalker* native_stack_walker,
ProfilerDartExitStackWalker* dart_exit_stack_walker,
ProfilerDartStackWalker* dart_stack_walker,
uword pc,
uword fp,
@ -783,7 +770,7 @@ static void CollectSample(Isolate* isolate,
} else if (StubCode::HasBeenInitialized() && exited_dart_code) {
AtomicOperations::IncrementInt64By(&counters->stack_walker_dart_exit, 1);
// We have a valid exit frame info, use the Dart stack walker.
dart_exit_stack_walker->walk();
dart_stack_walker->walk();
} else if (StubCode::HasBeenInitialized() && in_dart_code) {
AtomicOperations::IncrementInt64By(&counters->stack_walker_dart, 1);
// We are executing Dart code. We have frame pointers.
@ -951,7 +938,7 @@ void Profiler::DumpStackTrace(void* context) {
uword pc = SignalHandler::GetProgramCounter(mcontext);
uword fp = SignalHandler::GetFramePointer(mcontext);
uword sp = SignalHandler::GetCStackPointer(mcontext);
DumpStackTrace(/* native_stack_trace = */ true, sp, fp, pc);
DumpStackTrace(sp, fp, pc);
#else
// TODO(fschneider): Add support for more platforms.
// Do nothing on unsupported platforms.
@ -959,21 +946,18 @@ void Profiler::DumpStackTrace(void* context) {
}
void Profiler::DumpStackTrace(bool native_stack_trace) {
void Profiler::DumpStackTrace() {
uintptr_t sp = Thread::GetCurrentStackPointer();
uintptr_t fp = 0;
uintptr_t pc = GetProgramCounter();
COPY_FP_REGISTER(fp);
DumpStackTrace(native_stack_trace, sp, fp, pc);
DumpStackTrace(sp, fp, pc);
}
void Profiler::DumpStackTrace(bool native_stack_trace,
uword sp,
uword fp,
uword pc) {
void Profiler::DumpStackTrace(uword sp, uword fp, uword pc) {
// Allow only one stack trace to prevent recursively printing stack traces if
// we hit an assert while printing the stack.
static uintptr_t started_dump = 0;
@ -993,10 +977,7 @@ void Profiler::DumpStackTrace(bool native_stack_trace,
return;
}
const bool exited_dart_code = thread->HasExitedDartCode();
OS::PrintErr("Dumping %s stack trace for thread %" Px "\n",
native_stack_trace ? "native" : "dart-only",
OS::PrintErr("Dumping native stack trace for thread %" Px "\n",
OSThread::ThreadIdToIntPtr(os_thread->trace_id()));
uword stack_lower = 0;
@ -1014,18 +995,9 @@ void Profiler::DumpStackTrace(bool native_stack_trace,
return;
}
if (native_stack_trace) {
ProfilerNativeStackWalker native_stack_walker(
isolate, NULL, NULL, stack_lower, stack_upper, pc, fp, sp);
native_stack_walker.walk();
} else if (exited_dart_code) {
ProfilerDartExitStackWalker dart_exit_stack_walker(thread, isolate, NULL,
NULL);
dart_exit_stack_walker.walk();
} else {
ProfilerDartStackWalker dart_stack_walker(isolate, NULL, NULL, stack_lower,
stack_upper, pc, fp, sp);
}
ProfilerNativeStackWalker native_stack_walker(
isolate, NULL, NULL, stack_lower, stack_upper, pc, fp, sp);
native_stack_walker.walk();
OS::PrintErr("-- End of DumpStackTrace\n");
}
@ -1047,36 +1019,36 @@ void Profiler::SampleAllocation(Thread* thread, intptr_t cid) {
return;
}
uintptr_t sp = Thread::GetCurrentStackPointer();
uintptr_t fp = 0;
uintptr_t pc = GetProgramCounter();
COPY_FP_REGISTER(fp);
uword stack_lower = 0;
uword stack_upper = 0;
if (!InitialRegisterCheck(pc, fp, sp)) {
return;
}
if (!GetAndValidateIsolateStackBounds(thread, fp, sp, &stack_lower,
&stack_upper)) {
// Could not get stack boundary.
return;
}
Sample* sample = SetupSample(thread, sample_buffer, os_thread->trace_id());
sample->SetAllocationCid(cid);
if (FLAG_profile_vm) {
uintptr_t sp = Thread::GetCurrentStackPointer();
uintptr_t fp = 0;
uintptr_t pc = GetProgramCounter();
COPY_FP_REGISTER(fp);
uword stack_lower = 0;
uword stack_upper = 0;
if (!InitialRegisterCheck(pc, fp, sp)) {
return;
}
if (!GetAndValidateIsolateStackBounds(thread, fp, sp, &stack_lower,
&stack_upper)) {
// Could not get stack boundary.
return;
}
Sample* sample = SetupSample(thread, sample_buffer, os_thread->trace_id());
sample->SetAllocationCid(cid);
ProfilerNativeStackWalker native_stack_walker(
isolate, sample, sample_buffer, stack_lower, stack_upper, pc, fp, sp);
native_stack_walker.walk();
} else if (exited_dart_code) {
Sample* sample = SetupSample(thread, sample_buffer, os_thread->trace_id());
sample->SetAllocationCid(cid);
ProfilerDartExitStackWalker dart_exit_stack_walker(thread, isolate, sample,
sample_buffer);
ProfilerDartStackWalker dart_exit_stack_walker(
thread, sample, sample_buffer, stack_lower, stack_upper, pc, fp, sp,
exited_dart_code, true);
dart_exit_stack_walker.walk();
} else {
// Fall back.
@ -1214,19 +1186,15 @@ void Profiler::SampleThread(Thread* thread,
ProfilerNativeStackWalker native_stack_walker(
isolate, sample, sample_buffer, stack_lower, stack_upper, pc, fp, sp);
ProfilerDartExitStackWalker dart_exit_stack_walker(thread, isolate, sample,
sample_buffer);
ProfilerDartStackWalker dart_stack_walker(
isolate, sample, sample_buffer, stack_lower, stack_upper, pc, fp, sp);
const bool exited_dart_code = thread->HasExitedDartCode();
ProfilerDartStackWalker dart_stack_walker(thread, sample, sample_buffer,
stack_lower, stack_upper, pc, fp,
sp, exited_dart_code, false);
// All memory access is done inside CollectSample.
CollectSample(isolate, exited_dart_code, in_dart_code, sample,
&native_stack_walker, &dart_exit_stack_walker,
&dart_stack_walker, pc, fp, sp, &counters_);
&native_stack_walker, &dart_stack_walker, pc, fp, sp,
&counters_);
}

View file

@ -55,7 +55,7 @@ class Profiler : public AllStatic {
static SampleBuffer* sample_buffer() { return sample_buffer_; }
static void DumpStackTrace(void* context);
static void DumpStackTrace(bool native_stack_trace = true);
static void DumpStackTrace();
static void SampleAllocation(Thread* thread, intptr_t cid);
@ -75,10 +75,7 @@ class Profiler : public AllStatic {
}
private:
static void DumpStackTrace(bool native_stack_trace,
uword sp,
uword fp,
uword pc);
static void DumpStackTrace(uword sp, uword fp, uword pc);
// Does not walk the thread's stack.
static void SampleThreadSingleFrame(Thread* thread, uintptr_t pc);

View file

@ -252,6 +252,8 @@ TEST_CASE(Profiler_TrivialRecordAllocation) {
EXPECT(walker.Down());
EXPECT_STREQ("DRT_AllocateObject", walker.CurrentName());
EXPECT(walker.Down());
EXPECT_STREQ("[Stub] Allocate A", walker.CurrentName());
EXPECT(walker.Down());
EXPECT_STREQ("B.boo", walker.CurrentName());
EXPECT(walker.Down());
EXPECT_STREQ("main", walker.CurrentName());
@ -265,6 +267,8 @@ TEST_CASE(Profiler_TrivialRecordAllocation) {
EXPECT(walker.Down());
EXPECT_STREQ("B.boo", walker.CurrentName());
EXPECT(walker.Down());
EXPECT_STREQ("[Stub] Allocate A", walker.CurrentName());
EXPECT(walker.Down());
EXPECT_STREQ("DRT_AllocateObject", walker.CurrentName());
EXPECT(!walker.Down());
@ -274,6 +278,8 @@ TEST_CASE(Profiler_TrivialRecordAllocation) {
EXPECT(walker.Down());
EXPECT_STREQ("DRT_AllocateObject", walker.CurrentName());
EXPECT(walker.Down());
EXPECT_STREQ("[Stub] Allocate A", walker.CurrentName());
EXPECT(walker.Down());
EXPECT_STREQ("B.boo", walker.CurrentName());
EXPECT(walker.Down());
EXPECT_STREQ("main", walker.CurrentName());
@ -287,6 +293,8 @@ TEST_CASE(Profiler_TrivialRecordAllocation) {
EXPECT(walker.Down());
EXPECT_STREQ("B.boo", walker.CurrentName());
EXPECT(walker.Down());
EXPECT_STREQ("[Stub] Allocate A", walker.CurrentName());
EXPECT(walker.Down());
EXPECT_STREQ("DRT_AllocateObject", walker.CurrentName());
EXPECT(!walker.Down());
}
@ -372,6 +380,8 @@ TEST_CASE(Profiler_ToggleRecordAllocation) {
EXPECT(walker.Down());
EXPECT_STREQ("DRT_AllocateObject", walker.CurrentName());
EXPECT(walker.Down());
EXPECT_STREQ("[Stub] Allocate A", walker.CurrentName());
EXPECT(walker.Down());
EXPECT_STREQ("B.boo", walker.CurrentName());
EXPECT(walker.Down());
EXPECT_STREQ("main", walker.CurrentName());
@ -385,6 +395,8 @@ TEST_CASE(Profiler_ToggleRecordAllocation) {
EXPECT(walker.Down());
EXPECT_STREQ("B.boo", walker.CurrentName());
EXPECT(walker.Down());
EXPECT_STREQ("[Stub] Allocate A", walker.CurrentName());
EXPECT(walker.Down());
EXPECT_STREQ("DRT_AllocateObject", walker.CurrentName());
EXPECT(!walker.Down());
@ -394,6 +406,8 @@ TEST_CASE(Profiler_ToggleRecordAllocation) {
EXPECT(walker.Down());
EXPECT_STREQ("DRT_AllocateObject", walker.CurrentName());
EXPECT(walker.Down());
EXPECT_STREQ("[Stub] Allocate A", walker.CurrentName());
EXPECT(walker.Down());
EXPECT_STREQ("B.boo", walker.CurrentName());
EXPECT(walker.Down());
EXPECT_STREQ("main", walker.CurrentName());
@ -407,6 +421,8 @@ TEST_CASE(Profiler_ToggleRecordAllocation) {
EXPECT(walker.Down());
EXPECT_STREQ("B.boo", walker.CurrentName());
EXPECT(walker.Down());
EXPECT_STREQ("[Stub] Allocate A", walker.CurrentName());
EXPECT(walker.Down());
EXPECT_STREQ("DRT_AllocateObject", walker.CurrentName());
EXPECT(!walker.Down());
}
@ -499,10 +515,12 @@ TEST_CASE(Profiler_CodeTicks) {
EXPECT(walker.Down());
EXPECT_STREQ("DRT_AllocateObject", walker.CurrentName());
EXPECT(walker.Down());
EXPECT_STREQ("[Stub] Allocate A", walker.CurrentName());
EXPECT_EQ(3, walker.CurrentExclusiveTicks());
EXPECT(walker.Down());
EXPECT_STREQ("B.boo", walker.CurrentName());
EXPECT_EQ(3, walker.CurrentNodeTickCount());
EXPECT_EQ(3, walker.CurrentInclusiveTicks());
EXPECT_EQ(3, walker.CurrentExclusiveTicks());
EXPECT(walker.Down());
EXPECT_STREQ("main", walker.CurrentName());
EXPECT_EQ(3, walker.CurrentNodeTickCount());
@ -522,6 +540,8 @@ TEST_CASE(Profiler_CodeTicks) {
EXPECT_STREQ("B.boo", walker.CurrentName());
EXPECT_EQ(3, walker.CurrentNodeTickCount());
EXPECT_EQ(3, walker.CurrentInclusiveTicks());
EXPECT(walker.Down());
EXPECT_STREQ("[Stub] Allocate A", walker.CurrentName());
EXPECT_EQ(3, walker.CurrentExclusiveTicks());
EXPECT(walker.Down());
EXPECT_STREQ("DRT_AllocateObject", walker.CurrentName());
@ -598,10 +618,12 @@ TEST_CASE(Profiler_FunctionTicks) {
EXPECT(walker.Down());
EXPECT_STREQ("DRT_AllocateObject", walker.CurrentName());
EXPECT(walker.Down());
EXPECT_STREQ("[Stub] Allocate A", walker.CurrentName());
EXPECT_EQ(3, walker.CurrentExclusiveTicks());
EXPECT(walker.Down());
EXPECT_STREQ("B.boo", walker.CurrentName());
EXPECT_EQ(3, walker.CurrentNodeTickCount());
EXPECT_EQ(3, walker.CurrentInclusiveTicks());
EXPECT_EQ(3, walker.CurrentExclusiveTicks());
EXPECT(walker.Down());
EXPECT_STREQ("main", walker.CurrentName());
EXPECT_EQ(3, walker.CurrentNodeTickCount());
@ -621,6 +643,8 @@ TEST_CASE(Profiler_FunctionTicks) {
EXPECT_STREQ("B.boo", walker.CurrentName());
EXPECT_EQ(3, walker.CurrentNodeTickCount());
EXPECT_EQ(3, walker.CurrentInclusiveTicks());
EXPECT(walker.Down());
EXPECT_STREQ("[Stub] Allocate A", walker.CurrentName());
EXPECT_EQ(3, walker.CurrentExclusiveTicks());
EXPECT(walker.Down());
EXPECT_STREQ("DRT_AllocateObject", walker.CurrentName());
@ -747,6 +771,8 @@ TEST_CASE(Profiler_ArrayAllocation) {
EXPECT(walker.Down());
EXPECT_STREQ("DRT_AllocateArray", walker.CurrentName());
EXPECT(walker.Down());
EXPECT_STREQ("[Stub] AllocateArray", walker.CurrentName());
EXPECT(walker.Down());
EXPECT_STREQ("_List._List", walker.CurrentName());
EXPECT(walker.Down());
EXPECT_STREQ("List.List", walker.CurrentName());
@ -797,6 +823,8 @@ TEST_CASE(Profiler_ArrayAllocation) {
EXPECT(walker.Down());
EXPECT_STREQ("DRT_AllocateArray", walker.CurrentName());
EXPECT(walker.Down());
EXPECT_STREQ("[Stub] AllocateArray", walker.CurrentName());
EXPECT(walker.Down());
EXPECT_STREQ("_List._List", walker.CurrentName());
EXPECT(walker.Down());
EXPECT_STREQ("_GrowableList._GrowableList", walker.CurrentName());
@ -857,6 +885,8 @@ TEST_CASE(Profiler_ContextAllocation) {
EXPECT(walker.Down());
EXPECT_STREQ("DRT_AllocateContext", walker.CurrentName());
EXPECT(walker.Down());
EXPECT_STREQ("[Stub] AllocateContext", walker.CurrentName());
EXPECT(walker.Down());
EXPECT_STREQ("foo", walker.CurrentName());
EXPECT(!walker.Down());
}
@ -923,6 +953,8 @@ TEST_CASE(Profiler_ClosureAllocation) {
EXPECT(walker.Down());
EXPECT_SUBSTRING("DRT_AllocateObject", walker.CurrentName());
EXPECT(walker.Down());
EXPECT_STREQ("[Stub] Allocate _Closure", walker.CurrentName());
EXPECT(walker.Down());
EXPECT_SUBSTRING("foo", walker.CurrentName());
EXPECT(!walker.Down());
}
@ -1080,8 +1112,10 @@ TEST_CASE(Profiler_StringAllocation) {
EXPECT(walker.Down());
EXPECT_STREQ("String_concat", walker.CurrentName());
EXPECT(walker.Down());
#if 1
EXPECT_STREQ("_StringBase.+", walker.CurrentName());
EXPECT(walker.Down());
#endif
EXPECT_STREQ("foo", walker.CurrentName());
EXPECT(!walker.Down());
}
@ -1286,11 +1320,13 @@ TEST_CASE(Profiler_FunctionInline) {
EXPECT(walker.Down());
EXPECT_STREQ("DRT_AllocateObject", walker.CurrentName());
EXPECT(walker.Down());
EXPECT_STREQ("[Stub] Allocate A", walker.CurrentName());
EXPECT_EQ(50000, walker.CurrentExclusiveTicks());
EXPECT(walker.Down());
EXPECT_STREQ("B.boo", walker.CurrentName());
EXPECT_EQ(1, walker.SiblingCount());
EXPECT_EQ(50000, walker.CurrentNodeTickCount());
EXPECT_EQ(50000, walker.CurrentInclusiveTicks());
EXPECT_EQ(50000, walker.CurrentExclusiveTicks());
EXPECT(walker.Down());
EXPECT_STREQ("mainA", walker.CurrentName());
EXPECT_EQ(1, walker.SiblingCount());
@ -1311,6 +1347,8 @@ TEST_CASE(Profiler_FunctionInline) {
EXPECT_EQ(1, walker.SiblingCount());
EXPECT_EQ(50000, walker.CurrentNodeTickCount());
EXPECT_EQ(50000, walker.CurrentInclusiveTicks());
EXPECT(walker.Down());
EXPECT_STREQ("[Stub] Allocate A", walker.CurrentName());
EXPECT_EQ(50000, walker.CurrentExclusiveTicks());
EXPECT(walker.Down());
EXPECT_STREQ("DRT_AllocateObject", walker.CurrentName());
@ -1322,11 +1360,13 @@ TEST_CASE(Profiler_FunctionInline) {
EXPECT(walker.Down());
EXPECT_STREQ("DRT_AllocateObject", walker.CurrentName());
EXPECT(walker.Down());
EXPECT_STREQ("[Stub] Allocate A", walker.CurrentName());
EXPECT_EQ(50000, walker.CurrentExclusiveTicks());
EXPECT(walker.Down());
EXPECT_STREQ("B.choo", walker.CurrentName());
EXPECT_EQ(1, walker.SiblingCount());
EXPECT_EQ(50000, walker.CurrentNodeTickCount());
EXPECT_EQ(50000, walker.CurrentInclusiveTicks());
EXPECT_EQ(50000, walker.CurrentExclusiveTicks());
EXPECT(walker.Down());
EXPECT_STREQ("B.foo", walker.CurrentName());
EXPECT_EQ(1, walker.SiblingCount());
@ -1373,6 +1413,8 @@ TEST_CASE(Profiler_FunctionInline) {
EXPECT_EQ(1, walker.SiblingCount());
EXPECT_EQ(50000, walker.CurrentNodeTickCount());
EXPECT_EQ(50000, walker.CurrentInclusiveTicks());
EXPECT(walker.Down());
EXPECT_STREQ("[Stub] Allocate A", walker.CurrentName());
EXPECT_EQ(50000, walker.CurrentExclusiveTicks());
EXPECT(walker.Down());
EXPECT_STREQ("DRT_AllocateObject", walker.CurrentName());
@ -1397,6 +1439,10 @@ TEST_CASE(Profiler_FunctionInline) {
EXPECT(walker.Down());
EXPECT_STREQ("DRT_AllocateObject", walker.CurrentName());
EXPECT(walker.Down());
EXPECT_STREQ("[Stub] Allocate A", walker.CurrentName());
EXPECT(walker.Down());
EXPECT_STREQ("[Unoptimized Code]", walker.CurrentName());
EXPECT(walker.Down());
EXPECT_STREQ("B.boo", walker.CurrentName());
EXPECT(walker.Down());
EXPECT_STREQ("[Optimized Code]", walker.CurrentName());
@ -1416,6 +1462,10 @@ TEST_CASE(Profiler_FunctionInline) {
EXPECT(walker.Down());
EXPECT_STREQ("B.boo", walker.CurrentName());
EXPECT(walker.Down());
EXPECT_STREQ("[Unoptimized Code]", walker.CurrentName());
EXPECT(walker.Down());
EXPECT_STREQ("[Stub] Allocate A", walker.CurrentName());
EXPECT(walker.Down());
EXPECT_STREQ("DRT_AllocateObject", walker.CurrentName());
EXPECT(!walker.Down());
@ -1425,6 +1475,10 @@ TEST_CASE(Profiler_FunctionInline) {
EXPECT(walker.Down());
EXPECT_STREQ("DRT_AllocateObject", walker.CurrentName());
EXPECT(walker.Down());
EXPECT_STREQ("[Stub] Allocate A", walker.CurrentName());
EXPECT(walker.Down());
EXPECT_STREQ("[Unoptimized Code]", walker.CurrentName());
EXPECT(walker.Down());
EXPECT_STREQ("[Inline End]", walker.CurrentName());
EXPECT(walker.Down());
EXPECT_STREQ("B.choo", walker.CurrentName());
@ -1446,8 +1500,6 @@ TEST_CASE(Profiler_FunctionInline) {
// mainA -> B.boo -> B.foo -> B.choo.
walker.Reset(Profile::kInclusiveFunction);
EXPECT(walker.Down());
EXPECT_STREQ("[Unoptimized Code]", walker.CurrentName());
EXPECT(walker.Down());
EXPECT_STREQ("mainA", walker.CurrentName());
EXPECT(walker.Down());
EXPECT_STREQ("[Optimized Code]", walker.CurrentName());
@ -1462,6 +1514,10 @@ TEST_CASE(Profiler_FunctionInline) {
EXPECT(walker.Down());
EXPECT_STREQ("[Inline End]", walker.CurrentName());
EXPECT(walker.Down());
EXPECT_STREQ("[Unoptimized Code]", walker.CurrentName());
EXPECT(walker.Down());
EXPECT_STREQ("[Stub] Allocate A", walker.CurrentName());
EXPECT(walker.Down());
EXPECT_STREQ("DRT_AllocateObject", walker.CurrentName());
EXPECT(!walker.Down());
}
@ -1573,6 +1629,8 @@ TEST_CASE(Profiler_InliningIntervalBoundry) {
EXPECT(walker.Down());
EXPECT_STREQ("DRT_AllocateObject", walker.CurrentName());
EXPECT(walker.Down());
EXPECT_STREQ("[Stub] Allocate A", walker.CurrentName());
EXPECT(walker.Down());
EXPECT_STREQ("maybeAlloc", walker.CurrentName());
EXPECT(walker.Down());
EXPECT_STREQ("right", walker.CurrentName());
@ -1580,10 +1638,12 @@ TEST_CASE(Profiler_InliningIntervalBoundry) {
EXPECT_STREQ("a", walker.CurrentName());
EXPECT(walker.Down());
EXPECT_STREQ("mainAlloc", walker.CurrentName());
EXPECT(walker.Down()); // Account for "[Native] [xxxxxxx, xxxxxxx)"
EXPECT(!walker.Down());
// Inline expansion should show us the complete call chain:
walker.Reset(Profile::kInclusiveFunction);
EXPECT(walker.Down()); // Account for "[Native] [xxxxxxx, xxxxxxx)"
EXPECT(walker.Down());
EXPECT_STREQ("mainAlloc", walker.CurrentName());
EXPECT(walker.Down());
@ -1593,6 +1653,8 @@ TEST_CASE(Profiler_InliningIntervalBoundry) {
EXPECT(walker.Down());
EXPECT_STREQ("maybeAlloc", walker.CurrentName());
EXPECT(walker.Down());
EXPECT_STREQ("[Stub] Allocate A", walker.CurrentName());
EXPECT(walker.Down());
EXPECT_STREQ("DRT_AllocateObject", walker.CurrentName());
EXPECT(!walker.Down());
}
@ -1667,6 +1729,8 @@ TEST_CASE(Profiler_ChainedSamples) {
EXPECT(walker.Down());
EXPECT_STREQ("DRT_AllocateObject", walker.CurrentName());
EXPECT(walker.Down());
EXPECT_STREQ("[Stub] Allocate A", walker.CurrentName());
EXPECT(walker.Down());
EXPECT_STREQ("B.boo", walker.CurrentName());
EXPECT(walker.Down());
EXPECT_STREQ("orange", walker.CurrentName());
@ -1768,10 +1832,12 @@ TEST_CASE(Profiler_BasicSourcePosition) {
EXPECT(walker.Down());
EXPECT_STREQ("DRT_AllocateObject", walker.CurrentName());
EXPECT(walker.Down());
EXPECT_STREQ("[Stub] Allocate A", walker.CurrentName());
EXPECT_EQ(1, walker.CurrentExclusiveTicks());
EXPECT(walker.Down());
EXPECT_STREQ("B.boo", walker.CurrentName());
EXPECT_EQ(1, walker.CurrentNodeTickCount());
EXPECT_EQ(1, walker.CurrentInclusiveTicks());
EXPECT_EQ(1, walker.CurrentExclusiveTicks());
EXPECT_STREQ("A", walker.CurrentToken());
EXPECT(walker.Down());
EXPECT_STREQ("main", walker.CurrentName());
@ -1860,10 +1926,12 @@ TEST_CASE(Profiler_BasicSourcePositionOptimized) {
EXPECT(walker.Down());
EXPECT_STREQ("DRT_AllocateObject", walker.CurrentName());
EXPECT(walker.Down());
EXPECT_STREQ("[Stub] Allocate A", walker.CurrentName());
EXPECT_EQ(1, walker.CurrentExclusiveTicks());
EXPECT(walker.Down());
EXPECT_STREQ("B.boo", walker.CurrentName());
EXPECT_EQ(1, walker.CurrentNodeTickCount());
EXPECT_EQ(1, walker.CurrentInclusiveTicks());
EXPECT_EQ(1, walker.CurrentExclusiveTicks());
EXPECT_STREQ("A", walker.CurrentToken());
EXPECT(walker.Down());
EXPECT_STREQ("main", walker.CurrentName());
@ -1945,10 +2013,12 @@ TEST_CASE(Profiler_SourcePosition) {
EXPECT(walker.Down());
EXPECT_STREQ("DRT_AllocateObject", walker.CurrentName());
EXPECT(walker.Down());
EXPECT_STREQ("[Stub] Allocate A", walker.CurrentName());
EXPECT_EQ(1, walker.CurrentExclusiveTicks());
EXPECT(walker.Down());
EXPECT_STREQ("B.boo", walker.CurrentName());
EXPECT_EQ(1, walker.CurrentNodeTickCount());
EXPECT_EQ(1, walker.CurrentInclusiveTicks());
EXPECT_EQ(1, walker.CurrentExclusiveTicks());
EXPECT_STREQ("A", walker.CurrentToken());
EXPECT(walker.Down());
EXPECT_STREQ("B.oats", walker.CurrentName());
@ -2068,10 +2138,12 @@ TEST_CASE(Profiler_SourcePositionOptimized) {
EXPECT(walker.Down());
EXPECT_STREQ("DRT_AllocateObject", walker.CurrentName());
EXPECT(walker.Down());
EXPECT_STREQ("[Stub] Allocate A", walker.CurrentName());
EXPECT_EQ(1, walker.CurrentExclusiveTicks());
EXPECT(walker.Down());
EXPECT_STREQ("B.boo", walker.CurrentName());
EXPECT_EQ(1, walker.CurrentNodeTickCount());
EXPECT_EQ(1, walker.CurrentInclusiveTicks());
EXPECT_EQ(1, walker.CurrentExclusiveTicks());
EXPECT_STREQ("A", walker.CurrentToken());
EXPECT(walker.Down());
EXPECT_STREQ("B.oats", walker.CurrentName());
@ -2174,10 +2246,12 @@ TEST_CASE(Profiler_BinaryOperatorSourcePosition) {
EXPECT(walker.Down());
EXPECT_STREQ("DRT_AllocateObject", walker.CurrentName());
EXPECT(walker.Down());
EXPECT_STREQ("[Stub] Allocate A", walker.CurrentName());
EXPECT_EQ(1, walker.CurrentExclusiveTicks());
EXPECT(walker.Down());
EXPECT_STREQ("B.boo", walker.CurrentName());
EXPECT_EQ(1, walker.CurrentNodeTickCount());
EXPECT_EQ(1, walker.CurrentInclusiveTicks());
EXPECT_EQ(1, walker.CurrentExclusiveTicks());
EXPECT_STREQ("A", walker.CurrentToken());
EXPECT(walker.Down());
EXPECT_STREQ("B.oats", walker.CurrentName());
@ -2306,10 +2380,12 @@ TEST_CASE(Profiler_BinaryOperatorSourcePositionOptimized) {
EXPECT(walker.Down());
EXPECT_STREQ("DRT_AllocateObject", walker.CurrentName());
EXPECT(walker.Down());
EXPECT_STREQ("[Stub] Allocate A", walker.CurrentName());
EXPECT_EQ(1, walker.CurrentExclusiveTicks());
EXPECT(walker.Down());
EXPECT_STREQ("B.boo", walker.CurrentName());
EXPECT_EQ(1, walker.CurrentNodeTickCount());
EXPECT_EQ(1, walker.CurrentInclusiveTicks());
EXPECT_EQ(1, walker.CurrentExclusiveTicks());
EXPECT_STREQ("A", walker.CurrentToken());
EXPECT(walker.Down());
EXPECT_STREQ("B.oats", walker.CurrentName());

View file

@ -147,6 +147,7 @@ class StackFrame : public ValueObject {
// fields fp_ and sp_ when they return the respective frame objects.
friend class FrameSetIterator;
friend class StackFrameIterator;
friend class ProfilerDartStackWalker;
DISALLOW_COPY_AND_ASSIGN(StackFrame);
};
@ -286,6 +287,7 @@ class StackFrameIterator : public ValueObject {
StackFrame* current_frame_; // Points to the current frame in the iterator.
Thread* thread_;
friend class ProfilerDartStackWalker;
DISALLOW_COPY_AND_ASSIGN(StackFrameIterator);
};