| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 223 } | 223 } |
| 224 #endif | 224 #endif |
| 225 | 225 |
| 226 | 226 |
| 227 void MarkCompactCollector::AddEvacuationCandidate(Page* p) { | 227 void MarkCompactCollector::AddEvacuationCandidate(Page* p) { |
| 228 p->MarkEvacuationCandidate(); | 228 p->MarkEvacuationCandidate(); |
| 229 evacuation_candidates_.Add(p); | 229 evacuation_candidates_.Add(p); |
| 230 } | 230 } |
| 231 | 231 |
| 232 | 232 |
| 233 bool MarkCompactCollector::StartCompaction() { | 233 static void TraceFragmentation(PagedSpace* space) { |
| 234 int number_of_pages = space->CountTotalPages(); |
| 235 intptr_t reserved = (number_of_pages * space->AreaSize()); |
| 236 intptr_t free = reserved - space->SizeOfObjects(); |
| 237 PrintF("[%s]: %d pages, %d (%.1f%%) free\n", |
| 238 AllocationSpaceName(space->identity()), |
| 239 number_of_pages, |
| 240 static_cast<int>(free), |
| 241 static_cast<double>(free) * 100 / reserved); |
| 242 } |
| 243 |
| 244 |
| 245 bool MarkCompactCollector::StartCompaction(CompactionMode mode) { |
| 234 if (!compacting_) { | 246 if (!compacting_) { |
| 235 ASSERT(evacuation_candidates_.length() == 0); | 247 ASSERT(evacuation_candidates_.length() == 0); |
| 236 | 248 |
| 237 CollectEvacuationCandidates(heap()->old_pointer_space()); | 249 CollectEvacuationCandidates(heap()->old_pointer_space()); |
| 238 CollectEvacuationCandidates(heap()->old_data_space()); | 250 CollectEvacuationCandidates(heap()->old_data_space()); |
| 239 | 251 |
| 240 if (FLAG_compact_code_space) { | 252 if (mode == NON_INCREMENTAL_COMPACTION) { |
| 241 CollectEvacuationCandidates(heap()->code_space()); | 253 CollectEvacuationCandidates(heap()->code_space()); |
| 254 } else if (FLAG_trace_fragmentation) { |
| 255 TraceFragmentation(heap()->code_space()); |
| 256 } |
| 257 |
| 258 if (FLAG_trace_fragmentation) { |
| 259 TraceFragmentation(heap()->map_space()); |
| 260 TraceFragmentation(heap()->cell_space()); |
| 242 } | 261 } |
| 243 | 262 |
| 244 heap()->old_pointer_space()->EvictEvacuationCandidatesFromFreeLists(); | 263 heap()->old_pointer_space()->EvictEvacuationCandidatesFromFreeLists(); |
| 245 heap()->old_data_space()->EvictEvacuationCandidatesFromFreeLists(); | 264 heap()->old_data_space()->EvictEvacuationCandidatesFromFreeLists(); |
| 246 heap()->code_space()->EvictEvacuationCandidatesFromFreeLists(); | 265 heap()->code_space()->EvictEvacuationCandidatesFromFreeLists(); |
| 247 | 266 |
| 248 compacting_ = evacuation_candidates_.length() > 0; | 267 compacting_ = evacuation_candidates_.length() > 0; |
| 249 } | 268 } |
| 250 | 269 |
| 251 return compacting_; | 270 return compacting_; |
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 407 case CELL_SPACE: return "CELL_SPACE"; | 426 case CELL_SPACE: return "CELL_SPACE"; |
| 408 case LO_SPACE: return "LO_SPACE"; | 427 case LO_SPACE: return "LO_SPACE"; |
| 409 default: | 428 default: |
| 410 UNREACHABLE(); | 429 UNREACHABLE(); |
| 411 } | 430 } |
| 412 | 431 |
| 413 return NULL; | 432 return NULL; |
| 414 } | 433 } |
| 415 | 434 |
| 416 | 435 |
| 436 // Returns zero for pages that have so little fragmentation that it is not |
| 437 // worth defragmenting them. Otherwise a positive integer that gives an |
| 438 // estimate of fragmentation on an arbitrary scale. |
| 439 static int FreeListFragmentation(PagedSpace* space, Page* p) { |
| 440 // If page was not swept then there are no free list items on it. |
| 441 if (!p->WasSwept()) { |
| 442 if (FLAG_trace_fragmentation) { |
| 443 PrintF("%p [%s]: %d bytes live (unswept)\n", |
| 444 reinterpret_cast<void*>(p), |
| 445 AllocationSpaceName(space->identity()), |
| 446 p->LiveBytes()); |
| 447 } |
| 448 return 0; |
| 449 } |
| 450 |
| 451 FreeList::SizeStats sizes; |
| 452 space->CountFreeListItems(p, &sizes); |
| 453 |
| 454 intptr_t ratio; |
| 455 intptr_t ratio_threshold; |
| 456 int area_size = space->AreaSize(); |
| 457 if (space->identity() == CODE_SPACE) { |
| 458 ratio = (sizes.medium_size_ * 10 + sizes.large_size_ * 2) * 100 / |
| 459 area_size; |
| 460 ratio_threshold = 10; |
| 461 } else { |
| 462 ratio = (sizes.small_size_ * 5 + sizes.medium_size_) * 100 / |
| 463 area_size; |
| 464 ratio_threshold = 15; |
| 465 } |
| 466 |
| 467 if (FLAG_trace_fragmentation) { |
| 468 PrintF("%p [%s]: %d (%.2f%%) %d (%.2f%%) %d (%.2f%%) %d (%.2f%%) %s\n", |
| 469 reinterpret_cast<void*>(p), |
| 470 AllocationSpaceName(space->identity()), |
| 471 static_cast<int>(sizes.small_size_), |
| 472 static_cast<double>(sizes.small_size_ * 100) / |
| 473 area_size, |
| 474 static_cast<int>(sizes.medium_size_), |
| 475 static_cast<double>(sizes.medium_size_ * 100) / |
| 476 area_size, |
| 477 static_cast<int>(sizes.large_size_), |
| 478 static_cast<double>(sizes.large_size_ * 100) / |
| 479 area_size, |
| 480 static_cast<int>(sizes.huge_size_), |
| 481 static_cast<double>(sizes.huge_size_ * 100) / |
| 482 area_size, |
| 483 (ratio > ratio_threshold) ? "[fragmented]" : ""); |
| 484 } |
| 485 |
| 486 if (FLAG_always_compact && sizes.Total() != area_size) { |
| 487 return 1; |
| 488 } |
| 489 |
| 490 if (ratio <= ratio_threshold) return 0; // Not fragmented. |
| 491 |
| 492 return static_cast<int>(ratio - ratio_threshold); |
| 493 } |
| 494 |
| 495 |
| 417 void MarkCompactCollector::CollectEvacuationCandidates(PagedSpace* space) { | 496 void MarkCompactCollector::CollectEvacuationCandidates(PagedSpace* space) { |
| 418 ASSERT(space->identity() == OLD_POINTER_SPACE || | 497 ASSERT(space->identity() == OLD_POINTER_SPACE || |
| 419 space->identity() == OLD_DATA_SPACE || | 498 space->identity() == OLD_DATA_SPACE || |
| 420 space->identity() == CODE_SPACE); | 499 space->identity() == CODE_SPACE); |
| 421 | 500 |
| 422 int number_of_pages = space->CountTotalPages(); | 501 int number_of_pages = space->CountTotalPages(); |
| 423 | 502 |
| 424 PageIterator it(space); | |
| 425 const int kMaxMaxEvacuationCandidates = 1000; | 503 const int kMaxMaxEvacuationCandidates = 1000; |
| 426 int max_evacuation_candidates = Min( | 504 int max_evacuation_candidates = Min( |
| 427 kMaxMaxEvacuationCandidates, | 505 kMaxMaxEvacuationCandidates, |
| 428 static_cast<int>(sqrt(static_cast<double>(number_of_pages / 2)) + 1)); | 506 static_cast<int>(sqrt(static_cast<double>(number_of_pages / 2)) + 1)); |
| 429 | 507 |
| 430 if (FLAG_stress_compaction || FLAG_always_compact) { | 508 if (FLAG_stress_compaction || FLAG_always_compact) { |
| 431 max_evacuation_candidates = kMaxMaxEvacuationCandidates; | 509 max_evacuation_candidates = kMaxMaxEvacuationCandidates; |
| 432 } | 510 } |
| 433 | 511 |
| 434 class Candidate { | 512 class Candidate { |
| 435 public: | 513 public: |
| 436 Candidate() : fragmentation_(0), page_(NULL) { } | 514 Candidate() : fragmentation_(0), page_(NULL) { } |
| 437 Candidate(int f, Page* p) : fragmentation_(f), page_(p) { } | 515 Candidate(int f, Page* p) : fragmentation_(f), page_(p) { } |
| 438 | 516 |
| 439 int fragmentation() { return fragmentation_; } | 517 int fragmentation() { return fragmentation_; } |
| 440 Page* page() { return page_; } | 518 Page* page() { return page_; } |
| 441 | 519 |
| 442 private: | 520 private: |
| 443 int fragmentation_; | 521 int fragmentation_; |
| 444 Page* page_; | 522 Page* page_; |
| 445 }; | 523 }; |
| 446 | 524 |
| 525 enum CompactionMode { |
| 526 COMPACT_FREE_LISTS, |
| 527 REDUCE_MEMORY_FOOTPRINT |
| 528 }; |
| 529 |
| 530 CompactionMode mode = COMPACT_FREE_LISTS; |
| 531 |
| 532 intptr_t reserved = number_of_pages * space->AreaSize(); |
| 533 intptr_t over_reserved = reserved - space->SizeOfObjects(); |
| 534 static const intptr_t kFreenessThreshold = 50; |
| 535 |
| 536 if (over_reserved >= 2 * space->AreaSize() && |
| 537 reduce_memory_footprint_) { |
| 538 mode = REDUCE_MEMORY_FOOTPRINT; |
| 539 |
| 540 // We expect that empty pages are easier to compact so slightly bump the |
| 541 // limit. |
| 542 max_evacuation_candidates += 2; |
| 543 |
| 544 if (FLAG_trace_fragmentation) { |
| 545 PrintF("Estimated over reserved memory: %.1f MB (setting threshold %d)\n", |
| 546 static_cast<double>(over_reserved) / MB, |
| 547 static_cast<int>(kFreenessThreshold)); |
| 548 } |
| 549 } |
| 550 |
| 551 intptr_t estimated_release = 0; |
| 552 |
| 447 Candidate candidates[kMaxMaxEvacuationCandidates]; | 553 Candidate candidates[kMaxMaxEvacuationCandidates]; |
| 448 | 554 |
| 449 int count = 0; | 555 int count = 0; |
| 450 if (it.has_next()) it.next(); // Never compact the first page. | |
| 451 int fragmentation = 0; | 556 int fragmentation = 0; |
| 452 Candidate* least = NULL; | 557 Candidate* least = NULL; |
| 558 |
| 559 PageIterator it(space); |
| 560 if (it.has_next()) it.next(); // Never compact the first page. |
| 561 |
| 453 while (it.has_next()) { | 562 while (it.has_next()) { |
| 454 Page* p = it.next(); | 563 Page* p = it.next(); |
| 455 p->ClearEvacuationCandidate(); | 564 p->ClearEvacuationCandidate(); |
| 565 |
| 456 if (FLAG_stress_compaction) { | 566 if (FLAG_stress_compaction) { |
| 457 int counter = space->heap()->ms_count(); | 567 int counter = space->heap()->ms_count(); |
| 458 uintptr_t page_number = reinterpret_cast<uintptr_t>(p) >> kPageSizeBits; | 568 uintptr_t page_number = reinterpret_cast<uintptr_t>(p) >> kPageSizeBits; |
| 459 if ((counter & 1) == (page_number & 1)) fragmentation = 1; | 569 if ((counter & 1) == (page_number & 1)) fragmentation = 1; |
| 570 } else if (mode == REDUCE_MEMORY_FOOTPRINT) { |
| 571 // Don't try to release too many pages. |
| 572 if (estimated_release >= ((over_reserved * 3) / 4)) { |
| 573 continue; |
| 574 } |
| 575 |
| 576 intptr_t free_bytes = 0; |
| 577 |
| 578 if (!p->WasSwept()) { |
| 579 free_bytes = (p->size() - p->LiveBytes()); |
| 580 } else { |
| 581 FreeList::SizeStats sizes; |
| 582 space->CountFreeListItems(p, &sizes); |
| 583 free_bytes = sizes.Total(); |
| 584 } |
| 585 |
| 586 int free_pct = static_cast<int>(free_bytes * 100 / p->area_size()); |
| 587 |
| 588 if (free_pct >= kFreenessThreshold) { |
| 589 estimated_release += p->area_size() + |
| 590 (p->area_size() - free_bytes); |
| 591 fragmentation = free_pct; |
| 592 } else { |
| 593 fragmentation = 0; |
| 594 } |
| 595 |
| 596 if (FLAG_trace_fragmentation) { |
| 597 PrintF("%p [%s]: %d (%.2f%%) free %s\n", |
| 598 reinterpret_cast<void*>(p), |
| 599 AllocationSpaceName(space->identity()), |
| 600 static_cast<int>(free_bytes), |
| 601 static_cast<double>(free_bytes * 100) / p->area_size(), |
| 602 (fragmentation > 0) ? "[fragmented]" : ""); |
| 603 } |
| 460 } else { | 604 } else { |
| 461 fragmentation = space->Fragmentation(p); | 605 fragmentation = FreeListFragmentation(space, p); |
| 462 } | 606 } |
| 607 |
| 463 if (fragmentation != 0) { | 608 if (fragmentation != 0) { |
| 464 if (count < max_evacuation_candidates) { | 609 if (count < max_evacuation_candidates) { |
| 465 candidates[count++] = Candidate(fragmentation, p); | 610 candidates[count++] = Candidate(fragmentation, p); |
| 466 } else { | 611 } else { |
| 467 if (least == NULL) { | 612 if (least == NULL) { |
| 468 for (int i = 0; i < max_evacuation_candidates; i++) { | 613 for (int i = 0; i < max_evacuation_candidates; i++) { |
| 469 if (least == NULL || | 614 if (least == NULL || |
| 470 candidates[i].fragmentation() < least->fragmentation()) { | 615 candidates[i].fragmentation() < least->fragmentation()) { |
| 471 least = candidates + i; | 616 least = candidates + i; |
| 472 } | 617 } |
| 473 } | 618 } |
| 474 } | 619 } |
| 475 if (least->fragmentation() < fragmentation) { | 620 if (least->fragmentation() < fragmentation) { |
| 476 *least = Candidate(fragmentation, p); | 621 *least = Candidate(fragmentation, p); |
| 477 least = NULL; | 622 least = NULL; |
| 478 } | 623 } |
| 479 } | 624 } |
| 480 } | 625 } |
| 481 } | 626 } |
| 627 |
| 482 for (int i = 0; i < count; i++) { | 628 for (int i = 0; i < count; i++) { |
| 483 AddEvacuationCandidate(candidates[i].page()); | 629 AddEvacuationCandidate(candidates[i].page()); |
| 484 } | 630 } |
| 485 | 631 |
| 486 if (count > 0 && FLAG_trace_fragmentation) { | 632 if (count > 0 && FLAG_trace_fragmentation) { |
| 487 PrintF("Collected %d evacuation candidates for space %s\n", | 633 PrintF("Collected %d evacuation candidates for space %s\n", |
| 488 count, | 634 count, |
| 489 AllocationSpaceName(space->identity())); | 635 AllocationSpaceName(space->identity())); |
| 490 } | 636 } |
| 491 } | 637 } |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 545 if (was_marked_incrementally_ && PreciseSweepingRequired()) { | 691 if (was_marked_incrementally_ && PreciseSweepingRequired()) { |
| 546 heap()->incremental_marking()->Abort(); | 692 heap()->incremental_marking()->Abort(); |
| 547 ClearMarkbits(); | 693 ClearMarkbits(); |
| 548 AbortCompaction(); | 694 AbortCompaction(); |
| 549 was_marked_incrementally_ = false; | 695 was_marked_incrementally_ = false; |
| 550 } | 696 } |
| 551 | 697 |
| 552 // Don't start compaction if we are in the middle of incremental | 698 // Don't start compaction if we are in the middle of incremental |
| 553 // marking cycle. We did not collect any slots. | 699 // marking cycle. We did not collect any slots. |
| 554 if (!FLAG_never_compact && !was_marked_incrementally_) { | 700 if (!FLAG_never_compact && !was_marked_incrementally_) { |
| 555 StartCompaction(); | 701 StartCompaction(NON_INCREMENTAL_COMPACTION); |
| 556 } | 702 } |
| 557 | 703 |
| 558 PagedSpaces spaces; | 704 PagedSpaces spaces; |
| 559 for (PagedSpace* space = spaces.next(); | 705 for (PagedSpace* space = spaces.next(); |
| 560 space != NULL; | 706 space != NULL; |
| 561 space = spaces.next()) { | 707 space = spaces.next()) { |
| 562 space->PrepareForMarkCompact(); | 708 space->PrepareForMarkCompact(); |
| 563 } | 709 } |
| 564 | 710 |
| 565 #ifdef DEBUG | 711 #ifdef DEBUG |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 657 candidate->set_code(shared->code()); | 803 candidate->set_code(shared->code()); |
| 658 } | 804 } |
| 659 | 805 |
| 660 // We are in the middle of a GC cycle so the write barrier in the code | 806 // We are in the middle of a GC cycle so the write barrier in the code |
| 661 // setter did not record the slot update and we have to do that manually. | 807 // setter did not record the slot update and we have to do that manually. |
| 662 Address slot = candidate->address() + JSFunction::kCodeEntryOffset; | 808 Address slot = candidate->address() + JSFunction::kCodeEntryOffset; |
| 663 Code* target = Code::cast(Code::GetObjectFromEntryAddress(slot)); | 809 Code* target = Code::cast(Code::GetObjectFromEntryAddress(slot)); |
| 664 isolate_->heap()->mark_compact_collector()-> | 810 isolate_->heap()->mark_compact_collector()-> |
| 665 RecordCodeEntrySlot(slot, target); | 811 RecordCodeEntrySlot(slot, target); |
| 666 | 812 |
| 813 RecordSharedFunctionInfoCodeSlot(shared); |
| 814 |
| 667 candidate = next_candidate; | 815 candidate = next_candidate; |
| 668 } | 816 } |
| 669 | 817 |
| 670 jsfunction_candidates_head_ = NULL; | 818 jsfunction_candidates_head_ = NULL; |
| 671 } | 819 } |
| 672 | 820 |
| 673 | 821 |
| 674 void ProcessSharedFunctionInfoCandidates() { | 822 void ProcessSharedFunctionInfoCandidates() { |
| 675 Code* lazy_compile = isolate_->builtins()->builtin(Builtins::kLazyCompile); | 823 Code* lazy_compile = isolate_->builtins()->builtin(Builtins::kLazyCompile); |
| 676 | 824 |
| 677 SharedFunctionInfo* candidate = shared_function_info_candidates_head_; | 825 SharedFunctionInfo* candidate = shared_function_info_candidates_head_; |
| 678 SharedFunctionInfo* next_candidate; | 826 SharedFunctionInfo* next_candidate; |
| 679 while (candidate != NULL) { | 827 while (candidate != NULL) { |
| 680 next_candidate = GetNextCandidate(candidate); | 828 next_candidate = GetNextCandidate(candidate); |
| 681 SetNextCandidate(candidate, NULL); | 829 SetNextCandidate(candidate, NULL); |
| 682 | 830 |
| 683 Code* code = candidate->code(); | 831 Code* code = candidate->code(); |
| 684 MarkBit code_mark = Marking::MarkBitFrom(code); | 832 MarkBit code_mark = Marking::MarkBitFrom(code); |
| 685 if (!code_mark.Get()) { | 833 if (!code_mark.Get()) { |
| 686 candidate->set_code(lazy_compile); | 834 candidate->set_code(lazy_compile); |
| 687 } | 835 } |
| 688 | 836 |
| 837 RecordSharedFunctionInfoCodeSlot(candidate); |
| 838 |
| 689 candidate = next_candidate; | 839 candidate = next_candidate; |
| 690 } | 840 } |
| 691 | 841 |
| 692 shared_function_info_candidates_head_ = NULL; | 842 shared_function_info_candidates_head_ = NULL; |
| 693 } | 843 } |
| 694 | 844 |
| 845 void RecordSharedFunctionInfoCodeSlot(SharedFunctionInfo* shared) { |
| 846 Object** slot = HeapObject::RawField(shared, |
| 847 SharedFunctionInfo::kCodeOffset); |
| 848 isolate_->heap()->mark_compact_collector()-> |
| 849 RecordSlot(slot, slot, HeapObject::cast(*slot)); |
| 850 } |
| 851 |
| 695 static JSFunction** GetNextCandidateField(JSFunction* candidate) { | 852 static JSFunction** GetNextCandidateField(JSFunction* candidate) { |
| 696 return reinterpret_cast<JSFunction**>( | 853 return reinterpret_cast<JSFunction**>( |
| 697 candidate->address() + JSFunction::kCodeEntryOffset); | 854 candidate->address() + JSFunction::kCodeEntryOffset); |
| 698 } | 855 } |
| 699 | 856 |
| 700 static JSFunction* GetNextCandidate(JSFunction* candidate) { | 857 static JSFunction* GetNextCandidate(JSFunction* candidate) { |
| 701 return *GetNextCandidateField(candidate); | 858 return *GetNextCandidateField(candidate); |
| 702 } | 859 } |
| 703 | 860 |
| 704 static void SetNextCandidate(JSFunction* candidate, | 861 static void SetNextCandidate(JSFunction* candidate, |
| (...skipping 456 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1161 // Make sure this is a RegExp that actually contains code. | 1318 // Make sure this is a RegExp that actually contains code. |
| 1162 if (re->TypeTagUnchecked() != JSRegExp::IRREGEXP) return; | 1319 if (re->TypeTagUnchecked() != JSRegExp::IRREGEXP) return; |
| 1163 | 1320 |
| 1164 Object* code = re->DataAtUnchecked(JSRegExp::code_index(is_ascii)); | 1321 Object* code = re->DataAtUnchecked(JSRegExp::code_index(is_ascii)); |
| 1165 if (!code->IsSmi() && | 1322 if (!code->IsSmi() && |
| 1166 HeapObject::cast(code)->map()->instance_type() == CODE_TYPE) { | 1323 HeapObject::cast(code)->map()->instance_type() == CODE_TYPE) { |
| 1167 // Save a copy that can be reinstated if we need the code again. | 1324 // Save a copy that can be reinstated if we need the code again. |
| 1168 re->SetDataAtUnchecked(JSRegExp::saved_code_index(is_ascii), | 1325 re->SetDataAtUnchecked(JSRegExp::saved_code_index(is_ascii), |
| 1169 code, | 1326 code, |
| 1170 heap); | 1327 heap); |
| 1328 |
| 1329 // Saving a copy might create a pointer into compaction candidate |
| 1330 // that was not observed by marker. This might happen if JSRegExp data |
| 1331 // was marked through the compilation cache before marker reached JSRegExp |
| 1332 // object. |
| 1333 FixedArray* data = FixedArray::cast(re->data()); |
| 1334 Object** slot = data->data_start() + JSRegExp::saved_code_index(is_ascii); |
| 1335 heap->mark_compact_collector()-> |
| 1336 RecordSlot(slot, slot, code); |
| 1337 |
| 1171 // Set a number in the 0-255 range to guarantee no smi overflow. | 1338 // Set a number in the 0-255 range to guarantee no smi overflow. |
| 1172 re->SetDataAtUnchecked(JSRegExp::code_index(is_ascii), | 1339 re->SetDataAtUnchecked(JSRegExp::code_index(is_ascii), |
| 1173 Smi::FromInt(heap->sweep_generation() & 0xff), | 1340 Smi::FromInt(heap->sweep_generation() & 0xff), |
| 1174 heap); | 1341 heap); |
| 1175 } else if (code->IsSmi()) { | 1342 } else if (code->IsSmi()) { |
| 1176 int value = Smi::cast(code)->value(); | 1343 int value = Smi::cast(code)->value(); |
| 1177 // The regexp has not been compiled yet or there was a compilation error. | 1344 // The regexp has not been compiled yet or there was a compilation error. |
| 1178 if (value == JSRegExp::kUninitializedValue || | 1345 if (value == JSRegExp::kUninitializedValue || |
| 1179 value == JSRegExp::kCompilationErrorValue) { | 1346 value == JSRegExp::kCompilationErrorValue) { |
| 1180 return; | 1347 return; |
| (...skipping 2063 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3244 slots_buffer_allocator_.DeallocateChain(&migration_slots_buffer_); | 3411 slots_buffer_allocator_.DeallocateChain(&migration_slots_buffer_); |
| 3245 ASSERT(migration_slots_buffer_ == NULL); | 3412 ASSERT(migration_slots_buffer_ == NULL); |
| 3246 for (int i = 0; i < npages; i++) { | 3413 for (int i = 0; i < npages; i++) { |
| 3247 Page* p = evacuation_candidates_[i]; | 3414 Page* p = evacuation_candidates_[i]; |
| 3248 if (!p->IsEvacuationCandidate()) continue; | 3415 if (!p->IsEvacuationCandidate()) continue; |
| 3249 PagedSpace* space = static_cast<PagedSpace*>(p->owner()); | 3416 PagedSpace* space = static_cast<PagedSpace*>(p->owner()); |
| 3250 space->Free(p->area_start(), p->area_size()); | 3417 space->Free(p->area_start(), p->area_size()); |
| 3251 p->set_scan_on_scavenge(false); | 3418 p->set_scan_on_scavenge(false); |
| 3252 slots_buffer_allocator_.DeallocateChain(p->slots_buffer_address()); | 3419 slots_buffer_allocator_.DeallocateChain(p->slots_buffer_address()); |
| 3253 p->ClearEvacuationCandidate(); | 3420 p->ClearEvacuationCandidate(); |
| 3421 p->ResetLiveBytes(); |
| 3422 space->ReleasePage(p); |
| 3254 } | 3423 } |
| 3255 evacuation_candidates_.Rewind(0); | 3424 evacuation_candidates_.Rewind(0); |
| 3256 compacting_ = false; | 3425 compacting_ = false; |
| 3257 } | 3426 } |
| 3258 | 3427 |
| 3259 | 3428 |
| 3260 static const int kStartTableEntriesPerLine = 5; | 3429 static const int kStartTableEntriesPerLine = 5; |
| 3261 static const int kStartTableLines = 171; | 3430 static const int kStartTableLines = 171; |
| 3262 static const int kStartTableInvalidLine = 127; | 3431 static const int kStartTableInvalidLine = 127; |
| 3263 static const int kStartTableUnusedEntry = 126; | 3432 static const int kStartTableUnusedEntry = 126; |
| (...skipping 688 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3952 while (buffer != NULL) { | 4121 while (buffer != NULL) { |
| 3953 SlotsBuffer* next_buffer = buffer->next(); | 4122 SlotsBuffer* next_buffer = buffer->next(); |
| 3954 DeallocateBuffer(buffer); | 4123 DeallocateBuffer(buffer); |
| 3955 buffer = next_buffer; | 4124 buffer = next_buffer; |
| 3956 } | 4125 } |
| 3957 *buffer_address = NULL; | 4126 *buffer_address = NULL; |
| 3958 } | 4127 } |
| 3959 | 4128 |
| 3960 | 4129 |
| 3961 } } // namespace v8::internal | 4130 } } // namespace v8::internal |
| OLD | NEW |