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 = |