1 // Copyright 2006-2010 the V8 project authors. All rights reserved. 2 // Redistribution and use in source and binary forms, with or without 3 // modification, are permitted provided that the following conditions are 4 // met: 5 // 6 // * Redistributions of source code must retain the above copyright 7 // notice, this list of conditions and the following disclaimer. 8 // * Redistributions in binary form must reproduce the above 9 // copyright notice, this list of conditions and the following 10 // disclaimer in the documentation and/or other materials provided 11 // with the distribution. 12 // * Neither the name of Google Inc. nor the names of its 13 // contributors may be used to endorse or promote products derived 14 // from this software without specific prior written permission. 15 // 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28 #ifndef V8_SPACES_H_ 29 #define V8_SPACES_H_ 30 31 #include "list-inl.h" 32 #include "log.h" 33 34 namespace v8 { 35 namespace internal { 36 37 class Isolate; 38 39 // ----------------------------------------------------------------------------- 40 // Heap structures: 41 // 42 // A JS heap consists of a young generation, an old generation, and a large 43 // object space. The young generation is divided into two semispaces. A 44 // scavenger implements Cheney's copying algorithm. The old generation is 45 // separated into a map space and an old object space. The map space contains 46 // all (and only) map objects, the rest of old objects go into the old space. 47 // The old generation is collected by a mark-sweep-compact collector. 48 // 49 // The semispaces of the young generation are contiguous. The old and map 50 // spaces consists of a list of pages. A page has a page header and an object 51 // area. A page size is deliberately chosen as 8K bytes. 52 // The first word of a page is an opaque page header that has the 53 // address of the next page and its ownership information. The second word may 54 // have the allocation top address of this page. Heap objects are aligned to the 55 // pointer size. 56 // 57 // There is a separate large object space for objects larger than 58 // Page::kMaxHeapObjectSize, so that they do not have to move during 59 // collection. The large object space is paged. Pages in large object space 60 // may be larger than 8K. 61 // 62 // A card marking write barrier is used to keep track of intergenerational 63 // references. Old space pages are divided into regions of Page::kRegionSize 64 // size. Each region has a corresponding dirty bit in the page header which is 65 // set if the region might contain pointers to new space. For details about 66 // dirty bits encoding see comments in the Page::GetRegionNumberForAddress() 67 // method body. 68 // 69 // During scavenges and mark-sweep collections we iterate intergenerational 70 // pointers without decoding heap object maps so if the page belongs to old 71 // pointer space or large object space it is essential to guarantee that 72 // the page does not contain any garbage pointers to new space: every pointer 73 // aligned word which satisfies the Heap::InNewSpace() predicate must be a 74 // pointer to a live heap object in new space. Thus objects in old pointer 75 // and large object spaces should have a special layout (e.g. no bare integer 76 // fields). This requirement does not apply to map space which is iterated in 77 // a special fashion. However we still require pointer fields of dead maps to 78 // be cleaned. 79 // 80 // To enable lazy cleaning of old space pages we use a notion of allocation 81 // watermark. Every pointer under watermark is considered to be well formed. 82 // Page allocation watermark is not necessarily equal to page allocation top but 83 // all alive objects on page should reside under allocation watermark. 84 // During scavenge allocation watermark might be bumped and invalid pointers 85 // might appear below it. To avoid following them we store a valid watermark 86 // into special field in the page header and set a page WATERMARK_INVALIDATED 87 // flag. For details see comments in the Page::SetAllocationWatermark() method 88 // body. 89 // 90 91 // Some assertion macros used in the debugging mode. 92 93 #define ASSERT_PAGE_ALIGNED(address) \ 94 ASSERT((OffsetFrom(address) & Page::kPageAlignmentMask) == 0) 95 96 #define ASSERT_OBJECT_ALIGNED(address) \ 97 ASSERT((OffsetFrom(address) & kObjectAlignmentMask) == 0) 98 99 #define ASSERT_MAP_ALIGNED(address) \ 100 ASSERT((OffsetFrom(address) & kMapAlignmentMask) == 0) 101 102 #define ASSERT_OBJECT_SIZE(size) \ 103 ASSERT((0 < size) && (size <= Page::kMaxHeapObjectSize)) 104 105 #define ASSERT_PAGE_OFFSET(offset) \ 106 ASSERT((Page::kObjectStartOffset <= offset) \ 107 && (offset <= Page::kPageSize)) 108 109 #define ASSERT_MAP_PAGE_INDEX(index) \ 110 ASSERT((0 <= index) && (index <= MapSpace::kMaxMapPageIndex)) 111 112 113 class PagedSpace; 114 class MemoryAllocator; 115 class AllocationInfo; 116 117 // ----------------------------------------------------------------------------- 118 // A page normally has 8K bytes. Large object pages may be larger. A page 119 // address is always aligned to the 8K page size. 120 // 121 // Each page starts with a header of Page::kPageHeaderSize size which contains 122 // bookkeeping data. 123 // 124 // The mark-compact collector transforms a map pointer into a page index and a 125 // page offset. The exact encoding is described in the comments for 126 // class MapWord in objects.h. 127 // 128 // The only way to get a page pointer is by calling factory methods: 129 // Page* p = Page::FromAddress(addr); or 130 // Page* p = Page::FromAllocationTop(top); 131 class Page { 132 public: 133 // Returns the page containing a given address. The address ranges 134 // from [page_addr .. page_addr + kPageSize[ 135 // 136 // Note that this function only works for addresses in normal paged 137 // spaces and addresses in the first 8K of large object pages (i.e., 138 // the start of large objects but not necessarily derived pointers 139 // within them). INLINE(static Page * FromAddress (Address a))140 INLINE(static Page* FromAddress(Address a)) { 141 return reinterpret_cast<Page*>(OffsetFrom(a) & ~kPageAlignmentMask); 142 } 143 144 // Returns the page containing an allocation top. Because an allocation 145 // top address can be the upper bound of the page, we need to subtract 146 // it with kPointerSize first. The address ranges from 147 // [page_addr + kObjectStartOffset .. page_addr + kPageSize]. INLINE(static Page * FromAllocationTop (Address top))148 INLINE(static Page* FromAllocationTop(Address top)) { 149 Page* p = FromAddress(top - kPointerSize); 150 ASSERT_PAGE_OFFSET(p->Offset(top)); 151 return p; 152 } 153 154 // Returns the start address of this page. address()155 Address address() { return reinterpret_cast<Address>(this); } 156 157 // Checks whether this is a valid page address. is_valid()158 bool is_valid() { return address() != NULL; } 159 160 // Returns the next page of this page. 161 inline Page* next_page(); 162 163 // Return the end of allocation in this page. Undefined for unused pages. 164 inline Address AllocationTop(); 165 166 // Return the allocation watermark for the page. 167 // For old space pages it is guaranteed that the area under the watermark 168 // does not contain any garbage pointers to new space. 169 inline Address AllocationWatermark(); 170 171 // Return the allocation watermark offset from the beginning of the page. 172 inline uint32_t AllocationWatermarkOffset(); 173 174 inline void SetAllocationWatermark(Address allocation_watermark); 175 176 inline void SetCachedAllocationWatermark(Address allocation_watermark); 177 inline Address CachedAllocationWatermark(); 178 179 // Returns the start address of the object area in this page. ObjectAreaStart()180 Address ObjectAreaStart() { return address() + kObjectStartOffset; } 181 182 // Returns the end address (exclusive) of the object area in this page. ObjectAreaEnd()183 Address ObjectAreaEnd() { return address() + Page::kPageSize; } 184 185 // Checks whether an address is page aligned. IsAlignedToPageSize(Address a)186 static bool IsAlignedToPageSize(Address a) { 187 return 0 == (OffsetFrom(a) & kPageAlignmentMask); 188 } 189 190 // True if this page was in use before current compaction started. 191 // Result is valid only for pages owned by paged spaces and 192 // only after PagedSpace::PrepareForMarkCompact was called. 193 inline bool WasInUseBeforeMC(); 194 195 inline void SetWasInUseBeforeMC(bool was_in_use); 196 197 // True if this page is a large object page. 198 inline bool IsLargeObjectPage(); 199 200 inline void SetIsLargeObjectPage(bool is_large_object_page); 201 202 inline bool IsPageExecutable(); 203 204 inline void SetIsPageExecutable(bool is_page_executable); 205 206 // Returns the offset of a given address to this page. INLINE(int Offset (Address a))207 INLINE(int Offset(Address a)) { 208 int offset = static_cast<int>(a - address()); 209 ASSERT_PAGE_OFFSET(offset); 210 return offset; 211 } 212 213 // Returns the address for a given offset to the this page. OffsetToAddress(int offset)214 Address OffsetToAddress(int offset) { 215 ASSERT_PAGE_OFFSET(offset); 216 return address() + offset; 217 } 218 219 // --------------------------------------------------------------------- 220 // Card marking support 221 222 static const uint32_t kAllRegionsCleanMarks = 0x0; 223 static const uint32_t kAllRegionsDirtyMarks = 0xFFFFFFFF; 224 225 inline uint32_t GetRegionMarks(); 226 inline void SetRegionMarks(uint32_t dirty); 227 228 inline uint32_t GetRegionMaskForAddress(Address addr); 229 inline uint32_t GetRegionMaskForSpan(Address start, int length_in_bytes); 230 inline int GetRegionNumberForAddress(Address addr); 231 232 inline void MarkRegionDirty(Address addr); 233 inline bool IsRegionDirty(Address addr); 234 235 inline void ClearRegionMarks(Address start, 236 Address end, 237 bool reaches_limit); 238 239 // Page size in bytes. This must be a multiple of the OS page size. 240 static const int kPageSize = 1 << kPageSizeBits; 241 242 // Page size mask. 243 static const intptr_t kPageAlignmentMask = (1 << kPageSizeBits) - 1; 244 245 static const int kPageHeaderSize = kPointerSize + kPointerSize + kIntSize + 246 kIntSize + kPointerSize + kPointerSize; 247 248 // The start offset of the object area in a page. Aligned to both maps and 249 // code alignment to be suitable for both. 250 static const int kObjectStartOffset = 251 CODE_POINTER_ALIGN(MAP_POINTER_ALIGN(kPageHeaderSize)); 252 253 // Object area size in bytes. 254 static const int kObjectAreaSize = kPageSize - kObjectStartOffset; 255 256 // Maximum object size that fits in a page. 257 static const int kMaxHeapObjectSize = kObjectAreaSize; 258 259 static const int kDirtyFlagOffset = 2 * kPointerSize; 260 static const int kRegionSizeLog2 = 8; 261 static const int kRegionSize = 1 << kRegionSizeLog2; 262 static const intptr_t kRegionAlignmentMask = (kRegionSize - 1); 263 264 STATIC_CHECK(kRegionSize == kPageSize / kBitsPerInt); 265 266 enum PageFlag { 267 IS_NORMAL_PAGE = 0, 268 WAS_IN_USE_BEFORE_MC, 269 270 // Page allocation watermark was bumped by preallocation during scavenge. 271 // Correct watermark can be retrieved by CachedAllocationWatermark() method 272 WATERMARK_INVALIDATED, 273 IS_EXECUTABLE, 274 NUM_PAGE_FLAGS // Must be last 275 }; 276 static const int kPageFlagMask = (1 << NUM_PAGE_FLAGS) - 1; 277 278 // To avoid an additional WATERMARK_INVALIDATED flag clearing pass during 279 // scavenge we just invalidate the watermark on each old space page after 280 // processing it. And then we flip the meaning of the WATERMARK_INVALIDATED 281 // flag at the beginning of the next scavenge and each page becomes marked as 282 // having a valid watermark. 283 // 284 // The following invariant must hold for pages in old pointer and map spaces: 285 // If page is in use then page is marked as having invalid watermark at 286 // the beginning and at the end of any GC. 287 // 288 // This invariant guarantees that after flipping flag meaning at the 289 // beginning of scavenge all pages in use will be marked as having valid 290 // watermark. 291 static inline void FlipMeaningOfInvalidatedWatermarkFlag(Heap* heap); 292 293 // Returns true if the page allocation watermark was not altered during 294 // scavenge. 295 inline bool IsWatermarkValid(); 296 297 inline void InvalidateWatermark(bool value); 298 299 inline bool GetPageFlag(PageFlag flag); 300 inline void SetPageFlag(PageFlag flag, bool value); 301 inline void ClearPageFlags(); 302 303 inline void ClearGCFields(); 304 305 static const int kAllocationWatermarkOffsetShift = WATERMARK_INVALIDATED + 1; 306 static const int kAllocationWatermarkOffsetBits = kPageSizeBits + 1; 307 static const uint32_t kAllocationWatermarkOffsetMask = 308 ((1 << kAllocationWatermarkOffsetBits) - 1) << 309 kAllocationWatermarkOffsetShift; 310 311 static const uint32_t kFlagsMask = 312 ((1 << kAllocationWatermarkOffsetShift) - 1); 313 314 STATIC_CHECK(kBitsPerInt - kAllocationWatermarkOffsetShift >= 315 kAllocationWatermarkOffsetBits); 316 317 //--------------------------------------------------------------------------- 318 // Page header description. 319 // 320 // If a page is not in the large object space, the first word, 321 // opaque_header, encodes the next page address (aligned to kPageSize 8K) 322 // and the chunk number (0 ~ 8K-1). Only MemoryAllocator should use 323 // opaque_header. The value range of the opaque_header is [0..kPageSize[, 324 // or [next_page_start, next_page_end[. It cannot point to a valid address 325 // in the current page. If a page is in the large object space, the first 326 // word *may* (if the page start and large object chunk start are the 327 // same) contain the address of the next large object chunk. 328 intptr_t opaque_header; 329 330 // If the page is not in the large object space, the low-order bit of the 331 // second word is set. If the page is in the large object space, the 332 // second word *may* (if the page start and large object chunk start are 333 // the same) contain the large object chunk size. In either case, the 334 // low-order bit for large object pages will be cleared. 335 // For normal pages this word is used to store page flags and 336 // offset of allocation top. 337 intptr_t flags_; 338 339 // This field contains dirty marks for regions covering the page. Only dirty 340 // regions might contain intergenerational references. 341 // Only 32 dirty marks are supported so for large object pages several regions 342 // might be mapped to a single dirty mark. 343 uint32_t dirty_regions_; 344 345 // The index of the page in its owner space. 346 int mc_page_index; 347 348 // During mark-compact collections this field contains the forwarding address 349 // of the first live object in this page. 350 // During scavenge collection this field is used to store allocation watermark 351 // if it is altered during scavenge. 352 Address mc_first_forwarded; 353 354 Heap* heap_; 355 }; 356 357 358 // ---------------------------------------------------------------------------- 359 // Space is the abstract superclass for all allocation spaces. 360 class Space : public Malloced { 361 public: Space(Heap * heap,AllocationSpace id,Executability executable)362 Space(Heap* heap, AllocationSpace id, Executability executable) 363 : heap_(heap), id_(id), executable_(executable) {} 364 ~Space()365 virtual ~Space() {} 366 heap()367 Heap* heap() const { return heap_; } 368 369 // Does the space need executable memory? executable()370 Executability executable() { return executable_; } 371 372 // Identity used in error reporting. identity()373 AllocationSpace identity() { return id_; } 374 375 // Returns allocated size. 376 virtual intptr_t Size() = 0; 377 378 // Returns size of objects. Can differ from the allocated size 379 // (e.g. see LargeObjectSpace). SizeOfObjects()380 virtual intptr_t SizeOfObjects() { return Size(); } 381 382 #ifdef ENABLE_HEAP_PROTECTION 383 // Protect/unprotect the space by marking it read-only/writable. 384 virtual void Protect() = 0; 385 virtual void Unprotect() = 0; 386 #endif 387 388 #ifdef DEBUG 389 virtual void Print() = 0; 390 #endif 391 392 // After calling this we can allocate a certain number of bytes using only 393 // linear allocation (with a LinearAllocationScope and an AlwaysAllocateScope) 394 // without using freelists or causing a GC. This is used by partial 395 // snapshots. It returns true of space was reserved or false if a GC is 396 // needed. For paged spaces the space requested must include the space wasted 397 // at the end of each when allocating linearly. 398 virtual bool ReserveSpace(int bytes) = 0; 399 400 private: 401 Heap* heap_; 402 AllocationSpace id_; 403 Executability executable_; 404 }; 405 406 407 // ---------------------------------------------------------------------------- 408 // All heap objects containing executable code (code objects) must be allocated 409 // from a 2 GB range of memory, so that they can call each other using 32-bit 410 // displacements. This happens automatically on 32-bit platforms, where 32-bit 411 // displacements cover the entire 4GB virtual address space. On 64-bit 412 // platforms, we support this using the CodeRange object, which reserves and 413 // manages a range of virtual memory. 414 class CodeRange { 415 public: 416 explicit CodeRange(Isolate* isolate); 417 418 // Reserves a range of virtual memory, but does not commit any of it. 419 // Can only be called once, at heap initialization time. 420 // Returns false on failure. 421 bool Setup(const size_t requested_size); 422 423 // Frees the range of virtual memory, and frees the data structures used to 424 // manage it. 425 void TearDown(); 426 exists()427 bool exists() { return this != NULL && code_range_ != NULL; } contains(Address address)428 bool contains(Address address) { 429 if (this == NULL || code_range_ == NULL) return false; 430 Address start = static_cast<Address>(code_range_->address()); 431 return start <= address && address < start + code_range_->size(); 432 } 433 434 // Allocates a chunk of memory from the large-object portion of 435 // the code range. On platforms with no separate code range, should 436 // not be called. 437 MUST_USE_RESULT void* AllocateRawMemory(const size_t requested, 438 size_t* allocated); 439 void FreeRawMemory(void* buf, size_t length); 440 441 private: 442 Isolate* isolate_; 443 444 // The reserved range of virtual memory that all code objects are put in. 445 VirtualMemory* code_range_; 446 // Plain old data class, just a struct plus a constructor. 447 class FreeBlock { 448 public: FreeBlock(Address start_arg,size_t size_arg)449 FreeBlock(Address start_arg, size_t size_arg) 450 : start(start_arg), size(size_arg) {} FreeBlock(void * start_arg,size_t size_arg)451 FreeBlock(void* start_arg, size_t size_arg) 452 : start(static_cast<Address>(start_arg)), size(size_arg) {} 453 454 Address start; 455 size_t size; 456 }; 457 458 // Freed blocks of memory are added to the free list. When the allocation 459 // list is exhausted, the free list is sorted and merged to make the new 460 // allocation list. 461 List<FreeBlock> free_list_; 462 // Memory is allocated from the free blocks on the allocation list. 463 // The block at current_allocation_block_index_ is the current block. 464 List<FreeBlock> allocation_list_; 465 int current_allocation_block_index_; 466 467 // Finds a block on the allocation list that contains at least the 468 // requested amount of memory. If none is found, sorts and merges 469 // the existing free memory blocks, and searches again. 470 // If none can be found, terminates V8 with FatalProcessOutOfMemory. 471 void GetNextAllocationBlock(size_t requested); 472 // Compares the start addresses of two free blocks. 473 static int CompareFreeBlockAddress(const FreeBlock* left, 474 const FreeBlock* right); 475 476 DISALLOW_COPY_AND_ASSIGN(CodeRange); 477 }; 478 479 480 // ---------------------------------------------------------------------------- 481 // A space acquires chunks of memory from the operating system. The memory 482 // allocator manages chunks for the paged heap spaces (old space and map 483 // space). A paged chunk consists of pages. Pages in a chunk have contiguous 484 // addresses and are linked as a list. 485 // 486 // The allocator keeps an initial chunk which is used for the new space. The 487 // leftover regions of the initial chunk are used for the initial chunks of 488 // old space and map space if they are big enough to hold at least one page. 489 // The allocator assumes that there is one old space and one map space, each 490 // expands the space by allocating kPagesPerChunk pages except the last 491 // expansion (before running out of space). The first chunk may contain fewer 492 // than kPagesPerChunk pages as well. 493 // 494 // The memory allocator also allocates chunks for the large object space, but 495 // they are managed by the space itself. The new space does not expand. 496 // 497 // The fact that pages for paged spaces are allocated and deallocated in chunks 498 // induces a constraint on the order of pages in a linked lists. We say that 499 // pages are linked in the chunk-order if and only if every two consecutive 500 // pages from the same chunk are consecutive in the linked list. 501 // 502 503 504 class MemoryAllocator { 505 public: 506 explicit MemoryAllocator(Isolate* isolate); 507 508 // Initializes its internal bookkeeping structures. 509 // Max capacity of the total space and executable memory limit. 510 bool Setup(intptr_t max_capacity, intptr_t capacity_executable); 511 512 // Deletes valid chunks. 513 void TearDown(); 514 515 // Reserves an initial address range of virtual memory to be split between 516 // the two new space semispaces, the old space, and the map space. The 517 // memory is not yet committed or assigned to spaces and split into pages. 518 // The initial chunk is unmapped when the memory allocator is torn down. 519 // This function should only be called when there is not already a reserved 520 // initial chunk (initial_chunk_ should be NULL). It returns the start 521 // address of the initial chunk if successful, with the side effect of 522 // setting the initial chunk, or else NULL if unsuccessful and leaves the 523 // initial chunk NULL. 524 void* ReserveInitialChunk(const size_t requested); 525 526 // Commits pages from an as-yet-unmanaged block of virtual memory into a 527 // paged space. The block should be part of the initial chunk reserved via 528 // a call to ReserveInitialChunk. The number of pages is always returned in 529 // the output parameter num_pages. This function assumes that the start 530 // address is non-null and that it is big enough to hold at least one 531 // page-aligned page. The call always succeeds, and num_pages is always 532 // greater than zero. 533 Page* CommitPages(Address start, size_t size, PagedSpace* owner, 534 int* num_pages); 535 536 // Commit a contiguous block of memory from the initial chunk. Assumes that 537 // the address is not NULL, the size is greater than zero, and that the 538 // block is contained in the initial chunk. Returns true if it succeeded 539 // and false otherwise. 540 bool CommitBlock(Address start, size_t size, Executability executable); 541 542 // Uncommit a contiguous block of memory [start..(start+size)[. 543 // start is not NULL, the size is greater than zero, and the 544 // block is contained in the initial chunk. Returns true if it succeeded 545 // and false otherwise. 546 bool UncommitBlock(Address start, size_t size); 547 548 // Zaps a contiguous block of memory [start..(start+size)[ thus 549 // filling it up with a recognizable non-NULL bit pattern. 550 void ZapBlock(Address start, size_t size); 551 552 // Attempts to allocate the requested (non-zero) number of pages from the 553 // OS. Fewer pages might be allocated than requested. If it fails to 554 // allocate memory for the OS or cannot allocate a single page, this 555 // function returns an invalid page pointer (NULL). The caller must check 556 // whether the returned page is valid (by calling Page::is_valid()). It is 557 // guaranteed that allocated pages have contiguous addresses. The actual 558 // number of allocated pages is returned in the output parameter 559 // allocated_pages. If the PagedSpace owner is executable and there is 560 // a code range, the pages are allocated from the code range. 561 Page* AllocatePages(int requested_pages, int* allocated_pages, 562 PagedSpace* owner); 563 564 // Frees pages from a given page and after. Requires pages to be 565 // linked in chunk-order (see comment for class). 566 // If 'p' is the first page of a chunk, pages from 'p' are freed 567 // and this function returns an invalid page pointer. 568 // Otherwise, the function searches a page after 'p' that is 569 // the first page of a chunk. Pages after the found page 570 // are freed and the function returns 'p'. 571 Page* FreePages(Page* p); 572 573 // Frees all pages owned by given space. 574 void FreeAllPages(PagedSpace* space); 575 576 // Allocates and frees raw memory of certain size. 577 // These are just thin wrappers around OS::Allocate and OS::Free, 578 // but keep track of allocated bytes as part of heap. 579 // If the flag is EXECUTABLE and a code range exists, the requested 580 // memory is allocated from the code range. If a code range exists 581 // and the freed memory is in it, the code range manages the freed memory. 582 MUST_USE_RESULT void* AllocateRawMemory(const size_t requested, 583 size_t* allocated, 584 Executability executable); 585 void FreeRawMemory(void* buf, 586 size_t length, 587 Executability executable); 588 void PerformAllocationCallback(ObjectSpace space, 589 AllocationAction action, 590 size_t size); 591 592 void AddMemoryAllocationCallback(MemoryAllocationCallback callback, 593 ObjectSpace space, 594 AllocationAction action); 595 void RemoveMemoryAllocationCallback(MemoryAllocationCallback callback); 596 bool MemoryAllocationCallbackRegistered(MemoryAllocationCallback callback); 597 598 // Returns the maximum available bytes of heaps. Available()599 intptr_t Available() { return capacity_ < size_ ? 0 : capacity_ - size_; } 600 601 // Returns allocated spaces in bytes. Size()602 intptr_t Size() { return size_; } 603 604 // Returns the maximum available executable bytes of heaps. AvailableExecutable()605 intptr_t AvailableExecutable() { 606 if (capacity_executable_ < size_executable_) return 0; 607 return capacity_executable_ - size_executable_; 608 } 609 610 // Returns allocated executable spaces in bytes. SizeExecutable()611 intptr_t SizeExecutable() { return size_executable_; } 612 613 // Returns maximum available bytes that the old space can have. MaxAvailable()614 intptr_t MaxAvailable() { 615 return (Available() / Page::kPageSize) * Page::kObjectAreaSize; 616 } 617 618 // Links two pages. 619 inline void SetNextPage(Page* prev, Page* next); 620 621 // Returns the next page of a given page. 622 inline Page* GetNextPage(Page* p); 623 624 // Checks whether a page belongs to a space. 625 inline bool IsPageInSpace(Page* p, PagedSpace* space); 626 627 // Returns the space that owns the given page. 628 inline PagedSpace* PageOwner(Page* page); 629 630 // Finds the first/last page in the same chunk as a given page. 631 Page* FindFirstPageInSameChunk(Page* p); 632 Page* FindLastPageInSameChunk(Page* p); 633 634 // Relinks list of pages owned by space to make it chunk-ordered. 635 // Returns new first and last pages of space. 636 // Also returns last page in relinked list which has WasInUsedBeforeMC 637 // flag set. 638 void RelinkPageListInChunkOrder(PagedSpace* space, 639 Page** first_page, 640 Page** last_page, 641 Page** last_page_in_use); 642 643 #ifdef ENABLE_HEAP_PROTECTION 644 // Protect/unprotect a block of memory by marking it read-only/writable. 645 inline void Protect(Address start, size_t size); 646 inline void Unprotect(Address start, size_t size, 647 Executability executable); 648 649 // Protect/unprotect a chunk given a page in the chunk. 650 inline void ProtectChunkFromPage(Page* page); 651 inline void UnprotectChunkFromPage(Page* page); 652 #endif 653 654 #ifdef DEBUG 655 // Reports statistic info of the space. 656 void ReportStatistics(); 657 #endif 658 659 // Due to encoding limitation, we can only have 8K chunks. 660 static const int kMaxNofChunks = 1 << kPageSizeBits; 661 // If a chunk has at least 16 pages, the maximum heap size is about 662 // 8K * 8K * 16 = 1G bytes. 663 #ifdef V8_TARGET_ARCH_X64 664 static const int kPagesPerChunk = 32; 665 // On 64 bit the chunk table consists of 4 levels of 4096-entry tables. 666 static const int kPagesPerChunkLog2 = 5; 667 static const int kChunkTableLevels = 4; 668 static const int kChunkTableBitsPerLevel = 12; 669 #else 670 static const int kPagesPerChunk = 16; 671 // On 32 bit the chunk table consists of 2 levels of 256-entry tables. 672 static const int kPagesPerChunkLog2 = 4; 673 static const int kChunkTableLevels = 2; 674 static const int kChunkTableBitsPerLevel = 8; 675 #endif 676 677 private: 678 static const int kChunkSize = kPagesPerChunk * Page::kPageSize; 679 static const int kChunkSizeLog2 = kPagesPerChunkLog2 + kPageSizeBits; 680 681 Isolate* isolate_; 682 683 // Maximum space size in bytes. 684 intptr_t capacity_; 685 // Maximum subset of capacity_ that can be executable 686 intptr_t capacity_executable_; 687 688 // Allocated space size in bytes. 689 intptr_t size_; 690 691 // Allocated executable space size in bytes. 692 intptr_t size_executable_; 693 694 struct MemoryAllocationCallbackRegistration { MemoryAllocationCallbackRegistrationMemoryAllocationCallbackRegistration695 MemoryAllocationCallbackRegistration(MemoryAllocationCallback callback, 696 ObjectSpace space, 697 AllocationAction action) 698 : callback(callback), space(space), action(action) { 699 } 700 MemoryAllocationCallback callback; 701 ObjectSpace space; 702 AllocationAction action; 703 }; 704 // A List of callback that are triggered when memory is allocated or free'd 705 List<MemoryAllocationCallbackRegistration> 706 memory_allocation_callbacks_; 707 708 // The initial chunk of virtual memory. 709 VirtualMemory* initial_chunk_; 710 711 // Allocated chunk info: chunk start address, chunk size, and owning space. 712 class ChunkInfo BASE_EMBEDDED { 713 public: ChunkInfo()714 ChunkInfo() : address_(NULL), 715 size_(0), 716 owner_(NULL), 717 executable_(NOT_EXECUTABLE), 718 owner_identity_(FIRST_SPACE) {} 719 inline void init(Address a, size_t s, PagedSpace* o); address()720 Address address() { return address_; } size()721 size_t size() { return size_; } owner()722 PagedSpace* owner() { return owner_; } 723 // We save executability of the owner to allow using it 724 // when collecting stats after the owner has been destroyed. executable()725 Executability executable() const { return executable_; } owner_identity()726 AllocationSpace owner_identity() const { return owner_identity_; } 727 728 private: 729 Address address_; 730 size_t size_; 731 PagedSpace* owner_; 732 Executability executable_; 733 AllocationSpace owner_identity_; 734 }; 735 736 // Chunks_, free_chunk_ids_ and top_ act as a stack of free chunk ids. 737 List<ChunkInfo> chunks_; 738 List<int> free_chunk_ids_; 739 int max_nof_chunks_; 740 int top_; 741 742 // Push/pop a free chunk id onto/from the stack. 743 void Push(int free_chunk_id); 744 int Pop(); OutOfChunkIds()745 bool OutOfChunkIds() { return top_ == 0; } 746 747 // Frees a chunk. 748 void DeleteChunk(int chunk_id); 749 750 // Basic check whether a chunk id is in the valid range. 751 inline bool IsValidChunkId(int chunk_id); 752 753 // Checks whether a chunk id identifies an allocated chunk. 754 inline bool IsValidChunk(int chunk_id); 755 756 // Returns the chunk id that a page belongs to. 757 inline int GetChunkId(Page* p); 758 759 // True if the address lies in the initial chunk. 760 inline bool InInitialChunk(Address address); 761 762 // Initializes pages in a chunk. Returns the first page address. 763 // This function and GetChunkId() are provided for the mark-compact 764 // collector to rebuild page headers in the from space, which is 765 // used as a marking stack and its page headers are destroyed. 766 Page* InitializePagesInChunk(int chunk_id, int pages_in_chunk, 767 PagedSpace* owner); 768 769 Page* RelinkPagesInChunk(int chunk_id, 770 Address chunk_start, 771 size_t chunk_size, 772 Page* prev, 773 Page** last_page_in_use); 774 775 DISALLOW_COPY_AND_ASSIGN(MemoryAllocator); 776 }; 777 778 779 // ----------------------------------------------------------------------------- 780 // Interface for heap object iterator to be implemented by all object space 781 // object iterators. 782 // 783 // NOTE: The space specific object iterators also implements the own next() 784 // method which is used to avoid using virtual functions 785 // iterating a specific space. 786 787 class ObjectIterator : public Malloced { 788 public: ~ObjectIterator()789 virtual ~ObjectIterator() { } 790 791 virtual HeapObject* next_object() = 0; 792 }; 793 794 795 // ----------------------------------------------------------------------------- 796 // Heap object iterator in new/old/map spaces. 797 // 798 // A HeapObjectIterator iterates objects from a given address to the 799 // top of a space. The given address must be below the current 800 // allocation pointer (space top). There are some caveats. 801 // 802 // (1) If the space top changes upward during iteration (because of 803 // allocating new objects), the iterator does not iterate objects 804 // above the original space top. The caller must create a new 805 // iterator starting from the old top in order to visit these new 806 // objects. 807 // 808 // (2) If new objects are allocated below the original allocation top 809 // (e.g., free-list allocation in paged spaces), the new objects 810 // may or may not be iterated depending on their position with 811 // respect to the current point of iteration. 812 // 813 // (3) The space top should not change downward during iteration, 814 // otherwise the iterator will return not-necessarily-valid 815 // objects. 816 817 class HeapObjectIterator: public ObjectIterator { 818 public: 819 // Creates a new object iterator in a given space. If a start 820 // address is not given, the iterator starts from the space bottom. 821 // If the size function is not given, the iterator calls the default 822 // Object::Size(). 823 explicit HeapObjectIterator(PagedSpace* space); 824 HeapObjectIterator(PagedSpace* space, HeapObjectCallback size_func); 825 HeapObjectIterator(PagedSpace* space, Address start); 826 HeapObjectIterator(PagedSpace* space, 827 Address start, 828 HeapObjectCallback size_func); 829 HeapObjectIterator(Page* page, HeapObjectCallback size_func); 830 next()831 inline HeapObject* next() { 832 return (cur_addr_ < cur_limit_) ? FromCurrentPage() : FromNextPage(); 833 } 834 835 // implementation of ObjectIterator. next_object()836 virtual HeapObject* next_object() { return next(); } 837 838 private: 839 Address cur_addr_; // current iteration point 840 Address end_addr_; // end iteration point 841 Address cur_limit_; // current page limit 842 HeapObjectCallback size_func_; // size function 843 Page* end_page_; // caches the page of the end address 844 FromCurrentPage()845 HeapObject* FromCurrentPage() { 846 ASSERT(cur_addr_ < cur_limit_); 847 848 HeapObject* obj = HeapObject::FromAddress(cur_addr_); 849 int obj_size = (size_func_ == NULL) ? obj->Size() : size_func_(obj); 850 ASSERT_OBJECT_SIZE(obj_size); 851 852 cur_addr_ += obj_size; 853 ASSERT(cur_addr_ <= cur_limit_); 854 855 return obj; 856 } 857 858 // Slow path of next, goes into the next page. 859 HeapObject* FromNextPage(); 860 861 // Initializes fields. 862 void Initialize(Address start, Address end, HeapObjectCallback size_func); 863 864 #ifdef DEBUG 865 // Verifies whether fields have valid values. 866 void Verify(); 867 #endif 868 }; 869 870 871 // ----------------------------------------------------------------------------- 872 // A PageIterator iterates the pages in a paged space. 873 // 874 // The PageIterator class provides three modes for iterating pages in a space: 875 // PAGES_IN_USE iterates pages containing allocated objects. 876 // PAGES_USED_BY_MC iterates pages that hold relocated objects during a 877 // mark-compact collection. 878 // ALL_PAGES iterates all pages in the space. 879 // 880 // There are some caveats. 881 // 882 // (1) If the space expands during iteration, new pages will not be 883 // returned by the iterator in any mode. 884 // 885 // (2) If new objects are allocated during iteration, they will appear 886 // in pages returned by the iterator. Allocation may cause the 887 // allocation pointer or MC allocation pointer in the last page to 888 // change between constructing the iterator and iterating the last 889 // page. 890 // 891 // (3) The space should not shrink during iteration, otherwise the 892 // iterator will return deallocated pages. 893 894 class PageIterator BASE_EMBEDDED { 895 public: 896 enum Mode { 897 PAGES_IN_USE, 898 PAGES_USED_BY_MC, 899 ALL_PAGES 900 }; 901 902 PageIterator(PagedSpace* space, Mode mode); 903 904 inline bool has_next(); 905 inline Page* next(); 906 907 private: 908 PagedSpace* space_; 909 Page* prev_page_; // Previous page returned. 910 Page* stop_page_; // Page to stop at (last page returned by the iterator). 911 }; 912 913 914 // ----------------------------------------------------------------------------- 915 // A space has a list of pages. The next page can be accessed via 916 // Page::next_page() call. The next page of the last page is an 917 // invalid page pointer. A space can expand and shrink dynamically. 918 919 // An abstraction of allocation and relocation pointers in a page-structured 920 // space. 921 class AllocationInfo { 922 public: 923 Address top; // current allocation top 924 Address limit; // current allocation limit 925 926 #ifdef DEBUG VerifyPagedAllocation()927 bool VerifyPagedAllocation() { 928 return (Page::FromAllocationTop(top) == Page::FromAllocationTop(limit)) 929 && (top <= limit); 930 } 931 #endif 932 }; 933 934 935 // An abstraction of the accounting statistics of a page-structured space. 936 // The 'capacity' of a space is the number of object-area bytes (ie, not 937 // including page bookkeeping structures) currently in the space. The 'size' 938 // of a space is the number of allocated bytes, the 'waste' in the space is 939 // the number of bytes that are not allocated and not available to 940 // allocation without reorganizing the space via a GC (eg, small blocks due 941 // to internal fragmentation, top of page areas in map space), and the bytes 942 // 'available' is the number of unallocated bytes that are not waste. The 943 // capacity is the sum of size, waste, and available. 944 // 945 // The stats are only set by functions that ensure they stay balanced. These 946 // functions increase or decrease one of the non-capacity stats in 947 // conjunction with capacity, or else they always balance increases and 948 // decreases to the non-capacity stats. 949 class AllocationStats BASE_EMBEDDED { 950 public: AllocationStats()951 AllocationStats() { Clear(); } 952 953 // Zero out all the allocation statistics (ie, no capacity). Clear()954 void Clear() { 955 capacity_ = 0; 956 available_ = 0; 957 size_ = 0; 958 waste_ = 0; 959 } 960 961 // Reset the allocation statistics (ie, available = capacity with no 962 // wasted or allocated bytes). Reset()963 void Reset() { 964 available_ = capacity_; 965 size_ = 0; 966 waste_ = 0; 967 } 968 969 // Accessors for the allocation statistics. Capacity()970 intptr_t Capacity() { return capacity_; } Available()971 intptr_t Available() { return available_; } Size()972 intptr_t Size() { return size_; } Waste()973 intptr_t Waste() { return waste_; } 974 975 // Grow the space by adding available bytes. ExpandSpace(int size_in_bytes)976 void ExpandSpace(int size_in_bytes) { 977 capacity_ += size_in_bytes; 978 available_ += size_in_bytes; 979 } 980 981 // Shrink the space by removing available bytes. ShrinkSpace(int size_in_bytes)982 void ShrinkSpace(int size_in_bytes) { 983 capacity_ -= size_in_bytes; 984 available_ -= size_in_bytes; 985 } 986 987 // Allocate from available bytes (available -> size). AllocateBytes(intptr_t size_in_bytes)988 void AllocateBytes(intptr_t size_in_bytes) { 989 available_ -= size_in_bytes; 990 size_ += size_in_bytes; 991 } 992 993 // Free allocated bytes, making them available (size -> available). DeallocateBytes(intptr_t size_in_bytes)994 void DeallocateBytes(intptr_t size_in_bytes) { 995 size_ -= size_in_bytes; 996 available_ += size_in_bytes; 997 } 998 999 // Waste free bytes (available -> waste). WasteBytes(int size_in_bytes)1000 void WasteBytes(int size_in_bytes) { 1001 available_ -= size_in_bytes; 1002 waste_ += size_in_bytes; 1003 } 1004 1005 // Consider the wasted bytes to be allocated, as they contain filler 1006 // objects (waste -> size). FillWastedBytes(intptr_t size_in_bytes)1007 void FillWastedBytes(intptr_t size_in_bytes) { 1008 waste_ -= size_in_bytes; 1009 size_ += size_in_bytes; 1010 } 1011 1012 private: 1013 intptr_t capacity_; 1014 intptr_t available_; 1015 intptr_t size_; 1016 intptr_t waste_; 1017 }; 1018 1019 1020 class PagedSpace : public Space { 1021 public: 1022 // Creates a space with a maximum capacity, and an id. 1023 PagedSpace(Heap* heap, 1024 intptr_t max_capacity, 1025 AllocationSpace id, 1026 Executability executable); 1027 ~PagedSpace()1028 virtual ~PagedSpace() {} 1029 1030 // Set up the space using the given address range of virtual memory (from 1031 // the memory allocator's initial chunk) if possible. If the block of 1032 // addresses is not big enough to contain a single page-aligned page, a 1033 // fresh chunk will be allocated. 1034 bool Setup(Address start, size_t size); 1035 1036 // Returns true if the space has been successfully set up and not 1037 // subsequently torn down. 1038 bool HasBeenSetup(); 1039 1040 // Cleans up the space, frees all pages in this space except those belonging 1041 // to the initial chunk, uncommits addresses in the initial chunk. 1042 void TearDown(); 1043 1044 // Checks whether an object/address is in this space. 1045 inline bool Contains(Address a); Contains(HeapObject * o)1046 bool Contains(HeapObject* o) { return Contains(o->address()); } 1047 // Never crashes even if a is not a valid pointer. 1048 inline bool SafeContains(Address a); 1049 1050 // Given an address occupied by a live object, return that object if it is 1051 // in this space, or Failure::Exception() if it is not. The implementation 1052 // iterates over objects in the page containing the address, the cost is 1053 // linear in the number of objects in the page. It may be slow. 1054 MUST_USE_RESULT MaybeObject* FindObject(Address addr); 1055 1056 // Checks whether page is currently in use by this space. 1057 bool IsUsed(Page* page); 1058 1059 void MarkAllPagesClean(); 1060 1061 // Prepares for a mark-compact GC. 1062 virtual void PrepareForMarkCompact(bool will_compact); 1063 1064 // The top of allocation in a page in this space. Undefined if page is unused. PageAllocationTop(Page * page)1065 Address PageAllocationTop(Page* page) { 1066 return page == TopPageOf(allocation_info_) ? top() 1067 : PageAllocationLimit(page); 1068 } 1069 1070 // The limit of allocation for a page in this space. 1071 virtual Address PageAllocationLimit(Page* page) = 0; 1072 FlushTopPageWatermark()1073 void FlushTopPageWatermark() { 1074 AllocationTopPage()->SetCachedAllocationWatermark(top()); 1075 AllocationTopPage()->InvalidateWatermark(true); 1076 } 1077 1078 // Current capacity without growing (Size() + Available() + Waste()). Capacity()1079 intptr_t Capacity() { return accounting_stats_.Capacity(); } 1080 1081 // Total amount of memory committed for this space. For paged 1082 // spaces this equals the capacity. CommittedMemory()1083 intptr_t CommittedMemory() { return Capacity(); } 1084 1085 // Available bytes without growing. Available()1086 intptr_t Available() { return accounting_stats_.Available(); } 1087 1088 // Allocated bytes in this space. Size()1089 virtual intptr_t Size() { return accounting_stats_.Size(); } 1090 1091 // Wasted bytes due to fragmentation and not recoverable until the 1092 // next GC of this space. Waste()1093 intptr_t Waste() { return accounting_stats_.Waste(); } 1094 1095 // Returns the address of the first object in this space. bottom()1096 Address bottom() { return first_page_->ObjectAreaStart(); } 1097 1098 // Returns the allocation pointer in this space. top()1099 Address top() { return allocation_info_.top; } 1100 1101 // Allocate the requested number of bytes in the space if possible, return a 1102 // failure object if not. 1103 MUST_USE_RESULT inline MaybeObject* AllocateRaw(int size_in_bytes); 1104 1105 // Allocate the requested number of bytes for relocation during mark-compact 1106 // collection. 1107 MUST_USE_RESULT inline MaybeObject* MCAllocateRaw(int size_in_bytes); 1108 1109 virtual bool ReserveSpace(int bytes); 1110 1111 // Used by ReserveSpace. 1112 virtual void PutRestOfCurrentPageOnFreeList(Page* current_page) = 0; 1113 1114 // Free all pages in range from prev (exclusive) to last (inclusive). 1115 // Freed pages are moved to the end of page list. 1116 void FreePages(Page* prev, Page* last); 1117 1118 // Deallocates a block. 1119 virtual void DeallocateBlock(Address start, 1120 int size_in_bytes, 1121 bool add_to_freelist) = 0; 1122 1123 // Set space allocation info. SetTop(Address top)1124 void SetTop(Address top) { 1125 allocation_info_.top = top; 1126 allocation_info_.limit = PageAllocationLimit(Page::FromAllocationTop(top)); 1127 } 1128 1129 // --------------------------------------------------------------------------- 1130 // Mark-compact collection support functions 1131 1132 // Set the relocation point to the beginning of the space. 1133 void MCResetRelocationInfo(); 1134 1135 // Writes relocation info to the top page. MCWriteRelocationInfoToPage()1136 void MCWriteRelocationInfoToPage() { 1137 TopPageOf(mc_forwarding_info_)-> 1138 SetAllocationWatermark(mc_forwarding_info_.top); 1139 } 1140 1141 // Computes the offset of a given address in this space to the beginning 1142 // of the space. 1143 int MCSpaceOffsetForAddress(Address addr); 1144 1145 // Updates the allocation pointer to the relocation top after a mark-compact 1146 // collection. 1147 virtual void MCCommitRelocationInfo() = 0; 1148 1149 // Releases half of unused pages. 1150 void Shrink(); 1151 1152 // Ensures that the capacity is at least 'capacity'. Returns false on failure. 1153 bool EnsureCapacity(int capacity); 1154 1155 #ifdef ENABLE_HEAP_PROTECTION 1156 // Protect/unprotect the space by marking it read-only/writable. 1157 void Protect(); 1158 void Unprotect(); 1159 #endif 1160 1161 #ifdef DEBUG 1162 // Print meta info and objects in this space. 1163 virtual void Print(); 1164 1165 // Verify integrity of this space. 1166 virtual void Verify(ObjectVisitor* visitor); 1167 1168 // Overridden by subclasses to verify space-specific object 1169 // properties (e.g., only maps or free-list nodes are in map space). VerifyObject(HeapObject * obj)1170 virtual void VerifyObject(HeapObject* obj) {} 1171 1172 // Report code object related statistics 1173 void CollectCodeStatistics(); 1174 static void ReportCodeStatistics(); 1175 static void ResetCodeStatistics(); 1176 #endif 1177 1178 // Returns the page of the allocation pointer. AllocationTopPage()1179 Page* AllocationTopPage() { return TopPageOf(allocation_info_); } 1180 1181 void RelinkPageListInChunkOrder(bool deallocate_blocks); 1182 1183 protected: 1184 // Maximum capacity of this space. 1185 intptr_t max_capacity_; 1186 1187 // Accounting information for this space. 1188 AllocationStats accounting_stats_; 1189 1190 // The first page in this space. 1191 Page* first_page_; 1192 1193 // The last page in this space. Initially set in Setup, updated in 1194 // Expand and Shrink. 1195 Page* last_page_; 1196 1197 // True if pages owned by this space are linked in chunk-order. 1198 // See comment for class MemoryAllocator for definition of chunk-order. 1199 bool page_list_is_chunk_ordered_; 1200 1201 // Normal allocation information. 1202 AllocationInfo allocation_info_; 1203 1204 // Relocation information during mark-compact collections. 1205 AllocationInfo mc_forwarding_info_; 1206 1207 // Bytes of each page that cannot be allocated. Possibly non-zero 1208 // for pages in spaces with only fixed-size objects. Always zero 1209 // for pages in spaces with variable sized objects (those pages are 1210 // padded with free-list nodes). 1211 int page_extra_; 1212 1213 // Sets allocation pointer to a page bottom. 1214 static void SetAllocationInfo(AllocationInfo* alloc_info, Page* p); 1215 1216 // Returns the top page specified by an allocation info structure. TopPageOf(AllocationInfo alloc_info)1217 static Page* TopPageOf(AllocationInfo alloc_info) { 1218 return Page::FromAllocationTop(alloc_info.limit); 1219 } 1220 CountPagesToTop()1221 int CountPagesToTop() { 1222 Page* p = Page::FromAllocationTop(allocation_info_.top); 1223 PageIterator it(this, PageIterator::ALL_PAGES); 1224 int counter = 1; 1225 while (it.has_next()) { 1226 if (it.next() == p) return counter; 1227 counter++; 1228 } 1229 UNREACHABLE(); 1230 return -1; 1231 } 1232 1233 // Expands the space by allocating a fixed number of pages. Returns false if 1234 // it cannot allocate requested number of pages from OS. Newly allocated 1235 // pages are append to the last_page; 1236 bool Expand(Page* last_page); 1237 1238 // Generic fast case allocation function that tries linear allocation in 1239 // the top page of 'alloc_info'. Returns NULL on failure. 1240 inline HeapObject* AllocateLinearly(AllocationInfo* alloc_info, 1241 int size_in_bytes); 1242 1243 // During normal allocation or deserialization, roll to the next page in 1244 // the space (there is assumed to be one) and allocate there. This 1245 // function is space-dependent. 1246 virtual HeapObject* AllocateInNextPage(Page* current_page, 1247 int size_in_bytes) = 0; 1248 1249 // Slow path of AllocateRaw. This function is space-dependent. 1250 MUST_USE_RESULT virtual HeapObject* SlowAllocateRaw(int size_in_bytes) = 0; 1251 1252 // Slow path of MCAllocateRaw. 1253 MUST_USE_RESULT HeapObject* SlowMCAllocateRaw(int size_in_bytes); 1254 1255 #ifdef DEBUG 1256 // Returns the number of total pages in this space. 1257 int CountTotalPages(); 1258 #endif 1259 private: 1260 1261 // Returns a pointer to the page of the relocation pointer. MCRelocationTopPage()1262 Page* MCRelocationTopPage() { return TopPageOf(mc_forwarding_info_); } 1263 1264 friend class PageIterator; 1265 }; 1266 1267 1268 #if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING) 1269 class NumberAndSizeInfo BASE_EMBEDDED { 1270 public: NumberAndSizeInfo()1271 NumberAndSizeInfo() : number_(0), bytes_(0) {} 1272 number()1273 int number() const { return number_; } increment_number(int num)1274 void increment_number(int num) { number_ += num; } 1275 bytes()1276 int bytes() const { return bytes_; } increment_bytes(int size)1277 void increment_bytes(int size) { bytes_ += size; } 1278 clear()1279 void clear() { 1280 number_ = 0; 1281 bytes_ = 0; 1282 } 1283 1284 private: 1285 int number_; 1286 int bytes_; 1287 }; 1288 1289 1290 // HistogramInfo class for recording a single "bar" of a histogram. This 1291 // class is used for collecting statistics to print to stdout (when compiled 1292 // with DEBUG) or to the log file (when compiled with 1293 // ENABLE_LOGGING_AND_PROFILING). 1294 class HistogramInfo: public NumberAndSizeInfo { 1295 public: HistogramInfo()1296 HistogramInfo() : NumberAndSizeInfo() {} 1297 name()1298 const char* name() { return name_; } set_name(const char * name)1299 void set_name(const char* name) { name_ = name; } 1300 1301 private: 1302 const char* name_; 1303 }; 1304 #endif 1305 1306 1307 // ----------------------------------------------------------------------------- 1308 // SemiSpace in young generation 1309 // 1310 // A semispace is a contiguous chunk of memory. The mark-compact collector 1311 // uses the memory in the from space as a marking stack when tracing live 1312 // objects. 1313 1314 class SemiSpace : public Space { 1315 public: 1316 // Constructor. SemiSpace(Heap * heap)1317 explicit SemiSpace(Heap* heap) : Space(heap, NEW_SPACE, NOT_EXECUTABLE) { 1318 start_ = NULL; 1319 age_mark_ = NULL; 1320 } 1321 1322 // Sets up the semispace using the given chunk. 1323 bool Setup(Address start, int initial_capacity, int maximum_capacity); 1324 1325 // Tear down the space. Heap memory was not allocated by the space, so it 1326 // is not deallocated here. 1327 void TearDown(); 1328 1329 // True if the space has been set up but not torn down. HasBeenSetup()1330 bool HasBeenSetup() { return start_ != NULL; } 1331 1332 // Grow the size of the semispace by committing extra virtual memory. 1333 // Assumes that the caller has checked that the semispace has not reached 1334 // its maximum capacity (and thus there is space available in the reserved 1335 // address range to grow). 1336 bool Grow(); 1337 1338 // Grow the semispace to the new capacity. The new capacity 1339 // requested must be larger than the current capacity. 1340 bool GrowTo(int new_capacity); 1341 1342 // Shrinks the semispace to the new capacity. The new capacity 1343 // requested must be more than the amount of used memory in the 1344 // semispace and less than the current capacity. 1345 bool ShrinkTo(int new_capacity); 1346 1347 // Returns the start address of the space. low()1348 Address low() { return start_; } 1349 // Returns one past the end address of the space. high()1350 Address high() { return low() + capacity_; } 1351 1352 // Age mark accessors. age_mark()1353 Address age_mark() { return age_mark_; } set_age_mark(Address mark)1354 void set_age_mark(Address mark) { age_mark_ = mark; } 1355 1356 // True if the address is in the address range of this semispace (not 1357 // necessarily below the allocation pointer). Contains(Address a)1358 bool Contains(Address a) { 1359 return (reinterpret_cast<uintptr_t>(a) & address_mask_) 1360 == reinterpret_cast<uintptr_t>(start_); 1361 } 1362 1363 // True if the object is a heap object in the address range of this 1364 // semispace (not necessarily below the allocation pointer). Contains(Object * o)1365 bool Contains(Object* o) { 1366 return (reinterpret_cast<uintptr_t>(o) & object_mask_) == object_expected_; 1367 } 1368 1369 // The offset of an address from the beginning of the space. SpaceOffsetForAddress(Address addr)1370 int SpaceOffsetForAddress(Address addr) { 1371 return static_cast<int>(addr - low()); 1372 } 1373 1374 // If we don't have these here then SemiSpace will be abstract. However 1375 // they should never be called. Size()1376 virtual intptr_t Size() { 1377 UNREACHABLE(); 1378 return 0; 1379 } 1380 ReserveSpace(int bytes)1381 virtual bool ReserveSpace(int bytes) { 1382 UNREACHABLE(); 1383 return false; 1384 } 1385 is_committed()1386 bool is_committed() { return committed_; } 1387 bool Commit(); 1388 bool Uncommit(); 1389 1390 #ifdef ENABLE_HEAP_PROTECTION 1391 // Protect/unprotect the space by marking it read-only/writable. Protect()1392 virtual void Protect() {} Unprotect()1393 virtual void Unprotect() {} 1394 #endif 1395 1396 #ifdef DEBUG 1397 virtual void Print(); 1398 virtual void Verify(); 1399 #endif 1400 1401 // Returns the current capacity of the semi space. Capacity()1402 int Capacity() { return capacity_; } 1403 1404 // Returns the maximum capacity of the semi space. MaximumCapacity()1405 int MaximumCapacity() { return maximum_capacity_; } 1406 1407 // Returns the initial capacity of the semi space. InitialCapacity()1408 int InitialCapacity() { return initial_capacity_; } 1409 1410 private: 1411 // The current and maximum capacity of the space. 1412 int capacity_; 1413 int maximum_capacity_; 1414 int initial_capacity_; 1415 1416 // The start address of the space. 1417 Address start_; 1418 // Used to govern object promotion during mark-compact collection. 1419 Address age_mark_; 1420 1421 // Masks and comparison values to test for containment in this semispace. 1422 uintptr_t address_mask_; 1423 uintptr_t object_mask_; 1424 uintptr_t object_expected_; 1425 1426 bool committed_; 1427 1428 public: 1429 TRACK_MEMORY("SemiSpace") 1430 }; 1431 1432 1433 // A SemiSpaceIterator is an ObjectIterator that iterates over the active 1434 // semispace of the heap's new space. It iterates over the objects in the 1435 // semispace from a given start address (defaulting to the bottom of the 1436 // semispace) to the top of the semispace. New objects allocated after the 1437 // iterator is created are not iterated. 1438 class SemiSpaceIterator : public ObjectIterator { 1439 public: 1440 // Create an iterator over the objects in the given space. If no start 1441 // address is given, the iterator starts from the bottom of the space. If 1442 // no size function is given, the iterator calls Object::Size(). 1443 explicit SemiSpaceIterator(NewSpace* space); 1444 SemiSpaceIterator(NewSpace* space, HeapObjectCallback size_func); 1445 SemiSpaceIterator(NewSpace* space, Address start); 1446 next()1447 HeapObject* next() { 1448 if (current_ == limit_) return NULL; 1449 1450 HeapObject* object = HeapObject::FromAddress(current_); 1451 int size = (size_func_ == NULL) ? object->Size() : size_func_(object); 1452 1453 current_ += size; 1454 return object; 1455 } 1456 1457 // Implementation of the ObjectIterator functions. next_object()1458 virtual HeapObject* next_object() { return next(); } 1459 1460 private: 1461 void Initialize(NewSpace* space, Address start, Address end, 1462 HeapObjectCallback size_func); 1463 1464 // The semispace. 1465 SemiSpace* space_; 1466 // The current iteration point. 1467 Address current_; 1468 // The end of iteration. 1469 Address limit_; 1470 // The callback function. 1471 HeapObjectCallback size_func_; 1472 }; 1473 1474 1475 // ----------------------------------------------------------------------------- 1476 // The young generation space. 1477 // 1478 // The new space consists of a contiguous pair of semispaces. It simply 1479 // forwards most functions to the appropriate semispace. 1480 1481 class NewSpace : public Space { 1482 public: 1483 // Constructor. NewSpace(Heap * heap)1484 explicit NewSpace(Heap* heap) 1485 : Space(heap, NEW_SPACE, NOT_EXECUTABLE), 1486 to_space_(heap), 1487 from_space_(heap) {} 1488 1489 // Sets up the new space using the given chunk. 1490 bool Setup(Address start, int size); 1491 1492 // Tears down the space. Heap memory was not allocated by the space, so it 1493 // is not deallocated here. 1494 void TearDown(); 1495 1496 // True if the space has been set up but not torn down. HasBeenSetup()1497 bool HasBeenSetup() { 1498 return to_space_.HasBeenSetup() && from_space_.HasBeenSetup(); 1499 } 1500 1501 // Flip the pair of spaces. 1502 void Flip(); 1503 1504 // Grow the capacity of the semispaces. Assumes that they are not at 1505 // their maximum capacity. 1506 void Grow(); 1507 1508 // Shrink the capacity of the semispaces. 1509 void Shrink(); 1510 1511 // True if the address or object lies in the address range of either 1512 // semispace (not necessarily below the allocation pointer). Contains(Address a)1513 bool Contains(Address a) { 1514 return (reinterpret_cast<uintptr_t>(a) & address_mask_) 1515 == reinterpret_cast<uintptr_t>(start_); 1516 } Contains(Object * o)1517 bool Contains(Object* o) { 1518 return (reinterpret_cast<uintptr_t>(o) & object_mask_) == object_expected_; 1519 } 1520 1521 // Return the allocated bytes in the active semispace. Size()1522 virtual intptr_t Size() { return static_cast<int>(top() - bottom()); } 1523 // The same, but returning an int. We have to have the one that returns 1524 // intptr_t because it is inherited, but if we know we are dealing with the 1525 // new space, which can't get as big as the other spaces then this is useful: SizeAsInt()1526 int SizeAsInt() { return static_cast<int>(Size()); } 1527 1528 // Return the current capacity of a semispace. Capacity()1529 intptr_t Capacity() { 1530 ASSERT(to_space_.Capacity() == from_space_.Capacity()); 1531 return to_space_.Capacity(); 1532 } 1533 1534 // Return the total amount of memory committed for new space. CommittedMemory()1535 intptr_t CommittedMemory() { 1536 if (from_space_.is_committed()) return 2 * Capacity(); 1537 return Capacity(); 1538 } 1539 1540 // Return the available bytes without growing in the active semispace. Available()1541 intptr_t Available() { return Capacity() - Size(); } 1542 1543 // Return the maximum capacity of a semispace. MaximumCapacity()1544 int MaximumCapacity() { 1545 ASSERT(to_space_.MaximumCapacity() == from_space_.MaximumCapacity()); 1546 return to_space_.MaximumCapacity(); 1547 } 1548 1549 // Returns the initial capacity of a semispace. InitialCapacity()1550 int InitialCapacity() { 1551 ASSERT(to_space_.InitialCapacity() == from_space_.InitialCapacity()); 1552 return to_space_.InitialCapacity(); 1553 } 1554 1555 // Return the address of the allocation pointer in the active semispace. top()1556 Address top() { return allocation_info_.top; } 1557 // Return the address of the first object in the active semispace. bottom()1558 Address bottom() { return to_space_.low(); } 1559 1560 // Get the age mark of the inactive semispace. age_mark()1561 Address age_mark() { return from_space_.age_mark(); } 1562 // Set the age mark in the active semispace. set_age_mark(Address mark)1563 void set_age_mark(Address mark) { to_space_.set_age_mark(mark); } 1564 1565 // The start address of the space and a bit mask. Anding an address in the 1566 // new space with the mask will result in the start address. start()1567 Address start() { return start_; } mask()1568 uintptr_t mask() { return address_mask_; } 1569 1570 // The allocation top and limit addresses. allocation_top_address()1571 Address* allocation_top_address() { return &allocation_info_.top; } allocation_limit_address()1572 Address* allocation_limit_address() { return &allocation_info_.limit; } 1573 AllocateRaw(int size_in_bytes)1574 MUST_USE_RESULT MaybeObject* AllocateRaw(int size_in_bytes) { 1575 return AllocateRawInternal(size_in_bytes, &allocation_info_); 1576 } 1577 1578 // Allocate the requested number of bytes for relocation during mark-compact 1579 // collection. MCAllocateRaw(int size_in_bytes)1580 MUST_USE_RESULT MaybeObject* MCAllocateRaw(int size_in_bytes) { 1581 return AllocateRawInternal(size_in_bytes, &mc_forwarding_info_); 1582 } 1583 1584 // Reset the allocation pointer to the beginning of the active semispace. 1585 void ResetAllocationInfo(); 1586 // Reset the reloction pointer to the bottom of the inactive semispace in 1587 // preparation for mark-compact collection. 1588 void MCResetRelocationInfo(); 1589 // Update the allocation pointer in the active semispace after a 1590 // mark-compact collection. 1591 void MCCommitRelocationInfo(); 1592 1593 // Get the extent of the inactive semispace (for use as a marking stack). FromSpaceLow()1594 Address FromSpaceLow() { return from_space_.low(); } FromSpaceHigh()1595 Address FromSpaceHigh() { return from_space_.high(); } 1596 1597 // Get the extent of the active semispace (to sweep newly copied objects 1598 // during a scavenge collection). ToSpaceLow()1599 Address ToSpaceLow() { return to_space_.low(); } ToSpaceHigh()1600 Address ToSpaceHigh() { return to_space_.high(); } 1601 1602 // Offsets from the beginning of the semispaces. ToSpaceOffsetForAddress(Address a)1603 int ToSpaceOffsetForAddress(Address a) { 1604 return to_space_.SpaceOffsetForAddress(a); 1605 } FromSpaceOffsetForAddress(Address a)1606 int FromSpaceOffsetForAddress(Address a) { 1607 return from_space_.SpaceOffsetForAddress(a); 1608 } 1609 1610 // True if the object is a heap object in the address range of the 1611 // respective semispace (not necessarily below the allocation pointer of the 1612 // semispace). ToSpaceContains(Object * o)1613 bool ToSpaceContains(Object* o) { return to_space_.Contains(o); } FromSpaceContains(Object * o)1614 bool FromSpaceContains(Object* o) { return from_space_.Contains(o); } 1615 ToSpaceContains(Address a)1616 bool ToSpaceContains(Address a) { return to_space_.Contains(a); } FromSpaceContains(Address a)1617 bool FromSpaceContains(Address a) { return from_space_.Contains(a); } 1618 1619 virtual bool ReserveSpace(int bytes); 1620 1621 // Resizes a sequential string which must be the most recent thing that was 1622 // allocated in new space. 1623 template <typename StringType> 1624 inline void ShrinkStringAtAllocationBoundary(String* string, int len); 1625 1626 #ifdef ENABLE_HEAP_PROTECTION 1627 // Protect/unprotect the space by marking it read-only/writable. 1628 virtual void Protect(); 1629 virtual void Unprotect(); 1630 #endif 1631 1632 #ifdef DEBUG 1633 // Verify the active semispace. 1634 virtual void Verify(); 1635 // Print the active semispace. Print()1636 virtual void Print() { to_space_.Print(); } 1637 #endif 1638 1639 #if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING) 1640 // Iterates the active semispace to collect statistics. 1641 void CollectStatistics(); 1642 // Reports previously collected statistics of the active semispace. 1643 void ReportStatistics(); 1644 // Clears previously collected statistics. 1645 void ClearHistograms(); 1646 1647 // Record the allocation or promotion of a heap object. Note that we don't 1648 // record every single allocation, but only those that happen in the 1649 // to space during a scavenge GC. 1650 void RecordAllocation(HeapObject* obj); 1651 void RecordPromotion(HeapObject* obj); 1652 #endif 1653 1654 // Return whether the operation succeded. CommitFromSpaceIfNeeded()1655 bool CommitFromSpaceIfNeeded() { 1656 if (from_space_.is_committed()) return true; 1657 return from_space_.Commit(); 1658 } 1659 UncommitFromSpace()1660 bool UncommitFromSpace() { 1661 if (!from_space_.is_committed()) return true; 1662 return from_space_.Uncommit(); 1663 } 1664 1665 private: 1666 // The semispaces. 1667 SemiSpace to_space_; 1668 SemiSpace from_space_; 1669 1670 // Start address and bit mask for containment testing. 1671 Address start_; 1672 uintptr_t address_mask_; 1673 uintptr_t object_mask_; 1674 uintptr_t object_expected_; 1675 1676 // Allocation pointer and limit for normal allocation and allocation during 1677 // mark-compact collection. 1678 AllocationInfo allocation_info_; 1679 AllocationInfo mc_forwarding_info_; 1680 1681 #if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING) 1682 HistogramInfo* allocated_histogram_; 1683 HistogramInfo* promoted_histogram_; 1684 #endif 1685 1686 // Implementation of AllocateRaw and MCAllocateRaw. 1687 MUST_USE_RESULT inline MaybeObject* AllocateRawInternal( 1688 int size_in_bytes, 1689 AllocationInfo* alloc_info); 1690 1691 friend class SemiSpaceIterator; 1692 1693 public: 1694 TRACK_MEMORY("NewSpace") 1695 }; 1696 1697 1698 // ----------------------------------------------------------------------------- 1699 // Free lists for old object spaces 1700 // 1701 // Free-list nodes are free blocks in the heap. They look like heap objects 1702 // (free-list node pointers have the heap object tag, and they have a map like 1703 // a heap object). They have a size and a next pointer. The next pointer is 1704 // the raw address of the next free list node (or NULL). 1705 class FreeListNode: public HeapObject { 1706 public: 1707 // Obtain a free-list node from a raw address. This is not a cast because 1708 // it does not check nor require that the first word at the address is a map 1709 // pointer. FromAddress(Address address)1710 static FreeListNode* FromAddress(Address address) { 1711 return reinterpret_cast<FreeListNode*>(HeapObject::FromAddress(address)); 1712 } 1713 1714 static inline bool IsFreeListNode(HeapObject* object); 1715 1716 // Set the size in bytes, which can be read with HeapObject::Size(). This 1717 // function also writes a map to the first word of the block so that it 1718 // looks like a heap object to the garbage collector and heap iteration 1719 // functions. 1720 void set_size(Heap* heap, int size_in_bytes); 1721 1722 // Accessors for the next field. 1723 inline Address next(Heap* heap); 1724 inline void set_next(Heap* heap, Address next); 1725 1726 private: 1727 static const int kNextOffset = POINTER_SIZE_ALIGN(ByteArray::kHeaderSize); 1728 1729 DISALLOW_IMPLICIT_CONSTRUCTORS(FreeListNode); 1730 }; 1731 1732 1733 // The free list for the old space. 1734 class OldSpaceFreeList BASE_EMBEDDED { 1735 public: 1736 OldSpaceFreeList(Heap* heap, AllocationSpace owner); 1737 1738 // Clear the free list. 1739 void Reset(); 1740 1741 // Return the number of bytes available on the free list. available()1742 intptr_t available() { return available_; } 1743 1744 // Place a node on the free list. The block of size 'size_in_bytes' 1745 // starting at 'start' is placed on the free list. The return value is the 1746 // number of bytes that have been lost due to internal fragmentation by 1747 // freeing the block. Bookkeeping information will be written to the block, 1748 // ie, its contents will be destroyed. The start address should be word 1749 // aligned, and the size should be a non-zero multiple of the word size. 1750 int Free(Address start, int size_in_bytes); 1751 1752 // Allocate a block of size 'size_in_bytes' from the free list. The block 1753 // is unitialized. A failure is returned if no block is available. The 1754 // number of bytes lost to fragmentation is returned in the output parameter 1755 // 'wasted_bytes'. The size should be a non-zero multiple of the word size. 1756 MUST_USE_RESULT MaybeObject* Allocate(int size_in_bytes, int* wasted_bytes); 1757 1758 void MarkNodes(); 1759 1760 private: 1761 // The size range of blocks, in bytes. (Smaller allocations are allowed, but 1762 // will always result in waste.) 1763 static const int kMinBlockSize = 2 * kPointerSize; 1764 static const int kMaxBlockSize = Page::kMaxHeapObjectSize; 1765 1766 Heap* heap_; 1767 1768 // The identity of the owning space, for building allocation Failure 1769 // objects. 1770 AllocationSpace owner_; 1771 1772 // Total available bytes in all blocks on this free list. 1773 int available_; 1774 1775 // Blocks are put on exact free lists in an array, indexed by size in words. 1776 // The available sizes are kept in an increasingly ordered list. Entries 1777 // corresponding to sizes < kMinBlockSize always have an empty free list 1778 // (but index kHead is used for the head of the size list). 1779 struct SizeNode { 1780 // Address of the head FreeListNode of the implied block size or NULL. 1781 Address head_node_; 1782 // Size (words) of the next larger available size if head_node_ != NULL. 1783 int next_size_; 1784 }; 1785 static const int kFreeListsLength = kMaxBlockSize / kPointerSize + 1; 1786 SizeNode free_[kFreeListsLength]; 1787 1788 // Sentinel elements for the size list. Real elements are in ]kHead..kEnd[. 1789 static const int kHead = kMinBlockSize / kPointerSize - 1; 1790 static const int kEnd = kMaxInt; 1791 1792 // We keep a "finger" in the size list to speed up a common pattern: 1793 // repeated requests for the same or increasing sizes. 1794 int finger_; 1795 1796 // Starting from *prev, find and return the smallest size >= index (words), 1797 // or kEnd. Update *prev to be the largest size < index, or kHead. FindSize(int index,int * prev)1798 int FindSize(int index, int* prev) { 1799 int cur = free_[*prev].next_size_; 1800 while (cur < index) { 1801 *prev = cur; 1802 cur = free_[cur].next_size_; 1803 } 1804 return cur; 1805 } 1806 1807 // Remove an existing element from the size list. RemoveSize(int index)1808 void RemoveSize(int index) { 1809 int prev = kHead; 1810 int cur = FindSize(index, &prev); 1811 ASSERT(cur == index); 1812 free_[prev].next_size_ = free_[cur].next_size_; 1813 finger_ = prev; 1814 } 1815 1816 // Insert a new element into the size list. InsertSize(int index)1817 void InsertSize(int index) { 1818 int prev = kHead; 1819 int cur = FindSize(index, &prev); 1820 ASSERT(cur != index); 1821 free_[prev].next_size_ = index; 1822 free_[index].next_size_ = cur; 1823 } 1824 1825 // The size list is not updated during a sequence of calls to Free, but is 1826 // rebuilt before the next allocation. 1827 void RebuildSizeList(); 1828 bool needs_rebuild_; 1829 1830 #ifdef DEBUG 1831 // Does this free list contain a free block located at the address of 'node'? 1832 bool Contains(FreeListNode* node); 1833 #endif 1834 1835 DISALLOW_COPY_AND_ASSIGN(OldSpaceFreeList); 1836 }; 1837 1838 1839 // The free list for the map space. 1840 class FixedSizeFreeList BASE_EMBEDDED { 1841 public: 1842 FixedSizeFreeList(Heap* heap, AllocationSpace owner, int object_size); 1843 1844 // Clear the free list. 1845 void Reset(); 1846 1847 // Return the number of bytes available on the free list. available()1848 intptr_t available() { return available_; } 1849 1850 // Place a node on the free list. The block starting at 'start' (assumed to 1851 // have size object_size_) is placed on the free list. Bookkeeping 1852 // information will be written to the block, ie, its contents will be 1853 // destroyed. The start address should be word aligned. 1854 void Free(Address start); 1855 1856 // Allocate a fixed sized block from the free list. The block is unitialized. 1857 // A failure is returned if no block is available. 1858 MUST_USE_RESULT MaybeObject* Allocate(); 1859 1860 void MarkNodes(); 1861 1862 private: 1863 1864 Heap* heap_; 1865 1866 // Available bytes on the free list. 1867 intptr_t available_; 1868 1869 // The head of the free list. 1870 Address head_; 1871 1872 // The tail of the free list. 1873 Address tail_; 1874 1875 // The identity of the owning space, for building allocation Failure 1876 // objects. 1877 AllocationSpace owner_; 1878 1879 // The size of the objects in this space. 1880 int object_size_; 1881 1882 DISALLOW_COPY_AND_ASSIGN(FixedSizeFreeList); 1883 }; 1884 1885 1886 // ----------------------------------------------------------------------------- 1887 // Old object space (excluding map objects) 1888 1889 class OldSpace : public PagedSpace { 1890 public: 1891 // Creates an old space object with a given maximum capacity. 1892 // The constructor does not allocate pages from OS. OldSpace(Heap * heap,intptr_t max_capacity,AllocationSpace id,Executability executable)1893 OldSpace(Heap* heap, 1894 intptr_t max_capacity, 1895 AllocationSpace id, 1896 Executability executable) 1897 : PagedSpace(heap, max_capacity, id, executable), 1898 free_list_(heap, id) { 1899 page_extra_ = 0; 1900 } 1901 1902 // The bytes available on the free list (ie, not above the linear allocation 1903 // pointer). AvailableFree()1904 intptr_t AvailableFree() { return free_list_.available(); } 1905 1906 // The limit of allocation for a page in this space. PageAllocationLimit(Page * page)1907 virtual Address PageAllocationLimit(Page* page) { 1908 return page->ObjectAreaEnd(); 1909 } 1910 1911 // Give a block of memory to the space's free list. It might be added to 1912 // the free list or accounted as waste. 1913 // If add_to_freelist is false then just accounting stats are updated and 1914 // no attempt to add area to free list is made. Free(Address start,int size_in_bytes,bool add_to_freelist)1915 void Free(Address start, int size_in_bytes, bool add_to_freelist) { 1916 accounting_stats_.DeallocateBytes(size_in_bytes); 1917 1918 if (add_to_freelist) { 1919 int wasted_bytes = free_list_.Free(start, size_in_bytes); 1920 accounting_stats_.WasteBytes(wasted_bytes); 1921 } 1922 } 1923 1924 virtual void DeallocateBlock(Address start, 1925 int size_in_bytes, 1926 bool add_to_freelist); 1927 1928 // Prepare for full garbage collection. Resets the relocation pointer and 1929 // clears the free list. 1930 virtual void PrepareForMarkCompact(bool will_compact); 1931 1932 // Updates the allocation pointer to the relocation top after a mark-compact 1933 // collection. 1934 virtual void MCCommitRelocationInfo(); 1935 1936 virtual void PutRestOfCurrentPageOnFreeList(Page* current_page); 1937 MarkFreeListNodes()1938 void MarkFreeListNodes() { free_list_.MarkNodes(); } 1939 1940 #ifdef DEBUG 1941 // Reports statistics for the space 1942 void ReportStatistics(); 1943 #endif 1944 1945 protected: 1946 // Virtual function in the superclass. Slow path of AllocateRaw. 1947 MUST_USE_RESULT HeapObject* SlowAllocateRaw(int size_in_bytes); 1948 1949 // Virtual function in the superclass. Allocate linearly at the start of 1950 // the page after current_page (there is assumed to be one). 1951 HeapObject* AllocateInNextPage(Page* current_page, int size_in_bytes); 1952 1953 private: 1954 // The space's free list. 1955 OldSpaceFreeList free_list_; 1956 1957 public: 1958 TRACK_MEMORY("OldSpace") 1959 }; 1960 1961 1962 // ----------------------------------------------------------------------------- 1963 // Old space for objects of a fixed size 1964 1965 class FixedSpace : public PagedSpace { 1966 public: FixedSpace(Heap * heap,intptr_t max_capacity,AllocationSpace id,int object_size_in_bytes,const char * name)1967 FixedSpace(Heap* heap, 1968 intptr_t max_capacity, 1969 AllocationSpace id, 1970 int object_size_in_bytes, 1971 const char* name) 1972 : PagedSpace(heap, max_capacity, id, NOT_EXECUTABLE), 1973 object_size_in_bytes_(object_size_in_bytes), 1974 name_(name), 1975 free_list_(heap, id, object_size_in_bytes) { 1976 page_extra_ = Page::kObjectAreaSize % object_size_in_bytes; 1977 } 1978 1979 // The limit of allocation for a page in this space. PageAllocationLimit(Page * page)1980 virtual Address PageAllocationLimit(Page* page) { 1981 return page->ObjectAreaEnd() - page_extra_; 1982 } 1983 object_size_in_bytes()1984 int object_size_in_bytes() { return object_size_in_bytes_; } 1985 1986 // Give a fixed sized block of memory to the space's free list. 1987 // If add_to_freelist is false then just accounting stats are updated and 1988 // no attempt to add area to free list is made. Free(Address start,bool add_to_freelist)1989 void Free(Address start, bool add_to_freelist) { 1990 if (add_to_freelist) { 1991 free_list_.Free(start); 1992 } 1993 accounting_stats_.DeallocateBytes(object_size_in_bytes_); 1994 } 1995 1996 // Prepares for a mark-compact GC. 1997 virtual void PrepareForMarkCompact(bool will_compact); 1998 1999 // Updates the allocation pointer to the relocation top after a mark-compact 2000 // collection. 2001 virtual void MCCommitRelocationInfo(); 2002 2003 virtual void PutRestOfCurrentPageOnFreeList(Page* current_page); 2004 2005 virtual void DeallocateBlock(Address start, 2006 int size_in_bytes, 2007 bool add_to_freelist); 2008 MarkFreeListNodes()2009 void MarkFreeListNodes() { free_list_.MarkNodes(); } 2010 2011 #ifdef DEBUG 2012 // Reports statistic info of the space 2013 void ReportStatistics(); 2014 #endif 2015 2016 protected: 2017 // Virtual function in the superclass. Slow path of AllocateRaw. 2018 MUST_USE_RESULT HeapObject* SlowAllocateRaw(int size_in_bytes); 2019 2020 // Virtual function in the superclass. Allocate linearly at the start of 2021 // the page after current_page (there is assumed to be one). 2022 HeapObject* AllocateInNextPage(Page* current_page, int size_in_bytes); 2023 ResetFreeList()2024 void ResetFreeList() { 2025 free_list_.Reset(); 2026 } 2027 2028 private: 2029 // The size of objects in this space. 2030 int object_size_in_bytes_; 2031 2032 // The name of this space. 2033 const char* name_; 2034 2035 // The space's free list. 2036 FixedSizeFreeList free_list_; 2037 }; 2038 2039 2040 // ----------------------------------------------------------------------------- 2041 // Old space for all map objects 2042 2043 class MapSpace : public FixedSpace { 2044 public: 2045 // Creates a map space object with a maximum capacity. MapSpace(Heap * heap,intptr_t max_capacity,int max_map_space_pages,AllocationSpace id)2046 MapSpace(Heap* heap, 2047 intptr_t max_capacity, 2048 int max_map_space_pages, 2049 AllocationSpace id) 2050 : FixedSpace(heap, max_capacity, id, Map::kSize, "map"), 2051 max_map_space_pages_(max_map_space_pages) { 2052 ASSERT(max_map_space_pages < kMaxMapPageIndex); 2053 } 2054 2055 // Prepares for a mark-compact GC. 2056 virtual void PrepareForMarkCompact(bool will_compact); 2057 2058 // Given an index, returns the page address. PageAddress(int page_index)2059 Address PageAddress(int page_index) { return page_addresses_[page_index]; } 2060 2061 static const int kMaxMapPageIndex = 1 << MapWord::kMapPageIndexBits; 2062 2063 // Are map pointers encodable into map word? MapPointersEncodable()2064 bool MapPointersEncodable() { 2065 if (!FLAG_use_big_map_space) { 2066 ASSERT(CountPagesToTop() <= kMaxMapPageIndex); 2067 return true; 2068 } 2069 return CountPagesToTop() <= max_map_space_pages_; 2070 } 2071 2072 // Should be called after forced sweep to find out if map space needs 2073 // compaction. NeedsCompaction(int live_maps)2074 bool NeedsCompaction(int live_maps) { 2075 return !MapPointersEncodable() && live_maps <= CompactionThreshold(); 2076 } 2077 TopAfterCompaction(int live_maps)2078 Address TopAfterCompaction(int live_maps) { 2079 ASSERT(NeedsCompaction(live_maps)); 2080 2081 int pages_left = live_maps / kMapsPerPage; 2082 PageIterator it(this, PageIterator::ALL_PAGES); 2083 while (pages_left-- > 0) { 2084 ASSERT(it.has_next()); 2085 it.next()->SetRegionMarks(Page::kAllRegionsCleanMarks); 2086 } 2087 ASSERT(it.has_next()); 2088 Page* top_page = it.next(); 2089 top_page->SetRegionMarks(Page::kAllRegionsCleanMarks); 2090 ASSERT(top_page->is_valid()); 2091 2092 int offset = live_maps % kMapsPerPage * Map::kSize; 2093 Address top = top_page->ObjectAreaStart() + offset; 2094 ASSERT(top < top_page->ObjectAreaEnd()); 2095 ASSERT(Contains(top)); 2096 2097 return top; 2098 } 2099 FinishCompaction(Address new_top,int live_maps)2100 void FinishCompaction(Address new_top, int live_maps) { 2101 Page* top_page = Page::FromAddress(new_top); 2102 ASSERT(top_page->is_valid()); 2103 2104 SetAllocationInfo(&allocation_info_, top_page); 2105 allocation_info_.top = new_top; 2106 2107 int new_size = live_maps * Map::kSize; 2108 accounting_stats_.DeallocateBytes(accounting_stats_.Size()); 2109 accounting_stats_.AllocateBytes(new_size); 2110 2111 // Flush allocation watermarks. 2112 for (Page* p = first_page_; p != top_page; p = p->next_page()) { 2113 p->SetAllocationWatermark(p->AllocationTop()); 2114 } 2115 top_page->SetAllocationWatermark(new_top); 2116 2117 #ifdef DEBUG 2118 if (FLAG_enable_slow_asserts) { 2119 intptr_t actual_size = 0; 2120 for (Page* p = first_page_; p != top_page; p = p->next_page()) 2121 actual_size += kMapsPerPage * Map::kSize; 2122 actual_size += (new_top - top_page->ObjectAreaStart()); 2123 ASSERT(accounting_stats_.Size() == actual_size); 2124 } 2125 #endif 2126 2127 Shrink(); 2128 ResetFreeList(); 2129 } 2130 2131 protected: 2132 #ifdef DEBUG 2133 virtual void VerifyObject(HeapObject* obj); 2134 #endif 2135 2136 private: 2137 static const int kMapsPerPage = Page::kObjectAreaSize / Map::kSize; 2138 2139 // Do map space compaction if there is a page gap. CompactionThreshold()2140 int CompactionThreshold() { 2141 return kMapsPerPage * (max_map_space_pages_ - 1); 2142 } 2143 2144 const int max_map_space_pages_; 2145 2146 // An array of page start address in a map space. 2147 Address page_addresses_[kMaxMapPageIndex]; 2148 2149 public: 2150 TRACK_MEMORY("MapSpace") 2151 }; 2152 2153 2154 // ----------------------------------------------------------------------------- 2155 // Old space for all global object property cell objects 2156 2157 class CellSpace : public FixedSpace { 2158 public: 2159 // Creates a property cell space object with a maximum capacity. CellSpace(Heap * heap,intptr_t max_capacity,AllocationSpace id)2160 CellSpace(Heap* heap, intptr_t max_capacity, AllocationSpace id) 2161 : FixedSpace(heap, max_capacity, id, JSGlobalPropertyCell::kSize, "cell") 2162 {} 2163 2164 protected: 2165 #ifdef DEBUG 2166 virtual void VerifyObject(HeapObject* obj); 2167 #endif 2168 2169 public: 2170 TRACK_MEMORY("CellSpace") 2171 }; 2172 2173 2174 // ----------------------------------------------------------------------------- 2175 // Large objects ( > Page::kMaxHeapObjectSize ) are allocated and managed by 2176 // the large object space. A large object is allocated from OS heap with 2177 // extra padding bytes (Page::kPageSize + Page::kObjectStartOffset). 2178 // A large object always starts at Page::kObjectStartOffset to a page. 2179 // Large objects do not move during garbage collections. 2180 2181 // A LargeObjectChunk holds exactly one large object page with exactly one 2182 // large object. 2183 class LargeObjectChunk { 2184 public: 2185 // Allocates a new LargeObjectChunk that contains a large object page 2186 // (Page::kPageSize aligned) that has at least size_in_bytes (for a large 2187 // object) bytes after the object area start of that page. 2188 static LargeObjectChunk* New(int size_in_bytes, Executability executable); 2189 2190 // Free the memory associated with the chunk. 2191 inline void Free(Executability executable); 2192 2193 // Interpret a raw address as a large object chunk. FromAddress(Address address)2194 static LargeObjectChunk* FromAddress(Address address) { 2195 return reinterpret_cast<LargeObjectChunk*>(address); 2196 } 2197 2198 // Returns the address of this chunk. address()2199 Address address() { return reinterpret_cast<Address>(this); } 2200 2201 // Accessors for the fields of the chunk. next()2202 LargeObjectChunk* next() { return next_; } set_next(LargeObjectChunk * chunk)2203 void set_next(LargeObjectChunk* chunk) { next_ = chunk; } size()2204 size_t size() { return size_ & ~Page::kPageFlagMask; } 2205 2206 // Compute the start address in the chunk. 2207 inline Address GetStartAddress(); 2208 2209 // Returns the object in this chunk. GetObject()2210 HeapObject* GetObject() { return HeapObject::FromAddress(GetStartAddress()); } 2211 2212 // Given a requested size returns the physical size of a chunk to be 2213 // allocated. 2214 static int ChunkSizeFor(int size_in_bytes); 2215 2216 // Given a chunk size, returns the object size it can accommodate. Used by 2217 // LargeObjectSpace::Available. ObjectSizeFor(intptr_t chunk_size)2218 static intptr_t ObjectSizeFor(intptr_t chunk_size) { 2219 if (chunk_size <= (Page::kPageSize + Page::kObjectStartOffset)) return 0; 2220 return chunk_size - Page::kPageSize - Page::kObjectStartOffset; 2221 } 2222 2223 private: 2224 // A pointer to the next large object chunk in the space or NULL. 2225 LargeObjectChunk* next_; 2226 2227 // The total size of this chunk. 2228 size_t size_; 2229 2230 public: 2231 TRACK_MEMORY("LargeObjectChunk") 2232 }; 2233 2234 2235 class LargeObjectSpace : public Space { 2236 public: 2237 LargeObjectSpace(Heap* heap, AllocationSpace id); ~LargeObjectSpace()2238 virtual ~LargeObjectSpace() {} 2239 2240 // Initializes internal data structures. 2241 bool Setup(); 2242 2243 // Releases internal resources, frees objects in this space. 2244 void TearDown(); 2245 2246 // Allocates a (non-FixedArray, non-Code) large object. 2247 MUST_USE_RESULT MaybeObject* AllocateRaw(int size_in_bytes); 2248 // Allocates a large Code object. 2249 MUST_USE_RESULT MaybeObject* AllocateRawCode(int size_in_bytes); 2250 // Allocates a large FixedArray. 2251 MUST_USE_RESULT MaybeObject* AllocateRawFixedArray(int size_in_bytes); 2252 2253 // Available bytes for objects in this space. 2254 inline intptr_t Available(); 2255 Size()2256 virtual intptr_t Size() { 2257 return size_; 2258 } 2259 SizeOfObjects()2260 virtual intptr_t SizeOfObjects() { 2261 return objects_size_; 2262 } 2263 PageCount()2264 int PageCount() { 2265 return page_count_; 2266 } 2267 2268 // Finds an object for a given address, returns Failure::Exception() 2269 // if it is not found. The function iterates through all objects in this 2270 // space, may be slow. 2271 MaybeObject* FindObject(Address a); 2272 2273 // Finds a large object page containing the given pc, returns NULL 2274 // if such a page doesn't exist. 2275 LargeObjectChunk* FindChunkContainingPc(Address pc); 2276 2277 // Iterates objects covered by dirty regions. 2278 void IterateDirtyRegions(ObjectSlotCallback func); 2279 2280 // Frees unmarked objects. 2281 void FreeUnmarkedObjects(); 2282 2283 // Checks whether a heap object is in this space; O(1). 2284 bool Contains(HeapObject* obj); 2285 2286 // Checks whether the space is empty. IsEmpty()2287 bool IsEmpty() { return first_chunk_ == NULL; } 2288 2289 // See the comments for ReserveSpace in the Space class. This has to be 2290 // called after ReserveSpace has been called on the paged spaces, since they 2291 // may use some memory, leaving less for large objects. 2292 virtual bool ReserveSpace(int bytes); 2293 2294 #ifdef ENABLE_HEAP_PROTECTION 2295 // Protect/unprotect the space by marking it read-only/writable. 2296 void Protect(); 2297 void Unprotect(); 2298 #endif 2299 2300 #ifdef DEBUG 2301 virtual void Verify(); 2302 virtual void Print(); 2303 void ReportStatistics(); 2304 void CollectCodeStatistics(); 2305 #endif 2306 // Checks whether an address is in the object area in this space. It 2307 // iterates all objects in the space. May be slow. SlowContains(Address addr)2308 bool SlowContains(Address addr) { return !FindObject(addr)->IsFailure(); } 2309 2310 private: 2311 // The head of the linked list of large object chunks. 2312 LargeObjectChunk* first_chunk_; 2313 intptr_t size_; // allocated bytes 2314 int page_count_; // number of chunks 2315 intptr_t objects_size_; // size of objects 2316 2317 // Shared implementation of AllocateRaw, AllocateRawCode and 2318 // AllocateRawFixedArray. 2319 MUST_USE_RESULT MaybeObject* AllocateRawInternal(int requested_size, 2320 int object_size, 2321 Executability executable); 2322 2323 friend class LargeObjectIterator; 2324 2325 public: 2326 TRACK_MEMORY("LargeObjectSpace") 2327 }; 2328 2329 2330 class LargeObjectIterator: public ObjectIterator { 2331 public: 2332 explicit LargeObjectIterator(LargeObjectSpace* space); 2333 LargeObjectIterator(LargeObjectSpace* space, HeapObjectCallback size_func); 2334 2335 HeapObject* next(); 2336 2337 // implementation of ObjectIterator. next_object()2338 virtual HeapObject* next_object() { return next(); } 2339 2340 private: 2341 LargeObjectChunk* current_; 2342 HeapObjectCallback size_func_; 2343 }; 2344 2345 2346 #ifdef DEBUG 2347 struct CommentStatistic { 2348 const char* comment; 2349 int size; 2350 int count; ClearCommentStatistic2351 void Clear() { 2352 comment = NULL; 2353 size = 0; 2354 count = 0; 2355 } 2356 // Must be small, since an iteration is used for lookup. 2357 static const int kMaxComments = 64; 2358 }; 2359 #endif 2360 2361 2362 } } // namespace v8::internal 2363 2364 #endif // V8_SPACES_H_ 2365