Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 384 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 395 #endif | 395 #endif |
| 396 isolate_->counters()->memory_allocated()->Increment(alloced); | 396 isolate_->counters()->memory_allocated()->Increment(alloced); |
| 397 return mem; | 397 return mem; |
| 398 } | 398 } |
| 399 | 399 |
| 400 | 400 |
| 401 void MemoryAllocator::FreeRawMemory(void* mem, | 401 void MemoryAllocator::FreeRawMemory(void* mem, |
| 402 size_t length, | 402 size_t length, |
| 403 Executability executable) { | 403 Executability executable) { |
| 404 #ifdef DEBUG | 404 #ifdef DEBUG |
| 405 ZapBlock(reinterpret_cast<Address>(mem), length); | 405 // Do not try to zap the guard page. |
| 406 size_t guardsize = (executable == EXECUTABLE) ? Page::kPageSize : 0; | |
| 407 ZapBlock(reinterpret_cast<Address>(mem) + guardsize, length - guardsize); | |
| 406 #endif | 408 #endif |
| 407 if (isolate_->code_range()->contains(static_cast<Address>(mem))) { | 409 if (isolate_->code_range()->contains(static_cast<Address>(mem))) { |
| 408 isolate_->code_range()->FreeRawMemory(mem, length); | 410 isolate_->code_range()->FreeRawMemory(mem, length); |
| 409 } else { | 411 } else { |
| 410 OS::Free(mem, length); | 412 OS::Free(mem, length); |
| 411 } | 413 } |
| 412 isolate_->counters()->memory_allocated()->Decrement(static_cast<int>(length)); | 414 isolate_->counters()->memory_allocated()->Decrement(static_cast<int>(length)); |
| 413 size_ -= static_cast<int>(length); | 415 size_ -= static_cast<int>(length); |
| 414 if (executable == EXECUTABLE) size_executable_ -= static_cast<int>(length); | 416 if (executable == EXECUTABLE) size_executable_ -= static_cast<int>(length); |
| 415 | 417 |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 496 Page* MemoryAllocator::AllocatePages(int requested_pages, | 498 Page* MemoryAllocator::AllocatePages(int requested_pages, |
| 497 int* allocated_pages, | 499 int* allocated_pages, |
| 498 PagedSpace* owner) { | 500 PagedSpace* owner) { |
| 499 if (requested_pages <= 0) return Page::FromAddress(NULL); | 501 if (requested_pages <= 0) return Page::FromAddress(NULL); |
| 500 size_t chunk_size = requested_pages * Page::kPageSize; | 502 size_t chunk_size = requested_pages * Page::kPageSize; |
| 501 | 503 |
| 502 void* chunk = AllocateRawMemory(chunk_size, &chunk_size, owner->executable()); | 504 void* chunk = AllocateRawMemory(chunk_size, &chunk_size, owner->executable()); |
| 503 if (chunk == NULL) return Page::FromAddress(NULL); | 505 if (chunk == NULL) return Page::FromAddress(NULL); |
| 504 LOG(isolate_, NewEvent("PagedChunk", chunk, chunk_size)); | 506 LOG(isolate_, NewEvent("PagedChunk", chunk, chunk_size)); |
| 505 | 507 |
| 508 size_t guardsize = 0; | |
| 509 if (owner->executable() == EXECUTABLE) { | |
| 510 guardsize = Page::kPageSize; | |
| 511 OS::Guard(chunk, guardsize); | |
| 512 chunk_size -= guardsize; | |
| 513 chunk = static_cast<Address>(chunk) + guardsize; | |
| 514 } | |
| 515 | |
| 506 *allocated_pages = PagesInChunk(static_cast<Address>(chunk), chunk_size); | 516 *allocated_pages = PagesInChunk(static_cast<Address>(chunk), chunk_size); |
| 507 // We may 'lose' a page due to alignment. | 517 // We may 'lose' a page due to alignment. |
| 508 ASSERT(*allocated_pages >= kPagesPerChunk - 1); | 518 ASSERT(*allocated_pages >= kPagesPerChunk - 1); |
|
Mads Ager (chromium)
2011/07/19 09:11:14
Will this actually work? What if we lose a page du
Cris Neckar
2011/07/19 18:35:32
Done.
| |
| 509 if (*allocated_pages == 0) { | 519 if (*allocated_pages == 0) { |
| 510 FreeRawMemory(chunk, chunk_size, owner->executable()); | 520 FreeRawMemory(static_cast<Address>(chunk) - guardsize, |
| 521 chunk_size + guardsize, | |
| 522 owner->executable()); | |
| 511 LOG(isolate_, DeleteEvent("PagedChunk", chunk)); | 523 LOG(isolate_, DeleteEvent("PagedChunk", chunk)); |
| 512 return Page::FromAddress(NULL); | 524 return Page::FromAddress(NULL); |
| 513 } | 525 } |
| 514 | 526 |
| 515 int chunk_id = Pop(); | 527 int chunk_id = Pop(); |
| 516 chunks_[chunk_id].init(static_cast<Address>(chunk), chunk_size, owner); | 528 chunks_[chunk_id].init(static_cast<Address>(chunk), chunk_size, owner); |
| 517 | 529 |
| 518 ObjectSpace space = static_cast<ObjectSpace>(1 << owner->identity()); | 530 ObjectSpace space = static_cast<ObjectSpace>(1 << owner->identity()); |
| 519 PerformAllocationCallback(space, kAllocationActionAllocate, chunk_size); | 531 PerformAllocationCallback(space, kAllocationActionAllocate, chunk_size); |
| 520 Page* new_pages = InitializePagesInChunk(chunk_id, *allocated_pages, owner); | 532 Page* new_pages = InitializePagesInChunk(chunk_id, *allocated_pages, owner); |
| (...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 674 if (InInitialChunk(c.address())) { | 686 if (InInitialChunk(c.address())) { |
| 675 // TODO(1240712): VirtualMemory::Uncommit has a return value which | 687 // TODO(1240712): VirtualMemory::Uncommit has a return value which |
| 676 // is ignored here. | 688 // is ignored here. |
| 677 initial_chunk_->Uncommit(c.address(), c.size()); | 689 initial_chunk_->Uncommit(c.address(), c.size()); |
| 678 Counters* counters = isolate_->counters(); | 690 Counters* counters = isolate_->counters(); |
| 679 counters->memory_allocated()->Decrement(static_cast<int>(c.size())); | 691 counters->memory_allocated()->Decrement(static_cast<int>(c.size())); |
| 680 } else { | 692 } else { |
| 681 LOG(isolate_, DeleteEvent("PagedChunk", c.address())); | 693 LOG(isolate_, DeleteEvent("PagedChunk", c.address())); |
| 682 ObjectSpace space = static_cast<ObjectSpace>(1 << c.owner_identity()); | 694 ObjectSpace space = static_cast<ObjectSpace>(1 << c.owner_identity()); |
| 683 size_t size = c.size(); | 695 size_t size = c.size(); |
| 684 FreeRawMemory(c.address(), size, c.executable()); | 696 size_t guardsize = (c.executable() == EXECUTABLE) ? Page::kPageSize : 0; |
| 697 FreeRawMemory(c.address() - guardsize, size + guardsize, c.executable()); | |
| 685 PerformAllocationCallback(space, kAllocationActionFree, size); | 698 PerformAllocationCallback(space, kAllocationActionFree, size); |
| 686 } | 699 } |
| 687 c.init(NULL, 0, NULL); | 700 c.init(NULL, 0, NULL); |
| 688 Push(chunk_id); | 701 Push(chunk_id); |
| 689 } | 702 } |
| 690 | 703 |
| 691 | 704 |
| 692 Page* MemoryAllocator::FindFirstPageInSameChunk(Page* p) { | 705 Page* MemoryAllocator::FindFirstPageInSameChunk(Page* p) { |
| 693 int chunk_id = GetChunkId(p); | 706 int chunk_id = GetChunkId(p); |
| 694 ASSERT(IsValidChunk(chunk_id)); | 707 ASSERT(IsValidChunk(chunk_id)); |
| (...skipping 1970 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2665 } | 2678 } |
| 2666 | 2679 |
| 2667 | 2680 |
| 2668 // ----------------------------------------------------------------------------- | 2681 // ----------------------------------------------------------------------------- |
| 2669 // LargeObjectChunk | 2682 // LargeObjectChunk |
| 2670 | 2683 |
| 2671 LargeObjectChunk* LargeObjectChunk::New(int size_in_bytes, | 2684 LargeObjectChunk* LargeObjectChunk::New(int size_in_bytes, |
| 2672 Executability executable) { | 2685 Executability executable) { |
| 2673 size_t requested = ChunkSizeFor(size_in_bytes); | 2686 size_t requested = ChunkSizeFor(size_in_bytes); |
| 2674 size_t size; | 2687 size_t size; |
| 2688 size_t guardsize = (executable == EXECUTABLE) ? Page::kPageSize : 0; | |
| 2675 Isolate* isolate = Isolate::Current(); | 2689 Isolate* isolate = Isolate::Current(); |
| 2676 void* mem = isolate->memory_allocator()->AllocateRawMemory( | 2690 void* mem = isolate->memory_allocator()->AllocateRawMemory( |
| 2677 requested, &size, executable); | 2691 requested + guardsize, &size, executable); |
| 2678 if (mem == NULL) return NULL; | 2692 if (mem == NULL) return NULL; |
| 2679 | 2693 |
| 2680 // The start of the chunk may be overlayed with a page so we have to | 2694 // The start of the chunk may be overlayed with a page so we have to |
| 2681 // make sure that the page flags fit in the size field. | 2695 // make sure that the page flags fit in the size field. |
| 2682 ASSERT((size & Page::kPageFlagMask) == 0); | 2696 ASSERT((size & Page::kPageFlagMask) == 0); |
| 2683 | 2697 |
| 2684 LOG(isolate, NewEvent("LargeObjectChunk", mem, size)); | 2698 LOG(isolate, NewEvent("LargeObjectChunk", mem, size)); |
| 2685 if (size < requested) { | 2699 if (size < requested + guardsize) { |
| 2686 isolate->memory_allocator()->FreeRawMemory( | 2700 isolate->memory_allocator()->FreeRawMemory( |
| 2687 mem, size, executable); | 2701 static_cast<Address>(mem) - guardsize, size + guardsize, executable); |
|
Mads Ager (chromium)
2011/07/19 09:11:14
This looks wrong. You should use mem and size dire
Cris Neckar
2011/07/19 18:35:32
Yep I am dumb. :)
| |
| 2688 LOG(isolate, DeleteEvent("LargeObjectChunk", mem)); | 2702 LOG(isolate, DeleteEvent("LargeObjectChunk", mem)); |
| 2689 return NULL; | 2703 return NULL; |
| 2690 } | 2704 } |
| 2691 | 2705 |
| 2706 if (guardsize != 0) { | |
| 2707 OS::Guard(mem, guardsize); | |
| 2708 size -= guardsize; | |
| 2709 mem = static_cast<Address>(mem) + guardsize; | |
| 2710 } | |
| 2711 | |
| 2692 ObjectSpace space = (executable == EXECUTABLE) | 2712 ObjectSpace space = (executable == EXECUTABLE) |
| 2693 ? kObjectSpaceCodeSpace | 2713 ? kObjectSpaceCodeSpace |
| 2694 : kObjectSpaceLoSpace; | 2714 : kObjectSpaceLoSpace; |
| 2695 isolate->memory_allocator()->PerformAllocationCallback( | 2715 isolate->memory_allocator()->PerformAllocationCallback( |
| 2696 space, kAllocationActionAllocate, size); | 2716 space, kAllocationActionAllocate, size); |
| 2697 | 2717 |
| 2698 LargeObjectChunk* chunk = reinterpret_cast<LargeObjectChunk*>(mem); | 2718 LargeObjectChunk* chunk = reinterpret_cast<LargeObjectChunk*>(mem); |
| 2699 chunk->size_ = size; | 2719 chunk->size_ = size; |
| 2700 Page* page = Page::FromAddress(RoundUp(chunk->address(), Page::kPageSize)); | 2720 Page* page = Page::FromAddress(RoundUp(chunk->address(), Page::kPageSize)); |
| 2701 page->heap_ = isolate->heap(); | 2721 page->heap_ = isolate->heap(); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2735 while (first_chunk_ != NULL) { | 2755 while (first_chunk_ != NULL) { |
| 2736 LargeObjectChunk* chunk = first_chunk_; | 2756 LargeObjectChunk* chunk = first_chunk_; |
| 2737 first_chunk_ = first_chunk_->next(); | 2757 first_chunk_ = first_chunk_->next(); |
| 2738 LOG(heap()->isolate(), DeleteEvent("LargeObjectChunk", chunk->address())); | 2758 LOG(heap()->isolate(), DeleteEvent("LargeObjectChunk", chunk->address())); |
| 2739 Page* page = Page::FromAddress(RoundUp(chunk->address(), Page::kPageSize)); | 2759 Page* page = Page::FromAddress(RoundUp(chunk->address(), Page::kPageSize)); |
| 2740 Executability executable = | 2760 Executability executable = |
| 2741 page->IsPageExecutable() ? EXECUTABLE : NOT_EXECUTABLE; | 2761 page->IsPageExecutable() ? EXECUTABLE : NOT_EXECUTABLE; |
| 2742 ObjectSpace space = kObjectSpaceLoSpace; | 2762 ObjectSpace space = kObjectSpaceLoSpace; |
| 2743 if (executable == EXECUTABLE) space = kObjectSpaceCodeSpace; | 2763 if (executable == EXECUTABLE) space = kObjectSpaceCodeSpace; |
| 2744 size_t size = chunk->size(); | 2764 size_t size = chunk->size(); |
| 2745 heap()->isolate()->memory_allocator()->FreeRawMemory(chunk->address(), | 2765 size_t guardsize = (executable == EXECUTABLE) ? Page::kPageSize : 0; |
| 2746 size, | 2766 heap()->isolate()->memory_allocator()->FreeRawMemory( |
| 2747 executable); | 2767 chunk->address() - guardsize, |
| 2768 size + guardsize, | |
| 2769 executable); | |
| 2748 heap()->isolate()->memory_allocator()->PerformAllocationCallback( | 2770 heap()->isolate()->memory_allocator()->PerformAllocationCallback( |
| 2749 space, kAllocationActionFree, size); | 2771 space, kAllocationActionFree, size); |
| 2750 } | 2772 } |
| 2751 | 2773 |
| 2752 size_ = 0; | 2774 size_ = 0; |
| 2753 page_count_ = 0; | 2775 page_count_ = 0; |
| 2754 objects_size_ = 0; | 2776 objects_size_ = 0; |
| 2755 } | 2777 } |
| 2756 | 2778 |
| 2757 | 2779 |
| (...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2934 | 2956 |
| 2935 // Free the chunk. | 2957 // Free the chunk. |
| 2936 heap()->mark_compact_collector()->ReportDeleteIfNeeded( | 2958 heap()->mark_compact_collector()->ReportDeleteIfNeeded( |
| 2937 object, heap()->isolate()); | 2959 object, heap()->isolate()); |
| 2938 LiveObjectList::ProcessNonLive(object); | 2960 LiveObjectList::ProcessNonLive(object); |
| 2939 | 2961 |
| 2940 size_ -= static_cast<int>(chunk_size); | 2962 size_ -= static_cast<int>(chunk_size); |
| 2941 objects_size_ -= object->Size(); | 2963 objects_size_ -= object->Size(); |
| 2942 page_count_--; | 2964 page_count_--; |
| 2943 ObjectSpace space = kObjectSpaceLoSpace; | 2965 ObjectSpace space = kObjectSpaceLoSpace; |
| 2944 if (executable == EXECUTABLE) space = kObjectSpaceCodeSpace; | 2966 size_t guardsize = 0; |
| 2945 heap()->isolate()->memory_allocator()->FreeRawMemory(chunk_address, | 2967 if (executable == EXECUTABLE) { |
| 2946 chunk_size, | 2968 space = kObjectSpaceCodeSpace; |
| 2947 executable); | 2969 guardsize = Page::kPageSize; |
| 2970 } | |
| 2971 heap()->isolate()->memory_allocator()->FreeRawMemory( | |
| 2972 chunk_address - guardsize, | |
| 2973 chunk_size + guardsize, | |
| 2974 executable); | |
| 2948 heap()->isolate()->memory_allocator()->PerformAllocationCallback( | 2975 heap()->isolate()->memory_allocator()->PerformAllocationCallback( |
| 2949 space, kAllocationActionFree, size_); | 2976 space, kAllocationActionFree, size_); |
| 2950 LOG(heap()->isolate(), DeleteEvent("LargeObjectChunk", chunk_address)); | 2977 LOG(heap()->isolate(), DeleteEvent("LargeObjectChunk", chunk_address)); |
| 2951 } | 2978 } |
| 2952 } | 2979 } |
| 2953 } | 2980 } |
| 2954 | 2981 |
| 2955 | 2982 |
| 2956 bool LargeObjectSpace::Contains(HeapObject* object) { | 2983 bool LargeObjectSpace::Contains(HeapObject* object) { |
| 2957 Address address = object->address(); | 2984 Address address = object->address(); |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3057 for (HeapObject* obj = obj_it.next(); obj != NULL; obj = obj_it.next()) { | 3084 for (HeapObject* obj = obj_it.next(); obj != NULL; obj = obj_it.next()) { |
| 3058 if (obj->IsCode()) { | 3085 if (obj->IsCode()) { |
| 3059 Code* code = Code::cast(obj); | 3086 Code* code = Code::cast(obj); |
| 3060 isolate->code_kind_statistics()[code->kind()] += code->Size(); | 3087 isolate->code_kind_statistics()[code->kind()] += code->Size(); |
| 3061 } | 3088 } |
| 3062 } | 3089 } |
| 3063 } | 3090 } |
| 3064 #endif // DEBUG | 3091 #endif // DEBUG |
| 3065 | 3092 |
| 3066 } } // namespace v8::internal | 3093 } } // namespace v8::internal |
| OLD | NEW |