Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(240)

Side by Side Diff: runtime/vm/profiler_test.cc

Issue 1582683003: Fall back to inlining intervals to generate stack traces in --noopt. Inlined frames will lack line … (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « runtime/vm/profiler_service.cc ('k') | tests/language/language.status » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "platform/assert.h" 5 #include "platform/assert.h"
6 6
7 #include "vm/dart_api_impl.h" 7 #include "vm/dart_api_impl.h"
8 #include "vm/dart_api_state.h" 8 #include "vm/dart_api_state.h"
9 #include "vm/globals.h" 9 #include "vm/globals.h"
10 #include "vm/profiler.h" 10 #include "vm/profiler.h"
(...skipping 16 matching lines...) Expand all
27 27
28 ~DisableNativeProfileScope() { 28 ~DisableNativeProfileScope() {
29 FLAG_profile_vm = FLAG_profile_vm_; 29 FLAG_profile_vm = FLAG_profile_vm_;
30 } 30 }
31 31
32 private: 32 private:
33 const bool FLAG_profile_vm_; 33 const bool FLAG_profile_vm_;
34 }; 34 };
35 35
36 36
37 class DisableBackgroundCompilationScope : public ValueObject {
38 public:
39 DisableBackgroundCompilationScope()
40 : FLAG_background_compilation_(FLAG_background_compilation) {
41 FLAG_background_compilation = false;
42 }
43
44 ~DisableBackgroundCompilationScope() {
45 FLAG_background_compilation = FLAG_background_compilation_;
46 }
47
48 private:
49 const bool FLAG_background_compilation_;
50 };
51
52
37 // Temporarily adjust the maximum profile depth. 53 // Temporarily adjust the maximum profile depth.
38 class MaxProfileDepthScope : public ValueObject { 54 class MaxProfileDepthScope : public ValueObject {
39 public: 55 public:
40 explicit MaxProfileDepthScope(intptr_t new_max_depth) 56 explicit MaxProfileDepthScope(intptr_t new_max_depth)
41 : FLAG_max_profile_depth_(FLAG_max_profile_depth) { 57 : FLAG_max_profile_depth_(FLAG_max_profile_depth) {
42 Profiler::SetSampleDepth(new_max_depth); 58 Profiler::SetSampleDepth(new_max_depth);
43 } 59 }
44 60
45 ~MaxProfileDepthScope() { 61 ~MaxProfileDepthScope() {
46 Profiler::SetSampleDepth(FLAG_max_profile_depth_); 62 Profiler::SetSampleDepth(FLAG_max_profile_depth_);
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
132 Isolate* isolate = Isolate::Current(); 148 Isolate* isolate = Isolate::Current();
133 SampleBuffer* sample_buffer = new SampleBuffer(3); 149 SampleBuffer* sample_buffer = new SampleBuffer(3);
134 Sample* sample = sample_buffer->ReserveSample(); 150 Sample* sample = sample_buffer->ReserveSample();
135 sample->Init(isolate, 0, 0); 151 sample->Init(isolate, 0, 0);
136 sample->set_metadata(99); 152 sample->set_metadata(99);
137 sample->set_is_allocation_sample(true); 153 sample->set_is_allocation_sample(true);
138 EXPECT_EQ(99, sample->allocation_cid()); 154 EXPECT_EQ(99, sample->allocation_cid());
139 delete sample_buffer; 155 delete sample_buffer;
140 } 156 }
141 157
158
142 static RawClass* GetClass(const Library& lib, const char* name) { 159 static RawClass* GetClass(const Library& lib, const char* name) {
143 const Class& cls = Class::Handle( 160 const Class& cls = Class::Handle(
144 lib.LookupClassAllowPrivate(String::Handle(Symbols::New(name)))); 161 lib.LookupClassAllowPrivate(String::Handle(Symbols::New(name))));
145 EXPECT(!cls.IsNull()); // No ambiguity error expected. 162 EXPECT(!cls.IsNull()); // No ambiguity error expected.
146 return cls.raw(); 163 return cls.raw();
147 } 164 }
148 165
149 166
167 static RawFunction* GetFunction(const Library& lib, const char* name) {
168 const Function& func = Function::Handle(
169 lib.LookupFunctionAllowPrivate(String::Handle(Symbols::New(name))));
170 EXPECT(!func.IsNull()); // No ambiguity error expected.
171 return func.raw();
172 }
173
174
150 class AllocationFilter : public SampleFilter { 175 class AllocationFilter : public SampleFilter {
151 public: 176 public:
152 AllocationFilter(Isolate* isolate, 177 AllocationFilter(Isolate* isolate,
153 intptr_t cid, 178 intptr_t cid,
154 int64_t time_origin_micros = -1, 179 int64_t time_origin_micros = -1,
155 int64_t time_extent_micros = -1) 180 int64_t time_extent_micros = -1)
156 : SampleFilter(isolate, 181 : SampleFilter(isolate,
157 time_origin_micros, 182 time_origin_micros,
158 time_extent_micros), 183 time_extent_micros),
159 cid_(cid), 184 cid_(cid),
(...skipping 987 matching lines...) Expand 10 before | Expand all | Expand 10 after
1147 AllocationFilter filter(isolate, one_byte_string_class.id()); 1172 AllocationFilter filter(isolate, one_byte_string_class.id());
1148 profile.Build(thread, &filter, Profile::kNoTags); 1173 profile.Build(thread, &filter, Profile::kNoTags);
1149 // We should now have two allocation samples. 1174 // We should now have two allocation samples.
1150 EXPECT_EQ(2, profile.sample_count()); 1175 EXPECT_EQ(2, profile.sample_count());
1151 } 1176 }
1152 } 1177 }
1153 1178
1154 1179
1155 TEST_CASE(Profiler_FunctionInline) { 1180 TEST_CASE(Profiler_FunctionInline) {
1156 DisableNativeProfileScope dnps; 1181 DisableNativeProfileScope dnps;
1182 DisableBackgroundCompilationScope dbcs;
1183
1157 const char* kScript = 1184 const char* kScript =
1158 "class A {\n" 1185 "class A {\n"
1159 " var a;\n" 1186 " var a;\n"
1160 " var b;\n" 1187 " var b;\n"
1161 "}\n" 1188 "}\n"
1162 "class B {\n" 1189 "class B {\n"
1163 " static choo(bool alloc) {\n" 1190 " static choo(bool alloc) {\n"
1164 " if (alloc) return new A();\n" 1191 " if (alloc) return new A();\n"
1165 " return alloc && alloc && !alloc;\n" 1192 " return alloc && alloc && !alloc;\n"
1166 " }\n" 1193 " }\n"
1167 " static foo(bool alloc) {\n" 1194 " static foo(bool alloc) {\n"
1168 " choo(alloc);\n" 1195 " choo(alloc);\n"
1169 " }\n" 1196 " }\n"
1170 " static boo(bool alloc) {\n" 1197 " static boo(bool alloc) {\n"
1171 " for (var i = 0; i < 50000; i++) {\n" 1198 " for (var i = 0; i < 50000; i++) {\n"
1172 " foo(alloc);\n" 1199 " foo(alloc);\n"
1173 " }\n" 1200 " }\n"
1174 " }\n" 1201 " }\n"
1175 "}\n" 1202 "}\n"
1176 "main() {\n" 1203 "main() {\n"
1177 " B.boo(false);\n" 1204 " B.boo(false);\n"
1178 "}\n" 1205 "}\n"
1179 "mainA() {\n" 1206 "mainA() {\n"
1180 " B.boo(true);\n" 1207 " B.boo(true);\n"
1181 "}\n"; 1208 "}\n";
1182 1209
1183 const bool old_flag = FLAG_background_compilation;
1184 FLAG_background_compilation = false;
1185 Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL); 1210 Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
1186 EXPECT_VALID(lib); 1211 EXPECT_VALID(lib);
1187 Library& root_library = Library::Handle(); 1212 Library& root_library = Library::Handle();
1188 root_library ^= Api::UnwrapHandle(lib); 1213 root_library ^= Api::UnwrapHandle(lib);
1189 1214
1190 const Class& class_a = Class::Handle(GetClass(root_library, "A")); 1215 const Class& class_a = Class::Handle(GetClass(root_library, "A"));
1191 EXPECT(!class_a.IsNull()); 1216 EXPECT(!class_a.IsNull());
1192 1217
1193 // Compile "main". 1218 // Compile "main".
1194 Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL); 1219 Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL);
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after
1391 EXPECT(walker.Down()); 1416 EXPECT(walker.Down());
1392 EXPECT_STREQ("[Inline Start]", walker.CurrentName()); 1417 EXPECT_STREQ("[Inline Start]", walker.CurrentName());
1393 EXPECT(walker.Down()); 1418 EXPECT(walker.Down());
1394 EXPECT_STREQ("B.foo", walker.CurrentName()); 1419 EXPECT_STREQ("B.foo", walker.CurrentName());
1395 EXPECT(walker.Down()); 1420 EXPECT(walker.Down());
1396 EXPECT_STREQ("B.choo", walker.CurrentName()); 1421 EXPECT_STREQ("B.choo", walker.CurrentName());
1397 EXPECT(walker.Down()); 1422 EXPECT(walker.Down());
1398 EXPECT_STREQ("[Inline End]", walker.CurrentName()); 1423 EXPECT_STREQ("[Inline End]", walker.CurrentName());
1399 EXPECT(!walker.Down()); 1424 EXPECT(!walker.Down());
1400 } 1425 }
1401 FLAG_background_compilation = old_flag;
1402 } 1426 }
1403 1427
1404 1428
1429 TEST_CASE(Profiler_InliningIntervalBoundry) {
1430 // The PC of frames below the top frame is a call's return address,
1431 // which can belong to a different inlining interval than the call.
1432 // This test checks the profiler service takes this into account; see
1433 // ProfileBuilder::ProcessFrame.
1434
1435 DisableNativeProfileScope dnps;
1436 DisableBackgroundCompilationScope dbcs;
1437 const char* kScript =
1438 "class A {\n"
1439 "}\n"
1440 "bool alloc = false;"
1441 "maybeAlloc() {\n"
1442 " try {\n"
1443 " if (alloc) new A();\n"
1444 " } catch (e) {\n"
1445 " }\n"
1446 "}\n"
1447 "right() => maybeAlloc();\n"
1448 "doNothing() {\n"
1449 " try {\n"
1450 " } catch (e) {\n"
1451 " }\n"
1452 "}\n"
1453 "wrong() => doNothing();\n"
1454 "a() {\n"
1455 " try {\n"
1456 " right();\n"
1457 " wrong();\n"
1458 " } catch (e) {\n"
1459 " }\n"
1460 "}\n"
1461 "mainNoAlloc() {\n"
1462 " for (var i = 0; i < 20000; i++) {\n"
1463 " a();\n"
1464 " }\n"
1465 "}\n"
1466 "mainAlloc() {\n"
1467 " alloc = true;\n"
1468 " a();\n"
1469 "}\n";
1470
1471 Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
1472 EXPECT_VALID(lib);
1473 Library& root_library = Library::Handle();
1474 root_library ^= Api::UnwrapHandle(lib);
1475
1476 const Class& class_a = Class::Handle(GetClass(root_library, "A"));
1477 EXPECT(!class_a.IsNull());
1478
1479 // Compile and optimize.
1480 Dart_Handle result = Dart_Invoke(lib, NewString("mainNoAlloc"), 0, NULL);
1481 EXPECT_VALID(result);
1482 result = Dart_Invoke(lib, NewString("mainAlloc"), 0, NULL);
1483 EXPECT_VALID(result);
1484
1485 // At this point a should be optimized and have inlined both right and wrong,
1486 // but not maybeAllocate or doNothing.
1487 Function& func = Function::Handle();
1488 func = GetFunction(root_library, "a");
1489 EXPECT(!func.is_inlinable());
1490 EXPECT(func.HasOptimizedCode());
1491 func = GetFunction(root_library, "right");
1492 EXPECT(func.is_inlinable());
1493 func = GetFunction(root_library, "wrong");
1494 EXPECT(func.is_inlinable());
1495 func = GetFunction(root_library, "doNothing");
1496 EXPECT(!func.is_inlinable());
1497 func = GetFunction(root_library, "maybeAlloc");
1498 EXPECT(!func.is_inlinable());
1499
1500 {
1501 Thread* thread = Thread::Current();
1502 Isolate* isolate = thread->isolate();
1503 StackZone zone(thread);
1504 HANDLESCOPE(thread);
1505 Profile profile(isolate);
1506 AllocationFilter filter(isolate, class_a.id());
1507 profile.Build(thread, &filter, Profile::kNoTags);
1508 // We should have no allocation samples.
1509 EXPECT_EQ(0, profile.sample_count());
1510 }
1511
1512 // Turn on allocation tracing for A.
1513 class_a.SetTraceAllocation(true);
1514
1515 result = Dart_Invoke(lib, NewString("mainAlloc"), 0, NULL);
1516 EXPECT_VALID(result);
1517
1518 {
1519 Thread* thread = Thread::Current();
1520 Isolate* isolate = thread->isolate();
1521 StackZone zone(thread);
1522 HANDLESCOPE(thread);
1523 Profile profile(isolate);
1524 AllocationFilter filter(isolate, class_a.id());
1525 profile.Build(thread, &filter, Profile::kNoTags);
1526 EXPECT_EQ(1, profile.sample_count());
1527 ProfileTrieWalker walker(&profile);
1528
1529 // Inline expansion should show us the complete call chain:
1530 walker.Reset(Profile::kExclusiveFunction);
1531 EXPECT(walker.Down());
1532 EXPECT_STREQ("maybeAlloc", walker.CurrentName());
1533 EXPECT(walker.Down());
1534 EXPECT_STREQ("right", walker.CurrentName());
1535 EXPECT(walker.Down());
1536 EXPECT_STREQ("a", walker.CurrentName());
1537 EXPECT(walker.Down());
1538 EXPECT_STREQ("mainAlloc", walker.CurrentName());
1539 EXPECT(!walker.Down());
1540
1541 // Inline expansion should show us the complete call chain:
1542 walker.Reset(Profile::kInclusiveFunction);
1543 EXPECT(walker.Down());
1544 EXPECT_STREQ("mainAlloc", walker.CurrentName());
1545 EXPECT(walker.Down());
1546 EXPECT_STREQ("a", walker.CurrentName());
1547 EXPECT(walker.Down());
1548 EXPECT_STREQ("right", walker.CurrentName());
1549 EXPECT(walker.Down());
1550 EXPECT_STREQ("maybeAlloc", walker.CurrentName());
1551 EXPECT(!walker.Down());
1552 }
1553 }
1554
1555
1405 TEST_CASE(Profiler_ChainedSamples) { 1556 TEST_CASE(Profiler_ChainedSamples) {
1406 MaxProfileDepthScope mpds(32); 1557 MaxProfileDepthScope mpds(32);
1407 DisableNativeProfileScope dnps; 1558 DisableNativeProfileScope dnps;
1408 1559
1409 // Each sample holds 8 stack frames. 1560 // Each sample holds 8 stack frames.
1410 // This chain is 20 stack frames deep. 1561 // This chain is 20 stack frames deep.
1411 const char* kScript = 1562 const char* kScript =
1412 "class A {\n" 1563 "class A {\n"
1413 " var a;\n" 1564 " var a;\n"
1414 " var b;\n" 1565 " var b;\n"
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
1506 EXPECT(walker.Down()); 1657 EXPECT(walker.Down());
1507 EXPECT_STREQ("go", walker.CurrentName()); 1658 EXPECT_STREQ("go", walker.CurrentName());
1508 EXPECT(walker.Down()); 1659 EXPECT(walker.Down());
1509 EXPECT_STREQ("main", walker.CurrentName()); 1660 EXPECT_STREQ("main", walker.CurrentName());
1510 EXPECT(!walker.Down()); 1661 EXPECT(!walker.Down());
1511 } 1662 }
1512 } 1663 }
1513 1664
1514 } // namespace dart 1665 } // namespace dart
1515 1666
OLDNEW
« no previous file with comments | « runtime/vm/profiler_service.cc ('k') | tests/language/language.status » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698