• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2018 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_EVACUATION_ALLOCATOR_INL_H_
6 #define V8_HEAP_EVACUATION_ALLOCATOR_INL_H_
7 
8 #include "src/common/globals.h"
9 #include "src/heap/evacuation-allocator.h"
10 #include "src/heap/spaces-inl.h"
11 
12 namespace v8 {
13 namespace internal {
14 
Allocate(AllocationSpace space,int object_size,AllocationOrigin origin,AllocationAlignment alignment)15 AllocationResult EvacuationAllocator::Allocate(AllocationSpace space,
16                                                int object_size,
17                                                AllocationOrigin origin,
18                                                AllocationAlignment alignment) {
19   switch (space) {
20     case NEW_SPACE:
21       return AllocateInNewSpace(object_size, origin, alignment);
22     case OLD_SPACE:
23       return compaction_spaces_.Get(OLD_SPACE)->AllocateRaw(object_size,
24                                                             alignment, origin);
25     case MAP_SPACE:
26       return compaction_spaces_.Get(MAP_SPACE)->AllocateRaw(object_size,
27                                                             alignment, origin);
28     case CODE_SPACE:
29       return compaction_spaces_.Get(CODE_SPACE)
30           ->AllocateRaw(object_size, alignment, origin);
31     default:
32       UNREACHABLE();
33   }
34 }
35 
FreeLast(AllocationSpace space,HeapObject object,int object_size)36 void EvacuationAllocator::FreeLast(AllocationSpace space, HeapObject object,
37                                    int object_size) {
38   switch (space) {
39     case NEW_SPACE:
40       FreeLastInNewSpace(object, object_size);
41       return;
42     case OLD_SPACE:
43       FreeLastInOldSpace(object, object_size);
44       return;
45     case MAP_SPACE:
46       FreeLastInMapSpace(object, object_size);
47       return;
48     default:
49       // Only new and old space supported.
50       UNREACHABLE();
51   }
52 }
53 
FreeLastInNewSpace(HeapObject object,int object_size)54 void EvacuationAllocator::FreeLastInNewSpace(HeapObject object,
55                                              int object_size) {
56   if (!new_space_lab_.TryFreeLast(object, object_size)) {
57     // We couldn't free the last object so we have to write a proper filler.
58     heap_->CreateFillerObjectAt(object.address(), object_size,
59                                 ClearRecordedSlots::kNo);
60   }
61 }
62 
FreeLastInOldSpace(HeapObject object,int object_size)63 void EvacuationAllocator::FreeLastInOldSpace(HeapObject object,
64                                              int object_size) {
65   if (!compaction_spaces_.Get(OLD_SPACE)->TryFreeLast(object.address(),
66                                                       object_size)) {
67     // We couldn't free the last object so we have to write a proper filler.
68     heap_->CreateFillerObjectAt(object.address(), object_size,
69                                 ClearRecordedSlots::kNo);
70   }
71 }
72 
FreeLastInMapSpace(HeapObject object,int object_size)73 void EvacuationAllocator::FreeLastInMapSpace(HeapObject object,
74                                              int object_size) {
75   if (!compaction_spaces_.Get(MAP_SPACE)->TryFreeLast(object.address(),
76                                                       object_size)) {
77     // We couldn't free the last object so we have to write a proper filler.
78     heap_->CreateFillerObjectAt(object.address(), object_size,
79                                 ClearRecordedSlots::kNo);
80   }
81 }
82 
AllocateInLAB(int object_size,AllocationAlignment alignment)83 AllocationResult EvacuationAllocator::AllocateInLAB(
84     int object_size, AllocationAlignment alignment) {
85   AllocationResult allocation;
86   if (!new_space_lab_.IsValid() && !NewLocalAllocationBuffer()) {
87     return AllocationResult::Failure();
88   }
89   allocation = new_space_lab_.AllocateRawAligned(object_size, alignment);
90   if (allocation.IsFailure()) {
91     if (!NewLocalAllocationBuffer()) {
92       return AllocationResult::Failure();
93     } else {
94       allocation = new_space_lab_.AllocateRawAligned(object_size, alignment);
95       CHECK(!allocation.IsFailure());
96     }
97   }
98   return allocation;
99 }
100 
NewLocalAllocationBuffer()101 bool EvacuationAllocator::NewLocalAllocationBuffer() {
102   if (lab_allocation_will_fail_) return false;
103   AllocationResult result =
104       new_space_->AllocateRawSynchronized(kLabSize, kTaggedAligned);
105   if (result.IsFailure()) {
106     lab_allocation_will_fail_ = true;
107     return false;
108   }
109   LocalAllocationBuffer saved_lab = std::move(new_space_lab_);
110   new_space_lab_ = LocalAllocationBuffer::FromResult(heap_, result, kLabSize);
111   DCHECK(new_space_lab_.IsValid());
112   if (!new_space_lab_.TryMerge(&saved_lab)) {
113     saved_lab.CloseAndMakeIterable();
114   }
115   return true;
116 }
117 
AllocateInNewSpace(int object_size,AllocationOrigin origin,AllocationAlignment alignment)118 AllocationResult EvacuationAllocator::AllocateInNewSpace(
119     int object_size, AllocationOrigin origin, AllocationAlignment alignment) {
120   if (object_size > kMaxLabObjectSize) {
121     return new_space_->AllocateRawSynchronized(object_size, alignment, origin);
122   }
123   return AllocateInLAB(object_size, alignment);
124 }
125 
126 }  // namespace internal
127 }  // namespace v8
128 
129 #endif  // V8_HEAP_EVACUATION_ALLOCATOR_INL_H_
130