| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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/pages.h" | 5 #include "vm/pages.h" |
| 6 | 6 |
| 7 #include "platform/assert.h" | 7 #include "platform/assert.h" |
| 8 #include "vm/compiler_stats.h" | 8 #include "vm/compiler_stats.h" |
| 9 #include "vm/gc_marker.h" | 9 #include "vm/gc_marker.h" |
| 10 #include "vm/gc_sweeper.h" | 10 #include "vm/gc_sweeper.h" |
| (...skipping 397 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 408 // TODO(koda): Control growth. | 408 // TODO(koda): Control growth. |
| 409 } | 409 } |
| 410 | 410 |
| 411 | 411 |
| 412 void PageSpace::FreeExternal(intptr_t size) { | 412 void PageSpace::FreeExternal(intptr_t size) { |
| 413 intptr_t size_in_words = size >> kWordSizeLog2; | 413 intptr_t size_in_words = size >> kWordSizeLog2; |
| 414 usage_.external_in_words -= size_in_words; | 414 usage_.external_in_words -= size_in_words; |
| 415 } | 415 } |
| 416 | 416 |
| 417 | 417 |
| 418 // Provides exclusive access to the pages, and ensures they are walkable. | 418 // Provides exclusive access to all pages, and ensures they are walkable. |
| 419 class ExclusivePageIterator : ValueObject { | 419 class ExclusivePageIterator : ValueObject { |
| 420 public: | 420 public: |
| 421 explicit ExclusivePageIterator(const PageSpace* space) | 421 explicit ExclusivePageIterator(const PageSpace* space) |
| 422 : space_(space), ml_(space->pages_lock_) { | 422 : space_(space), ml_(space->pages_lock_) { |
| 423 space_->MakeIterable(); | 423 space_->MakeIterable(); |
| 424 page_ = space_->pages_; | 424 page_ = space_->pages_; |
| 425 if (page_ == NULL) { | 425 if (page_ == NULL) { |
| 426 page_ = space_->exec_pages_; | 426 page_ = space_->exec_pages_; |
| 427 if (page_ == NULL) { | 427 if (page_ == NULL) { |
| 428 page_ = space_->large_pages_; | 428 page_ = space_->large_pages_; |
| 429 } | 429 } |
| 430 } | 430 } |
| 431 } | 431 } |
| 432 HeapPage* page() const { return page_; } | 432 HeapPage* page() const { return page_; } |
| 433 bool Done() const { return page_ == NULL; } | 433 bool Done() const { return page_ == NULL; } |
| 434 void Advance() { | 434 void Advance() { |
| 435 ASSERT(!Done()); | 435 ASSERT(!Done()); |
| 436 page_ = space_->NextPageAnySize(page_); | 436 page_ = space_->NextPageAnySize(page_); |
| 437 } | 437 } |
| 438 private: | 438 private: |
| 439 const PageSpace* space_; | 439 const PageSpace* space_; |
| 440 MutexLocker ml_; | 440 MutexLocker ml_; |
| 441 NoGCScope no_gc; | 441 NoGCScope no_gc; |
| 442 HeapPage* page_; | 442 HeapPage* page_; |
| 443 }; | 443 }; |
| 444 | 444 |
| 445 | 445 |
| 446 // Provides exclusive access to code pages, and ensures they are walkable. |
| 447 // NOTE: This does not iterate over large pages which can contain code. |
| 448 class ExclusiveCodePageIterator : ValueObject { |
| 449 public: |
| 450 explicit ExclusiveCodePageIterator(const PageSpace* space) |
| 451 : space_(space), ml_(space->pages_lock_) { |
| 452 space_->MakeIterable(); |
| 453 page_ = space_->exec_pages_; |
| 454 } |
| 455 HeapPage* page() const { return page_; } |
| 456 bool Done() const { return page_ == NULL; } |
| 457 void Advance() { |
| 458 ASSERT(!Done()); |
| 459 page_ = page_->next(); |
| 460 } |
| 461 private: |
| 462 const PageSpace* space_; |
| 463 MutexLocker ml_; |
| 464 NoGCScope no_gc; |
| 465 HeapPage* page_; |
| 466 }; |
| 467 |
| 468 |
| 469 // Provides exclusive access to large pages, and ensures they are walkable. |
| 470 class ExclusiveLargePageIterator : ValueObject { |
| 471 public: |
| 472 explicit ExclusiveLargePageIterator(const PageSpace* space) |
| 473 : space_(space), ml_(space->pages_lock_) { |
| 474 space_->MakeIterable(); |
| 475 page_ = space_->large_pages_; |
| 476 } |
| 477 HeapPage* page() const { return page_; } |
| 478 bool Done() const { return page_ == NULL; } |
| 479 void Advance() { |
| 480 ASSERT(!Done()); |
| 481 page_ = page_->next(); |
| 482 } |
| 483 private: |
| 484 const PageSpace* space_; |
| 485 MutexLocker ml_; |
| 486 NoGCScope no_gc; |
| 487 HeapPage* page_; |
| 488 }; |
| 489 |
| 490 |
| 446 void PageSpace::MakeIterable() const { | 491 void PageSpace::MakeIterable() const { |
| 447 // TODO(koda): Assert not called from concurrent sweeper task. | 492 // TODO(koda): Assert not called from concurrent sweeper task. |
| 448 if (bump_top_ < bump_end_) { | 493 if (bump_top_ < bump_end_) { |
| 449 FreeListElement::AsElement(bump_top_, bump_end_ - bump_top_); | 494 FreeListElement::AsElement(bump_top_, bump_end_ - bump_top_); |
| 450 } | 495 } |
| 451 } | 496 } |
| 452 | 497 |
| 453 | 498 |
| 454 bool PageSpace::Contains(uword addr) const { | 499 bool PageSpace::Contains(uword addr) const { |
| 455 for (ExclusivePageIterator it(this); !it.Done(); it.Advance()) { | 500 for (ExclusivePageIterator it(this); !it.Done(); it.Advance()) { |
| 456 if (it.page()->Contains(addr)) { | 501 if (it.page()->Contains(addr)) { |
| 457 return true; | 502 return true; |
| 458 } | 503 } |
| 459 } | 504 } |
| 460 return false; | 505 return false; |
| 461 } | 506 } |
| 462 | 507 |
| 463 | 508 |
| 464 bool PageSpace::Contains(uword addr, HeapPage::PageType type) const { | 509 bool PageSpace::Contains(uword addr, HeapPage::PageType type) const { |
| 510 if (type == HeapPage::kExecutable) { |
| 511 // Fast path executable pages. |
| 512 for (ExclusiveCodePageIterator it(this); !it.Done(); it.Advance()) { |
| 513 if (it.page()->Contains(addr)) { |
| 514 return true; |
| 515 } |
| 516 } |
| 517 // Large pages can be executable, walk them too. |
| 518 for (ExclusiveLargePageIterator it(this); !it.Done(); it.Advance()) { |
| 519 if ((it.page()->type() == type) && it.page()->Contains(addr)) { |
| 520 return true; |
| 521 } |
| 522 } |
| 523 return false; |
| 524 } |
| 465 for (ExclusivePageIterator it(this); !it.Done(); it.Advance()) { | 525 for (ExclusivePageIterator it(this); !it.Done(); it.Advance()) { |
| 466 if ((it.page()->type() == type) && it.page()->Contains(addr)) { | 526 if ((it.page()->type() == type) && it.page()->Contains(addr)) { |
| 467 return true; | 527 return true; |
| 468 } | 528 } |
| 469 } | 529 } |
| 470 return false; | 530 return false; |
| 471 } | 531 } |
| 472 | 532 |
| 473 | 533 |
| 474 void PageSpace::StartEndAddress(uword* start, uword* end) const { | 534 void PageSpace::StartEndAddress(uword* start, uword* end) const { |
| (...skipping 18 matching lines...) Expand all Loading... |
| 493 | 553 |
| 494 void PageSpace::VisitObjectPointers(ObjectPointerVisitor* visitor) const { | 554 void PageSpace::VisitObjectPointers(ObjectPointerVisitor* visitor) const { |
| 495 for (ExclusivePageIterator it(this); !it.Done(); it.Advance()) { | 555 for (ExclusivePageIterator it(this); !it.Done(); it.Advance()) { |
| 496 it.page()->VisitObjectPointers(visitor); | 556 it.page()->VisitObjectPointers(visitor); |
| 497 } | 557 } |
| 498 } | 558 } |
| 499 | 559 |
| 500 | 560 |
| 501 RawObject* PageSpace::FindObject(FindObjectVisitor* visitor, | 561 RawObject* PageSpace::FindObject(FindObjectVisitor* visitor, |
| 502 HeapPage::PageType type) const { | 562 HeapPage::PageType type) const { |
| 563 if (type == HeapPage::kExecutable) { |
| 564 // Fast path executable pages. |
| 565 for (ExclusiveCodePageIterator it(this); !it.Done(); it.Advance()) { |
| 566 RawObject* obj = it.page()->FindObject(visitor); |
| 567 if (obj != Object::null()) { |
| 568 return obj; |
| 569 } |
| 570 } |
| 571 // Large pages can be executable, walk them too. |
| 572 for (ExclusiveLargePageIterator it(this); !it.Done(); it.Advance()) { |
| 573 if (it.page()->type() == type) { |
| 574 RawObject* obj = it.page()->FindObject(visitor); |
| 575 if (obj != Object::null()) { |
| 576 return obj; |
| 577 } |
| 578 } |
| 579 } |
| 580 return Object::null(); |
| 581 } |
| 582 |
| 503 for (ExclusivePageIterator it(this); !it.Done(); it.Advance()) { | 583 for (ExclusivePageIterator it(this); !it.Done(); it.Advance()) { |
| 504 if (it.page()->type() == type) { | 584 if (it.page()->type() == type) { |
| 505 RawObject* obj = it.page()->FindObject(visitor); | 585 RawObject* obj = it.page()->FindObject(visitor); |
| 506 if (obj != Object::null()) { | 586 if (obj != Object::null()) { |
| 507 return obj; | 587 return obj; |
| 508 } | 588 } |
| 509 } | 589 } |
| 510 } | 590 } |
| 511 return Object::null(); | 591 return Object::null(); |
| 512 } | 592 } |
| (...skipping 509 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1022 return 0; | 1102 return 0; |
| 1023 } else { | 1103 } else { |
| 1024 ASSERT(total_time >= gc_time); | 1104 ASSERT(total_time >= gc_time); |
| 1025 int result = static_cast<int>((static_cast<double>(gc_time) / | 1105 int result = static_cast<int>((static_cast<double>(gc_time) / |
| 1026 static_cast<double>(total_time)) * 100); | 1106 static_cast<double>(total_time)) * 100); |
| 1027 return result; | 1107 return result; |
| 1028 } | 1108 } |
| 1029 } | 1109 } |
| 1030 | 1110 |
| 1031 } // namespace dart | 1111 } // namespace dart |
| OLD | NEW |