1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifndef V8_HEAP_SPACES_INL_H_
6 #define V8_HEAP_SPACES_INL_H_
7
8 #include "src/heap/incremental-marking.h"
9 #include "src/heap/spaces.h"
10 #include "src/isolate.h"
11 #include "src/msan.h"
12 #include "src/profiler/heap-profiler.h"
13 #include "src/v8memory.h"
14
15 namespace v8 {
16 namespace internal {
17
18 template <class PAGE_TYPE>
19 PageIteratorImpl<PAGE_TYPE>& PageIteratorImpl<PAGE_TYPE>::operator++() {
20 p_ = p_->next_page();
21 return *this;
22 }
23
24 template <class PAGE_TYPE>
25 PageIteratorImpl<PAGE_TYPE> PageIteratorImpl<PAGE_TYPE>::operator++(int) {
26 PageIteratorImpl<PAGE_TYPE> tmp(*this);
27 operator++();
28 return tmp;
29 }
30
PageRange(Address start,Address limit)31 PageRange::PageRange(Address start, Address limit)
32 : begin_(Page::FromAddress(start)),
33 end_(Page::FromAllocationAreaAddress(limit)->next_page()) {
34 #ifdef DEBUG
35 if (begin_->InNewSpace()) {
36 SemiSpace::AssertValidRange(start, limit);
37 }
38 #endif // DEBUG
39 }
40
41 // -----------------------------------------------------------------------------
42 // SemiSpaceIterator
43
Next()44 HeapObject* SemiSpaceIterator::Next() {
45 while (current_ != limit_) {
46 if (Page::IsAlignedToPageSize(current_)) {
47 Page* page = Page::FromAllocationAreaAddress(current_);
48 page = page->next_page();
49 DCHECK(!page->is_anchor());
50 current_ = page->area_start();
51 if (current_ == limit_) return nullptr;
52 }
53 HeapObject* object = HeapObject::FromAddress(current_);
54 current_ += object->Size();
55 if (!object->IsFiller()) {
56 return object;
57 }
58 }
59 return nullptr;
60 }
61
62 // -----------------------------------------------------------------------------
63 // HeapObjectIterator
64
Next()65 HeapObject* HeapObjectIterator::Next() {
66 do {
67 HeapObject* next_obj = FromCurrentPage();
68 if (next_obj != nullptr) return next_obj;
69 } while (AdvanceToNextPage());
70 return nullptr;
71 }
72
FromCurrentPage()73 HeapObject* HeapObjectIterator::FromCurrentPage() {
74 while (cur_addr_ != cur_end_) {
75 if (cur_addr_ == space_->top() && cur_addr_ != space_->limit()) {
76 cur_addr_ = space_->limit();
77 continue;
78 }
79 HeapObject* obj = HeapObject::FromAddress(cur_addr_);
80 const int obj_size = obj->Size();
81 cur_addr_ += obj_size;
82 DCHECK_LE(cur_addr_, cur_end_);
83 if (!obj->IsFiller()) {
84 if (obj->IsCode()) {
85 DCHECK_EQ(space_, space_->heap()->code_space());
86 DCHECK_CODEOBJECT_SIZE(obj_size, space_);
87 } else {
88 DCHECK_OBJECT_SIZE(obj_size);
89 }
90 return obj;
91 }
92 }
93 return nullptr;
94 }
95
96 // -----------------------------------------------------------------------------
97 // MemoryAllocator
98
99 #ifdef ENABLE_HEAP_PROTECTION
100
Protect(Address start,size_t size)101 void MemoryAllocator::Protect(Address start, size_t size) {
102 base::OS::Protect(start, size);
103 }
104
105
Unprotect(Address start,size_t size,Executability executable)106 void MemoryAllocator::Unprotect(Address start, size_t size,
107 Executability executable) {
108 base::OS::Unprotect(start, size, executable);
109 }
110
111
ProtectChunkFromPage(Page * page)112 void MemoryAllocator::ProtectChunkFromPage(Page* page) {
113 int id = GetChunkId(page);
114 base::OS::Protect(chunks_[id].address(), chunks_[id].size());
115 }
116
117
UnprotectChunkFromPage(Page * page)118 void MemoryAllocator::UnprotectChunkFromPage(Page* page) {
119 int id = GetChunkId(page);
120 base::OS::Unprotect(chunks_[id].address(), chunks_[id].size(),
121 chunks_[id].owner()->executable() == EXECUTABLE);
122 }
123
124 #endif
125
126 // -----------------------------------------------------------------------------
127 // SemiSpace
128
Contains(HeapObject * o)129 bool SemiSpace::Contains(HeapObject* o) {
130 return id_ == kToSpace
131 ? MemoryChunk::FromAddress(o->address())->InToSpace()
132 : MemoryChunk::FromAddress(o->address())->InFromSpace();
133 }
134
Contains(Object * o)135 bool SemiSpace::Contains(Object* o) {
136 return o->IsHeapObject() && Contains(HeapObject::cast(o));
137 }
138
ContainsSlow(Address a)139 bool SemiSpace::ContainsSlow(Address a) {
140 for (Page* p : *this) {
141 if (p == MemoryChunk::FromAddress(a)) return true;
142 }
143 return false;
144 }
145
146 // --------------------------------------------------------------------------
147 // NewSpace
148
Contains(HeapObject * o)149 bool NewSpace::Contains(HeapObject* o) {
150 return MemoryChunk::FromAddress(o->address())->InNewSpace();
151 }
152
Contains(Object * o)153 bool NewSpace::Contains(Object* o) {
154 return o->IsHeapObject() && Contains(HeapObject::cast(o));
155 }
156
ContainsSlow(Address a)157 bool NewSpace::ContainsSlow(Address a) {
158 return from_space_.ContainsSlow(a) || to_space_.ContainsSlow(a);
159 }
160
ToSpaceContainsSlow(Address a)161 bool NewSpace::ToSpaceContainsSlow(Address a) {
162 return to_space_.ContainsSlow(a);
163 }
164
FromSpaceContainsSlow(Address a)165 bool NewSpace::FromSpaceContainsSlow(Address a) {
166 return from_space_.ContainsSlow(a);
167 }
168
ToSpaceContains(Object * o)169 bool NewSpace::ToSpaceContains(Object* o) { return to_space_.Contains(o); }
FromSpaceContains(Object * o)170 bool NewSpace::FromSpaceContains(Object* o) { return from_space_.Contains(o); }
171
Initialize(Heap * heap,MemoryChunk * chunk,Executability executable,SemiSpace * owner)172 Page* Page::Initialize(Heap* heap, MemoryChunk* chunk, Executability executable,
173 SemiSpace* owner) {
174 DCHECK_EQ(executable, Executability::NOT_EXECUTABLE);
175 bool in_to_space = (owner->id() != kFromSpace);
176 chunk->SetFlag(in_to_space ? MemoryChunk::IN_TO_SPACE
177 : MemoryChunk::IN_FROM_SPACE);
178 DCHECK(!chunk->IsFlagSet(in_to_space ? MemoryChunk::IN_FROM_SPACE
179 : MemoryChunk::IN_TO_SPACE));
180 Page* page = static_cast<Page*>(chunk);
181 heap->incremental_marking()->SetNewSpacePageFlags(page);
182 page->AllocateLocalTracker();
183 return page;
184 }
185
186 // --------------------------------------------------------------------------
187 // PagedSpace
188
189 template <Page::InitializationMode mode>
Initialize(Heap * heap,MemoryChunk * chunk,Executability executable,PagedSpace * owner)190 Page* Page::Initialize(Heap* heap, MemoryChunk* chunk, Executability executable,
191 PagedSpace* owner) {
192 Page* page = reinterpret_cast<Page*>(chunk);
193 DCHECK(page->area_size() <= kAllocatableMemory);
194 DCHECK(chunk->owner() == owner);
195
196 owner->IncreaseCapacity(page->area_size());
197 heap->incremental_marking()->SetOldSpacePageFlags(chunk);
198
199 // Make sure that categories are initialized before freeing the area.
200 page->InitializeFreeListCategories();
201 // In the case we do not free the memory, we effectively account for the whole
202 // page as allocated memory that cannot be used for further allocations.
203 if (mode == kFreeMemory) {
204 owner->Free(page->area_start(), page->area_size());
205 }
206
207 return page;
208 }
209
ConvertNewToOld(Page * old_page)210 Page* Page::ConvertNewToOld(Page* old_page) {
211 DCHECK(!old_page->is_anchor());
212 DCHECK(old_page->InNewSpace());
213 OldSpace* old_space = old_page->heap()->old_space();
214 old_page->set_owner(old_space);
215 old_page->SetFlags(0, ~0);
216 old_space->AccountCommitted(old_page->size());
217 Page* new_page = Page::Initialize<kDoNotFreeMemory>(
218 old_page->heap(), old_page, NOT_EXECUTABLE, old_space);
219 new_page->InsertAfter(old_space->anchor()->prev_page());
220 return new_page;
221 }
222
InitializeFreeListCategories()223 void Page::InitializeFreeListCategories() {
224 for (int i = kFirstCategory; i < kNumberOfCategories; i++) {
225 categories_[i].Initialize(static_cast<FreeListCategoryType>(i));
226 }
227 }
228
IncrementLiveBytes(HeapObject * object,int by)229 void MemoryChunk::IncrementLiveBytes(HeapObject* object, int by) {
230 MemoryChunk::FromAddress(object->address())->IncrementLiveBytes(by);
231 }
232
ResetLiveBytes()233 void MemoryChunk::ResetLiveBytes() {
234 if (FLAG_trace_live_bytes) {
235 PrintIsolate(heap()->isolate(), "live-bytes: reset page=%p %d->0\n",
236 static_cast<void*>(this), live_byte_count_);
237 }
238 live_byte_count_ = 0;
239 }
240
IncrementLiveBytes(int by)241 void MemoryChunk::IncrementLiveBytes(int by) {
242 if (FLAG_trace_live_bytes) {
243 PrintIsolate(
244 heap()->isolate(), "live-bytes: update page=%p delta=%d %d->%d\n",
245 static_cast<void*>(this), by, live_byte_count_, live_byte_count_ + by);
246 }
247 live_byte_count_ += by;
248 DCHECK_GE(live_byte_count_, 0);
249 DCHECK_LE(static_cast<size_t>(live_byte_count_), size_);
250 }
251
Contains(Address addr)252 bool PagedSpace::Contains(Address addr) {
253 return MemoryChunk::FromAnyPointerAddress(heap(), addr)->owner() == this;
254 }
255
Contains(Object * o)256 bool PagedSpace::Contains(Object* o) {
257 if (!o->IsHeapObject()) return false;
258 Page* p = Page::FromAddress(HeapObject::cast(o)->address());
259 if (!Page::IsValid(p)) return false;
260 return p->owner() == this;
261 }
262
UnlinkFreeListCategories(Page * page)263 void PagedSpace::UnlinkFreeListCategories(Page* page) {
264 DCHECK_EQ(this, page->owner());
265 page->ForAllFreeListCategories([this](FreeListCategory* category) {
266 DCHECK_EQ(free_list(), category->owner());
267 free_list()->RemoveCategory(category);
268 });
269 }
270
RelinkFreeListCategories(Page * page)271 intptr_t PagedSpace::RelinkFreeListCategories(Page* page) {
272 DCHECK_EQ(this, page->owner());
273 intptr_t added = 0;
274 page->ForAllFreeListCategories([&added](FreeListCategory* category) {
275 added += category->available();
276 category->Relink();
277 });
278 DCHECK_EQ(page->AvailableInFreeList(), page->available_in_free_list());
279 return added;
280 }
281
FromAnyPointerAddress(Heap * heap,Address addr)282 MemoryChunk* MemoryChunk::FromAnyPointerAddress(Heap* heap, Address addr) {
283 MemoryChunk* chunk = MemoryChunk::FromAddress(addr);
284 uintptr_t offset = addr - chunk->address();
285 if (offset < MemoryChunk::kHeaderSize || !chunk->HasPageHeader()) {
286 chunk = heap->lo_space()->FindPageThreadSafe(addr);
287 }
288 return chunk;
289 }
290
FromAnyPointerAddress(Heap * heap,Address addr)291 Page* Page::FromAnyPointerAddress(Heap* heap, Address addr) {
292 return static_cast<Page*>(MemoryChunk::FromAnyPointerAddress(heap, addr));
293 }
294
MarkNeverAllocateForTesting()295 void Page::MarkNeverAllocateForTesting() {
296 DCHECK(this->owner()->identity() != NEW_SPACE);
297 DCHECK(!IsFlagSet(NEVER_ALLOCATE_ON_PAGE));
298 SetFlag(NEVER_ALLOCATE_ON_PAGE);
299 reinterpret_cast<PagedSpace*>(owner())->free_list()->EvictFreeListItems(this);
300 }
301
MarkEvacuationCandidate()302 void Page::MarkEvacuationCandidate() {
303 DCHECK(!IsFlagSet(NEVER_EVACUATE));
304 DCHECK_NULL(old_to_old_slots_);
305 DCHECK_NULL(typed_old_to_old_slots_);
306 SetFlag(EVACUATION_CANDIDATE);
307 reinterpret_cast<PagedSpace*>(owner())->free_list()->EvictFreeListItems(this);
308 }
309
ClearEvacuationCandidate()310 void Page::ClearEvacuationCandidate() {
311 if (!IsFlagSet(COMPACTION_WAS_ABORTED)) {
312 DCHECK_NULL(old_to_old_slots_);
313 DCHECK_NULL(typed_old_to_old_slots_);
314 }
315 ClearFlag(EVACUATION_CANDIDATE);
316 InitializeFreeListCategories();
317 }
318
MemoryChunkIterator(Heap * heap)319 MemoryChunkIterator::MemoryChunkIterator(Heap* heap)
320 : heap_(heap),
321 state_(kOldSpaceState),
322 old_iterator_(heap->old_space()->begin()),
323 code_iterator_(heap->code_space()->begin()),
324 map_iterator_(heap->map_space()->begin()),
325 lo_iterator_(heap->lo_space()->begin()) {}
326
next()327 MemoryChunk* MemoryChunkIterator::next() {
328 switch (state_) {
329 case kOldSpaceState: {
330 if (old_iterator_ != heap_->old_space()->end()) return *(old_iterator_++);
331 state_ = kMapState;
332 // Fall through.
333 }
334 case kMapState: {
335 if (map_iterator_ != heap_->map_space()->end()) return *(map_iterator_++);
336 state_ = kCodeState;
337 // Fall through.
338 }
339 case kCodeState: {
340 if (code_iterator_ != heap_->code_space()->end())
341 return *(code_iterator_++);
342 state_ = kLargeObjectState;
343 // Fall through.
344 }
345 case kLargeObjectState: {
346 if (lo_iterator_ != heap_->lo_space()->end()) return *(lo_iterator_++);
347 state_ = kFinishedState;
348 // Fall through;
349 }
350 case kFinishedState:
351 return nullptr;
352 default:
353 break;
354 }
355 UNREACHABLE();
356 return nullptr;
357 }
358
page()359 Page* FreeListCategory::page() {
360 return Page::FromAddress(reinterpret_cast<Address>(this));
361 }
362
owner()363 FreeList* FreeListCategory::owner() {
364 return reinterpret_cast<PagedSpace*>(
365 Page::FromAddress(reinterpret_cast<Address>(this))->owner())
366 ->free_list();
367 }
368
is_linked()369 bool FreeListCategory::is_linked() {
370 return prev_ != nullptr || next_ != nullptr || owner()->top(type_) == this;
371 }
372
373 // Try linear allocation in the page of alloc_info's allocation top. Does
374 // not contain slow case logic (e.g. move to the next page or try free list
375 // allocation) so it can be used by all the allocation functions and for all
376 // the paged spaces.
AllocateLinearly(int size_in_bytes)377 HeapObject* PagedSpace::AllocateLinearly(int size_in_bytes) {
378 Address current_top = allocation_info_.top();
379 Address new_top = current_top + size_in_bytes;
380 if (new_top > allocation_info_.limit()) return NULL;
381
382 allocation_info_.set_top(new_top);
383 return HeapObject::FromAddress(current_top);
384 }
385
386
AllocateRawAligned(int size_in_bytes,AllocationAlignment alignment)387 AllocationResult LocalAllocationBuffer::AllocateRawAligned(
388 int size_in_bytes, AllocationAlignment alignment) {
389 Address current_top = allocation_info_.top();
390 int filler_size = Heap::GetFillToAlign(current_top, alignment);
391
392 Address new_top = current_top + filler_size + size_in_bytes;
393 if (new_top > allocation_info_.limit()) return AllocationResult::Retry();
394
395 allocation_info_.set_top(new_top);
396 if (filler_size > 0) {
397 return heap_->PrecedeWithFiller(HeapObject::FromAddress(current_top),
398 filler_size);
399 }
400
401 return AllocationResult(HeapObject::FromAddress(current_top));
402 }
403
404
AllocateLinearlyAligned(int * size_in_bytes,AllocationAlignment alignment)405 HeapObject* PagedSpace::AllocateLinearlyAligned(int* size_in_bytes,
406 AllocationAlignment alignment) {
407 Address current_top = allocation_info_.top();
408 int filler_size = Heap::GetFillToAlign(current_top, alignment);
409
410 Address new_top = current_top + filler_size + *size_in_bytes;
411 if (new_top > allocation_info_.limit()) return NULL;
412
413 allocation_info_.set_top(new_top);
414 if (filler_size > 0) {
415 *size_in_bytes += filler_size;
416 return heap()->PrecedeWithFiller(HeapObject::FromAddress(current_top),
417 filler_size);
418 }
419
420 return HeapObject::FromAddress(current_top);
421 }
422
423
424 // Raw allocation.
AllocateRawUnaligned(int size_in_bytes,UpdateSkipList update_skip_list)425 AllocationResult PagedSpace::AllocateRawUnaligned(
426 int size_in_bytes, UpdateSkipList update_skip_list) {
427 HeapObject* object = AllocateLinearly(size_in_bytes);
428
429 if (object == NULL) {
430 object = free_list_.Allocate(size_in_bytes);
431 if (object == NULL) {
432 object = SlowAllocateRaw(size_in_bytes);
433 }
434 if (object != NULL && heap()->incremental_marking()->black_allocation()) {
435 Address start = object->address();
436 Address end = object->address() + size_in_bytes;
437 Page::FromAllocationAreaAddress(start)->CreateBlackArea(start, end);
438 }
439 }
440
441 if (object != NULL) {
442 if (update_skip_list == UPDATE_SKIP_LIST && identity() == CODE_SPACE) {
443 SkipList::Update(object->address(), size_in_bytes);
444 }
445 MSAN_ALLOCATED_UNINITIALIZED_MEMORY(object->address(), size_in_bytes);
446 return object;
447 }
448
449 return AllocationResult::Retry(identity());
450 }
451
452
AllocateRawUnalignedSynchronized(int size_in_bytes)453 AllocationResult PagedSpace::AllocateRawUnalignedSynchronized(
454 int size_in_bytes) {
455 base::LockGuard<base::Mutex> lock_guard(&space_mutex_);
456 return AllocateRawUnaligned(size_in_bytes);
457 }
458
459
460 // Raw allocation.
AllocateRawAligned(int size_in_bytes,AllocationAlignment alignment)461 AllocationResult PagedSpace::AllocateRawAligned(int size_in_bytes,
462 AllocationAlignment alignment) {
463 DCHECK(identity() == OLD_SPACE);
464 int allocation_size = size_in_bytes;
465 HeapObject* object = AllocateLinearlyAligned(&allocation_size, alignment);
466
467 if (object == NULL) {
468 // We don't know exactly how much filler we need to align until space is
469 // allocated, so assume the worst case.
470 int filler_size = Heap::GetMaximumFillToAlign(alignment);
471 allocation_size += filler_size;
472 object = free_list_.Allocate(allocation_size);
473 if (object == NULL) {
474 object = SlowAllocateRaw(allocation_size);
475 }
476 if (object != NULL) {
477 if (heap()->incremental_marking()->black_allocation()) {
478 Address start = object->address();
479 Address end = object->address() + allocation_size;
480 Page::FromAllocationAreaAddress(start)->CreateBlackArea(start, end);
481 }
482 if (filler_size != 0) {
483 object = heap()->AlignWithFiller(object, size_in_bytes, allocation_size,
484 alignment);
485 // Filler objects are initialized, so mark only the aligned object
486 // memory as uninitialized.
487 allocation_size = size_in_bytes;
488 }
489 }
490 }
491
492 if (object != NULL) {
493 MSAN_ALLOCATED_UNINITIALIZED_MEMORY(object->address(), allocation_size);
494 return object;
495 }
496
497 return AllocationResult::Retry(identity());
498 }
499
500
AllocateRaw(int size_in_bytes,AllocationAlignment alignment)501 AllocationResult PagedSpace::AllocateRaw(int size_in_bytes,
502 AllocationAlignment alignment) {
503 #ifdef V8_HOST_ARCH_32_BIT
504 AllocationResult result =
505 alignment == kDoubleAligned
506 ? AllocateRawAligned(size_in_bytes, kDoubleAligned)
507 : AllocateRawUnaligned(size_in_bytes);
508 #else
509 AllocationResult result = AllocateRawUnaligned(size_in_bytes);
510 #endif
511 HeapObject* heap_obj = nullptr;
512 if (!result.IsRetry() && result.To(&heap_obj)) {
513 AllocationStep(heap_obj->address(), size_in_bytes);
514 }
515 return result;
516 }
517
518
519 // -----------------------------------------------------------------------------
520 // NewSpace
521
522
AllocateRawAligned(int size_in_bytes,AllocationAlignment alignment)523 AllocationResult NewSpace::AllocateRawAligned(int size_in_bytes,
524 AllocationAlignment alignment) {
525 Address top = allocation_info_.top();
526 int filler_size = Heap::GetFillToAlign(top, alignment);
527 int aligned_size_in_bytes = size_in_bytes + filler_size;
528
529 if (allocation_info_.limit() - top < aligned_size_in_bytes) {
530 // See if we can create room.
531 if (!EnsureAllocation(size_in_bytes, alignment)) {
532 return AllocationResult::Retry();
533 }
534
535 top = allocation_info_.top();
536 filler_size = Heap::GetFillToAlign(top, alignment);
537 aligned_size_in_bytes = size_in_bytes + filler_size;
538 }
539
540 HeapObject* obj = HeapObject::FromAddress(top);
541 allocation_info_.set_top(top + aligned_size_in_bytes);
542 DCHECK_SEMISPACE_ALLOCATION_INFO(allocation_info_, to_space_);
543
544 if (filler_size > 0) {
545 obj = heap()->PrecedeWithFiller(obj, filler_size);
546 }
547
548 MSAN_ALLOCATED_UNINITIALIZED_MEMORY(obj->address(), size_in_bytes);
549
550 return obj;
551 }
552
553
AllocateRawUnaligned(int size_in_bytes)554 AllocationResult NewSpace::AllocateRawUnaligned(int size_in_bytes) {
555 Address top = allocation_info_.top();
556 if (allocation_info_.limit() < top + size_in_bytes) {
557 // See if we can create room.
558 if (!EnsureAllocation(size_in_bytes, kWordAligned)) {
559 return AllocationResult::Retry();
560 }
561
562 top = allocation_info_.top();
563 }
564
565 HeapObject* obj = HeapObject::FromAddress(top);
566 allocation_info_.set_top(top + size_in_bytes);
567 DCHECK_SEMISPACE_ALLOCATION_INFO(allocation_info_, to_space_);
568
569 MSAN_ALLOCATED_UNINITIALIZED_MEMORY(obj->address(), size_in_bytes);
570
571 return obj;
572 }
573
574
AllocateRaw(int size_in_bytes,AllocationAlignment alignment)575 AllocationResult NewSpace::AllocateRaw(int size_in_bytes,
576 AllocationAlignment alignment) {
577 #ifdef V8_HOST_ARCH_32_BIT
578 return alignment == kDoubleAligned
579 ? AllocateRawAligned(size_in_bytes, kDoubleAligned)
580 : AllocateRawUnaligned(size_in_bytes);
581 #else
582 return AllocateRawUnaligned(size_in_bytes);
583 #endif
584 }
585
586
AllocateRawSynchronized(int size_in_bytes,AllocationAlignment alignment)587 MUST_USE_RESULT inline AllocationResult NewSpace::AllocateRawSynchronized(
588 int size_in_bytes, AllocationAlignment alignment) {
589 base::LockGuard<base::Mutex> guard(&mutex_);
590 return AllocateRaw(size_in_bytes, alignment);
591 }
592
Initialize(Heap * heap,MemoryChunk * chunk,Executability executable,Space * owner)593 LargePage* LargePage::Initialize(Heap* heap, MemoryChunk* chunk,
594 Executability executable, Space* owner) {
595 if (executable && chunk->size() > LargePage::kMaxCodePageSize) {
596 STATIC_ASSERT(LargePage::kMaxCodePageSize <= TypedSlotSet::kMaxOffset);
597 FATAL("Code page is too large.");
598 }
599 heap->incremental_marking()->SetOldSpacePageFlags(chunk);
600
601 MSAN_ALLOCATED_UNINITIALIZED_MEMORY(chunk->area_start(), chunk->area_size());
602
603 // Initialize the owner field for each contained page (except the first, which
604 // is initialized by MemoryChunk::Initialize).
605 for (Address addr = chunk->address() + Page::kPageSize + Page::kOwnerOffset;
606 addr < chunk->area_end(); addr += Page::kPageSize) {
607 // Clear out kPageHeaderTag.
608 Memory::Address_at(addr) = 0;
609 }
610
611 return static_cast<LargePage*>(chunk);
612 }
613
Available()614 size_t LargeObjectSpace::Available() {
615 return ObjectSizeFor(heap()->memory_allocator()->Available());
616 }
617
618
InvalidBuffer()619 LocalAllocationBuffer LocalAllocationBuffer::InvalidBuffer() {
620 return LocalAllocationBuffer(nullptr, AllocationInfo(nullptr, nullptr));
621 }
622
623
FromResult(Heap * heap,AllocationResult result,intptr_t size)624 LocalAllocationBuffer LocalAllocationBuffer::FromResult(Heap* heap,
625 AllocationResult result,
626 intptr_t size) {
627 if (result.IsRetry()) return InvalidBuffer();
628 HeapObject* obj = nullptr;
629 bool ok = result.To(&obj);
630 USE(ok);
631 DCHECK(ok);
632 Address top = HeapObject::cast(obj)->address();
633 return LocalAllocationBuffer(heap, AllocationInfo(top, top + size));
634 }
635
636
TryMerge(LocalAllocationBuffer * other)637 bool LocalAllocationBuffer::TryMerge(LocalAllocationBuffer* other) {
638 if (allocation_info_.top() == other->allocation_info_.limit()) {
639 allocation_info_.set_top(other->allocation_info_.top());
640 other->allocation_info_.Reset(nullptr, nullptr);
641 return true;
642 }
643 return false;
644 }
645
646 } // namespace internal
647 } // namespace v8
648
649 #endif // V8_HEAP_SPACES_INL_H_
650