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

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: 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
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 memory region owned by a specific space.
Erik Corry 2010/12/22 13:48:27 represents memory -> represents a memory
Vyacheslav Egorov (Chromium) 2010/12/22 19:55:07 Done.
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_; }
Erik Corry 2010/12/22 13:48:27 For getters the function is normally called the sa
Vyacheslav Egorov (Chromium) 2010/12/22 19:55:07 Done.
131
132 void set_next_chunk(MemoryChunk* next) { next_ = 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);
Erik Corry 2010/12/22 13:48:27 Implicit conversions from int to bool are not allo
Vyacheslav Egorov (Chromium) 2010/12/22 19:55:07 Done.
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_;
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_ = 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 of this page.
Erik Corry 2010/12/22 13:48:27 The next page in the chain of pages?
153 Address address() { return reinterpret_cast<Address>(this); } 233 inline Page* next_page() {
234 return static_cast<Page*>(next_chunk());
Erik Corry 2010/12/22 13:48:27 Should we assert that the next chunk is a page?
Vyacheslav Egorov (Chromium) 2010/12/22 19:55:07 I added an assert to check that pages have the sam
235 }
154 236
155 // Checks whether this is a valid page address. 237 inline void set_next_page(Page* page) {
156 bool is_valid() { return address() != NULL; } 238 set_next_chunk(page);
Erik Corry 2010/12/22 13:48:27 And assert here too?
157 239 }
158 // Returns the next page of this page.
159 inline Page* next_page();
160 240
161 // Return the end of allocation in this page. Undefined for unused pages. 241 // Return the end of allocation in this page. Undefined for unused pages.
162 inline Address AllocationTop(); 242 inline Address AllocationTop();
163 243
164 // Return the allocation watermark for the page. 244 // Return the allocation watermark for the page.
165 // For old space pages it is guaranteed that the area under the watermark 245 // For old space pages it is guaranteed that the area under the watermark
166 // does not contain any garbage pointers to new space. 246 // does not contain any garbage pointers to new space.
167 inline Address AllocationWatermark(); 247 inline Address AllocationWatermark();
168 248
169 // Return the allocation watermark offset from the beginning of the page. 249 // Return the allocation watermark offset from the beginning of the page.
(...skipping 10 matching lines...) Expand all
180 // Returns the end address (exclusive) of the object area in this page. 260 // Returns the end address (exclusive) of the object area in this page.
181 Address ObjectAreaEnd() { return address() + Page::kPageSize; } 261 Address ObjectAreaEnd() { return address() + Page::kPageSize; }
182 262
183 // Checks whether an address is page aligned. 263 // Checks whether an address is page aligned.
184 static bool IsAlignedToPageSize(Address a) { 264 static bool IsAlignedToPageSize(Address a) {
185 return 0 == (OffsetFrom(a) & kPageAlignmentMask); 265 return 0 == (OffsetFrom(a) & kPageAlignmentMask);
186 } 266 }
187 267
188 // True if this page was in use before current compaction started. 268 // True if this page was in use before current compaction started.
189 // Result is valid only for pages owned by paged spaces and 269 // Result is valid only for pages owned by paged spaces and
190 // only after PagedSpace::PrepareForMarkCompact was called. 270 // only after PagedSpace::PrepareForMarkCompact was called.
Erik Corry 2010/12/22 13:48:27 Should the comment go away?
Vyacheslav Egorov (Chromium) 2010/12/22 19:55:07 Done.
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 271
204 // Returns the offset of a given address to this page. 272 // Returns the offset of a given address to this page.
205 INLINE(int Offset(Address a)) { 273 INLINE(int Offset(Address a)) {
206 int offset = static_cast<int>(a - address()); 274 int offset = static_cast<int>(a - address());
207 ASSERT_PAGE_OFFSET(offset); 275 ASSERT_PAGE_OFFSET(offset);
208 return offset; 276 return offset;
209 } 277 }
210 278
211 // Returns the address for a given offset to the this page. 279 // Returns the address for a given offset to the this page.
212 Address OffsetToAddress(int offset) { 280 Address OffsetToAddress(int offset) {
(...skipping 20 matching lines...) Expand all
233 inline void ClearRegionMarks(Address start, 301 inline void ClearRegionMarks(Address start,
234 Address end, 302 Address end,
235 bool reaches_limit); 303 bool reaches_limit);
236 304
237 // Page size in bytes. This must be a multiple of the OS page size. 305 // Page size in bytes. This must be a multiple of the OS page size.
238 static const int kPageSize = 1 << kPageSizeBits; 306 static const int kPageSize = 1 << kPageSizeBits;
239 307
240 // Page size mask. 308 // Page size mask.
241 static const intptr_t kPageAlignmentMask = (1 << kPageSizeBits) - 1; 309 static const intptr_t kPageAlignmentMask = (1 << kPageSizeBits) - 1;
242 310
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 311 // The start offset of the object area in a page. Aligned to both maps and
247 // code alignment to be suitable for both. 312 // code alignment to be suitable for both.
248 static const int kObjectStartOffset = 313 static const int kObjectStartOffset = kBodyOffset;
249 CODE_POINTER_ALIGN(MAP_POINTER_ALIGN(kPageHeaderSize));
250 314
251 // Object area size in bytes. 315 // Object area size in bytes.
252 static const int kObjectAreaSize = kPageSize - kObjectStartOffset; 316 static const int kObjectAreaSize = kPageSize - kObjectStartOffset;
253 317
254 // Maximum object size that fits in a page. 318 // Maximum object size that fits in a page.
255 static const int kMaxHeapObjectSize = kObjectAreaSize; 319 static const int kMaxHeapObjectSize = kObjectAreaSize;
256 320
321 #ifdef ENABLE_CARDMARKING_WRITE_BARRIER
257 static const int kDirtyFlagOffset = 2 * kPointerSize; 322 static const int kDirtyFlagOffset = 2 * kPointerSize;
258 static const int kRegionSizeLog2 = 8; 323 static const int kRegionSizeLog2 = 8;
259 static const int kRegionSize = 1 << kRegionSizeLog2; 324 static const int kRegionSize = 1 << kRegionSizeLog2;
260 static const intptr_t kRegionAlignmentMask = (kRegionSize - 1); 325 static const intptr_t kRegionAlignmentMask = (kRegionSize - 1);
261 326
262 STATIC_CHECK(kRegionSize == kPageSize / kBitsPerInt); 327 STATIC_CHECK(kRegionSize == kPageSize / kBitsPerInt);
328 #endif
263 329
264 enum PageFlag { 330 enum PageFlag {
265 IS_NORMAL_PAGE = 0,
266 WAS_IN_USE_BEFORE_MC,
267
268 // Page allocation watermark was bumped by preallocation during scavenge. 331 // Page allocation watermark was bumped by preallocation during scavenge.
269 // Correct watermark can be retrieved by CachedAllocationWatermark() method 332 // Correct watermark can be retrieved by CachedAllocationWatermark() method
270 WATERMARK_INVALIDATED, 333 WATERMARK_INVALIDATED = NUM_MEMORY_CHUNK_FLAGS,
271 IS_EXECUTABLE,
272 NUM_PAGE_FLAGS // Must be last 334 NUM_PAGE_FLAGS // Must be last
273 }; 335 };
336
274 static const int kPageFlagMask = (1 << NUM_PAGE_FLAGS) - 1; 337 static const int kPageFlagMask = (1 << NUM_PAGE_FLAGS) - 1;
275 338
276 // To avoid an additional WATERMARK_INVALIDATED flag clearing pass during 339 // To avoid an additional WATERMARK_INVALIDATED flag clearing pass during
277 // scavenge we just invalidate the watermark on each old space page after 340 // 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 341 // 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 342 // flag at the beginning of the next scavenge and each page becomes marked as
280 // having a valid watermark. 343 // having a valid watermark.
281 // 344 //
282 // The following invariant must hold for pages in old pointer and map spaces: 345 // 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 346 // If page is in use then page is marked as having invalid watermark at
284 // the beginning and at the end of any GC. 347 // the beginning and at the end of any GC.
285 // 348 //
286 // This invariant guarantees that after flipping flag meaning at the 349 // This invariant guarantees that after flipping flag meaning at the
287 // beginning of scavenge all pages in use will be marked as having valid 350 // beginning of scavenge all pages in use will be marked as having valid
288 // watermark. 351 // watermark.
289 static inline void FlipMeaningOfInvalidatedWatermarkFlag(); 352 static inline void FlipMeaningOfInvalidatedWatermarkFlag();
290 353
291 // Returns true if the page allocation watermark was not altered during 354 // Returns true if the page allocation watermark was not altered during
292 // scavenge. 355 // scavenge.
293 inline bool IsWatermarkValid(); 356 inline bool IsWatermarkValid();
294 357
295 inline void InvalidateWatermark(bool value); 358 inline void InvalidateWatermark(bool value);
296 359
297 inline bool GetPageFlag(PageFlag flag);
298 inline void SetPageFlag(PageFlag flag, bool value);
299 inline void ClearPageFlags();
300
301 inline void ClearGCFields(); 360 inline void ClearGCFields();
302 361
303 static const int kAllocationWatermarkOffsetShift = WATERMARK_INVALIDATED + 1; 362 static const int kAllocationWatermarkOffsetShift = WATERMARK_INVALIDATED + 1;
304 static const int kAllocationWatermarkOffsetBits = kPageSizeBits + 1; 363 static const int kAllocationWatermarkOffsetBits = kPageSizeBits + 1;
305 static const uint32_t kAllocationWatermarkOffsetMask = 364 static const uint32_t kAllocationWatermarkOffsetMask =
306 ((1 << kAllocationWatermarkOffsetBits) - 1) << 365 ((1 << kAllocationWatermarkOffsetBits) - 1) <<
307 kAllocationWatermarkOffsetShift; 366 kAllocationWatermarkOffsetShift;
308 367
309 static const uint32_t kFlagsMask = 368 static const uint32_t kFlagsMask =
310 ((1 << kAllocationWatermarkOffsetShift) - 1); 369 ((1 << kAllocationWatermarkOffsetShift) - 1);
311 370
312 STATIC_CHECK(kBitsPerInt - kAllocationWatermarkOffsetShift >= 371 STATIC_CHECK(kBitsPerInt - kAllocationWatermarkOffsetShift >=
313 kAllocationWatermarkOffsetBits); 372 kAllocationWatermarkOffsetBits);
314 373
315 // This field contains the meaning of the WATERMARK_INVALIDATED flag. 374 // This field contains the meaning of the WATERMARK_INVALIDATED flag.
316 // Instead of clearing this flag from all pages we just flip 375 // Instead of clearing this flag from all pages we just flip
317 // its meaning at the beginning of a scavenge. 376 // its meaning at the beginning of a scavenge.
318 static intptr_t watermark_invalidated_mark_; 377 static intptr_t watermark_invalidated_mark_;
319 378
320 //--------------------------------------------------------------------------- 379 private:
321 // Page header description. 380 static Page* Initialize(MemoryChunk* chunk) {
322 // 381 Page* page = static_cast<Page*>(chunk);
323 // If a page is not in the large object space, the first word, 382 page->allocation_watermark_ = page->body();
324 // opaque_header, encodes the next page address (aligned to kPageSize 8K) 383 page->InvalidateWatermark(true);
325 // and the chunk number (0 ~ 8K-1). Only MemoryAllocator should use 384 return page;
326 // opaque_header. The value range of the opaque_header is [0..kPageSize[, 385 }
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 386
333 // If the page is not in the large object space, the low-order bit of the 387 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 388
342 // This field contains dirty marks for regions covering the page. Only dirty 389 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 }; 390 };
357 391
392 STATIC_CHECK(sizeof(Page) <= MemoryChunk::kHeaderSize);
393
394 class LargePage : public MemoryChunk {
395 public:
396 HeapObject* GetObject() {
397 return HeapObject::FromAddress(body());
398 }
399
400 inline LargePage* next_page() const {
401 return static_cast<LargePage*>(next_chunk());
402 }
403
404 inline void set_next_page(LargePage* page) {
405 set_next_chunk(page);
406 }
407 private:
408 static LargePage* Initialize(MemoryChunk* chunk) {
409 return static_cast<LargePage*>(chunk);
410 }
411
412 friend class MemoryAllocator;
413 };
414
415 STATIC_CHECK(sizeof(LargePage) <= MemoryChunk::kHeaderSize);
358 416
359 // ---------------------------------------------------------------------------- 417 // ----------------------------------------------------------------------------
360 // Space is the abstract superclass for all allocation spaces. 418 // Space is the abstract superclass for all allocation spaces.
361 class Space : public Malloced { 419 class Space : public Malloced {
362 public: 420 public:
363 Space(AllocationSpace id, Executability executable) 421 Space(AllocationSpace id, Executability executable)
364 : id_(id), executable_(executable) {} 422 : id_(id), executable_(executable) {}
365 423
366 virtual ~Space() {} 424 virtual ~Space() {}
367 425
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
495 553
496 class MemoryAllocator : public AllStatic { 554 class MemoryAllocator : public AllStatic {
497 public: 555 public:
498 // Initializes its internal bookkeeping structures. 556 // Initializes its internal bookkeeping structures.
499 // Max capacity of the total space and executable memory limit. 557 // Max capacity of the total space and executable memory limit.
500 static bool Setup(intptr_t max_capacity, intptr_t capacity_executable); 558 static bool Setup(intptr_t max_capacity, intptr_t capacity_executable);
501 559
502 // Deletes valid chunks. 560 // Deletes valid chunks.
503 static void TearDown(); 561 static void TearDown();
504 562
505 // Reserves an initial address range of virtual memory to be split between 563 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 564
516 // Commits pages from an as-yet-unmanaged block of virtual memory into a 565 static LargePage* AllocateLargePage(intptr_t object_size,
517 // paged space. The block should be part of the initial chunk reserved via 566 Executability executable,
518 // a call to ReserveInitialChunk. The number of pages is always returned in 567 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 568
526 // Commit a contiguous block of memory from the initial chunk. Assumes that 569 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 570
590 // Returns the maximum available bytes of heaps. 571 // Returns the maximum available bytes of heaps.
591 static intptr_t Available() { 572 static intptr_t Available() {
592 return capacity_ < size_ ? 0 : capacity_ - size_; 573 return capacity_ < size_ ? 0 : capacity_ - size_;
593 } 574 }
594 575
595 // Returns allocated spaces in bytes. 576 // Returns allocated spaces in bytes.
596 static intptr_t Size() { return size_; } 577 static intptr_t Size() { return size_; }
597 578
598 // Returns the maximum available executable bytes of heaps. 579 // Returns the maximum available executable bytes of heaps.
599 static intptr_t AvailableExecutable() { 580 static intptr_t AvailableExecutable() {
600 if (capacity_executable_ < size_executable_) return 0; 581 if (capacity_executable_ < size_executable_) return 0;
601 return capacity_executable_ - size_executable_; 582 return capacity_executable_ - size_executable_;
602 } 583 }
603 584
604 // Returns allocated executable spaces in bytes. 585 // Returns allocated executable spaces in bytes.
605 static intptr_t SizeExecutable() { return size_executable_; } 586 static intptr_t SizeExecutable() { return size_executable_; }
606 587
607 // Returns maximum available bytes that the old space can have. 588 // Returns maximum available bytes that the old space can have.
608 static intptr_t MaxAvailable() { 589 static intptr_t MaxAvailable() {
609 return (Available() / Page::kPageSize) * Page::kObjectAreaSize; 590 return (Available() / Page::kPageSize) * Page::kObjectAreaSize;
610 } 591 }
611 592
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 593 #ifdef ENABLE_HEAP_PROTECTION
641 // Protect/unprotect a block of memory by marking it read-only/writable. 594 // Protect/unprotect a block of memory by marking it read-only/writable.
642 static inline void Protect(Address start, size_t size); 595 static inline void Protect(Address start, size_t size);
643 static inline void Unprotect(Address start, size_t size, 596 static inline void Unprotect(Address start, size_t size,
644 Executability executable); 597 Executability executable);
645 598
646 // Protect/unprotect a chunk given a page in the chunk. 599 // Protect/unprotect a chunk given a page in the chunk.
647 static inline void ProtectChunkFromPage(Page* page); 600 static inline void ProtectChunkFromPage(Page* page);
648 static inline void UnprotectChunkFromPage(Page* page); 601 static inline void UnprotectChunkFromPage(Page* page);
649 #endif 602 #endif
650 603
651 #ifdef DEBUG 604 #ifdef DEBUG
652 // Reports statistic info of the space. 605 // Reports statistic info of the space.
653 static void ReportStatistics(); 606 static void ReportStatistics();
654 #endif 607 #endif
655 608
656 static void AddToAllocatedChunks(Address addr, intptr_t size); 609 static MemoryChunk* AllocateChunk(intptr_t body_size,
657 static void RemoveFromAllocatedChunks(Address addr, intptr_t size); 610 Executability executable,
658 // Note: This only checks the regular chunks, not the odd-sized initial 611 Space* space);
659 // chunk.
660 static bool InAllocatedChunks(Address addr);
661 612
662 // Due to encoding limitation, we can only have 8K chunks. 613 static void* AllocateAlignedMemory(const size_t requested,
663 static const int kMaxNofChunks = 1 << kPageSizeBits; 614 size_t alignment,
664 // If a chunk has at least 16 pages, the maximum heap size is about 615 Executability executable,
665 // 8K * 8K * 16 = 1G bytes. 616 size_t* allocated_size);
666 #ifdef V8_TARGET_ARCH_X64 617
667 static const int kPagesPerChunk = 32; 618 static void* ReserveAlignedMemory(const size_t requested,
668 // On 64 bit the chunk table consists of 4 levels of 4096-entry tables. 619 size_t alignment,
669 static const int kPagesPerChunkLog2 = 5; 620 size_t* allocated_size);
670 static const int kChunkTableLevels = 4; 621
671 static const int kChunkTableBitsPerLevel = 12; 622 static void FreeMemory(void* addr, size_t size, Executability executable);
672 #else 623
673 static const int kPagesPerChunk = 16; 624 // 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. 625 // the address is not NULL, the size is greater than zero, and that the
675 static const int kPagesPerChunkLog2 = 4; 626 // block is contained in the initial chunk. Returns true if it succeeded
676 static const int kChunkTableLevels = 2; 627 // and false otherwise.
677 static const int kChunkTableBitsPerLevel = 8; 628 static bool CommitBlock(Address start, size_t size, Executability executable);
678 #endif 629
630 // Uncommit a contiguous block of memory [start..(start+size)[.
631 // start is not NULL, the size is greater than zero, and the
632 // block is contained in the initial chunk. Returns true if it succeeded
633 // and false otherwise.
634 static bool UncommitBlock(Address start, size_t size);
635
636 // Zaps a contiguous block of memory [start..(start+size)[ thus
637 // filling it up with a recognizable non-NULL bit pattern.
638 static void ZapBlock(Address start, size_t size);
639
640 static void PerformAllocationCallback(ObjectSpace space,
641 AllocationAction action,
642 size_t size);
643
644 static void AddMemoryAllocationCallback(MemoryAllocationCallback callback,
645 ObjectSpace space,
646 AllocationAction action);
647
648 static void RemoveMemoryAllocationCallback(
649 MemoryAllocationCallback callback);
650
651 static bool MemoryAllocationCallbackRegistered(
652 MemoryAllocationCallback callback);
653
654
679 655
680 private: 656 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. 657 // Maximum space size in bytes.
693 static intptr_t capacity_; 658 static size_t capacity_;
Erik Corry 2010/12/22 13:48:27 I don't like unsigned types much, so I tend to pre
Vyacheslav Egorov (Chromium) 2010/12/22 19:55:07 I like signed types :-) But the reason I changed
694 // Maximum subset of capacity_ that can be executable 659 // Maximum subset of capacity_ that can be executable
695 static intptr_t capacity_executable_; 660 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 661
700 // Allocated space size in bytes. 662 // Allocated space size in bytes.
701 static intptr_t size_; 663 static size_t size_;
702 // Allocated executable space size in bytes. 664 // Allocated executable space size in bytes.
703 static intptr_t size_executable_; 665 static size_t size_executable_;
704 666
705 struct MemoryAllocationCallbackRegistration { 667 struct MemoryAllocationCallbackRegistration {
706 MemoryAllocationCallbackRegistration(MemoryAllocationCallback callback, 668 MemoryAllocationCallbackRegistration(MemoryAllocationCallback callback,
707 ObjectSpace space, 669 ObjectSpace space,
708 AllocationAction action) 670 AllocationAction action)
709 : callback(callback), space(space), action(action) { 671 : callback(callback), space(space), action(action) {
710 } 672 }
711 MemoryAllocationCallback callback; 673 MemoryAllocationCallback callback;
712 ObjectSpace space; 674 ObjectSpace space;
713 AllocationAction action; 675 AllocationAction action;
714 }; 676 };
715 // A List of callback that are triggered when memory is allocated or free'd 677 // A List of callback that are triggered when memory is allocated or free'd
716 static List<MemoryAllocationCallbackRegistration> 678 static List<MemoryAllocationCallbackRegistration>
717 memory_allocation_callbacks_; 679 memory_allocation_callbacks_;
718 680
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. 681 // Initializes pages in a chunk. Returns the first page address.
793 // This function and GetChunkId() are provided for the mark-compact 682 // This function and GetChunkId() are provided for the mark-compact
794 // collector to rebuild page headers in the from space, which is 683 // collector to rebuild page headers in the from space, which is
795 // used as a marking stack and its page headers are destroyed. 684 // used as a marking stack and its page headers are destroyed.
796 static Page* InitializePagesInChunk(int chunk_id, int pages_in_chunk, 685 static Page* InitializePagesInChunk(int chunk_id, int pages_in_chunk,
797 PagedSpace* owner); 686 PagedSpace* owner);
798 687
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 }; 688 };
805 689
806 690
807 // ----------------------------------------------------------------------------- 691 // -----------------------------------------------------------------------------
808 // Interface for heap object iterator to be implemented by all object space 692 // Interface for heap object iterator to be implemented by all object space
809 // object iterators. 693 // object iterators.
810 // 694 //
811 // NOTE: The space specific object iterators also implements the own next() 695 // NOTE: The space specific object iterators also implements the own next()
812 // method which is used to avoid using virtual functions 696 // method which is used to avoid using virtual functions
813 // iterating a specific space. 697 // 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 800 // change between constructing the iterator and iterating the last
917 // page. 801 // page.
918 // 802 //
919 // (3) The space should not shrink during iteration, otherwise the 803 // (3) The space should not shrink during iteration, otherwise the
920 // iterator will return deallocated pages. 804 // iterator will return deallocated pages.
921 805
922 class PageIterator BASE_EMBEDDED { 806 class PageIterator BASE_EMBEDDED {
923 public: 807 public:
924 enum Mode { 808 enum Mode {
925 PAGES_IN_USE, 809 PAGES_IN_USE,
926 PAGES_USED_BY_MC,
927 ALL_PAGES 810 ALL_PAGES
928 }; 811 };
929 812
930 PageIterator(PagedSpace* space, Mode mode); 813 PageIterator(PagedSpace* space, Mode mode);
931 814
932 inline bool has_next(); 815 inline bool has_next();
933 inline Page* next(); 816 inline Page* next();
934 817
935 private: 818 private:
936 PagedSpace* space_; 819 PagedSpace* space_;
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
1051 PagedSpace(intptr_t max_capacity, 934 PagedSpace(intptr_t max_capacity,
1052 AllocationSpace id, 935 AllocationSpace id,
1053 Executability executable); 936 Executability executable);
1054 937
1055 virtual ~PagedSpace() {} 938 virtual ~PagedSpace() {}
1056 939
1057 // Set up the space using the given address range of virtual memory (from 940 // 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 941 // 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 942 // addresses is not big enough to contain a single page-aligned page, a
1060 // fresh chunk will be allocated. 943 // fresh chunk will be allocated.
1061 bool Setup(Address start, size_t size); 944 bool Setup();
1062 945
1063 // Returns true if the space has been successfully set up and not 946 // Returns true if the space has been successfully set up and not
1064 // subsequently torn down. 947 // subsequently torn down.
1065 bool HasBeenSetup(); 948 bool HasBeenSetup();
1066 949
1067 // Cleans up the space, frees all pages in this space except those belonging 950 // Cleans up the space, frees all pages in this space except those belonging
1068 // to the initial chunk, uncommits addresses in the initial chunk. 951 // to the initial chunk, uncommits addresses in the initial chunk.
1069 void TearDown(); 952 void TearDown();
1070 953
1071 // Checks whether an object/address is in this space. 954 // Checks whether an object/address is in this space.
1072 inline bool Contains(Address a); 955 inline bool Contains(Address a);
1073 bool Contains(HeapObject* o) { return Contains(o->address()); } 956 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 957
1077 // Given an address occupied by a live object, return that object if it is 958 // 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 959 // 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 960 // 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. 961 // linear in the number of objects in the page. It may be slow.
1081 MUST_USE_RESULT MaybeObject* FindObject(Address addr); 962 MUST_USE_RESULT MaybeObject* FindObject(Address addr);
1082 963
1083 // Checks whether page is currently in use by this space. 964 // Checks whether page is currently in use by this space.
1084 bool IsUsed(Page* page); 965 bool IsUsed(Page* page);
1085 966
1086 void MarkAllPagesClean();
1087
1088 // Prepares for a mark-compact GC. 967 // Prepares for a mark-compact GC.
1089 virtual void PrepareForMarkCompact(bool will_compact); 968 virtual void PrepareForMarkCompact(bool will_compact);
1090 969
1091 // The top of allocation in a page in this space. Undefined if page is unused. 970 // The top of allocation in a page in this space. Undefined if page is unused.
1092 Address PageAllocationTop(Page* page) { 971 Address PageAllocationTop(Page* page) {
1093 return page == TopPageOf(allocation_info_) ? top() 972 return page == TopPageOf(allocation_info_) ? top()
1094 : PageAllocationLimit(page); 973 : PageAllocationLimit(page);
1095 } 974 }
1096 975
1097 // The limit of allocation for a page in this space. 976 // 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. 1001 // Returns the address of the first object in this space.
1123 Address bottom() { return first_page_->ObjectAreaStart(); } 1002 Address bottom() { return first_page_->ObjectAreaStart(); }
1124 1003
1125 // Returns the allocation pointer in this space. 1004 // Returns the allocation pointer in this space.
1126 Address top() { return allocation_info_.top; } 1005 Address top() { return allocation_info_.top; }
1127 1006
1128 // Allocate the requested number of bytes in the space if possible, return a 1007 // Allocate the requested number of bytes in the space if possible, return a
1129 // failure object if not. 1008 // failure object if not.
1130 MUST_USE_RESULT inline MaybeObject* AllocateRaw(int size_in_bytes); 1009 MUST_USE_RESULT inline MaybeObject* AllocateRaw(int size_in_bytes);
1131 1010
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); 1011 virtual bool ReserveSpace(int bytes);
1137 1012
1138 // Used by ReserveSpace. 1013 // Used by ReserveSpace.
1139 virtual void PutRestOfCurrentPageOnFreeList(Page* current_page) = 0; 1014 virtual void PutRestOfCurrentPageOnFreeList(Page* current_page) = 0;
1140 1015
1141 // Free all pages in range from prev (exclusive) to last (inclusive). 1016 // Free all pages in range from prev (exclusive) to last (inclusive).
1142 // Freed pages are moved to the end of page list. 1017 // Freed pages are moved to the end of page list.
1143 void FreePages(Page* prev, Page* last); 1018 void FreePages(Page* prev, Page* last);
1144 1019
1145 // Deallocates a block. 1020 // Deallocates a block.
1146 virtual void DeallocateBlock(Address start, 1021 virtual void DeallocateBlock(Address start,
1147 int size_in_bytes, 1022 int size_in_bytes,
1148 bool add_to_freelist) = 0; 1023 bool add_to_freelist) = 0;
1149 1024
1150 // Set space allocation info. 1025 // Set space allocation info.
1151 void SetTop(Address top) { 1026 void SetTop(Address top) {
1152 allocation_info_.top = top; 1027 allocation_info_.top = top;
1153 allocation_info_.limit = PageAllocationLimit(Page::FromAllocationTop(top)); 1028 allocation_info_.limit = PageAllocationLimit(Page::FromAllocationTop(top));
1154 } 1029 }
1155 1030
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. 1031 // Releases half of unused pages.
1177 void Shrink(); 1032 void Shrink();
1178 1033
1179 // Ensures that the capacity is at least 'capacity'. Returns false on failure. 1034 // Ensures that the capacity is at least 'capacity'. Returns false on failure.
1180 bool EnsureCapacity(int capacity); 1035 bool EnsureCapacity(int capacity);
1181 1036
1182 #ifdef ENABLE_HEAP_PROTECTION 1037 #ifdef ENABLE_HEAP_PROTECTION
1183 // Protect/unprotect the space by marking it read-only/writable. 1038 // Protect/unprotect the space by marking it read-only/writable.
1184 void Protect(); 1039 void Protect();
1185 void Unprotect(); 1040 void Unprotect();
(...skipping 12 matching lines...) Expand all
1198 1053
1199 // Report code object related statistics 1054 // Report code object related statistics
1200 void CollectCodeStatistics(); 1055 void CollectCodeStatistics();
1201 static void ReportCodeStatistics(); 1056 static void ReportCodeStatistics();
1202 static void ResetCodeStatistics(); 1057 static void ResetCodeStatistics();
1203 #endif 1058 #endif
1204 1059
1205 // Returns the page of the allocation pointer. 1060 // Returns the page of the allocation pointer.
1206 Page* AllocationTopPage() { return TopPageOf(allocation_info_); } 1061 Page* AllocationTopPage() { return TopPageOf(allocation_info_); }
1207 1062
1208 void RelinkPageListInChunkOrder(bool deallocate_blocks);
1209
1210 protected: 1063 protected:
1211 // Maximum capacity of this space. 1064 // Maximum capacity of this space.
1212 intptr_t max_capacity_; 1065 intptr_t max_capacity_;
1213 1066
1214 // Accounting information for this space. 1067 // Accounting information for this space.
1215 AllocationStats accounting_stats_; 1068 AllocationStats accounting_stats_;
1216 1069
1217 // The first page in this space. 1070 // The first page in this space.
1218 Page* first_page_; 1071 Page* first_page_;
1219 1072
1220 // The last page in this space. Initially set in Setup, updated in 1073 // The last page in this space. Initially set in Setup, updated in
1221 // Expand and Shrink. 1074 // Expand and Shrink.
1222 Page* last_page_; 1075 Page* last_page_;
1223 1076
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. 1077 // Normal allocation information.
1229 AllocationInfo allocation_info_; 1078 AllocationInfo allocation_info_;
1230 1079
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 1080 // Bytes of each page that cannot be allocated. Possibly non-zero
1235 // for pages in spaces with only fixed-size objects. Always zero 1081 // for pages in spaces with only fixed-size objects. Always zero
1236 // for pages in spaces with variable sized objects (those pages are 1082 // for pages in spaces with variable sized objects (those pages are
1237 // padded with free-list nodes). 1083 // padded with free-list nodes).
1238 int page_extra_; 1084 int page_extra_;
1239 1085
1240 // Sets allocation pointer to a page bottom. 1086 // Sets allocation pointer to a page bottom.
1241 static void SetAllocationInfo(AllocationInfo* alloc_info, Page* p); 1087 static void SetAllocationInfo(AllocationInfo* alloc_info, Page* p);
1242 1088
1243 // Returns the top page specified by an allocation info structure. 1089 // Returns the top page specified by an allocation info structure.
1244 static Page* TopPageOf(AllocationInfo alloc_info) { 1090 static Page* TopPageOf(AllocationInfo alloc_info) {
1245 return Page::FromAllocationTop(alloc_info.limit); 1091 return Page::FromAllocationTop(alloc_info.limit);
1246 } 1092 }
1247 1093
1248 int CountPagesToTop() { 1094 int CountPagesToTop() {
1249 Page* p = Page::FromAllocationTop(allocation_info_.top); 1095 Page* p = Page::FromAllocationTop(allocation_info_.top);
1250 PageIterator it(this, PageIterator::ALL_PAGES); 1096 PageIterator it(this, PageIterator::ALL_PAGES);
1251 int counter = 1; 1097 int counter = 1;
1252 while (it.has_next()) { 1098 while (it.has_next()) {
1253 if (it.next() == p) return counter; 1099 if (it.next() == p) return counter;
1254 counter++; 1100 counter++;
1255 } 1101 }
1256 UNREACHABLE(); 1102 UNREACHABLE();
1257 return -1; 1103 return -1;
1258 } 1104 }
1259 1105
1260 // Expands the space by allocating a fixed number of pages. Returns false if 1106 // 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 1107 // it cannot allocate requested number of pages from OS.
1262 // pages are append to the last_page; 1108 bool Expand();
1263 bool Expand(Page* last_page);
1264 1109
1265 // Generic fast case allocation function that tries linear allocation in 1110 // Generic fast case allocation function that tries linear allocation in
1266 // the top page of 'alloc_info'. Returns NULL on failure. 1111 // the top page of 'alloc_info'. Returns NULL on failure.
1267 inline HeapObject* AllocateLinearly(AllocationInfo* alloc_info, 1112 inline HeapObject* AllocateLinearly(AllocationInfo* alloc_info,
1268 int size_in_bytes); 1113 int size_in_bytes);
1269 1114
1270 // During normal allocation or deserialization, roll to the next page in 1115 // During normal allocation or deserialization, roll to the next page in
1271 // the space (there is assumed to be one) and allocate there. This 1116 // the space (there is assumed to be one) and allocate there. This
1272 // function is space-dependent. 1117 // function is space-dependent.
1273 virtual HeapObject* AllocateInNextPage(Page* current_page, 1118 virtual HeapObject* AllocateInNextPage(Page* current_page,
1274 int size_in_bytes) = 0; 1119 int size_in_bytes) = 0;
1275 1120
1276 // Slow path of AllocateRaw. This function is space-dependent. 1121 // Slow path of AllocateRaw. This function is space-dependent.
1277 MUST_USE_RESULT virtual HeapObject* SlowAllocateRaw(int size_in_bytes) = 0; 1122 MUST_USE_RESULT virtual HeapObject* SlowAllocateRaw(int size_in_bytes) = 0;
1278 1123
1279 // Slow path of MCAllocateRaw.
1280 MUST_USE_RESULT HeapObject* SlowMCAllocateRaw(int size_in_bytes);
1281
1282 #ifdef DEBUG 1124 #ifdef DEBUG
1283 // Returns the number of total pages in this space. 1125 // Returns the number of total pages in this space.
1284 int CountTotalPages(); 1126 int CountTotalPages();
1285 #endif 1127 #endif
1286 private: 1128 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; 1129 friend class PageIterator;
1292 }; 1130 };
1293 1131
1294 1132
1295 #if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING) 1133 #if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING)
1296 class NumberAndSizeInfo BASE_EMBEDDED { 1134 class NumberAndSizeInfo BASE_EMBEDDED {
1297 public: 1135 public:
1298 NumberAndSizeInfo() : number_(0), bytes_(0) {} 1136 NumberAndSizeInfo() : number_(0), bytes_(0) {}
1299 1137
1300 int number() const { return number_; } 1138 int number() const { return number_; }
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after
1504 // 1342 //
1505 // The new space consists of a contiguous pair of semispaces. It simply 1343 // The new space consists of a contiguous pair of semispaces. It simply
1506 // forwards most functions to the appropriate semispace. 1344 // forwards most functions to the appropriate semispace.
1507 1345
1508 class NewSpace : public Space { 1346 class NewSpace : public Space {
1509 public: 1347 public:
1510 // Constructor. 1348 // Constructor.
1511 NewSpace() : Space(NEW_SPACE, NOT_EXECUTABLE) {} 1349 NewSpace() : Space(NEW_SPACE, NOT_EXECUTABLE) {}
1512 1350
1513 // Sets up the new space using the given chunk. 1351 // Sets up the new space using the given chunk.
1514 bool Setup(Address start, int size); 1352 bool Setup(int max_semispace_size);
1515 1353
1516 // Tears down the space. Heap memory was not allocated by the space, so it 1354 // Tears down the space. Heap memory was not allocated by the space, so it
1517 // is not deallocated here. 1355 // is not deallocated here.
1518 void TearDown(); 1356 void TearDown();
1519 1357
1520 // True if the space has been set up but not torn down. 1358 // True if the space has been set up but not torn down.
1521 bool HasBeenSetup() { 1359 bool HasBeenSetup() {
1522 return to_space_.HasBeenSetup() && from_space_.HasBeenSetup(); 1360 return to_space_.HasBeenSetup() && from_space_.HasBeenSetup();
1523 } 1361 }
1524 1362
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
1592 uintptr_t mask() { return address_mask_; } 1430 uintptr_t mask() { return address_mask_; }
1593 1431
1594 // The allocation top and limit addresses. 1432 // The allocation top and limit addresses.
1595 Address* allocation_top_address() { return &allocation_info_.top; } 1433 Address* allocation_top_address() { return &allocation_info_.top; }
1596 Address* allocation_limit_address() { return &allocation_info_.limit; } 1434 Address* allocation_limit_address() { return &allocation_info_.limit; }
1597 1435
1598 MUST_USE_RESULT MaybeObject* AllocateRaw(int size_in_bytes) { 1436 MUST_USE_RESULT MaybeObject* AllocateRaw(int size_in_bytes) {
1599 return AllocateRawInternal(size_in_bytes, &allocation_info_); 1437 return AllocateRawInternal(size_in_bytes, &allocation_info_);
1600 } 1438 }
1601 1439
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. 1440 // Reset the allocation pointer to the beginning of the active semispace.
1609 void ResetAllocationInfo(); 1441 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 1442
1617 // Get the extent of the inactive semispace (for use as a marking stack). 1443 // Get the extent of the inactive semispace (for use as a marking stack).
1618 Address FromSpaceLow() { return from_space_.low(); } 1444 Address FromSpaceLow() { return from_space_.low(); }
1619 Address FromSpaceHigh() { return from_space_.high(); } 1445 Address FromSpaceHigh() { return from_space_.high(); }
1620 1446
1621 // Get the extent of the active semispace (to sweep newly copied objects 1447 // Get the extent of the active semispace (to sweep newly copied objects
1622 // during a scavenge collection). 1448 // during a scavenge collection).
1623 Address ToSpaceLow() { return to_space_.low(); } 1449 Address ToSpaceLow() { return to_space_.low(); }
1624 Address ToSpaceHigh() { return to_space_.high(); } 1450 Address ToSpaceHigh() { return to_space_.high(); }
1625 1451
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
1680 if (from_space_.is_committed()) return true; 1506 if (from_space_.is_committed()) return true;
1681 return from_space_.Commit(); 1507 return from_space_.Commit();
1682 } 1508 }
1683 1509
1684 bool UncommitFromSpace() { 1510 bool UncommitFromSpace() {
1685 if (!from_space_.is_committed()) return true; 1511 if (!from_space_.is_committed()) return true;
1686 return from_space_.Uncommit(); 1512 return from_space_.Uncommit();
1687 } 1513 }
1688 1514
1689 private: 1515 private:
1516 Address chunk_base_;
1517 uintptr_t chunk_size_;
1518
1690 // The semispaces. 1519 // The semispaces.
1691 SemiSpace to_space_; 1520 SemiSpace to_space_;
1692 SemiSpace from_space_; 1521 SemiSpace from_space_;
1693 1522
1694 // Start address and bit mask for containment testing. 1523 // Start address and bit mask for containment testing.
1695 Address start_; 1524 Address start_;
1696 uintptr_t address_mask_; 1525 uintptr_t address_mask_;
1697 uintptr_t object_mask_; 1526 uintptr_t object_mask_;
1698 uintptr_t object_expected_; 1527 uintptr_t object_expected_;
1699 1528
1700 // Allocation pointer and limit for normal allocation and allocation during 1529 // Allocation pointer and limit for normal allocation and allocation during
1701 // mark-compact collection. 1530 // mark-compact collection.
1702 AllocationInfo allocation_info_; 1531 AllocationInfo allocation_info_;
1703 AllocationInfo mc_forwarding_info_;
1704 1532
1705 #if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING) 1533 #if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING)
1706 HistogramInfo* allocated_histogram_; 1534 HistogramInfo* allocated_histogram_;
1707 HistogramInfo* promoted_histogram_; 1535 HistogramInfo* promoted_histogram_;
1708 #endif 1536 #endif
1709 1537
1710 // Implementation of AllocateRaw and MCAllocateRaw. 1538 // Implementation of AllocateRaw and MCAllocateRaw.
1711 MUST_USE_RESULT inline MaybeObject* AllocateRawInternal( 1539 MUST_USE_RESULT inline MaybeObject* AllocateRawInternal(
1712 int size_in_bytes, 1540 int size_in_bytes,
1713 AllocationInfo* alloc_info); 1541 AllocationInfo* alloc_info);
(...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after
1939 } 1767 }
1940 1768
1941 virtual void DeallocateBlock(Address start, 1769 virtual void DeallocateBlock(Address start,
1942 int size_in_bytes, 1770 int size_in_bytes,
1943 bool add_to_freelist); 1771 bool add_to_freelist);
1944 1772
1945 // Prepare for full garbage collection. Resets the relocation pointer and 1773 // Prepare for full garbage collection. Resets the relocation pointer and
1946 // clears the free list. 1774 // clears the free list.
1947 virtual void PrepareForMarkCompact(bool will_compact); 1775 virtual void PrepareForMarkCompact(bool will_compact);
1948 1776
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); 1777 virtual void PutRestOfCurrentPageOnFreeList(Page* current_page);
1954 1778
1955 void MarkFreeListNodes() { free_list_.MarkNodes(); } 1779 void MarkFreeListNodes() { free_list_.MarkNodes(); }
1956 1780
1957 #ifdef DEBUG 1781 #ifdef DEBUG
1958 // Reports statistics for the space 1782 // Reports statistics for the space
1959 void ReportStatistics(); 1783 void ReportStatistics();
1960 #endif 1784 #endif
1961 1785
1962 protected: 1786 protected:
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
2005 void Free(Address start, bool add_to_freelist) { 1829 void Free(Address start, bool add_to_freelist) {
2006 if (add_to_freelist) { 1830 if (add_to_freelist) {
2007 free_list_.Free(start); 1831 free_list_.Free(start);
2008 } 1832 }
2009 accounting_stats_.DeallocateBytes(object_size_in_bytes_); 1833 accounting_stats_.DeallocateBytes(object_size_in_bytes_);
2010 } 1834 }
2011 1835
2012 // Prepares for a mark-compact GC. 1836 // Prepares for a mark-compact GC.
2013 virtual void PrepareForMarkCompact(bool will_compact); 1837 virtual void PrepareForMarkCompact(bool will_compact);
2014 1838
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); 1839 virtual void PutRestOfCurrentPageOnFreeList(Page* current_page);
2020 1840
2021 virtual void DeallocateBlock(Address start, 1841 virtual void DeallocateBlock(Address start,
2022 int size_in_bytes, 1842 int size_in_bytes,
2023 bool add_to_freelist); 1843 bool add_to_freelist);
2024 1844
2025 void MarkFreeListNodes() { free_list_.MarkNodes(); } 1845 void MarkFreeListNodes() { free_list_.MarkNodes(); }
2026 1846
2027 #ifdef DEBUG 1847 #ifdef DEBUG
2028 // Reports statistic info of the space 1848 // Reports statistic info of the space
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
2168 }; 1988 };
2169 1989
2170 1990
2171 // ----------------------------------------------------------------------------- 1991 // -----------------------------------------------------------------------------
2172 // Large objects ( > Page::kMaxHeapObjectSize ) are allocated and managed by 1992 // Large objects ( > Page::kMaxHeapObjectSize ) are allocated and managed by
2173 // the large object space. A large object is allocated from OS heap with 1993 // the large object space. A large object is allocated from OS heap with
2174 // extra padding bytes (Page::kPageSize + Page::kObjectStartOffset). 1994 // extra padding bytes (Page::kPageSize + Page::kObjectStartOffset).
2175 // A large object always starts at Page::kObjectStartOffset to a page. 1995 // A large object always starts at Page::kObjectStartOffset to a page.
2176 // Large objects do not move during garbage collections. 1996 // Large objects do not move during garbage collections.
2177 1997
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 { 1998 class LargeObjectSpace : public Space {
2233 public: 1999 public:
2234 explicit LargeObjectSpace(AllocationSpace id); 2000 explicit LargeObjectSpace(AllocationSpace id);
2235 virtual ~LargeObjectSpace() {} 2001 virtual ~LargeObjectSpace() {}
2236 2002
2237 // Initializes internal data structures. 2003 // Initializes internal data structures.
2238 bool Setup(); 2004 bool Setup();
2239 2005
2240 // Releases internal resources, frees objects in this space. 2006 // Releases internal resources, frees objects in this space.
2241 void TearDown(); 2007 void TearDown();
2242 2008
2243 // Allocates a (non-FixedArray, non-Code) large object. 2009 // Allocates a (non-FixedArray, non-Code) large object.
2244 MUST_USE_RESULT MaybeObject* AllocateRaw(int size_in_bytes); 2010 MUST_USE_RESULT MaybeObject* AllocateRaw(int size_in_bytes);
2245 // Allocates a large Code object. 2011 // Allocates a large Code object.
2246 MUST_USE_RESULT MaybeObject* AllocateRawCode(int size_in_bytes); 2012 MUST_USE_RESULT MaybeObject* AllocateRawCode(int size_in_bytes);
2247 // Allocates a large FixedArray. 2013 // Allocates a large FixedArray.
2248 MUST_USE_RESULT MaybeObject* AllocateRawFixedArray(int size_in_bytes); 2014 MUST_USE_RESULT MaybeObject* AllocateRawFixedArray(int size_in_bytes);
2249 2015
2016 static intptr_t ObjectSizeFor(intptr_t chunk_size) {
2017 if (chunk_size <= (Page::kPageSize + Page::kObjectStartOffset)) return 0;
2018 return chunk_size - Page::kPageSize - Page::kObjectStartOffset;
2019 }
2020
2250 // Available bytes for objects in this space. 2021 // Available bytes for objects in this space.
2251 intptr_t Available() { 2022 intptr_t Available() {
2252 return LargeObjectChunk::ObjectSizeFor(MemoryAllocator::Available()); 2023 return ObjectSizeFor(MemoryAllocator::Available());
2253 } 2024 }
2254 2025
2255 virtual intptr_t Size() { 2026 virtual intptr_t Size() {
2256 return size_; 2027 return size_;
2257 } 2028 }
2258 2029
2259 virtual intptr_t SizeOfObjects() { 2030 virtual intptr_t SizeOfObjects() {
2260 return objects_size_; 2031 return objects_size_;
2261 } 2032 }
2262 2033
2263 int PageCount() { 2034 int PageCount() {
2264 return page_count_; 2035 return page_count_;
2265 } 2036 }
2266 2037
2267 // Finds an object for a given address, returns Failure::Exception() 2038 // Finds an object for a given address, returns Failure::Exception()
2268 // if it is not found. The function iterates through all objects in this 2039 // if it is not found. The function iterates through all objects in this
2269 // space, may be slow. 2040 // space, may be slow.
2270 MaybeObject* FindObject(Address a); 2041 MaybeObject* FindObject(Address a);
2271 2042
2272 // Finds a large object page containing the given pc, returns NULL 2043 // Finds a large object page containing the given pc, returns NULL
2273 // if such a page doesn't exist. 2044 // if such a page doesn't exist.
2274 LargeObjectChunk* FindChunkContainingPc(Address pc); 2045 LargePage* FindPageContainingPc(Address pc);
2275 2046
2276 // Iterates objects covered by dirty regions. 2047 // Iterates objects covered by dirty regions.
2277 void IterateDirtyRegions(ObjectSlotCallback func); 2048 void IterateDirtyRegions(ObjectSlotCallback func);
2278 2049
2279 // Frees unmarked objects. 2050 // Frees unmarked objects.
2280 void FreeUnmarkedObjects(); 2051 void FreeUnmarkedObjects();
2281 2052
2282 // Checks whether a heap object is in this space; O(1). 2053 // Checks whether a heap object is in this space; O(1).
2283 bool Contains(HeapObject* obj); 2054 bool Contains(HeapObject* obj);
2284 2055
2285 // Checks whether the space is empty. 2056 // Checks whether the space is empty.
2286 bool IsEmpty() { return first_chunk_ == NULL; } 2057 bool IsEmpty() { return first_page_ == NULL; }
2287 2058
2288 // See the comments for ReserveSpace in the Space class. This has to be 2059 // 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 2060 // called after ReserveSpace has been called on the paged spaces, since they
2290 // may use some memory, leaving less for large objects. 2061 // may use some memory, leaving less for large objects.
2291 virtual bool ReserveSpace(int bytes); 2062 virtual bool ReserveSpace(int bytes);
2292 2063
2293 #ifdef ENABLE_HEAP_PROTECTION 2064 #ifdef ENABLE_HEAP_PROTECTION
2294 // Protect/unprotect the space by marking it read-only/writable. 2065 // Protect/unprotect the space by marking it read-only/writable.
2295 void Protect(); 2066 void Protect();
2296 void Unprotect(); 2067 void Unprotect();
2297 #endif 2068 #endif
2298 2069
2299 #ifdef DEBUG 2070 #ifdef DEBUG
2300 virtual void Verify(); 2071 virtual void Verify();
2301 virtual void Print(); 2072 virtual void Print();
2302 void ReportStatistics(); 2073 void ReportStatistics();
2303 void CollectCodeStatistics(); 2074 void CollectCodeStatistics();
2304 #endif 2075 #endif
2305 // Checks whether an address is in the object area in this space. It 2076 // Checks whether an address is in the object area in this space. It
2306 // iterates all objects in the space. May be slow. 2077 // iterates all objects in the space. May be slow.
2307 bool SlowContains(Address addr) { return !FindObject(addr)->IsFailure(); } 2078 bool SlowContains(Address addr) { return !FindObject(addr)->IsFailure(); }
2308 2079
2309 private: 2080 private:
2310 // The head of the linked list of large object chunks. 2081 // The head of the linked list of large object chunks.
2311 LargeObjectChunk* first_chunk_; 2082 LargePage* first_page_;
2312 intptr_t size_; // allocated bytes 2083 intptr_t size_; // allocated bytes
2313 int page_count_; // number of chunks 2084 int page_count_; // number of chunks
2314 intptr_t objects_size_; // size of objects 2085 intptr_t objects_size_; // size of objects
2315 2086
2316 // Shared implementation of AllocateRaw, AllocateRawCode and 2087 // Shared implementation of AllocateRaw, AllocateRawCode and
2317 // AllocateRawFixedArray. 2088 // AllocateRawFixedArray.
2318 MUST_USE_RESULT MaybeObject* AllocateRawInternal(int requested_size, 2089 MUST_USE_RESULT MaybeObject* AllocateRawInternal(int object_size,
2319 int object_size,
2320 Executability executable); 2090 Executability executable);
2321 2091
2322 friend class LargeObjectIterator; 2092 friend class LargeObjectIterator;
2323 2093
2324 public: 2094 public:
2325 TRACK_MEMORY("LargeObjectSpace") 2095 TRACK_MEMORY("LargeObjectSpace")
2326 }; 2096 };
2327 2097
2328 2098
2329 class LargeObjectIterator: public ObjectIterator { 2099 class LargeObjectIterator: public ObjectIterator {
2330 public: 2100 public:
2331 explicit LargeObjectIterator(LargeObjectSpace* space); 2101 explicit LargeObjectIterator(LargeObjectSpace* space);
2332 LargeObjectIterator(LargeObjectSpace* space, HeapObjectCallback size_func); 2102 LargeObjectIterator(LargeObjectSpace* space, HeapObjectCallback size_func);
2333 2103
2334 HeapObject* next(); 2104 HeapObject* next();
2335 2105
2336 // implementation of ObjectIterator. 2106 // implementation of ObjectIterator.
2337 virtual HeapObject* next_object() { return next(); } 2107 virtual HeapObject* next_object() { return next(); }
2338 2108
2339 private: 2109 private:
2340 LargeObjectChunk* current_; 2110 LargePage* current_;
2341 HeapObjectCallback size_func_; 2111 HeapObjectCallback size_func_;
2342 }; 2112 };
2343 2113
2344 2114
2345 } } // namespace v8::internal 2115 } } // namespace v8::internal
2346 2116
2347 #endif // V8_SPACES_H_ 2117 #endif // V8_SPACES_H_
OLDNEW
« no previous file with comments | « src/platform-linux.cc ('k') | src/spaces.cc » ('j') | src/spaces.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698