mirror of
https://github.com/dart-lang/sdk
synced 2024-09-04 16:03:44 +00:00
Reland More allocation tracing unit tests
- Context allocation unit test. - Class allocation unit test. - Adjust behaviour of RecordAllocation when we haven't exited Dart code and we aren't profiling the VM to match the sampler. - Fix tests to ignore embedder samples by default BUG= Review URL: https://codereview.chromium.org//1307593003 .
This commit is contained in:
parent
0706f6de29
commit
7e2113bc6e
|
@ -965,11 +965,6 @@ void Profiler::RecordAllocation(Isolate* isolate, intptr_t cid) {
|
|||
|
||||
const bool exited_dart_code = ExitedDart(isolate);
|
||||
|
||||
if (!exited_dart_code && !FLAG_profile_vm) {
|
||||
// No Dart frames on stack and we are not profiling the vm.
|
||||
return;
|
||||
}
|
||||
|
||||
SampleBuffer* sample_buffer = GetSampleBuffer(isolate);
|
||||
if (sample_buffer == NULL) {
|
||||
// Profiler not initialized.
|
||||
|
@ -1010,14 +1005,22 @@ void Profiler::RecordAllocation(Isolate* isolate, intptr_t cid) {
|
|||
fp,
|
||||
sp);
|
||||
native_stack_walker.walk();
|
||||
} else {
|
||||
ASSERT(exited_dart_code);
|
||||
} else if (exited_dart_code) {
|
||||
Sample* sample = SetupSample(isolate,
|
||||
sample_buffer,
|
||||
OSThread::GetCurrentThreadId());
|
||||
sample->SetAllocationCid(cid);
|
||||
ProfilerDartExitStackWalker dart_exit_stack_walker(isolate, sample);
|
||||
dart_exit_stack_walker.walk();
|
||||
} else {
|
||||
// Fall back.
|
||||
uintptr_t pc = GetProgramCounter();
|
||||
Sample* sample = SetupSample(isolate,
|
||||
sample_buffer,
|
||||
OSThread::GetCurrentThreadId());
|
||||
sample->SetAllocationCid(cid);
|
||||
sample->set_vm_tag(VMTag::kEmbedderTagId);
|
||||
sample->SetAt(0, pc);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -132,15 +132,27 @@ class AllocationFilter : public SampleFilter {
|
|||
public:
|
||||
explicit AllocationFilter(Isolate* isolate, intptr_t cid)
|
||||
: SampleFilter(isolate),
|
||||
cid_(cid) {
|
||||
cid_(cid),
|
||||
enable_embedder_ticks_(false) {
|
||||
}
|
||||
|
||||
bool FilterSample(Sample* sample) {
|
||||
return sample->is_allocation_sample() && (sample->allocation_cid() == cid_);
|
||||
if (!enable_embedder_ticks_ &&
|
||||
(sample->vm_tag() == VMTag::kEmbedderTagId)) {
|
||||
// We don't want to see embedder ticks in the test.
|
||||
return false;
|
||||
}
|
||||
return sample->is_allocation_sample() &&
|
||||
(sample->allocation_cid() == cid_);
|
||||
}
|
||||
|
||||
void set_enable_embedder_ticks(bool enable) {
|
||||
enable_embedder_ticks_ = enable;
|
||||
}
|
||||
|
||||
private:
|
||||
intptr_t cid_;
|
||||
bool enable_embedder_ticks_;
|
||||
};
|
||||
|
||||
|
||||
|
@ -693,6 +705,141 @@ TEST_CASE(Profiler_ArrayAllocation) {
|
|||
}
|
||||
|
||||
|
||||
TEST_CASE(Profiler_ContextAllocation) {
|
||||
DisableNativeProfileScope dnps;
|
||||
const char* kScript =
|
||||
"var msg1 = 'a';\n"
|
||||
"foo() {\n"
|
||||
" var msg = msg1 + msg1;\n"
|
||||
" return (x) { return '$msg + $msg'; }(msg);\n"
|
||||
"}\n";
|
||||
Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
|
||||
EXPECT_VALID(lib);
|
||||
Library& root_library = Library::Handle();
|
||||
root_library ^= Api::UnwrapHandle(lib);
|
||||
Isolate* isolate = Isolate::Current();
|
||||
|
||||
const Class& context_class =
|
||||
Class::Handle(Object::context_class());
|
||||
EXPECT(!context_class.IsNull());
|
||||
|
||||
Dart_Handle result = Dart_Invoke(lib, NewString("foo"), 0, NULL);
|
||||
EXPECT_VALID(result);
|
||||
|
||||
{
|
||||
StackZone zone(isolate);
|
||||
HANDLESCOPE(isolate);
|
||||
Profile profile(isolate);
|
||||
AllocationFilter filter(isolate, context_class.id());
|
||||
profile.Build(&filter, Profile::kNoTags);
|
||||
// We should have no allocation samples.
|
||||
EXPECT_EQ(0, profile.sample_count());
|
||||
}
|
||||
|
||||
context_class.SetTraceAllocation(true);
|
||||
result = Dart_Invoke(lib, NewString("foo"), 0, NULL);
|
||||
EXPECT_VALID(result);
|
||||
|
||||
{
|
||||
StackZone zone(isolate);
|
||||
HANDLESCOPE(isolate);
|
||||
Profile profile(isolate);
|
||||
AllocationFilter filter(isolate, context_class.id());
|
||||
profile.Build(&filter, Profile::kNoTags);
|
||||
// We should have one allocation sample.
|
||||
EXPECT_EQ(1, profile.sample_count());
|
||||
ProfileTrieWalker walker(&profile);
|
||||
|
||||
walker.Reset(Profile::kExclusiveCode);
|
||||
EXPECT(walker.Down());
|
||||
EXPECT_STREQ("foo", walker.CurrentName());
|
||||
EXPECT(!walker.Down());
|
||||
}
|
||||
|
||||
context_class.SetTraceAllocation(false);
|
||||
result = Dart_Invoke(lib, NewString("foo"), 0, NULL);
|
||||
EXPECT_VALID(result);
|
||||
|
||||
{
|
||||
StackZone zone(isolate);
|
||||
HANDLESCOPE(isolate);
|
||||
Profile profile(isolate);
|
||||
AllocationFilter filter(isolate, context_class.id());
|
||||
profile.Build(&filter, Profile::kNoTags);
|
||||
// We should still only have one allocation sample.
|
||||
EXPECT_EQ(1, profile.sample_count());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE(Profiler_ClassAllocation) {
|
||||
DisableNativeProfileScope dnps;
|
||||
const char* kScript =
|
||||
"var msg1 = 'a';\n"
|
||||
"\n"
|
||||
"foo() {\n"
|
||||
" var msg = msg1 + msg1;\n"
|
||||
" var msg2 = msg + msg;\n"
|
||||
" return (x, y, z, w) { return '$x + $y + $z'; }(msg, msg2, msg, msg);\n"
|
||||
"}\n"
|
||||
"bar() {\n"
|
||||
" var msg = msg1 + msg1;\n"
|
||||
" var msg2 = msg + msg;\n"
|
||||
" return (x, y) { return '$x + $y'; }(msg, msg2);\n"
|
||||
"}\n";
|
||||
|
||||
Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
|
||||
EXPECT_VALID(lib);
|
||||
Library& root_library = Library::Handle();
|
||||
root_library ^= Api::UnwrapHandle(lib);
|
||||
Isolate* isolate = Isolate::Current();
|
||||
|
||||
const Class& class_class =
|
||||
Class::Handle(Object::class_class());
|
||||
EXPECT(!class_class.IsNull());
|
||||
class_class.SetTraceAllocation(true);
|
||||
|
||||
// Invoke "foo" which during compilation, triggers a closure class allocation.
|
||||
Dart_Handle result = Dart_Invoke(lib, NewString("foo"), 0, NULL);
|
||||
EXPECT_VALID(result);
|
||||
|
||||
{
|
||||
StackZone zone(isolate);
|
||||
HANDLESCOPE(isolate);
|
||||
Profile profile(isolate);
|
||||
AllocationFilter filter(isolate, class_class.id());
|
||||
filter.set_enable_embedder_ticks(true);
|
||||
profile.Build(&filter, Profile::kNoTags);
|
||||
// We should have one allocation sample.
|
||||
EXPECT_EQ(1, profile.sample_count());
|
||||
ProfileTrieWalker walker(&profile);
|
||||
|
||||
walker.Reset(Profile::kExclusiveCode);
|
||||
EXPECT(walker.Down());
|
||||
EXPECT_SUBSTRING("dart::Profiler::RecordAllocation", walker.CurrentName());
|
||||
EXPECT(!walker.Down());
|
||||
}
|
||||
|
||||
// Disable allocation tracing for Class.
|
||||
class_class.SetTraceAllocation(false);
|
||||
|
||||
// Invoke "bar" which during compilation, triggers a closure class allocation.
|
||||
result = Dart_Invoke(lib, NewString("bar"), 0, NULL);
|
||||
EXPECT_VALID(result);
|
||||
|
||||
{
|
||||
StackZone zone(isolate);
|
||||
HANDLESCOPE(isolate);
|
||||
Profile profile(isolate);
|
||||
AllocationFilter filter(isolate, class_class.id());
|
||||
filter.set_enable_embedder_ticks(true);
|
||||
profile.Build(&filter, Profile::kNoTags);
|
||||
// We should still only have one allocation sample.
|
||||
EXPECT_EQ(1, profile.sample_count());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE(Profiler_TypedArrayAllocation) {
|
||||
DisableNativeProfileScope dnps;
|
||||
const char* kScript =
|
||||
|
|
Loading…
Reference in a new issue