Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(632)

Side by Side Diff: src/spaces.h

Issue 5987005: Refactor MemoryAllocator to allow big normal pages (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/gc
Patch Set: remove rogue printf Created 10 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/platform-linux.cc ('k') | src/spaces.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2006-2010 the V8 project authors. All rights reserved. 1 // Copyright 2006-2010 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
104 ASSERT((Page::kObjectStartOffset <= offset) \ 104 ASSERT((Page::kObjectStartOffset <= offset) \
105 && (offset <= Page::kPageSize)) 105 && (offset <= Page::kPageSize))
106 106
107 #define ASSERT_MAP_PAGE_INDEX(index) \ 107 #define ASSERT_MAP_PAGE_INDEX(index) \
108 ASSERT((0 <= index) && (index <= MapSpace::kMaxMapPageIndex)) 108 ASSERT((0 <= index) && (index <= MapSpace::kMaxMapPageIndex))
109 109
110 110
111 class PagedSpace; 111 class PagedSpace;
112 class MemoryAllocator; 112 class MemoryAllocator;
113 class AllocationInfo; 113 class AllocationInfo;
114 class Space;
115
116 // MemoryChunk represents a memory region owned by a specific space.
117 // It is divided into the header and the body. Chunk start is always
118 // 1MB aligned. Start of the body is aligned so it can accomodate
119 // any heap object.
120 class MemoryChunk {
121 public:
122 static MemoryChunk* FromAddress(Address a) {
123 return reinterpret_cast<MemoryChunk*>(OffsetFrom(a) & ~kAlignmentMask);
124 }
125
126 Address address() { return reinterpret_cast<Address>(this); }
127
128 bool is_valid() { return address() != NULL; }
129
130 MemoryChunk* next_chunk() const { return next_chunk_; }
131
132 void set_next_chunk(MemoryChunk* next) { next_chunk_ = next; }
133
134 Space* owner() const { return owner_; }
135
136 Address body() { return address() + kBodyOffset; }
137
138 int body_size() { return size() - kBodyOffset; }
139
140 enum MemoryChunkFlags {
141 IS_EXECUTABLE,
142 NUM_MEMORY_CHUNK_FLAGS
143 };
144
145 void SetFlag(MemoryChunkFlags flag) {
146 flags_ |= 1 << flag;
147 }
148
149 void ClearFlag(MemoryChunkFlags flag) {
150 flags_ &= ~(1 << flag);
151 }
152
153 bool IsFlagSet(MemoryChunkFlags flag) {
154 return (flags_ & (1 << flag)) != 0;
155 }
156
157 static const intptr_t kAlignment = (1 << kPageSizeBits);
158
159 static const intptr_t kAlignmentMask = kAlignment - 1;
160
161 static const size_t kHeaderSize = kPointerSize + kPointerSize + kPointerSize +
162 kPointerSize + kPointerSize;
163
164 static const int kBodyOffset =
165 CODE_POINTER_ALIGN(MAP_POINTER_ALIGN(kHeaderSize));
166
167 size_t size() const { return size_; }
168
169 Executability executable() {
170 return IsFlagSet(IS_EXECUTABLE) ? EXECUTABLE : NOT_EXECUTABLE;
171 }
172
173 protected:
174 MemoryChunk* next_chunk_;
175 size_t size_;
176 intptr_t flags_;
177 Space* owner_;
178
179 private:
180 static MemoryChunk* Initialize(Address base,
181 size_t size,
182 Executability executable,
183 Space* owner) {
184 MemoryChunk* chunk = FromAddress(base);
185
186 ASSERT(base == chunk->address());
187
188 chunk->next_chunk_ = NULL;
189 chunk->size_ = size;
190 chunk->flags_ = 0;
191 chunk->owner_ = owner;
192
193 if (executable == EXECUTABLE) chunk->SetFlag(IS_EXECUTABLE);
194
195 return chunk;
196 }
197
198 friend class MemoryAllocator;
199 };
200
201 STATIC_CHECK(sizeof(MemoryChunk) <= MemoryChunk::kHeaderSize);
114 202
115 // ----------------------------------------------------------------------------- 203 // -----------------------------------------------------------------------------
116 // A page normally has 8K bytes. Large object pages may be larger. A page 204 // A page is a memory chunk of a size 1MB. Large object pages may be larger.
117 // address is always aligned to the 8K page size.
118 //
119 // Each page starts with a header of Page::kPageHeaderSize size which contains
120 // bookkeeping data.
121 //
122 // The mark-compact collector transforms a map pointer into a page index and a
123 // page offset. The exact encoding is described in the comments for
124 // class MapWord in objects.h.
125 // 205 //
126 // The only way to get a page pointer is by calling factory methods: 206 // The only way to get a page pointer is by calling factory methods:
127 // Page* p = Page::FromAddress(addr); or 207 // Page* p = Page::FromAddress(addr); or
128 // Page* p = Page::FromAllocationTop(top); 208 // Page* p = Page::FromAllocationTop(top);
129 class Page { 209 class Page : public MemoryChunk {
130 public: 210 public:
131 // Returns the page containing a given address. The address ranges 211 // Returns the page containing a given address. The address ranges
132 // from [page_addr .. page_addr + kPageSize[ 212 // from [page_addr .. page_addr + kPageSize[
133 // 213 //
134 // Note that this function only works for addresses in normal paged 214 // Note that this function only works for addresses in normal paged
135 // spaces and addresses in the first 8K of large object pages (i.e., 215 // spaces and addresses in the first 8K of large object pages (i.e.,
136 // the start of large objects but not necessarily derived pointers 216 // the start of large objects but not necessarily derived pointers
137 // within them). 217 // within them).
138 INLINE(static Page* FromAddress(Address a)) { 218 INLINE(static Page* FromAddress(Address a)) {
139 return reinterpret_cast<Page*>(OffsetFrom(a) & ~kPageAlignmentMask); 219 return reinterpret_cast<Page*>(OffsetFrom(a) & ~kPageAlignmentMask);
140 } 220 }
141 221
142 // Returns the page containing an allocation top. Because an allocation 222 // Returns the page containing an allocation top. Because an allocation
143 // top address can be the upper bound of the page, we need to subtract 223 // top address can be the upper bound of the page, we need to subtract
144 // it with kPointerSize first. The address ranges from 224 // it with kPointerSize first. The address ranges from
145 // [page_addr + kObjectStartOffset .. page_addr + kPageSize]. 225 // [page_addr + kObjectStartOffset .. page_addr + kPageSize].
146 INLINE(static Page* FromAllocationTop(Address top)) { 226 INLINE(static Page* FromAllocationTop(Address top)) {
147 Page* p = FromAddress(top - kPointerSize); 227 Page* p = FromAddress(top - kPointerSize);
148 ASSERT_PAGE_OFFSET(p->Offset(top)); 228 ASSERT_PAGE_OFFSET(p->Offset(top));
149 return p; 229 return p;
150 } 230 }
151 231
152 // Returns the start address of this page. 232 // Returns the next page in the chain of pages owned by a space.
153 Address address() { return reinterpret_cast<Address>(this); } 233 inline Page* next_page() {
234 ASSERT(!next_chunk()->is_valid() || next_chunk()->owner() == owner());
235 return static_cast<Page*>(next_chunk());
236 }
154 237
155 // Checks whether this is a valid page address. 238 inline void set_next_page(Page* page) {
156 bool is_valid() { return address() != NULL; } 239 ASSERT(!page->is_valid() || page->owner() == owner());
157 240 set_next_chunk(page);
158 // Returns the next page of this page. 241 }
159 inline Page* next_page();
160 242
161 // Return the end of allocation in this page. Undefined for unused pages. 243 // Return the end of allocation in this page. Undefined for unused pages.
162 inline Address AllocationTop(); 244 inline Address AllocationTop();
163 245
164 // Return the allocation watermark for the page. 246 // Return the allocation watermark for the page.
165 // For old space pages it is guaranteed that the area under the watermark 247 // For old space pages it is guaranteed that the area under the watermark
166 // does not contain any garbage pointers to new space. 248 // does not contain any garbage pointers to new space.
167 inline Address AllocationWatermark(); 249 inline Address AllocationWatermark();
168 250
169 // Return the allocation watermark offset from the beginning of the page. 251 // Return the allocation watermark offset from the beginning of the page.
170 inline uint32_t AllocationWatermarkOffset(); 252 inline uint32_t AllocationWatermarkOffset();
171 253
172 inline void SetAllocationWatermark(Address allocation_watermark); 254 inline void SetAllocationWatermark(Address allocation_watermark);
173 255
174 inline void SetCachedAllocationWatermark(Address allocation_watermark); 256 inline void SetCachedAllocationWatermark(Address allocation_watermark);
175 inline Address CachedAllocationWatermark(); 257 inline Address CachedAllocationWatermark();
176 258
177 // Returns the start address of the object area in this page. 259 // Returns the start address of the object area in this page.
178 Address ObjectAreaStart() { return address() + kObjectStartOffset; } 260 Address ObjectAreaStart() { return address() + kObjectStartOffset; }
179 261
180 // Returns the end address (exclusive) of the object area in this page. 262 // Returns the end address (exclusive) of the object area in this page.
181 Address ObjectAreaEnd() { return address() + Page::kPageSize; } 263 Address ObjectAreaEnd() { return address() + Page::kPageSize; }
182 264
183 // Checks whether an address is page aligned. 265 // Checks whether an address is page aligned.
184 static bool IsAlignedToPageSize(Address a) { 266 static bool IsAlignedToPageSize(Address a) {
185 return 0 == (OffsetFrom(a) & kPageAlignmentMask); 267 return 0 == (OffsetFrom(a) & kPageAlignmentMask);
186 } 268 }
187 269
188 // True if this page was in use before current compaction started.
189 // Result is valid only for pages owned by paged spaces and
190 // only after PagedSpace::PrepareForMarkCompact was called.
191 inline bool WasInUseBeforeMC();
192
193 inline void SetWasInUseBeforeMC(bool was_in_use);
194
195 // True if this page is a large object page.
196 inline bool IsLargeObjectPage();
197
198 inline void SetIsLargeObjectPage(bool is_large_object_page);
199
200 inline bool IsPageExecutable();
201
202 inline void SetIsPageExecutable(bool is_page_executable);
203
204 // Returns the offset of a given address to this page. 270 // Returns the offset of a given address to this page.
205 INLINE(int Offset(Address a)) { 271 INLINE(int Offset(Address a)) {
206 int offset = static_cast<int>(a - address()); 272 int offset = static_cast<int>(a - address());
207 ASSERT_PAGE_OFFSET(offset); 273 ASSERT_PAGE_OFFSET(offset);
208 return offset; 274 return offset;
209 } 275 }
210 276
211 // Returns the address for a given offset to the this page. 277 // Returns the address for a given offset to the this page.
212 Address OffsetToAddress(int offset) { 278 Address OffsetToAddress(int offset) {
213 ASSERT_PAGE_OFFSET(offset); 279 ASSERT_PAGE_OFFSET(offset);
(...skipping 19 matching lines...) Expand all
233 inline void ClearRegionMarks(Address start, 299 inline void ClearRegionMarks(Address start,
234 Address end, 300 Address end,
235 bool reaches_limit); 301 bool reaches_limit);
236 302
237 // Page size in bytes. This must be a multiple of the OS page size. 303 // Page size in bytes. This must be a multiple of the OS page size.
238 static const int kPageSize = 1 << kPageSizeBits; 304 static const int kPageSize = 1 << kPageSizeBits;
239 305
240 // Page size mask. 306 // Page size mask.
241 static const intptr_t kPageAlignmentMask = (1 << kPageSizeBits) - 1; 307 static const intptr_t kPageAlignmentMask = (1 << kPageSizeBits) - 1;
242 308
243 static const int kPageHeaderSize = kPointerSize + kPointerSize + kIntSize +
244 kIntSize + kPointerSize;
245
246 // The start offset of the object area in a page. Aligned to both maps and 309 // The start offset of the object area in a page. Aligned to both maps and
247 // code alignment to be suitable for both. 310 // code alignment to be suitable for both.
248 static const int kObjectStartOffset = 311 static const int kObjectStartOffset = kBodyOffset;
249 CODE_POINTER_ALIGN(MAP_POINTER_ALIGN(kPageHeaderSize));
250 312
251 // Object area size in bytes. 313 // Object area size in bytes.
252 static const int kObjectAreaSize = kPageSize - kObjectStartOffset; 314 static const int kObjectAreaSize = kPageSize - kObjectStartOffset;
253 315
254 // Maximum object size that fits in a page. 316 // Maximum object size that fits in a page.
255 static const int kMaxHeapObjectSize = kObjectAreaSize; 317 static const int kMaxHeapObjectSize = kObjectAreaSize;
256 318
319 #ifdef ENABLE_CARDMARKING_WRITE_BARRIER
257 static const int kDirtyFlagOffset = 2 * kPointerSize; 320 static const int kDirtyFlagOffset = 2 * kPointerSize;
258 static const int kRegionSizeLog2 = 8; 321 static const int kRegionSizeLog2 = 8;
259 static const int kRegionSize = 1 << kRegionSizeLog2; 322 static const int kRegionSize = 1 << kRegionSizeLog2;
260 static const intptr_t kRegionAlignmentMask = (kRegionSize - 1); 323 static const intptr_t kRegionAlignmentMask = (kRegionSize - 1);
261 324
262 STATIC_CHECK(kRegionSize == kPageSize / kBitsPerInt); 325 STATIC_CHECK(kRegionSize == kPageSize / kBitsPerInt);
326 #endif
263 327
264 enum PageFlag { 328 enum PageFlag {
265 IS_NORMAL_PAGE = 0,
266 WAS_IN_USE_BEFORE_MC,
267
268 // Page allocation watermark was bumped by preallocation during scavenge. 329 // Page allocation watermark was bumped by preallocation during scavenge.
269 // Correct watermark can be retrieved by CachedAllocationWatermark() method 330 // Correct watermark can be retrieved by CachedAllocationWatermark() method
270 WATERMARK_INVALIDATED, 331 WATERMARK_INVALIDATED = NUM_MEMORY_CHUNK_FLAGS,
271 IS_EXECUTABLE,
272 NUM_PAGE_FLAGS // Must be last 332 NUM_PAGE_FLAGS // Must be last
273 }; 333 };
334
274 static const int kPageFlagMask = (1 << NUM_PAGE_FLAGS) - 1; 335 static const int kPageFlagMask = (1 << NUM_PAGE_FLAGS) - 1;
275 336
276 // To avoid an additional WATERMARK_INVALIDATED flag clearing pass during 337 // To avoid an additional WATERMARK_INVALIDATED flag clearing pass during
277 // scavenge we just invalidate the watermark on each old space page after 338 // scavenge we just invalidate the watermark on each old space page after
278 // processing it. And then we flip the meaning of the WATERMARK_INVALIDATED 339 // processing it. And then we flip the meaning of the WATERMARK_INVALIDATED
279 // flag at the beginning of the next scavenge and each page becomes marked as 340 // flag at the beginning of the next scavenge and each page becomes marked as
280 // having a valid watermark. 341 // having a valid watermark.
281 // 342 //
282 // The following invariant must hold for pages in old pointer and map spaces: 343 // The following invariant must hold for pages in old pointer and map spaces:
283 // If page is in use then page is marked as having invalid watermark at 344 // If page is in use then page is marked as having invalid watermark at
284 // the beginning and at the end of any GC. 345 // the beginning and at the end of any GC.
285 // 346 //
286 // This invariant guarantees that after flipping flag meaning at the 347 // This invariant guarantees that after flipping flag meaning at the
287 // beginning of scavenge all pages in use will be marked as having valid 348 // beginning of scavenge all pages in use will be marked as having valid
288 // watermark. 349 // watermark.
289 static inline void FlipMeaningOfInvalidatedWatermarkFlag(); 350 static inline void FlipMeaningOfInvalidatedWatermarkFlag();
290 351
291 // Returns true if the page allocation watermark was not altered during 352 // Returns true if the page allocation watermark was not altered during
292 // scavenge. 353 // scavenge.
293 inline bool IsWatermarkValid(); 354 inline bool IsWatermarkValid();
294 355
295 inline void InvalidateWatermark(bool value); 356 inline void InvalidateWatermark(bool value);
296 357
297 inline bool GetPageFlag(PageFlag flag);
298 inline void SetPageFlag(PageFlag flag, bool value);
299 inline void ClearPageFlags();
300
301 inline void ClearGCFields(); 358 inline void ClearGCFields();
302 359
303 static const int kAllocationWatermarkOffsetShift = WATERMARK_INVALIDATED + 1; 360 static const int kAllocationWatermarkOffsetShift = WATERMARK_INVALIDATED + 1;
304 static const int kAllocationWatermarkOffsetBits = kPageSizeBits + 1; 361 static const int kAllocationWatermarkOffsetBits = kPageSizeBits + 1;
305 static const uint32_t kAllocationWatermarkOffsetMask = 362 static const uint32_t kAllocationWatermarkOffsetMask =
306 ((1 << kAllocationWatermarkOffsetBits) - 1) << 363 ((1 << kAllocationWatermarkOffsetBits) - 1) <<
307 kAllocationWatermarkOffsetShift; 364 kAllocationWatermarkOffsetShift;
308 365
309 static const uint32_t kFlagsMask = 366 static const uint32_t kFlagsMask =
310 ((1 << kAllocationWatermarkOffsetShift) - 1); 367 ((1 << kAllocationWatermarkOffsetShift) - 1);
311 368
312 STATIC_CHECK(kBitsPerInt - kAllocationWatermarkOffsetShift >= 369 STATIC_CHECK(kBitsPerInt - kAllocationWatermarkOffsetShift >=
313 kAllocationWatermarkOffsetBits); 370 kAllocationWatermarkOffsetBits);
314 371
315 // This field contains the meaning of the WATERMARK_INVALIDATED flag. 372 // This field contains the meaning of the WATERMARK_INVALIDATED flag.
316 // Instead of clearing this flag from all pages we just flip 373 // Instead of clearing this flag from all pages we just flip
317 // its meaning at the beginning of a scavenge. 374 // its meaning at the beginning of a scavenge.
318 static intptr_t watermark_invalidated_mark_; 375 static intptr_t watermark_invalidated_mark_;
319 376
320 //--------------------------------------------------------------------------- 377 private:
321 // Page header description. 378 static Page* Initialize(MemoryChunk* chunk) {
322 // 379 Page* page = static_cast<Page*>(chunk);
323 // If a page is not in the large object space, the first word, 380 page->allocation_watermark_ = page->body();
324 // opaque_header, encodes the next page address (aligned to kPageSize 8K) 381 page->InvalidateWatermark(true);
325 // and the chunk number (0 ~ 8K-1). Only MemoryAllocator should use 382 return page;
326 // opaque_header. The value range of the opaque_header is [0..kPageSize[, 383 }
327 // or [next_page_start, next_page_end[. It cannot point to a valid address
328 // in the current page. If a page is in the large object space, the first
329 // word *may* (if the page start and large object chunk start are the
330 // same) contain the address of the next large object chunk.
331 intptr_t opaque_header;
332 384
333 // If the page is not in the large object space, the low-order bit of the 385 Address allocation_watermark_;
334 // second word is set. If the page is in the large object space, the
335 // second word *may* (if the page start and large object chunk start are
336 // the same) contain the large object chunk size. In either case, the
337 // low-order bit for large object pages will be cleared.
338 // For normal pages this word is used to store page flags and
339 // offset of allocation top.
340 intptr_t flags_;
341 386
342 // This field contains dirty marks for regions covering the page. Only dirty 387 friend class MemoryAllocator;
343 // regions might contain intergenerational references.
344 // Only 32 dirty marks are supported so for large object pages several regions
345 // might be mapped to a single dirty mark.
346 uint32_t dirty_regions_;
347
348 // The index of the page in its owner space.
349 int mc_page_index;
350
351 // During mark-compact collections this field contains the forwarding address
352 // of the first live object in this page.
353 // During scavenge collection this field is used to store allocation watermark
354 // if it is altered during scavenge.
355 Address mc_first_forwarded;
356 }; 388 };
357 389
390 STATIC_CHECK(sizeof(Page) <= MemoryChunk::kHeaderSize);
391
392 class LargePage : public MemoryChunk {
393 public:
394 HeapObject* GetObject() {
395 return HeapObject::FromAddress(body());
396 }
397
398 inline LargePage* next_page() const {
399 return static_cast<LargePage*>(next_chunk());
400 }
401
402 inline void set_next_page(LargePage* page) {
403 set_next_chunk(page);
404 }
405 private:
406 static LargePage* Initialize(MemoryChunk* chunk) {
407 return static_cast<LargePage*>(chunk);
408 }
409
410 friend class MemoryAllocator;
411 };
412
413 STATIC_CHECK(sizeof(LargePage) <= MemoryChunk::kHeaderSize);
358 414
359 // ---------------------------------------------------------------------------- 415 // ----------------------------------------------------------------------------
360 // Space is the abstract superclass for all allocation spaces. 416 // Space is the abstract superclass for all allocation spaces.
361 class Space : public Malloced { 417 class Space : public Malloced {
362 public: 418 public:
363 Space(AllocationSpace id, Executability executable) 419 Space(AllocationSpace id, Executability executable)
364 : id_(id), executable_(executable) {} 420 : id_(id), executable_(executable) {}
365 421
366 virtual ~Space() {} 422 virtual ~Space() {}
367 423
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
423 static bool exists() { return code_range_ != NULL; } 479 static bool exists() { return code_range_ != NULL; }
424 static bool contains(Address address) { 480 static bool contains(Address address) {
425 if (code_range_ == NULL) return false; 481 if (code_range_ == NULL) return false;
426 Address start = static_cast<Address>(code_range_->address()); 482 Address start = static_cast<Address>(code_range_->address());
427 return start <= address && address < start + code_range_->size(); 483 return start <= address && address < start + code_range_->size();
428 } 484 }
429 485
430 // Allocates a chunk of memory from the large-object portion of 486 // Allocates a chunk of memory from the large-object portion of
431 // the code range. On platforms with no separate code range, should 487 // the code range. On platforms with no separate code range, should
432 // not be called. 488 // not be called.
433 MUST_USE_RESULT static void* AllocateRawMemory(const size_t requested, 489 MUST_USE_RESULT static Address AllocateRawMemory(const size_t requested,
434 size_t* allocated); 490 size_t* allocated);
435 static void FreeRawMemory(void* buf, size_t length); 491 static void FreeRawMemory(Address buf, size_t length);
436 492
437 private: 493 private:
438 // The reserved range of virtual memory that all code objects are put in. 494 // The reserved range of virtual memory that all code objects are put in.
439 static VirtualMemory* code_range_; 495 static VirtualMemory* code_range_;
440 // Plain old data class, just a struct plus a constructor. 496 // Plain old data class, just a struct plus a constructor.
441 class FreeBlock { 497 class FreeBlock {
442 public: 498 public:
443 FreeBlock(Address start_arg, size_t size_arg) 499 FreeBlock(Address start_arg, size_t size_arg)
444 : start(start_arg), size(size_arg) {} 500 : start(start_arg), size(size_arg) {
501 ASSERT(IsAddressAligned(start, MemoryChunk::kAlignment));
502 ASSERT(size >= static_cast<size_t>(Page::kPageSize));
503 }
445 FreeBlock(void* start_arg, size_t size_arg) 504 FreeBlock(void* start_arg, size_t size_arg)
446 : start(static_cast<Address>(start_arg)), size(size_arg) {} 505 : start(static_cast<Address>(start_arg)), size(size_arg) {
506 ASSERT(IsAddressAligned(start, MemoryChunk::kAlignment));
507 ASSERT(size >= static_cast<size_t>(Page::kPageSize));
508 }
447 509
448 Address start; 510 Address start;
449 size_t size; 511 size_t size;
450 }; 512 };
451 513
452 // Freed blocks of memory are added to the free list. When the allocation 514 // Freed blocks of memory are added to the free list. When the allocation
453 // list is exhausted, the free list is sorted and merged to make the new 515 // list is exhausted, the free list is sorted and merged to make the new
454 // allocation list. 516 // allocation list.
455 static List<FreeBlock> free_list_; 517 static List<FreeBlock> free_list_;
456 // Memory is allocated from the free blocks on the allocation list. 518 // Memory is allocated from the free blocks on the allocation list.
457 // The block at current_allocation_block_index_ is the current block. 519 // The block at current_allocation_block_index_ is the current block.
458 static List<FreeBlock> allocation_list_; 520 static List<FreeBlock> allocation_list_;
459 static int current_allocation_block_index_; 521 static int current_allocation_block_index_;
460 522
461 // Finds a block on the allocation list that contains at least the 523 // Finds a block on the allocation list that contains at least the
462 // requested amount of memory. If none is found, sorts and merges 524 // requested amount of memory. If none is found, sorts and merges
463 // the existing free memory blocks, and searches again. 525 // the existing free memory blocks, and searches again.
464 // If none can be found, terminates V8 with FatalProcessOutOfMemory. 526 // If none can be found, terminates V8 with FatalProcessOutOfMemory.
465 static void GetNextAllocationBlock(size_t requested); 527 static void GetNextAllocationBlock(size_t requested);
466 // Compares the start addresses of two free blocks. 528 // Compares the start addresses of two free blocks.
467 static int CompareFreeBlockAddress(const FreeBlock* left, 529 static int CompareFreeBlockAddress(const FreeBlock* left,
468 const FreeBlock* right); 530 const FreeBlock* right);
469 }; 531 };
470 532
471 533
472 // ---------------------------------------------------------------------------- 534 // ----------------------------------------------------------------------------
473 // A space acquires chunks of memory from the operating system. The memory 535 // A space acquires chunks of memory from the operating system. The memory
474 // allocator manages chunks for the paged heap spaces (old space and map 536 // allocator allocated and deallocates pages for the paged heap spaces and large
475 // space). A paged chunk consists of pages. Pages in a chunk have contiguous 537 // pages for large object space.
476 // addresses and are linked as a list.
477 // 538 //
478 // The allocator keeps an initial chunk which is used for the new space. The 539 // Each space has to manage it's own pages.
479 // leftover regions of the initial chunk are used for the initial chunks of
480 // old space and map space if they are big enough to hold at least one page.
481 // The allocator assumes that there is one old space and one map space, each
482 // expands the space by allocating kPagesPerChunk pages except the last
483 // expansion (before running out of space). The first chunk may contain fewer
484 // than kPagesPerChunk pages as well.
485 // 540 //
486 // The memory allocator also allocates chunks for the large object space, but
487 // they are managed by the space itself. The new space does not expand.
488 //
489 // The fact that pages for paged spaces are allocated and deallocated in chunks
490 // induces a constraint on the order of pages in a linked lists. We say that
491 // pages are linked in the chunk-order if and only if every two consecutive
492 // pages from the same chunk are consecutive in the linked list.
493 //
494
495
496 class MemoryAllocator : public AllStatic { 541 class MemoryAllocator : public AllStatic {
497 public: 542 public:
498 // Initializes its internal bookkeeping structures. 543 // Initializes its internal bookkeeping structures.
499 // Max capacity of the total space and executable memory limit. 544 // Max capacity of the total space and executable memory limit.
500 static bool Setup(intptr_t max_capacity, intptr_t capacity_executable); 545 static bool Setup(intptr_t max_capacity, intptr_t capacity_executable);
501 546
502 // Deletes valid chunks.
503 static void TearDown(); 547 static void TearDown();
504 548
505 // Reserves an initial address range of virtual memory to be split between 549 static Page* AllocatePage(PagedSpace* owner, Executability executable);
506 // the two new space semispaces, the old space, and the map space. The
507 // memory is not yet committed or assigned to spaces and split into pages.
508 // The initial chunk is unmapped when the memory allocator is torn down.
509 // This function should only be called when there is not already a reserved
510 // initial chunk (initial_chunk_ should be NULL). It returns the start
511 // address of the initial chunk if successful, with the side effect of
512 // setting the initial chunk, or else NULL if unsuccessful and leaves the
513 // initial chunk NULL.
514 static void* ReserveInitialChunk(const size_t requested);
515 550
516 // Commits pages from an as-yet-unmanaged block of virtual memory into a 551 static LargePage* AllocateLargePage(intptr_t object_size,
517 // paged space. The block should be part of the initial chunk reserved via 552 Executability executable,
518 // a call to ReserveInitialChunk. The number of pages is always returned in 553 Space* owner);
519 // the output parameter num_pages. This function assumes that the start
520 // address is non-null and that it is big enough to hold at least one
521 // page-aligned page. The call always succeeds, and num_pages is always
522 // greater than zero.
523 static Page* CommitPages(Address start, size_t size, PagedSpace* owner,
524 int* num_pages);
525 554
526 // Commit a contiguous block of memory from the initial chunk. Assumes that 555 static void Free(MemoryChunk* chunk);
527 // the address is not NULL, the size is greater than zero, and that the
528 // block is contained in the initial chunk. Returns true if it succeeded
529 // and false otherwise.
530 static bool CommitBlock(Address start, size_t size, Executability executable);
531
532 // Uncommit a contiguous block of memory [start..(start+size)[.
533 // start is not NULL, the size is greater than zero, and the
534 // block is contained in the initial chunk. Returns true if it succeeded
535 // and false otherwise.
536 static bool UncommitBlock(Address start, size_t size);
537
538 // Zaps a contiguous block of memory [start..(start+size)[ thus
539 // filling it up with a recognizable non-NULL bit pattern.
540 static void ZapBlock(Address start, size_t size);
541
542 // Attempts to allocate the requested (non-zero) number of pages from the
543 // OS. Fewer pages might be allocated than requested. If it fails to
544 // allocate memory for the OS or cannot allocate a single page, this
545 // function returns an invalid page pointer (NULL). The caller must check
546 // whether the returned page is valid (by calling Page::is_valid()). It is
547 // guaranteed that allocated pages have contiguous addresses. The actual
548 // number of allocated pages is returned in the output parameter
549 // allocated_pages. If the PagedSpace owner is executable and there is
550 // a code range, the pages are allocated from the code range.
551 static Page* AllocatePages(int requested_pages, int* allocated_pages,
552 PagedSpace* owner);
553
554 // Frees pages from a given page and after. Requires pages to be
555 // linked in chunk-order (see comment for class).
556 // If 'p' is the first page of a chunk, pages from 'p' are freed
557 // and this function returns an invalid page pointer.
558 // Otherwise, the function searches a page after 'p' that is
559 // the first page of a chunk. Pages after the found page
560 // are freed and the function returns 'p'.
561 static Page* FreePages(Page* p);
562
563 // Frees all pages owned by given space.
564 static void FreeAllPages(PagedSpace* space);
565
566 // Allocates and frees raw memory of certain size.
567 // These are just thin wrappers around OS::Allocate and OS::Free,
568 // but keep track of allocated bytes as part of heap.
569 // If the flag is EXECUTABLE and a code range exists, the requested
570 // memory is allocated from the code range. If a code range exists
571 // and the freed memory is in it, the code range manages the freed memory.
572 MUST_USE_RESULT static void* AllocateRawMemory(const size_t requested,
573 size_t* allocated,
574 Executability executable);
575 static void FreeRawMemory(void* buf,
576 size_t length,
577 Executability executable);
578 static void PerformAllocationCallback(ObjectSpace space,
579 AllocationAction action,
580 size_t size);
581
582 static void AddMemoryAllocationCallback(MemoryAllocationCallback callback,
583 ObjectSpace space,
584 AllocationAction action);
585 static void RemoveMemoryAllocationCallback(
586 MemoryAllocationCallback callback);
587 static bool MemoryAllocationCallbackRegistered(
588 MemoryAllocationCallback callback);
589 556
590 // Returns the maximum available bytes of heaps. 557 // Returns the maximum available bytes of heaps.
591 static intptr_t Available() { 558 static intptr_t Available() {
592 return capacity_ < size_ ? 0 : capacity_ - size_; 559 return capacity_ < size_ ? 0 : capacity_ - size_;
593 } 560 }
594 561
595 // Returns allocated spaces in bytes. 562 // Returns allocated spaces in bytes.
596 static intptr_t Size() { return size_; } 563 static intptr_t Size() { return size_; }
597 564
598 // Returns the maximum available executable bytes of heaps. 565 // Returns the maximum available executable bytes of heaps.
599 static intptr_t AvailableExecutable() { 566 static intptr_t AvailableExecutable() {
600 if (capacity_executable_ < size_executable_) return 0; 567 if (capacity_executable_ < size_executable_) return 0;
601 return capacity_executable_ - size_executable_; 568 return capacity_executable_ - size_executable_;
602 } 569 }
603 570
604 // Returns allocated executable spaces in bytes. 571 // Returns allocated executable spaces in bytes.
605 static intptr_t SizeExecutable() { return size_executable_; } 572 static intptr_t SizeExecutable() { return size_executable_; }
606 573
607 // Returns maximum available bytes that the old space can have. 574 // Returns maximum available bytes that the old space can have.
608 static intptr_t MaxAvailable() { 575 static intptr_t MaxAvailable() {
609 return (Available() / Page::kPageSize) * Page::kObjectAreaSize; 576 return (Available() / Page::kPageSize) * Page::kObjectAreaSize;
610 } 577 }
611 578
612 // Sanity check on a pointer.
613 static bool SafeIsInAPageChunk(Address addr);
614
615 // Links two pages.
616 static inline void SetNextPage(Page* prev, Page* next);
617
618 // Returns the next page of a given page.
619 static inline Page* GetNextPage(Page* p);
620
621 // Checks whether a page belongs to a space.
622 static inline bool IsPageInSpace(Page* p, PagedSpace* space);
623
624 // Returns the space that owns the given page.
625 static inline PagedSpace* PageOwner(Page* page);
626
627 // Finds the first/last page in the same chunk as a given page.
628 static Page* FindFirstPageInSameChunk(Page* p);
629 static Page* FindLastPageInSameChunk(Page* p);
630
631 // Relinks list of pages owned by space to make it chunk-ordered.
632 // Returns new first and last pages of space.
633 // Also returns last page in relinked list which has WasInUsedBeforeMC
634 // flag set.
635 static void RelinkPageListInChunkOrder(PagedSpace* space,
636 Page** first_page,
637 Page** last_page,
638 Page** last_page_in_use);
639
640 #ifdef ENABLE_HEAP_PROTECTION 579 #ifdef ENABLE_HEAP_PROTECTION
641 // Protect/unprotect a block of memory by marking it read-only/writable. 580 // Protect/unprotect a block of memory by marking it read-only/writable.
642 static inline void Protect(Address start, size_t size); 581 static inline void Protect(Address start, size_t size);
643 static inline void Unprotect(Address start, size_t size, 582 static inline void Unprotect(Address start, size_t size,
644 Executability executable); 583 Executability executable);
645 584
646 // Protect/unprotect a chunk given a page in the chunk. 585 // Protect/unprotect a chunk given a page in the chunk.
647 static inline void ProtectChunkFromPage(Page* page); 586 static inline void ProtectChunkFromPage(Page* page);
648 static inline void UnprotectChunkFromPage(Page* page); 587 static inline void UnprotectChunkFromPage(Page* page);
649 #endif 588 #endif
650 589
651 #ifdef DEBUG 590 #ifdef DEBUG
652 // Reports statistic info of the space. 591 // Reports statistic info of the space.
653 static void ReportStatistics(); 592 static void ReportStatistics();
654 #endif 593 #endif
655 594
656 static void AddToAllocatedChunks(Address addr, intptr_t size); 595 static MemoryChunk* AllocateChunk(intptr_t body_size,
657 static void RemoveFromAllocatedChunks(Address addr, intptr_t size); 596 Executability executable,
658 // Note: This only checks the regular chunks, not the odd-sized initial 597 Space* space);
659 // chunk.
660 static bool InAllocatedChunks(Address addr);
661 598
662 // Due to encoding limitation, we can only have 8K chunks. 599 static Address AllocateAlignedMemory(const size_t requested,
663 static const int kMaxNofChunks = 1 << kPageSizeBits; 600 size_t alignment,
664 // If a chunk has at least 16 pages, the maximum heap size is about 601 Executability executable,
665 // 8K * 8K * 16 = 1G bytes. 602 size_t* allocated_size);
666 #ifdef V8_TARGET_ARCH_X64 603
667 static const int kPagesPerChunk = 32; 604 static Address ReserveAlignedMemory(const size_t requested,
668 // On 64 bit the chunk table consists of 4 levels of 4096-entry tables. 605 size_t alignment,
669 static const int kPagesPerChunkLog2 = 5; 606 size_t* allocated_size);
670 static const int kChunkTableLevels = 4; 607
671 static const int kChunkTableBitsPerLevel = 12; 608 static void FreeMemory(Address addr, size_t size, Executability executable);
672 #else 609
673 static const int kPagesPerChunk = 16; 610 // Commit a contiguous block of memory from the initial chunk. Assumes that
674 // On 32 bit the chunk table consists of 2 levels of 256-entry tables. 611 // the address is not NULL, the size is greater than zero, and that the
675 static const int kPagesPerChunkLog2 = 4; 612 // block is contained in the initial chunk. Returns true if it succeeded
676 static const int kChunkTableLevels = 2; 613 // and false otherwise.
677 static const int kChunkTableBitsPerLevel = 8; 614 static bool CommitBlock(Address start, size_t size, Executability executable);
678 #endif 615
616 // Uncommit a contiguous block of memory [start..(start+size)[.
617 // start is not NULL, the size is greater than zero, and the
618 // block is contained in the initial chunk. Returns true if it succeeded
619 // and false otherwise.
620 static bool UncommitBlock(Address start, size_t size);
621
622 // Zaps a contiguous block of memory [start..(start+size)[ thus
623 // filling it up with a recognizable non-NULL bit pattern.
624 static void ZapBlock(Address start, size_t size);
625
626 static void PerformAllocationCallback(ObjectSpace space,
627 AllocationAction action,
628 size_t size);
629
630 static void AddMemoryAllocationCallback(MemoryAllocationCallback callback,
631 ObjectSpace space,
632 AllocationAction action);
633
634 static void RemoveMemoryAllocationCallback(
635 MemoryAllocationCallback callback);
636
637 static bool MemoryAllocationCallbackRegistered(
638 MemoryAllocationCallback callback);
639
640
679 641
680 private: 642 private:
681 static const int kChunkSize = kPagesPerChunk * Page::kPageSize;
682 static const int kChunkSizeLog2 = kPagesPerChunkLog2 + kPageSizeBits;
683 static const int kChunkTableTopLevelEntries =
684 1 << (sizeof(intptr_t) * kBitsPerByte - kChunkSizeLog2 -
685 (kChunkTableLevels - 1) * kChunkTableBitsPerLevel);
686
687 // The chunks are not chunk-size aligned so for a given chunk-sized area of
688 // memory there can be two chunks that cover it.
689 static const int kChunkTableFineGrainedWordsPerEntry = 2;
690 static const uintptr_t kUnusedChunkTableEntry = 0;
691
692 // Maximum space size in bytes. 643 // Maximum space size in bytes.
693 static intptr_t capacity_; 644 static size_t capacity_;
694 // Maximum subset of capacity_ that can be executable 645 // Maximum subset of capacity_ that can be executable
695 static intptr_t capacity_executable_; 646 static size_t capacity_executable_;
696
697 // Top level table to track whether memory is part of a chunk or not.
698 static uintptr_t chunk_table_[kChunkTableTopLevelEntries];
699 647
700 // Allocated space size in bytes. 648 // Allocated space size in bytes.
701 static intptr_t size_; 649 static size_t size_;
702 // Allocated executable space size in bytes. 650 // Allocated executable space size in bytes.
703 static intptr_t size_executable_; 651 static size_t size_executable_;
704 652
705 struct MemoryAllocationCallbackRegistration { 653 struct MemoryAllocationCallbackRegistration {
706 MemoryAllocationCallbackRegistration(MemoryAllocationCallback callback, 654 MemoryAllocationCallbackRegistration(MemoryAllocationCallback callback,
707 ObjectSpace space, 655 ObjectSpace space,
708 AllocationAction action) 656 AllocationAction action)
709 : callback(callback), space(space), action(action) { 657 : callback(callback), space(space), action(action) {
710 } 658 }
711 MemoryAllocationCallback callback; 659 MemoryAllocationCallback callback;
712 ObjectSpace space; 660 ObjectSpace space;
713 AllocationAction action; 661 AllocationAction action;
714 }; 662 };
715 // A List of callback that are triggered when memory is allocated or free'd 663 // A List of callback that are triggered when memory is allocated or free'd
716 static List<MemoryAllocationCallbackRegistration> 664 static List<MemoryAllocationCallbackRegistration>
717 memory_allocation_callbacks_; 665 memory_allocation_callbacks_;
718 666
719 // The initial chunk of virtual memory.
720 static VirtualMemory* initial_chunk_;
721
722 // Allocated chunk info: chunk start address, chunk size, and owning space.
723 class ChunkInfo BASE_EMBEDDED {
724 public:
725 ChunkInfo() : address_(NULL),
726 size_(0),
727 owner_(NULL),
728 executable_(NOT_EXECUTABLE) {}
729 inline void init(Address a, size_t s, PagedSpace* o);
730 Address address() { return address_; }
731 size_t size() { return size_; }
732 PagedSpace* owner() { return owner_; }
733 // We save executability of the owner to allow using it
734 // when collecting stats after the owner has been destroyed.
735 Executability executable() const { return executable_; }
736
737 private:
738 Address address_;
739 size_t size_;
740 PagedSpace* owner_;
741 Executability executable_;
742 };
743
744 // Chunks_, free_chunk_ids_ and top_ act as a stack of free chunk ids.
745 static List<ChunkInfo> chunks_;
746 static List<int> free_chunk_ids_;
747 static int max_nof_chunks_;
748 static int top_;
749
750 // Push/pop a free chunk id onto/from the stack.
751 static void Push(int free_chunk_id);
752 static int Pop();
753 static bool OutOfChunkIds() { return top_ == 0; }
754
755 // Frees a chunk.
756 static void DeleteChunk(int chunk_id);
757
758 // Helpers to maintain and query the chunk tables.
759 static void AddChunkUsingAddress(
760 uintptr_t chunk_start, // Where the chunk starts.
761 uintptr_t chunk_index_base); // Used to place the chunk in the tables.
762 static void RemoveChunkFoundUsingAddress(
763 uintptr_t chunk_start, // Where the chunk starts.
764 uintptr_t chunk_index_base); // Used to locate the entry in the tables.
765 // Controls whether the lookup creates intermediate levels of tables as
766 // needed.
767 enum CreateTables { kDontCreateTables, kCreateTablesAsNeeded };
768 static uintptr_t* AllocatedChunksFinder(uintptr_t* table,
769 uintptr_t address,
770 int bit_position,
771 CreateTables create_as_needed);
772 static void FreeChunkTables(uintptr_t* array, int length, int level);
773 static int FineGrainedIndexForAddress(uintptr_t address) {
774 int index = ((address >> kChunkSizeLog2) &
775 ((1 << kChunkTableBitsPerLevel) - 1));
776 return index * kChunkTableFineGrainedWordsPerEntry;
777 }
778
779
780 // Basic check whether a chunk id is in the valid range.
781 static inline bool IsValidChunkId(int chunk_id);
782
783 // Checks whether a chunk id identifies an allocated chunk.
784 static inline bool IsValidChunk(int chunk_id);
785
786 // Returns the chunk id that a page belongs to.
787 static inline int GetChunkId(Page* p);
788
789 // True if the address lies in the initial chunk.
790 static inline bool InInitialChunk(Address address);
791
792 // Initializes pages in a chunk. Returns the first page address. 667 // Initializes pages in a chunk. Returns the first page address.
793 // This function and GetChunkId() are provided for the mark-compact 668 // This function and GetChunkId() are provided for the mark-compact
794 // collector to rebuild page headers in the from space, which is 669 // collector to rebuild page headers in the from space, which is
795 // used as a marking stack and its page headers are destroyed. 670 // used as a marking stack and its page headers are destroyed.
796 static Page* InitializePagesInChunk(int chunk_id, int pages_in_chunk, 671 static Page* InitializePagesInChunk(int chunk_id, int pages_in_chunk,
797 PagedSpace* owner); 672 PagedSpace* owner);
798
799 static Page* RelinkPagesInChunk(int chunk_id,
800 Address chunk_start,
801 size_t chunk_size,
802 Page* prev,
803 Page** last_page_in_use);
804 }; 673 };
805 674
806 675
807 // ----------------------------------------------------------------------------- 676 // -----------------------------------------------------------------------------
808 // Interface for heap object iterator to be implemented by all object space 677 // Interface for heap object iterator to be implemented by all object space
809 // object iterators. 678 // object iterators.
810 // 679 //
811 // NOTE: The space specific object iterators also implements the own next() 680 // NOTE: The space specific object iterators also implements the own next()
812 // method which is used to avoid using virtual functions 681 // method which is used to avoid using virtual functions
813 // iterating a specific space. 682 // iterating a specific space.
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
916 // change between constructing the iterator and iterating the last 785 // change between constructing the iterator and iterating the last
917 // page. 786 // page.
918 // 787 //
919 // (3) The space should not shrink during iteration, otherwise the 788 // (3) The space should not shrink during iteration, otherwise the
920 // iterator will return deallocated pages. 789 // iterator will return deallocated pages.
921 790
922 class PageIterator BASE_EMBEDDED { 791 class PageIterator BASE_EMBEDDED {
923 public: 792 public:
924 enum Mode { 793 enum Mode {
925 PAGES_IN_USE, 794 PAGES_IN_USE,
926 PAGES_USED_BY_MC,
927 ALL_PAGES 795 ALL_PAGES
928 }; 796 };
929 797
930 PageIterator(PagedSpace* space, Mode mode); 798 PageIterator(PagedSpace* space, Mode mode);
931 799
932 inline bool has_next(); 800 inline bool has_next();
933 inline Page* next(); 801 inline Page* next();
934 802
935 private: 803 private:
936 PagedSpace* space_; 804 PagedSpace* space_;
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
1051 PagedSpace(intptr_t max_capacity, 919 PagedSpace(intptr_t max_capacity,
1052 AllocationSpace id, 920 AllocationSpace id,
1053 Executability executable); 921 Executability executable);
1054 922
1055 virtual ~PagedSpace() {} 923 virtual ~PagedSpace() {}
1056 924
1057 // Set up the space using the given address range of virtual memory (from 925 // Set up the space using the given address range of virtual memory (from
1058 // the memory allocator's initial chunk) if possible. If the block of 926 // the memory allocator's initial chunk) if possible. If the block of
1059 // addresses is not big enough to contain a single page-aligned page, a 927 // addresses is not big enough to contain a single page-aligned page, a
1060 // fresh chunk will be allocated. 928 // fresh chunk will be allocated.
1061 bool Setup(Address start, size_t size); 929 bool Setup();
1062 930
1063 // Returns true if the space has been successfully set up and not 931 // Returns true if the space has been successfully set up and not
1064 // subsequently torn down. 932 // subsequently torn down.
1065 bool HasBeenSetup(); 933 bool HasBeenSetup();
1066 934
1067 // Cleans up the space, frees all pages in this space except those belonging 935 // Cleans up the space, frees all pages in this space except those belonging
1068 // to the initial chunk, uncommits addresses in the initial chunk. 936 // to the initial chunk, uncommits addresses in the initial chunk.
1069 void TearDown(); 937 void TearDown();
1070 938
1071 // Checks whether an object/address is in this space. 939 // Checks whether an object/address is in this space.
1072 inline bool Contains(Address a); 940 inline bool Contains(Address a);
1073 bool Contains(HeapObject* o) { return Contains(o->address()); } 941 bool Contains(HeapObject* o) { return Contains(o->address()); }
1074 // Never crashes even if a is not a valid pointer.
1075 inline bool SafeContains(Address a);
1076 942
1077 // Given an address occupied by a live object, return that object if it is 943 // Given an address occupied by a live object, return that object if it is
1078 // in this space, or Failure::Exception() if it is not. The implementation 944 // in this space, or Failure::Exception() if it is not. The implementation
1079 // iterates over objects in the page containing the address, the cost is 945 // iterates over objects in the page containing the address, the cost is
1080 // linear in the number of objects in the page. It may be slow. 946 // linear in the number of objects in the page. It may be slow.
1081 MUST_USE_RESULT MaybeObject* FindObject(Address addr); 947 MUST_USE_RESULT MaybeObject* FindObject(Address addr);
1082 948
1083 // Checks whether page is currently in use by this space. 949 // Checks whether page is currently in use by this space.
1084 bool IsUsed(Page* page); 950 bool IsUsed(Page* page);
1085 951
1086 void MarkAllPagesClean();
1087
1088 // Prepares for a mark-compact GC. 952 // Prepares for a mark-compact GC.
1089 virtual void PrepareForMarkCompact(bool will_compact); 953 virtual void PrepareForMarkCompact(bool will_compact);
1090 954
1091 // The top of allocation in a page in this space. Undefined if page is unused. 955 // The top of allocation in a page in this space. Undefined if page is unused.
1092 Address PageAllocationTop(Page* page) { 956 Address PageAllocationTop(Page* page) {
1093 return page == TopPageOf(allocation_info_) ? top() 957 return page == TopPageOf(allocation_info_) ? top()
1094 : PageAllocationLimit(page); 958 : PageAllocationLimit(page);
1095 } 959 }
1096 960
1097 // The limit of allocation for a page in this space. 961 // The limit of allocation for a page in this space.
(...skipping 24 matching lines...) Expand all
1122 // Returns the address of the first object in this space. 986 // Returns the address of the first object in this space.
1123 Address bottom() { return first_page_->ObjectAreaStart(); } 987 Address bottom() { return first_page_->ObjectAreaStart(); }
1124 988
1125 // Returns the allocation pointer in this space. 989 // Returns the allocation pointer in this space.
1126 Address top() { return allocation_info_.top; } 990 Address top() { return allocation_info_.top; }
1127 991
1128 // Allocate the requested number of bytes in the space if possible, return a 992 // Allocate the requested number of bytes in the space if possible, return a
1129 // failure object if not. 993 // failure object if not.
1130 MUST_USE_RESULT inline MaybeObject* AllocateRaw(int size_in_bytes); 994 MUST_USE_RESULT inline MaybeObject* AllocateRaw(int size_in_bytes);
1131 995
1132 // Allocate the requested number of bytes for relocation during mark-compact
1133 // collection.
1134 MUST_USE_RESULT inline MaybeObject* MCAllocateRaw(int size_in_bytes);
1135
1136 virtual bool ReserveSpace(int bytes); 996 virtual bool ReserveSpace(int bytes);
1137 997
1138 // Used by ReserveSpace. 998 // Used by ReserveSpace.
1139 virtual void PutRestOfCurrentPageOnFreeList(Page* current_page) = 0; 999 virtual void PutRestOfCurrentPageOnFreeList(Page* current_page) = 0;
1140 1000
1141 // Free all pages in range from prev (exclusive) to last (inclusive). 1001 // Free all pages in range from prev (exclusive) to last (inclusive).
1142 // Freed pages are moved to the end of page list. 1002 // Freed pages are moved to the end of page list.
1143 void FreePages(Page* prev, Page* last); 1003 void FreePages(Page* prev, Page* last);
1144 1004
1145 // Deallocates a block. 1005 // Deallocates a block.
1146 virtual void DeallocateBlock(Address start, 1006 virtual void DeallocateBlock(Address start,
1147 int size_in_bytes, 1007 int size_in_bytes,
1148 bool add_to_freelist) = 0; 1008 bool add_to_freelist) = 0;
1149 1009
1150 // Set space allocation info. 1010 // Set space allocation info.
1151 void SetTop(Address top) { 1011 void SetTop(Address top) {
1152 allocation_info_.top = top; 1012 allocation_info_.top = top;
1153 allocation_info_.limit = PageAllocationLimit(Page::FromAllocationTop(top)); 1013 allocation_info_.limit = PageAllocationLimit(Page::FromAllocationTop(top));
1154 } 1014 }
1155 1015
1156 // ---------------------------------------------------------------------------
1157 // Mark-compact collection support functions
1158
1159 // Set the relocation point to the beginning of the space.
1160 void MCResetRelocationInfo();
1161
1162 // Writes relocation info to the top page.
1163 void MCWriteRelocationInfoToPage() {
1164 TopPageOf(mc_forwarding_info_)->
1165 SetAllocationWatermark(mc_forwarding_info_.top);
1166 }
1167
1168 // Computes the offset of a given address in this space to the beginning
1169 // of the space.
1170 int MCSpaceOffsetForAddress(Address addr);
1171
1172 // Updates the allocation pointer to the relocation top after a mark-compact
1173 // collection.
1174 virtual void MCCommitRelocationInfo() = 0;
1175
1176 // Releases half of unused pages. 1016 // Releases half of unused pages.
1177 void Shrink(); 1017 void Shrink();
1178 1018
1179 // Ensures that the capacity is at least 'capacity'. Returns false on failure. 1019 // Ensures that the capacity is at least 'capacity'. Returns false on failure.
1180 bool EnsureCapacity(int capacity); 1020 bool EnsureCapacity(int capacity);
1181 1021
1182 #ifdef ENABLE_HEAP_PROTECTION 1022 #ifdef ENABLE_HEAP_PROTECTION
1183 // Protect/unprotect the space by marking it read-only/writable. 1023 // Protect/unprotect the space by marking it read-only/writable.
1184 void Protect(); 1024 void Protect();
1185 void Unprotect(); 1025 void Unprotect();
(...skipping 12 matching lines...) Expand all
1198 1038
1199 // Report code object related statistics 1039 // Report code object related statistics
1200 void CollectCodeStatistics(); 1040 void CollectCodeStatistics();
1201 static void ReportCodeStatistics(); 1041 static void ReportCodeStatistics();
1202 static void ResetCodeStatistics(); 1042 static void ResetCodeStatistics();
1203 #endif 1043 #endif
1204 1044
1205 // Returns the page of the allocation pointer. 1045 // Returns the page of the allocation pointer.
1206 Page* AllocationTopPage() { return TopPageOf(allocation_info_); } 1046 Page* AllocationTopPage() { return TopPageOf(allocation_info_); }
1207 1047
1208 void RelinkPageListInChunkOrder(bool deallocate_blocks);
1209
1210 protected: 1048 protected:
1211 // Maximum capacity of this space. 1049 // Maximum capacity of this space.
1212 intptr_t max_capacity_; 1050 intptr_t max_capacity_;
1213 1051
1214 // Accounting information for this space. 1052 // Accounting information for this space.
1215 AllocationStats accounting_stats_; 1053 AllocationStats accounting_stats_;
1216 1054
1217 // The first page in this space. 1055 // The first page in this space.
1218 Page* first_page_; 1056 Page* first_page_;
1219 1057
1220 // The last page in this space. Initially set in Setup, updated in 1058 // The last page in this space. Initially set in Setup, updated in
1221 // Expand and Shrink. 1059 // Expand and Shrink.
1222 Page* last_page_; 1060 Page* last_page_;
1223 1061
1224 // True if pages owned by this space are linked in chunk-order.
1225 // See comment for class MemoryAllocator for definition of chunk-order.
1226 bool page_list_is_chunk_ordered_;
1227
1228 // Normal allocation information. 1062 // Normal allocation information.
1229 AllocationInfo allocation_info_; 1063 AllocationInfo allocation_info_;
1230 1064
1231 // Relocation information during mark-compact collections.
1232 AllocationInfo mc_forwarding_info_;
1233
1234 // Bytes of each page that cannot be allocated. Possibly non-zero 1065 // Bytes of each page that cannot be allocated. Possibly non-zero
1235 // for pages in spaces with only fixed-size objects. Always zero 1066 // for pages in spaces with only fixed-size objects. Always zero
1236 // for pages in spaces with variable sized objects (those pages are 1067 // for pages in spaces with variable sized objects (those pages are
1237 // padded with free-list nodes). 1068 // padded with free-list nodes).
1238 int page_extra_; 1069 int page_extra_;
1239 1070
1240 // Sets allocation pointer to a page bottom. 1071 // Sets allocation pointer to a page bottom.
1241 static void SetAllocationInfo(AllocationInfo* alloc_info, Page* p); 1072 static void SetAllocationInfo(AllocationInfo* alloc_info, Page* p);
1242 1073
1243 // Returns the top page specified by an allocation info structure. 1074 // Returns the top page specified by an allocation info structure.
1244 static Page* TopPageOf(AllocationInfo alloc_info) { 1075 static Page* TopPageOf(AllocationInfo alloc_info) {
1245 return Page::FromAllocationTop(alloc_info.limit); 1076 return Page::FromAllocationTop(alloc_info.limit);
1246 } 1077 }
1247 1078
1248 int CountPagesToTop() { 1079 int CountPagesToTop() {
1249 Page* p = Page::FromAllocationTop(allocation_info_.top); 1080 Page* p = Page::FromAllocationTop(allocation_info_.top);
1250 PageIterator it(this, PageIterator::ALL_PAGES); 1081 PageIterator it(this, PageIterator::ALL_PAGES);
1251 int counter = 1; 1082 int counter = 1;
1252 while (it.has_next()) { 1083 while (it.has_next()) {
1253 if (it.next() == p) return counter; 1084 if (it.next() == p) return counter;
1254 counter++; 1085 counter++;
1255 } 1086 }
1256 UNREACHABLE(); 1087 UNREACHABLE();
1257 return -1; 1088 return -1;
1258 } 1089 }
1259 1090
1260 // Expands the space by allocating a fixed number of pages. Returns false if 1091 // Expands the space by allocating a fixed number of pages. Returns false if
1261 // it cannot allocate requested number of pages from OS. Newly allocated 1092 // it cannot allocate requested number of pages from OS.
1262 // pages are append to the last_page; 1093 bool Expand();
1263 bool Expand(Page* last_page);
1264 1094
1265 // Generic fast case allocation function that tries linear allocation in 1095 // Generic fast case allocation function that tries linear allocation in
1266 // the top page of 'alloc_info'. Returns NULL on failure. 1096 // the top page of 'alloc_info'. Returns NULL on failure.
1267 inline HeapObject* AllocateLinearly(AllocationInfo* alloc_info, 1097 inline HeapObject* AllocateLinearly(AllocationInfo* alloc_info,
1268 int size_in_bytes); 1098 int size_in_bytes);
1269 1099
1270 // During normal allocation or deserialization, roll to the next page in 1100 // During normal allocation or deserialization, roll to the next page in
1271 // the space (there is assumed to be one) and allocate there. This 1101 // the space (there is assumed to be one) and allocate there. This
1272 // function is space-dependent. 1102 // function is space-dependent.
1273 virtual HeapObject* AllocateInNextPage(Page* current_page, 1103 virtual HeapObject* AllocateInNextPage(Page* current_page,
1274 int size_in_bytes) = 0; 1104 int size_in_bytes) = 0;
1275 1105
1276 // Slow path of AllocateRaw. This function is space-dependent. 1106 // Slow path of AllocateRaw. This function is space-dependent.
1277 MUST_USE_RESULT virtual HeapObject* SlowAllocateRaw(int size_in_bytes) = 0; 1107 MUST_USE_RESULT virtual HeapObject* SlowAllocateRaw(int size_in_bytes) = 0;
1278 1108
1279 // Slow path of MCAllocateRaw.
1280 MUST_USE_RESULT HeapObject* SlowMCAllocateRaw(int size_in_bytes);
1281
1282 #ifdef DEBUG 1109 #ifdef DEBUG
1283 // Returns the number of total pages in this space. 1110 // Returns the number of total pages in this space.
1284 int CountTotalPages(); 1111 int CountTotalPages();
1285 #endif 1112 #endif
1286 private: 1113 private:
1287
1288 // Returns a pointer to the page of the relocation pointer.
1289 Page* MCRelocationTopPage() { return TopPageOf(mc_forwarding_info_); }
1290
1291 friend class PageIterator; 1114 friend class PageIterator;
1292 }; 1115 };
1293 1116
1294 1117
1295 #if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING) 1118 #if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING)
1296 class NumberAndSizeInfo BASE_EMBEDDED { 1119 class NumberAndSizeInfo BASE_EMBEDDED {
1297 public: 1120 public:
1298 NumberAndSizeInfo() : number_(0), bytes_(0) {} 1121 NumberAndSizeInfo() : number_(0), bytes_(0) {}
1299 1122
1300 int number() const { return number_; } 1123 int number() const { return number_; }
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after
1504 // 1327 //
1505 // The new space consists of a contiguous pair of semispaces. It simply 1328 // The new space consists of a contiguous pair of semispaces. It simply
1506 // forwards most functions to the appropriate semispace. 1329 // forwards most functions to the appropriate semispace.
1507 1330
1508 class NewSpace : public Space { 1331 class NewSpace : public Space {
1509 public: 1332 public:
1510 // Constructor. 1333 // Constructor.
1511 NewSpace() : Space(NEW_SPACE, NOT_EXECUTABLE) {} 1334 NewSpace() : Space(NEW_SPACE, NOT_EXECUTABLE) {}
1512 1335
1513 // Sets up the new space using the given chunk. 1336 // Sets up the new space using the given chunk.
1514 bool Setup(Address start, int size); 1337 bool Setup(int max_semispace_size);
1515 1338
1516 // Tears down the space. Heap memory was not allocated by the space, so it 1339 // Tears down the space. Heap memory was not allocated by the space, so it
1517 // is not deallocated here. 1340 // is not deallocated here.
1518 void TearDown(); 1341 void TearDown();
1519 1342
1520 // True if the space has been set up but not torn down. 1343 // True if the space has been set up but not torn down.
1521 bool HasBeenSetup() { 1344 bool HasBeenSetup() {
1522 return to_space_.HasBeenSetup() && from_space_.HasBeenSetup(); 1345 return to_space_.HasBeenSetup() && from_space_.HasBeenSetup();
1523 } 1346 }
1524 1347
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
1592 uintptr_t mask() { return address_mask_; } 1415 uintptr_t mask() { return address_mask_; }
1593 1416
1594 // The allocation top and limit addresses. 1417 // The allocation top and limit addresses.
1595 Address* allocation_top_address() { return &allocation_info_.top; } 1418 Address* allocation_top_address() { return &allocation_info_.top; }
1596 Address* allocation_limit_address() { return &allocation_info_.limit; } 1419 Address* allocation_limit_address() { return &allocation_info_.limit; }
1597 1420
1598 MUST_USE_RESULT MaybeObject* AllocateRaw(int size_in_bytes) { 1421 MUST_USE_RESULT MaybeObject* AllocateRaw(int size_in_bytes) {
1599 return AllocateRawInternal(size_in_bytes, &allocation_info_); 1422 return AllocateRawInternal(size_in_bytes, &allocation_info_);
1600 } 1423 }
1601 1424
1602 // Allocate the requested number of bytes for relocation during mark-compact
1603 // collection.
1604 MUST_USE_RESULT MaybeObject* MCAllocateRaw(int size_in_bytes) {
1605 return AllocateRawInternal(size_in_bytes, &mc_forwarding_info_);
1606 }
1607
1608 // Reset the allocation pointer to the beginning of the active semispace. 1425 // Reset the allocation pointer to the beginning of the active semispace.
1609 void ResetAllocationInfo(); 1426 void ResetAllocationInfo();
1610 // Reset the reloction pointer to the bottom of the inactive semispace in
1611 // preparation for mark-compact collection.
1612 void MCResetRelocationInfo();
1613 // Update the allocation pointer in the active semispace after a
1614 // mark-compact collection.
1615 void MCCommitRelocationInfo();
1616 1427
1617 // Get the extent of the inactive semispace (for use as a marking stack). 1428 // Get the extent of the inactive semispace (for use as a marking stack).
1618 Address FromSpaceLow() { return from_space_.low(); } 1429 Address FromSpaceLow() { return from_space_.low(); }
1619 Address FromSpaceHigh() { return from_space_.high(); } 1430 Address FromSpaceHigh() { return from_space_.high(); }
1620 1431
1621 // Get the extent of the active semispace (to sweep newly copied objects 1432 // Get the extent of the active semispace (to sweep newly copied objects
1622 // during a scavenge collection). 1433 // during a scavenge collection).
1623 Address ToSpaceLow() { return to_space_.low(); } 1434 Address ToSpaceLow() { return to_space_.low(); }
1624 Address ToSpaceHigh() { return to_space_.high(); } 1435 Address ToSpaceHigh() { return to_space_.high(); }
1625 1436
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
1680 if (from_space_.is_committed()) return true; 1491 if (from_space_.is_committed()) return true;
1681 return from_space_.Commit(); 1492 return from_space_.Commit();
1682 } 1493 }
1683 1494
1684 bool UncommitFromSpace() { 1495 bool UncommitFromSpace() {
1685 if (!from_space_.is_committed()) return true; 1496 if (!from_space_.is_committed()) return true;
1686 return from_space_.Uncommit(); 1497 return from_space_.Uncommit();
1687 } 1498 }
1688 1499
1689 private: 1500 private:
1501 Address chunk_base_;
1502 uintptr_t chunk_size_;
1503
1690 // The semispaces. 1504 // The semispaces.
1691 SemiSpace to_space_; 1505 SemiSpace to_space_;
1692 SemiSpace from_space_; 1506 SemiSpace from_space_;
1693 1507
1694 // Start address and bit mask for containment testing. 1508 // Start address and bit mask for containment testing.
1695 Address start_; 1509 Address start_;
1696 uintptr_t address_mask_; 1510 uintptr_t address_mask_;
1697 uintptr_t object_mask_; 1511 uintptr_t object_mask_;
1698 uintptr_t object_expected_; 1512 uintptr_t object_expected_;
1699 1513
1700 // Allocation pointer and limit for normal allocation and allocation during 1514 // Allocation pointer and limit for normal allocation and allocation during
1701 // mark-compact collection. 1515 // mark-compact collection.
1702 AllocationInfo allocation_info_; 1516 AllocationInfo allocation_info_;
1703 AllocationInfo mc_forwarding_info_;
1704 1517
1705 #if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING) 1518 #if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING)
1706 HistogramInfo* allocated_histogram_; 1519 HistogramInfo* allocated_histogram_;
1707 HistogramInfo* promoted_histogram_; 1520 HistogramInfo* promoted_histogram_;
1708 #endif 1521 #endif
1709 1522
1710 // Implementation of AllocateRaw and MCAllocateRaw. 1523 // Implementation of AllocateRaw and MCAllocateRaw.
1711 MUST_USE_RESULT inline MaybeObject* AllocateRawInternal( 1524 MUST_USE_RESULT inline MaybeObject* AllocateRawInternal(
1712 int size_in_bytes, 1525 int size_in_bytes,
1713 AllocationInfo* alloc_info); 1526 AllocationInfo* alloc_info);
(...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after
1939 } 1752 }
1940 1753
1941 virtual void DeallocateBlock(Address start, 1754 virtual void DeallocateBlock(Address start,
1942 int size_in_bytes, 1755 int size_in_bytes,
1943 bool add_to_freelist); 1756 bool add_to_freelist);
1944 1757
1945 // Prepare for full garbage collection. Resets the relocation pointer and 1758 // Prepare for full garbage collection. Resets the relocation pointer and
1946 // clears the free list. 1759 // clears the free list.
1947 virtual void PrepareForMarkCompact(bool will_compact); 1760 virtual void PrepareForMarkCompact(bool will_compact);
1948 1761
1949 // Updates the allocation pointer to the relocation top after a mark-compact
1950 // collection.
1951 virtual void MCCommitRelocationInfo();
1952
1953 virtual void PutRestOfCurrentPageOnFreeList(Page* current_page); 1762 virtual void PutRestOfCurrentPageOnFreeList(Page* current_page);
1954 1763
1955 void MarkFreeListNodes() { free_list_.MarkNodes(); } 1764 void MarkFreeListNodes() { free_list_.MarkNodes(); }
1956 1765
1957 #ifdef DEBUG 1766 #ifdef DEBUG
1958 // Reports statistics for the space 1767 // Reports statistics for the space
1959 void ReportStatistics(); 1768 void ReportStatistics();
1960 #endif 1769 #endif
1961 1770
1962 protected: 1771 protected:
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
2005 void Free(Address start, bool add_to_freelist) { 1814 void Free(Address start, bool add_to_freelist) {
2006 if (add_to_freelist) { 1815 if (add_to_freelist) {
2007 free_list_.Free(start); 1816 free_list_.Free(start);
2008 } 1817 }
2009 accounting_stats_.DeallocateBytes(object_size_in_bytes_); 1818 accounting_stats_.DeallocateBytes(object_size_in_bytes_);
2010 } 1819 }
2011 1820
2012 // Prepares for a mark-compact GC. 1821 // Prepares for a mark-compact GC.
2013 virtual void PrepareForMarkCompact(bool will_compact); 1822 virtual void PrepareForMarkCompact(bool will_compact);
2014 1823
2015 // Updates the allocation pointer to the relocation top after a mark-compact
2016 // collection.
2017 virtual void MCCommitRelocationInfo();
2018
2019 virtual void PutRestOfCurrentPageOnFreeList(Page* current_page); 1824 virtual void PutRestOfCurrentPageOnFreeList(Page* current_page);
2020 1825
2021 virtual void DeallocateBlock(Address start, 1826 virtual void DeallocateBlock(Address start,
2022 int size_in_bytes, 1827 int size_in_bytes,
2023 bool add_to_freelist); 1828 bool add_to_freelist);
2024 1829
2025 void MarkFreeListNodes() { free_list_.MarkNodes(); } 1830 void MarkFreeListNodes() { free_list_.MarkNodes(); }
2026 1831
2027 #ifdef DEBUG 1832 #ifdef DEBUG
2028 // Reports statistic info of the space 1833 // Reports statistic info of the space
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
2168 }; 1973 };
2169 1974
2170 1975
2171 // ----------------------------------------------------------------------------- 1976 // -----------------------------------------------------------------------------
2172 // Large objects ( > Page::kMaxHeapObjectSize ) are allocated and managed by 1977 // Large objects ( > Page::kMaxHeapObjectSize ) are allocated and managed by
2173 // the large object space. A large object is allocated from OS heap with 1978 // the large object space. A large object is allocated from OS heap with
2174 // extra padding bytes (Page::kPageSize + Page::kObjectStartOffset). 1979 // extra padding bytes (Page::kPageSize + Page::kObjectStartOffset).
2175 // A large object always starts at Page::kObjectStartOffset to a page. 1980 // A large object always starts at Page::kObjectStartOffset to a page.
2176 // Large objects do not move during garbage collections. 1981 // Large objects do not move during garbage collections.
2177 1982
2178 // A LargeObjectChunk holds exactly one large object page with exactly one
2179 // large object.
2180 class LargeObjectChunk {
2181 public:
2182 // Allocates a new LargeObjectChunk that contains a large object page
2183 // (Page::kPageSize aligned) that has at least size_in_bytes (for a large
2184 // object) bytes after the object area start of that page.
2185 static LargeObjectChunk* New(int size_in_bytes, Executability executable);
2186
2187 // Free the memory associated with the chunk.
2188 inline void Free(Executability executable);
2189
2190 // Interpret a raw address as a large object chunk.
2191 static LargeObjectChunk* FromAddress(Address address) {
2192 return reinterpret_cast<LargeObjectChunk*>(address);
2193 }
2194
2195 // Returns the address of this chunk.
2196 Address address() { return reinterpret_cast<Address>(this); }
2197
2198 // Accessors for the fields of the chunk.
2199 LargeObjectChunk* next() { return next_; }
2200 void set_next(LargeObjectChunk* chunk) { next_ = chunk; }
2201 size_t size() { return size_ & ~Page::kPageFlagMask; }
2202
2203 // Compute the start address in the chunk.
2204 inline Address GetStartAddress();
2205
2206 // Returns the object in this chunk.
2207 HeapObject* GetObject() { return HeapObject::FromAddress(GetStartAddress()); }
2208
2209 // Given a requested size returns the physical size of a chunk to be
2210 // allocated.
2211 static int ChunkSizeFor(int size_in_bytes);
2212
2213 // Given a chunk size, returns the object size it can accommodate. Used by
2214 // LargeObjectSpace::Available.
2215 static intptr_t ObjectSizeFor(intptr_t chunk_size) {
2216 if (chunk_size <= (Page::kPageSize + Page::kObjectStartOffset)) return 0;
2217 return chunk_size - Page::kPageSize - Page::kObjectStartOffset;
2218 }
2219
2220 private:
2221 // A pointer to the next large object chunk in the space or NULL.
2222 LargeObjectChunk* next_;
2223
2224 // The total size of this chunk.
2225 size_t size_;
2226
2227 public:
2228 TRACK_MEMORY("LargeObjectChunk")
2229 };
2230
2231
2232 class LargeObjectSpace : public Space { 1983 class LargeObjectSpace : public Space {
2233 public: 1984 public:
2234 explicit LargeObjectSpace(AllocationSpace id); 1985 explicit LargeObjectSpace(AllocationSpace id);
2235 virtual ~LargeObjectSpace() {} 1986 virtual ~LargeObjectSpace() {}
2236 1987
2237 // Initializes internal data structures. 1988 // Initializes internal data structures.
2238 bool Setup(); 1989 bool Setup();
2239 1990
2240 // Releases internal resources, frees objects in this space. 1991 // Releases internal resources, frees objects in this space.
2241 void TearDown(); 1992 void TearDown();
2242 1993
2243 // Allocates a (non-FixedArray, non-Code) large object. 1994 // Allocates a (non-FixedArray, non-Code) large object.
2244 MUST_USE_RESULT MaybeObject* AllocateRaw(int size_in_bytes); 1995 MUST_USE_RESULT MaybeObject* AllocateRaw(int size_in_bytes);
2245 // Allocates a large Code object. 1996 // Allocates a large Code object.
2246 MUST_USE_RESULT MaybeObject* AllocateRawCode(int size_in_bytes); 1997 MUST_USE_RESULT MaybeObject* AllocateRawCode(int size_in_bytes);
2247 // Allocates a large FixedArray. 1998 // Allocates a large FixedArray.
2248 MUST_USE_RESULT MaybeObject* AllocateRawFixedArray(int size_in_bytes); 1999 MUST_USE_RESULT MaybeObject* AllocateRawFixedArray(int size_in_bytes);
2249 2000
2001 static intptr_t ObjectSizeFor(intptr_t chunk_size) {
2002 if (chunk_size <= (Page::kPageSize + Page::kObjectStartOffset)) return 0;
2003 return chunk_size - Page::kPageSize - Page::kObjectStartOffset;
2004 }
2005
2250 // Available bytes for objects in this space. 2006 // Available bytes for objects in this space.
2251 intptr_t Available() { 2007 intptr_t Available() {
2252 return LargeObjectChunk::ObjectSizeFor(MemoryAllocator::Available()); 2008 return ObjectSizeFor(MemoryAllocator::Available());
2253 } 2009 }
2254 2010
2255 virtual intptr_t Size() { 2011 virtual intptr_t Size() {
2256 return size_; 2012 return size_;
2257 } 2013 }
2258 2014
2259 virtual intptr_t SizeOfObjects() { 2015 virtual intptr_t SizeOfObjects() {
2260 return objects_size_; 2016 return objects_size_;
2261 } 2017 }
2262 2018
2263 int PageCount() { 2019 int PageCount() {
2264 return page_count_; 2020 return page_count_;
2265 } 2021 }
2266 2022
2267 // Finds an object for a given address, returns Failure::Exception() 2023 // Finds an object for a given address, returns Failure::Exception()
2268 // if it is not found. The function iterates through all objects in this 2024 // if it is not found. The function iterates through all objects in this
2269 // space, may be slow. 2025 // space, may be slow.
2270 MaybeObject* FindObject(Address a); 2026 MaybeObject* FindObject(Address a);
2271 2027
2272 // Finds a large object page containing the given pc, returns NULL 2028 // Finds a large object page containing the given pc, returns NULL
2273 // if such a page doesn't exist. 2029 // if such a page doesn't exist.
2274 LargeObjectChunk* FindChunkContainingPc(Address pc); 2030 LargePage* FindPageContainingPc(Address pc);
2275 2031
2276 // Iterates objects covered by dirty regions. 2032 // Iterates objects covered by dirty regions.
2277 void IterateDirtyRegions(ObjectSlotCallback func); 2033 void IterateDirtyRegions(ObjectSlotCallback func);
2278 2034
2279 // Frees unmarked objects. 2035 // Frees unmarked objects.
2280 void FreeUnmarkedObjects(); 2036 void FreeUnmarkedObjects();
2281 2037
2282 // Checks whether a heap object is in this space; O(1). 2038 // Checks whether a heap object is in this space; O(1).
2283 bool Contains(HeapObject* obj); 2039 bool Contains(HeapObject* obj);
2284 2040
2285 // Checks whether the space is empty. 2041 // Checks whether the space is empty.
2286 bool IsEmpty() { return first_chunk_ == NULL; } 2042 bool IsEmpty() { return first_page_ == NULL; }
2287 2043
2288 // See the comments for ReserveSpace in the Space class. This has to be 2044 // See the comments for ReserveSpace in the Space class. This has to be
2289 // called after ReserveSpace has been called on the paged spaces, since they 2045 // called after ReserveSpace has been called on the paged spaces, since they
2290 // may use some memory, leaving less for large objects. 2046 // may use some memory, leaving less for large objects.
2291 virtual bool ReserveSpace(int bytes); 2047 virtual bool ReserveSpace(int bytes);
2292 2048
2293 #ifdef ENABLE_HEAP_PROTECTION 2049 #ifdef ENABLE_HEAP_PROTECTION
2294 // Protect/unprotect the space by marking it read-only/writable. 2050 // Protect/unprotect the space by marking it read-only/writable.
2295 void Protect(); 2051 void Protect();
2296 void Unprotect(); 2052 void Unprotect();
2297 #endif 2053 #endif
2298 2054
2299 #ifdef DEBUG 2055 #ifdef DEBUG
2300 virtual void Verify(); 2056 virtual void Verify();
2301 virtual void Print(); 2057 virtual void Print();
2302 void ReportStatistics(); 2058 void ReportStatistics();
2303 void CollectCodeStatistics(); 2059 void CollectCodeStatistics();
2304 #endif 2060 #endif
2305 // Checks whether an address is in the object area in this space. It 2061 // Checks whether an address is in the object area in this space. It
2306 // iterates all objects in the space. May be slow. 2062 // iterates all objects in the space. May be slow.
2307 bool SlowContains(Address addr) { return !FindObject(addr)->IsFailure(); } 2063 bool SlowContains(Address addr) { return !FindObject(addr)->IsFailure(); }
2308 2064
2309 private: 2065 private:
2310 // The head of the linked list of large object chunks. 2066 // The head of the linked list of large object chunks.
2311 LargeObjectChunk* first_chunk_; 2067 LargePage* first_page_;
2312 intptr_t size_; // allocated bytes 2068 intptr_t size_; // allocated bytes
2313 int page_count_; // number of chunks 2069 int page_count_; // number of chunks
2314 intptr_t objects_size_; // size of objects 2070 intptr_t objects_size_; // size of objects
2315 2071
2316 // Shared implementation of AllocateRaw, AllocateRawCode and 2072 // Shared implementation of AllocateRaw, AllocateRawCode and
2317 // AllocateRawFixedArray. 2073 // AllocateRawFixedArray.
2318 MUST_USE_RESULT MaybeObject* AllocateRawInternal(int requested_size, 2074 MUST_USE_RESULT MaybeObject* AllocateRawInternal(int object_size,
2319 int object_size,
2320 Executability executable); 2075 Executability executable);
2321 2076
2322 friend class LargeObjectIterator; 2077 friend class LargeObjectIterator;
2323 2078
2324 public: 2079 public:
2325 TRACK_MEMORY("LargeObjectSpace") 2080 TRACK_MEMORY("LargeObjectSpace")
2326 }; 2081 };
2327 2082
2328 2083
2329 class LargeObjectIterator: public ObjectIterator { 2084 class LargeObjectIterator: public ObjectIterator {
2330 public: 2085 public:
2331 explicit LargeObjectIterator(LargeObjectSpace* space); 2086 explicit LargeObjectIterator(LargeObjectSpace* space);
2332 LargeObjectIterator(LargeObjectSpace* space, HeapObjectCallback size_func); 2087 LargeObjectIterator(LargeObjectSpace* space, HeapObjectCallback size_func);
2333 2088
2334 HeapObject* next(); 2089 HeapObject* next();
2335 2090
2336 // implementation of ObjectIterator. 2091 // implementation of ObjectIterator.
2337 virtual HeapObject* next_object() { return next(); } 2092 virtual HeapObject* next_object() { return next(); }
2338 2093
2339 private: 2094 private:
2340 LargeObjectChunk* current_; 2095 LargePage* current_;
2341 HeapObjectCallback size_func_; 2096 HeapObjectCallback size_func_;
2342 }; 2097 };
2343 2098
2344 2099
2345 } } // namespace v8::internal 2100 } } // namespace v8::internal
2346 2101
2347 #endif // V8_SPACES_H_ 2102 #endif // V8_SPACES_H_
OLDNEW
« no previous file with comments | « src/platform-linux.cc ('k') | src/spaces.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698