OLD | NEW |
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/native_symbol.h" | 8 #include "vm/native_symbol.h" |
9 #include "vm/object.h" | 9 #include "vm/object.h" |
10 #include "vm/os.h" | 10 #include "vm/os.h" |
(...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
261 void ProfileCode::GenerateAndSetSymbolName(const char* prefix) { | 261 void ProfileCode::GenerateAndSetSymbolName(const char* prefix) { |
262 const intptr_t kBuffSize = 512; | 262 const intptr_t kBuffSize = 512; |
263 char buff[kBuffSize]; | 263 char buff[kBuffSize]; |
264 OS::SNPrint(&buff[0], kBuffSize-1, "%s [%" Px ", %" Px ")", | 264 OS::SNPrint(&buff[0], kBuffSize-1, "%s [%" Px ", %" Px ")", |
265 prefix, start(), end()); | 265 prefix, start(), end()); |
266 SetName(buff); | 266 SetName(buff); |
267 } | 267 } |
268 | 268 |
269 | 269 |
270 void ProfileCode::Tick(uword pc, bool exclusive, intptr_t serial) { | 270 void ProfileCode::Tick(uword pc, bool exclusive, intptr_t serial) { |
| 271 // If exclusive is set, tick it. |
271 if (exclusive) { | 272 if (exclusive) { |
272 exclusive_ticks_++; | 273 exclusive_ticks_++; |
273 } else { | 274 TickAddress(pc, true); |
274 if (inclusive_serial_ == serial) { | |
275 // Already ticked for this sample. | |
276 return; | |
277 } | |
278 inclusive_serial_ = serial; | |
279 inclusive_ticks_++; | |
280 } | 275 } |
281 TickAddress(pc, exclusive); | 276 // Fall through and tick inclusive count too. |
| 277 if (inclusive_serial_ == serial) { |
| 278 // Already gave inclusive tick for this sample. |
| 279 return; |
| 280 } |
| 281 inclusive_serial_ = serial; |
| 282 inclusive_ticks_++; |
| 283 TickAddress(pc, false); |
282 } | 284 } |
283 | 285 |
284 | 286 |
285 void ProfileCode::TickAddress(uword pc, bool exclusive) { | 287 void ProfileCode::TickAddress(uword pc, bool exclusive) { |
286 const intptr_t length = address_ticks_.length(); | 288 const intptr_t length = address_ticks_.length(); |
287 | 289 |
288 intptr_t i = 0; | 290 intptr_t i = 0; |
289 for (; i < length; i++) { | 291 for (; i < length; i++) { |
290 ProfileCodeAddress& entry = address_ticks_[i]; | 292 ProfileCodeAddress& entry = address_ticks_[i]; |
291 if (entry.pc() == pc) { | 293 if (entry.pc() == pc) { |
(...skipping 683 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
975 BuildFunctionTable(); | 977 BuildFunctionTable(); |
976 | 978 |
977 BuildCodeTrie(Profile::kExclusiveCode); | 979 BuildCodeTrie(Profile::kExclusiveCode); |
978 BuildCodeTrie(Profile::kInclusiveCode); | 980 BuildCodeTrie(Profile::kInclusiveCode); |
979 | 981 |
980 BuildFunctionTrie(Profile::kExclusiveFunction); | 982 BuildFunctionTrie(Profile::kExclusiveFunction); |
981 BuildFunctionTrie(Profile::kInclusiveFunction); | 983 BuildFunctionTrie(Profile::kInclusiveFunction); |
982 } | 984 } |
983 | 985 |
984 private: | 986 private: |
| 987 // Returns true if |frame_index| in |sample| is using CPU. |
| 988 static bool IsExecutingFrame(ProcessedSample* sample, intptr_t frame_index) { |
| 989 return (frame_index == 0) && (sample->first_frame_executing() || |
| 990 sample->IsAllocationSample()); |
| 991 } |
| 992 |
985 static bool IsInclusiveTrie(Profile::TrieKind kind) { | 993 static bool IsInclusiveTrie(Profile::TrieKind kind) { |
986 return (kind == Profile::kInclusiveFunction) || | 994 return (kind == Profile::kInclusiveFunction) || |
987 (kind == Profile::kInclusiveCode); | 995 (kind == Profile::kInclusiveCode); |
988 } | 996 } |
989 | 997 |
990 void Setup() { | 998 void Setup() { |
991 profile_->live_code_ = new ProfileCodeTable(); | 999 profile_->live_code_ = new ProfileCodeTable(); |
992 profile_->dead_code_ = new ProfileCodeTable(); | 1000 profile_->dead_code_ = new ProfileCodeTable(); |
993 profile_->tag_code_ = new ProfileCodeTable(); | 1001 profile_->tag_code_ = new ProfileCodeTable(); |
994 profile_->functions_ = new ProfileFunctionTable(); | 1002 profile_->functions_ = new ProfileFunctionTable(); |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1034 RegisterProfileCodeTag(VMTag::kNativeTagId); | 1042 RegisterProfileCodeTag(VMTag::kNativeTagId); |
1035 } else if (VMTag::IsRuntimeEntryTag(sample->vm_tag())) { | 1043 } else if (VMTag::IsRuntimeEntryTag(sample->vm_tag())) { |
1036 RegisterProfileCodeTag(VMTag::kRuntimeTagId); | 1044 RegisterProfileCodeTag(VMTag::kRuntimeTagId); |
1037 } | 1045 } |
1038 RegisterProfileCodeTag(sample->vm_tag()); | 1046 RegisterProfileCodeTag(sample->vm_tag()); |
1039 // Make sure user tag exists. | 1047 // Make sure user tag exists. |
1040 RegisterProfileCodeTag(sample->user_tag()); | 1048 RegisterProfileCodeTag(sample->user_tag()); |
1041 | 1049 |
1042 // Make sure that a ProfileCode objects exist for all pcs in the sample | 1050 // Make sure that a ProfileCode objects exist for all pcs in the sample |
1043 // and tick each one. | 1051 // and tick each one. |
1044 for (intptr_t i = 0; i < sample->length(); i++) { | 1052 for (intptr_t j = 0; j < sample->length(); j++) { |
1045 const uword pc = sample->At(i); | 1053 const uword pc = sample->At(j); |
1046 ASSERT(pc != 0); | 1054 ASSERT(pc != 0); |
1047 ProfileCode* code = RegisterProfileCode(pc, timestamp); | 1055 ProfileCode* code = RegisterProfileCode(pc, timestamp); |
1048 ASSERT(code != NULL); | 1056 ASSERT(code != NULL); |
1049 code->Tick(pc, (i == 0), i); | 1057 code->Tick(pc, IsExecutingFrame(sample, j), i); |
1050 } | 1058 } |
1051 } | 1059 } |
1052 } | 1060 } |
1053 | 1061 |
1054 void FinalizeCodeIndexes() { | 1062 void FinalizeCodeIndexes() { |
1055 ScopeTimer sw("ProfileBuilder::FinalizeCodeIndexes", FLAG_trace_profiler); | 1063 ScopeTimer sw("ProfileBuilder::FinalizeCodeIndexes", FLAG_trace_profiler); |
1056 ProfileCodeTable* live_table = profile_->live_code_; | 1064 ProfileCodeTable* live_table = profile_->live_code_; |
1057 ProfileCodeTable* dead_table = profile_->dead_code_; | 1065 ProfileCodeTable* dead_table = profile_->dead_code_; |
1058 ProfileCodeTable* tag_table = profile_->tag_code_; | 1066 ProfileCodeTable* tag_table = profile_->tag_code_; |
1059 const intptr_t dead_code_index_offset = live_table->length(); | 1067 const intptr_t dead_code_index_offset = live_table->length(); |
(...skipping 870 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1930 ProfileCode* code = profile_->GetCode(current_->table_index()); | 1938 ProfileCode* code = profile_->GetCode(current_->table_index()); |
1931 return code->name(); | 1939 return code->name(); |
1932 } else { | 1940 } else { |
1933 ProfileFunction* func = profile_->GetFunction(current_->table_index()); | 1941 ProfileFunction* func = profile_->GetFunction(current_->table_index()); |
1934 return func->Name(); | 1942 return func->Name(); |
1935 } | 1943 } |
1936 UNREACHABLE(); | 1944 UNREACHABLE(); |
1937 } | 1945 } |
1938 | 1946 |
1939 | 1947 |
| 1948 intptr_t ProfileTrieWalker::CurrentNodeTickCount() { |
| 1949 if (current_ == NULL) { |
| 1950 return -1; |
| 1951 } |
| 1952 return current_->count(); |
| 1953 } |
| 1954 |
| 1955 |
| 1956 intptr_t ProfileTrieWalker::CurrentInclusiveTicks() { |
| 1957 if (current_ == NULL) { |
| 1958 return -1; |
| 1959 } |
| 1960 if (code_trie_) { |
| 1961 ProfileCode* code = profile_->GetCode(current_->table_index()); |
| 1962 return code->inclusive_ticks(); |
| 1963 } else { |
| 1964 ProfileFunction* func = profile_->GetFunction(current_->table_index()); |
| 1965 return func->inclusive_ticks(); |
| 1966 } |
| 1967 UNREACHABLE(); |
| 1968 } |
| 1969 |
| 1970 |
| 1971 intptr_t ProfileTrieWalker::CurrentExclusiveTicks() { |
| 1972 if (current_ == NULL) { |
| 1973 return -1; |
| 1974 } |
| 1975 if (code_trie_) { |
| 1976 ProfileCode* code = profile_->GetCode(current_->table_index()); |
| 1977 return code->exclusive_ticks(); |
| 1978 } else { |
| 1979 ProfileFunction* func = profile_->GetFunction(current_->table_index()); |
| 1980 return func->exclusive_ticks(); |
| 1981 } |
| 1982 UNREACHABLE(); |
| 1983 } |
| 1984 |
| 1985 |
1940 bool ProfileTrieWalker::Down() { | 1986 bool ProfileTrieWalker::Down() { |
1941 if ((current_ == NULL) || (current_->NumChildren() == 0)) { | 1987 if ((current_ == NULL) || (current_->NumChildren() == 0)) { |
1942 return false; | 1988 return false; |
1943 } | 1989 } |
1944 parent_ = current_; | 1990 parent_ = current_; |
1945 current_ = current_->At(0); | 1991 current_ = current_->At(0); |
1946 return true; | 1992 return true; |
1947 } | 1993 } |
1948 | 1994 |
1949 | 1995 |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2055 ASSERT(sample_buffer != NULL); | 2101 ASSERT(sample_buffer != NULL); |
2056 | 2102 |
2057 ClearProfileVisitor clear_profile(isolate); | 2103 ClearProfileVisitor clear_profile(isolate); |
2058 sample_buffer->VisitSamples(&clear_profile); | 2104 sample_buffer->VisitSamples(&clear_profile); |
2059 | 2105 |
2060 // Enable profile interrupts. | 2106 // Enable profile interrupts. |
2061 Profiler::BeginExecution(isolate); | 2107 Profiler::BeginExecution(isolate); |
2062 } | 2108 } |
2063 | 2109 |
2064 } // namespace dart | 2110 } // namespace dart |
OLD | NEW |