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