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

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

Issue 2670843006: Encode inlining information in CodeSourceMap and remove inlining interval arrays. (Closed)
Patch Set: . Created 3 years, 10 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/precompiler.cc ('k') | runtime/vm/profiler_test.cc » ('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) 2015, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, 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 "vm/profiler_service.h" 5 #include "vm/profiler_service.h"
6 6
7 #include "vm/growable_array.h" 7 #include "vm/growable_array.h"
8 #include "vm/hash_map.h" 8 #include "vm/hash_map.h"
9 #include "vm/log.h" 9 #include "vm/log.h"
10 #include "vm/native_symbol.h" 10 #include "vm/native_symbol.h"
(...skipping 1031 matching lines...) Expand 10 before | Expand all | Expand 10 after
1042 OS::Print("LOOKUPS: %" Pd " HITS: %" Pd " MISSES: %" Pd "\n", total, 1042 OS::Print("LOOKUPS: %" Pd " HITS: %" Pd " MISSES: %" Pd "\n", total,
1043 cache_hit_, cache_miss_); 1043 cache_hit_, cache_miss_);
1044 } 1044 }
1045 } 1045 }
1046 1046
1047 void Get(uword pc, 1047 void Get(uword pc,
1048 const Code& code, 1048 const Code& code,
1049 ProcessedSample* sample, 1049 ProcessedSample* sample,
1050 intptr_t frame_index, 1050 intptr_t frame_index,
1051 // Outputs: 1051 // Outputs:
1052 GrowableArray<Function*>** inlined_functions, 1052 GrowableArray<const Function*>** inlined_functions,
1053 GrowableArray<TokenPosition>** inlined_token_positions, 1053 GrowableArray<TokenPosition>** inlined_token_positions,
1054 TokenPosition* token_position) { 1054 TokenPosition* token_position) {
1055 const intptr_t offset = OffsetForPC(pc, code, sample, frame_index); 1055 const intptr_t offset = OffsetForPC(pc, code, sample, frame_index);
1056 if (FindInCache(pc, offset, inlined_functions, inlined_token_positions, 1056 if (FindInCache(pc, offset, inlined_functions, inlined_token_positions,
1057 token_position)) { 1057 token_position)) {
1058 // Found in cache. 1058 // Found in cache.
1059 return; 1059 return;
1060 } 1060 }
1061 Add(pc, code, sample, frame_index, inlined_functions, 1061 Add(pc, code, sample, frame_index, inlined_functions,
1062 inlined_token_positions, token_position); 1062 inlined_token_positions, token_position);
1063 } 1063 }
1064 1064
1065 private: 1065 private:
1066 bool FindInCache(uword pc, 1066 bool FindInCache(uword pc,
1067 intptr_t offset, 1067 intptr_t offset,
1068 GrowableArray<Function*>** inlined_functions, 1068 GrowableArray<const Function*>** inlined_functions,
1069 GrowableArray<TokenPosition>** inlined_token_positions, 1069 GrowableArray<TokenPosition>** inlined_token_positions,
1070 TokenPosition* token_position) { 1070 TokenPosition* token_position) {
1071 // Simple linear scan. 1071 // Simple linear scan.
1072 for (intptr_t i = 0; i < kCacheSize; i++) { 1072 for (intptr_t i = 0; i < kCacheSize; i++) {
1073 intptr_t index = (last_hit_ + i) % kCacheSize; 1073 intptr_t index = (last_hit_ + i) % kCacheSize;
1074 if ((cache_[index].pc == pc) && (cache_[index].offset == offset)) { 1074 if ((cache_[index].pc == pc) && (cache_[index].offset == offset)) {
1075 // Hit. 1075 // Hit.
1076 if (cache_[index].inlined_functions.length() == 0) { 1076 if (cache_[index].inlined_functions.length() == 0) {
1077 *inlined_functions = NULL; 1077 *inlined_functions = NULL;
1078 *inlined_token_positions = NULL; 1078 *inlined_token_positions = NULL;
(...skipping 10 matching lines...) Expand all
1089 cache_miss_++; 1089 cache_miss_++;
1090 return false; 1090 return false;
1091 } 1091 }
1092 1092
1093 // Add to cache and fill in outputs. 1093 // Add to cache and fill in outputs.
1094 void Add(uword pc, 1094 void Add(uword pc,
1095 const Code& code, 1095 const Code& code,
1096 ProcessedSample* sample, 1096 ProcessedSample* sample,
1097 intptr_t frame_index, 1097 intptr_t frame_index,
1098 // Outputs: 1098 // Outputs:
1099 GrowableArray<Function*>** inlined_functions, 1099 GrowableArray<const Function*>** inlined_functions,
1100 GrowableArray<TokenPosition>** inlined_token_positions, 1100 GrowableArray<TokenPosition>** inlined_token_positions,
1101 TokenPosition* token_position) { 1101 TokenPosition* token_position) {
1102 const intptr_t offset = OffsetForPC(pc, code, sample, frame_index); 1102 const intptr_t offset = OffsetForPC(pc, code, sample, frame_index);
1103 CacheEntry* cache_entry = &cache_[NextFreeIndex()]; 1103 CacheEntry* cache_entry = &cache_[NextFreeIndex()];
1104 cache_entry->pc = pc; 1104 cache_entry->pc = pc;
1105 cache_entry->offset = offset; 1105 cache_entry->offset = offset;
1106 code.GetInlinedFunctionsAt(offset, &(cache_entry->inlined_functions), 1106 code.GetInlinedFunctionsAt(offset, &(cache_entry->inlined_functions),
1107 &(cache_entry->inlined_token_positions)); 1107 &(cache_entry->inlined_token_positions));
1108 cache_entry->token_position = code.GetTokenPositionAt(offset);
1109 *token_position = (cache_entry->token_position);
1110 if (cache_entry->inlined_functions.length() == 0) { 1108 if (cache_entry->inlined_functions.length() == 0) {
1111 *inlined_functions = NULL; 1109 *inlined_functions = NULL;
1112 *inlined_token_positions = NULL; 1110 *inlined_token_positions = NULL;
1111 *token_position = cache_entry->token_position = TokenPosition();
1113 return; 1112 return;
1114 } 1113 }
1115 // The inlined token position table does not include the token position
1116 // of the final call. Insert it at the beginning because the table.
1117 // is reversed.
1118 cache_entry->inlined_token_positions.InsertAt(0,
1119 cache_entry->token_position);
1120 1114
1121 // Write outputs. 1115 // Write outputs.
1122 *inlined_functions = &(cache_entry->inlined_functions); 1116 *inlined_functions = &(cache_entry->inlined_functions);
1123 *inlined_token_positions = &(cache_entry->inlined_token_positions); 1117 *inlined_token_positions = &(cache_entry->inlined_token_positions);
1118 *token_position = cache_entry->token_position =
1119 cache_entry->inlined_token_positions[0];
1124 } 1120 }
1125 1121
1126 intptr_t NextFreeIndex() { 1122 intptr_t NextFreeIndex() {
1127 cache_cursor_ = (cache_cursor_ + 1) % kCacheSize; 1123 cache_cursor_ = (cache_cursor_ + 1) % kCacheSize;
1128 return cache_cursor_; 1124 return cache_cursor_;
1129 } 1125 }
1130 1126
1131 intptr_t OffsetForPC(uword pc, 1127 intptr_t OffsetForPC(uword pc,
1132 const Code& code, 1128 const Code& code,
1133 ProcessedSample* sample, 1129 ProcessedSample* sample,
(...skipping 16 matching lines...) Expand all
1150 return offset; 1146 return offset;
1151 } 1147 }
1152 1148
1153 struct CacheEntry { 1149 struct CacheEntry {
1154 void Reset() { 1150 void Reset() {
1155 pc = 0; 1151 pc = 0;
1156 offset = 0; 1152 offset = 0;
1157 } 1153 }
1158 uword pc; 1154 uword pc;
1159 intptr_t offset; 1155 intptr_t offset;
1160 GrowableArray<Function*> inlined_functions; 1156 GrowableArray<const Function*> inlined_functions;
1161 GrowableArray<TokenPosition> inlined_token_positions; 1157 GrowableArray<TokenPosition> inlined_token_positions;
1162 TokenPosition token_position; 1158 TokenPosition token_position;
1163 }; 1159 };
1164 1160
1165 static const intptr_t kCacheSize = 128; 1161 static const intptr_t kCacheSize = 128;
1166 intptr_t cache_cursor_; 1162 intptr_t cache_cursor_;
1167 intptr_t last_hit_; 1163 intptr_t last_hit_;
1168 CacheEntry cache_[kCacheSize]; 1164 CacheEntry cache_[kCacheSize];
1169 intptr_t cache_miss_; 1165 intptr_t cache_miss_;
1170 intptr_t cache_hit_; 1166 intptr_t cache_hit_;
(...skipping 414 matching lines...) Expand 10 before | Expand all | Expand 10 after
1585 intptr_t sample_index, 1581 intptr_t sample_index,
1586 ProcessedSample* sample, 1582 ProcessedSample* sample,
1587 intptr_t frame_index) { 1583 intptr_t frame_index) {
1588 const uword pc = sample->At(frame_index); 1584 const uword pc = sample->At(frame_index);
1589 ProfileCode* profile_code = GetProfileCode(pc, sample->timestamp()); 1585 ProfileCode* profile_code = GetProfileCode(pc, sample->timestamp());
1590 ProfileFunction* function = profile_code->function(); 1586 ProfileFunction* function = profile_code->function();
1591 ASSERT(function != NULL); 1587 ASSERT(function != NULL);
1592 const intptr_t code_index = profile_code->code_table_index(); 1588 const intptr_t code_index = profile_code->code_table_index();
1593 ASSERT(profile_code != NULL); 1589 ASSERT(profile_code != NULL);
1594 const Code& code = Code::ZoneHandle(profile_code->code()); 1590 const Code& code = Code::ZoneHandle(profile_code->code());
1595 GrowableArray<Function*>* inlined_functions = NULL; 1591 GrowableArray<const Function*>* inlined_functions = NULL;
1596 GrowableArray<TokenPosition>* inlined_token_positions = NULL; 1592 GrowableArray<TokenPosition>* inlined_token_positions = NULL;
1597 TokenPosition token_position = TokenPosition::kNoSource; 1593 TokenPosition token_position = TokenPosition::kNoSource;
1598 if (!code.IsNull()) { 1594 if (!code.IsNull()) {
1599 inlined_functions_cache_.Get(pc, code, sample, frame_index, 1595 inlined_functions_cache_.Get(pc, code, sample, frame_index,
1600 &inlined_functions, &inlined_token_positions, 1596 &inlined_functions, &inlined_token_positions,
1601 &token_position); 1597 &token_position);
1602 if (FLAG_trace_profiler_verbose) { 1598 if (FLAG_trace_profiler_verbose) {
1603 for (intptr_t i = 0; i < inlined_functions->length(); i++) { 1599 for (intptr_t i = 0; i < inlined_functions->length(); i++) {
1604 const String& name = 1600 const String& name =
1605 String::Handle((*inlined_functions)[i]->QualifiedScrubbedName()); 1601 String::Handle((*inlined_functions)[i]->QualifiedScrubbedName());
1606 THR_Print("InlinedFunction[%" Pd "] = {%s, %s}\n", i, 1602 THR_Print("InlinedFunction[%" Pd "] = {%s, %s}\n", i,
1607 name.ToCString(), 1603 name.ToCString(),
1608 (*inlined_token_positions)[i].ToCString()); 1604 (*inlined_token_positions)[i].ToCString());
1609 } 1605 }
1610 } 1606 }
1611 } 1607 }
1608
1612 if (code.IsNull() || (inlined_functions == NULL) || 1609 if (code.IsNull() || (inlined_functions == NULL) ||
1613 (inlined_functions->length() == 0)) { 1610 (inlined_functions->length() <= 1)) {
1614 // No inlined functions. 1611 // No inlined functions.
1615 if (inclusive_tree_) { 1612 if (inclusive_tree_) {
1616 current = AppendKind(code, current); 1613 current = AppendKind(code, current);
1617 } 1614 }
1618 current = ProcessFunction(current, sample_index, sample, frame_index, 1615 current = ProcessFunction(current, sample_index, sample, frame_index,
1619 function, token_position, code_index); 1616 function, token_position, code_index);
1620 if (!inclusive_tree_) { 1617 if (!inclusive_tree_) {
1621 current = AppendKind(code, current); 1618 current = AppendKind(code, current);
1622 } 1619 }
1623 return current; 1620 return current;
1624 } 1621 }
1625 1622
1626 ASSERT(code.is_optimized()); 1623 ASSERT(code.is_optimized());
1627 1624
1628 if (inclusive_tree_) { 1625 if (inclusive_tree_) {
1629 for (intptr_t i = inlined_functions->length() - 1; i >= 0; i--) { 1626 for (intptr_t i = 0; i < inlined_functions->length(); i++) {
1630 Function* inlined_function = (*inlined_functions)[i]; 1627 const Function* inlined_function = (*inlined_functions)[i];
1631 ASSERT(inlined_function != NULL); 1628 ASSERT(inlined_function != NULL);
1632 ASSERT(!inlined_function->IsNull()); 1629 ASSERT(!inlined_function->IsNull());
1633 TokenPosition inlined_token_position = (*inlined_token_positions)[i]; 1630 TokenPosition inlined_token_position = (*inlined_token_positions)[i];
1634 const bool inliner = i == (inlined_functions->length() - 1); 1631 const bool inliner = i == 0;
1635 if (inliner) { 1632 if (inliner) {
1636 current = AppendKind(code, current); 1633 current = AppendKind(code, current);
1637 } 1634 }
1638 current = ProcessInlinedFunction(current, sample_index, sample, 1635 current = ProcessInlinedFunction(current, sample_index, sample,
1639 frame_index, inlined_function, 1636 frame_index, inlined_function,
1640 inlined_token_position, code_index); 1637 inlined_token_position, code_index);
1641 if (inliner) { 1638 if (inliner) {
1642 current = AppendKind(kInlineStart, current); 1639 current = AppendKind(kInlineStart, current);
1643 } 1640 }
1644 } 1641 }
1645 current = AppendKind(kInlineFinish, current); 1642 current = AppendKind(kInlineFinish, current);
1646 } else { 1643 } else {
1647 // Append the inlined children. 1644 // Append the inlined children.
1648 current = AppendKind(kInlineFinish, current); 1645 current = AppendKind(kInlineFinish, current);
1649 for (intptr_t i = 0; i < inlined_functions->length(); i++) { 1646 for (intptr_t i = inlined_functions->length() - 1; i >= 0; i--) {
1650 Function* inlined_function = (*inlined_functions)[i]; 1647 const Function* inlined_function = (*inlined_functions)[i];
1651 ASSERT(inlined_function != NULL); 1648 ASSERT(inlined_function != NULL);
1652 ASSERT(!inlined_function->IsNull()); 1649 ASSERT(!inlined_function->IsNull());
1653 TokenPosition inlined_token_position = (*inlined_token_positions)[i]; 1650 TokenPosition inlined_token_position = (*inlined_token_positions)[i];
1654 const bool inliner = i == (inlined_functions->length() - 1); 1651 const bool inliner = i == 0;
1655 if (inliner) { 1652 if (inliner) {
1656 current = AppendKind(kInlineStart, current); 1653 current = AppendKind(kInlineStart, current);
1657 } 1654 }
1658 current = ProcessInlinedFunction(current, sample_index, sample, 1655 current = ProcessInlinedFunction(current, sample_index, sample,
1659 frame_index + i, inlined_function, 1656 frame_index + i, inlined_function,
1660 inlined_token_position, code_index); 1657 inlined_token_position, code_index);
1661 if (inliner) { 1658 if (inliner) {
1662 current = AppendKind(code, current); 1659 current = AppendKind(code, current);
1663 } 1660 }
1664 } 1661 }
1665 } 1662 }
1666 1663
1667 return current; 1664 return current;
1668 } 1665 }
1669 1666
1670 ProfileFunctionTrieNode* ProcessInlinedFunction( 1667 ProfileFunctionTrieNode* ProcessInlinedFunction(
1671 ProfileFunctionTrieNode* current, 1668 ProfileFunctionTrieNode* current,
1672 intptr_t sample_index, 1669 intptr_t sample_index,
1673 ProcessedSample* sample, 1670 ProcessedSample* sample,
1674 intptr_t frame_index, 1671 intptr_t frame_index,
1675 Function* inlined_function, 1672 const Function* inlined_function,
1676 TokenPosition inlined_token_position, 1673 TokenPosition inlined_token_position,
1677 intptr_t code_index) { 1674 intptr_t code_index) {
1678 ProfileFunctionTable* function_table = profile_->functions_; 1675 ProfileFunctionTable* function_table = profile_->functions_;
1679 ProfileFunction* function = function_table->LookupOrAdd(*inlined_function); 1676 ProfileFunction* function = function_table->LookupOrAdd(*inlined_function);
1680 ASSERT(function != NULL); 1677 ASSERT(function != NULL);
1681 return ProcessFunction(current, sample_index, sample, frame_index, function, 1678 return ProcessFunction(current, sample_index, sample, frame_index, function,
1682 inlined_token_position, code_index); 1679 inlined_token_position, code_index);
1683 } 1680 }
1684 1681
1685 bool ShouldTickNode(ProcessedSample* sample, intptr_t frame_index) { 1682 bool ShouldTickNode(ProcessedSample* sample, intptr_t frame_index) {
(...skipping 1080 matching lines...) Expand 10 before | Expand all | Expand 10 after
2766 // Disable thread interrupts while processing the buffer. 2763 // Disable thread interrupts while processing the buffer.
2767 DisableThreadInterruptsScope dtis(thread); 2764 DisableThreadInterruptsScope dtis(thread);
2768 2765
2769 ClearProfileVisitor clear_profile(isolate); 2766 ClearProfileVisitor clear_profile(isolate);
2770 sample_buffer->VisitSamples(&clear_profile); 2767 sample_buffer->VisitSamples(&clear_profile);
2771 } 2768 }
2772 2769
2773 #endif // !PRODUCT 2770 #endif // !PRODUCT
2774 2771
2775 } // namespace dart 2772 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/precompiler.cc ('k') | runtime/vm/profiler_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698