1// Copyright 2020 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#include "src/heap/large-spaces.h" 6 7#include "src/base/platform/mutex.h" 8#include "src/base/sanitizer/msan.h" 9#include "src/common/globals.h" 10#include "src/execution/isolate.h" 11#include "src/heap/combined-heap.h" 12#include "src/heap/incremental-marking.h" 13#include "src/heap/list.h" 14#include "src/heap/marking.h" 15#include "src/heap/memory-allocator.h" 16#include "src/heap/memory-chunk-inl.h" 17#include "src/heap/remembered-set.h" 18#include "src/heap/slot-set.h" 19#include "src/heap/spaces-inl.h" 20#include "src/logging/log.h" 21#include "src/objects/objects-inl.h" 22#include "src/utils/ostreams.h" 23 24namespace v8 { 25namespace internal { 26 27// This check is here to ensure that the lower 32 bits of any real heap object 28// can't overlap with the lower 32 bits of cleared weak reference value and 29// therefore it's enough to compare only the lower 32 bits of a MaybeObject in 30// order to figure out if it's a cleared weak reference or not. 31STATIC_ASSERT(kClearedWeakHeapObjectLower32 < LargePage::kHeaderSize); 32 33LargePage::LargePage(Heap* heap, BaseSpace* space, size_t chunk_size, 34 Address area_start, Address area_end, 35 VirtualMemory reservation, Executability executable) 36 : MemoryChunk(heap, space, chunk_size, area_start, area_end, 37 std::move(reservation), executable, PageSize::kLarge) { 38 STATIC_ASSERT(LargePage::kMaxCodePageSize <= TypedSlotSet::kMaxOffset); 39 40 if (executable && chunk_size > LargePage::kMaxCodePageSize) { 41 FATAL("Code page is too large."); 42 } 43 44 SetFlag(MemoryChunk::LARGE_PAGE); 45 list_node().Initialize(); 46} 47 48LargePage* LargePage::Initialize(Heap* heap, MemoryChunk* chunk, 49 Executability executable) { 50 if (executable && chunk->size() > LargePage::kMaxCodePageSize) { 51 STATIC_ASSERT(LargePage::kMaxCodePageSize <= TypedSlotSet::kMaxOffset); 52 FATAL("Code page is too large."); 53 } 54 55 MSAN_ALLOCATED_UNINITIALIZED_MEMORY(chunk->area_start(), chunk->area_size()); 56 57 LargePage* page = static_cast<LargePage*>(chunk); 58 page->SetFlag(MemoryChunk::LARGE_PAGE); 59 page->list_node().Initialize(); 60 return page; 61} 62 63size_t LargeObjectSpace::Available() const { 64 // We return zero here since we cannot take advantage of already allocated 65 // large object memory. 66 return 0; 67} 68 69Address LargePage::GetAddressToShrink(Address object_address, 70 size_t object_size) { 71 if (executable() == EXECUTABLE) { 72 return 0; 73 } 74 size_t used_size = ::RoundUp((object_address - address()) + object_size, 75 MemoryAllocator::GetCommitPageSize()); 76 if (used_size < CommittedPhysicalMemory()) { 77 return address() + used_size; 78 } 79 return 0; 80} 81 82void LargePage::ClearOutOfLiveRangeSlots(Address free_start) { 83 RememberedSet<OLD_TO_NEW>::RemoveRange(this, free_start, area_end(), 84 SlotSet::FREE_EMPTY_BUCKETS); 85 RememberedSet<OLD_TO_OLD>::RemoveRange(this, free_start, area_end(), 86 SlotSet::FREE_EMPTY_BUCKETS); 87 RememberedSet<OLD_TO_NEW>::RemoveRangeTyped(this, free_start, area_end()); 88 RememberedSet<OLD_TO_OLD>::RemoveRangeTyped(this, free_start, area_end()); 89} 90 91// ----------------------------------------------------------------------------- 92// LargeObjectSpaceObjectIterator 93 94LargeObjectSpaceObjectIterator::LargeObjectSpaceObjectIterator( 95 LargeObjectSpace* space) { 96 current_ = space->first_page(); 97} 98 99HeapObject LargeObjectSpaceObjectIterator::Next() { 100 if (current_ == nullptr) return HeapObject(); 101 102 HeapObject object = current_->GetObject(); 103 current_ = current_->next_page(); 104 return object; 105} 106 107// ----------------------------------------------------------------------------- 108// OldLargeObjectSpace 109 110LargeObjectSpace::LargeObjectSpace(Heap* heap, AllocationSpace id) 111 : Space(heap, id, new NoFreeList()), 112 size_(0), 113 page_count_(0), 114 objects_size_(0), 115 pending_object_(0) {} 116 117void LargeObjectSpace::TearDown() { 118 while (!memory_chunk_list_.Empty()) { 119 LargePage* page = first_page(); 120 LOG(heap()->isolate(), 121 DeleteEvent("LargeObjectChunk", 122 reinterpret_cast<void*>(page->address()))); 123 memory_chunk_list_.Remove(page); 124 heap()->memory_allocator()->Free(MemoryAllocator::FreeMode::kImmediately, 125 page); 126 } 127} 128 129void LargeObjectSpace::AdvanceAndInvokeAllocationObservers(Address soon_object, 130 size_t object_size) { 131 if (!allocation_counter_.IsActive()) return; 132 133 if (object_size >= allocation_counter_.NextBytes()) { 134 allocation_counter_.InvokeAllocationObservers(soon_object, object_size, 135 object_size); 136 } 137 138 // Large objects can be accounted immediately since no LAB is involved. 139 allocation_counter_.AdvanceAllocationObservers(object_size); 140} 141 142AllocationResult OldLargeObjectSpace::AllocateRaw(int object_size) { 143 return AllocateRaw(object_size, NOT_EXECUTABLE); 144} 145 146AllocationResult OldLargeObjectSpace::AllocateRaw(int object_size, 147 Executability executable) { 148 DCHECK(!FLAG_enable_third_party_heap); 149 // Check if we want to force a GC before growing the old space further. 150 // If so, fail the allocation. 151 if (!heap()->CanExpandOldGeneration(object_size) || 152 !heap()->ShouldExpandOldGenerationOnSlowAllocation()) { 153 return AllocationResult::Failure(); 154 } 155 156 LargePage* page = AllocateLargePage(object_size, executable); 157 if (page == nullptr) return AllocationResult::Failure(); 158 page->SetOldGenerationPageFlags(heap()->incremental_marking()->IsMarking()); 159 HeapObject object = page->GetObject(); 160 UpdatePendingObject(object); 161 heap()->StartIncrementalMarkingIfAllocationLimitIsReached( 162 heap()->GCFlagsForIncrementalMarking(), 163 kGCCallbackScheduleIdleGarbageCollection); 164 if (heap()->incremental_marking()->black_allocation()) { 165 heap()->incremental_marking()->marking_state()->WhiteToBlack(object); 166 } 167 DCHECK_IMPLIES( 168 heap()->incremental_marking()->black_allocation(), 169 heap()->incremental_marking()->marking_state()->IsBlack(object)); 170 page->InitializationMemoryFence(); 171 heap()->NotifyOldGenerationExpansion(identity(), page); 172 AdvanceAndInvokeAllocationObservers(object.address(), 173 static_cast<size_t>(object_size)); 174 return AllocationResult::FromObject(object); 175} 176 177AllocationResult OldLargeObjectSpace::AllocateRawBackground( 178 LocalHeap* local_heap, int object_size) { 179 return AllocateRawBackground(local_heap, object_size, NOT_EXECUTABLE); 180} 181 182AllocationResult OldLargeObjectSpace::AllocateRawBackground( 183 LocalHeap* local_heap, int object_size, Executability executable) { 184 DCHECK(!FLAG_enable_third_party_heap); 185 // Check if we want to force a GC before growing the old space further. 186 // If so, fail the allocation. 187 if (!heap()->CanExpandOldGenerationBackground(local_heap, object_size) || 188 !heap()->ShouldExpandOldGenerationOnSlowAllocation(local_heap)) { 189 return AllocationResult::Failure(); 190 } 191 192 LargePage* page = AllocateLargePage(object_size, executable); 193 if (page == nullptr) return AllocationResult::Failure(); 194 page->SetOldGenerationPageFlags(heap()->incremental_marking()->IsMarking()); 195 HeapObject object = page->GetObject(); 196 heap()->StartIncrementalMarkingIfAllocationLimitIsReachedBackground(); 197 if (heap()->incremental_marking()->black_allocation()) { 198 heap()->incremental_marking()->marking_state()->WhiteToBlack(object); 199 } 200 DCHECK_IMPLIES( 201 heap()->incremental_marking()->black_allocation(), 202 heap()->incremental_marking()->marking_state()->IsBlack(object)); 203 page->InitializationMemoryFence(); 204 if (identity() == CODE_LO_SPACE) { 205 heap()->isolate()->AddCodeMemoryChunk(page); 206 } 207 return AllocationResult::FromObject(object); 208} 209 210LargePage* LargeObjectSpace::AllocateLargePage(int object_size, 211 Executability executable) { 212 LargePage* page = heap()->memory_allocator()->AllocateLargePage( 213 this, object_size, executable); 214 if (page == nullptr) return nullptr; 215 DCHECK_GE(page->area_size(), static_cast<size_t>(object_size)); 216 217 { 218 base::MutexGuard guard(&allocation_mutex_); 219 AddPage(page, object_size); 220 } 221 222 HeapObject object = page->GetObject(); 223 224 heap()->CreateFillerObjectAt(object.address(), object_size, 225 ClearRecordedSlots::kNo); 226 return page; 227} 228 229size_t LargeObjectSpace::CommittedPhysicalMemory() const { 230 // On a platform that provides lazy committing of memory, we over-account 231 // the actually committed memory. There is no easy way right now to support 232 // precise accounting of committed memory in large object space. 233 return CommittedMemory(); 234} 235 236LargePage* CodeLargeObjectSpace::FindPage(Address a) { 237 base::MutexGuard guard(&allocation_mutex_); 238 const Address key = BasicMemoryChunk::FromAddress(a)->address(); 239 auto it = chunk_map_.find(key); 240 if (it != chunk_map_.end()) { 241 LargePage* page = it->second; 242 CHECK(page->Contains(a)); 243 return page; 244 } 245 return nullptr; 246} 247 248void OldLargeObjectSpace::ClearMarkingStateOfLiveObjects() { 249 IncrementalMarking::NonAtomicMarkingState* marking_state = 250 heap()->incremental_marking()->non_atomic_marking_state(); 251 LargeObjectSpaceObjectIterator it(this); 252 for (HeapObject obj = it.Next(); !obj.is_null(); obj = it.Next()) { 253 if (marking_state->IsBlackOrGrey(obj)) { 254 Marking::MarkWhite(marking_state->MarkBitFrom(obj)); 255 MemoryChunk* chunk = MemoryChunk::FromHeapObject(obj); 256 RememberedSet<OLD_TO_NEW>::FreeEmptyBuckets(chunk); 257 chunk->ProgressBar().ResetIfEnabled(); 258 marking_state->SetLiveBytes(chunk, 0); 259 } 260 DCHECK(marking_state->IsWhite(obj)); 261 } 262} 263 264void CodeLargeObjectSpace::InsertChunkMapEntries(LargePage* page) { 265 for (Address current = reinterpret_cast<Address>(page); 266 current < reinterpret_cast<Address>(page) + page->size(); 267 current += MemoryChunk::kPageSize) { 268 chunk_map_[current] = page; 269 } 270} 271 272void CodeLargeObjectSpace::RemoveChunkMapEntries(LargePage* page) { 273 for (Address current = page->address(); 274 current < reinterpret_cast<Address>(page) + page->size(); 275 current += MemoryChunk::kPageSize) { 276 chunk_map_.erase(current); 277 } 278} 279 280void OldLargeObjectSpace::PromoteNewLargeObject(LargePage* page) { 281 DCHECK_EQ(page->owner_identity(), NEW_LO_SPACE); 282 DCHECK(page->IsLargePage()); 283 DCHECK(page->IsFlagSet(MemoryChunk::FROM_PAGE)); 284 DCHECK(!page->IsFlagSet(MemoryChunk::TO_PAGE)); 285 PtrComprCageBase cage_base(heap()->isolate()); 286 size_t object_size = static_cast<size_t>(page->GetObject().Size(cage_base)); 287 static_cast<LargeObjectSpace*>(page->owner())->RemovePage(page, object_size); 288 page->ClearFlag(MemoryChunk::FROM_PAGE); 289 AddPage(page, object_size); 290} 291 292void LargeObjectSpace::AddPage(LargePage* page, size_t object_size) { 293 size_ += static_cast<int>(page->size()); 294 AccountCommitted(page->size()); 295 objects_size_ += object_size; 296 page_count_++; 297 memory_chunk_list_.PushBack(page); 298 page->set_owner(this); 299 page->SetOldGenerationPageFlags(!is_off_thread() && 300 heap()->incremental_marking()->IsMarking()); 301} 302 303void LargeObjectSpace::RemovePage(LargePage* page, size_t object_size) { 304 size_ -= static_cast<int>(page->size()); 305 AccountUncommitted(page->size()); 306 objects_size_ -= object_size; 307 page_count_--; 308 memory_chunk_list_.Remove(page); 309 page->set_owner(nullptr); 310} 311 312void LargeObjectSpace::FreeUnmarkedObjects() { 313 LargePage* current = first_page(); 314 IncrementalMarking::NonAtomicMarkingState* marking_state = 315 heap()->incremental_marking()->non_atomic_marking_state(); 316 // Right-trimming does not update the objects_size_ counter. We are lazily 317 // updating it after every GC. 318 size_t surviving_object_size = 0; 319 PtrComprCageBase cage_base(heap()->isolate()); 320 while (current) { 321 LargePage* next_current = current->next_page(); 322 HeapObject object = current->GetObject(); 323 DCHECK(!marking_state->IsGrey(object)); 324 size_t size = static_cast<size_t>(object.Size(cage_base)); 325 if (marking_state->IsBlack(object)) { 326 Address free_start; 327 surviving_object_size += size; 328 if ((free_start = current->GetAddressToShrink(object.address(), size)) != 329 0) { 330 DCHECK(!current->IsFlagSet(Page::IS_EXECUTABLE)); 331 current->ClearOutOfLiveRangeSlots(free_start); 332 const size_t bytes_to_free = 333 current->size() - (free_start - current->address()); 334 heap()->memory_allocator()->PartialFreeMemory( 335 current, free_start, bytes_to_free, 336 current->area_start() + object.Size(cage_base)); 337 size_ -= bytes_to_free; 338 AccountUncommitted(bytes_to_free); 339 } 340 } else { 341 RemovePage(current, size); 342 heap()->memory_allocator()->Free(MemoryAllocator::FreeMode::kConcurrently, 343 current); 344 } 345 current = next_current; 346 } 347 objects_size_ = surviving_object_size; 348} 349 350bool LargeObjectSpace::Contains(HeapObject object) const { 351 BasicMemoryChunk* chunk = BasicMemoryChunk::FromHeapObject(object); 352 353 bool owned = (chunk->owner() == this); 354 355 SLOW_DCHECK(!owned || ContainsSlow(object.address())); 356 357 return owned; 358} 359 360bool LargeObjectSpace::ContainsSlow(Address addr) const { 361 for (const LargePage* page : *this) { 362 if (page->Contains(addr)) return true; 363 } 364 return false; 365} 366 367std::unique_ptr<ObjectIterator> LargeObjectSpace::GetObjectIterator( 368 Heap* heap) { 369 return std::unique_ptr<ObjectIterator>( 370 new LargeObjectSpaceObjectIterator(this)); 371} 372 373#ifdef VERIFY_HEAP 374// We do not assume that the large object iterator works, because it depends 375// on the invariants we are checking during verification. 376void LargeObjectSpace::Verify(Isolate* isolate) { 377 size_t external_backing_store_bytes[kNumTypes]; 378 379 for (int i = 0; i < kNumTypes; i++) { 380 external_backing_store_bytes[static_cast<ExternalBackingStoreType>(i)] = 0; 381 } 382 383 PtrComprCageBase cage_base(isolate); 384 for (LargePage* chunk = first_page(); chunk != nullptr; 385 chunk = chunk->next_page()) { 386 // Each chunk contains an object that starts at the large object page's 387 // object area start. 388 HeapObject object = chunk->GetObject(); 389 Page* page = Page::FromHeapObject(object); 390 CHECK(object.address() == page->area_start()); 391 392 // The first word should be a map, and we expect all map pointers to be 393 // in map space or read-only space. 394 Map map = object.map(cage_base); 395 CHECK(map.IsMap(cage_base)); 396 CHECK(ReadOnlyHeap::Contains(map) || 397 isolate->heap()->space_for_maps()->Contains(map)); 398 399 // We have only the following types in the large object space: 400 const bool is_valid_lo_space_object = // 401 object.IsAbstractCode(cage_base) || // 402 object.IsBigInt(cage_base) || // 403 object.IsByteArray(cage_base) || // 404 object.IsContext(cage_base) || // 405 object.IsExternalString(cage_base) || // 406 object.IsFeedbackMetadata(cage_base) || // 407 object.IsFeedbackVector(cage_base) || // 408 object.IsFixedArray(cage_base) || // 409 object.IsFixedDoubleArray(cage_base) || // 410 object.IsFreeSpace(cage_base) || // 411 object.IsPreparseData(cage_base) || // 412 object.IsPropertyArray(cage_base) || // 413 object.IsScopeInfo() || // 414 object.IsSeqString(cage_base) || // 415 object.IsSloppyArgumentsElements(cage_base) || // 416 object.IsSwissNameDictionary() || // 417 object.IsThinString(cage_base) || // 418 object.IsUncompiledDataWithoutPreparseData(cage_base) || // 419#if V8_ENABLE_WEBASSEMBLY // 420 object.IsWasmArray() || // 421#endif // 422 object.IsWeakArrayList(cage_base) || // 423 object.IsWeakFixedArray(cage_base); 424 if (!is_valid_lo_space_object) { 425 object.Print(); 426 FATAL("Found invalid Object (instance_type=%i) in large object space.", 427 object.map(cage_base).instance_type()); 428 } 429 430 // The object itself should look OK. 431 object.ObjectVerify(isolate); 432 433 if (!FLAG_verify_heap_skip_remembered_set) { 434 heap()->VerifyRememberedSetFor(object); 435 } 436 437 // Byte arrays and strings don't have interior pointers. 438 if (object.IsAbstractCode(cage_base)) { 439 VerifyPointersVisitor code_visitor(heap()); 440 object.IterateBody(map, object.Size(cage_base), &code_visitor); 441 } else if (object.IsFixedArray(cage_base)) { 442 FixedArray array = FixedArray::cast(object); 443 for (int j = 0; j < array.length(); j++) { 444 Object element = array.get(j); 445 if (element.IsHeapObject()) { 446 HeapObject element_object = HeapObject::cast(element); 447 CHECK(IsValidHeapObject(heap(), element_object)); 448 CHECK(element_object.map(cage_base).IsMap(cage_base)); 449 } 450 } 451 } else if (object.IsPropertyArray(cage_base)) { 452 PropertyArray array = PropertyArray::cast(object); 453 for (int j = 0; j < array.length(); j++) { 454 Object property = array.get(j); 455 if (property.IsHeapObject()) { 456 HeapObject property_object = HeapObject::cast(property); 457 CHECK(heap()->Contains(property_object)); 458 CHECK(property_object.map(cage_base).IsMap(cage_base)); 459 } 460 } 461 } 462 for (int i = 0; i < kNumTypes; i++) { 463 ExternalBackingStoreType t = static_cast<ExternalBackingStoreType>(i); 464 external_backing_store_bytes[t] += chunk->ExternalBackingStoreBytes(t); 465 } 466 467 CHECK(!chunk->IsFlagSet(Page::PAGE_NEW_OLD_PROMOTION)); 468 CHECK(!chunk->IsFlagSet(Page::PAGE_NEW_NEW_PROMOTION)); 469 } 470 for (int i = 0; i < kNumTypes; i++) { 471 ExternalBackingStoreType t = static_cast<ExternalBackingStoreType>(i); 472 CHECK_EQ(external_backing_store_bytes[t], ExternalBackingStoreBytes(t)); 473 } 474} 475#endif 476 477#ifdef DEBUG 478void LargeObjectSpace::Print() { 479 StdoutStream os; 480 LargeObjectSpaceObjectIterator it(this); 481 for (HeapObject obj = it.Next(); !obj.is_null(); obj = it.Next()) { 482 obj.Print(os); 483 } 484} 485#endif // DEBUG 486 487void LargeObjectSpace::UpdatePendingObject(HeapObject object) { 488 base::SharedMutexGuard<base::kExclusive> guard(&pending_allocation_mutex_); 489 pending_object_.store(object.address(), std::memory_order_release); 490} 491 492OldLargeObjectSpace::OldLargeObjectSpace(Heap* heap) 493 : LargeObjectSpace(heap, LO_SPACE) {} 494 495OldLargeObjectSpace::OldLargeObjectSpace(Heap* heap, AllocationSpace id) 496 : LargeObjectSpace(heap, id) {} 497 498NewLargeObjectSpace::NewLargeObjectSpace(Heap* heap, size_t capacity) 499 : LargeObjectSpace(heap, NEW_LO_SPACE), 500 capacity_(capacity) {} 501 502AllocationResult NewLargeObjectSpace::AllocateRaw(int object_size) { 503 DCHECK(!FLAG_enable_third_party_heap); 504 // Do not allocate more objects if promoting the existing object would exceed 505 // the old generation capacity. 506 if (!heap()->CanExpandOldGeneration(SizeOfObjects())) { 507 return AllocationResult::Failure(); 508 } 509 510 // Allocation for the first object must succeed independent from the capacity. 511 if (SizeOfObjects() > 0 && static_cast<size_t>(object_size) > Available()) { 512 return AllocationResult::Failure(); 513 } 514 515 LargePage* page = AllocateLargePage(object_size, NOT_EXECUTABLE); 516 if (page == nullptr) return AllocationResult::Failure(); 517 518 // The size of the first object may exceed the capacity. 519 capacity_ = std::max(capacity_, SizeOfObjects()); 520 521 HeapObject result = page->GetObject(); 522 page->SetYoungGenerationPageFlags(heap()->incremental_marking()->IsMarking()); 523 page->SetFlag(MemoryChunk::TO_PAGE); 524 UpdatePendingObject(result); 525 if (FLAG_minor_mc) { 526 page->AllocateYoungGenerationBitmap(); 527 heap() 528 ->minor_mark_compact_collector() 529 ->non_atomic_marking_state() 530 ->ClearLiveness(page); 531 } 532 page->InitializationMemoryFence(); 533 DCHECK(page->IsLargePage()); 534 DCHECK_EQ(page->owner_identity(), NEW_LO_SPACE); 535 AdvanceAndInvokeAllocationObservers(result.address(), 536 static_cast<size_t>(object_size)); 537 return AllocationResult::FromObject(result); 538} 539 540size_t NewLargeObjectSpace::Available() const { 541 return capacity_ - SizeOfObjects(); 542} 543 544void NewLargeObjectSpace::Flip() { 545 for (LargePage* chunk = first_page(); chunk != nullptr; 546 chunk = chunk->next_page()) { 547 chunk->SetFlag(MemoryChunk::FROM_PAGE); 548 chunk->ClearFlag(MemoryChunk::TO_PAGE); 549 } 550} 551 552void NewLargeObjectSpace::FreeDeadObjects( 553 const std::function<bool(HeapObject)>& is_dead) { 554 bool is_marking = heap()->incremental_marking()->IsMarking(); 555 size_t surviving_object_size = 0; 556 bool freed_pages = false; 557 PtrComprCageBase cage_base(heap()->isolate()); 558 for (auto it = begin(); it != end();) { 559 LargePage* page = *it; 560 it++; 561 HeapObject object = page->GetObject(); 562 size_t size = static_cast<size_t>(object.Size(cage_base)); 563 if (is_dead(object)) { 564 freed_pages = true; 565 RemovePage(page, size); 566 heap()->memory_allocator()->Free(MemoryAllocator::FreeMode::kConcurrently, 567 page); 568 if (FLAG_concurrent_marking && is_marking) { 569 heap()->concurrent_marking()->ClearMemoryChunkData(page); 570 } 571 } else { 572 surviving_object_size += size; 573 } 574 } 575 // Right-trimming does not update the objects_size_ counter. We are lazily 576 // updating it after every GC. 577 objects_size_ = surviving_object_size; 578 if (freed_pages) { 579 heap()->memory_allocator()->unmapper()->FreeQueuedChunks(); 580 } 581} 582 583void NewLargeObjectSpace::SetCapacity(size_t capacity) { 584 capacity_ = std::max(capacity, SizeOfObjects()); 585} 586 587CodeLargeObjectSpace::CodeLargeObjectSpace(Heap* heap) 588 : OldLargeObjectSpace(heap, CODE_LO_SPACE), 589 chunk_map_(kInitialChunkMapCapacity) {} 590 591AllocationResult CodeLargeObjectSpace::AllocateRaw(int object_size) { 592 DCHECK(!FLAG_enable_third_party_heap); 593 return OldLargeObjectSpace::AllocateRaw(object_size, EXECUTABLE); 594} 595 596AllocationResult CodeLargeObjectSpace::AllocateRawBackground( 597 LocalHeap* local_heap, int object_size) { 598 DCHECK(!FLAG_enable_third_party_heap); 599 return OldLargeObjectSpace::AllocateRawBackground(local_heap, object_size, 600 EXECUTABLE); 601} 602 603void CodeLargeObjectSpace::AddPage(LargePage* page, size_t object_size) { 604 OldLargeObjectSpace::AddPage(page, object_size); 605 InsertChunkMapEntries(page); 606} 607 608void CodeLargeObjectSpace::RemovePage(LargePage* page, size_t object_size) { 609 RemoveChunkMapEntries(page); 610 heap()->isolate()->RemoveCodeMemoryChunk(page); 611 OldLargeObjectSpace::RemovePage(page, object_size); 612} 613 614} // namespace internal 615} // namespace v8 616