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

Side by Side Diff: src/profile-generator.cc

Issue 3020002: Heap profiler: implement diffing of snapshots. (Closed)
Patch Set: Comments addressed Created 10 years, 5 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 | « src/profile-generator.h ('k') | test/cctest/test-heap-profiler.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 2010 the V8 project authors. All rights reserved. 1 // Copyright 2010 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after
174 OS::Print(" %s:%d", entry_->resource_name(), entry_->line_number()); 174 OS::Print(" %s:%d", entry_->resource_name(), entry_->line_number());
175 OS::Print("\n"); 175 OS::Print("\n");
176 for (HashMap::Entry* p = children_.Start(); 176 for (HashMap::Entry* p = children_.Start();
177 p != NULL; 177 p != NULL;
178 p = children_.Next(p)) { 178 p = children_.Next(p)) {
179 reinterpret_cast<ProfileNode*>(p->value)->Print(indent + 2); 179 reinterpret_cast<ProfileNode*>(p->value)->Print(indent + 2);
180 } 180 }
181 } 181 }
182 182
183 183
184 namespace {
185
186 class DeleteNodesCallback { 184 class DeleteNodesCallback {
187 public: 185 public:
188 void BeforeTraversingChild(ProfileNode*, ProfileNode*) { } 186 void BeforeTraversingChild(ProfileNode*, ProfileNode*) { }
189 187
190 void AfterAllChildrenTraversed(ProfileNode* node) { 188 void AfterAllChildrenTraversed(ProfileNode* node) {
191 delete node; 189 delete node;
192 } 190 }
193 191
194 void AfterChildTraversed(ProfileNode*, ProfileNode*) { } 192 void AfterChildTraversed(ProfileNode*, ProfileNode*) { }
195 }; 193 };
196 194
197 } // namespace
198
199 195
200 ProfileTree::ProfileTree() 196 ProfileTree::ProfileTree()
201 : root_entry_(Logger::FUNCTION_TAG, 197 : root_entry_(Logger::FUNCTION_TAG,
202 "", 198 "",
203 "(root)", 199 "(root)",
204 "", 200 "",
205 0, 201 0,
206 TokenEnumerator::kNoSecurityToken), 202 TokenEnumerator::kNoSecurityToken),
207 root_(new ProfileNode(this, &root_entry_)) { 203 root_(new ProfileNode(this, &root_entry_)) {
208 } 204 }
(...skipping 24 matching lines...) Expand all
233 entry != path.start() + path.length(); 229 entry != path.start() + path.length();
234 ++entry) { 230 ++entry) {
235 if (*entry != NULL) { 231 if (*entry != NULL) {
236 node = node->FindOrAddChild(*entry); 232 node = node->FindOrAddChild(*entry);
237 } 233 }
238 } 234 }
239 node->IncrementSelfTicks(); 235 node->IncrementSelfTicks();
240 } 236 }
241 237
242 238
243 namespace {
244
245 struct NodesPair { 239 struct NodesPair {
246 NodesPair(ProfileNode* src, ProfileNode* dst) 240 NodesPair(ProfileNode* src, ProfileNode* dst)
247 : src(src), dst(dst) { } 241 : src(src), dst(dst) { }
248 ProfileNode* src; 242 ProfileNode* src;
249 ProfileNode* dst; 243 ProfileNode* dst;
250 }; 244 };
251 245
252 246
253 class FilteredCloneCallback { 247 class FilteredCloneCallback {
254 public: 248 public:
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
287 return parent_token == TokenEnumerator::kNoSecurityToken 281 return parent_token == TokenEnumerator::kNoSecurityToken
288 || parent_token == security_token_id_; 282 || parent_token == security_token_id_;
289 } 283 }
290 return false; 284 return false;
291 } 285 }
292 286
293 List<NodesPair> stack_; 287 List<NodesPair> stack_;
294 int security_token_id_; 288 int security_token_id_;
295 }; 289 };
296 290
297 } // namespace
298
299 void ProfileTree::FilteredClone(ProfileTree* src, int security_token_id) { 291 void ProfileTree::FilteredClone(ProfileTree* src, int security_token_id) {
300 ms_to_ticks_scale_ = src->ms_to_ticks_scale_; 292 ms_to_ticks_scale_ = src->ms_to_ticks_scale_;
301 FilteredCloneCallback cb(root_, security_token_id); 293 FilteredCloneCallback cb(root_, security_token_id);
302 src->TraverseDepthFirst(&cb); 294 src->TraverseDepthFirst(&cb);
303 CalculateTotalTicks(); 295 CalculateTotalTicks();
304 } 296 }
305 297
306 298
307 void ProfileTree::SetTickRatePerMs(double ticks_per_ms) { 299 void ProfileTree::SetTickRatePerMs(double ticks_per_ms) {
308 ms_to_ticks_scale_ = ticks_per_ms > 0 ? 1.0 / ticks_per_ms : 1.0; 300 ms_to_ticks_scale_ = ticks_per_ms > 0 ? 1.0 / ticks_per_ms : 1.0;
309 } 301 }
310 302
311 303
312 namespace {
313
314 class Position { 304 class Position {
315 public: 305 public:
316 explicit Position(ProfileNode* node) 306 explicit Position(ProfileNode* node)
317 : node(node), child_idx_(0) { } 307 : node(node), child_idx_(0) { }
318 INLINE(ProfileNode* current_child()) { 308 INLINE(ProfileNode* current_child()) {
319 return node->children()->at(child_idx_); 309 return node->children()->at(child_idx_);
320 } 310 }
321 INLINE(bool has_current_child()) { 311 INLINE(bool has_current_child()) {
322 return child_idx_ < node->children()->length(); 312 return child_idx_ < node->children()->length();
323 } 313 }
324 INLINE(void next_child()) { ++child_idx_; } 314 INLINE(void next_child()) { ++child_idx_; }
325 315
326 ProfileNode* node; 316 ProfileNode* node;
327 private: 317 private:
328 int child_idx_; 318 int child_idx_;
329 }; 319 };
330 320
331 } // namespace
332
333 321
334 // Non-recursive implementation of a depth-first post-order tree traversal. 322 // Non-recursive implementation of a depth-first post-order tree traversal.
335 template <typename Callback> 323 template <typename Callback>
336 void ProfileTree::TraverseDepthFirst(Callback* callback) { 324 void ProfileTree::TraverseDepthFirst(Callback* callback) {
337 List<Position> stack(10); 325 List<Position> stack(10);
338 stack.Add(Position(root_)); 326 stack.Add(Position(root_));
339 while (stack.length() > 0) { 327 while (stack.length() > 0) {
340 Position& current = stack.last(); 328 Position& current = stack.last();
341 if (current.has_current_child()) { 329 if (current.has_current_child()) {
342 callback->BeforeTraversingChild(current.node, current.current_child()); 330 callback->BeforeTraversingChild(current.node, current.current_child());
343 stack.Add(Position(current.current_child())); 331 stack.Add(Position(current.current_child()));
344 } else { 332 } else {
345 callback->AfterAllChildrenTraversed(current.node); 333 callback->AfterAllChildrenTraversed(current.node);
346 if (stack.length() > 1) { 334 if (stack.length() > 1) {
347 Position& parent = stack[stack.length() - 2]; 335 Position& parent = stack[stack.length() - 2];
348 callback->AfterChildTraversed(parent.node, current.node); 336 callback->AfterChildTraversed(parent.node, current.node);
349 parent.next_child(); 337 parent.next_child();
350 } 338 }
351 // Remove child from the stack. 339 // Remove child from the stack.
352 stack.RemoveLast(); 340 stack.RemoveLast();
353 } 341 }
354 } 342 }
355 } 343 }
356 344
357 345
358 namespace {
359
360 class CalculateTotalTicksCallback { 346 class CalculateTotalTicksCallback {
361 public: 347 public:
362 void BeforeTraversingChild(ProfileNode*, ProfileNode*) { } 348 void BeforeTraversingChild(ProfileNode*, ProfileNode*) { }
363 349
364 void AfterAllChildrenTraversed(ProfileNode* node) { 350 void AfterAllChildrenTraversed(ProfileNode* node) {
365 node->IncreaseTotalTicks(node->self_ticks()); 351 node->IncreaseTotalTicks(node->self_ticks());
366 } 352 }
367 353
368 void AfterChildTraversed(ProfileNode* parent, ProfileNode* child) { 354 void AfterChildTraversed(ProfileNode* parent, ProfileNode* child) {
369 parent->IncreaseTotalTicks(child->total_ticks()); 355 parent->IncreaseTotalTicks(child->total_ticks());
370 } 356 }
371 }; 357 };
372 358
373 } // namespace
374
375 359
376 void ProfileTree::CalculateTotalTicks() { 360 void ProfileTree::CalculateTotalTicks() {
377 CalculateTotalTicksCallback cb; 361 CalculateTotalTicksCallback cb;
378 TraverseDepthFirst(&cb); 362 TraverseDepthFirst(&cb);
379 } 363 }
380 364
381 365
382 void ProfileTree::ShortPrint() { 366 void ProfileTree::ShortPrint() {
383 OS::Print("root: %u %u %.2fms %.2fms\n", 367 OS::Print("root: %u %u %.2fms %.2fms\n",
384 root_->total_ticks(), root_->self_ticks(), 368 root_->total_ticks(), root_->self_ticks(),
(...skipping 485 matching lines...) Expand 10 before | Expand all | Expand 10 after
870 void HeapEntry::SetPropertyReference(const char* name, HeapEntry* entry) { 854 void HeapEntry::SetPropertyReference(const char* name, HeapEntry* entry) {
871 AddEdge(new HeapGraphEdge(HeapGraphEdge::PROPERTY, name, this, entry)); 855 AddEdge(new HeapGraphEdge(HeapGraphEdge::PROPERTY, name, this, entry));
872 } 856 }
873 857
874 858
875 void HeapEntry::SetAutoIndexReference(HeapEntry* entry) { 859 void HeapEntry::SetAutoIndexReference(HeapEntry* entry) {
876 SetElementReference(next_auto_index_++, entry); 860 SetElementReference(next_auto_index_++, entry);
877 } 861 }
878 862
879 863
864 void HeapEntry::SetUnidirAutoIndexReference(HeapEntry* entry) {
865 children_.Add(new HeapGraphEdge(next_auto_index_++, this, entry));
866 }
867
868
880 int HeapEntry::TotalSize() { 869 int HeapEntry::TotalSize() {
881 return total_size_ != kUnknownSize ? total_size_ : CalculateTotalSize(); 870 return total_size_ != kUnknownSize ? total_size_ : CalculateTotalSize();
882 } 871 }
883 872
884 873
885 int HeapEntry::NonSharedTotalSize() { 874 int HeapEntry::NonSharedTotalSize() {
886 return non_shared_total_size_ != kUnknownSize ? 875 return non_shared_total_size_ != kUnknownSize ?
887 non_shared_total_size_ : CalculateNonSharedTotalSize(); 876 non_shared_total_size_ : CalculateNonSharedTotalSize();
888 } 877 }
889 878
890 879
891 int HeapEntry::CalculateTotalSize() { 880 template<class Visitor>
892 snapshot_->ClearPaint(); 881 void HeapEntry::ApplyAndPaintAllReachable(Visitor* visitor) {
893 List<HeapEntry*> list(10); 882 List<HeapEntry*> list(10);
894 list.Add(this); 883 list.Add(this);
895 total_size_ = self_size_;
896 this->PaintReachable(); 884 this->PaintReachable();
885 visitor->Apply(this);
897 while (!list.is_empty()) { 886 while (!list.is_empty()) {
898 HeapEntry* entry = list.RemoveLast(); 887 HeapEntry* entry = list.RemoveLast();
899 const int children_count = entry->children_.length(); 888 const int children_count = entry->children_.length();
900 for (int i = 0; i < children_count; ++i) { 889 for (int i = 0; i < children_count; ++i) {
901 HeapEntry* child = entry->children_[i]->to(); 890 HeapEntry* child = entry->children_[i]->to();
902 if (!child->painted_reachable()) { 891 if (!child->painted_reachable()) {
903 list.Add(child); 892 list.Add(child);
904 child->PaintReachable(); 893 child->PaintReachable();
905 total_size_ += child->self_size_; 894 visitor->Apply(child);
906 } 895 }
907 } 896 }
908 } 897 }
898 }
899
900
901 class NullClass {
902 public:
903 void Apply(HeapEntry* entry) { }
904 };
905
906 void HeapEntry::PaintAllReachable() {
907 NullClass null;
908 ApplyAndPaintAllReachable(&null);
909 }
910
911
912 class TotalSizeCalculator {
913 public:
914 TotalSizeCalculator()
915 : total_size_(0) {
916 }
917
918 int total_size() const { return total_size_; }
919
920 void Apply(HeapEntry* entry) {
921 total_size_ += entry->self_size();
922 }
923
924 private:
925 int total_size_;
926 };
927
928 int HeapEntry::CalculateTotalSize() {
929 snapshot_->ClearPaint();
930 TotalSizeCalculator calc;
931 ApplyAndPaintAllReachable(&calc);
932 total_size_ = calc.total_size();
909 return total_size_; 933 return total_size_;
910 } 934 }
911 935
912 936
913 namespace {
914
915 class NonSharedSizeCalculator { 937 class NonSharedSizeCalculator {
916 public: 938 public:
917 NonSharedSizeCalculator() 939 NonSharedSizeCalculator()
918 : non_shared_total_size_(0) { 940 : non_shared_total_size_(0) {
919 } 941 }
920 942
921 int non_shared_total_size() const { return non_shared_total_size_; } 943 int non_shared_total_size() const { return non_shared_total_size_; }
922 944
923 void Apply(HeapEntry* entry) { 945 void Apply(HeapEntry* entry) {
924 if (entry->painted_reachable()) { 946 if (entry->painted_reachable()) {
925 non_shared_total_size_ += entry->self_size(); 947 non_shared_total_size_ += entry->self_size();
926 } 948 }
927 } 949 }
928 950
929 private: 951 private:
930 int non_shared_total_size_; 952 int non_shared_total_size_;
931 }; 953 };
932 954
933 } // namespace
934
935 int HeapEntry::CalculateNonSharedTotalSize() { 955 int HeapEntry::CalculateNonSharedTotalSize() {
936 // To calculate non-shared total size, first we paint all reachable 956 // To calculate non-shared total size, first we paint all reachable
937 // nodes in one color, then we paint all nodes reachable from other 957 // nodes in one color, then we paint all nodes reachable from other
938 // nodes with a different color. Then we consider only nodes painted 958 // nodes with a different color. Then we consider only nodes painted
939 // with the first color for caclulating the total size. 959 // with the first color for calculating the total size.
940 snapshot_->ClearPaint(); 960 snapshot_->ClearPaint();
961 PaintAllReachable();
962
941 List<HeapEntry*> list(10); 963 List<HeapEntry*> list(10);
942 list.Add(this); 964 if (this != snapshot_->root()) {
943 this->PaintReachable(); 965 list.Add(snapshot_->root());
966 snapshot_->root()->PaintReachableFromOthers();
967 }
944 while (!list.is_empty()) { 968 while (!list.is_empty()) {
945 HeapEntry* entry = list.RemoveLast(); 969 HeapEntry* entry = list.RemoveLast();
946 const int children_count = entry->children_.length(); 970 const int children_count = entry->children_.length();
947 for (int i = 0; i < children_count; ++i) { 971 for (int i = 0; i < children_count; ++i) {
948 HeapEntry* child = entry->children_[i]->to(); 972 HeapEntry* child = entry->children_[i]->to();
949 if (!child->painted_reachable()) { 973 if (child != this && child->not_painted_reachable_from_others()) {
950 list.Add(child); 974 list.Add(child);
951 child->PaintReachable();
952 }
953 }
954 }
955
956 List<HeapEntry*> list2(10);
957 if (this != snapshot_->root()) {
958 list2.Add(snapshot_->root());
959 snapshot_->root()->PaintReachableFromOthers();
960 }
961 while (!list2.is_empty()) {
962 HeapEntry* entry = list2.RemoveLast();
963 const int children_count = entry->children_.length();
964 for (int i = 0; i < children_count; ++i) {
965 HeapEntry* child = entry->children_[i]->to();
966 if (child != this && child->not_painted_reachable_from_others()) {
967 list2.Add(child);
968 child->PaintReachableFromOthers(); 975 child->PaintReachableFromOthers();
969 } 976 }
970 } 977 }
971 } 978 }
972 979
973 NonSharedSizeCalculator calculator; 980 NonSharedSizeCalculator calculator;
974 snapshot_->IterateEntries(&calculator); 981 snapshot_->IterateEntries(&calculator);
975 return calculator.non_shared_total_size(); 982 non_shared_total_size_ = calculator.non_shared_total_size();
983 return non_shared_total_size_;
976 } 984 }
977 985
978 986
979 class CachedHeapGraphPath { 987 class CachedHeapGraphPath {
980 public: 988 public:
981 CachedHeapGraphPath() 989 CachedHeapGraphPath()
982 : nodes_(NodesMatch) { } 990 : nodes_(NodesMatch) { }
983 CachedHeapGraphPath(const CachedHeapGraphPath& src) 991 CachedHeapGraphPath(const CachedHeapGraphPath& src)
984 : nodes_(NodesMatch, &HashMap::DefaultAllocator, src.nodes_.capacity()), 992 : nodes_(NodesMatch, &HashMap::DefaultAllocator, src.nodes_.capacity()),
985 path_(src.path_.length() + 1) { 993 path_(src.path_.length() + 1) {
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
1071 1079
1072 for (int i = 0; i < retainers_.length(); ++i) { 1080 for (int i = 0; i < retainers_.length(); ++i) {
1073 HeapGraphEdge* edge = retainers_[i]; 1081 HeapGraphEdge* edge = retainers_[i];
1074 edge->from()->RemoveChild(edge); 1082 edge->from()->RemoveChild(edge);
1075 } 1083 }
1076 retainers_.Clear(); 1084 retainers_.Clear();
1077 } 1085 }
1078 1086
1079 1087
1080 void HeapEntry::Print(int max_depth, int indent) { 1088 void HeapEntry::Print(int max_depth, int indent) {
1081 OS::Print("%6d %6d %6d ", self_size_, TotalSize(), NonSharedTotalSize()); 1089 OS::Print("%6d %6d %6d [%ld] ",
1090 self_size_, TotalSize(), NonSharedTotalSize(), id_);
1082 if (type_ != STRING) { 1091 if (type_ != STRING) {
1083 OS::Print("%s %.40s\n", TypeAsString(), name_); 1092 OS::Print("%s %.40s\n", TypeAsString(), name_);
1084 } else { 1093 } else {
1085 OS::Print("\""); 1094 OS::Print("\"");
1086 const char* c = name_; 1095 const char* c = name_;
1087 while (*c && (c - name_) <= 40) { 1096 while (*c && (c - name_) <= 40) {
1088 if (*c != '\n') 1097 if (*c != '\n')
1089 OS::Print("%c", *c); 1098 OS::Print("%c", *c);
1090 else 1099 else
1091 OS::Print("\\n"); 1100 OS::Print("\\n");
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after
1237 cache_entry->value = entry; 1246 cache_entry->value = entry;
1238 } 1247 }
1239 1248
1240 1249
1241 HeapSnapshot::HeapSnapshot(HeapSnapshotsCollection* collection, 1250 HeapSnapshot::HeapSnapshot(HeapSnapshotsCollection* collection,
1242 const char* title, 1251 const char* title,
1243 unsigned uid) 1252 unsigned uid)
1244 : collection_(collection), 1253 : collection_(collection),
1245 title_(title), 1254 title_(title),
1246 uid_(uid), 1255 uid_(uid),
1247 root_(this) { 1256 root_(this),
1257 sorted_entries_(NULL) {
1248 } 1258 }
1249 1259
1250 1260
1261 HeapSnapshot::~HeapSnapshot() {
1262 delete sorted_entries_;
1263 }
1264
1265
1251 void HeapSnapshot::ClearPaint() { 1266 void HeapSnapshot::ClearPaint() {
1252 root_.ClearPaint(); 1267 root_.ClearPaint();
1253 entries_.Apply(&HeapEntry::ClearPaint); 1268 entries_.Apply(&HeapEntry::ClearPaint);
1254 } 1269 }
1255 1270
1256 1271
1257 HeapEntry* HeapSnapshot::GetEntry(Object* obj) { 1272 HeapEntry* HeapSnapshot::GetEntry(Object* obj) {
1258 if (!obj->IsHeapObject()) return NULL; 1273 if (!obj->IsHeapObject()) return NULL;
1259 HeapObject* object = HeapObject::cast(obj); 1274 HeapObject* object = HeapObject::cast(obj);
1260 1275
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
1348 } 1363 }
1349 } 1364 }
1350 1365
1351 1366
1352 HeapEntry* HeapSnapshot::AddEntry(HeapObject* object, 1367 HeapEntry* HeapSnapshot::AddEntry(HeapObject* object,
1353 HeapEntry::Type type, 1368 HeapEntry::Type type,
1354 const char* name) { 1369 const char* name) {
1355 HeapEntry* entry = new HeapEntry(this, 1370 HeapEntry* entry = new HeapEntry(this,
1356 type, 1371 type,
1357 name, 1372 name,
1373 collection_->GetObjectId(object->address()),
1358 GetObjectSize(object), 1374 GetObjectSize(object),
1359 GetObjectSecurityToken(object)); 1375 GetObjectSecurityToken(object));
1360 entries_.Pair(object, entry); 1376 entries_.Pair(object, entry);
1361 1377
1362 // Detect, if this is a JS global object of the current context, and 1378 // Detect, if this is a JS global object of the current context, and
1363 // add it to snapshot's roots. There can be several JS global objects 1379 // add it to snapshot's roots. There can be several JS global objects
1364 // in a context. 1380 // in a context.
1365 if (object->IsJSGlobalProxy()) { 1381 if (object->IsJSGlobalProxy()) {
1366 int global_security_token = GetGlobalSecurityToken(); 1382 int global_security_token = GetGlobalSecurityToken();
1367 int object_security_token = 1383 int object_security_token =
1368 collection_->token_enumerator()->GetTokenId( 1384 collection_->token_enumerator()->GetTokenId(
1369 Context::cast( 1385 Context::cast(
1370 JSGlobalProxy::cast(object)->context())->security_token()); 1386 JSGlobalProxy::cast(object)->context())->security_token());
1371 if (object_security_token == TokenEnumerator::kNoSecurityToken 1387 if (object_security_token == TokenEnumerator::kNoSecurityToken
1372 || object_security_token == global_security_token) { 1388 || object_security_token == global_security_token) {
1373 HeapEntry* global_object_entry = 1389 HeapEntry* global_object_entry =
1374 GetEntry(HeapObject::cast(object->map()->prototype())); 1390 GetEntry(HeapObject::cast(object->map()->prototype()));
1375 ASSERT(global_object_entry != NULL); 1391 ASSERT(global_object_entry != NULL);
1376 root_.SetAutoIndexReference(global_object_entry); 1392 root_.SetAutoIndexReference(global_object_entry);
1377 } 1393 }
1378 } 1394 }
1379 1395
1380 return entry; 1396 return entry;
1381 } 1397 }
1382 1398
1383 1399
1384 namespace {
1385
1386 class EdgesCutter { 1400 class EdgesCutter {
1387 public: 1401 public:
1388 explicit EdgesCutter(int global_security_token) 1402 explicit EdgesCutter(int global_security_token)
1389 : global_security_token_(global_security_token) { 1403 : global_security_token_(global_security_token) {
1390 } 1404 }
1391 1405
1392 void Apply(HeapEntry* entry) { 1406 void Apply(HeapEntry* entry) {
1393 if (entry->security_token_id() != TokenEnumerator::kNoSecurityToken 1407 if (entry->security_token_id() != TokenEnumerator::kNoSecurityToken
1394 && entry->security_token_id() != global_security_token_) { 1408 && entry->security_token_id() != global_security_token_) {
1395 entry->CutEdges(); 1409 entry->CutEdges();
1396 } 1410 }
1397 } 1411 }
1398 1412
1399 private: 1413 private:
1400 const int global_security_token_; 1414 const int global_security_token_;
1401 }; 1415 };
1402 1416
1403 } // namespace
1404
1405 void HeapSnapshot::CutObjectsFromForeignSecurityContexts() { 1417 void HeapSnapshot::CutObjectsFromForeignSecurityContexts() {
1406 EdgesCutter cutter(GetGlobalSecurityToken()); 1418 EdgesCutter cutter(GetGlobalSecurityToken());
1407 entries_.Apply(&cutter); 1419 entries_.Apply(&cutter);
1408 } 1420 }
1409 1421
1410 1422
1411 int HeapSnapshot::GetGlobalSecurityToken() { 1423 int HeapSnapshot::GetGlobalSecurityToken() {
1412 return collection_->token_enumerator()->GetTokenId( 1424 return collection_->token_enumerator()->GetTokenId(
1413 Top::context()->global()->global_context()->security_token()); 1425 Top::context()->global()->global_context()->security_token());
1414 } 1426 }
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
1447 size += f->context()->Size(); 1459 size += f->context()->Size();
1448 } 1460 }
1449 if (f->literals()->length() != 0) { 1461 if (f->literals()->length() != 0) {
1450 size += f->literals()->Size(); 1462 size += f->literals()->Size();
1451 } 1463 }
1452 } 1464 }
1453 return size; 1465 return size;
1454 } 1466 }
1455 1467
1456 1468
1469 class EntriesCollector {
1470 public:
1471 explicit EntriesCollector(List<HeapEntry*>* list) : list_(list) { }
1472 void Apply(HeapEntry* entry) {
1473 list_->Add(entry);
1474 }
1475 private:
1476 List<HeapEntry*>* list_;
1477 };
1478
1479 template<class T>
1480 static int SortByIds(const T* entry1_ptr,
1481 const T* entry2_ptr) {
1482 if ((*entry1_ptr)->id() == (*entry2_ptr)->id()) return 0;
1483 return (*entry1_ptr)->id() < (*entry2_ptr)->id() ? -1 : 1;
1484 }
1485
1486 List<HeapEntry*>* HeapSnapshot::GetSortedEntriesList() {
1487 if (sorted_entries_ != NULL) return sorted_entries_;
1488 sorted_entries_ = new List<HeapEntry*>(entries_.capacity());
1489 EntriesCollector collector(sorted_entries_);
1490 entries_.Apply(&collector);
1491 sorted_entries_->Sort(SortByIds);
1492 return sorted_entries_;
1493 }
1494
1495
1496 HeapSnapshotsDiff* HeapSnapshot::CompareWith(HeapSnapshot* snapshot) {
1497 return collection_->CompareSnapshots(this, snapshot);
1498 }
1499
1500
1457 void HeapSnapshot::Print(int max_depth) { 1501 void HeapSnapshot::Print(int max_depth) {
1458 root_.Print(max_depth, 0); 1502 root_.Print(max_depth, 0);
1459 } 1503 }
1460 1504
1461 1505
1506 HeapObjectsMap::HeapObjectsMap()
1507 : initial_fill_mode_(true),
1508 next_id_(1),
1509 entries_map_(AddressesMatch),
1510 entries_(new List<EntryInfo>()) { }
1511
1512
1513 HeapObjectsMap::~HeapObjectsMap() {
1514 delete entries_;
1515 }
1516
1517
1518 void HeapObjectsMap::SnapshotGenerationFinished() {
1519 initial_fill_mode_ = false;
1520 RemoveDeadEntries();
1521 }
1522
1523
1524 uint64_t HeapObjectsMap::FindObject(Address addr) {
1525 if (!initial_fill_mode_) {
1526 uint64_t existing = FindEntry(addr);
1527 if (existing != 0) return existing;
1528 }
1529 uint64_t id = next_id_++;
1530 AddEntry(addr, id);
1531 return id;
1532 }
1533
1534
1535 void HeapObjectsMap::MoveObject(Address from, Address to) {
1536 HashMap::Entry* entry = entries_map_.Lookup(from, AddressHash(from), false);
1537 if (entry != NULL) {
1538 void* value = entry->value;
1539 entries_map_.Remove(from, AddressHash(from));
1540 entry = entries_map_.Lookup(to, AddressHash(to), true);
1541 ASSERT(entry->value == NULL);
1542 entry->value = value;
1543 }
1544 }
1545
1546
1547 void HeapObjectsMap::AddEntry(Address addr, uint64_t id) {
1548 HashMap::Entry* entry = entries_map_.Lookup(addr, AddressHash(addr), true);
1549 ASSERT(entry->value == NULL);
1550 entry->value = reinterpret_cast<void*>(entries_->length());
1551 entries_->Add(EntryInfo(id));
1552 }
1553
1554
1555 uint64_t HeapObjectsMap::FindEntry(Address addr) {
1556 HashMap::Entry* entry = entries_map_.Lookup(addr, AddressHash(addr), false);
1557 if (entry != NULL) {
1558 int entry_index = reinterpret_cast<intptr_t>(entry->value);
1559 EntryInfo& entry_info = entries_->at(entry_index);
1560 entry_info.accessed = true;
1561 return entry_info.id;
1562 } else {
1563 return 0;
1564 }
1565 }
1566
1567
1568 void HeapObjectsMap::RemoveDeadEntries() {
1569 List<EntryInfo>* new_entries = new List<EntryInfo>();
1570 for (HashMap::Entry* entry = entries_map_.Start();
1571 entry != NULL;
1572 entry = entries_map_.Next(entry)) {
1573 int entry_index = reinterpret_cast<intptr_t>(entry->value);
1574 EntryInfo& entry_info = entries_->at(entry_index);
1575 if (entry_info.accessed) {
1576 entry->value = reinterpret_cast<void*>(new_entries->length());
1577 new_entries->Add(EntryInfo(entry_info.id, false));
1578 }
1579 }
1580 delete entries_;
1581 entries_ = new_entries;
1582 }
1583
1584
1462 HeapSnapshotsCollection::HeapSnapshotsCollection() 1585 HeapSnapshotsCollection::HeapSnapshotsCollection()
1463 : snapshots_uids_(HeapSnapshotsMatch), 1586 : is_tracking_objects_(false),
1587 snapshots_uids_(HeapSnapshotsMatch),
1464 token_enumerator_(new TokenEnumerator()) { 1588 token_enumerator_(new TokenEnumerator()) {
1465 } 1589 }
1466 1590
1467 1591
1468 static void DeleteHeapSnapshot(HeapSnapshot** snapshot_ptr) { 1592 static void DeleteHeapSnapshot(HeapSnapshot** snapshot_ptr) {
1469 delete *snapshot_ptr; 1593 delete *snapshot_ptr;
1470 } 1594 }
1471 1595
1472 1596
1473 HeapSnapshotsCollection::~HeapSnapshotsCollection() { 1597 HeapSnapshotsCollection::~HeapSnapshotsCollection() {
1474 delete token_enumerator_; 1598 delete token_enumerator_;
1475 snapshots_.Iterate(DeleteHeapSnapshot); 1599 snapshots_.Iterate(DeleteHeapSnapshot);
1476 } 1600 }
1477 1601
1478 1602
1479 HeapSnapshot* HeapSnapshotsCollection::NewSnapshot(const char* name, 1603 HeapSnapshot* HeapSnapshotsCollection::NewSnapshot(const char* name,
1480 unsigned uid) { 1604 unsigned uid) {
1605 is_tracking_objects_ = true; // Start watching for heap objects moves.
1481 HeapSnapshot* snapshot = new HeapSnapshot(this, name, uid); 1606 HeapSnapshot* snapshot = new HeapSnapshot(this, name, uid);
1482 snapshots_.Add(snapshot); 1607 snapshots_.Add(snapshot);
1483 HashMap::Entry* entry = 1608 HashMap::Entry* entry =
1484 snapshots_uids_.Lookup(reinterpret_cast<void*>(snapshot->uid()), 1609 snapshots_uids_.Lookup(reinterpret_cast<void*>(snapshot->uid()),
1485 static_cast<uint32_t>(snapshot->uid()), 1610 static_cast<uint32_t>(snapshot->uid()),
1486 true); 1611 true);
1487 ASSERT(entry->value == NULL); 1612 ASSERT(entry->value == NULL);
1488 entry->value = snapshot; 1613 entry->value = snapshot;
1489 return snapshot; 1614 return snapshot;
1490 } 1615 }
1491 1616
1492 1617
1493 HeapSnapshot* HeapSnapshotsCollection::GetSnapshot(unsigned uid) { 1618 HeapSnapshot* HeapSnapshotsCollection::GetSnapshot(unsigned uid) {
1494 HashMap::Entry* entry = snapshots_uids_.Lookup(reinterpret_cast<void*>(uid), 1619 HashMap::Entry* entry = snapshots_uids_.Lookup(reinterpret_cast<void*>(uid),
1495 static_cast<uint32_t>(uid), 1620 static_cast<uint32_t>(uid),
1496 false); 1621 false);
1497 return entry != NULL ? reinterpret_cast<HeapSnapshot*>(entry->value) : NULL; 1622 return entry != NULL ? reinterpret_cast<HeapSnapshot*>(entry->value) : NULL;
1498 } 1623 }
1499 1624
1500 1625
1626 HeapSnapshotsDiff* HeapSnapshotsCollection::CompareSnapshots(
1627 HeapSnapshot* snapshot1,
1628 HeapSnapshot* snapshot2) {
1629 return comparator_.Compare(snapshot1, snapshot2);
1630 }
1631
1632
1501 HeapSnapshotGenerator::HeapSnapshotGenerator(HeapSnapshot* snapshot) 1633 HeapSnapshotGenerator::HeapSnapshotGenerator(HeapSnapshot* snapshot)
1502 : snapshot_(snapshot) { 1634 : snapshot_(snapshot) {
1503 } 1635 }
1504 1636
1505 1637
1506 void HeapSnapshotGenerator::GenerateSnapshot() { 1638 void HeapSnapshotGenerator::GenerateSnapshot() {
1507 AssertNoAllocation no_alloc; 1639 AssertNoAllocation no_alloc;
1508 1640
1509 // Iterate heap contents. 1641 // Iterate heap contents.
1510 HeapIterator iterator; 1642 HeapIterator iterator;
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
1623 Object* k = dictionary->KeyAt(i); 1755 Object* k = dictionary->KeyAt(i);
1624 if (dictionary->IsKey(k)) { 1756 if (dictionary->IsKey(k)) {
1625 ASSERT(k->IsNumber()); 1757 ASSERT(k->IsNumber());
1626 uint32_t index = static_cast<uint32_t>(k->Number()); 1758 uint32_t index = static_cast<uint32_t>(k->Number());
1627 snapshot_->SetElementReference(entry, index, dictionary->ValueAt(i)); 1759 snapshot_->SetElementReference(entry, index, dictionary->ValueAt(i));
1628 } 1760 }
1629 } 1761 }
1630 } 1762 }
1631 } 1763 }
1632 1764
1765
1766 static void DeleteHeapSnapshotsDiff(HeapSnapshotsDiff** diff_ptr) {
1767 delete *diff_ptr;
1768 }
1769
1770 HeapSnapshotsComparator::~HeapSnapshotsComparator() {
1771 diffs_.Iterate(DeleteHeapSnapshotsDiff);
1772 }
1773
1774
1775 HeapSnapshotsDiff* HeapSnapshotsComparator::Compare(HeapSnapshot* snapshot1,
1776 HeapSnapshot* snapshot2) {
1777 HeapSnapshotsDiff* diff = new HeapSnapshotsDiff(snapshot1, snapshot2);
1778 diffs_.Add(diff);
1779 List<HeapEntry*>* entries1 = snapshot1->GetSortedEntriesList();
1780 List<HeapEntry*>* entries2 = snapshot2->GetSortedEntriesList();
1781 int i = 0, j = 0;
1782 List<HeapEntry*> added_entries, deleted_entries;
1783 while (i < entries1->length() && j < entries2->length()) {
1784 uint64_t id1 = entries1->at(i)->id();
1785 uint64_t id2 = entries2->at(j)->id();
1786 if (id1 == id2) {
1787 i++;
1788 j++;
1789 } else if (id1 < id2) {
1790 HeapEntry* entry = entries1->at(i++);
1791 deleted_entries.Add(entry);
1792 } else {
1793 HeapEntry* entry = entries2->at(j++);
1794 added_entries.Add(entry);
1795 }
1796 }
1797 while (i < entries1->length()) {
1798 HeapEntry* entry = entries1->at(i++);
1799 deleted_entries.Add(entry);
1800 }
1801 while (j < entries2->length()) {
1802 HeapEntry* entry = entries2->at(j++);
1803 added_entries.Add(entry);
1804 }
1805
1806 snapshot1->ClearPaint();
1807 snapshot1->root()->PaintAllReachable();
1808 for (int i = 0; i < deleted_entries.length(); ++i) {
1809 HeapEntry* entry = deleted_entries[i];
1810 if (entry->painted_reachable())
1811 diff->AddDeletedEntry(entry);
1812 }
1813 snapshot2->ClearPaint();
1814 snapshot2->root()->PaintAllReachable();
1815 for (int i = 0; i < added_entries.length(); ++i) {
1816 HeapEntry* entry = added_entries[i];
1817 if (entry->painted_reachable())
1818 diff->AddAddedEntry(entry);
1819 }
1820 return diff;
1821 }
1822
1633 } } // namespace v8::internal 1823 } } // namespace v8::internal
1634 1824
1635 #endif // ENABLE_LOGGING_AND_PROFILING 1825 #endif // ENABLE_LOGGING_AND_PROFILING
OLDNEW
« no previous file with comments | « src/profile-generator.h ('k') | test/cctest/test-heap-profiler.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698