| Index: runtime/vm/profiler_test.cc
|
| diff --git a/runtime/vm/profiler_test.cc b/runtime/vm/profiler_test.cc
|
| index f0472db3328d2b1bacd74eeda1efc90eeb1803c9..1efc6b1cf26316f80fb96678ce4b5b8e202da4b5 100644
|
| --- a/runtime/vm/profiler_test.cc
|
| +++ b/runtime/vm/profiler_test.cc
|
| @@ -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 =
|
|
|