| Index: src/spaces.h | 
| =================================================================== | 
| --- src/spaces.h	(revision 10568) | 
| +++ src/spaces.h	(working copy) | 
| @@ -505,9 +505,11 @@ | 
| static const int kObjectStartOffset = kBodyOffset - 1 + | 
| (kObjectStartAlignment - (kBodyOffset - 1) % kObjectStartAlignment); | 
|  | 
| -  intptr_t size() const { return size_; } | 
| +  size_t size() const { return size_; } | 
|  | 
| -  void set_size(size_t size) { size_ = size; } | 
| +  void set_size(size_t size) { | 
| +    size_ = size; | 
| +  } | 
|  | 
| Executability executable() { | 
| return IsFlagSet(IS_EXECUTABLE) ? EXECUTABLE : NOT_EXECUTABLE; | 
| @@ -659,7 +661,7 @@ | 
| Address ObjectAreaStart() { return address() + kObjectStartOffset; } | 
|  | 
| // Returns the end address (exclusive) of the object area in this page. | 
| -  Address ObjectAreaEnd() { return address() + size(); } | 
| +  Address ObjectAreaEnd() { return address() + Page::kPageSize; } | 
|  | 
| // Checks whether an address is page aligned. | 
| static bool IsAlignedToPageSize(Address a) { | 
| @@ -678,17 +680,11 @@ | 
| return address() + offset; | 
| } | 
|  | 
| -  // Expand the committed area for pages that are small. | 
| -  void CommitMore(intptr_t space_needed); | 
| - | 
| // --------------------------------------------------------------------- | 
|  | 
| // Page size in bytes.  This must be a multiple of the OS page size. | 
| static const int kPageSize = 1 << kPageSizeBits; | 
|  | 
| -  // For a 1Mbyte page grow 64k at a time. | 
| -  static const int kGrowthUnit = 1 << (kPageSizeBits - 4); | 
| - | 
| // Page size mask. | 
| static const intptr_t kPageAlignmentMask = (1 << kPageSizeBits) - 1; | 
|  | 
| @@ -724,8 +720,6 @@ | 
| void ClearSweptPrecisely() { ClearFlag(WAS_SWEPT_PRECISELY); } | 
| void ClearSweptConservatively() { ClearFlag(WAS_SWEPT_CONSERVATIVELY); } | 
|  | 
| -  Address RoundUpToObjectAlignment(Address a); | 
| - | 
| #ifdef DEBUG | 
| void Print(); | 
| #endif  // DEBUG | 
| @@ -855,10 +849,12 @@ | 
| FreeBlock(Address start_arg, size_t size_arg) | 
| : start(start_arg), size(size_arg) { | 
| ASSERT(IsAddressAligned(start, MemoryChunk::kAlignment)); | 
| +      ASSERT(size >= static_cast<size_t>(Page::kPageSize)); | 
| } | 
| FreeBlock(void* start_arg, size_t size_arg) | 
| : start(static_cast<Address>(start_arg)), size(size_arg) { | 
| ASSERT(IsAddressAligned(start, MemoryChunk::kAlignment)); | 
| +      ASSERT(size >= static_cast<size_t>(Page::kPageSize)); | 
| } | 
|  | 
| Address start; | 
| @@ -954,9 +950,7 @@ | 
|  | 
| void TearDown(); | 
|  | 
| -  Page* AllocatePage(intptr_t object_area_size, | 
| -                     PagedSpace* owner, | 
| -                     Executability executable); | 
| +  Page* AllocatePage(PagedSpace* owner, Executability executable); | 
|  | 
| LargePage* AllocateLargePage(intptr_t object_size, | 
| Executability executable, | 
| @@ -965,14 +959,10 @@ | 
| void Free(MemoryChunk* chunk); | 
|  | 
| // Returns the maximum available bytes of heaps. | 
| -  intptr_t Available() { | 
| -    return capacity_ < memory_allocator_reserved_ ? | 
| -           0 : | 
| -           capacity_ - memory_allocator_reserved_; | 
| -  } | 
| +  intptr_t Available() { return capacity_ < size_ ? 0 : capacity_ - size_; } | 
|  | 
| // Returns allocated spaces in bytes. | 
| -  intptr_t Size() { return memory_allocator_reserved_; } | 
| +  intptr_t Size() { return size_; } | 
|  | 
| // Returns the maximum available executable bytes of heaps. | 
| intptr_t AvailableExecutable() { | 
| @@ -994,7 +984,6 @@ | 
| #endif | 
|  | 
| MemoryChunk* AllocateChunk(intptr_t body_size, | 
| -                             intptr_t committed_body_size, | 
| Executability executable, | 
| Space* space); | 
|  | 
| @@ -1002,7 +991,6 @@ | 
| size_t alignment, | 
| VirtualMemory* controller); | 
| Address AllocateAlignedMemory(size_t requested, | 
| -                                size_t committed, | 
| size_t alignment, | 
| Executability executable, | 
| VirtualMemory* controller); | 
| @@ -1022,12 +1010,6 @@ | 
| // and false otherwise. | 
| bool UncommitBlock(Address start, size_t size); | 
|  | 
| -  void AllocationBookkeeping(Space* owner, | 
| -                             Address base, | 
| -                             intptr_t reserved_size, | 
| -                             intptr_t committed_size, | 
| -                             Executability executable); | 
| - | 
| // Zaps a contiguous block of memory [start..(start+size)[ thus | 
| // filling it up with a recognizable non-NULL bit pattern. | 
| void ZapBlock(Address start, size_t size); | 
| @@ -1055,7 +1037,7 @@ | 
| size_t capacity_executable_; | 
|  | 
| // Allocated space size in bytes. | 
| -  size_t memory_allocator_reserved_; | 
| +  size_t size_; | 
| // Allocated executable space size in bytes. | 
| size_t size_executable_; | 
|  | 
| @@ -1400,15 +1382,9 @@ | 
| static const int kMinBlockSize = 3 * kPointerSize; | 
| static const int kMaxBlockSize = Page::kMaxHeapObjectSize; | 
|  | 
| -  FreeListNode* PickNodeFromList(FreeListNode** list, | 
| -                                 int* node_size, | 
| -                                 int minimum_size); | 
| +  FreeListNode* PickNodeFromList(FreeListNode** list, int* node_size); | 
|  | 
| -  FreeListNode* FindNodeFor(int size_in_bytes, int* node_size, Address limit); | 
| -  FreeListNode* FindAbuttingNode(int size_in_bytes, | 
| -                                 int* node_size, | 
| -                                 Address limit, | 
| -                                 FreeListNode** list_head); | 
| +  FreeListNode* FindNodeFor(int size_in_bytes, int* node_size); | 
|  | 
| PagedSpace* owner_; | 
| Heap* heap_; | 
| @@ -1508,8 +1484,6 @@ | 
| // free bytes that were not found at all due to lazy sweeping. | 
| virtual intptr_t Waste() { return accounting_stats_.Waste(); } | 
|  | 
| -  virtual int ObjectAlignment() { return kObjectAlignment; } | 
| - | 
| // Returns the allocation pointer in this space. | 
| Address top() { return allocation_info_.top; } | 
| Address limit() { return allocation_info_.limit; } | 
| @@ -1524,7 +1498,7 @@ | 
| // the free list or accounted as waste. | 
| // If add_to_freelist is false then just accounting stats are updated and | 
| // no attempt to add area to free list is made. | 
| -  int AddToFreeLists(Address start, int size_in_bytes) { | 
| +  int Free(Address start, int size_in_bytes) { | 
| int wasted = free_list_.Free(start, size_in_bytes); | 
| accounting_stats_.DeallocateBytes(size_in_bytes - wasted); | 
| return size_in_bytes - wasted; | 
| @@ -1532,7 +1506,6 @@ | 
|  | 
| // Set space allocation info. | 
| void SetTop(Address top, Address limit) { | 
| -    ASSERT(top == NULL || top >= Page::FromAddress(top - 1)->ObjectAreaStart()); | 
| ASSERT(top == limit || | 
| Page::FromAddress(top) == Page::FromAddress(limit - 1)); | 
| allocation_info_.top = top; | 
| @@ -1599,14 +1572,12 @@ | 
|  | 
| void IncreaseUnsweptFreeBytes(Page* p) { | 
| ASSERT(ShouldBeSweptLazily(p)); | 
| -    unswept_free_bytes_ += | 
| -        (p->ObjectAreaEnd() - p->ObjectAreaStart()) - p->LiveBytes(); | 
| +    unswept_free_bytes_ += (Page::kObjectAreaSize - p->LiveBytes()); | 
| } | 
|  | 
| void DecreaseUnsweptFreeBytes(Page* p) { | 
| ASSERT(ShouldBeSweptLazily(p)); | 
| -    unswept_free_bytes_ -= | 
| -        (p->ObjectAreaEnd() - p->ObjectAreaStart() - p->LiveBytes()); | 
| +    unswept_free_bytes_ -= (Page::kObjectAreaSize - p->LiveBytes()); | 
| } | 
|  | 
| bool AdvanceSweeper(intptr_t bytes_to_sweep); | 
| @@ -1615,7 +1586,6 @@ | 
| return !first_unswept_page_->is_valid(); | 
| } | 
|  | 
| -  inline bool HasAPage() { return anchor_.next_page() != &anchor_; } | 
| Page* FirstPage() { return anchor_.next_page(); } | 
| Page* LastPage() { return anchor_.prev_page(); } | 
|  | 
| @@ -1626,17 +1596,15 @@ | 
| FreeList::SizeStats sizes; | 
| free_list_.CountFreeListItems(p, &sizes); | 
|  | 
| -    intptr_t object_area_size = p->ObjectAreaEnd() - p->ObjectAreaStart(); | 
| - | 
| intptr_t ratio; | 
| intptr_t ratio_threshold; | 
| if (identity() == CODE_SPACE) { | 
| ratio = (sizes.medium_size_ * 10 + sizes.large_size_ * 2) * 100 / | 
| -          object_area_size; | 
| +          Page::kObjectAreaSize; | 
| ratio_threshold = 10; | 
| } else { | 
| ratio = (sizes.small_size_ * 5 + sizes.medium_size_) * 100 / | 
| -          object_area_size; | 
| +          Page::kObjectAreaSize; | 
| ratio_threshold = 15; | 
| } | 
|  | 
| @@ -1646,20 +1614,20 @@ | 
| identity(), | 
| static_cast<int>(sizes.small_size_), | 
| static_cast<double>(sizes.small_size_ * 100) / | 
| -                 object_area_size, | 
| +                 Page::kObjectAreaSize, | 
| static_cast<int>(sizes.medium_size_), | 
| static_cast<double>(sizes.medium_size_ * 100) / | 
| -                 object_area_size, | 
| +                 Page::kObjectAreaSize, | 
| static_cast<int>(sizes.large_size_), | 
| static_cast<double>(sizes.large_size_ * 100) / | 
| -                 object_area_size, | 
| +                 Page::kObjectAreaSize, | 
| static_cast<int>(sizes.huge_size_), | 
| static_cast<double>(sizes.huge_size_ * 100) / | 
| -                 object_area_size, | 
| +                 Page::kObjectAreaSize, | 
| (ratio > ratio_threshold) ? "[fragmented]" : ""); | 
| } | 
|  | 
| -    if (FLAG_always_compact && sizes.Total() != object_area_size) { | 
| +    if (FLAG_always_compact && sizes.Total() != Page::kObjectAreaSize) { | 
| return 1; | 
| } | 
| if (ratio <= ratio_threshold) return 0;  // Not fragmented. | 
| @@ -1690,6 +1658,12 @@ | 
| // Normal allocation information. | 
| AllocationInfo allocation_info_; | 
|  | 
| +  // Bytes of each page that cannot be allocated.  Possibly non-zero | 
| +  // for pages in spaces with only fixed-size objects.  Always zero | 
| +  // for pages in spaces with variable sized objects (those pages are | 
| +  // padded with free-list nodes). | 
| +  int page_extra_; | 
| + | 
| bool was_swept_conservatively_; | 
|  | 
| // The first page to be swept when the lazy sweeper advances. Is set | 
| @@ -1701,11 +1675,10 @@ | 
| // done conservatively. | 
| intptr_t unswept_free_bytes_; | 
|  | 
| -  // Expands the space by allocating a page. Returns false if it cannot | 
| -  // allocate a page from OS, or if the hard heap size limit has been hit.  The | 
| -  // new page will have at least enough committed space to satisfy the object | 
| -  // size indicated by the allocation_size argument; | 
| -  bool Expand(intptr_t allocation_size); | 
| +  // Expands the space by allocating a fixed number of pages. Returns false if | 
| +  // it cannot allocate requested number of pages from OS, or if the hard heap | 
| +  // size limit has been hit. | 
| +  bool Expand(); | 
|  | 
| // Generic fast case allocation function that tries linear allocation at the | 
| // address denoted by top in allocation_info_. | 
| @@ -1860,8 +1833,7 @@ | 
| anchor_(this), | 
| current_page_(NULL) { } | 
|  | 
| -  // Sets up the semispace using the given chunk.  After this, call Commit() | 
| -  // to make the semispace usable. | 
| +  // Sets up the semispace using the given chunk. | 
| void SetUp(Address start, int initial_capacity, int maximum_capacity); | 
|  | 
| // Tear down the space.  Heap memory was not allocated by the space, so it | 
| @@ -2366,8 +2338,15 @@ | 
| intptr_t max_capacity, | 
| AllocationSpace id, | 
| Executability executable) | 
| -      : PagedSpace(heap, max_capacity, id, executable) { } | 
| +      : PagedSpace(heap, max_capacity, id, executable) { | 
| +    page_extra_ = 0; | 
| +  } | 
|  | 
| +  // The limit of allocation for a page in this space. | 
| +  virtual Address PageAllocationLimit(Page* page) { | 
| +    return page->ObjectAreaEnd(); | 
| +  } | 
| + | 
| public: | 
| TRACK_MEMORY("OldSpace") | 
| }; | 
| @@ -2393,12 +2372,17 @@ | 
| const char* name) | 
| : PagedSpace(heap, max_capacity, id, NOT_EXECUTABLE), | 
| object_size_in_bytes_(object_size_in_bytes), | 
| -        name_(name) { } | 
| +        name_(name) { | 
| +    page_extra_ = Page::kObjectAreaSize % object_size_in_bytes; | 
| +  } | 
|  | 
| +  // The limit of allocation for a page in this space. | 
| +  virtual Address PageAllocationLimit(Page* page) { | 
| +    return page->ObjectAreaEnd() - page_extra_; | 
| +  } | 
| + | 
| int object_size_in_bytes() { return object_size_in_bytes_; } | 
|  | 
| -  virtual int ObjectAlignment() { return object_size_in_bytes_; } | 
| - | 
| // Prepares for a mark-compact GC. | 
| virtual void PrepareForMarkCompact(); | 
|  | 
|  |